- Add support for MDB2's 'sqlsrv' driver (#1486395)

release-0.6
alecpl 15 years ago
parent 8f85e3759c
commit 2273d4117f

@ -1,6 +1,7 @@
CHANGELOG RoundCube Webmail
===========================
- Add support for MDB2's 'sqlsrv' driver (#1486395)
- Use jQuery-1.4
- Removed problematic browser-caching of messages
- Fix incompatybility with suhosin.executor.disable_emodifier (#1486321)

@ -17,7 +17,7 @@ $rcmail_config = array();
// PEAR database DSN for read/write operations
// format is db_provider://user:password@host/database
// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
// currently supported db_providers: mysql, mysqli, pgsql, sqlite, mssql
// currently supported db_providers: mysql, mysqli, pgsql, sqlite, mssql or sqlsrv
$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
// postgres example: 'pgsql://roundcube:pass@localhost/roundcubemail';

@ -1051,6 +1051,7 @@ class rcmail
return;
$cookie = session_get_cookie_params();
setcookie($name, $value, $exp, $cookie['path'], $cookie['domain'],
rcube_https_check(), true);
}

@ -106,7 +106,7 @@ class rcube_mdb2
if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
$this->_sqlite_create_database($dbh, $this->sqlite_initials);
}
else if ($this->db_provider!='mssql')
else if ($this->db_provider!='mssql' && $this->db_provider!='sqlsrv')
$dbh->setCharset('utf8');
return $dbh;
@ -467,6 +467,7 @@ class rcube_mdb2
switch($this->db_provider)
{
case 'mssql':
case 'sqlsrv':
return "getdate()";
default:
@ -511,6 +512,7 @@ class rcube_mdb2
break;
case 'mssql':
case 'sqlsrv':
return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
default:

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: MDB2.php,v 1.318 2008/03/08 14:18:38 quipo Exp $
// $Id: MDB2.php 292663 2009-12-26 18:21:46Z quipo $
//
/**
@ -101,6 +101,7 @@ define('MDB2_ERROR_MANAGER_PARSE', -33);
define('MDB2_ERROR_LOADMODULE', -34);
define('MDB2_ERROR_INSUFFICIENT_DATA', -35);
define('MDB2_ERROR_NO_PERMISSION', -36);
define('MDB2_ERROR_DISCONNECT_FAILED', -37);
// }}}
// {{{ Verbose constants
@ -342,6 +343,11 @@ class MDB2
$err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
return $err;
}
if (!MDB2::classExists($class_name)) {
$msg = "unable to load class '$class_name' from file '$file_name'";
$err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
return $err;
}
}
return MDB2_OK;
}
@ -403,7 +409,7 @@ class MDB2
// {{{ function &connect($dsn, $options = false)
/**
* Create a new MDB2 connection object and connect to the specified
* Create a new MDB2_Driver_* connection object and connect to the specified
* database
*
* IMPORTANT: In order for MDB2 to work properly it is necessary that
@ -417,11 +423,11 @@ class MDB2
* $db = MDB2::connect($dsn);
* ^^
*
* @param mixed 'data source name', see the MDB2::parseDSN
* @param mixed $dsn 'data source name', see the MDB2::parseDSN
* method for a description of the dsn format.
* Can also be specified as an array of the
* format returned by MDB2::parseDSN.
* @param array An associative array of option names and
* @param array $options An associative array of option names and
* their values.
*
* @return mixed a newly created MDB2 connection object, or a MDB2
@ -566,7 +572,7 @@ class MDB2
*/
function apiVersion()
{
return '2.5.0b1';
return '@package_version@';
}
// }}}
@ -627,7 +633,7 @@ class MDB2
function isError($data, $code = null)
{
if (is_a($data, 'MDB2_Error')) {
if (is_null($code)) {
if (null === $code) {
return true;
} elseif (is_string($code)) {
return $data->getMessage() === $code;
@ -767,10 +773,11 @@ class MDB2
MDB2_ERROR_TRUNCATED => 'truncated',
MDB2_ERROR_DEADLOCK => 'deadlock detected',
MDB2_ERROR_NO_PERMISSION => 'no permission',
MDB2_ERROR_DISCONNECT_FAILED => 'disconnect failed',
);
}
if (is_null($value)) {
if (null === $value) {
return $errorMessages;
}
@ -824,7 +831,7 @@ class MDB2
*/
function parseDSN($dsn)
{
$parsed = array();
$parsed = $GLOBALS['_MDB2_dsninfo_default'];
if (is_array($dsn)) {
$dsn = array_merge($parsed, $dsn);
@ -843,7 +850,6 @@ class MDB2
$dsn = null;
}
// Get phptype and dbsyntax
// $str => phptype(dbsyntax)
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
@ -855,7 +861,7 @@ class MDB2
}
if (!count($dsn)) {
return array_merge($GLOBALS['_MDB2_dsninfo_default'], $parsed);
return $parsed;
}
// Get (if found): username and password
@ -892,7 +898,9 @@ class MDB2
//"username/password@[//]host[:port][/service_name]"
//e.g. "scott/tiger@//mymachine:1521/oracle"
$proto_opts = $dsn;
$dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1);
$pos = strrpos($proto_opts, '/');
$dsn = substr($proto_opts, $pos + 1);
$proto_opts = substr($proto_opts, 0, $pos);
} elseif (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
} else {
@ -930,7 +938,7 @@ class MDB2
}
foreach ($opts as $opt) {
list($key, $value) = explode('=', $opt);
if (!isset($parsed[$key])) {
if (!array_key_exists($key, $parsed) || false === $parsed[$key]) {
// don't allow params overwrite
$parsed[$key] = rawurldecode($value);
}
@ -938,7 +946,7 @@ class MDB2
}
}
return array_merge($GLOBALS['_MDB2_dsninfo_default'], $parsed);
return $parsed;
}
// }}}
@ -1001,7 +1009,7 @@ class MDB2_Error extends PEAR_Error
function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN,
$level = E_USER_NOTICE, $debuginfo = null, $dummy = null)
{
if (is_null($code)) {
if (null === $code) {
$code = MDB2_ERROR;
}
$this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code,
@ -1146,8 +1154,11 @@ class MDB2_Driver_Common extends PEAR
* <li>$options['emulate_prepared'] -> boolean: force prepared statements to be emulated</li>
* <li>$options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes</li>
* <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li>
* <li>$options['bindname_format'] -> string: regular expression pattern for named parameters
* <li>$options['bindname_format'] -> string: regular expression pattern for named parameters</li>
* <li>$options['multi_query'] -> boolean: determines if queries returning multiple result sets should be executed</li>
* <li>$options['max_identifiers_length'] -> integer: max identifier length</li>
* <li>$options['default_fk_action_onupdate'] -> string: default FOREIGN KEY ON UPDATE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']</li>
* <li>$options['default_fk_action_ondelete'] -> string: default FOREIGN KEY ON DELETE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']</li>
* </ul>
*
* @var array
@ -1197,6 +1208,8 @@ class MDB2_Driver_Common extends PEAR
'lob_allow_url_include' => false,
'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)',
'max_identifiers_length' => 30,
'default_fk_action_onupdate' => 'RESTRICT',
'default_fk_action_ondelete' => 'RESTRICT',
);
/**
@ -1427,36 +1440,44 @@ class MDB2_Driver_Common extends PEAR
* callbacks etc. Basically a wrapper for PEAR::raiseError
* without the message string.
*
* @param mixed integer error code, or a PEAR error object (all other
* parameters are ignored if this parameter is an object
* @param int error mode, see PEAR_Error docs
* @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the
* @param mixed $code integer error code, or a PEAR error object (all
* other parameters are ignored if this parameter is
* an object
* @param int $mode error mode, see PEAR_Error docs
* @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
* error level (E_USER_NOTICE etc). If error mode is
* PEAR_ERROR_CALLBACK, this is the callback function,
* either as a function name, or as an array of an
* object and method name. For other error modes this
* parameter is ignored.
* @param string Extra debug information. Defaults to the last
* @param string $userinfo Extra debug information. Defaults to the last
* query and native error code.
* @param string name of the method that triggered the error
* @param string $method name of the method that triggered the error
* @param string $dummy1 not used
* @param bool $dummy2 not used
*
* @return PEAR_Error instance of a PEAR Error object
*
* @access public
* @see PEAR_Error
*/
function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $method = null)
{
function &raiseError($code = null,
$mode = null,
$options = null,
$userinfo = null,
$method = null,
$dummy1 = null,
$dummy2 = false
) {
$userinfo = "[Error message: $userinfo]\n";
// The error is yet a MDB2 error object
if (PEAR::isError($code)) {
// because we use the static PEAR::raiseError, our global
// handler should be used if it is set
if (is_null($mode) && !empty($this->_default_error_mode)) {
if ((null === $mode) && !empty($this->_default_error_mode)) {
$mode = $this->_default_error_mode;
$options = $this->_default_error_options;
}
if (is_null($userinfo)) {
if (null === $userinfo) {
$userinfo = $code->getUserinfo();
}
$code = $code->getCode();
@ -1469,13 +1490,13 @@ class MDB2_Driver_Common extends PEAR
}
$native_errno = $native_msg = null;
list($code, $native_errno, $native_msg) = $this->errorInfo($code);
if (!is_null($native_errno) && $native_errno !== '') {
if ((null !== $native_errno) && $native_errno !== '') {
$userinfo.= "[Native code: $native_errno]\n";
}
if (!is_null($native_msg) && $native_msg !== '') {
if ((null !== $native_msg) && $native_msg !== '') {
$userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n";
}
if (!is_null($method)) {
if (null !== $method) {
$userinfo = $method.': '.$userinfo;
}
}
@ -1926,7 +1947,7 @@ class MDB2_Driver_Common extends PEAR
return $err;
}
$this->{$property} = new $class_name($this->db_index);
$this->modules[$module] = $this->{$property};
$this->modules[$module] =& $this->{$property};
if ($version) {
// this will be used in the connect method to determine if the module
// needs to be loaded with a different version if the server
@ -1973,7 +1994,7 @@ class MDB2_Driver_Common extends PEAR
}
}
}
if (!is_null($module)) {
if (null !== $module) {
return call_user_func_array(array(&$this->modules[$module], $method), $params);
}
trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $method), E_USER_ERROR);
@ -2183,7 +2204,7 @@ class MDB2_Driver_Common extends PEAR
*/
function failNestedTransaction($error = null, $immediately = false)
{
if (is_null($error)) {
if (null !== $error) {
$error = $this->has_transaction_error ? $this->has_transaction_error : true;
} elseif (!$error) {
$error = true;
@ -2265,11 +2286,10 @@ class MDB2_Driver_Common extends PEAR
/**
* Log out and disconnect from the database.
*
* @param bool if the disconnect should be forced even if the
* @param boolean $force whether 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
* @return mixed true on success, false if not connected and error object on error
*
* @access public
*/
@ -2384,6 +2404,26 @@ class MDB2_Driver_Common extends PEAR
return $dsn;
}
// }}}
// {{{ _isNewLinkSet()
/**
* Check if the 'new_link' option is set
*
* @return boolean
*
* @access protected
*/
function _isNewLinkSet()
{
return (isset($this->dsn['new_link'])
&& ($this->dsn['new_link'] === true
|| (is_string($this->dsn['new_link']) && preg_match('/^true$/i', $this->dsn['new_link']))
|| (is_numeric($this->dsn['new_link']) && 0 != (int)$this->dsn['new_link'])
)
);
}
// }}}
// {{{ function &standaloneQuery($query, $types = null, $is_manip = false)
@ -2563,7 +2603,7 @@ class MDB2_Driver_Common extends PEAR
}
// }}}
// {{{ function &_wrapResult($result, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null)
// {{{ function &_wrapResult($result_resource, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null)
/**
* wrap a result set into the correct class
@ -2634,7 +2674,7 @@ class MDB2_Driver_Common extends PEAR
'result wrap class does not exist '.$result_wrap_class, __FUNCTION__);
return $err;
}
$result = new $result_wrap_class($result, $this->fetchmode);
$result = new $result_wrap_class($result_resource, $this->fetchmode);
}
return $result;
}
@ -2682,7 +2722,7 @@ class MDB2_Driver_Common extends PEAR
'it was not specified a valid selected range row limit', __FUNCTION__);
}
$this->limit = $limit;
if (!is_null($offset)) {
if (null !== $offset) {
$offset = (int)$offset;
if ($offset < 0) {
return $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
@ -2739,8 +2779,7 @@ class MDB2_Driver_Common extends PEAR
/**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
* key field values, the old row is deleted before the new row is inserted.
*
* The REPLACE type of query does not make part of the SQL standards. Since
* practically only MySQL and SQLite implement it natively, this type of
@ -2916,7 +2955,6 @@ class MDB2_Driver_Common extends PEAR
$colon = ':';
$positions = array();
$position = 0;
while ($position < strlen($query)) {
$q_position = strpos($query, $question, $position);
$c_position = strpos($query, $colon, $position);
@ -2929,7 +2967,7 @@ class MDB2_Driver_Common extends PEAR
} else {
break;
}
if (is_null($placeholder_type)) {
if (null === $placeholder_type) {
$placeholder_type_guess = $query[$p_position];
}
@ -2943,7 +2981,7 @@ class MDB2_Driver_Common extends PEAR
}
if ($query[$position] == $placeholder_type_guess) {
if (is_null($placeholder_type)) {
if (null === $placeholder_type) {
$placeholder_type = $query[$p_position];
$question = $colon = $placeholder_type;
if (!empty($types) && is_array($types)) {
@ -3007,7 +3045,7 @@ class MDB2_Driver_Common extends PEAR
*/
function _skipDelimitedStrings($query, $position, $p_position)
{
$ignores[] = $this->string_quoting;
$ignores = $this->string_quoting;
$ignores[] = $this->identifier_quoting;
$ignores = array_merge($ignores, $this->sql_comments);
@ -3028,8 +3066,10 @@ class MDB2_Driver_Common extends PEAR
} while ($ignore['escape']
&& $end_quote-1 != $start_quote
&& $query[($end_quote - 1)] == $ignore['escape']
&& ($ignore['escape_pattern'] !== $ignore['escape']
|| $query[($end_quote - 2)] != $ignore['escape']));
&& ( $ignore['escape_pattern'] !== $ignore['escape']
|| $query[($end_quote - 2)] != $ignore['escape'])
);
$position = $end_quote + 1;
return $position;
}
@ -3169,7 +3209,7 @@ class MDB2_Driver_Common extends PEAR
function getIndexName($idx)
{
return sprintf($this->options['idxname_format'],
preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
preg_replace('/[^a-z0-9_\-\$.]/i', '_', $idx));
}
// }}}
@ -3238,12 +3278,12 @@ class MDB2_Driver_Common extends PEAR
* the first row of the result set and then frees
* the result set.
*
* @param string the SELECT query statement to be executed.
* @param string optional argument that specifies the expected
* datatype of the result set field, so that an eventual conversion
* may be performed. The default datatype is text, meaning that no
* conversion is performed
* @param int the column number to fetch
* @param string $query the SELECT query statement to be executed.
* @param string $type optional argument that specifies the expected
* datatype of the result set field, so that an eventual
* conversion may be performed. The default datatype is
* text, meaning that no conversion is performed
* @param mixed $colnum the column number (or name) to fetch
*
* @return mixed MDB2_OK or field value on success, a MDB2 error on failure
*
@ -3299,15 +3339,14 @@ class MDB2_Driver_Common extends PEAR
* Execute the specified query, fetch the value from the first column of
* each row of the result set into an array and then frees the result set.
*
* @param string the SELECT query statement to be executed.
* @param string optional argument that specifies the expected
* datatype of the result set field, so that an eventual conversion
* may be performed. The default datatype is text, meaning that no
* conversion is performed
* @param int the row number to fetch
* @param string $query the SELECT query statement to be executed.
* @param string $type optional argument that specifies the expected
* datatype of the result set field, so that an eventual
* conversion may be performed. The default datatype is text,
* meaning that no conversion is performed
* @param mixed $colnum the column number (or name) to fetch
*
* @return mixed MDB2_OK or data array on success, a MDB2 error on failure
*
* @access public
*/
function queryCol($query, $type = null, $colnum = 0)
@ -3517,11 +3556,10 @@ class MDB2_Result_Common extends MDB2_Result
/**
* fetch single column from the next row from a result set
*
* @param int the column number to fetch
* @param int|string the column number (or name) to fetch
* @param int number of the row where the data can be found
*
* @return string data on success, a MDB2 error on failure
*
* @access public
*/
function fetchOne($colnum = 0, $rownum = null)
@ -3544,10 +3582,9 @@ class MDB2_Result_Common extends MDB2_Result
/**
* Fetch and return a column from the current row pointer position
*
* @param int the column number to fetch
* @param int|string the column number (or name) to fetch
*
* @return mixed data array on success, a MDB2 error on failure
*
* @access public
*/
function fetchCol($colnum = 0)
@ -3608,7 +3645,7 @@ class MDB2_Result_Common extends MDB2_Result
}
$shift_array = $rekey ? false : null;
if (!is_null($shift_array)) {
if (null !== $shift_array) {
if (is_object($row)) {
$colnum = count(get_object_vars($row));
} else {
@ -3814,7 +3851,7 @@ class MDB2_Result_Common extends MDB2_Result
$column = $column_names[$column];
}
$this->values[$column] =& $value;
if (!is_null($type)) {
if (null !== $type) {
$this->types[$column] = $type;
}
return MDB2_OK;
@ -3984,7 +4021,7 @@ class MDB2_Statement_Common
'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
}
$this->values[$parameter] = $value;
if (!is_null($type)) {
if (null !== $type) {
$this->types[$parameter] = $type;
}
return MDB2_OK;
@ -4053,7 +4090,7 @@ class MDB2_Statement_Common
'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
}
$this->values[$parameter] =& $value;
if (!is_null($type)) {
if (null !== $type) {
$this->types[$parameter] = $type;
}
return MDB2_OK;
@ -4095,18 +4132,18 @@ class MDB2_Statement_Common
* Execute a prepared query statement.
*
* @param array specifies all necessary information
* for bindParam() the array elements must use keys corresponding to
* the number of the position of the parameter.
* for bindParam() the array elements must use keys corresponding
* to the number of the position of the parameter.
* @param mixed specifies which result class to use
* @param mixed specifies which class to wrap results in
*
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
*
* @return mixed MDB2_Result or integer (affected rows) on success,
* a MDB2 error on failure
* @access public
*/
function &execute($values = null, $result_class = true, $result_wrap_class = false)
{
if (is_null($this->positions)) {
if (null === $this->positions) {
return $this->db->raiseError(MDB2_ERROR, null, null,
'Prepared statement has already been freed', __FUNCTION__);
}
@ -4132,8 +4169,8 @@ class MDB2_Statement_Common
* @param mixed specifies which result class to use
* @param mixed specifies which class to wrap results in
*
* @return mixed MDB2_Result or integer on success, a MDB2 error on failure
*
* @return mixed MDB2_Result or integer (affected rows) on success,
* a MDB2 error on failure
* @access private
*/
function &_execute($result_class = true, $result_wrap_class = false)
@ -4184,7 +4221,7 @@ class MDB2_Statement_Common
*/
function free()
{
if (is_null($this->positions)) {
if (null === $this->positions) {
return $this->db->raiseError(MDB2_ERROR, null, null,
'Prepared statement has already been freed', __FUNCTION__);
}

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Date.php,v 1.10 2006/03/01 12:15:32 lsmith Exp $
// $Id: Date.php 208329 2006-03-01 12:15:38Z lsmith $
//
/**

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.137 2008/02/17 18:53:40 afz Exp $
// $Id: Common.php 292715 2009-12-28 14:06:34Z quipo $
require_once 'MDB2/LOB.php';
@ -232,7 +232,7 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
*/
function convertResult($value, $type, $rtrim = true)
{
if (is_null($value)) {
if (null === $value) {
return null;
}
$db =& $this->getDBInstance();
@ -313,7 +313,7 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
if (count($types)) {
reset($types);
foreach (array_keys($sorted_types) as $k) {
if (is_null($sorted_types[$k])) {
if (null === $sorted_types[$k]) {
$sorted_types[$k] = current($types);
next($types);
}
@ -511,7 +511,7 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
$field['default'] = ' ';
}
}
if (!is_null($field['default'])) {
if (null !== $field['default']) {
$default = ' DEFAULT ' . $this->quote($field['default'], $field['type']);
}
}
@ -1119,7 +1119,7 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
return $db;
}
if (is_null($value)
if ((null === $value)
|| ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
) {
if (!$quote) {
@ -1128,7 +1128,7 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
return 'NULL';
}
if (is_null($type)) {
if (null === $type) {
switch (gettype($value)) {
case 'integer':
$type = 'integer';
@ -1288,10 +1288,16 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
*/
function _quoteLOB($value, $quote, $escape_wildcards)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->options['lob_allow_url_include']) {
$value = $this->_readFile($value);
if (PEAR::isError($value)) {
return $value;
}
}
return $this->_quoteText($value, $quote, $escape_wildcards);
}
@ -1554,7 +1560,7 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
*/
function _retrieveLOB(&$lob)
{
if (is_null($lob['value'])) {
if (null === $lob['value']) {
$lob['value'] = $lob['resource'];
}
$lob['loaded'] = true;
@ -1687,21 +1693,32 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
}
$match = '';
if (!is_null($operator)) {
if (null !== $operator) {
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
if (is_null($field)) {
if (null === $field) {
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'case insensitive LIKE matching requires passing the field name', __FUNCTION__);
}
$db->loadModule('Function', null, true);
$match = $db->function->lower($field).' LIKE ';
break;
case 'NOT ILIKE':
if (null === $field) {
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'case insensitive NOT ILIKE matching requires passing the field name', __FUNCTION__);
}
$db->loadModule('Function', null, true);
$match = $db->function->lower($field).' NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = is_null($field) ? 'LIKE ' : $field.' LIKE ';
$match = (null === $field) ? 'LIKE ' : ($field.' LIKE ');
break;
case 'NOT LIKE':
$match = (null === $field) ? 'NOT LIKE ' : ($field.' NOT LIKE ');
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
@ -1713,9 +1730,6 @@ class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
if ($key % 2) {
$match.= $value;
} else {
if ($operator === 'ILIKE') {
$value = strtolower($value);
}
$escaped = $db->escape($value);
if (PEAR::isError($escaped)) {
return $escaped;

@ -44,7 +44,7 @@
// | Daniel Convissor <danielc@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.65 2008/02/19 14:54:17 afz Exp $
// $Id: mssql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
@ -71,7 +71,7 @@ class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common
*/
function _baseConvertResult($value, $type, $rtrim = true)
{
if (is_null($value)) {
if (null === $value) {
return null;
}
switch ($type) {
@ -228,7 +228,7 @@ class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common
if ($field['default'] === '') {
$field['default'] = 0;
}
if (is_null($field['default'])) {
if (null === $field['default']) {
$default = ' DEFAULT (null)';
} else {
$default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')';
@ -338,6 +338,65 @@ class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common
return $value;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* @access public
*
* @param array $pattern even keys are strings, odd are patterns (% and _)
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
* @param string $field optional field name that is being matched against
* (might be required when emulating ILIKE)
*
* @return string SQL pattern
*/
function matchPattern($pattern, $operator = null, $field = null)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$match = '';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);
}
}
$match.= "'";
foreach ($pattern as $key => $value) {
if ($key % 2) {
$match.= $value;
} else {
$match.= $db->escapePattern($db->escape($value));
}
}
$match.= "'";
$match.= $this->patternEscapeString();
return $match;
}
// }}}
// {{{ _mapNativeDatatype()
@ -376,6 +435,7 @@ class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common
$type[0] = 'integer';
$length = 8;
break;
case 'smalldatetime':
case 'datetime':
$type[0] = 'timestamp';
break;

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.65 2008/02/22 19:23:49 quipo Exp $
// $Id: mysql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
@ -352,18 +352,24 @@ class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE BINARY ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE BINARY ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php,v 1.63 2008/02/22 19:23:49 quipo Exp $
// $Id: mysqli.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
@ -352,18 +352,24 @@ class MDB2_Driver_Datatype_mysqli extends MDB2_Driver_Datatype_Common
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE BINARY ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE BINARY ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);

@ -42,7 +42,7 @@
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.91 2008/03/09 12:28:08 quipo Exp $
// $Id: pgsql.php 292715 2009-12-28 14:06:34Z quipo $
require_once 'MDB2/Driver/Datatype/Common.php';
@ -68,7 +68,7 @@ class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
*/
function _baseConvertResult($value, $type, $rtrim = true)
{
if (is_null($value)) {
if (null === $value) {
return null;
}
switch ($type) {
@ -124,8 +124,7 @@ class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
switch ($field['type']) {
case 'text':
$length = !empty($field['length'])
? $field['length'] : $db->options['default_text_field_length'];
$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');
@ -240,6 +239,16 @@ class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
*/
function _quoteCLOB($value, $quote, $escape_wildcards)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->options['lob_allow_url_include']) {
$value = $this->_readFile($value);
if (PEAR::isError($value)) {
return $value;
}
}
return $this->_quoteText($value, $quote, $escape_wildcards);
}
@ -262,11 +271,17 @@ class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
if (!$quote) {
return $value;
}
if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->options['lob_allow_url_include']) {
$value = $this->_readFile($value);
if (PEAR::isError($value)) {
return $value;
}
}
if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
$connection = $db->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -324,18 +339,24 @@ class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'ILIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT ILIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $
// $Id: sqlite.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
@ -243,18 +243,24 @@ class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);

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

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.21 2008/02/17 18:51:39 quipo Exp $
// $Id: Common.php 292715 2009-12-28 14:06:34Z quipo $
//
/**
@ -166,7 +166,7 @@ class MDB2_Driver_Function_Common extends MDB2_Module_Common
*/
function substring($value, $position = 1, $length = null)
{
if (!is_null($length)) {
if (null !== $length) {
return "SUBSTRING($value FROM $position FOR $length)";
}
return "SUBSTRING($value FROM $position)";

@ -42,7 +42,7 @@
// | Author: Frank M. Kromann <frank@kromann.info> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.16 2008/02/17 18:54:08 quipo Exp $
// $Id: mssql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';
@ -134,7 +134,7 @@ class MDB2_Driver_Function_mssql extends MDB2_Driver_Function_Common
*/
function substring($value, $position = 1, $length = null)
{
if (!is_null($length)) {
if (null !== $length) {
return "SUBSTRING($value, $position, $length)";
}
return "SUBSTRING($value, $position, LEN($value) - $position + 1)";

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.12 2008/02/17 18:54:08 quipo Exp $
// $Id: mysql.php 253106 2008-02-17 18:54:08Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php,v 1.14 2008/02/17 18:54:08 quipo Exp $
// $Id: mysqli.php 253106 2008-02-17 18:54:08Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';

@ -42,7 +42,7 @@
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.10 2008/02/17 18:54:08 quipo Exp $
// $Id: pgsql.php 268669 2008-11-09 19:46:50Z quipo $
require_once 'MDB2/Driver/Function/Common.php';
@ -93,7 +93,7 @@ class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common
*/
function unixtimestamp($expression)
{
return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', TIMESTAMP '. $expression.'))';
return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', CAST ((' . $expression . ') AS TIMESTAMP)))';
}
// }}}

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php,v 1.10 2008/02/17 18:54:08 quipo Exp $
// $Id: sqlite.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';
@ -116,10 +116,10 @@ class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common
*/
function substring($value, $position = 1, $length = null)
{
if (!is_null($length)) {
return "substr($value,$position,$length)";
if (null !== $length) {
return "substr($value, $position, $length)";
}
return "substr($value,$position,length($value))";
return "substr($value, $position, length($value))";
}
// }}}

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

@ -43,7 +43,7 @@
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.71 2008/02/12 23:12:27 quipo Exp $
// $Id: Common.php 273526 2009-01-14 15:01:21Z quipo $
//
/**
@ -69,6 +69,10 @@ class MDB2_Driver_Manager_Common extends MDB2_Module_Common
/**
* Split the "[owner|schema].table" notation into an array
*
* @param string $table [schema and] table name
*
* @return array array(schema, table)
* @access private
*/
function splitTableSchema($table)

@ -44,7 +44,7 @@
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.109 2008/03/05 12:55:57 afz Exp $
// $Id: mssql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Manager/Common.php';
@ -715,11 +715,11 @@ class MDB2_Driver_Manager_mssql extends MDB2_Driver_Manager_Common
return $db;
}
$table = $db->quoteIdentifier($table, true);
$table = $db->quote($table, 'text');
$columns = $db->queryCol("SELECT c.name
FROM syscolumns c
LEFT JOIN sysobjects o ON c.id = o.id
WHERE o.name = '$table'");
WHERE o.name = $table");
if (PEAR::isError($columns)) {
return $columns;
}
@ -893,7 +893,7 @@ class MDB2_Driver_Manager_mssql extends MDB2_Driver_Manager_Common
FROM sysobjects o
WHERE xtype = 'TR'
AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0";
if (!is_null($table)) {
if (null !== $table) {
$query .= " AND object_name(parent_obj) = $table";
}
@ -994,12 +994,12 @@ class MDB2_Driver_Manager_mssql extends MDB2_Driver_Manager_Common
if (PEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$table = $db->quote($table, 'text');
$query = "SELECT c.constraint_name
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
WHERE c.constraint_catalog = DB_NAME()
AND c.table_name = '$table'";
AND c.table_name = $table";
$constraints = $db->queryCol($query);
if (PEAR::isError($constraints)) {
return $constraints;

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.108 2008/03/11 19:58:12 quipo Exp $
// $Id: mysql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Manager/Common.php';
@ -222,7 +222,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
$autoincrement = $fieldname;
}
}
if (!is_null($autoincrement) && count($pk_fields) > 1) {
if ((null !== $autoincrement) && count($pk_fields) > 1) {
$options['primary'] = $pk_fields;
} else {
// the PK constraint is on max one field => OK
@ -235,7 +235,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
return $query;
}
if (!is_null($autoincrement)) {
if (null !== $autoincrement) {
// we have to remove the PK clause added by _getIntegerDeclaration()
$query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query);
}
@ -659,7 +659,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$query = 'SHOW TRIGGERS';
if (!is_null($table)) {
if (null !== $table) {
$table = $db->quote($table, 'text');
$query .= " LIKE $table";
}
@ -691,7 +691,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$query = "SHOW /*!50002 FULL*/ TABLES";
if (!is_null($database)) {
if (null !== $database) {
$query .= " FROM $database";
}
$query.= "/*!50002 WHERE Table_type = 'BASE TABLE'*/";
@ -731,7 +731,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$query = 'SHOW FULL TABLES';
if (!is_null($database)) {
if (null !== $database) {
$query.= " FROM $database";
}
$query.= " WHERE Table_type = 'VIEW'";
@ -940,10 +940,10 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$type = '';
$name = $db->quoteIdentifier($db->getIndexName($name), true);
$idx_name = $db->quoteIdentifier($db->getIndexName($name), true);
if (!empty($definition['primary'])) {
$type = 'PRIMARY';
$name = 'KEY';
$idx_name = 'KEY';
} elseif (!empty($definition['unique'])) {
$type = 'UNIQUE';
} elseif (!empty($definition['foreign'])) {
@ -955,13 +955,17 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$table_quoted = $db->quoteIdentifier($table, true);
$query = "ALTER TABLE $table_quoted ADD $type $name";
$query = "ALTER TABLE $table_quoted ADD $type $idx_name";
if (!empty($definition['foreign'])) {
$query .= ' FOREIGN KEY';
}
$fields = array();
foreach (array_keys($definition['fields']) as $field) {
$fields[] = $db->quoteIdentifier($field, true);
foreach ($definition['fields'] as $field => $fieldinfo) {
$quoted = $db->quoteIdentifier($field, true);
if (!empty($fieldinfo['length'])) {
$quoted .= '(' . $fieldinfo['length'] . ')';
}
$fields[] = $quoted;
}
$query .= ' ('. implode(', ', $fields) . ')';
if (!empty($definition['foreign'])) {
@ -972,6 +976,13 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$query .= ' ('. implode(', ', $referenced_fields) . ')';
$query .= $this->_getAdvancedFKOptions($definition);
// add index on FK column(s) or we can't add a FK constraint
// @see http://forums.mysql.com/read.php?22,19755,226009
$result = $this->createIndex($table, $name.'_fkidx', $definition);
if (PEAR::isError($result)) {
return $result;
}
}
$res = $db->exec($query);
if (PEAR::isError($res)) {
@ -1053,14 +1064,14 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
// create triggers to enforce FOREIGN KEY constraints
if ($db->supports('triggers') && !empty($foreign_keys)) {
$table = $db->quoteIdentifier($table, true);
$table_quoted = $db->quoteIdentifier($table, true);
foreach ($foreign_keys as $fkname => $fkdef) {
if (empty($fkdef)) {
continue;
}
//set actions to 'RESTRICT' if not set
$fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']);
$fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']);
//set actions to default if not set
$fkdef['onupdate'] = empty($fkdef['onupdate']) ? $db->options['default_fk_action_onupdate'] : strtoupper($fkdef['onupdate']);
$fkdef['ondelete'] = empty($fkdef['ondelete']) ? $db->options['default_fk_action_ondelete'] : strtoupper($fkdef['ondelete']);
$trigger_names = array(
'insert' => $fkname.'_insert_trg',
@ -1075,10 +1086,10 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
$restrict_action = ' IF (SELECT ';
$aliased_fields = array();
foreach ($table_fields as $field) {
$aliased_fields[] = $table .'.'.$field .' AS '.$field;
$aliased_fields[] = $table_quoted .'.'.$field .' AS '.$field;
}
$restrict_action .= implode(',', $aliased_fields)
.' FROM '.$table
.' FROM '.$table_quoted
.' WHERE ';
$conditions = array();
$new_values = array();
@ -1088,13 +1099,24 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
$new_values[] = $table_fields[$i] .' = NEW.'.$referenced_fields[$i];
$null_values[] = $table_fields[$i] .' = NULL';
}
$restrict_action .= implode(' AND ', $conditions).') IS NOT NULL'
.' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
$conditions2 = array();
if ('NO ACTION' != $fkdef['ondelete']) {
// There is no NEW row in on DELETE trigger
for ($i=0; $i<count($referenced_fields); $i++) {
$conditions2[] = 'NEW.'.$referenced_fields[$i] .' <> OLD.'.$referenced_fields[$i];
}
}
$restrict_action .= implode(' AND ', $conditions).') IS NOT NULL';
if (!empty($conditions2)) {
$restrict_action .= ' AND (' .implode(' OR ', $conditions2) .')';
}
$restrict_action .= ' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
.' END IF;';
$cascade_action_update = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
$cascade_action_delete = 'DELETE FROM '.$table.' WHERE '.implode(' AND ', $conditions). ';';
$setnull_action = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
$cascade_action_update = 'UPDATE '.$table_quoted.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
$cascade_action_delete = 'DELETE FROM '.$table_quoted.' WHERE '.implode(' AND ', $conditions). ';';
$setnull_action = 'UPDATE '.$table_quoted.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
$db->loadModule('Reverse', null, true);
@ -1106,7 +1128,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$default_values[] = $table_field .' = '. $field_definition[0]['default'];
}
$setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
$setdefault_action = 'UPDATE '.$table_quoted.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
}
$query = 'CREATE TRIGGER %s'
@ -1122,8 +1144,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
$sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action;
} elseif ('NO ACTION' == $fkdef['onupdate']) {
$sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update');
} else {
//'RESTRICT'
} elseif ('RESTRICT' == $fkdef['onupdate']) {
$sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update');
}
if ('CASCADE' == $fkdef['ondelete']) {
@ -1134,8 +1155,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
$sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action;
} elseif ('NO ACTION' == $fkdef['ondelete']) {
$sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete');
} else {
//'RESTRICT'
} elseif ('RESTRICT' == $fkdef['ondelete']) {
$sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete');
}
$sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
@ -1393,7 +1413,7 @@ class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
}
$query = "SHOW TABLES";
if (!is_null($database)) {
if (null !== $database) {
$query .= " FROM $database";
}
$table_names = $db->queryCol($query);

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php,v 1.95 2008/03/11 19:58:12 quipo Exp $
// $Id: mysqli.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Manager/Common.php';
@ -222,7 +222,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
$autoincrement = $fieldname;
}
}
if (!is_null($autoincrement) && count($pk_fields) > 1) {
if ((null !== $autoincrement) && count($pk_fields) > 1) {
$options['primary'] = $pk_fields;
} else {
// the PK constraint is on max one field => OK
@ -235,7 +235,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
return $query;
}
if (!is_null($autoincrement)) {
if (null !== $autoincrement) {
// we have to remove the PK clause added by _getIntegerDeclaration()
$query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query);
}
@ -659,7 +659,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$query = 'SHOW TRIGGERS';
if (!is_null($table)) {
if (null !== $table) {
$table = $db->quote($table, 'text');
$query .= " LIKE $table";
}
@ -691,7 +691,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$query = "SHOW /*!50002 FULL*/ TABLES";
if (!is_null($database)) {
if (null !== $database) {
$query .= " FROM $database";
}
$query.= "/*!50002 WHERE Table_type = 'BASE TABLE'*/";
@ -731,7 +731,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$query = 'SHOW FULL TABLES';
if (!is_null($database)) {
if (null !== $database) {
$query.= " FROM $database";
}
$query.= " WHERE Table_type = 'VIEW'";
@ -940,10 +940,10 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$type = '';
$name = $db->quoteIdentifier($db->getIndexName($name), true);
$idx_name = $db->quoteIdentifier($db->getIndexName($name), true);
if (!empty($definition['primary'])) {
$type = 'PRIMARY';
$name = 'KEY';
$idx_name = 'KEY';
} elseif (!empty($definition['unique'])) {
$type = 'UNIQUE';
} elseif (!empty($definition['foreign'])) {
@ -955,13 +955,17 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$table_quoted = $db->quoteIdentifier($table, true);
$query = "ALTER TABLE $table_quoted ADD $type $name";
$query = "ALTER TABLE $table_quoted ADD $type $idx_name";
if (!empty($definition['foreign'])) {
$query .= ' FOREIGN KEY';
}
$fields = array();
foreach (array_keys($definition['fields']) as $field) {
$fields[] = $db->quoteIdentifier($field, true);
foreach ($definition['fields'] as $field => $fieldinfo) {
$quoted = $db->quoteIdentifier($field, true);
if (!empty($fieldinfo['length'])) {
$quoted .= '(' . $fieldinfo['length'] . ')';
}
$fields[] = $quoted;
}
$query .= ' ('. implode(', ', $fields) . ')';
if (!empty($definition['foreign'])) {
@ -972,6 +976,13 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$query .= ' ('. implode(', ', $referenced_fields) . ')';
$query .= $this->_getAdvancedFKOptions($definition);
// add index on FK column(s) or we can't add a FK constraint
// @see http://forums.mysql.com/read.php?22,19755,226009
$result = $this->createIndex($table, $name.'_fkidx', $definition);
if (PEAR::isError($result)) {
return $result;
}
}
$res = $db->exec($query);
if (PEAR::isError($res)) {
@ -1053,14 +1064,14 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
// create triggers to enforce FOREIGN KEY constraints
if ($db->supports('triggers') && !empty($foreign_keys)) {
$table = $db->quoteIdentifier($table, true);
$table_quoted = $db->quoteIdentifier($table, true);
foreach ($foreign_keys as $fkname => $fkdef) {
if (empty($fkdef)) {
continue;
}
//set actions to 'RESTRICT' if not set
$fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']);
$fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']);
//set actions to default if not set
$fkdef['onupdate'] = empty($fkdef['onupdate']) ? $db->options['default_fk_action_onupdate'] : strtoupper($fkdef['onupdate']);
$fkdef['ondelete'] = empty($fkdef['ondelete']) ? $db->options['default_fk_action_ondelete'] : strtoupper($fkdef['ondelete']);
$trigger_names = array(
'insert' => $fkname.'_insert_trg',
@ -1075,10 +1086,10 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
$restrict_action = ' IF (SELECT ';
$aliased_fields = array();
foreach ($table_fields as $field) {
$aliased_fields[] = $table .'.'.$field .' AS '.$field;
$aliased_fields[] = $table_quoted .'.'.$field .' AS '.$field;
}
$restrict_action .= implode(',', $aliased_fields)
.' FROM '.$table
.' FROM '.$table_quoted
.' WHERE ';
$conditions = array();
$new_values = array();
@ -1088,13 +1099,24 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
$new_values[] = $table_fields[$i] .' = NEW.'.$referenced_fields[$i];
$null_values[] = $table_fields[$i] .' = NULL';
}
$restrict_action .= implode(' AND ', $conditions).') IS NOT NULL'
.' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
$conditions2 = array();
if ('NO ACTION' != $fkdef['ondelete']) {
// There is no NEW row in on DELETE trigger
for ($i=0; $i<count($referenced_fields); $i++) {
$conditions2[] = 'NEW.'.$referenced_fields[$i] .' <> OLD.'.$referenced_fields[$i];
}
}
$restrict_action .= implode(' AND ', $conditions).') IS NOT NULL';
if (!empty($conditions2)) {
$restrict_action .= ' AND (' .implode(' OR ', $conditions2) .')';
}
$restrict_action .= ' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
.' END IF;';
$cascade_action_update = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
$cascade_action_delete = 'DELETE FROM '.$table.' WHERE '.implode(' AND ', $conditions). ';';
$setnull_action = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
$cascade_action_update = 'UPDATE '.$table_quoted.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
$cascade_action_delete = 'DELETE FROM '.$table_quoted.' WHERE '.implode(' AND ', $conditions). ';';
$setnull_action = 'UPDATE '.$table_quoted.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
$db->loadModule('Reverse', null, true);
@ -1106,7 +1128,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$default_values[] = $table_field .' = '. $field_definition[0]['default'];
}
$setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
$setdefault_action = 'UPDATE '.$table_quoted.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
}
$query = 'CREATE TRIGGER %s'
@ -1122,8 +1144,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
$sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action;
} elseif ('NO ACTION' == $fkdef['onupdate']) {
$sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update');
} else {
//'RESTRICT'
} elseif ('RESTRICT' == $fkdef['onupdate']) {
$sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update');
}
if ('CASCADE' == $fkdef['ondelete']) {
@ -1134,8 +1155,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
$sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action;
} elseif ('NO ACTION' == $fkdef['ondelete']) {
$sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete');
} else {
//'RESTRICT'
} elseif ('RESTRICT' == $fkdef['ondelete']) {
$sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete');
}
$sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
@ -1393,7 +1413,7 @@ class MDB2_Driver_Manager_mysqli extends MDB2_Driver_Manager_Common
}
$query = "SHOW TABLES";
if (!is_null($database)) {
if (null !== $database) {
$query .= " FROM $database";
}
$table_names = $db->queryCol($query);

@ -42,7 +42,7 @@
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.82 2008/03/05 12:55:57 afz Exp $
// $Id: pgsql.php 292715 2009-12-28 14:06:34Z quipo $
require_once 'MDB2/Driver/Manager/Common.php';
@ -349,6 +349,8 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
return MDB2_OK;
}
$name = $db->quoteIdentifier($name, true);
if (!empty($changes['remove']) && is_array($changes['remove'])) {
foreach ($changes['remove'] as $field_name => $field) {
$field_name = $db->quoteIdentifier($field_name, true);
@ -393,7 +395,8 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
'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']);
$type = $db->datatype->getTypeDeclaration($field['definition']);
$query = "ALTER $field_name TYPE $type USING CAST($field_name AS $type)";
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
return $result;
@ -406,7 +409,7 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
return $result;
}
}
if (!empty($field['definition']['notnull'])) {
if (array_key_exists('notnull', $field['definition'])) {
$query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL';
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
@ -416,7 +419,6 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
}
}
$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);
@ -606,9 +608,9 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
FROM pg_trigger trg,
pg_class tbl
WHERE trg.tgrelid = tbl.oid';
if (!is_null($table)) {
if (null !== $table) {
$table = $db->quote(strtoupper($table), 'text');
$query .= " AND tbl.relname = $table";
$query .= " AND UPPER(tbl.relname) = $table";
}
$result = $db->queryCol($query);
if (PEAR::isError($result)) {
@ -683,7 +685,12 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
return $db;
}
list($schema, $table) = $this->splitTableSchema($table);
$table = $db->quoteIdentifier($table, true);
if (!empty($schema)) {
$table = $db->quoteIdentifier($schema, true) . '.' .$table;
}
$db->setLimit(1);
$result2 = $db->query("SELECT * FROM $table");
if (PEAR::isError($result2)) {
@ -714,9 +721,19 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
return $db;
}
list($schema, $table) = $this->splitTableSchema($table);
$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'";
$subquery = "SELECT indexrelid
FROM pg_index
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE pg_class.relname = $table
AND indisunique != 't'
AND indisprimary != 't'";
if (!empty($schema)) {
$subquery .= ' AND pg_namespace.nspname = '.$db->quote($schema, 'text');
}
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
$indexes = $db->queryCol($query, 'text');
if (PEAR::isError($indexes)) {
@ -737,6 +754,57 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
return array_keys($result);
}
// }}}
// {{{ dropConstraint()
/**
* drop existing constraint
*
* @param string $table name of table that should be used in method
* @param string $name name of the constraint to be dropped
* @param string $primary hint if the constraint is primary
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropConstraint($table, $name, $primary = false)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
// is it an UNIQUE index?
$query = 'SELECT relname
FROM pg_class
WHERE oid IN (
SELECT indexrelid
FROM pg_index, pg_class
WHERE pg_class.relname = '.$db->quote($table, 'text').'
AND pg_class.oid = pg_index.indrelid
AND indisunique = \'t\')
EXCEPT
SELECT conname
FROM pg_constraint, pg_class
WHERE pg_constraint.conrelid = pg_class.oid
AND relname = '. $db->quote($table, 'text');
$unique = $db->queryCol($query, 'text');
if (PEAR::isError($unique) || empty($unique)) {
// not an UNIQUE index, maybe a CONSTRAINT
return parent::dropConstraint($table, $name, $primary);
}
if (in_array($name, $unique)) {
return $db->exec('DROP INDEX '.$db->quoteIdentifier($name, true));
}
$idxname = $db->getIndexName($name);
if (in_array($idxname, $unique)) {
return $db->exec('DROP INDEX '.$db->quoteIdentifier($idxname, true));
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$name . ' is not an existing constraint for table ' . $table, __FUNCTION__);
}
// }}}
// {{{ listTableConstraints()
@ -754,11 +822,32 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
return $db;
}
list($schema, $table) = $this->splitTableSchema($table);
$table = $db->quote($table, 'text');
$query = 'SELECT conname
FROM pg_constraint, pg_class
WHERE pg_constraint.conrelid = pg_class.oid
AND relname = ' .$table;
FROM pg_constraint
LEFT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE relname = ' .$table;
if (!empty($schema)) {
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
}
$query .= '
UNION DISTINCT
SELECT relname
FROM pg_class
WHERE oid IN (
SELECT indexrelid
FROM pg_index
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE pg_class.relname = '.$table.'
AND indisunique = \'t\'';
if (!empty($schema)) {
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
}
$query .= ')';
$constraints = $db->queryCol($query);
if (PEAR::isError($constraints)) {
return $constraints;

@ -43,7 +43,7 @@
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php,v 1.74 2008/03/05 11:08:53 quipo Exp $
// $Id: sqlite.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Manager/Common.php';
@ -221,8 +221,10 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
* 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
* @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 MDB2_OK on success, a MDB2 error on failure
* @access public
*/
@ -242,9 +244,9 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
if (empty($fkdef)) {
continue;
}
//set actions to 'RESTRICT' if not set
$fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']);
$fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']);
//set actions to default if not set
$fkdef['onupdate'] = empty($fkdef['onupdate']) ? $db->options['default_fk_action_onupdate'] : strtoupper($fkdef['onupdate']);
$fkdef['ondelete'] = empty($fkdef['ondelete']) ? $db->options['default_fk_action_ondelete'] : strtoupper($fkdef['ondelete']);
$trigger_names = array(
'insert' => $fkname.'_insert_trg',
@ -300,7 +302,12 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
$new_values[] = $table_fields[$i] .' = NEW.'.$referenced_fields[$i];
$null_values[] = $table_fields[$i] .' = NULL';
}
$restrict_action .= implode(' AND ', $conditions).') IS NOT NULL';
$conditions2 = array();
for ($i=0; $i<count($referenced_fields); $i++) {
$conditions2[] = 'NEW.'.$referenced_fields[$i] .' <> OLD.'.$referenced_fields[$i];
}
$restrict_action .= implode(' AND ', $conditions).') IS NOT NULL'
.' AND (' .implode(' OR ', $conditions2) .')';
$cascade_action_update = 'UPDATE '.$name.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions);
$cascade_action_delete = 'DELETE FROM '.$name.' WHERE '.implode(' AND ', $conditions);
@ -331,8 +338,7 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
$sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action. '; END;';
} elseif ('NO ACTION' == $fkdef['onupdate']) {
$sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update') . '; END;';
} else {
//'RESTRICT'
} elseif ('RESTRICT' == $fkdef['onupdate']) {
$sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . '; END;';
}
if ('CASCADE' == $fkdef['ondelete']) {
@ -343,8 +349,7 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
$sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action. '; END;';
} elseif ('NO ACTION' == $fkdef['ondelete']) {
$sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete') . '; END;';
} else {
//'RESTRICT'
} elseif ('RESTRICT' == $fkdef['ondelete']) {
$sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . '; END;';
}
@ -899,7 +904,7 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
}
$query = "SELECT name FROM sqlite_master WHERE type='trigger' AND sql NOT NULL";
if (!is_null($table)) {
if (null !== $table) {
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$query.= ' AND LOWER(tbl_name)='.$db->quote(strtolower($table), 'text');
} else {
@ -1159,6 +1164,7 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
* @param string $table table name
* @param string $fkname FOREIGN KEY constraint name
* @param string $referenced_table referenced table name
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access private
*/
@ -1186,7 +1192,7 @@ class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
return MDB2_OK;
}
// }]]
// }}}
// {{{ listTableConstraints()
/**

File diff suppressed because it is too large Load Diff

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.2 2007/09/09 13:47:36 quipo Exp $
// $Id: Common.php 242348 2007-09-09 13:47:36Z quipo $
//
/**

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $
// $Id: mssql.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $
// $Id: mysql.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php,v 1.8 2006/06/18 21:59:05 lsmith Exp $
// $Id: mysqli.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';

@ -42,7 +42,7 @@
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.12 2006/07/15 13:07:15 lsmith Exp $
// $Id: pgsql.php 216444 2006-07-15 13:07:15Z lsmith $
require_once 'MDB2/Driver/Native/Common.php';

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $
// $Id: sqlite.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';

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

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.42 2008/01/12 12:50:58 quipo Exp $
// $Id: Common.php 273526 2009-01-14 15:01:21Z quipo $
//
/**
@ -76,6 +76,10 @@ class MDB2_Driver_Reverse_Common extends MDB2_Module_Common
/**
* Split the "[owner|schema].table" notation into an array
*
* @param string $table [schema and] table name
*
* @return array array(schema, table)
* @access private
*/
function splitTableSchema($table)

@ -43,7 +43,7 @@
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.49 2008/02/17 15:30:57 quipo Exp $
// $Id: mssql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
@ -134,7 +134,7 @@ class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common
$default = false;
if (array_key_exists('column_default', $column)) {
$default = $column['column_default'];
if (is_null($default) && $notnull) {
if ((null === $default) && $notnull) {
$default = '';
} elseif (strlen($default) > 4
&& substr($default, 0, 1) == '('
@ -151,16 +151,16 @@ class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (!is_null($length)) {
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_null($fixed)) {
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
if (false !== $default) {
$definition[0]['default'] = $default;
}
foreach ($types as $key => $type) {
@ -222,7 +222,7 @@ class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $index_name_mdb2));
if (!PEAR::isError($result) && !is_null($result)) {
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
@ -320,7 +320,7 @@ class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $constraint_name_mdb2));
if (!PEAR::isError($result) && !is_null($result)) {
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.79 2007/11/25 13:38:29 quipo Exp $
// $Id: mysql.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
@ -113,7 +113,7 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
$default = false;
if (array_key_exists('default', $column)) {
$default = $column['default'];
if (is_null($default) && $notnull) {
if ((null === $default) && $notnull) {
$default = '';
}
}
@ -131,13 +131,13 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (!is_null($length)) {
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_null($fixed)) {
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
@ -146,7 +146,7 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
if ($autoincrement !== false) {
$definition[0]['autoincrement'] = $autoincrement;
}
if (!is_null($collate)) {
if (null !== $collate) {
$definition[0]['collate'] = $collate;
$definition[0]['charset'] = $charset;
}
@ -192,7 +192,7 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
if (!PEAR::isError($result) && !is_null($result)) {
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
@ -269,7 +269,7 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
if (strtolower($constraint_name) != 'primary') {
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
if (!PEAR::isError($result) && !is_null($result)) {
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;
@ -310,6 +310,56 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
if ($constraint_name == $key_name) {
if ($row['non_unique']) {
//FOREIGN KEY?
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
if ($row['key_name'] == 'PRIMARY') {
$definition['primary'] = true;
} elseif (!$row['non_unique']) {
$definition['unique'] = true;
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
return $definition;
}
// }}}
// {{{ _getTableFKConstraintDefinition()
/**
* Get the FK definition from the CREATE TABLE statement
*
* @param string $table table name
* @param string $constraint_name constraint name
* @param array $definition default values for constraint definition
*
* @return array|PEAR_Error
* @access private
*/
function _getTableFKConstraintDefinition($table, $constraint_name, $definition)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SHOW CREATE TABLE '. $db->escape($table);
$constraint = $db->queryOne($query, 'text', 1);
if (!PEAR::isError($constraint) && !empty($constraint)) {
@ -320,6 +370,8 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
$constraint = strtoupper($constraint);
}
}
$constraint_name_original = $constraint_name;
$constraint_name = $db->getIndexName($constraint_name);
$pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i';
if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
//fallback to original constraint name
@ -351,39 +403,9 @@ class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
return $definition;
}
}
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;
} elseif (!$row['non_unique']) {
$definition['unique'] = true;
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTriggerDefinition()

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php,v 1.69 2007/11/25 13:38:29 quipo Exp $
// $Id: mysqli.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
@ -167,7 +167,7 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
$default = false;
if (array_key_exists('default', $column)) {
$default = $column['default'];
if (is_null($default) && $notnull) {
if ((null === $default) && $notnull) {
$default = '';
}
}
@ -185,13 +185,13 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (!is_null($length)) {
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_null($fixed)) {
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
@ -200,7 +200,7 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
if ($autoincrement !== false) {
$definition[0]['autoincrement'] = $autoincrement;
}
if (!is_null($collate)) {
if (null !== $collate) {
$definition[0]['collate'] = $collate;
$definition[0]['charset'] = $charset;
}
@ -246,7 +246,7 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
if (!PEAR::isError($result) && !is_null($result)) {
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
@ -323,7 +323,7 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
if (strtolower($constraint_name) != 'primary') {
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
if (!PEAR::isError($result) && !is_null($result)) {
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;
@ -364,6 +364,56 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
if ($constraint_name == $key_name) {
if ($row['non_unique']) {
//FOREIGN KEY?
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
if ($row['key_name'] == 'PRIMARY') {
$definition['primary'] = true;
} elseif (!$row['non_unique']) {
$definition['unique'] = true;
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
return $definition;
}
// }}}
// {{{ _getTableFKConstraintDefinition()
/**
* Get the FK definition from the CREATE TABLE statement
*
* @param string $table table name
* @param string $constraint_name constraint name
* @param array $definition default values for constraint definition
*
* @return array|PEAR_Error
* @access private
*/
function _getTableFKConstraintDefinition($table, $constraint_name, $definition)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SHOW CREATE TABLE '. $db->escape($table);
$constraint = $db->queryOne($query, 'text', 1);
if (!PEAR::isError($constraint) && !empty($constraint)) {
@ -374,6 +424,8 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
$constraint = strtoupper($constraint);
}
}
$constraint_name_original = $constraint_name;
$constraint_name = $db->getIndexName($constraint_name);
$pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i';
if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
//fallback to original constraint name
@ -405,39 +457,9 @@ class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
return $definition;
}
}
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;
} elseif (!$row['non_unique']) {
$definition['unique'] = true;
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTriggerDefinition()

@ -43,7 +43,7 @@
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.70 2008/03/13 20:38:09 quipo Exp $
// $Id: pgsql.php 292715 2009-12-28 14:06:34Z quipo $
require_once 'MDB2/Driver/Reverse/Common.php';
@ -143,11 +143,12 @@ class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
}
$default = null;
if ($column['atthasdef'] === 't'
&& strpos($column['default'], 'NULL') !== 0
&& !preg_match("/nextval\('([^']+)'/", $column['default'])
) {
$pattern = '/(\'.*\')::[\w ]+$/i';
$pattern = '/^\'(.*)\'::[\w ]+$/i';
$default = $column['default'];#substr($column['adsrc'], 1, -1);
if (is_null($default) && $notnull) {
if ((null === $default) && $notnull) {
$default = '';
} elseif (!empty($default) && preg_match($pattern, $default)) {
//remove data type cast
@ -159,13 +160,13 @@ class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
$autoincrement = true;
}
$definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
if (!is_null($length)) {
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_null($fixed)) {
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
@ -310,11 +311,42 @@ class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
if (PEAR::isError($row)) {
return $row;
}
$uniqueIndex = false;
if (empty($row)) {
// We might be looking for a UNIQUE index that was not created
// as a constraint but should be treated as such.
$query = 'SELECT relname AS constraint_name,
indkey,
0 AS "check",
0 AS "foreign",
0 AS "primary",
1 AS "unique",
0 AS deferrable,
0 AS initiallydeferred,
NULL AS references_table,
NULL AS onupdate,
NULL AS ondelete,
NULL AS match
FROM pg_index, pg_class
WHERE pg_class.oid = pg_index.indexrelid
AND indisunique = \'t\'
AND pg_class.relname = %s';
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($row) || empty($row)) {
// fallback to the given $index_name, without transformation
$constraint_name_mdb2 = $constraint_name;
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
}
if (PEAR::isError($row)) {
return $row;
}
if (empty($row)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
$uniqueIndex = true;
}
$row = array_change_key_case($row, CASE_LOWER);
@ -335,13 +367,26 @@ class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
'match' => $row['match'],
);
if ($uniqueIndex) {
$db->loadModule('Manager', null, true);
$columns = $db->manager->listTableFields($table_name);
$index_column_numbers = explode(' ', $row['indkey']);
$colpos = 1;
foreach ($index_column_numbers as $number) {
$definition['fields'][$columns[($number - 1)]] = array(
'position' => $colpos++,
'sorting' => 'ascending',
);
}
return $definition;
}
$query = 'SELECT a.attname
FROM pg_constraint c
LEFT JOIN pg_class t ON c.conrelid = t.oid
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)
WHERE c.conname = %s
AND t.relname = ' . $db->quote($table, 'text');
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
if (PEAR::isError($fields)) {
return $fields;
@ -361,7 +406,6 @@ class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey)
WHERE c.conname = %s
AND t.relname = ' . $db->quote($definition['references']['table'], 'text');
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$foreign_fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
if (PEAR::isError($foreign_fields)) {
return $foreign_fields;

@ -43,7 +43,7 @@
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php,v 1.79 2008/03/05 11:08:53 quipo Exp $
// $Id: sqlite.php 292715 2009-12-28 14:06:34Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
@ -57,6 +57,25 @@ require_once 'MDB2/Driver/Reverse/Common.php';
*/
class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
{
/**
* Remove SQL comments from the field definition
*
* @access private
*/
function _removeComments($sql) {
$lines = explode("\n", $sql);
foreach ($lines as $k => $line) {
$pieces = explode('--', $line);
if (count($pieces) > 1 && (substr_count($pieces[0], '\'') % 2) == 0) {
$lines[$k] = substr($line, 0, strpos($line, '--'));
}
}
return implode("\n", $lines);
}
/**
*
*/
function _getTableColumns($sql)
{
$db =& $this->getDBInstance();
@ -68,14 +87,15 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
$column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
// replace the decimal length-places-separator with a colon
$column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def);
$column_sql = split(',', $column_def);
$column_def = $this->_removeComments($column_def);
$column_sql = explode(',', $column_def);
$columns = array();
$count = count($column_sql);
if ($count == 0) {
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unexpected empty table column definition list', __FUNCTION__);
}
$regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( UNSIGNED)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?$/i';
$regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
$regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i';
for ($i=0, $j=0; $i<$count; ++$i) {
if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {
@ -93,14 +113,14 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
if (isset($matches[6]) && strlen($matches[6])) {
$columns[$j]['decimal'] = $matches[6];
}
if (isset($matches[7]) && strlen($matches[7])) {
if (isset($matches[8]) && strlen($matches[8])) {
$columns[$j]['unsigned'] = true;
}
if (isset($matches[8]) && strlen($matches[8])) {
if (isset($matches[9]) && strlen($matches[9])) {
$columns[$j]['autoincrement'] = true;
}
if (isset($matches[10]) && strlen($matches[10])) {
$default = $matches[10];
if (isset($matches[12]) && strlen($matches[12])) {
$default = $matches[12];
if (strlen($default) && $default[0]=="'") {
$default = str_replace("''", "'", substr($default, 1, strlen($default)-2));
}
@ -109,8 +129,12 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
}
$columns[$j]['default'] = $default;
}
if (isset($matches[11]) && strlen($matches[11])) {
$columns[$j]['notnull'] = ($matches[11] === ' NOT NULL');
if (isset($matches[7]) && strlen($matches[7])) {
$columns[$j]['notnull'] = ($matches[7] === ' NOT NULL');
} else if (isset($matches[9]) && strlen($matches[9])) {
$columns[$j]['notnull'] = ($matches[9] === ' NOT NULL');
} else if (isset($matches[13]) && strlen($matches[13])) {
$columns[$j]['notnull'] = ($matches[13] === ' NOT NULL');
}
++$j;
}
@ -177,7 +201,7 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
$default = false;
if (array_key_exists('default', $column)) {
$default = $column['default'];
if (is_null($default) && $notnull) {
if ((null === $default) && $notnull) {
$default = '';
}
}
@ -190,13 +214,13 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (!is_null($length)) {
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_null($fixed)) {
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
@ -276,7 +300,7 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
$start_pos = strpos($sql, '(');
$end_pos = strrpos($sql, ')');
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
$column_names = split(',', $column_names);
$column_names = explode(',', $column_names);
if (preg_match("/^create unique/", $sql)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
@ -384,7 +408,7 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) {
$definition['primary'] = true;
$definition['fields'] = array();
$column_names = split(',', $tmp[1]);
$column_names = explode(',', $tmp[1]);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
@ -396,7 +420,7 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) {
$definition['primary'] = true;
$definition['fields'] = array();
$column_names = split(',', $tmp[1]);
$column_names = explode(',', $tmp[1]);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
@ -426,14 +450,14 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
$definition['onupdate'] = 'NO ACTION';
$definition['ondelete'] = 'NO ACTION';
$definition['references']['table'] = $tmp[2];
$column_names = split(',', $tmp[1]);
$column_names = explode(',', $tmp[1]);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
$referenced_cols = split(',', $tmp[3]);
$referenced_cols = explode(',', $tmp[3]);
$colpos = 1;
foreach ($referenced_cols as $column_name) {
$definition['references']['fields'][trim($column_name)] = array(
@ -463,7 +487,7 @@ class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
$start_pos = strpos($sql, '(');
$end_pos = strrpos($sql, ')');
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
$column_names = split(',', $column_names);
$column_names = explode(',', $column_names);
if (!preg_match("/^create unique/", $sql)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,

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

@ -43,7 +43,7 @@
// | Author: Frank M. Kromann <frank@kromann.info> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.174 2008/03/08 14:18:39 quipo Exp $
// $Id: mssql.php 292715 2009-12-28 14:06:34Z quipo $
//
// {{{ Class MDB2_Driver_mssql
/**
@ -113,7 +113,7 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
*/
function errorInfo($error = null, $connection = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->connection;
}
@ -126,7 +126,7 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
}
}
$native_msg = @mssql_get_last_message();
if (is_null($error)) {
if (null === $error) {
static $ecode_map;
if (empty($ecode_map)) {
$ecode_map = array(
@ -202,28 +202,50 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
return $text;
}
// }}}
// {{{ escape()
/**
* Quotes a string so it can be safely used in a query. It will quote
* the text so it can safely be used within a query.
*
* @param string $text the input string to quote
* @param bool $escape_wildcards flag
*
* @return string quoted string
* @access public
*/
function escape($text, $escape_wildcards = false)
{
$text = parent::escape($text, $escape_wildcards);
// http://pear.php.net/bugs/bug.php?id=16118
// http://support.microsoft.com/kb/164291
return preg_replace("/\\\\(\r\n|\r|\n)/", '\\\\$1', $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
* @param string $savepoint 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 (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) {
}
if ($this->in_transaction) {
return MDB2_OK; //nothing to do
}
if (!$this->destructor_registered && $this->opened_persistent) {
@ -247,9 +269,9 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
* 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
* @param string $savepoint name of a savepoint to release
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function commit($savepoint = null)
@ -259,7 +281,7 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
return MDB2_OK;
}
@ -280,9 +302,9 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
* 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
* @param string $savepoint name of a savepoint to rollback to
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function rollback($savepoint = null)
@ -292,7 +314,7 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'rollback cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
$query = 'ROLLBACK TRANSACTION '.$savepoint;
return $this->_doQuery($query, true);
}
@ -311,12 +333,20 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
/**
* do the grunt work of the connect
*
* @param string $username
* @param string $password
* @param boolean $persistent
*
* @return connection on success or MDB2 Error Object on failure
* @access protected
*/
function _doConnect($username, $password, $persistent = false)
{
if (!PEAR::loadExtension($this->phptype) && !PEAR::loadExtension('sybase_ct')) {
if ( !PEAR::loadExtension($this->phptype)
&& !PEAR::loadExtension('sybase_ct')
&& !PEAR::loadExtension('odbtp')
&& !function_exists('mssql_connect')
) {
return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
}
@ -330,9 +360,7 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
$params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port'];
}
if (!$persistent) {
if (isset($this->dsn['new_link'])
&& ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)
) {
if ($this->_isNewLinkSet()) {
$params[] = true;
} else {
$params[] = false;
@ -349,18 +377,24 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
@mssql_query('SET ANSI_NULL_DFLT_ON ON', $connection);
/*
/*
if (!empty($this->dsn['charset'])) {
$result = $this->setCharset($this->dsn['charset'], $connection);
if (PEAR::isError($result)) {
return $result;
}
}
*/
*/
if ((bool)ini_get('mssql.datetimeconvert')) {
// his isn't the most elegant way of doing it but it prevents from
// breaking anything thus preserves BC. Bug #11849
if (isset($this->options['datetimeconvert']) && (bool)$this->options['datetimeconvert'] !== false) {
@ini_set('mssql.datetimeconvert', '1');
} else {
@ini_set('mssql.datetimeconvert', '0');
}
}
if (empty($this->dsn['disable_iso_date'])) {
@mssql_query('SET DATEFORMAT ymd', $connection);
@ -482,9 +516,15 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
}
if (!$this->opened_persistent || $force) {
@mssql_close($this->connection);
$ok = @mssql_close($this->connection);
if (!$ok) {
return $this->raiseError(MDB2_ERROR_DISCONNECT_FAILED,
null, null, null, __FUNCTION__);
}
}
} else {
return false;
}
return parent::disconnect($force);
}
@ -551,13 +591,13 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
return $result;
}
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
}
if (is_null($database_name)) {
if (null === $database_name) {
$database_name = $this->database_name;
}
@ -596,7 +636,7 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
*/
function _affectedRows($connection, $result = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -786,13 +826,13 @@ class MDB2_Driver_mssql extends MDB2_Driver_Common
function lastInsertID($table = null, $field = null)
{
$server_info = $this->getServerVersion();
if (is_array($server_info) && !is_null($server_info['major'])
if (is_array($server_info) && (null !== $server_info['major'])
&& $server_info['major'] >= 8
) {
$query = "SELECT IDENT_CURRENT('$table')";
} else {
$query = "SELECT @@IDENTITY";
if (!is_null($table)) {
if (null !== $table) {
$query .= ' FROM '.$this->quoteIdentifier($table, true);
}
}
@ -851,6 +891,7 @@ class MDB2_Result_mssql extends MDB2_Result_Common
*
* @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
*/
@ -860,7 +901,7 @@ class MDB2_Result_mssql extends MDB2_Result_Common
$null = null;
return $null;
}
if (!is_null($rownum)) {
if (null !== $rownum) {
$seek = $this->seek($rownum);
if (PEAR::isError($seek)) {
return $seek;
@ -880,7 +921,7 @@ class MDB2_Result_mssql extends MDB2_Result_Common
$row = @mssql_fetch_row($this->result);
}
if (!$row) {
if ($this->result === false) {
if (false === $this->result) {
$err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
return $err;
@ -911,7 +952,8 @@ class MDB2_Result_mssql extends MDB2_Result_Common
if ($object_class == 'stdClass') {
$row = (object) $row;
} else {
$row = new $object_class($row);
$rowObj = new $object_class($row);
$row = $rowObj;
}
}
++$this->rownum;
@ -960,11 +1002,12 @@ class MDB2_Result_mssql extends MDB2_Result_Common
function numCols()
{
$cols = @mssql_num_fields($this->result);
if (is_null($cols)) {
if ($this->result === false) {
if (null === $cols) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return count($this->types);
}
return $this->db->raiseError(null, null, null,
@ -984,10 +1027,11 @@ class MDB2_Result_mssql extends MDB2_Result_Common
*/
function nextResult()
{
if ($this->result === false) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return false;
}
return @mssql_next_result($this->result);
@ -1006,7 +1050,7 @@ class MDB2_Result_mssql extends MDB2_Result_Common
{
if (is_resource($this->result) && $this->db->connection) {
$free = @mssql_free_result($this->result);
if ($free === false) {
if (false === $free) {
return $this->db->raiseError(null, null, null,
'Could not free result', __FUNCTION__);
}
@ -1036,16 +1080,18 @@ class MDB2_BufferedResult_mssql extends MDB2_Result_mssql
* 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) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return MDB2_OK;
}
return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
@ -1085,18 +1131,22 @@ class MDB2_BufferedResult_mssql extends MDB2_Result_mssql
function numRows()
{
$rows = @mssql_num_rows($this->result);
if (is_null($rows)) {
if ($this->result === false) {
if (null === $rows) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return 0;
}
return $this->db->raiseError(null, null, null,
'Could not get row count', __FUNCTION__);
}
if ($this->limit) {
$rows -= $this->limit -1 + $this->offset;
$rows -= $this->offset;
if ($rows > $this->limit + 1) {
$rows = $this->limit + 1;
}
if ($rows < 0) {
$rows = 0;
}

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.208 2008/03/13 03:31:55 afz Exp $
// $Id: mysql.php 292659 2009-12-26 17:31:01Z quipo $
//
/**
@ -337,7 +337,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
$this->destructor_registered = true;
register_shutdown_function('MDB2_closeOpenTransactions');
}
$query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 1';
$query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 0';
$result =& $this->_doQuery($query, true);
if (PEAR::isError($result)) {
return $result;
@ -390,7 +390,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
return $result;
}
if (!$this->start_transaction) {
$query = 'SET AUTOCOMMIT = 0';
$query = 'SET AUTOCOMMIT = 1';
$result =& $this->_doQuery($query, true);
if (PEAR::isError($result)) {
return $result;
@ -436,7 +436,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
return $result;
}
if (!$this->start_transaction) {
$query = 'SET AUTOCOMMIT = 0';
$query = 'SET AUTOCOMMIT = 1';
$result =& $this->_doQuery($query, true);
if (PEAR::isError($result)) {
return $result;
@ -501,21 +501,19 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
}
$params = array();
if ($this->dsn['protocol'] && $this->dsn['protocol'] == 'unix') {
$params[0] = ':' . $this->dsn['socket'];
} else {
$params[0] = $this->dsn['hostspec'] ? $this->dsn['hostspec']
: 'localhost';
if ($this->dsn['port']) {
$params[0].= ':' . $this->dsn['port'];
$unix = ($this->dsn['protocol'] && $this->dsn['protocol'] == 'unix');
if (empty($this->dsn['hostspec'])) {
$this->dsn['hostspec'] = $unix ? '' : 'localhost';
}
if ($this->dsn['hostspec']) {
$params[0] = $this->dsn['hostspec'] . ($this->dsn['port'] ? ':' . $this->dsn['port'] : '');
} else {
$params[0] = ':' . $this->dsn['socket'];
}
$params[] = $username ? $username : null;
$params[] = $password ? $password : null;
if (!$persistent) {
if (isset($this->dsn['new_link'])
&& ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)
) {
if ($this->_isNewLinkSet()) {
$params[] = true;
} else {
$params[] = false;
@ -625,9 +623,18 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
$collation = array_pop($charset);
$charset = array_pop($charset);
}
$client_info = mysql_get_client_info();
if (function_exists('mysql_set_charset') && version_compare($client_info, '5.0.6')) {
if (!$result = mysql_set_charset($charset, $connection)) {
$err =& $this->raiseError(null, null, null,
'Could not set client character set', __FUNCTION__);
return $err;
}
return $result;
}
$query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'";
if (!is_null($collation)) {
$query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'";
$query .= " COLLATE '".mysql_real_escape_string($collation, $connection)."'";
}
return $this->_doQuery($query, true, $connection);
}
@ -687,9 +694,15 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
}
if (!$this->opened_persistent || $force) {
@mysql_close($this->connection);
$ok = @mysql_close($this->connection);
if (!$ok) {
return $this->raiseError(MDB2_ERROR_DISCONNECT_FAILED,
null, null, null, __FUNCTION__);
}
}
} else {
return false;
}
return parent::disconnect($force);
}
@ -780,7 +793,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
$function = $this->options['result_buffering']
? 'mysql_query' : 'mysql_unbuffered_query';
$result = @$function($query, $connection);
if (!$result) {
if (!$result && 0 !== mysql_errno($connection)) {
$err =& $this->raiseError(null, null, null,
'Could not execute statement', __FUNCTION__);
return $err;
@ -1021,6 +1034,12 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
*/
function &prepare($query, $types = null, $result_types = null, $lobs = array())
{
// connect to get server capabilities (http://pear.php.net/bugs/16147)
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
if ($this->options['emulate_prepared']
|| $this->supported['prepared_statements'] !== true
) {
@ -1099,10 +1118,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
$position = $p_position;
}
}
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
static $prep_statement_counter = 1;
$statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand()));
$statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']);
@ -1124,8 +1140,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
/**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
* key field values, the old row is deleted before the new row is inserted.
*
* The REPLACE type of query does not make part of the SQL standards. Since
* practically only MySQL implements it natively, this type of query is
@ -1183,6 +1198,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
*
* Default: 0
*
* @see http://dev.mysql.com/doc/refman/5.0/en/replace.html
* @return mixed MDB2_OK on success, a MDB2 error on failure
*/
function replace($table, $fields)
@ -1393,7 +1409,8 @@ class MDB2_Result_mysql extends MDB2_Result_Common
if ($object_class == 'stdClass') {
$row = (object) $row;
} else {
$row = new $object_class($row);
$rowObj = new $object_class($row);
$row = $rowObj;
}
}
++$this->rownum;
@ -1555,6 +1572,8 @@ class MDB2_BufferedResult_mysql extends MDB2_Result_mysql
}
return $rows;
}
// }}}
}
/**
@ -1573,7 +1592,9 @@ class MDB2_Statement_mysql extends MDB2_Statement_Common
*
* @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
*
* @return mixed MDB2_Result or integer (affected rows) on success,
* a MDB2 error on failure
* @access private
*/
function &_execute($result_class = true, $result_wrap_class = false)
@ -1602,6 +1623,7 @@ class MDB2_Statement_mysql extends MDB2_Statement_Common
return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
}
$close = false;
$value = $this->values[$parameter];
$type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null;
if (is_resource($value) || $type == 'clob' || $type == 'blob' && $this->db->options['lob_allow_url_include']) {

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php,v 1.188 2008/03/13 03:31:55 afz Exp $
// $Id: mysqli.php 292715 2009-12-28 14:06:34Z quipo $
//
/**
@ -189,7 +189,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
$native_code = @mysqli_connect_errno();
$native_msg = @mysqli_connect_error();
}
if (is_null($error)) {
if (null === $error) {
static $ecode_map;
if (empty($ecode_map)) {
$ecode_map = array(
@ -320,7 +320,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
{
$this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
$this->_getServerCapabilities();
if (!is_null($savepoint)) {
if (null !== $savepoint) {
if (!$this->supports('savepoints')) {
return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'savepoints are not supported', __FUNCTION__);
@ -331,10 +331,11 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
}
$query = 'SAVEPOINT '.$savepoint;
return $this->_doQuery($query, true);
} elseif ($this->in_transaction) {
}
if ($this->in_transaction) {
return MDB2_OK; //nothing to do
}
$query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 1';
$query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 0';
$result =& $this->_doQuery($query, true);
if (PEAR::isError($result)) {
return $result;
@ -364,7 +365,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
if (!$this->supports('savepoints')) {
return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'savepoints are not supported', __FUNCTION__);
@ -387,7 +388,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
return $result;
}
if (!$this->start_transaction) {
$query = 'SET AUTOCOMMIT = 0';
$query = 'SET AUTOCOMMIT = 1';
$result =& $this->_doQuery($query, true);
if (PEAR::isError($result)) {
return $result;
@ -418,7 +419,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'rollback cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
if (!$this->supports('savepoints')) {
return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'savepoints are not supported', __FUNCTION__);
@ -433,7 +434,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
return $result;
}
if (!$this->start_transaction) {
$query = 'SET AUTOCOMMIT = 0';
$query = 'SET AUTOCOMMIT = 1';
$result =& $this->_doQuery($query, true);
if (PEAR::isError($result)) {
return $result;
@ -590,7 +591,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
*/
function setCharset($charset, $connection = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -606,7 +607,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
((50000 <= $client_info) && (50006 > $client_info)))
) {
$query = "SET NAMES '".mysqli_real_escape_string($connection, $charset)."'";
if (!is_null($collation)) {
if (null !== $collation) {
$query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'";
}
return $this->_doQuery($query, true, $connection);
@ -673,8 +674,14 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
}
if ($force) {
@mysqli_close($this->connection);
$ok = @mysqli_close($this->connection);
if (!$ok) {
return $this->raiseError(MDB2_ERROR_DISCONNECT_FAILED,
null, null, null, __FUNCTION__);
}
}
} else {
return false;
}
return parent::disconnect($force);
}
@ -742,13 +749,13 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
return $result;
}
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
}
if (is_null($database_name)) {
if (null === $database_name) {
$database_name = $this->database_name;
}
@ -770,7 +777,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
$result = mysqli_query($connection, $query);
}
if (!$result) {
if (!$result && 0 !== mysqli_errno($connection)) {
$err =& $this->raiseError(null, null, null,
'Could not execute statement', __FUNCTION__);
return $err;
@ -807,7 +814,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
*/
function _affectedRows($connection, $result = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -946,7 +953,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
$this->supported['prepared_statements'] = true;
}
// SAVEPOINTS were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB)
// SAVEPOINTs were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB)
if (version_compare($server_version, '4.1.0', '>=')) {
if (version_compare($server_version, '4.1.1', '<')) {
$this->supported['savepoints'] = false;
@ -988,7 +995,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
function _skipUserDefinedVariable($query, $position)
{
$found = strpos(strrev(substr($query, 0, $position)), '@');
if ($found === false) {
if (false === $found) {
return $position;
}
$pos = strlen($query) - strlen(substr($query, $position)) - $found - 1;
@ -1025,6 +1032,12 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
*/
function &prepare($query, $types = null, $result_types = null, $lobs = array())
{
// connect to get server capabilities (http://pear.php.net/bugs/16147)
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
if ($this->options['emulate_prepared']
|| $this->supported['prepared_statements'] !== true
) {
@ -1060,7 +1073,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
} else {
break;
}
if (is_null($placeholder_type)) {
if (null === $placeholder_type) {
$placeholder_type_guess = $query[$p_position];
}
@ -1081,7 +1094,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
}
if ($query[$position] == $placeholder_type_guess) {
if (is_null($placeholder_type)) {
if (null === $placeholder_type) {
$placeholder_type = $query[$p_position];
$question = $colon = $placeholder_type;
}
@ -1103,10 +1116,6 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
$position = $p_position;
}
}
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
if (!$is_manip) {
static $prep_statement_counter = 1;
@ -1140,8 +1149,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
/**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
* key field values, the old row is deleted before the new row is inserted.
*
* The REPLACE type of query does not make part of the SQL standards. Since
* practically only MySQL implements it natively, this type of query is
@ -1199,6 +1207,7 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common
*
* Default: 0
*
* @see http://dev.mysql.com/doc/refman/5.0/en/replace.html
* @return mixed MDB2_OK on success, a MDB2 error on failure
*/
function replace($table, $fields)
@ -1357,7 +1366,7 @@ class MDB2_Result_mysqli extends MDB2_Result_Common
*/
function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
{
if (!is_null($rownum)) {
if (null !== $rownum) {
$seek = $this->seek($rownum);
if (PEAR::isError($seek)) {
return $seek;
@ -1378,7 +1387,7 @@ class MDB2_Result_mysqli extends MDB2_Result_Common
}
if (!$row) {
if ($this->result === false) {
if (false === $this->result) {
$err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
return $err;
@ -1409,7 +1418,8 @@ class MDB2_Result_mysqli extends MDB2_Result_Common
if ($object_class == 'stdClass') {
$row = (object) $row;
} else {
$row = new $object_class($row);
$rowObj = new $object_class($row);
$row = $rowObj;
}
}
++$this->rownum;
@ -1458,11 +1468,12 @@ class MDB2_Result_mysqli extends MDB2_Result_Common
function numCols()
{
$cols = @mysqli_num_fields($this->result);
if (is_null($cols)) {
if ($this->result === false) {
if (null === $cols) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return count($this->types);
}
return $this->db->raiseError(null, null, null,
@ -1510,13 +1521,16 @@ class MDB2_Result_mysqli extends MDB2_Result_Common
*/
function free()
{
do {
if (is_object($this->result) && $this->db->connection) {
$free = @mysqli_free_result($this->result);
if ($free === false) {
if (false === $free) {
return $this->db->raiseError(null, null, null,
'Could not free result', __FUNCTION__);
}
}
} while ($this->result = $this->nextResult());
$this->result = false;
return MDB2_OK;
}
@ -1544,10 +1558,11 @@ class MDB2_BufferedResult_mysqli extends MDB2_Result_mysqli
function seek($rownum = 0)
{
if ($this->rownum != ($rownum - 1) && !@mysqli_data_seek($this->result, $rownum)) {
if ($this->result === false) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return MDB2_OK;
}
return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
@ -1587,11 +1602,12 @@ class MDB2_BufferedResult_mysqli extends MDB2_Result_mysqli
function numRows()
{
$rows = @mysqli_num_rows($this->result);
if (is_null($rows)) {
if ($this->result === false) {
if (null === $rows) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return 0;
}
return $this->db->raiseError(null, null, null,
@ -1646,12 +1662,14 @@ class MDB2_Statement_mysqli extends MDB2_Statement_Common
*
* @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
*
* @return mixed MDB2_Result or integer (affected rows) on success,
* a MDB2 error on failure
* @access private
*/
function &_execute($result_class = true, $result_wrap_class = false)
{
if (is_null($this->statement)) {
if (null === $this->statement) {
$result =& parent::_execute($result_class, $result_wrap_class);
return $result;
}
@ -1731,7 +1749,7 @@ class MDB2_Statement_mysqli extends MDB2_Statement_Common
$query.= ' USING @'.implode(', @', array_values($this->positions));
} else {
$result = @call_user_func_array('mysqli_stmt_bind_param', $parameters);
if ($result === false) {
if (false === $result) {
$err =& $this->db->raiseError(null, null, null,
'Unable to bind parameters', __FUNCTION__);
return $err;
@ -1813,7 +1831,7 @@ class MDB2_Statement_mysqli extends MDB2_Statement_Common
*/
function free()
{
if (is_null($this->positions)) {
if (null === $this->positions) {
return $this->db->raiseError(MDB2_ERROR, null, null,
'Prepared statement has already been freed', __FUNCTION__);
}
@ -1824,7 +1842,7 @@ class MDB2_Statement_mysqli extends MDB2_Statement_Common
$result = $this->db->raiseError(null, null, null,
'Could not free statement', __FUNCTION__);
}
} elseif (!is_null($this->statement)) {
} elseif (null !== $this->statement) {
$connection = $this->db->getConnection();
if (PEAR::isError($connection)) {
return $connection;

@ -43,7 +43,7 @@
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.197 2008/03/08 14:18:39 quipo Exp $
// $Id: pgsql.php 292715 2009-12-28 14:06:34Z quipo $
/**
* MDB2 PostGreSQL driver
@ -95,7 +95,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
$this->options['DBA_username'] = false;
$this->options['DBA_password'] = false;
$this->options['multi_query'] = false;
$this->options['disable_smart_seqname'] = false;
$this->options['disable_smart_seqname'] = true;
$this->options['max_identifiers_length'] = 63;
}
@ -136,6 +136,8 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
=> MDB2_ERROR_NOSUCHTABLE,
'/database .* does not exist/'
=> MDB2_ERROR_NOT_FOUND,
'/constraint .* does not exist/'
=> MDB2_ERROR_NOT_FOUND,
'/index .* does not exist/'
=> MDB2_ERROR_NOT_FOUND,
'/database .* already exists/i'
@ -234,14 +236,15 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
function beginTransaction($savepoint = null)
{
$this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
if (!is_null($savepoint)) {
if (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 = 'SAVEPOINT '.$savepoint;
return $this->_doQuery($query, true);
} elseif ($this->in_transaction) {
}
if ($this->in_transaction) {
return MDB2_OK; //nothing to do
}
if (!$this->destructor_registered && $this->opened_persistent) {
@ -277,7 +280,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
$query = 'RELEASE SAVEPOINT '.$savepoint;
return $this->_doQuery($query, true);
}
@ -311,7 +314,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'rollback cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
$query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
return $this->_doQuery($query, true);
}
@ -423,9 +426,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
$params[0].= ' service=' . $this->dsn['service'];
}
if (!empty($this->dsn['new_link'])
&& ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true))
{
if ($this->_isNewLinkSet()) {
if (version_compare(phpversion(), '4.3.0', '>=')) {
$params[] = PGSQL_CONNECT_FORCE_NEW;
}
@ -452,6 +453,29 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
}
}
// Enable extra compatibility settings on 8.2 and later
if (function_exists('pg_parameter_status')) {
$version = pg_parameter_status($connection, 'server_version');
if ($version == false) {
return $this->raiseError(null, null, null,
'Unable to retrieve server version', __FUNCTION__);
}
$version = explode ('.', $version);
if ( $version['0'] > 8
|| ($version['0'] == 8 && $version['1'] >= 2)
) {
if (!@pg_query($connection, "SET SESSION STANDARD_CONFORMING_STRINGS = OFF")) {
return $this->raiseError(null, null, null,
'Unable to set standard_conforming_strings to off', __FUNCTION__);
}
if (!@pg_query($connection, "SET SESSION ESCAPE_STRING_WARNING = OFF")) {
return $this->raiseError(null, null, null,
'Unable to set escape_string_warning to off', __FUNCTION__);
}
}
}
return $connection;
}
@ -509,7 +533,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
*/
function setCharset($charset, $connection = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -580,9 +604,15 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
}
if (!$this->opened_persistent || $force) {
@pg_close($this->connection);
$ok = @pg_close($this->connection);
if (!$ok) {
return $this->raiseError(MDB2_ERROR_DISCONNECT_FAILED,
null, null, null, __FUNCTION__);
}
}
} else {
return false;
}
return parent::disconnect($force);
}
@ -653,7 +683,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
return $result;
}
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -691,7 +721,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
*/
function _affectedRows($connection, $result = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -879,7 +909,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
} else {
break;
}
if (is_null($placeholder_type)) {
if (null === $placeholder_type) {
$placeholder_type_guess = $query[$p_position];
}
@ -893,7 +923,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
}
if ($query[$position] == $placeholder_type_guess) {
if (is_null($placeholder_type)) {
if (null === $placeholder_type) {
$placeholder_type = $query[$p_position];
$question = $colon = $placeholder_type;
if (!empty($types) && is_array($types)) {
@ -952,7 +982,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
static $prep_statement_counter = 1;
$statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand()));
$statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']);
if ($pgtypes === false) {
if (false === $pgtypes) {
$result = @pg_prepare($connection, $statement_name, $query);
if (!$result) {
$err =& $this->raiseError(null, null, null,
@ -1036,8 +1066,7 @@ class MDB2_Driver_pgsql extends MDB2_Driver_Common
}
}
return sprintf($this->options['seqname_format'],
preg_replace('/[^\w\$.]/i', '_', $sqn));
return parent::getSequenceName($sqn);
}
// }}}
@ -1137,7 +1166,7 @@ class MDB2_Result_pgsql extends MDB2_Result_Common
*/
function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
{
if (!is_null($rownum)) {
if (null !== $rownum) {
$seek = $this->seek($rownum);
if (PEAR::isError($seek)) {
return $seek;
@ -1157,7 +1186,7 @@ class MDB2_Result_pgsql extends MDB2_Result_Common
$row = @pg_fetch_row($this->result);
}
if (!$row) {
if ($this->result === false) {
if (false === $this->result) {
$err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
return $err;
@ -1188,7 +1217,8 @@ class MDB2_Result_pgsql extends MDB2_Result_Common
if ($object_class == 'stdClass') {
$row = (object) $row;
} else {
$row = new $object_class($row);
$rowObj = new $object_class($row);
$row = $rowObj;
}
}
++$this->rownum;
@ -1237,11 +1267,12 @@ class MDB2_Result_pgsql extends MDB2_Result_Common
function numCols()
{
$cols = @pg_num_fields($this->result);
if (is_null($cols)) {
if ($this->result === false) {
if (null === $cols) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return count($this->types);
}
return $this->db->raiseError(null, null, null,
@ -1285,7 +1316,7 @@ class MDB2_Result_pgsql extends MDB2_Result_Common
{
if (is_resource($this->result) && $this->db->connection) {
$free = @pg_free_result($this->result);
if ($free === false) {
if (false === $free) {
return $this->db->raiseError(null, null, null,
'Could not free result', __FUNCTION__);
}
@ -1316,10 +1347,11 @@ class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql
function seek($rownum = 0)
{
if ($this->rownum != ($rownum - 1) && !@pg_result_seek($this->result, $rownum)) {
if ($this->result === false) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return MDB2_OK;
}
return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
@ -1359,11 +1391,12 @@ class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql
function numRows()
{
$rows = @pg_num_rows($this->result);
if (is_null($rows)) {
if ($this->result === false) {
if (null === $rows) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return 0;
}
return $this->db->raiseError(null, null, null,
@ -1389,12 +1422,14 @@ class MDB2_Statement_pgsql extends MDB2_Statement_Common
*
* @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
*
* @return mixed MDB2_Result or integer (affected rows) on success,
* a MDB2 error on failure
* @access private
*/
function &_execute($result_class = true, $result_wrap_class = false)
{
if (is_null($this->statement)) {
if (null === $this->statement) {
$result =& parent::_execute($result_class, $result_wrap_class);
return $result;
}
@ -1490,13 +1525,13 @@ class MDB2_Statement_pgsql extends MDB2_Statement_Common
*/
function free()
{
if (is_null($this->positions)) {
if (null === $this->positions) {
return $this->db->raiseError(MDB2_ERROR, null, null,
'Prepared statement has already been freed', __FUNCTION__);
}
$result = MDB2_OK;
if (!is_null($this->statement)) {
if (null !== $this->statement) {
$connection = $this->db->getConnection();
if (PEAR::isError($connection)) {
return $connection;

@ -43,7 +43,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php,v 1.158 2008/03/08 14:18:39 quipo Exp $
// $Id: sqlite.php 292715 2009-12-28 14:06:34Z quipo $
//
/**
@ -131,7 +131,7 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
// this hack to work around it, per bug #9599.
$native_msg = preg_replace('/^sqlite[a-z_]+\(\)[^:]*: /', '', $native_msg);
if (is_null($error)) {
if (null === $error) {
static $error_regexps;
if (empty($error_regexps)) {
$error_regexps = array(
@ -194,10 +194,11 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
function beginTransaction($savepoint = null)
{
$this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
if (!is_null($savepoint)) {
if (null !== $savepoint) {
return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'savepoints are not supported', __FUNCTION__);
} elseif ($this->in_transaction) {
}
if ($this->in_transaction) {
return MDB2_OK; //nothing to do
}
if (!$this->destructor_registered && $this->opened_persistent) {
@ -234,7 +235,7 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'savepoints are not supported', __FUNCTION__);
}
@ -269,7 +270,7 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'rollback cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
if (null !== $savepoint) {
return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'savepoints are not supported', __FUNCTION__);
}
@ -364,7 +365,11 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
}
if (!empty($this->database_name)) {
if (empty($this->database_name)) {
return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
'unable to establish a connection', __FUNCTION__);
}
if ($database_file !== ':memory:') {
if (!file_exists($database_file)) {
if (!touch($database_file)) {
@ -412,21 +417,19 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
'unable to establish a connection', __FUNCTION__);
}
/*
if (!empty($this->dsn['charset'])) {
$result = $this->setCharset($this->dsn['charset'], $connection);
if (PEAR::isError($result)) {
return $result;
}
if ($this->fix_assoc_fields_names ||
$this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES)
{
@sqlite_query("PRAGMA short_column_names = 1", $connection);
$this->fix_assoc_fields_names = true;
}
*/
$this->connection = $connection;
$this->connected_dsn = $this->dsn;
$this->connected_database_name = $database_file;
$this->opened_persistent = $this->getoption('persistent');
$this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
}
return MDB2_OK;
}
@ -479,36 +482,12 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
if (!$this->opened_persistent || $force) {
@sqlite_close($this->connection);
}
} else {
return false;
}
return parent::disconnect($force);
}
// }}}
// {{{ getConnection()
/**
* Returns a native connection
*
* @return mixed a valid MDB2 connection object,
* or a MDB2 error object on error
* @access public
*/
function getConnection()
{
$connection = parent::getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
$fix_assoc_fields_names = $this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES;
if ($fix_assoc_fields_names !== $this->fix_assoc_fields_names) {
@sqlite_query("PRAGMA short_column_names = $fix_assoc_fields_names;", $connection);
$this->fix_assoc_fields_names = $fix_assoc_fields_names;
}
return $connection;
}
// }}}
// {{{ _doQuery()
@ -536,7 +515,7 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
return $result;
}
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -582,7 +561,7 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
*/
function _affectedRows($connection, $result = null)
{
if (is_null($connection)) {
if (null === $connection) {
$connection = $this->getConnection();
if (PEAR::isError($connection)) {
return $connection;
@ -673,8 +652,7 @@ class MDB2_Driver_sqlite extends MDB2_Driver_Common
/**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
* key field values, the old row is deleted before the new row is inserted.
*
* The REPLACE type of query does not make part of the SQL standards. Since
* practically only SQLite implements it natively, this type of query is
@ -898,7 +876,7 @@ class MDB2_Result_sqlite extends MDB2_Result_Common
*/
function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
{
if (!is_null($rownum)) {
if (null !== $rownum) {
$seek = $this->seek($rownum);
if (PEAR::isError($seek)) {
return $seek;
@ -918,7 +896,7 @@ class MDB2_Result_sqlite extends MDB2_Result_Common
$row = @sqlite_fetch_array($this->result, SQLITE_NUM);
}
if (!$row) {
if ($this->result === false) {
if (false === $this->result) {
$err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
return $err;
@ -949,7 +927,8 @@ class MDB2_Result_sqlite extends MDB2_Result_Common
if ($object_class == 'stdClass') {
$row = (object) $row;
} else {
$row = new $object_class($row);
$rowObj = new $object_class($row);
$row = $rowObj;
}
}
++$this->rownum;
@ -998,11 +977,12 @@ class MDB2_Result_sqlite extends MDB2_Result_Common
function numCols()
{
$cols = @sqlite_num_fields($this->result);
if (is_null($cols)) {
if ($this->result === false) {
if (null === $cols) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return count($this->types);
}
return $this->db->raiseError(null, null, null,
@ -1033,10 +1013,11 @@ class MDB2_BufferedResult_sqlite extends MDB2_Result_sqlite
function seek($rownum = 0)
{
if (!@sqlite_seek($this->result, $rownum)) {
if ($this->result === false) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return MDB2_OK;
}
return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
@ -1076,11 +1057,12 @@ class MDB2_BufferedResult_sqlite extends MDB2_Result_sqlite
function numRows()
{
$rows = @sqlite_num_rows($this->result);
if (is_null($rows)) {
if ($this->result === false) {
if (null === $rows) {
if (false === $this->result) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
}
if (null === $this->result) {
return 0;
}
return $this->db->raiseError(null, null, null,
@ -1101,5 +1083,4 @@ class MDB2_Statement_sqlite extends MDB2_Statement_Common
{
}
?>

File diff suppressed because it is too large Load Diff

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Extended.php,v 1.60 2007/11/28 19:49:34 quipo Exp $
// $Id: Extended.php 292715 2009-12-28 14:06:34Z quipo $
/**
* @package MDB2
@ -214,7 +214,7 @@ class MDB2_Extended extends MDB2_Module_Common
}
}
if ($where !== false && !is_null($where)) {
if ((false !== $where) && (null !== $where)) {
if (is_array($where)) {
$where = implode(' AND ', $where);
}

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Iterator.php,v 1.22 2006/05/06 14:03:41 lsmith Exp $
// $Id: Iterator.php 212543 2006-05-06 14:03:41Z lsmith $
/**
* PHP5 Iterator

@ -42,7 +42,7 @@
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: LOB.php,v 1.34 2006/10/25 11:52:21 lsmith Exp $
// $Id: LOB.php 222350 2006-10-25 11:52:21Z lsmith $
/**
* @package MDB2

Loading…
Cancel
Save