parent
cd1ecef75f
commit
ede1c64edd
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,183 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: Date.php,v 1.10 2006/03/01 12:15:32 lsmith Exp $ |
||||
// |
||||
|
||||
/** |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
|
||||
/** |
||||
* Several methods to convert the MDB2 native timestamp format (ISO based) |
||||
* to and from data structures that are convenient to worth with in side of php. |
||||
* For more complex date arithmetic please take a look at the Date package in PEAR |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Date |
||||
{ |
||||
// {{{ mdbNow() |
||||
|
||||
/** |
||||
* return the current datetime |
||||
* |
||||
* @return string current datetime in the MDB2 format |
||||
* @access public |
||||
*/ |
||||
function mdbNow() |
||||
{ |
||||
return date('Y-m-d H:i:s'); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ mdbToday() |
||||
|
||||
/** |
||||
* return the current date |
||||
* |
||||
* @return string current date in the MDB2 format |
||||
* @access public |
||||
*/ |
||||
function mdbToday() |
||||
{ |
||||
return date('Y-m-d'); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ mdbTime() |
||||
|
||||
/** |
||||
* return the current time |
||||
* |
||||
* @return string current time in the MDB2 format |
||||
* @access public |
||||
*/ |
||||
function mdbTime() |
||||
{ |
||||
return date('H:i:s'); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ date2Mdbstamp() |
||||
|
||||
/** |
||||
* convert a date into a MDB2 timestamp |
||||
* |
||||
* @param int hour of the date |
||||
* @param int minute of the date |
||||
* @param int second of the date |
||||
* @param int month of the date |
||||
* @param int day of the date |
||||
* @param int year of the date |
||||
* |
||||
* @return string a valid MDB2 timestamp |
||||
* @access public |
||||
*/ |
||||
function date2Mdbstamp($hour = null, $minute = null, $second = null, |
||||
$month = null, $day = null, $year = null) |
||||
{ |
||||
return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1)); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ unix2Mdbstamp() |
||||
|
||||
/** |
||||
* convert a unix timestamp into a MDB2 timestamp |
||||
* |
||||
* @param int a valid unix timestamp |
||||
* |
||||
* @return string a valid MDB2 timestamp |
||||
* @access public |
||||
*/ |
||||
function unix2Mdbstamp($unix_timestamp) |
||||
{ |
||||
return date('Y-m-d H:i:s', $unix_timestamp); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ mdbstamp2Unix() |
||||
|
||||
/** |
||||
* convert a MDB2 timestamp into a unix timestamp |
||||
* |
||||
* @param int a valid MDB2 timestamp |
||||
* @return string unix timestamp with the time stored in the MDB2 format |
||||
* |
||||
* @access public |
||||
*/ |
||||
function mdbstamp2Unix($mdb_timestamp) |
||||
{ |
||||
$arr = MDB2_Date::mdbstamp2Date($mdb_timestamp); |
||||
|
||||
return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ mdbstamp2Date() |
||||
|
||||
/** |
||||
* convert a MDB2 timestamp into an array containing all |
||||
* values necessary to pass to php's date() function |
||||
* |
||||
* @param int a valid MDB2 timestamp |
||||
* |
||||
* @return array with the time split |
||||
* @access public |
||||
*/ |
||||
function mdbstamp2Date($mdb_timestamp) |
||||
{ |
||||
list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) = |
||||
sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u"); |
||||
return $arr; |
||||
} |
||||
// }}} |
||||
} |
||||
|
||||
?> |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,553 @@ |
||||
<?php |
||||
// vim: set et ts=4 sw=4 fdm=marker: |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: mysql.php,v 1.65 2008/02/22 19:23:49 quipo Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Datatype/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 MySQL driver |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common |
||||
{ |
||||
// {{{ _getCharsetFieldDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET |
||||
* of a field declaration to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $charset name of the charset |
||||
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET |
||||
* of a field declaration. |
||||
*/ |
||||
function _getCharsetFieldDeclaration($charset) |
||||
{ |
||||
return 'CHARACTER SET '.$charset; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getCollationFieldDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to set the COLLATION |
||||
* of a field declaration to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $collation name of the collation |
||||
* @return string DBMS specific SQL code portion needed to set the COLLATION |
||||
* of a field declaration. |
||||
*/ |
||||
function _getCollationFieldDeclaration($collation) |
||||
{ |
||||
return 'COLLATE '.$collation; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTypeDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an text type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param array $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. Currently, the types |
||||
* of supported field properties are as follows: |
||||
* |
||||
* length |
||||
* Integer value that determines the maximum length of the text |
||||
* field. If this argument is missing the field should be |
||||
* declared to have the longest length allowed by the DBMS. |
||||
* |
||||
* default |
||||
* Text value to be used as default for this field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is constrained |
||||
* to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access public |
||||
*/ |
||||
function getTypeDeclaration($field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
switch ($field['type']) { |
||||
case 'text': |
||||
if (empty($field['length']) && array_key_exists('default', $field)) { |
||||
$field['length'] = $db->varchar_max_length; |
||||
} |
||||
$length = !empty($field['length']) ? $field['length'] : false; |
||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false; |
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)') |
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT'); |
||||
case 'clob': |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 255) { |
||||
return 'TINYTEXT'; |
||||
} elseif ($length <= 65532) { |
||||
return 'TEXT'; |
||||
} elseif ($length <= 16777215) { |
||||
return 'MEDIUMTEXT'; |
||||
} |
||||
} |
||||
return 'LONGTEXT'; |
||||
case 'blob': |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 255) { |
||||
return 'TINYBLOB'; |
||||
} elseif ($length <= 65532) { |
||||
return 'BLOB'; |
||||
} elseif ($length <= 16777215) { |
||||
return 'MEDIUMBLOB'; |
||||
} |
||||
} |
||||
return 'LONGBLOB'; |
||||
case 'integer': |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 1) { |
||||
return 'TINYINT'; |
||||
} elseif ($length == 2) { |
||||
return 'SMALLINT'; |
||||
} elseif ($length == 3) { |
||||
return 'MEDIUMINT'; |
||||
} elseif ($length == 4) { |
||||
return 'INT'; |
||||
} elseif ($length > 4) { |
||||
return 'BIGINT'; |
||||
} |
||||
} |
||||
return 'INT'; |
||||
case 'boolean': |
||||
return 'TINYINT(1)'; |
||||
case 'date': |
||||
return 'DATE'; |
||||
case 'time': |
||||
return 'TIME'; |
||||
case 'timestamp': |
||||
return 'DATETIME'; |
||||
case 'float': |
||||
return 'DOUBLE'; |
||||
case 'decimal': |
||||
$length = !empty($field['length']) ? $field['length'] : 18; |
||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; |
||||
return 'DECIMAL('.$length.','.$scale.')'; |
||||
} |
||||
return ''; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getIntegerDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an integer type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $name name the field to be declared. |
||||
* @param string $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. |
||||
* Currently, the types of supported field |
||||
* properties are as follows: |
||||
* |
||||
* unsigned |
||||
* Boolean flag that indicates whether the field |
||||
* should be declared as unsigned integer if |
||||
* possible. |
||||
* |
||||
* default |
||||
* Integer value to be used as default for this |
||||
* field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is |
||||
* constrained to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access protected |
||||
*/ |
||||
function _getIntegerDeclaration($name, $field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$default = $autoinc = ''; |
||||
if (!empty($field['autoincrement'])) { |
||||
$autoinc = ' AUTO_INCREMENT PRIMARY KEY'; |
||||
} elseif (array_key_exists('default', $field)) { |
||||
if ($field['default'] === '') { |
||||
$field['default'] = empty($field['notnull']) ? null : 0; |
||||
} |
||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer'); |
||||
} |
||||
|
||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; |
||||
$name = $db->quoteIdentifier($name, true); |
||||
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getFloatDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an float type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $name name the field to be declared. |
||||
* @param string $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. |
||||
* Currently, the types of supported field |
||||
* properties are as follows: |
||||
* |
||||
* unsigned |
||||
* Boolean flag that indicates whether the field |
||||
* should be declared as unsigned float if |
||||
* possible. |
||||
* |
||||
* default |
||||
* float value to be used as default for this |
||||
* field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is |
||||
* constrained to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access protected |
||||
*/ |
||||
function _getFloatDeclaration($name, $field) |
||||
{ |
||||
// Since AUTO_INCREMENT can be used for integer or floating-point types, |
||||
// reuse the INTEGER declaration |
||||
// @see http://bugs.mysql.com/bug.php?id=31032 |
||||
return $this->_getIntegerDeclaration($name, $field); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getDecimalDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an decimal type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $name name the field to be declared. |
||||
* @param string $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. |
||||
* Currently, the types of supported field |
||||
* properties are as follows: |
||||
* |
||||
* unsigned |
||||
* Boolean flag that indicates whether the field |
||||
* should be declared as unsigned integer if |
||||
* possible. |
||||
* |
||||
* default |
||||
* Decimal value to be used as default for this |
||||
* field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is |
||||
* constrained to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access protected |
||||
*/ |
||||
function _getDecimalDeclaration($name, $field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$default = ''; |
||||
if (array_key_exists('default', $field)) { |
||||
if ($field['default'] === '') { |
||||
$field['default'] = empty($field['notnull']) ? null : 0; |
||||
} |
||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer'); |
||||
} elseif (empty($field['notnull'])) { |
||||
$default = ' DEFAULT NULL'; |
||||
} |
||||
|
||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; |
||||
$name = $db->quoteIdentifier($name, true); |
||||
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ matchPattern() |
||||
|
||||
/** |
||||
* build a pattern matching string |
||||
* |
||||
* @access public |
||||
* |
||||
* @param array $pattern even keys are strings, odd are patterns (% and _) |
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) |
||||
* @param string $field optional field name that is being matched against |
||||
* (might be required when emulating ILIKE) |
||||
* |
||||
* @return string SQL pattern |
||||
*/ |
||||
function matchPattern($pattern, $operator = null, $field = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$match = ''; |
||||
if (!is_null($operator)) { |
||||
$field = is_null($field) ? '' : $field.' '; |
||||
$operator = strtoupper($operator); |
||||
switch ($operator) { |
||||
// case insensitive |
||||
case 'ILIKE': |
||||
$match = $field.'LIKE '; |
||||
break; |
||||
// case sensitive |
||||
case 'LIKE': |
||||
$match = $field.'LIKE BINARY '; |
||||
break; |
||||
default: |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'not a supported operator type:'. $operator, __FUNCTION__); |
||||
} |
||||
} |
||||
$match.= "'"; |
||||
foreach ($pattern as $key => $value) { |
||||
if ($key % 2) { |
||||
$match.= $value; |
||||
} else { |
||||
$match.= $db->escapePattern($db->escape($value)); |
||||
} |
||||
} |
||||
$match.= "'"; |
||||
$match.= $this->patternEscapeString(); |
||||
return $match; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _mapNativeDatatype() |
||||
|
||||
/** |
||||
* Maps a native array description of a field to a MDB2 datatype and length |
||||
* |
||||
* @param array $field native field description |
||||
* @return array containing the various possible types, length, sign, fixed |
||||
* @access public |
||||
*/ |
||||
function _mapNativeDatatype($field) |
||||
{ |
||||
$db_type = strtolower($field['type']); |
||||
$db_type = strtok($db_type, '(), '); |
||||
if ($db_type == 'national') { |
||||
$db_type = strtok('(), '); |
||||
} |
||||
if (!empty($field['length'])) { |
||||
$length = strtok($field['length'], ', '); |
||||
$decimal = strtok(', '); |
||||
} else { |
||||
$length = strtok('(), '); |
||||
$decimal = strtok('(), '); |
||||
} |
||||
$type = array(); |
||||
$unsigned = $fixed = null; |
||||
switch ($db_type) { |
||||
case 'tinyint': |
||||
$type[] = 'integer'; |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 1; |
||||
break; |
||||
case 'smallint': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 2; |
||||
break; |
||||
case 'mediumint': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 3; |
||||
break; |
||||
case 'int': |
||||
case 'integer': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 4; |
||||
break; |
||||
case 'bigint': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 8; |
||||
break; |
||||
case 'tinytext': |
||||
case 'mediumtext': |
||||
case 'longtext': |
||||
case 'text': |
||||
case 'varchar': |
||||
$fixed = false; |
||||
case 'string': |
||||
case 'char': |
||||
$type[] = 'text'; |
||||
if ($length == '1') { |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
} elseif (strstr($db_type, 'text')) { |
||||
$type[] = 'clob'; |
||||
if ($decimal == 'binary') { |
||||
$type[] = 'blob'; |
||||
} |
||||
$type = array_reverse($type); |
||||
} |
||||
if ($fixed !== false) { |
||||
$fixed = true; |
||||
} |
||||
break; |
||||
case 'enum': |
||||
$type[] = 'text'; |
||||
preg_match_all('/\'.+\'/U', $field['type'], $matches); |
||||
$length = 0; |
||||
$fixed = false; |
||||
if (is_array($matches)) { |
||||
foreach ($matches[0] as $value) { |
||||
$length = max($length, strlen($value)-2); |
||||
} |
||||
if ($length == '1' && count($matches[0]) == 2) { |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
} |
||||
} |
||||
$type[] = 'integer'; |
||||
case 'set': |
||||
$fixed = false; |
||||
$type[] = 'text'; |
||||
$type[] = 'integer'; |
||||
break; |
||||
case 'date': |
||||
$type[] = 'date'; |
||||
$length = null; |
||||
break; |
||||
case 'datetime': |
||||
case 'timestamp': |
||||
$type[] = 'timestamp'; |
||||
$length = null; |
||||
break; |
||||
case 'time': |
||||
$type[] = 'time'; |
||||
$length = null; |
||||
break; |
||||
case 'float': |
||||
case 'double': |
||||
case 'real': |
||||
$type[] = 'float'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
break; |
||||
case 'unknown': |
||||
case 'decimal': |
||||
case 'numeric': |
||||
$type[] = 'decimal'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
if ($decimal !== false) { |
||||
$length = $length.','.$decimal; |
||||
} |
||||
break; |
||||
case 'tinyblob': |
||||
case 'mediumblob': |
||||
case 'longblob': |
||||
case 'blob': |
||||
$type[] = 'blob'; |
||||
$length = null; |
||||
break; |
||||
case 'binary': |
||||
case 'varbinary': |
||||
$type[] = 'blob'; |
||||
break; |
||||
case 'year': |
||||
$type[] = 'integer'; |
||||
$type[] = 'date'; |
||||
$length = null; |
||||
break; |
||||
default: |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'unknown database attribute type: '.$db_type, __FUNCTION__); |
||||
} |
||||
|
||||
if ((int)$length <= 0) { |
||||
$length = null; |
||||
} |
||||
|
||||
return array($type, $length, $unsigned, $fixed); |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
|
||||
?> |
||||
@ -0,0 +1,554 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Paul Cooper <pgc@ucecom.com> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: pgsql.php,v 1.93 2008/08/28 20:32:57 afz Exp $ |
||||
|
||||
require_once 'MDB2/Driver/Datatype/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 PostGreSQL driver |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Paul Cooper <pgc@ucecom.com> |
||||
*/ |
||||
class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common |
||||
{ |
||||
// {{{ _baseConvertResult() |
||||
|
||||
/** |
||||
* General type conversion method |
||||
* |
||||
* @param mixed $value refernce to a value to be converted |
||||
* @param string $type specifies which type to convert to |
||||
* @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text |
||||
* @return object a MDB2 error on failure |
||||
* @access protected |
||||
*/ |
||||
function _baseConvertResult($value, $type, $rtrim = true) |
||||
{ |
||||
if (is_null($value)) { |
||||
return null; |
||||
} |
||||
switch ($type) { |
||||
case 'boolean': |
||||
return $value == 't'; |
||||
case 'float': |
||||
return doubleval($value); |
||||
case 'date': |
||||
return $value; |
||||
case 'time': |
||||
return substr($value, 0, strlen('HH:MM:SS')); |
||||
case 'timestamp': |
||||
return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS')); |
||||
case 'blob': |
||||
$value = pg_unescape_bytea($value); |
||||
return parent::_baseConvertResult($value, $type, $rtrim); |
||||
} |
||||
return parent::_baseConvertResult($value, $type, $rtrim); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTypeDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an text type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param array $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. Currently, the types |
||||
* of supported field properties are as follows: |
||||
* |
||||
* length |
||||
* Integer value that determines the maximum length of the text |
||||
* field. If this argument is missing the field should be |
||||
* declared to have the longest length allowed by the DBMS. |
||||
* |
||||
* default |
||||
* Text value to be used as default for this field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is constrained |
||||
* to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access public |
||||
*/ |
||||
function getTypeDeclaration($field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
switch ($field['type']) { |
||||
case 'text': |
||||
$length = !empty($field['length']) ? $field['length'] : false; |
||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false; |
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') |
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT'); |
||||
case 'clob': |
||||
return 'TEXT'; |
||||
case 'blob': |
||||
return 'BYTEA'; |
||||
case 'integer': |
||||
if (!empty($field['autoincrement'])) { |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length > 4) { |
||||
return 'BIGSERIAL PRIMARY KEY'; |
||||
} |
||||
} |
||||
return 'SERIAL PRIMARY KEY'; |
||||
} |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 2) { |
||||
return 'SMALLINT'; |
||||
} elseif ($length == 3 || $length == 4) { |
||||
return 'INT'; |
||||
} elseif ($length > 4) { |
||||
return 'BIGINT'; |
||||
} |
||||
} |
||||
return 'INT'; |
||||
case 'boolean': |
||||
return 'BOOLEAN'; |
||||
case 'date': |
||||
return 'DATE'; |
||||
case 'time': |
||||
return 'TIME without time zone'; |
||||
case 'timestamp': |
||||
return 'TIMESTAMP without time zone'; |
||||
case 'float': |
||||
return 'FLOAT8'; |
||||
case 'decimal': |
||||
$length = !empty($field['length']) ? $field['length'] : 18; |
||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; |
||||
return 'NUMERIC('.$length.','.$scale.')'; |
||||
} |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getIntegerDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an integer type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $name name the field to be declared. |
||||
* @param array $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. Currently, the types |
||||
* of supported field properties are as follows: |
||||
* |
||||
* unsigned |
||||
* Boolean flag that indicates whether the field should be |
||||
* declared as unsigned integer if possible. |
||||
* |
||||
* default |
||||
* Integer value to be used as default for this field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is constrained |
||||
* to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access protected |
||||
*/ |
||||
function _getIntegerDeclaration($name, $field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
if (!empty($field['unsigned'])) { |
||||
$db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; |
||||
} |
||||
if (!empty($field['autoincrement'])) { |
||||
$name = $db->quoteIdentifier($name, true); |
||||
return $name.' '.$this->getTypeDeclaration($field); |
||||
} |
||||
$default = ''; |
||||
if (array_key_exists('default', $field)) { |
||||
if ($field['default'] === '') { |
||||
$field['default'] = empty($field['notnull']) ? null : 0; |
||||
} |
||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer'); |
||||
} |
||||
|
||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
||||
$name = $db->quoteIdentifier($name, true); |
||||
return $name.' '.$this->getTypeDeclaration($field).$default.$notnull; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _quoteCLOB() |
||||
|
||||
/** |
||||
* Convert a text value into a DBMS specific format that is suitable to |
||||
* compose query statements. |
||||
* |
||||
* @param string $value text string value that is intended to be converted. |
||||
* @param bool $quote determines if the value should be quoted and escaped |
||||
* @param bool $escape_wildcards if to escape escape wildcards |
||||
* @return string text string that represents the given argument value in |
||||
* a DBMS specific format. |
||||
* @access protected |
||||
*/ |
||||
function _quoteCLOB($value, $quote, $escape_wildcards) |
||||
{ |
||||
return $this->_quoteText($value, $quote, $escape_wildcards); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _quoteBLOB() |
||||
|
||||
/** |
||||
* Convert a text value into a DBMS specific format that is suitable to |
||||
* compose query statements. |
||||
* |
||||
* @param string $value text string value that is intended to be converted. |
||||
* @param bool $quote determines if the value should be quoted and escaped |
||||
* @param bool $escape_wildcards if to escape escape wildcards |
||||
* @return string text string that represents the given argument value in |
||||
* a DBMS specific format. |
||||
* @access protected |
||||
*/ |
||||
function _quoteBLOB($value, $quote, $escape_wildcards) |
||||
{ |
||||
if (!$quote) { |
||||
return $value; |
||||
} |
||||
if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) { |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
$connection = $db->getConnection(); |
||||
if (PEAR::isError($connection)) { |
||||
return $connection; |
||||
} |
||||
$value = @pg_escape_bytea($connection, $value); |
||||
} else { |
||||
$value = @pg_escape_bytea($value); |
||||
} |
||||
return "'".$value."'"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _quoteBoolean() |
||||
|
||||
/** |
||||
* Convert a text value into a DBMS specific format that is suitable to |
||||
* compose query statements. |
||||
* |
||||
* @param string $value text string value that is intended to be converted. |
||||
* @param bool $quote determines if the value should be quoted and escaped |
||||
* @param bool $escape_wildcards if to escape escape wildcards |
||||
* @return string text string that represents the given argument value in |
||||
* a DBMS specific format. |
||||
* @access protected |
||||
*/ |
||||
function _quoteBoolean($value, $quote, $escape_wildcards) |
||||
{ |
||||
$value = $value ? 't' : 'f'; |
||||
if (!$quote) { |
||||
return $value; |
||||
} |
||||
return "'".$value."'"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ matchPattern() |
||||
|
||||
/** |
||||
* build a pattern matching string |
||||
* |
||||
* @access public |
||||
* |
||||
* @param array $pattern even keys are strings, odd are patterns (% and _) |
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) |
||||
* @param string $field optional field name that is being matched against |
||||
* (might be required when emulating ILIKE) |
||||
* |
||||
* @return string SQL pattern |
||||
*/ |
||||
function matchPattern($pattern, $operator = null, $field = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$match = ''; |
||||
if (!is_null($operator)) { |
||||
$field = is_null($field) ? '' : $field.' '; |
||||
$operator = strtoupper($operator); |
||||
switch ($operator) { |
||||
// case insensitive |
||||
case 'ILIKE': |
||||
$match = $field.'ILIKE '; |
||||
break; |
||||
// case sensitive |
||||
case 'LIKE': |
||||
$match = $field.'LIKE '; |
||||
break; |
||||
default: |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'not a supported operator type:'. $operator, __FUNCTION__); |
||||
} |
||||
} |
||||
$match.= "'"; |
||||
foreach ($pattern as $key => $value) { |
||||
if ($key % 2) { |
||||
$match.= $value; |
||||
} else { |
||||
$match.= $db->escapePattern($db->escape($value)); |
||||
} |
||||
} |
||||
$match.= "'"; |
||||
$match.= $this->patternEscapeString(); |
||||
return $match; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ patternEscapeString() |
||||
|
||||
/** |
||||
* build string to define escape pattern string |
||||
* |
||||
* @access public |
||||
* |
||||
* |
||||
* @return string define escape pattern |
||||
*/ |
||||
function patternEscapeString() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _mapNativeDatatype() |
||||
|
||||
/** |
||||
* Maps a native array description of a field to a MDB2 datatype and length |
||||
* |
||||
* @param array $field native field description |
||||
* @return array containing the various possible types, length, sign, fixed |
||||
* @access public |
||||
*/ |
||||
function _mapNativeDatatype($field) |
||||
{ |
||||
$db_type = strtolower($field['type']); |
||||
$length = $field['length']; |
||||
$type = array(); |
||||
$unsigned = $fixed = null; |
||||
switch ($db_type) { |
||||
case 'smallint': |
||||
case 'int2': |
||||
$type[] = 'integer'; |
||||
$unsigned = false; |
||||
$length = 2; |
||||
if ($length == '2') { |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
} |
||||
break; |
||||
case 'int': |
||||
case 'int4': |
||||
case 'integer': |
||||
case 'serial': |
||||
case 'serial4': |
||||
$type[] = 'integer'; |
||||
$unsigned = false; |
||||
$length = 4; |
||||
break; |
||||
case 'bigint': |
||||
case 'int8': |
||||
case 'bigserial': |
||||
case 'serial8': |
||||
$type[] = 'integer'; |
||||
$unsigned = false; |
||||
$length = 8; |
||||
break; |
||||
case 'bool': |
||||
case 'boolean': |
||||
$type[] = 'boolean'; |
||||
$length = null; |
||||
break; |
||||
case 'text': |
||||
case 'varchar': |
||||
$fixed = false; |
||||
case 'unknown': |
||||
case 'char': |
||||
case 'bpchar': |
||||
$type[] = 'text'; |
||||
if ($length == '1') { |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
} elseif (strstr($db_type, 'text')) { |
||||
$type[] = 'clob'; |
||||
$type = array_reverse($type); |
||||
} |
||||
if ($fixed !== false) { |
||||
$fixed = true; |
||||
} |
||||
break; |
||||
case 'date': |
||||
$type[] = 'date'; |
||||
$length = null; |
||||
break; |
||||
case 'datetime': |
||||
case 'timestamp': |
||||
case 'timestamptz': |
||||
$type[] = 'timestamp'; |
||||
$length = null; |
||||
break; |
||||
case 'time': |
||||
$type[] = 'time'; |
||||
$length = null; |
||||
break; |
||||
case 'float': |
||||
case 'float4': |
||||
case 'float8': |
||||
case 'double': |
||||
case 'real': |
||||
$type[] = 'float'; |
||||
break; |
||||
case 'decimal': |
||||
case 'money': |
||||
case 'numeric': |
||||
$type[] = 'decimal'; |
||||
if (isset($field['scale'])) { |
||||
$length = $length.','.$field['scale']; |
||||
} |
||||
break; |
||||
case 'tinyblob': |
||||
case 'mediumblob': |
||||
case 'longblob': |
||||
case 'blob': |
||||
case 'bytea': |
||||
$type[] = 'blob'; |
||||
$length = null; |
||||
break; |
||||
case 'oid': |
||||
$type[] = 'blob'; |
||||
$type[] = 'clob'; |
||||
$length = null; |
||||
break; |
||||
case 'year': |
||||
$type[] = 'integer'; |
||||
$type[] = 'date'; |
||||
$length = null; |
||||
break; |
||||
default: |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'unknown database attribute type: '.$db_type, __FUNCTION__); |
||||
} |
||||
|
||||
if ((int)$length <= 0) { |
||||
$length = null; |
||||
} |
||||
|
||||
return array($type, $length, $unsigned, $fixed); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ mapPrepareDatatype() |
||||
|
||||
/** |
||||
* Maps an mdb2 datatype to native prepare type |
||||
* |
||||
* @param string $type |
||||
* @return string |
||||
* @access public |
||||
*/ |
||||
function mapPrepareDatatype($type) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
if (!empty($db->options['datatype_map'][$type])) { |
||||
$type = $db->options['datatype_map'][$type]; |
||||
if (!empty($db->options['datatype_map_callback'][$type])) { |
||||
$parameter = array('type' => $type); |
||||
return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter)); |
||||
} |
||||
} |
||||
|
||||
switch ($type) { |
||||
case 'integer': |
||||
return 'int'; |
||||
case 'boolean': |
||||
return 'bool'; |
||||
case 'decimal': |
||||
case 'float': |
||||
return 'numeric'; |
||||
case 'clob': |
||||
return 'text'; |
||||
case 'blob': |
||||
return 'bytea'; |
||||
default: |
||||
break; |
||||
} |
||||
return $type; |
||||
} |
||||
// }}} |
||||
} |
||||
?> |
||||
@ -0,0 +1,409 @@ |
||||
<?php |
||||
// vim: set et ts=4 sw=4 fdm=marker: |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Datatype/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 SQLite driver |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common |
||||
{ |
||||
// {{{ _getCollationFieldDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to set the COLLATION |
||||
* of a field declaration to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $collation name of the collation |
||||
* |
||||
* @return string DBMS specific SQL code portion needed to set the COLLATION |
||||
* of a field declaration. |
||||
*/ |
||||
function _getCollationFieldDeclaration($collation) |
||||
{ |
||||
return 'COLLATE '.$collation; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTypeDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an text type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param array $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. Currently, the types |
||||
* of supported field properties are as follows: |
||||
* |
||||
* length |
||||
* Integer value that determines the maximum length of the text |
||||
* field. If this argument is missing the field should be |
||||
* declared to have the longest length allowed by the DBMS. |
||||
* |
||||
* default |
||||
* Text value to be used as default for this field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is constrained |
||||
* to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access public |
||||
*/ |
||||
function getTypeDeclaration($field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
switch ($field['type']) { |
||||
case 'text': |
||||
$length = !empty($field['length']) |
||||
? $field['length'] : false; |
||||
$fixed = !empty($field['fixed']) ? $field['fixed'] : false; |
||||
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') |
||||
: ($length ? 'VARCHAR('.$length.')' : 'TEXT'); |
||||
case 'clob': |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 255) { |
||||
return 'TINYTEXT'; |
||||
} elseif ($length <= 65532) { |
||||
return 'TEXT'; |
||||
} elseif ($length <= 16777215) { |
||||
return 'MEDIUMTEXT'; |
||||
} |
||||
} |
||||
return 'LONGTEXT'; |
||||
case 'blob': |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 255) { |
||||
return 'TINYBLOB'; |
||||
} elseif ($length <= 65532) { |
||||
return 'BLOB'; |
||||
} elseif ($length <= 16777215) { |
||||
return 'MEDIUMBLOB'; |
||||
} |
||||
} |
||||
return 'LONGBLOB'; |
||||
case 'integer': |
||||
if (!empty($field['length'])) { |
||||
$length = $field['length']; |
||||
if ($length <= 2) { |
||||
return 'SMALLINT'; |
||||
} elseif ($length == 3 || $length == 4) { |
||||
return 'INTEGER'; |
||||
} elseif ($length > 4) { |
||||
return 'BIGINT'; |
||||
} |
||||
} |
||||
return 'INTEGER'; |
||||
case 'boolean': |
||||
return 'BOOLEAN'; |
||||
case 'date': |
||||
return 'DATE'; |
||||
case 'time': |
||||
return 'TIME'; |
||||
case 'timestamp': |
||||
return 'DATETIME'; |
||||
case 'float': |
||||
return 'DOUBLE'.($db->options['fixed_float'] ? '('. |
||||
($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : ''); |
||||
case 'decimal': |
||||
$length = !empty($field['length']) ? $field['length'] : 18; |
||||
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places']; |
||||
return 'DECIMAL('.$length.','.$scale.')'; |
||||
} |
||||
return ''; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getIntegerDeclaration() |
||||
|
||||
/** |
||||
* Obtain DBMS specific SQL code portion needed to declare an integer type |
||||
* field to be used in statements like CREATE TABLE. |
||||
* |
||||
* @param string $name name the field to be declared. |
||||
* @param string $field associative array with the name of the properties |
||||
* of the field being declared as array indexes. |
||||
* Currently, the types of supported field |
||||
* properties are as follows: |
||||
* |
||||
* unsigned |
||||
* Boolean flag that indicates whether the field |
||||
* should be declared as unsigned integer if |
||||
* possible. |
||||
* |
||||
* default |
||||
* Integer value to be used as default for this |
||||
* field. |
||||
* |
||||
* notnull |
||||
* Boolean flag that indicates whether this field is |
||||
* constrained to not be set to null. |
||||
* @return string DBMS specific SQL code portion that should be used to |
||||
* declare the specified field. |
||||
* @access protected |
||||
*/ |
||||
function _getIntegerDeclaration($name, $field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$default = $autoinc = ''; |
||||
if (!empty($field['autoincrement'])) { |
||||
$autoinc = ' PRIMARY KEY'; |
||||
} elseif (array_key_exists('default', $field)) { |
||||
if ($field['default'] === '') { |
||||
$field['default'] = empty($field['notnull']) ? null : 0; |
||||
} |
||||
$default = ' DEFAULT '.$this->quote($field['default'], 'integer'); |
||||
} |
||||
|
||||
$notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
||||
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; |
||||
$name = $db->quoteIdentifier($name, true); |
||||
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ matchPattern() |
||||
|
||||
/** |
||||
* build a pattern matching string |
||||
* |
||||
* @access public |
||||
* |
||||
* @param array $pattern even keys are strings, odd are patterns (% and _) |
||||
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future) |
||||
* @param string $field optional field name that is being matched against |
||||
* (might be required when emulating ILIKE) |
||||
* |
||||
* @return string SQL pattern |
||||
*/ |
||||
function matchPattern($pattern, $operator = null, $field = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$match = ''; |
||||
if (!is_null($operator)) { |
||||
$field = is_null($field) ? '' : $field.' '; |
||||
$operator = strtoupper($operator); |
||||
switch ($operator) { |
||||
// case insensitive |
||||
case 'ILIKE': |
||||
$match = $field.'LIKE '; |
||||
break; |
||||
// case sensitive |
||||
case 'LIKE': |
||||
$match = $field.'LIKE '; |
||||
break; |
||||
default: |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'not a supported operator type:'. $operator, __FUNCTION__); |
||||
} |
||||
} |
||||
$match.= "'"; |
||||
foreach ($pattern as $key => $value) { |
||||
if ($key % 2) { |
||||
$match.= $value; |
||||
} else { |
||||
$match.= $db->escapePattern($db->escape($value)); |
||||
} |
||||
} |
||||
$match.= "'"; |
||||
$match.= $this->patternEscapeString(); |
||||
return $match; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _mapNativeDatatype() |
||||
|
||||
/** |
||||
* Maps a native array description of a field to a MDB2 datatype and length |
||||
* |
||||
* @param array $field native field description |
||||
* @return array containing the various possible types, length, sign, fixed |
||||
* @access public |
||||
*/ |
||||
function _mapNativeDatatype($field) |
||||
{ |
||||
$db_type = strtolower($field['type']); |
||||
$length = !empty($field['length']) ? $field['length'] : null; |
||||
$unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null; |
||||
$fixed = null; |
||||
$type = array(); |
||||
switch ($db_type) { |
||||
case 'boolean': |
||||
$type[] = 'boolean'; |
||||
break; |
||||
case 'tinyint': |
||||
$type[] = 'integer'; |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 1; |
||||
break; |
||||
case 'smallint': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 2; |
||||
break; |
||||
case 'mediumint': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 3; |
||||
break; |
||||
case 'int': |
||||
case 'integer': |
||||
case 'serial': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 4; |
||||
break; |
||||
case 'bigint': |
||||
case 'bigserial': |
||||
$type[] = 'integer'; |
||||
$unsigned = preg_match('/ unsigned/i', $field['type']); |
||||
$length = 8; |
||||
break; |
||||
case 'clob': |
||||
$type[] = 'clob'; |
||||
$fixed = false; |
||||
break; |
||||
case 'tinytext': |
||||
case 'mediumtext': |
||||
case 'longtext': |
||||
case 'text': |
||||
case 'varchar': |
||||
case 'varchar2': |
||||
$fixed = false; |
||||
case 'char': |
||||
$type[] = 'text'; |
||||
if ($length == '1') { |
||||
$type[] = 'boolean'; |
||||
if (preg_match('/^(is|has)/', $field['name'])) { |
||||
$type = array_reverse($type); |
||||
} |
||||
} elseif (strstr($db_type, 'text')) { |
||||
$type[] = 'clob'; |
||||
$type = array_reverse($type); |
||||
} |
||||
if ($fixed !== false) { |
||||
$fixed = true; |
||||
} |
||||
break; |
||||
case 'date': |
||||
$type[] = 'date'; |
||||
$length = null; |
||||
break; |
||||
case 'datetime': |
||||
case 'timestamp': |
||||
$type[] = 'timestamp'; |
||||
$length = null; |
||||
break; |
||||
case 'time': |
||||
$type[] = 'time'; |
||||
$length = null; |
||||
break; |
||||
case 'float': |
||||
case 'double': |
||||
case 'real': |
||||
$type[] = 'float'; |
||||
break; |
||||
case 'decimal': |
||||
case 'numeric': |
||||
$type[] = 'decimal'; |
||||
$length = $length.','.$field['decimal']; |
||||
break; |
||||
case 'tinyblob': |
||||
case 'mediumblob': |
||||
case 'longblob': |
||||
case 'blob': |
||||
$type[] = 'blob'; |
||||
$length = null; |
||||
break; |
||||
case 'year': |
||||
$type[] = 'integer'; |
||||
$type[] = 'date'; |
||||
$length = null; |
||||
break; |
||||
default: |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'unknown database attribute type: '.$db_type, __FUNCTION__); |
||||
} |
||||
|
||||
if ((int)$length <= 0) { |
||||
$length = null; |
||||
} |
||||
|
||||
return array($type, $length, $unsigned, $fixed); |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
|
||||
?> |
||||
@ -0,0 +1,293 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: Common.php,v 1.21 2008/02/17 18:51:39 quipo Exp $ |
||||
// |
||||
|
||||
/** |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
|
||||
/** |
||||
* Base class for the function modules that is extended by each MDB2 driver |
||||
* |
||||
* To load this module in the MDB2 object: |
||||
* $mdb->loadModule('Function'); |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Function_Common extends MDB2_Module_Common |
||||
{ |
||||
// {{{ executeStoredProc() |
||||
|
||||
/** |
||||
* Execute a stored procedure and return any results |
||||
* |
||||
* @param string $name string that identifies the function to execute |
||||
* @param mixed $params array that contains the paramaters to pass the stored proc |
||||
* @param mixed $types array that contains the types of the columns in |
||||
* the result set |
||||
* @param mixed $result_class string which specifies which result class to use |
||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in |
||||
* |
||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
return $error; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ functionTable() |
||||
|
||||
/** |
||||
* return string for internal table used when calling only a function |
||||
* |
||||
* @return string for internal table used when calling only a function |
||||
* @access public |
||||
*/ |
||||
function functionTable() |
||||
{ |
||||
return ''; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ now() |
||||
|
||||
/** |
||||
* Return string to call a variable with the current timestamp inside an SQL statement |
||||
* There are three special variables for current date and time: |
||||
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type) |
||||
* - CURRENT_DATE (date, DATE type) |
||||
* - CURRENT_TIME (time, TIME type) |
||||
* |
||||
* @param string $type 'timestamp' | 'time' | 'date' |
||||
* |
||||
* @return string to call a variable with the current timestamp |
||||
* @access public |
||||
*/ |
||||
function now($type = 'timestamp') |
||||
{ |
||||
switch ($type) { |
||||
case 'time': |
||||
return 'CURRENT_TIME'; |
||||
case 'date': |
||||
return 'CURRENT_DATE'; |
||||
case 'timestamp': |
||||
default: |
||||
return 'CURRENT_TIMESTAMP'; |
||||
} |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ unixtimestamp() |
||||
|
||||
/** |
||||
* return string to call a function to get the unix timestamp from a iso timestamp |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return string to call a variable with the timestamp |
||||
* @access public |
||||
*/ |
||||
function unixtimestamp($expression) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
return $error; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ substring() |
||||
|
||||
/** |
||||
* return string to call a function to get a substring inside an SQL statement |
||||
* |
||||
* @return string to call a function to get a substring |
||||
* @access public |
||||
*/ |
||||
function substring($value, $position = 1, $length = null) |
||||
{ |
||||
if (!is_null($length)) { |
||||
return "SUBSTRING($value FROM $position FOR $length)"; |
||||
} |
||||
return "SUBSTRING($value FROM $position)"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ replace() |
||||
|
||||
/** |
||||
* return string to call a function to get replace inside an SQL statement. |
||||
* |
||||
* @return string to call a function to get a replace |
||||
* @access public |
||||
*/ |
||||
function replace($str, $from_str, $to_str) |
||||
{ |
||||
return "REPLACE($str, $from_str , $to_str)"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ concat() |
||||
|
||||
/** |
||||
* Returns string to concatenate two or more string parameters |
||||
* |
||||
* @param string $value1 |
||||
* @param string $value2 |
||||
* @param string $values... |
||||
* |
||||
* @return string to concatenate two strings |
||||
* @access public |
||||
*/ |
||||
function concat($value1, $value2) |
||||
{ |
||||
$args = func_get_args(); |
||||
return "(".implode(' || ', $args).")"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ random() |
||||
|
||||
/** |
||||
* return string to call a function to get random value inside an SQL statement |
||||
* |
||||
* @return return string to generate float between 0 and 1 |
||||
* @access public |
||||
*/ |
||||
function random() |
||||
{ |
||||
return 'RAND()'; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ lower() |
||||
|
||||
/** |
||||
* return string to call a function to lower the case of an expression |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return return string to lower case of an expression |
||||
* @access public |
||||
*/ |
||||
function lower($expression) |
||||
{ |
||||
return "LOWER($expression)"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ upper() |
||||
|
||||
/** |
||||
* return string to call a function to upper the case of an expression |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return return string to upper case of an expression |
||||
* @access public |
||||
*/ |
||||
function upper($expression) |
||||
{ |
||||
return "UPPER($expression)"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ length() |
||||
|
||||
/** |
||||
* return string to call a function to get the length of a string expression |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return return string to get the string expression length |
||||
* @access public |
||||
*/ |
||||
function length($expression) |
||||
{ |
||||
return "LENGTH($expression)"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ guid() |
||||
|
||||
/** |
||||
* Returns global unique identifier |
||||
* |
||||
* @return string to get global unique identifier |
||||
* @access public |
||||
*/ |
||||
function guid() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
return $error; |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
?> |
||||
@ -0,0 +1,136 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: mysql.php,v 1.12 2008/02/17 18:54:08 quipo Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Function/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 MySQL driver for the function modules |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common |
||||
{ |
||||
// }}} |
||||
// {{{ executeStoredProc() |
||||
|
||||
/** |
||||
* Execute a stored procedure and return any results |
||||
* |
||||
* @param string $name string that identifies the function to execute |
||||
* @param mixed $params array that contains the paramaters to pass the stored proc |
||||
* @param mixed $types array that contains the types of the columns in |
||||
* the result set |
||||
* @param mixed $result_class string which specifies which result class to use |
||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in |
||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'CALL '.$name; |
||||
$query .= $params ? '('.implode(', ', $params).')' : '()'; |
||||
return $db->query($query, $types, $result_class, $result_wrap_class); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ unixtimestamp() |
||||
|
||||
/** |
||||
* return string to call a function to get the unix timestamp from a iso timestamp |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return string to call a variable with the timestamp |
||||
* @access public |
||||
*/ |
||||
function unixtimestamp($expression) |
||||
{ |
||||
return 'UNIX_TIMESTAMP('. $expression.')'; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ concat() |
||||
|
||||
/** |
||||
* Returns string to concatenate two or more string parameters |
||||
* |
||||
* @param string $value1 |
||||
* @param string $value2 |
||||
* @param string $values... |
||||
* @return string to concatenate two strings |
||||
* @access public |
||||
**/ |
||||
function concat($value1, $value2) |
||||
{ |
||||
$args = func_get_args(); |
||||
return "CONCAT(".implode(', ', $args).")"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ guid() |
||||
|
||||
/** |
||||
* Returns global unique identifier |
||||
* |
||||
* @return string to get global unique identifier |
||||
* @access public |
||||
*/ |
||||
function guid() |
||||
{ |
||||
return 'UUID()'; |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
?> |
||||
@ -0,0 +1,115 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Paul Cooper <pgc@ucecom.com> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: pgsql.php,v 1.11 2008/11/09 19:46:50 quipo Exp $ |
||||
|
||||
require_once 'MDB2/Driver/Function/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 MySQL driver for the function modules |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common |
||||
{ |
||||
// {{{ executeStoredProc() |
||||
|
||||
/** |
||||
* Execute a stored procedure and return any results |
||||
* |
||||
* @param string $name string that identifies the function to execute |
||||
* @param mixed $params array that contains the paramaters to pass the stored proc |
||||
* @param mixed $types array that contains the types of the columns in |
||||
* the result set |
||||
* @param mixed $result_class string which specifies which result class to use |
||||
* @param mixed $result_wrap_class string which specifies which class to wrap results in |
||||
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'SELECT * FROM '.$name; |
||||
$query .= $params ? '('.implode(', ', $params).')' : '()'; |
||||
return $db->query($query, $types, $result_class, $result_wrap_class); |
||||
} |
||||
// }}} |
||||
// {{{ unixtimestamp() |
||||
|
||||
/** |
||||
* return string to call a function to get the unix timestamp from a iso timestamp |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return string to call a variable with the timestamp |
||||
* @access public |
||||
*/ |
||||
function unixtimestamp($expression) |
||||
{ |
||||
return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', CAST ((' . $expression . ') AS TIMESTAMP)))'; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ random() |
||||
|
||||
/** |
||||
* return string to call a function to get random value inside an SQL statement |
||||
* |
||||
* @return return string to generate float between 0 and 1 |
||||
* @access public |
||||
*/ |
||||
function random() |
||||
{ |
||||
return 'RANDOM()'; |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
?> |
||||
@ -0,0 +1,162 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: sqlite.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Function/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 SQLite driver for the function modules |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common |
||||
{ |
||||
// {{{ constructor |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
function __construct($db_index) |
||||
{ |
||||
parent::__construct($db_index); |
||||
// create all sorts of UDFs |
||||
} |
||||
|
||||
// {{{ now() |
||||
|
||||
/** |
||||
* Return string to call a variable with the current timestamp inside an SQL statement |
||||
* There are three special variables for current date and time. |
||||
* |
||||
* @return string to call a variable with the current timestamp |
||||
* @access public |
||||
*/ |
||||
function now($type = 'timestamp') |
||||
{ |
||||
switch ($type) { |
||||
case 'time': |
||||
return 'time(\'now\')'; |
||||
case 'date': |
||||
return 'date(\'now\')'; |
||||
case 'timestamp': |
||||
default: |
||||
return 'datetime(\'now\')'; |
||||
} |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ unixtimestamp() |
||||
|
||||
/** |
||||
* return string to call a function to get the unix timestamp from a iso timestamp |
||||
* |
||||
* @param string $expression |
||||
* |
||||
* @return string to call a variable with the timestamp |
||||
* @access public |
||||
*/ |
||||
function unixtimestamp($expression) |
||||
{ |
||||
return 'strftime("%s",'. $expression.', "utc")'; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ substring() |
||||
|
||||
/** |
||||
* return string to call a function to get a substring inside an SQL statement |
||||
* |
||||
* @return string to call a function to get a substring |
||||
* @access public |
||||
*/ |
||||
function substring($value, $position = 1, $length = null) |
||||
{ |
||||
if (!is_null($length)) { |
||||
return "substr($value,$position,$length)"; |
||||
} |
||||
return "substr($value,$position,length($value))"; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ random() |
||||
|
||||
/** |
||||
* return string to call a function to get random value inside an SQL statement |
||||
* |
||||
* @return return string to generate float between 0 and 1 |
||||
* @access public |
||||
*/ |
||||
function random() |
||||
{ |
||||
return '((RANDOM()+2147483648)/4294967296)'; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ replace() |
||||
|
||||
/** |
||||
* return string to call a function to get a replacement inside an SQL statement. |
||||
* |
||||
* @return string to call a function to get a replace |
||||
* @access public |
||||
*/ |
||||
function replace($str, $from_str, $to_str) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
return $error; |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
?> |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,948 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Paul Cooper <pgc@ucecom.com> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: pgsql.php,v 1.87 2008/11/29 14:09:59 afz Exp $ |
||||
|
||||
require_once 'MDB2/Driver/Manager/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 MySQL driver for the management modules |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Paul Cooper <pgc@ucecom.com> |
||||
*/ |
||||
class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common |
||||
{ |
||||
// {{{ createDatabase() |
||||
|
||||
/** |
||||
* create a new database |
||||
* |
||||
* @param string $name name of the database that should be created |
||||
* @param array $options array with charset info |
||||
* |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function createDatabase($name, $options = array()) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$name = $db->quoteIdentifier($name, true); |
||||
$query = 'CREATE DATABASE ' . $name; |
||||
if (!empty($options['charset'])) { |
||||
$query .= ' WITH ENCODING ' . $db->quote($options['charset'], 'text'); |
||||
} |
||||
return $db->standaloneQuery($query, null, true); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ alterDatabase() |
||||
|
||||
/** |
||||
* alter an existing database |
||||
* |
||||
* @param string $name name of the database that is intended to be changed |
||||
* @param array $options array with name, owner info |
||||
* |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function alterDatabase($name, $options = array()) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); |
||||
if (!empty($options['name'])) { |
||||
$query .= ' RENAME TO ' . $options['name']; |
||||
} |
||||
if (!empty($options['owner'])) { |
||||
$query .= ' OWNER TO ' . $options['owner']; |
||||
} |
||||
return $db->standaloneQuery($query, null, true); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ dropDatabase() |
||||
|
||||
/** |
||||
* drop an existing database |
||||
* |
||||
* @param string $name name of the database that should be dropped |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function dropDatabase($name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$name = $db->quoteIdentifier($name, true); |
||||
$query = "DROP DATABASE $name"; |
||||
return $db->standaloneQuery($query, null, true); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getAdvancedFKOptions() |
||||
|
||||
/** |
||||
* Return the FOREIGN KEY query section dealing with non-standard options |
||||
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ... |
||||
* |
||||
* @param array $definition |
||||
* @return string |
||||
* @access protected |
||||
*/ |
||||
function _getAdvancedFKOptions($definition) |
||||
{ |
||||
$query = ''; |
||||
if (!empty($definition['match'])) { |
||||
$query .= ' MATCH '.$definition['match']; |
||||
} |
||||
if (!empty($definition['onupdate'])) { |
||||
$query .= ' ON UPDATE '.$definition['onupdate']; |
||||
} |
||||
if (!empty($definition['ondelete'])) { |
||||
$query .= ' ON DELETE '.$definition['ondelete']; |
||||
} |
||||
if (!empty($definition['deferrable'])) { |
||||
$query .= ' DEFERRABLE'; |
||||
} else { |
||||
$query .= ' NOT DEFERRABLE'; |
||||
} |
||||
if (!empty($definition['initiallydeferred'])) { |
||||
$query .= ' INITIALLY DEFERRED'; |
||||
} else { |
||||
$query .= ' INITIALLY IMMEDIATE'; |
||||
} |
||||
return $query; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ truncateTable() |
||||
|
||||
/** |
||||
* Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, |
||||
* it falls back to a DELETE FROM TABLE query) |
||||
* |
||||
* @param string $name name of the table that should be truncated |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function truncateTable($name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$name = $db->quoteIdentifier($name, true); |
||||
return $db->exec("TRUNCATE TABLE $name"); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ vacuum() |
||||
|
||||
/** |
||||
* Optimize (vacuum) all the tables in the db (or only the specified table) |
||||
* and optionally run ANALYZE. |
||||
* |
||||
* @param string $table table name (all the tables if empty) |
||||
* @param array $options an array with driver-specific options: |
||||
* - timeout [int] (in seconds) [mssql-only] |
||||
* - analyze [boolean] [pgsql and mysql] |
||||
* - full [boolean] [pgsql-only] |
||||
* - freeze [boolean] [pgsql-only] |
||||
* |
||||
* @return mixed MDB2_OK success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function vacuum($table = null, $options = array()) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
$query = 'VACUUM'; |
||||
|
||||
if (!empty($options['full'])) { |
||||
$query .= ' FULL'; |
||||
} |
||||
if (!empty($options['freeze'])) { |
||||
$query .= ' FREEZE'; |
||||
} |
||||
if (!empty($options['analyze'])) { |
||||
$query .= ' ANALYZE'; |
||||
} |
||||
|
||||
if (!empty($table)) { |
||||
$query .= ' '.$db->quoteIdentifier($table, true); |
||||
} |
||||
return $db->exec($query); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ alterTable() |
||||
|
||||
/** |
||||
* alter an existing table |
||||
* |
||||
* @param string $name name of the table that is intended to be changed. |
||||
* @param array $changes associative array that contains the details of each type |
||||
* of change that is intended to be performed. The types of |
||||
* changes that are currently supported are defined as follows: |
||||
* |
||||
* name |
||||
* |
||||
* New name for the table. |
||||
* |
||||
* add |
||||
* |
||||
* Associative array with the names of fields to be added as |
||||
* indexes of the array. The value of each entry of the array |
||||
* should be set to another associative array with the properties |
||||
* of the fields to be added. The properties of the fields should |
||||
* be the same as defined by the MDB2 parser. |
||||
* |
||||
* |
||||
* remove |
||||
* |
||||
* Associative array with the names of fields to be removed as indexes |
||||
* of the array. Currently the values assigned to each entry are ignored. |
||||
* An empty array should be used for future compatibility. |
||||
* |
||||
* rename |
||||
* |
||||
* Associative array with the names of fields to be renamed as indexes |
||||
* of the array. The value of each entry of the array should be set to |
||||
* another associative array with the entry named name with the new |
||||
* field name and the entry named Declaration that is expected to contain |
||||
* the portion of the field declaration already in DBMS specific SQL code |
||||
* as it is used in the CREATE TABLE statement. |
||||
* |
||||
* change |
||||
* |
||||
* Associative array with the names of the fields to be changed as indexes |
||||
* of the array. Keep in mind that if it is intended to change either the |
||||
* name of a field and any other properties, the change array entries |
||||
* should have the new names of the fields as array indexes. |
||||
* |
||||
* The value of each entry of the array should be set to another associative |
||||
* array with the properties of the fields to that are meant to be changed as |
||||
* array entries. These entries should be assigned to the new values of the |
||||
* respective properties. The properties of the fields should be the same |
||||
* as defined by the MDB2 parser. |
||||
* |
||||
* Example |
||||
* array( |
||||
* 'name' => 'userlist', |
||||
* 'add' => array( |
||||
* 'quota' => array( |
||||
* 'type' => 'integer', |
||||
* 'unsigned' => 1 |
||||
* ) |
||||
* ), |
||||
* 'remove' => array( |
||||
* 'file_limit' => array(), |
||||
* 'time_limit' => array() |
||||
* ), |
||||
* 'change' => array( |
||||
* 'name' => array( |
||||
* 'length' => '20', |
||||
* 'definition' => array( |
||||
* 'type' => 'text', |
||||
* 'length' => 20, |
||||
* ), |
||||
* ) |
||||
* ), |
||||
* 'rename' => array( |
||||
* 'sex' => array( |
||||
* 'name' => 'gender', |
||||
* 'definition' => array( |
||||
* 'type' => 'text', |
||||
* 'length' => 1, |
||||
* 'default' => 'M', |
||||
* ), |
||||
* ) |
||||
* ) |
||||
* ) |
||||
* |
||||
* @param boolean $check indicates whether the function should just check if the DBMS driver |
||||
* can perform the requested table alterations if the value is true or |
||||
* actually perform them otherwise. |
||||
* @access public |
||||
* |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
*/ |
||||
function alterTable($name, $changes, $check) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
foreach ($changes as $change_name => $change) { |
||||
switch ($change_name) { |
||||
case 'add': |
||||
case 'remove': |
||||
case 'change': |
||||
case 'name': |
||||
case 'rename': |
||||
break; |
||||
default: |
||||
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, |
||||
'change type "'.$change_name.'\" not yet supported', __FUNCTION__); |
||||
} |
||||
} |
||||
|
||||
if ($check) { |
||||
return MDB2_OK; |
||||
} |
||||
|
||||
$name = $db->quoteIdentifier($name, true); |
||||
|
||||
if (!empty($changes['remove']) && is_array($changes['remove'])) { |
||||
foreach ($changes['remove'] as $field_name => $field) { |
||||
$field_name = $db->quoteIdentifier($field_name, true); |
||||
$query = 'DROP ' . $field_name; |
||||
$result = $db->exec("ALTER TABLE $name $query"); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!empty($changes['rename']) && is_array($changes['rename'])) { |
||||
foreach ($changes['rename'] as $field_name => $field) { |
||||
$field_name = $db->quoteIdentifier($field_name, true); |
||||
$result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true)); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!empty($changes['add']) && is_array($changes['add'])) { |
||||
foreach ($changes['add'] as $field_name => $field) { |
||||
$query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); |
||||
$result = $db->exec("ALTER TABLE $name $query"); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!empty($changes['change']) && is_array($changes['change'])) { |
||||
foreach ($changes['change'] as $field_name => $field) { |
||||
$field_name = $db->quoteIdentifier($field_name, true); |
||||
if (!empty($field['definition']['type'])) { |
||||
$server_info = $db->getServerVersion(); |
||||
if (PEAR::isError($server_info)) { |
||||
return $server_info; |
||||
} |
||||
if (is_array($server_info) && $server_info['major'] < 8) { |
||||
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, |
||||
'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__); |
||||
} |
||||
$db->loadModule('Datatype', null, true); |
||||
$type = $db->datatype->getTypeDeclaration($field['definition']); |
||||
$query = "ALTER $field_name TYPE $type USING CAST($field_name AS $type)"; |
||||
$result = $db->exec("ALTER TABLE $name $query"); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
if (array_key_exists('default', $field['definition'])) { |
||||
$query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']); |
||||
$result = $db->exec("ALTER TABLE $name $query"); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
if (!empty($field['definition']['notnull'])) { |
||||
$query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL'; |
||||
$result = $db->exec("ALTER TABLE $name $query"); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!empty($changes['name'])) { |
||||
$change_name = $db->quoteIdentifier($changes['name'], true); |
||||
$result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
|
||||
return MDB2_OK; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listDatabases() |
||||
|
||||
/** |
||||
* list all databases |
||||
* |
||||
* @return mixed array of database names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listDatabases() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'SELECT datname FROM pg_database'; |
||||
$result2 = $db->standaloneQuery($query, array('text'), false); |
||||
if (!MDB2::isResultCommon($result2)) { |
||||
return $result2; |
||||
} |
||||
|
||||
$result = $result2->fetchCol(); |
||||
$result2->free(); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listUsers() |
||||
|
||||
/** |
||||
* list all users |
||||
* |
||||
* @return mixed array of user names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listUsers() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'SELECT usename FROM pg_user'; |
||||
$result2 = $db->standaloneQuery($query, array('text'), false); |
||||
if (!MDB2::isResultCommon($result2)) { |
||||
return $result2; |
||||
} |
||||
|
||||
$result = $result2->fetchCol(); |
||||
$result2->free(); |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listViews() |
||||
|
||||
/** |
||||
* list all views in the current database |
||||
* |
||||
* @return mixed array of view names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listViews() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = "SELECT viewname |
||||
FROM pg_views |
||||
WHERE schemaname NOT IN ('pg_catalog', 'information_schema') |
||||
AND viewname !~ '^pg_'"; |
||||
$result = $db->queryCol($query); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listTableViews() |
||||
|
||||
/** |
||||
* list the views in the database that reference a given table |
||||
* |
||||
* @param string table for which all referenced views should be found |
||||
* @return mixed array of view names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listTableViews($table) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables'; |
||||
$query.= ' WHERE tablename ='.$db->quote($table, 'text'); |
||||
$result = $db->queryCol($query); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listFunctions() |
||||
|
||||
/** |
||||
* list all functions in the current database |
||||
* |
||||
* @return mixed array of function names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listFunctions() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = " |
||||
SELECT |
||||
proname |
||||
FROM |
||||
pg_proc pr, |
||||
pg_type tp |
||||
WHERE |
||||
tp.oid = pr.prorettype |
||||
AND pr.proisagg = FALSE |
||||
AND tp.typname <> 'trigger' |
||||
AND pr.pronamespace IN |
||||
(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')"; |
||||
$result = $db->queryCol($query); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listTableTriggers() |
||||
|
||||
/** |
||||
* list all triggers in the database that reference a given table |
||||
* |
||||
* @param string table for which all referenced triggers should be found |
||||
* @return mixed array of trigger names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listTableTriggers($table = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'SELECT trg.tgname AS trigger_name |
||||
FROM pg_trigger trg, |
||||
pg_class tbl |
||||
WHERE trg.tgrelid = tbl.oid'; |
||||
if (!is_null($table)) { |
||||
$table = $db->quote(strtoupper($table), 'text'); |
||||
$query .= " AND tbl.relname = $table"; |
||||
} |
||||
$result = $db->queryCol($query); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listTables() |
||||
|
||||
/** |
||||
* list all tables in the current database |
||||
* |
||||
* @return mixed array of table names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listTables() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
// gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php |
||||
$query = 'SELECT c.relname AS "Name"' |
||||
. ' FROM pg_class c, pg_user u' |
||||
. ' WHERE c.relowner = u.usesysid' |
||||
. " AND c.relkind = 'r'" |
||||
. ' AND NOT EXISTS' |
||||
. ' (SELECT 1 FROM pg_views' |
||||
. ' WHERE viewname = c.relname)' |
||||
. " AND c.relname !~ '^(pg_|sql_)'" |
||||
. ' UNION' |
||||
. ' SELECT c.relname AS "Name"' |
||||
. ' FROM pg_class c' |
||||
. " WHERE c.relkind = 'r'" |
||||
. ' AND NOT EXISTS' |
||||
. ' (SELECT 1 FROM pg_views' |
||||
. ' WHERE viewname = c.relname)' |
||||
. ' AND NOT EXISTS' |
||||
. ' (SELECT 1 FROM pg_user' |
||||
. ' WHERE usesysid = c.relowner)' |
||||
. " AND c.relname !~ '^pg_'"; |
||||
$result = $db->queryCol($query); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listTableFields() |
||||
|
||||
/** |
||||
* list all fields in a table in the current database |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @return mixed array of field names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listTableFields($table) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table); |
||||
|
||||
$table = $db->quoteIdentifier($table, true); |
||||
if (!empty($schema)) { |
||||
$table = $db->quoteIdentifier($schema, true) . '.' .$table; |
||||
} |
||||
$db->setLimit(1); |
||||
$result2 = $db->query("SELECT * FROM $table"); |
||||
if (PEAR::isError($result2)) { |
||||
return $result2; |
||||
} |
||||
$result = $result2->getColumnNames(); |
||||
$result2->free(); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
return array_flip($result); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listTableIndexes() |
||||
|
||||
/** |
||||
* list all indexes in a table |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @return mixed array of index names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listTableIndexes($table) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table); |
||||
|
||||
$table = $db->quote($table, 'text'); |
||||
$subquery = "SELECT indexrelid |
||||
FROM pg_index |
||||
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid |
||||
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid |
||||
WHERE pg_class.relname = $table |
||||
AND indisunique != 't' |
||||
AND indisprimary != 't'"; |
||||
if (!empty($schema)) { |
||||
$subquery .= ' AND pg_namespace.nspname = '.$db->quote($schema, 'text'); |
||||
} |
||||
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)"; |
||||
$indexes = $db->queryCol($query, 'text'); |
||||
if (PEAR::isError($indexes)) { |
||||
return $indexes; |
||||
} |
||||
|
||||
$result = array(); |
||||
foreach ($indexes as $index) { |
||||
$index = $this->_fixIndexName($index); |
||||
if (!empty($index)) { |
||||
$result[$index] = true; |
||||
} |
||||
} |
||||
|
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_change_key_case($result, $db->options['field_case']); |
||||
} |
||||
return array_keys($result); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ dropConstraint() |
||||
|
||||
/** |
||||
* drop existing constraint |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @param string $name name of the constraint to be dropped |
||||
* @param string $primary hint if the constraint is primary |
||||
* |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function dropConstraint($table, $name, $primary = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
// is it an UNIQUE index? |
||||
$query = 'SELECT relname |
||||
FROM pg_class |
||||
WHERE oid IN ( |
||||
SELECT indexrelid |
||||
FROM pg_index, pg_class |
||||
WHERE pg_class.relname = '.$db->quote($table, 'text').' |
||||
AND pg_class.oid = pg_index.indrelid |
||||
AND indisunique = \'t\') |
||||
EXCEPT |
||||
SELECT conname |
||||
FROM pg_constraint, pg_class |
||||
WHERE pg_constraint.conrelid = pg_class.oid |
||||
AND relname = '. $db->quote($table, 'text'); |
||||
$unique = $db->queryCol($query, 'text'); |
||||
if (PEAR::isError($unique) || empty($unique)) { |
||||
// not an UNIQUE index, maybe a CONSTRAINT |
||||
return parent::dropConstraint($table, $name, $primary); |
||||
} |
||||
|
||||
if (in_array($name, $unique)) { |
||||
return $db->exec('DROP INDEX '.$db->quoteIdentifier($name, true)); |
||||
} |
||||
$idxname = $db->getIndexName($name); |
||||
if (in_array($idxname, $unique)) { |
||||
return $db->exec('DROP INDEX '.$db->quoteIdentifier($idxname, true)); |
||||
} |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$name . ' is not an existing constraint for table ' . $table, __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listTableConstraints() |
||||
|
||||
/** |
||||
* list all constraints in a table |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @return mixed array of constraint names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listTableConstraints($table) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table); |
||||
|
||||
$table = $db->quote($table, 'text'); |
||||
$query = 'SELECT conname |
||||
FROM pg_constraint |
||||
LEFT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid |
||||
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid |
||||
WHERE relname = ' .$table; |
||||
if (!empty($schema)) { |
||||
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text'); |
||||
} |
||||
$query .= ' |
||||
UNION DISTINCT |
||||
SELECT relname |
||||
FROM pg_class |
||||
WHERE oid IN ( |
||||
SELECT indexrelid |
||||
FROM pg_index |
||||
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid |
||||
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid |
||||
WHERE pg_class.relname = '.$table.' |
||||
AND indisunique = \'t\''; |
||||
if (!empty($schema)) { |
||||
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text'); |
||||
} |
||||
$query .= ')'; |
||||
$constraints = $db->queryCol($query); |
||||
if (PEAR::isError($constraints)) { |
||||
return $constraints; |
||||
} |
||||
|
||||
$result = array(); |
||||
foreach ($constraints as $constraint) { |
||||
$constraint = $this->_fixIndexName($constraint); |
||||
if (!empty($constraint)) { |
||||
$result[$constraint] = true; |
||||
} |
||||
} |
||||
|
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE |
||||
&& $db->options['field_case'] == CASE_LOWER |
||||
) { |
||||
$result = array_change_key_case($result, $db->options['field_case']); |
||||
} |
||||
return array_keys($result); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ createSequence() |
||||
|
||||
/** |
||||
* create sequence |
||||
* |
||||
* @param string $seq_name name of the sequence to be created |
||||
* @param string $start start value of the sequence; default is 1 |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function createSequence($seq_name, $start = 1) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); |
||||
return $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1". |
||||
($start < 1 ? " MINVALUE $start" : '')." START $start"); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ dropSequence() |
||||
|
||||
/** |
||||
* drop existing sequence |
||||
* |
||||
* @param string $seq_name name of the sequence to be dropped |
||||
* @return mixed MDB2_OK on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function dropSequence($seq_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); |
||||
return $db->exec("DROP SEQUENCE $sequence_name"); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ listSequences() |
||||
|
||||
/** |
||||
* list all sequences in the current database |
||||
* |
||||
* @return mixed array of sequence names on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function listSequences() |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN"; |
||||
$query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')"; |
||||
$table_names = $db->queryCol($query); |
||||
if (PEAR::isError($table_names)) { |
||||
return $table_names; |
||||
} |
||||
$result = array(); |
||||
foreach ($table_names as $table_name) { |
||||
$result[] = $this->_fixSequenceName($table_name); |
||||
} |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
||||
} |
||||
return $result; |
||||
} |
||||
} |
||||
?> |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,61 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: Common.php,v 1.2 2007/09/09 13:47:36 quipo Exp $ |
||||
// |
||||
|
||||
/** |
||||
* Base class for the natuve modules that is extended by each MDB2 driver |
||||
* |
||||
* To load this module in the MDB2 object: |
||||
* $mdb->loadModule('Native'); |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Native_Common extends MDB2_Module_Common |
||||
{ |
||||
} |
||||
?> |
||||
@ -0,0 +1,60 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: mysql.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Native/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 MySQL driver for the native module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Native_mysql extends MDB2_Driver_Native_Common |
||||
{ |
||||
} |
||||
?> |
||||
@ -0,0 +1,88 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Paul Cooper <pgc@ucecom.com> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: pgsql.php,v 1.12 2006/07/15 13:07:15 lsmith Exp $ |
||||
|
||||
require_once 'MDB2/Driver/Native/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 PostGreSQL driver for the native module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Paul Cooper <pgc@ucecom.com> |
||||
*/ |
||||
class MDB2_Driver_Native_pgsql extends MDB2_Driver_Native_Common |
||||
{ |
||||
// }}} |
||||
// {{{ deleteOID() |
||||
|
||||
/** |
||||
* delete an OID |
||||
* |
||||
* @param integer $OID |
||||
* @return mixed MDB2_OK on success or MDB2 Error Object on failure |
||||
* @access public |
||||
*/ |
||||
function deleteOID($OID) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$connection = $db->getConnection(); |
||||
if (PEAR::isError($connection)) { |
||||
return $connection; |
||||
} |
||||
|
||||
if (!@pg_lo_unlink($connection, $OID)) { |
||||
return $db->raiseError(null, null, null, |
||||
'Unable to unlink OID: '.$OID, __FUNCTION__); |
||||
} |
||||
return MDB2_OK; |
||||
} |
||||
|
||||
} |
||||
?> |
||||
@ -0,0 +1,60 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: sqlite.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Native/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 SQLite driver for the native module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common |
||||
{ |
||||
} |
||||
?> |
||||
@ -0,0 +1,517 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: Common.php,v 1.43 2009/01/14 15:01:21 quipo Exp $ |
||||
// |
||||
|
||||
/** |
||||
* @package MDB2 |
||||
* @category Database |
||||
*/ |
||||
|
||||
/** |
||||
* These are constants for the tableInfo-function |
||||
* they are bitwised or'ed. so if there are more constants to be defined |
||||
* in the future, adjust MDB2_TABLEINFO_FULL accordingly |
||||
*/ |
||||
|
||||
define('MDB2_TABLEINFO_ORDER', 1); |
||||
define('MDB2_TABLEINFO_ORDERTABLE', 2); |
||||
define('MDB2_TABLEINFO_FULL', 3); |
||||
|
||||
/** |
||||
* Base class for the schema reverse engineering module that is extended by each MDB2 driver |
||||
* |
||||
* To load this module in the MDB2 object: |
||||
* $mdb->loadModule('Reverse'); |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Reverse_Common extends MDB2_Module_Common |
||||
{ |
||||
// {{{ splitTableSchema() |
||||
|
||||
/** |
||||
* Split the "[owner|schema].table" notation into an array |
||||
* |
||||
* @param string $table [schema and] table name |
||||
* |
||||
* @return array array(schema, table) |
||||
* @access private |
||||
*/ |
||||
function splitTableSchema($table) |
||||
{ |
||||
$ret = array(); |
||||
if (strpos($table, '.') !== false) { |
||||
return explode('.', $table); |
||||
} |
||||
return array(null, $table); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableFieldDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a field into an array |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @param string $field name of field that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure. |
||||
* The returned array contains an array for each field definition, |
||||
* with all or some of these indices, depending on the field data type: |
||||
* [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type] |
||||
* @access public |
||||
*/ |
||||
function getTableFieldDefinition($table, $field) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableIndexDefinition() |
||||
|
||||
/** |
||||
* Get the structure of an index into an array |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @param string $index name of index that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* The returned array has this structure: |
||||
* </pre> |
||||
* array ( |
||||
* [fields] => array ( |
||||
* [field1name] => array() // one entry per each field covered |
||||
* [field2name] => array() // by the index |
||||
* [field3name] => array( |
||||
* [sorting] => ascending |
||||
* ) |
||||
* ) |
||||
* ); |
||||
* </pre> |
||||
* @access public |
||||
*/ |
||||
function getTableIndexDefinition($table, $index) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableConstraintDefinition() |
||||
|
||||
/** |
||||
* Get the structure of an constraints into an array |
||||
* |
||||
* @param string $table name of table that should be used in method |
||||
* @param string $index name of index that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* The returned array has this structure: |
||||
* <pre> |
||||
* array ( |
||||
* [primary] => 0 |
||||
* [unique] => 0 |
||||
* [foreign] => 1 |
||||
* [check] => 0 |
||||
* [fields] => array ( |
||||
* [field1name] => array() // one entry per each field covered |
||||
* [field2name] => array() // by the index |
||||
* [field3name] => array( |
||||
* [sorting] => ascending |
||||
* [position] => 3 |
||||
* ) |
||||
* ) |
||||
* [references] => array( |
||||
* [table] => name |
||||
* [fields] => array( |
||||
* [field1name] => array( //one entry per each referenced field |
||||
* [position] => 1 |
||||
* ) |
||||
* ) |
||||
* ) |
||||
* [deferrable] => 0 |
||||
* [initiallydeferred] => 0 |
||||
* [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION |
||||
* [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION |
||||
* [match] => SIMPLE|PARTIAL|FULL |
||||
* ); |
||||
* </pre> |
||||
* @access public |
||||
*/ |
||||
function getTableConstraintDefinition($table, $index) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getSequenceDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a sequence into an array |
||||
* |
||||
* @param string $sequence name of sequence that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* The returned array has this structure: |
||||
* <pre> |
||||
* array ( |
||||
* [start] => n |
||||
* ); |
||||
* </pre> |
||||
* @access public |
||||
*/ |
||||
function getSequenceDefinition($sequence) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$start = $db->currId($sequence); |
||||
if (PEAR::isError($start)) { |
||||
return $start; |
||||
} |
||||
if ($db->supports('current_id')) { |
||||
$start++; |
||||
} else { |
||||
$db->warnings[] = 'database does not support getting current |
||||
sequence value, the sequence value was incremented'; |
||||
} |
||||
$definition = array(); |
||||
if ($start != 1) { |
||||
$definition = array('start' => $start); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTriggerDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a trigger into an array |
||||
* |
||||
* EXPERIMENTAL |
||||
* |
||||
* WARNING: this function is experimental and may change the returned value |
||||
* at any time until labelled as non-experimental |
||||
* |
||||
* @param string $trigger name of trigger that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* The returned array has this structure: |
||||
* <pre> |
||||
* array ( |
||||
* [trigger_name] => 'trigger name', |
||||
* [table_name] => 'table name', |
||||
* [trigger_body] => 'trigger body definition', |
||||
* [trigger_type] => 'BEFORE' | 'AFTER', |
||||
* [trigger_event] => 'INSERT' | 'UPDATE' | 'DELETE' |
||||
* //or comma separated list of multiple events, when supported |
||||
* [trigger_enabled] => true|false |
||||
* [trigger_comment] => 'trigger comment', |
||||
* ); |
||||
* </pre> |
||||
* The oci8 driver also returns a [when_clause] index. |
||||
* @access public |
||||
*/ |
||||
function getTriggerDefinition($trigger) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ tableInfo() |
||||
|
||||
/** |
||||
* Returns information about a table or a result set |
||||
* |
||||
* The format of the resulting array depends on which <var>$mode</var> |
||||
* you select. The sample output below is based on this query: |
||||
* <pre> |
||||
* SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId |
||||
* FROM tblFoo |
||||
* JOIN tblBar ON tblFoo.fldId = tblBar.fldId |
||||
* </pre> |
||||
* |
||||
* <ul> |
||||
* <li> |
||||
* |
||||
* <kbd>null</kbd> (default) |
||||
* <pre> |
||||
* [0] => Array ( |
||||
* [table] => tblFoo |
||||
* [name] => fldId |
||||
* [type] => int |
||||
* [len] => 11 |
||||
* [flags] => primary_key not_null |
||||
* ) |
||||
* [1] => Array ( |
||||
* [table] => tblFoo |
||||
* [name] => fldPhone |
||||
* [type] => string |
||||
* [len] => 20 |
||||
* [flags] => |
||||
* ) |
||||
* [2] => Array ( |
||||
* [table] => tblBar |
||||
* [name] => fldId |
||||
* [type] => int |
||||
* [len] => 11 |
||||
* [flags] => primary_key not_null |
||||
* ) |
||||
* </pre> |
||||
* |
||||
* </li><li> |
||||
* |
||||
* <kbd>MDB2_TABLEINFO_ORDER</kbd> |
||||
* |
||||
* <p>In addition to the information found in the default output, |
||||
* a notation of the number of columns is provided by the |
||||
* <samp>num_fields</samp> element while the <samp>order</samp> |
||||
* element provides an array with the column names as the keys and |
||||
* their location index number (corresponding to the keys in the |
||||
* the default output) as the values.</p> |
||||
* |
||||
* <p>If a result set has identical field names, the last one is |
||||
* used.</p> |
||||
* |
||||
* <pre> |
||||
* [num_fields] => 3 |
||||
* [order] => Array ( |
||||
* [fldId] => 2 |
||||
* [fldTrans] => 1 |
||||
* ) |
||||
* </pre> |
||||
* |
||||
* </li><li> |
||||
* |
||||
* <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd> |
||||
* |
||||
* <p>Similar to <kbd>MDB2_TABLEINFO_ORDER</kbd> but adds more |
||||
* dimensions to the array in which the table names are keys and |
||||
* the field names are sub-keys. This is helpful for queries that |
||||
* join tables which have identical field names.</p> |
||||
* |
||||
* <pre> |
||||
* [num_fields] => 3 |
||||
* [ordertable] => Array ( |
||||
* [tblFoo] => Array ( |
||||
* [fldId] => 0 |
||||
* [fldPhone] => 1 |
||||
* ) |
||||
* [tblBar] => Array ( |
||||
* [fldId] => 2 |
||||
* ) |
||||
* ) |
||||
* </pre> |
||||
* |
||||
* </li> |
||||
* </ul> |
||||
* |
||||
* The <samp>flags</samp> element contains a space separated list |
||||
* of extra information about the field. This data is inconsistent |
||||
* between DBMS's due to the way each DBMS works. |
||||
* + <samp>primary_key</samp> |
||||
* + <samp>unique_key</samp> |
||||
* + <samp>multiple_key</samp> |
||||
* + <samp>not_null</samp> |
||||
* |
||||
* Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp> |
||||
* elements if <var>$result</var> is a table name. The following DBMS's |
||||
* provide full information from queries: |
||||
* + fbsql |
||||
* + mysql |
||||
* |
||||
* If the 'portability' option has <samp>MDB2_PORTABILITY_FIX_CASE</samp> |
||||
* turned on, the names of tables and fields will be lower or upper cased. |
||||
* |
||||
* @param object|string $result MDB2_result object from a query or a |
||||
* string containing the name of a table. |
||||
* While this also accepts a query result |
||||
* resource identifier, this behavior is |
||||
* deprecated. |
||||
* @param int $mode either unused or one of the tableInfo modes: |
||||
* <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>, |
||||
* <kbd>MDB2_TABLEINFO_ORDER</kbd> or |
||||
* <kbd>MDB2_TABLEINFO_FULL</kbd> (which does both). |
||||
* These are bitwise, so the first two can be |
||||
* combined using <kbd>|</kbd>. |
||||
* |
||||
* @return array an associative array with the information requested. |
||||
* A MDB2_Error object on failure. |
||||
* |
||||
* @see MDB2_Driver_Common::setOption() |
||||
*/ |
||||
function tableInfo($result, $mode = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
if (!is_string($result)) { |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'method not implemented', __FUNCTION__); |
||||
} |
||||
|
||||
$db->loadModule('Manager', null, true); |
||||
$fields = $db->manager->listTableFields($result); |
||||
if (PEAR::isError($fields)) { |
||||
return $fields; |
||||
} |
||||
|
||||
$flags = array(); |
||||
|
||||
$idxname_format = $db->getOption('idxname_format'); |
||||
$db->setOption('idxname_format', '%s'); |
||||
|
||||
$indexes = $db->manager->listTableIndexes($result); |
||||
if (PEAR::isError($indexes)) { |
||||
$db->setOption('idxname_format', $idxname_format); |
||||
return $indexes; |
||||
} |
||||
|
||||
foreach ($indexes as $index) { |
||||
$definition = $this->getTableIndexDefinition($result, $index); |
||||
if (PEAR::isError($definition)) { |
||||
$db->setOption('idxname_format', $idxname_format); |
||||
return $definition; |
||||
} |
||||
if (count($definition['fields']) > 1) { |
||||
foreach ($definition['fields'] as $field => $sort) { |
||||
$flags[$field] = 'multiple_key'; |
||||
} |
||||
} |
||||
} |
||||
|
||||
$constraints = $db->manager->listTableConstraints($result); |
||||
if (PEAR::isError($constraints)) { |
||||
return $constraints; |
||||
} |
||||
|
||||
foreach ($constraints as $constraint) { |
||||
$definition = $this->getTableConstraintDefinition($result, $constraint); |
||||
if (PEAR::isError($definition)) { |
||||
$db->setOption('idxname_format', $idxname_format); |
||||
return $definition; |
||||
} |
||||
$flag = !empty($definition['primary']) |
||||
? 'primary_key' : (!empty($definition['unique']) |
||||
? 'unique_key' : false); |
||||
if ($flag) { |
||||
foreach ($definition['fields'] as $field => $sort) { |
||||
if (empty($flags[$field]) || $flags[$field] != 'primary_key') { |
||||
$flags[$field] = $flag; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
$res = array(); |
||||
|
||||
if ($mode) { |
||||
$res['num_fields'] = count($fields); |
||||
} |
||||
|
||||
foreach ($fields as $i => $field) { |
||||
$definition = $this->getTableFieldDefinition($result, $field); |
||||
if (PEAR::isError($definition)) { |
||||
$db->setOption('idxname_format', $idxname_format); |
||||
return $definition; |
||||
} |
||||
$res[$i] = $definition[0]; |
||||
$res[$i]['name'] = $field; |
||||
$res[$i]['table'] = $result; |
||||
$res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype'])); |
||||
// 'primary_key', 'unique_key', 'multiple_key' |
||||
$res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field]; |
||||
// not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]' |
||||
if (!empty($res[$i]['notnull'])) { |
||||
$res[$i]['flags'].= ' not_null'; |
||||
} |
||||
if (!empty($res[$i]['unsigned'])) { |
||||
$res[$i]['flags'].= ' unsigned'; |
||||
} |
||||
if (!empty($res[$i]['auto_increment'])) { |
||||
$res[$i]['flags'].= ' autoincrement'; |
||||
} |
||||
if (!empty($res[$i]['default'])) { |
||||
$res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']); |
||||
} |
||||
|
||||
if ($mode & MDB2_TABLEINFO_ORDER) { |
||||
$res['order'][$res[$i]['name']] = $i; |
||||
} |
||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) { |
||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
||||
} |
||||
} |
||||
|
||||
$db->setOption('idxname_format', $idxname_format); |
||||
return $res; |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,536 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: mysql.php,v 1.80 2008/03/26 21:15:37 quipo Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Reverse/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 MySQL driver for the schema reverse engineering module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
* @author Lorenzo Alberton <l.alberton@quipo.it> |
||||
*/ |
||||
class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common |
||||
{ |
||||
// {{{ getTableFieldDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a field into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $field_name name of field that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableFieldDefinition($table_name, $field_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$result = $db->loadModule('Datatype', null, true); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$table = $db->quoteIdentifier($table, true); |
||||
$query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name); |
||||
$columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($columns)) { |
||||
return $columns; |
||||
} |
||||
foreach ($columns as $column) { |
||||
$column = array_change_key_case($column, CASE_LOWER); |
||||
$column['name'] = $column['field']; |
||||
unset($column['field']); |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$column['name'] = strtolower($column['name']); |
||||
} else { |
||||
$column['name'] = strtoupper($column['name']); |
||||
} |
||||
} else { |
||||
$column = array_change_key_case($column, $db->options['field_case']); |
||||
} |
||||
if ($field_name == $column['name']) { |
||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column); |
||||
if (PEAR::isError($mapped_datatype)) { |
||||
return $mapped_datatype; |
||||
} |
||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype; |
||||
$notnull = false; |
||||
if (empty($column['null']) || $column['null'] !== 'YES') { |
||||
$notnull = true; |
||||
} |
||||
$default = false; |
||||
if (array_key_exists('default', $column)) { |
||||
$default = $column['default']; |
||||
if (is_null($default) && $notnull) { |
||||
$default = ''; |
||||
} |
||||
} |
||||
$autoincrement = false; |
||||
if (!empty($column['extra']) && $column['extra'] == 'auto_increment') { |
||||
$autoincrement = true; |
||||
} |
||||
$collate = null; |
||||
if (!empty($column['collation'])) { |
||||
$collate = $column['collation']; |
||||
$charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate); |
||||
} |
||||
|
||||
$definition[0] = array( |
||||
'notnull' => $notnull, |
||||
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type']) |
||||
); |
||||
if (!is_null($length)) { |
||||
$definition[0]['length'] = $length; |
||||
} |
||||
if (!is_null($unsigned)) { |
||||
$definition[0]['unsigned'] = $unsigned; |
||||
} |
||||
if (!is_null($fixed)) { |
||||
$definition[0]['fixed'] = $fixed; |
||||
} |
||||
if ($default !== false) { |
||||
$definition[0]['default'] = $default; |
||||
} |
||||
if ($autoincrement !== false) { |
||||
$definition[0]['autoincrement'] = $autoincrement; |
||||
} |
||||
if (!is_null($collate)) { |
||||
$definition[0]['collate'] = $collate; |
||||
$definition[0]['charset'] = $charset; |
||||
} |
||||
foreach ($types as $key => $type) { |
||||
$definition[$key] = $definition[0]; |
||||
if ($type == 'clob' || $type == 'blob') { |
||||
unset($definition[$key]['default']); |
||||
} elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) { |
||||
$definition[$key]['default'] = '0000-00-00 00:00:00'; |
||||
} |
||||
$definition[$key]['type'] = $type; |
||||
$definition[$key]['mdb2type'] = $type; |
||||
} |
||||
return $definition; |
||||
} |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table column', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableIndexDefinition() |
||||
|
||||
/** |
||||
* Get the structure of an index into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $index_name name of index that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableIndexDefinition($table_name, $index_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$table = $db->quoteIdentifier($table, true); |
||||
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */"; |
||||
$index_name_mdb2 = $db->getIndexName($index_name); |
||||
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2))); |
||||
if (!PEAR::isError($result) && !is_null($result)) { |
||||
// apply 'idxname_format' only if the query succeeded, otherwise |
||||
// fallback to the given $index_name, without transformation |
||||
$index_name = $index_name_mdb2; |
||||
} |
||||
$result = $db->query(sprintf($query, $db->quote($index_name))); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
$colpos = 1; |
||||
$definition = array(); |
||||
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { |
||||
$row = array_change_key_case($row, CASE_LOWER); |
||||
$key_name = $row['key_name']; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$key_name = strtolower($key_name); |
||||
} else { |
||||
$key_name = strtoupper($key_name); |
||||
} |
||||
} |
||||
if ($index_name == $key_name) { |
||||
if (!$row['non_unique']) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$index_name . ' is not an existing table index', __FUNCTION__); |
||||
} |
||||
$column_name = $row['column_name']; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$column_name = strtolower($column_name); |
||||
} else { |
||||
$column_name = strtoupper($column_name); |
||||
} |
||||
} |
||||
$definition['fields'][$column_name] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
if (!empty($row['collation'])) { |
||||
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' |
||||
? 'ascending' : 'descending'); |
||||
} |
||||
} |
||||
} |
||||
$result->free(); |
||||
if (empty($definition['fields'])) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$index_name . ' is not an existing table index', __FUNCTION__); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableConstraintDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a constraint into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $constraint_name name of constraint that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableConstraintDefinition($table_name, $constraint_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
$constraint_name_original = $constraint_name; |
||||
|
||||
$table = $db->quoteIdentifier($table, true); |
||||
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */"; |
||||
if (strtolower($constraint_name) != 'primary') { |
||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name); |
||||
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2))); |
||||
if (!PEAR::isError($result) && !is_null($result)) { |
||||
// apply 'idxname_format' only if the query succeeded, otherwise |
||||
// fallback to the given $index_name, without transformation |
||||
$constraint_name = $constraint_name_mdb2; |
||||
} |
||||
} |
||||
$result = $db->query(sprintf($query, $db->quote($constraint_name))); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
$colpos = 1; |
||||
//default values, eventually overridden |
||||
$definition = array( |
||||
'primary' => false, |
||||
'unique' => false, |
||||
'foreign' => false, |
||||
'check' => false, |
||||
'fields' => array(), |
||||
'references' => array( |
||||
'table' => '', |
||||
'fields' => array(), |
||||
), |
||||
'onupdate' => '', |
||||
'ondelete' => '', |
||||
'match' => '', |
||||
'deferrable' => false, |
||||
'initiallydeferred' => false, |
||||
); |
||||
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) { |
||||
$row = array_change_key_case($row, CASE_LOWER); |
||||
$key_name = $row['key_name']; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$key_name = strtolower($key_name); |
||||
} else { |
||||
$key_name = strtoupper($key_name); |
||||
} |
||||
} |
||||
if ($constraint_name == $key_name) { |
||||
if ($row['non_unique']) { |
||||
//FOREIGN KEY? |
||||
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition); |
||||
} |
||||
if ($row['key_name'] == 'PRIMARY') { |
||||
$definition['primary'] = true; |
||||
} elseif (!$row['non_unique']) { |
||||
$definition['unique'] = true; |
||||
} |
||||
$column_name = $row['column_name']; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$column_name = strtolower($column_name); |
||||
} else { |
||||
$column_name = strtoupper($column_name); |
||||
} |
||||
} |
||||
$definition['fields'][$column_name] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
if (!empty($row['collation'])) { |
||||
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A' |
||||
? 'ascending' : 'descending'); |
||||
} |
||||
} |
||||
} |
||||
$result->free(); |
||||
if (empty($definition['fields'])) { |
||||
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ _getTableFKConstraintDefinition() |
||||
|
||||
/** |
||||
* Get the FK definition from the CREATE TABLE statement |
||||
* |
||||
* @param string $table table name |
||||
* @param string $constraint_name constraint name |
||||
* @param array $definition default values for constraint definition |
||||
* |
||||
* @return array|PEAR_Error |
||||
* @access private |
||||
*/ |
||||
function _getTableFKConstraintDefinition($table, $constraint_name, $definition) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
$query = 'SHOW CREATE TABLE '. $db->escape($table); |
||||
$constraint = $db->queryOne($query, 'text', 1); |
||||
if (!PEAR::isError($constraint) && !empty($constraint)) { |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$constraint = strtolower($constraint); |
||||
} else { |
||||
$constraint = strtoupper($constraint); |
||||
} |
||||
} |
||||
$constraint_name_original = $constraint_name; |
||||
$constraint_name = $db->getIndexName($constraint_name); |
||||
$pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i'; |
||||
if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) { |
||||
//fallback to original constraint name |
||||
$pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^ ]+) \(([^\)]+)\)/i'; |
||||
} |
||||
if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) { |
||||
$definition['foreign'] = true; |
||||
$column_names = explode(',', $matches[1]); |
||||
$referenced_cols = explode(',', $matches[3]); |
||||
$definition['references'] = array( |
||||
'table' => $matches[2], |
||||
'fields' => array(), |
||||
); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
$colpos = 1; |
||||
foreach ($referenced_cols as $column_name) { |
||||
$definition['references']['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
$definition['onupdate'] = 'NO ACTION'; |
||||
$definition['ondelete'] = 'NO ACTION'; |
||||
$definition['match'] = 'SIMPLE'; |
||||
return $definition; |
||||
} |
||||
} |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTriggerDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a trigger into an array |
||||
* |
||||
* EXPERIMENTAL |
||||
* |
||||
* WARNING: this function is experimental and may change the returned value |
||||
* at any time until labelled as non-experimental |
||||
* |
||||
* @param string $trigger name of trigger that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTriggerDefinition($trigger) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = 'SELECT trigger_name, |
||||
event_object_table AS table_name, |
||||
action_statement AS trigger_body, |
||||
action_timing AS trigger_type, |
||||
event_manipulation AS trigger_event |
||||
FROM information_schema.triggers |
||||
WHERE trigger_name = '. $db->quote($trigger, 'text'); |
||||
$types = array( |
||||
'trigger_name' => 'text', |
||||
'table_name' => 'text', |
||||
'trigger_body' => 'text', |
||||
'trigger_type' => 'text', |
||||
'trigger_event' => 'text', |
||||
); |
||||
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($def)) { |
||||
return $def; |
||||
} |
||||
$def['trigger_comment'] = ''; |
||||
$def['trigger_enabled'] = true; |
||||
return $def; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ tableInfo() |
||||
|
||||
/** |
||||
* Returns information about a table or a result set |
||||
* |
||||
* @param object|string $result MDB2_result object from a query or a |
||||
* string containing the name of a table. |
||||
* While this also accepts a query result |
||||
* resource identifier, this behavior is |
||||
* deprecated. |
||||
* @param int $mode a valid tableInfo mode |
||||
* |
||||
* @return array an associative array with the information requested. |
||||
* A MDB2_Error object on failure. |
||||
* |
||||
* @see MDB2_Driver_Common::setOption() |
||||
*/ |
||||
function tableInfo($result, $mode = null) |
||||
{ |
||||
if (is_string($result)) { |
||||
return parent::tableInfo($result, $mode); |
||||
} |
||||
|
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; |
||||
if (!is_resource($resource)) { |
||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, |
||||
'Could not generate result resource', __FUNCTION__); |
||||
} |
||||
|
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$case_func = 'strtolower'; |
||||
} else { |
||||
$case_func = 'strtoupper'; |
||||
} |
||||
} else { |
||||
$case_func = 'strval'; |
||||
} |
||||
|
||||
$count = @mysql_num_fields($resource); |
||||
$res = array(); |
||||
if ($mode) { |
||||
$res['num_fields'] = $count; |
||||
} |
||||
|
||||
$db->loadModule('Datatype', null, true); |
||||
for ($i = 0; $i < $count; $i++) { |
||||
$res[$i] = array( |
||||
'table' => $case_func(@mysql_field_table($resource, $i)), |
||||
'name' => $case_func(@mysql_field_name($resource, $i)), |
||||
'type' => @mysql_field_type($resource, $i), |
||||
'length' => @mysql_field_len($resource, $i), |
||||
'flags' => @mysql_field_flags($resource, $i), |
||||
); |
||||
if ($res[$i]['type'] == 'string') { |
||||
$res[$i]['type'] = 'char'; |
||||
} elseif ($res[$i]['type'] == 'unknown') { |
||||
$res[$i]['type'] = 'decimal'; |
||||
} |
||||
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); |
||||
if (PEAR::isError($mdb2type_info)) { |
||||
return $mdb2type_info; |
||||
} |
||||
$res[$i]['mdb2type'] = $mdb2type_info[0][0]; |
||||
if ($mode & MDB2_TABLEINFO_ORDER) { |
||||
$res['order'][$res[$i]['name']] = $i; |
||||
} |
||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) { |
||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
||||
} |
||||
} |
||||
|
||||
return $res; |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,573 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Authors: Paul Cooper <pgc@ucecom.com> | |
||||
// | Lorenzo Alberton <l.alberton@quipo.it> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: pgsql.php,v 1.75 2008/08/22 16:36:20 quipo Exp $ |
||||
|
||||
require_once 'MDB2/Driver/Reverse/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 PostGreSQL driver for the schema reverse engineering module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Paul Cooper <pgc@ucecom.com> |
||||
* @author Lorenzo Alberton <l.alberton@quipo.it> |
||||
*/ |
||||
class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common |
||||
{ |
||||
// {{{ getTableFieldDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a field into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $field_name name of field that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableFieldDefinition($table_name, $field_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$result = $db->loadModule('Datatype', null, true); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$query = "SELECT a.attname AS name, |
||||
t.typname AS type, |
||||
CASE a.attlen |
||||
WHEN -1 THEN |
||||
CASE t.typname |
||||
WHEN 'numeric' THEN (a.atttypmod / 65536) |
||||
WHEN 'decimal' THEN (a.atttypmod / 65536) |
||||
WHEN 'money' THEN (a.atttypmod / 65536) |
||||
ELSE CASE a.atttypmod |
||||
WHEN -1 THEN NULL |
||||
ELSE a.atttypmod - 4 |
||||
END |
||||
END |
||||
ELSE a.attlen |
||||
END AS length, |
||||
CASE t.typname |
||||
WHEN 'numeric' THEN (a.atttypmod % 65536) - 4 |
||||
WHEN 'decimal' THEN (a.atttypmod % 65536) - 4 |
||||
WHEN 'money' THEN (a.atttypmod % 65536) - 4 |
||||
ELSE 0 |
||||
END AS scale, |
||||
a.attnotnull, |
||||
a.atttypmod, |
||||
a.atthasdef, |
||||
(SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128) |
||||
FROM pg_attrdef d |
||||
WHERE d.adrelid = a.attrelid |
||||
AND d.adnum = a.attnum |
||||
AND a.atthasdef |
||||
) as default |
||||
FROM pg_attribute a, |
||||
pg_class c, |
||||
pg_type t |
||||
WHERE c.relname = ".$db->quote($table, 'text')." |
||||
AND a.atttypid = t.oid |
||||
AND c.oid = a.attrelid |
||||
AND NOT a.attisdropped |
||||
AND a.attnum > 0 |
||||
AND a.attname = ".$db->quote($field_name, 'text')." |
||||
ORDER BY a.attnum"; |
||||
$column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($column)) { |
||||
return $column; |
||||
} |
||||
|
||||
if (empty($column)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table column', __FUNCTION__); |
||||
} |
||||
|
||||
$column = array_change_key_case($column, CASE_LOWER); |
||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column); |
||||
if (PEAR::isError($mapped_datatype)) { |
||||
return $mapped_datatype; |
||||
} |
||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype; |
||||
$notnull = false; |
||||
if (!empty($column['attnotnull']) && $column['attnotnull'] == 't') { |
||||
$notnull = true; |
||||
} |
||||
$default = null; |
||||
if ($column['atthasdef'] === 't' |
||||
&& !preg_match("/nextval\('([^']+)'/", $column['default']) |
||||
) { |
||||
$pattern = '/^\'(.*)\'::[\w ]+$/i'; |
||||
$default = $column['default'];#substr($column['adsrc'], 1, -1); |
||||
if (is_null($default) && $notnull) { |
||||
$default = ''; |
||||
} elseif (!empty($default) && preg_match($pattern, $default)) { |
||||
//remove data type cast |
||||
$default = preg_replace ($pattern, '\\1', $default); |
||||
} |
||||
} |
||||
$autoincrement = false; |
||||
if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) { |
||||
$autoincrement = true; |
||||
} |
||||
$definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']); |
||||
if (!is_null($length)) { |
||||
$definition[0]['length'] = $length; |
||||
} |
||||
if (!is_null($unsigned)) { |
||||
$definition[0]['unsigned'] = $unsigned; |
||||
} |
||||
if (!is_null($fixed)) { |
||||
$definition[0]['fixed'] = $fixed; |
||||
} |
||||
if ($default !== false) { |
||||
$definition[0]['default'] = $default; |
||||
} |
||||
if ($autoincrement !== false) { |
||||
$definition[0]['autoincrement'] = $autoincrement; |
||||
} |
||||
foreach ($types as $key => $type) { |
||||
$definition[$key] = $definition[0]; |
||||
if ($type == 'clob' || $type == 'blob') { |
||||
unset($definition[$key]['default']); |
||||
} |
||||
$definition[$key]['type'] = $type; |
||||
$definition[$key]['mdb2type'] = $type; |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableIndexDefinition() |
||||
|
||||
/** |
||||
* Get the structure of an index into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $index_name name of index that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableIndexDefinition($table_name, $index_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$query = 'SELECT relname, indkey FROM pg_index, pg_class'; |
||||
$query.= ' WHERE pg_class.oid = pg_index.indexrelid'; |
||||
$query.= " AND indisunique != 't' AND indisprimary != 't'"; |
||||
$query.= ' AND pg_class.relname = %s'; |
||||
$index_name_mdb2 = $db->getIndexName($index_name); |
||||
$row = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($row) || empty($row)) { |
||||
// fallback to the given $index_name, without transformation |
||||
$row = $db->queryRow(sprintf($query, $db->quote($index_name, 'text')), null, MDB2_FETCHMODE_ASSOC); |
||||
} |
||||
if (PEAR::isError($row)) { |
||||
return $row; |
||||
} |
||||
|
||||
if (empty($row)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table index', __FUNCTION__); |
||||
} |
||||
|
||||
$row = array_change_key_case($row, CASE_LOWER); |
||||
|
||||
$db->loadModule('Manager', null, true); |
||||
$columns = $db->manager->listTableFields($table_name); |
||||
|
||||
$definition = array(); |
||||
|
||||
$index_column_numbers = explode(' ', $row['indkey']); |
||||
|
||||
$colpos = 1; |
||||
foreach ($index_column_numbers as $number) { |
||||
$definition['fields'][$columns[($number - 1)]] = array( |
||||
'position' => $colpos++, |
||||
'sorting' => 'ascending', |
||||
); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableConstraintDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a constraint into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $constraint_name name of constraint that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableConstraintDefinition($table_name, $constraint_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$query = "SELECT c.oid, |
||||
c.conname AS constraint_name, |
||||
CASE WHEN c.contype = 'c' THEN 1 ELSE 0 END AS \"check\", |
||||
CASE WHEN c.contype = 'f' THEN 1 ELSE 0 END AS \"foreign\", |
||||
CASE WHEN c.contype = 'p' THEN 1 ELSE 0 END AS \"primary\", |
||||
CASE WHEN c.contype = 'u' THEN 1 ELSE 0 END AS \"unique\", |
||||
CASE WHEN c.condeferrable = 'f' THEN 0 ELSE 1 END AS deferrable, |
||||
CASE WHEN c.condeferred = 'f' THEN 0 ELSE 1 END AS initiallydeferred, |
||||
--array_to_string(c.conkey, ' ') AS constraint_key, |
||||
t.relname AS table_name, |
||||
t2.relname AS references_table, |
||||
CASE confupdtype |
||||
WHEN 'a' THEN 'NO ACTION' |
||||
WHEN 'r' THEN 'RESTRICT' |
||||
WHEN 'c' THEN 'CASCADE' |
||||
WHEN 'n' THEN 'SET NULL' |
||||
WHEN 'd' THEN 'SET DEFAULT' |
||||
END AS onupdate, |
||||
CASE confdeltype |
||||
WHEN 'a' THEN 'NO ACTION' |
||||
WHEN 'r' THEN 'RESTRICT' |
||||
WHEN 'c' THEN 'CASCADE' |
||||
WHEN 'n' THEN 'SET NULL' |
||||
WHEN 'd' THEN 'SET DEFAULT' |
||||
END AS ondelete, |
||||
CASE confmatchtype |
||||
WHEN 'u' THEN 'UNSPECIFIED' |
||||
WHEN 'f' THEN 'FULL' |
||||
WHEN 'p' THEN 'PARTIAL' |
||||
END AS match, |
||||
--array_to_string(c.confkey, ' ') AS fk_constraint_key, |
||||
consrc |
||||
FROM pg_constraint c |
||||
LEFT JOIN pg_class t ON c.conrelid = t.oid |
||||
LEFT JOIN pg_class t2 ON c.confrelid = t2.oid |
||||
WHERE c.conname = %s |
||||
AND t.relname = " . $db->quote($table, 'text'); |
||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name); |
||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($row) || empty($row)) { |
||||
// fallback to the given $index_name, without transformation |
||||
$constraint_name_mdb2 = $constraint_name; |
||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); |
||||
} |
||||
if (PEAR::isError($row)) { |
||||
return $row; |
||||
} |
||||
$uniqueIndex = false; |
||||
if (empty($row)) { |
||||
// We might be looking for a UNIQUE index that was not created |
||||
// as a constraint but should be treated as such. |
||||
$query = 'SELECT relname AS constraint_name, |
||||
indkey, |
||||
0 AS "check", |
||||
0 AS "foreign", |
||||
0 AS "primary", |
||||
1 AS "unique", |
||||
0 AS deferrable, |
||||
0 AS initiallydeferred, |
||||
NULL AS references_table, |
||||
NULL AS onupdate, |
||||
NULL AS ondelete, |
||||
NULL AS match |
||||
FROM pg_index, pg_class |
||||
WHERE pg_class.oid = pg_index.indexrelid |
||||
AND indisunique = \'t\' |
||||
AND pg_class.relname = %s'; |
||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name); |
||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($row) || empty($row)) { |
||||
// fallback to the given $index_name, without transformation |
||||
$constraint_name_mdb2 = $constraint_name; |
||||
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC); |
||||
} |
||||
if (PEAR::isError($row)) { |
||||
return $row; |
||||
} |
||||
if (empty($row)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
$uniqueIndex = true; |
||||
} |
||||
|
||||
$row = array_change_key_case($row, CASE_LOWER); |
||||
|
||||
$definition = array( |
||||
'primary' => (boolean)$row['primary'], |
||||
'unique' => (boolean)$row['unique'], |
||||
'foreign' => (boolean)$row['foreign'], |
||||
'check' => (boolean)$row['check'], |
||||
'fields' => array(), |
||||
'references' => array( |
||||
'table' => $row['references_table'], |
||||
'fields' => array(), |
||||
), |
||||
'deferrable' => (boolean)$row['deferrable'], |
||||
'initiallydeferred' => (boolean)$row['initiallydeferred'], |
||||
'onupdate' => $row['onupdate'], |
||||
'ondelete' => $row['ondelete'], |
||||
'match' => $row['match'], |
||||
); |
||||
|
||||
if ($uniqueIndex) { |
||||
$db->loadModule('Manager', null, true); |
||||
$columns = $db->manager->listTableFields($table_name); |
||||
$index_column_numbers = explode(' ', $row['indkey']); |
||||
$colpos = 1; |
||||
foreach ($index_column_numbers as $number) { |
||||
$definition['fields'][$columns[($number - 1)]] = array( |
||||
'position' => $colpos++, |
||||
'sorting' => 'ascending', |
||||
); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
$query = 'SELECT a.attname |
||||
FROM pg_constraint c |
||||
LEFT JOIN pg_class t ON c.conrelid = t.oid |
||||
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey) |
||||
WHERE c.conname = %s |
||||
AND t.relname = ' . $db->quote($table, 'text'); |
||||
$fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null); |
||||
if (PEAR::isError($fields)) { |
||||
return $fields; |
||||
} |
||||
$colpos = 1; |
||||
foreach ($fields as $field) { |
||||
$definition['fields'][$field] = array( |
||||
'position' => $colpos++, |
||||
'sorting' => 'ascending', |
||||
); |
||||
} |
||||
|
||||
if ($definition['foreign']) { |
||||
$query = 'SELECT a.attname |
||||
FROM pg_constraint c |
||||
LEFT JOIN pg_class t ON c.confrelid = t.oid |
||||
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey) |
||||
WHERE c.conname = %s |
||||
AND t.relname = ' . $db->quote($definition['references']['table'], 'text'); |
||||
$foreign_fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null); |
||||
if (PEAR::isError($foreign_fields)) { |
||||
return $foreign_fields; |
||||
} |
||||
$colpos = 1; |
||||
foreach ($foreign_fields as $foreign_field) { |
||||
$definition['references']['fields'][$foreign_field] = array( |
||||
'position' => $colpos++, |
||||
); |
||||
} |
||||
} |
||||
|
||||
if ($definition['check']) { |
||||
$check_def = $db->queryOne("SELECT pg_get_constraintdef(" . $row['oid'] . ", 't')"); |
||||
// ... |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTriggerDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a trigger into an array |
||||
* |
||||
* EXPERIMENTAL |
||||
* |
||||
* WARNING: this function is experimental and may change the returned value |
||||
* at any time until labelled as non-experimental |
||||
* |
||||
* @param string $trigger name of trigger that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
* |
||||
* @TODO: add support for plsql functions and functions with args |
||||
*/ |
||||
function getTriggerDefinition($trigger) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = "SELECT trg.tgname AS trigger_name, |
||||
tbl.relname AS table_name, |
||||
CASE |
||||
WHEN p.proname IS NOT NULL THEN 'EXECUTE PROCEDURE ' || p.proname || '();' |
||||
ELSE '' |
||||
END AS trigger_body, |
||||
CASE trg.tgtype & cast(2 as int2) |
||||
WHEN 0 THEN 'AFTER' |
||||
ELSE 'BEFORE' |
||||
END AS trigger_type, |
||||
CASE trg.tgtype & cast(28 as int2) |
||||
WHEN 16 THEN 'UPDATE' |
||||
WHEN 8 THEN 'DELETE' |
||||
WHEN 4 THEN 'INSERT' |
||||
WHEN 20 THEN 'INSERT, UPDATE' |
||||
WHEN 28 THEN 'INSERT, UPDATE, DELETE' |
||||
WHEN 24 THEN 'UPDATE, DELETE' |
||||
WHEN 12 THEN 'INSERT, DELETE' |
||||
END AS trigger_event, |
||||
CASE trg.tgenabled |
||||
WHEN 'O' THEN 't' |
||||
ELSE trg.tgenabled |
||||
END AS trigger_enabled, |
||||
obj_description(trg.oid, 'pg_trigger') AS trigger_comment |
||||
FROM pg_trigger trg, |
||||
pg_class tbl, |
||||
pg_proc p |
||||
WHERE trg.tgrelid = tbl.oid |
||||
AND trg.tgfoid = p.oid |
||||
AND trg.tgname = ". $db->quote($trigger, 'text'); |
||||
$types = array( |
||||
'trigger_name' => 'text', |
||||
'table_name' => 'text', |
||||
'trigger_body' => 'text', |
||||
'trigger_type' => 'text', |
||||
'trigger_event' => 'text', |
||||
'trigger_comment' => 'text', |
||||
'trigger_enabled' => 'boolean', |
||||
); |
||||
return $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ tableInfo() |
||||
|
||||
/** |
||||
* Returns information about a table or a result set |
||||
* |
||||
* NOTE: only supports 'table' and 'flags' if <var>$result</var> |
||||
* is a table name. |
||||
* |
||||
* @param object|string $result MDB2_result object from a query or a |
||||
* string containing the name of a table. |
||||
* While this also accepts a query result |
||||
* resource identifier, this behavior is |
||||
* deprecated. |
||||
* @param int $mode a valid tableInfo mode |
||||
* |
||||
* @return array an associative array with the information requested. |
||||
* A MDB2_Error object on failure. |
||||
* |
||||
* @see MDB2_Driver_Common::tableInfo() |
||||
*/ |
||||
function tableInfo($result, $mode = null) |
||||
{ |
||||
if (is_string($result)) { |
||||
return parent::tableInfo($result, $mode); |
||||
} |
||||
|
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result; |
||||
if (!is_resource($resource)) { |
||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, |
||||
'Could not generate result resource', __FUNCTION__); |
||||
} |
||||
|
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$case_func = 'strtolower'; |
||||
} else { |
||||
$case_func = 'strtoupper'; |
||||
} |
||||
} else { |
||||
$case_func = 'strval'; |
||||
} |
||||
|
||||
$count = @pg_num_fields($resource); |
||||
$res = array(); |
||||
|
||||
if ($mode) { |
||||
$res['num_fields'] = $count; |
||||
} |
||||
|
||||
$db->loadModule('Datatype', null, true); |
||||
for ($i = 0; $i < $count; $i++) { |
||||
$res[$i] = array( |
||||
'table' => function_exists('pg_field_table') ? @pg_field_table($resource, $i) : '', |
||||
'name' => $case_func(@pg_field_name($resource, $i)), |
||||
'type' => @pg_field_type($resource, $i), |
||||
'length' => @pg_field_size($resource, $i), |
||||
'flags' => '', |
||||
); |
||||
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]); |
||||
if (PEAR::isError($mdb2type_info)) { |
||||
return $mdb2type_info; |
||||
} |
||||
$res[$i]['mdb2type'] = $mdb2type_info[0][0]; |
||||
if ($mode & MDB2_TABLEINFO_ORDER) { |
||||
$res['order'][$res[$i]['name']] = $i; |
||||
} |
||||
if ($mode & MDB2_TABLEINFO_ORDERTABLE) { |
||||
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
||||
} |
||||
} |
||||
|
||||
return $res; |
||||
} |
||||
} |
||||
?> |
||||
@ -0,0 +1,609 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith, Lorenzo Alberton | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Authors: Lukas Smith <smith@pooteeweet.org> | |
||||
// | Lorenzo Alberton <l.alberton@quipo.it> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: sqlite.php,v 1.80 2008/05/03 10:30:14 quipo Exp $ |
||||
// |
||||
|
||||
require_once 'MDB2/Driver/Reverse/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 SQlite driver for the schema reverse engineering module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common |
||||
{ |
||||
/** |
||||
* Remove SQL comments from the field definition |
||||
* |
||||
* @access private |
||||
*/ |
||||
function _removeComments($sql) { |
||||
$lines = split("\n", $sql); |
||||
foreach ($lines as $k => $line) { |
||||
$pieces = explode('--', $line); |
||||
if (count($pieces) > 1 && (substr_count($pieces[0], '\'') % 2) == 0) { |
||||
$lines[$k] = substr($line, 0, strpos($line, '--')); |
||||
} |
||||
} |
||||
return implode("\n", $lines); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
function _getTableColumns($sql) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
$start_pos = strpos($sql, '('); |
||||
$end_pos = strrpos($sql, ')'); |
||||
$column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1); |
||||
// replace the decimal length-places-separator with a colon |
||||
$column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def); |
||||
$column_def = $this->_removeComments($column_def); |
||||
$column_sql = split(',', $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]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i'; |
||||
$regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i'; |
||||
for ($i=0, $j=0; $i<$count; ++$i) { |
||||
if (!preg_match($regexp, trim($column_sql[$i]), $matches)) { |
||||
if (!preg_match($regexp2, trim($column_sql[$i]))) { |
||||
continue; |
||||
} |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'unexpected table column SQL definition: "'.$column_sql[$i].'"', __FUNCTION__); |
||||
} |
||||
$columns[$j]['name'] = trim($matches[1], implode('', $db->identifier_quoting)); |
||||
$columns[$j]['type'] = strtolower($matches[2]); |
||||
if (isset($matches[4]) && strlen($matches[4])) { |
||||
$columns[$j]['length'] = $matches[4]; |
||||
} |
||||
if (isset($matches[6]) && strlen($matches[6])) { |
||||
$columns[$j]['decimal'] = $matches[6]; |
||||
} |
||||
if (isset($matches[8]) && strlen($matches[8])) { |
||||
$columns[$j]['unsigned'] = true; |
||||
} |
||||
if (isset($matches[9]) && strlen($matches[9])) { |
||||
$columns[$j]['autoincrement'] = true; |
||||
} |
||||
if (isset($matches[12]) && strlen($matches[12])) { |
||||
$default = $matches[12]; |
||||
if (strlen($default) && $default[0]=="'") { |
||||
$default = str_replace("''", "'", substr($default, 1, strlen($default)-2)); |
||||
} |
||||
if ($default === 'NULL') { |
||||
$default = null; |
||||
} |
||||
$columns[$j]['default'] = $default; |
||||
} |
||||
if (isset($matches[7]) && strlen($matches[7])) { |
||||
$columns[$j]['notnull'] = ($matches[7] === ' NOT NULL'); |
||||
} else if (isset($matches[9]) && strlen($matches[9])) { |
||||
$columns[$j]['notnull'] = ($matches[9] === ' NOT NULL'); |
||||
} else if (isset($matches[13]) && strlen($matches[13])) { |
||||
$columns[$j]['notnull'] = ($matches[13] === ' NOT NULL'); |
||||
} |
||||
++$j; |
||||
} |
||||
return $columns; |
||||
} |
||||
|
||||
// {{{ getTableFieldDefinition() |
||||
|
||||
/** |
||||
* Get the stucture of a field into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $field_name name of field that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure. |
||||
* The returned array contains an array for each field definition, |
||||
* with (some of) these indices: |
||||
* [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type] |
||||
* @access public |
||||
*/ |
||||
function getTableFieldDefinition($table_name, $field_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$result = $db->loadModule('Datatype', null, true); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text'); |
||||
} else { |
||||
$query.= 'name='.$db->quote($table, 'text'); |
||||
} |
||||
$sql = $db->queryOne($query); |
||||
if (PEAR::isError($sql)) { |
||||
return $sql; |
||||
} |
||||
$columns = $this->_getTableColumns($sql); |
||||
foreach ($columns as $column) { |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
if ($db->options['field_case'] == CASE_LOWER) { |
||||
$column['name'] = strtolower($column['name']); |
||||
} else { |
||||
$column['name'] = strtoupper($column['name']); |
||||
} |
||||
} else { |
||||
$column = array_change_key_case($column, $db->options['field_case']); |
||||
} |
||||
if ($field_name == $column['name']) { |
||||
$mapped_datatype = $db->datatype->mapNativeDatatype($column); |
||||
if (PEAR::isError($mapped_datatype)) { |
||||
return $mapped_datatype; |
||||
} |
||||
list($types, $length, $unsigned, $fixed) = $mapped_datatype; |
||||
$notnull = false; |
||||
if (!empty($column['notnull'])) { |
||||
$notnull = $column['notnull']; |
||||
} |
||||
$default = false; |
||||
if (array_key_exists('default', $column)) { |
||||
$default = $column['default']; |
||||
if (is_null($default) && $notnull) { |
||||
$default = ''; |
||||
} |
||||
} |
||||
$autoincrement = false; |
||||
if (!empty($column['autoincrement'])) { |
||||
$autoincrement = true; |
||||
} |
||||
|
||||
$definition[0] = array( |
||||
'notnull' => $notnull, |
||||
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type']) |
||||
); |
||||
if (!is_null($length)) { |
||||
$definition[0]['length'] = $length; |
||||
} |
||||
if (!is_null($unsigned)) { |
||||
$definition[0]['unsigned'] = $unsigned; |
||||
} |
||||
if (!is_null($fixed)) { |
||||
$definition[0]['fixed'] = $fixed; |
||||
} |
||||
if ($default !== false) { |
||||
$definition[0]['default'] = $default; |
||||
} |
||||
if ($autoincrement !== false) { |
||||
$definition[0]['autoincrement'] = $autoincrement; |
||||
} |
||||
foreach ($types as $key => $type) { |
||||
$definition[$key] = $definition[0]; |
||||
if ($type == 'clob' || $type == 'blob') { |
||||
unset($definition[$key]['default']); |
||||
} |
||||
$definition[$key]['type'] = $type; |
||||
$definition[$key]['mdb2type'] = $type; |
||||
} |
||||
return $definition; |
||||
} |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table column', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableIndexDefinition() |
||||
|
||||
/** |
||||
* Get the stucture of an index into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $index_name name of index that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableIndexDefinition($table_name, $index_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text'); |
||||
} else { |
||||
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text'); |
||||
} |
||||
$query.= ' AND sql NOT NULL ORDER BY name'; |
||||
$index_name_mdb2 = $db->getIndexName($index_name); |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$qry = sprintf($query, $db->quote(strtolower($index_name_mdb2), 'text')); |
||||
} else { |
||||
$qry = sprintf($query, $db->quote($index_name_mdb2, 'text')); |
||||
} |
||||
$sql = $db->queryOne($qry, 'text'); |
||||
if (PEAR::isError($sql) || empty($sql)) { |
||||
// fallback to the given $index_name, without transformation |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$qry = sprintf($query, $db->quote(strtolower($index_name), 'text')); |
||||
} else { |
||||
$qry = sprintf($query, $db->quote($index_name, 'text')); |
||||
} |
||||
$sql = $db->queryOne($qry, 'text'); |
||||
} |
||||
if (PEAR::isError($sql)) { |
||||
return $sql; |
||||
} |
||||
if (!$sql) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table index', __FUNCTION__); |
||||
} |
||||
|
||||
$sql = strtolower($sql); |
||||
$start_pos = strpos($sql, '('); |
||||
$end_pos = strrpos($sql, ')'); |
||||
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1); |
||||
$column_names = split(',', $column_names); |
||||
|
||||
if (preg_match("/^create unique/", $sql)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table index', __FUNCTION__); |
||||
} |
||||
|
||||
$definition = array(); |
||||
$count = count($column_names); |
||||
for ($i=0; $i<$count; ++$i) { |
||||
$column_name = strtok($column_names[$i], ' '); |
||||
$collation = strtok(' '); |
||||
$definition['fields'][$column_name] = array( |
||||
'position' => $i+1 |
||||
); |
||||
if (!empty($collation)) { |
||||
$definition['fields'][$column_name]['sorting'] = |
||||
($collation=='ASC' ? 'ascending' : 'descending'); |
||||
} |
||||
} |
||||
|
||||
if (empty($definition['fields'])) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table index', __FUNCTION__); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableConstraintDefinition() |
||||
|
||||
/** |
||||
* Get the stucture of a constraint into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $constraint_name name of constraint that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableConstraintDefinition($table_name, $constraint_name) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text'); |
||||
} else { |
||||
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text'); |
||||
} |
||||
$query.= ' AND sql NOT NULL ORDER BY name'; |
||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name); |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text')); |
||||
} else { |
||||
$qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text')); |
||||
} |
||||
$sql = $db->queryOne($qry, 'text'); |
||||
if (PEAR::isError($sql) || empty($sql)) { |
||||
// fallback to the given $index_name, without transformation |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text')); |
||||
} else { |
||||
$qry = sprintf($query, $db->quote($constraint_name, 'text')); |
||||
} |
||||
$sql = $db->queryOne($qry, 'text'); |
||||
} |
||||
if (PEAR::isError($sql)) { |
||||
return $sql; |
||||
} |
||||
//default values, eventually overridden |
||||
$definition = array( |
||||
'primary' => false, |
||||
'unique' => false, |
||||
'foreign' => false, |
||||
'check' => false, |
||||
'fields' => array(), |
||||
'references' => array( |
||||
'table' => '', |
||||
'fields' => array(), |
||||
), |
||||
'onupdate' => '', |
||||
'ondelete' => '', |
||||
'match' => '', |
||||
'deferrable' => false, |
||||
'initiallydeferred' => false, |
||||
); |
||||
if (!$sql) { |
||||
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text'); |
||||
} else { |
||||
$query.= 'name='.$db->quote($table, 'text'); |
||||
} |
||||
$query.= " AND sql NOT NULL ORDER BY name"; |
||||
$sql = $db->queryOne($query, 'text'); |
||||
if (PEAR::isError($sql)) { |
||||
return $sql; |
||||
} |
||||
if ($constraint_name == 'primary') { |
||||
// search in table definition for PRIMARY KEYs |
||||
if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) { |
||||
$definition['primary'] = true; |
||||
$definition['fields'] = array(); |
||||
$column_names = split(',', $tmp[1]); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
return $definition; |
||||
} |
||||
if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) { |
||||
$definition['primary'] = true; |
||||
$definition['fields'] = array(); |
||||
$column_names = split(',', $tmp[1]); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
return $definition; |
||||
} |
||||
} else { |
||||
// search in table definition for FOREIGN KEYs |
||||
$pattern = "/\bCONSTRAINT\b\s+%s\s+ |
||||
\bFOREIGN\s+KEY\b\s*\(([^\)]+)\)\s* |
||||
\bREFERENCES\b\s+([^\s]+)\s*\(([^\)]+)\)\s* |
||||
(?:\bMATCH\s*([^\s]+))?\s* |
||||
(?:\bON\s+UPDATE\s+([^\s,\)]+))?\s* |
||||
(?:\bON\s+DELETE\s+([^\s,\)]+))?\s* |
||||
/imsx"; |
||||
$found_fk = false; |
||||
if (preg_match(sprintf($pattern, $constraint_name_mdb2), $sql, $tmp)) { |
||||
$found_fk = true; |
||||
} elseif (preg_match(sprintf($pattern, $constraint_name), $sql, $tmp)) { |
||||
$found_fk = true; |
||||
} |
||||
if ($found_fk) { |
||||
$definition['foreign'] = true; |
||||
$definition['match'] = 'SIMPLE'; |
||||
$definition['onupdate'] = 'NO ACTION'; |
||||
$definition['ondelete'] = 'NO ACTION'; |
||||
$definition['references']['table'] = $tmp[2]; |
||||
$column_names = split(',', $tmp[1]); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
$referenced_cols = split(',', $tmp[3]); |
||||
$colpos = 1; |
||||
foreach ($referenced_cols as $column_name) { |
||||
$definition['references']['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
if (isset($tmp[4])) { |
||||
$definition['match'] = $tmp[4]; |
||||
} |
||||
if (isset($tmp[5])) { |
||||
$definition['onupdate'] = $tmp[5]; |
||||
} |
||||
if (isset($tmp[6])) { |
||||
$definition['ondelete'] = $tmp[6]; |
||||
} |
||||
return $definition; |
||||
} |
||||
} |
||||
$sql = false; |
||||
} |
||||
if (!$sql) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
|
||||
$sql = strtolower($sql); |
||||
$start_pos = strpos($sql, '('); |
||||
$end_pos = strrpos($sql, ')'); |
||||
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1); |
||||
$column_names = split(',', $column_names); |
||||
|
||||
if (!preg_match("/^create unique/", $sql)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
|
||||
$definition['unique'] = true; |
||||
$count = count($column_names); |
||||
for ($i=0; $i<$count; ++$i) { |
||||
$column_name = strtok($column_names[$i]," "); |
||||
$collation = strtok(" "); |
||||
$definition['fields'][$column_name] = array( |
||||
'position' => $i+1 |
||||
); |
||||
if (!empty($collation)) { |
||||
$definition['fields'][$column_name]['sorting'] = |
||||
($collation=='ASC' ? 'ascending' : 'descending'); |
||||
} |
||||
} |
||||
|
||||
if (empty($definition['fields'])) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTriggerDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a trigger into an array |
||||
* |
||||
* EXPERIMENTAL |
||||
* |
||||
* WARNING: this function is experimental and may change the returned value |
||||
* at any time until labelled as non-experimental |
||||
* |
||||
* @param string $trigger name of trigger that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTriggerDefinition($trigger) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = "SELECT name as trigger_name, |
||||
tbl_name AS table_name, |
||||
sql AS trigger_body, |
||||
NULL AS trigger_type, |
||||
NULL AS trigger_event, |
||||
NULL AS trigger_comment, |
||||
1 AS trigger_enabled |
||||
FROM sqlite_master |
||||
WHERE type='trigger'"; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text'); |
||||
} else { |
||||
$query.= ' AND name='.$db->quote($trigger, 'text'); |
||||
} |
||||
$types = array( |
||||
'trigger_name' => 'text', |
||||
'table_name' => 'text', |
||||
'trigger_body' => 'text', |
||||
'trigger_type' => 'text', |
||||
'trigger_event' => 'text', |
||||
'trigger_comment' => 'text', |
||||
'trigger_enabled' => 'boolean', |
||||
); |
||||
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($def)) { |
||||
return $def; |
||||
} |
||||
if (empty($def)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing trigger', __FUNCTION__); |
||||
} |
||||
if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) { |
||||
$def['trigger_type'] = strtoupper($tmp[1]); |
||||
$def['trigger_event'] = strtoupper($tmp[2]); |
||||
} |
||||
return $def; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ tableInfo() |
||||
|
||||
/** |
||||
* Returns information about a table |
||||
* |
||||
* @param string $result a string containing the name of a table |
||||
* @param int $mode a valid tableInfo mode |
||||
* |
||||
* @return array an associative array with the information requested. |
||||
* A MDB2_Error object on failure. |
||||
* |
||||
* @see MDB2_Driver_Common::tableInfo() |
||||
* @since Method available since Release 1.7.0 |
||||
*/ |
||||
function tableInfo($result, $mode = null) |
||||
{ |
||||
if (is_string($result)) { |
||||
return parent::tableInfo($result, $mode); |
||||
} |
||||
|
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null, |
||||
'This DBMS can not obtain tableInfo from result sets', __FUNCTION__); |
||||
} |
||||
} |
||||
|
||||
?> |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,721 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP versions 4 and 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: Extended.php,v 1.60 2007/11/28 19:49:34 quipo Exp $ |
||||
|
||||
/** |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
|
||||
/** |
||||
* Used by autoPrepare() |
||||
*/ |
||||
define('MDB2_AUTOQUERY_INSERT', 1); |
||||
define('MDB2_AUTOQUERY_UPDATE', 2); |
||||
define('MDB2_AUTOQUERY_DELETE', 3); |
||||
define('MDB2_AUTOQUERY_SELECT', 4); |
||||
|
||||
/** |
||||
* MDB2_Extended: class which adds several high level methods to MDB2 |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Extended extends MDB2_Module_Common |
||||
{ |
||||
// {{{ autoPrepare() |
||||
|
||||
/** |
||||
* Generate an insert, update or delete query and call prepare() on it |
||||
* |
||||
* @param string table |
||||
* @param array the fields names |
||||
* @param int type of query to build |
||||
* MDB2_AUTOQUERY_INSERT |
||||
* MDB2_AUTOQUERY_UPDATE |
||||
* MDB2_AUTOQUERY_DELETE |
||||
* MDB2_AUTOQUERY_SELECT |
||||
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement) |
||||
* @param array that contains the types of the placeholders |
||||
* @param mixed array that contains the types of the columns in |
||||
* the result set or MDB2_PREPARE_RESULT, if set to |
||||
* MDB2_PREPARE_MANIP the query is handled as a manipulation query |
||||
* |
||||
* @return resource handle for the query |
||||
* @see buildManipSQL |
||||
* @access public |
||||
*/ |
||||
function autoPrepare($table, $table_fields, $mode = MDB2_AUTOQUERY_INSERT, |
||||
$where = false, $types = null, $result_types = MDB2_PREPARE_MANIP) |
||||
{ |
||||
$query = $this->buildManipSQL($table, $table_fields, $mode, $where); |
||||
if (PEAR::isError($query)) { |
||||
return $query; |
||||
} |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
$lobs = array(); |
||||
foreach ((array)$types as $param => $type) { |
||||
if (($type == 'clob') || ($type == 'blob')) { |
||||
$lobs[$param] = $table_fields[$param]; |
||||
} |
||||
} |
||||
return $db->prepare($query, $types, $result_types, $lobs); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ autoExecute() |
||||
|
||||
/** |
||||
* Generate an insert, update or delete query and call prepare() and execute() on it |
||||
* |
||||
* @param string name of the table |
||||
* @param array assoc ($key=>$value) where $key is a field name and $value its value |
||||
* @param int type of query to build |
||||
* MDB2_AUTOQUERY_INSERT |
||||
* MDB2_AUTOQUERY_UPDATE |
||||
* MDB2_AUTOQUERY_DELETE |
||||
* MDB2_AUTOQUERY_SELECT |
||||
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement) |
||||
* @param array that contains the types of the placeholders |
||||
* @param string which specifies which result class to use |
||||
* @param mixed array that contains the types of the columns in |
||||
* the result set or MDB2_PREPARE_RESULT, if set to |
||||
* MDB2_PREPARE_MANIP the query is handled as a manipulation query |
||||
* |
||||
* @return bool|MDB2_Error true on success, a MDB2 error on failure |
||||
* @see buildManipSQL |
||||
* @see autoPrepare |
||||
* @access public |
||||
*/ |
||||
function &autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT, |
||||
$where = false, $types = null, $result_class = true, $result_types = MDB2_PREPARE_MANIP) |
||||
{ |
||||
$fields_values = (array)$fields_values; |
||||
if ($mode == MDB2_AUTOQUERY_SELECT) { |
||||
if (is_array($result_types)) { |
||||
$keys = array_keys($result_types); |
||||
} elseif (!empty($fields_values)) { |
||||
$keys = $fields_values; |
||||
} else { |
||||
$keys = array(); |
||||
} |
||||
} else { |
||||
$keys = array_keys($fields_values); |
||||
} |
||||
$params = array_values($fields_values); |
||||
if (empty($params)) { |
||||
$query = $this->buildManipSQL($table, $keys, $mode, $where); |
||||
|
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
if ($mode == MDB2_AUTOQUERY_SELECT) { |
||||
$result =& $db->query($query, $result_types, $result_class); |
||||
} else { |
||||
$result = $db->exec($query); |
||||
} |
||||
} else { |
||||
$stmt = $this->autoPrepare($table, $keys, $mode, $where, $types, $result_types); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
$result =& $stmt->execute($params, $result_class); |
||||
$stmt->free(); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ buildManipSQL() |
||||
|
||||
/** |
||||
* Make automaticaly an sql query for prepare() |
||||
* |
||||
* Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), MDB2_AUTOQUERY_INSERT) |
||||
* will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) |
||||
* NB : - This belongs more to a SQL Builder class, but this is a simple facility |
||||
* - Be carefull ! If you don't give a $where param with an UPDATE/DELETE query, all |
||||
* the records of the table will be updated/deleted ! |
||||
* |
||||
* @param string name of the table |
||||
* @param ordered array containing the fields names |
||||
* @param int type of query to build |
||||
* MDB2_AUTOQUERY_INSERT |
||||
* MDB2_AUTOQUERY_UPDATE |
||||
* MDB2_AUTOQUERY_DELETE |
||||
* MDB2_AUTOQUERY_SELECT |
||||
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement) |
||||
* |
||||
* @return string sql query for prepare() |
||||
* @access public |
||||
*/ |
||||
function buildManipSQL($table, $table_fields, $mode, $where = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
if ($db->options['quote_identifier']) { |
||||
$table = $db->quoteIdentifier($table); |
||||
} |
||||
|
||||
if (!empty($table_fields) && $db->options['quote_identifier']) { |
||||
foreach ($table_fields as $key => $field) { |
||||
$table_fields[$key] = $db->quoteIdentifier($field); |
||||
} |
||||
} |
||||
|
||||
if ($where !== false && !is_null($where)) { |
||||
if (is_array($where)) { |
||||
$where = implode(' AND ', $where); |
||||
} |
||||
$where = ' WHERE '.$where; |
||||
} |
||||
|
||||
switch ($mode) { |
||||
case MDB2_AUTOQUERY_INSERT: |
||||
if (empty($table_fields)) { |
||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, |
||||
'Insert requires table fields', __FUNCTION__); |
||||
} |
||||
$cols = implode(', ', $table_fields); |
||||
$values = '?'.str_repeat(', ?', (count($table_fields) - 1)); |
||||
return 'INSERT INTO '.$table.' ('.$cols.') VALUES ('.$values.')'; |
||||
break; |
||||
case MDB2_AUTOQUERY_UPDATE: |
||||
if (empty($table_fields)) { |
||||
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null, |
||||
'Update requires table fields', __FUNCTION__); |
||||
} |
||||
$set = implode(' = ?, ', $table_fields).' = ?'; |
||||
$sql = 'UPDATE '.$table.' SET '.$set.$where; |
||||
return $sql; |
||||
break; |
||||
case MDB2_AUTOQUERY_DELETE: |
||||
$sql = 'DELETE FROM '.$table.$where; |
||||
return $sql; |
||||
break; |
||||
case MDB2_AUTOQUERY_SELECT: |
||||
$cols = !empty($table_fields) ? implode(', ', $table_fields) : '*'; |
||||
$sql = 'SELECT '.$cols.' FROM '.$table.$where; |
||||
return $sql; |
||||
break; |
||||
} |
||||
return $db->raiseError(MDB2_ERROR_SYNTAX, null, null, |
||||
'Non existant mode', __FUNCTION__); |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ limitQuery() |
||||
|
||||
/** |
||||
* Generates a limited query |
||||
* |
||||
* @param string query |
||||
* @param array that contains the types of the columns in the result set |
||||
* @param integer the numbers of rows to fetch |
||||
* @param integer the row to start to fetching |
||||
* @param string which specifies which result class to use |
||||
* @param mixed string which specifies which class to wrap results in |
||||
* |
||||
* @return MDB2_Result|MDB2_Error result set on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function &limitQuery($query, $types, $limit, $offset = 0, $result_class = true, |
||||
$result_wrap_class = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$result = $db->setLimit($limit, $offset); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
$result =& $db->query($query, $types, $result_class, $result_wrap_class); |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ execParam() |
||||
|
||||
/** |
||||
* Execute a parameterized DML statement. |
||||
* |
||||
* @param string the SQL query |
||||
* @param array if supplied, prepare/execute will be used |
||||
* with this array as execute parameters |
||||
* @param array that contains the types of the values defined in $params |
||||
* |
||||
* @return int|MDB2_Error affected rows on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function execParam($query, $params = array(), $param_types = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
settype($params, 'array'); |
||||
if (empty($params)) { |
||||
return $db->exec($query); |
||||
} |
||||
|
||||
$stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
|
||||
$result = $stmt->execute($params); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$stmt->free(); |
||||
return $result; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getOne() |
||||
|
||||
/** |
||||
* Fetch the first column of the first row of data returned from a query. |
||||
* Takes care of doing the query and freeing the results when finished. |
||||
* |
||||
* @param string the SQL query |
||||
* @param string that contains the type of the column in the result set |
||||
* @param array if supplied, prepare/execute will be used |
||||
* with this array as execute parameters |
||||
* @param array that contains the types of the values defined in $params |
||||
* @param int|string which column to return |
||||
* |
||||
* @return scalar|MDB2_Error data on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getOne($query, $type = null, $params = array(), |
||||
$param_types = null, $colnum = 0) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
settype($params, 'array'); |
||||
settype($type, 'array'); |
||||
if (empty($params)) { |
||||
return $db->queryOne($query, $type, $colnum); |
||||
} |
||||
|
||||
$stmt = $db->prepare($query, $param_types, $type); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
|
||||
$result = $stmt->execute($params); |
||||
if (!MDB2::isResultCommon($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$one = $result->fetchOne($colnum); |
||||
$stmt->free(); |
||||
$result->free(); |
||||
return $one; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getRow() |
||||
|
||||
/** |
||||
* Fetch the first row of data returned from a query. Takes care |
||||
* of doing the query and freeing the results when finished. |
||||
* |
||||
* @param string the SQL query |
||||
* @param array that contains the types of the columns in the result set |
||||
* @param array if supplied, prepare/execute will be used |
||||
* with this array as execute parameters |
||||
* @param array that contains the types of the values defined in $params |
||||
* @param int the fetch mode to use |
||||
* |
||||
* @return array|MDB2_Error data on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getRow($query, $types = null, $params = array(), |
||||
$param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
settype($params, 'array'); |
||||
if (empty($params)) { |
||||
return $db->queryRow($query, $types, $fetchmode); |
||||
} |
||||
|
||||
$stmt = $db->prepare($query, $param_types, $types); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
|
||||
$result = $stmt->execute($params); |
||||
if (!MDB2::isResultCommon($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$row = $result->fetchRow($fetchmode); |
||||
$stmt->free(); |
||||
$result->free(); |
||||
return $row; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getCol() |
||||
|
||||
/** |
||||
* Fetch a single column from a result set and return it as an |
||||
* indexed array. |
||||
* |
||||
* @param string the SQL query |
||||
* @param string that contains the type of the column in the result set |
||||
* @param array if supplied, prepare/execute will be used |
||||
* with this array as execute parameters |
||||
* @param array that contains the types of the values defined in $params |
||||
* @param int|string which column to return |
||||
* |
||||
* @return array|MDB2_Error data on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getCol($query, $type = null, $params = array(), |
||||
$param_types = null, $colnum = 0) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
settype($params, 'array'); |
||||
settype($type, 'array'); |
||||
if (empty($params)) { |
||||
return $db->queryCol($query, $type, $colnum); |
||||
} |
||||
|
||||
$stmt = $db->prepare($query, $param_types, $type); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
|
||||
$result = $stmt->execute($params); |
||||
if (!MDB2::isResultCommon($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$col = $result->fetchCol($colnum); |
||||
$stmt->free(); |
||||
$result->free(); |
||||
return $col; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getAll() |
||||
|
||||
/** |
||||
* Fetch all the rows returned from a query. |
||||
* |
||||
* @param string the SQL query |
||||
* @param array that contains the types of the columns in the result set |
||||
* @param array if supplied, prepare/execute will be used |
||||
* with this array as execute parameters |
||||
* @param array that contains the types of the values defined in $params |
||||
* @param int the fetch mode to use |
||||
* @param bool if set to true, the $all will have the first |
||||
* column as its first dimension |
||||
* @param bool $force_array used only when the query returns exactly |
||||
* two columns. If true, the values of the returned array will be |
||||
* one-element arrays instead of scalars. |
||||
* @param bool $group if true, the values of the returned array is |
||||
* wrapped in another array. If the same key value (in the first |
||||
* column) repeats itself, the values will be appended to this array |
||||
* instead of overwriting the existing values. |
||||
* |
||||
* @return array|MDB2_Error data on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getAll($query, $types = null, $params = array(), |
||||
$param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT, |
||||
$rekey = false, $force_array = false, $group = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
settype($params, 'array'); |
||||
if (empty($params)) { |
||||
return $db->queryAll($query, $types, $fetchmode, $rekey, $force_array, $group); |
||||
} |
||||
|
||||
$stmt = $db->prepare($query, $param_types, $types); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
|
||||
$result = $stmt->execute($params); |
||||
if (!MDB2::isResultCommon($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$all = $result->fetchAll($fetchmode, $rekey, $force_array, $group); |
||||
$stmt->free(); |
||||
$result->free(); |
||||
return $all; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getAssoc() |
||||
|
||||
/** |
||||
* Fetch the entire result set of a query and return it as an |
||||
* associative array using the first column as the key. |
||||
* |
||||
* If the result set contains more than two columns, the value |
||||
* will be an array of the values from column 2-n. If the result |
||||
* set contains only two columns, the returned value will be a |
||||
* scalar with the value of the second column (unless forced to an |
||||
* array with the $force_array parameter). A MDB2 error code is |
||||
* returned on errors. If the result set contains fewer than two |
||||
* columns, a MDB2_ERROR_TRUNCATED error is returned. |
||||
* |
||||
* For example, if the table 'mytable' contains: |
||||
* <pre> |
||||
* ID TEXT DATE |
||||
* -------------------------------- |
||||
* 1 'one' 944679408 |
||||
* 2 'two' 944679408 |
||||
* 3 'three' 944679408 |
||||
* </pre> |
||||
* Then the call getAssoc('SELECT id,text FROM mytable') returns: |
||||
* <pre> |
||||
* array( |
||||
* '1' => 'one', |
||||
* '2' => 'two', |
||||
* '3' => 'three', |
||||
* ) |
||||
* </pre> |
||||
* ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: |
||||
* <pre> |
||||
* array( |
||||
* '1' => array('one', '944679408'), |
||||
* '2' => array('two', '944679408'), |
||||
* '3' => array('three', '944679408') |
||||
* ) |
||||
* </pre> |
||||
* |
||||
* If the more than one row occurs with the same value in the |
||||
* first column, the last row overwrites all previous ones by |
||||
* default. Use the $group parameter if you don't want to |
||||
* overwrite like this. Example: |
||||
* <pre> |
||||
* getAssoc('SELECT category,id,name FROM mytable', null, null |
||||
* MDB2_FETCHMODE_ASSOC, false, true) returns: |
||||
* array( |
||||
* '1' => array(array('id' => '4', 'name' => 'number four'), |
||||
* array('id' => '6', 'name' => 'number six') |
||||
* ), |
||||
* '9' => array(array('id' => '4', 'name' => 'number four'), |
||||
* array('id' => '6', 'name' => 'number six') |
||||
* ) |
||||
* ) |
||||
* </pre> |
||||
* |
||||
* Keep in mind that database functions in PHP usually return string |
||||
* values for results regardless of the database's internal type. |
||||
* |
||||
* @param string the SQL query |
||||
* @param array that contains the types of the columns in the result set |
||||
* @param array if supplied, prepare/execute will be used |
||||
* with this array as execute parameters |
||||
* @param array that contains the types of the values defined in $params |
||||
* @param bool $force_array used only when the query returns |
||||
* exactly two columns. If TRUE, the values of the returned array |
||||
* will be one-element arrays instead of scalars. |
||||
* @param bool $group if TRUE, the values of the returned array |
||||
* is wrapped in another array. If the same key value (in the first |
||||
* column) repeats itself, the values will be appended to this array |
||||
* instead of overwriting the existing values. |
||||
* |
||||
* @return array|MDB2_Error data on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getAssoc($query, $types = null, $params = array(), $param_types = null, |
||||
$fetchmode = MDB2_FETCHMODE_DEFAULT, $force_array = false, $group = false) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
settype($params, 'array'); |
||||
if (empty($params)) { |
||||
return $db->queryAll($query, $types, $fetchmode, true, $force_array, $group); |
||||
} |
||||
|
||||
$stmt = $db->prepare($query, $param_types, $types); |
||||
if (PEAR::isError($stmt)) { |
||||
return $stmt; |
||||
} |
||||
|
||||
$result = $stmt->execute($params); |
||||
if (!MDB2::isResultCommon($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$all = $result->fetchAll($fetchmode, true, $force_array, $group); |
||||
$stmt->free(); |
||||
$result->free(); |
||||
return $all; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ executeMultiple() |
||||
|
||||
/** |
||||
* This function does several execute() calls on the same statement handle. |
||||
* $params must be an array indexed numerically from 0, one execute call is |
||||
* done for every 'row' in the array. |
||||
* |
||||
* If an error occurs during execute(), executeMultiple() does not execute |
||||
* the unfinished rows, but rather returns that error. |
||||
* |
||||
* @param resource query handle from prepare() |
||||
* @param array numeric array containing the data to insert into the query |
||||
* |
||||
* @return bool|MDB2_Error true on success, a MDB2 error on failure |
||||
* @access public |
||||
* @see prepare(), execute() |
||||
*/ |
||||
function executeMultiple(&$stmt, $params = null) |
||||
{ |
||||
for ($i = 0, $j = count($params); $i < $j; $i++) { |
||||
$result = $stmt->execute($params[$i]); |
||||
if (PEAR::isError($result)) { |
||||
return $result; |
||||
} |
||||
} |
||||
return MDB2_OK; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getBeforeID() |
||||
|
||||
/** |
||||
* Returns the next free id of a sequence if the RDBMS |
||||
* does not support auto increment |
||||
* |
||||
* @param string name of the table into which a new row was inserted |
||||
* @param string name of the field into which a new row was inserted |
||||
* @param bool when true the sequence is automatic created, if it not exists |
||||
* @param bool if the returned value should be quoted |
||||
* |
||||
* @return int|MDB2_Error id on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getBeforeID($table, $field = null, $ondemand = true, $quote = true) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
if ($db->supports('auto_increment') !== true) { |
||||
$seq = $table.(empty($field) ? '' : '_'.$field); |
||||
$id = $db->nextID($seq, $ondemand); |
||||
if (!$quote || PEAR::isError($id)) { |
||||
return $id; |
||||
} |
||||
return $db->quote($id, 'integer'); |
||||
} elseif (!$quote) { |
||||
return null; |
||||
} |
||||
return 'NULL'; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getAfterID() |
||||
|
||||
/** |
||||
* Returns the autoincrement ID if supported or $id |
||||
* |
||||
* @param mixed value as returned by getBeforeId() |
||||
* @param string name of the table into which a new row was inserted |
||||
* @param string name of the field into which a new row was inserted |
||||
* |
||||
* @return int|MDB2_Error id on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getAfterID($id, $table, $field = null) |
||||
{ |
||||
$db =& $this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
if ($db->supports('auto_increment') !== true) { |
||||
return $id; |
||||
} |
||||
return $db->lastInsertID($table, $field); |
||||
} |
||||
|
||||
// }}} |
||||
} |
||||
?> |
||||
@ -0,0 +1,259 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP version 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: Iterator.php,v 1.22 2006/05/06 14:03:41 lsmith Exp $ |
||||
|
||||
/** |
||||
* PHP5 Iterator |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Iterator implements Iterator |
||||
{ |
||||
protected $fetchmode; |
||||
protected $result; |
||||
protected $row; |
||||
|
||||
// {{{ constructor |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
public function __construct($result, $fetchmode = MDB2_FETCHMODE_DEFAULT) |
||||
{ |
||||
$this->result = $result; |
||||
$this->fetchmode = $fetchmode; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ seek() |
||||
|
||||
/** |
||||
* Seek forward to a specific row in a result set |
||||
* |
||||
* @param int number of the row where the data can be found |
||||
* |
||||
* @return void |
||||
* @access public |
||||
*/ |
||||
public function seek($rownum) |
||||
{ |
||||
$this->row = null; |
||||
if ($this->result) { |
||||
$this->result->seek($rownum); |
||||
} |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ next() |
||||
|
||||
/** |
||||
* Fetch next row of data |
||||
* |
||||
* @return void |
||||
* @access public |
||||
*/ |
||||
public function next() |
||||
{ |
||||
$this->row = null; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ current() |
||||
|
||||
/** |
||||
* return a row of data |
||||
* |
||||
* @return void |
||||
* @access public |
||||
*/ |
||||
public function current() |
||||
{ |
||||
if (is_null($this->row)) { |
||||
$row = $this->result->fetchRow($this->fetchmode); |
||||
if (PEAR::isError($row)) { |
||||
$row = false; |
||||
} |
||||
$this->row = $row; |
||||
} |
||||
return $this->row; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ valid() |
||||
|
||||
/** |
||||
* Check if the end of the result set has been reached |
||||
* |
||||
* @return bool true/false, false is also returned on failure |
||||
* @access public |
||||
*/ |
||||
public function valid() |
||||
{ |
||||
return (bool)$this->current(); |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ free() |
||||
|
||||
/** |
||||
* Free the internal resources associated with result. |
||||
* |
||||
* @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid |
||||
* @access public |
||||
*/ |
||||
public function free() |
||||
{ |
||||
if ($this->result) { |
||||
return $this->result->free(); |
||||
} |
||||
$this->result = false; |
||||
$this->row = null; |
||||
return false; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ key() |
||||
|
||||
/** |
||||
* Returns the row number |
||||
* |
||||
* @return int|bool|MDB2_Error true on success, false|MDB2_Error if result is invalid |
||||
* @access public |
||||
*/ |
||||
public function key() |
||||
{ |
||||
if ($this->result) { |
||||
return $this->result->rowCount(); |
||||
} |
||||
return false; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ rewind() |
||||
|
||||
/** |
||||
* Seek to the first row in a result set |
||||
* |
||||
* @return void |
||||
* @access public |
||||
*/ |
||||
public function rewind() |
||||
{ |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ destructor |
||||
|
||||
/** |
||||
* Destructor |
||||
*/ |
||||
public function __destruct() |
||||
{ |
||||
$this->free(); |
||||
} |
||||
// }}} |
||||
} |
||||
|
||||
/** |
||||
* PHP5 buffered Iterator |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_BufferedIterator extends MDB2_Iterator implements SeekableIterator |
||||
{ |
||||
// {{{ valid() |
||||
|
||||
/** |
||||
* Check if the end of the result set has been reached |
||||
* |
||||
* @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid |
||||
* @access public |
||||
*/ |
||||
public function valid() |
||||
{ |
||||
if ($this->result) { |
||||
return $this->result->valid(); |
||||
} |
||||
return false; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{count() |
||||
|
||||
/** |
||||
* Returns the number of rows in a result object |
||||
* |
||||
* @return int|MDB2_Error number of rows, false|MDB2_Error if result is invalid |
||||
* @access public |
||||
*/ |
||||
public function count() |
||||
{ |
||||
if ($this->result) { |
||||
return $this->result->numRows(); |
||||
} |
||||
return false; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ rewind() |
||||
|
||||
/** |
||||
* Seek to the first row in a result set |
||||
* |
||||
* @return void |
||||
* @access public |
||||
*/ |
||||
public function rewind() |
||||
{ |
||||
$this->seek(0); |
||||
} |
||||
// }}} |
||||
} |
||||
|
||||
?> |
||||
@ -0,0 +1,264 @@ |
||||
<?php |
||||
// +----------------------------------------------------------------------+ |
||||
// | PHP version 5 | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
||||
// | Stig. S. Bakken, Lukas Smith | |
||||
// | All rights reserved. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB | |
||||
// | API as well as database abstraction for PHP applications. | |
||||
// | This LICENSE is in the BSD license style. | |
||||
// | | |
||||
// | Redistribution and use in source and binary forms, with or without | |
||||
// | modification, are permitted provided that the following conditions | |
||||
// | are met: | |
||||
// | | |
||||
// | Redistributions of source code must retain the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer. | |
||||
// | | |
||||
// | Redistributions in binary form must reproduce the above copyright | |
||||
// | notice, this list of conditions and the following disclaimer in the | |
||||
// | documentation and/or other materials provided with the distribution. | |
||||
// | | |
||||
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, | |
||||
// | Lukas Smith nor the names of his contributors may be used to endorse | |
||||
// | or promote products derived from this software without specific prior| |
||||
// | written permission. | |
||||
// | | |
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
||||
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
||||
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
||||
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
||||
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS| |
||||
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
||||
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
||||
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY| |
||||
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
||||
// | POSSIBILITY OF SUCH DAMAGE. | |
||||
// +----------------------------------------------------------------------+ |
||||
// | Author: Lukas Smith <smith@pooteeweet.org> | |
||||
// +----------------------------------------------------------------------+ |
||||
// |
||||
// $Id: LOB.php,v 1.34 2006/10/25 11:52:21 lsmith Exp $ |
||||
|
||||
/** |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
|
||||
require_once 'MDB2.php'; |
||||
|
||||
/** |
||||
* MDB2_LOB: user land stream wrapper implementation for LOB support |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_LOB |
||||
{ |
||||
/** |
||||
* contains the key to the global MDB2 instance array of the associated |
||||
* MDB2 instance |
||||
* |
||||
* @var integer |
||||
* @access protected |
||||
*/ |
||||
var $db_index; |
||||
|
||||
/** |
||||
* contains the key to the global MDB2_LOB instance array of the associated |
||||
* MDB2_LOB instance |
||||
* |
||||
* @var integer |
||||
* @access protected |
||||
*/ |
||||
var $lob_index; |
||||
|
||||
// {{{ stream_open() |
||||
|
||||
/** |
||||
* open stream |
||||
* |
||||
* @param string specifies the URL that was passed to fopen() |
||||
* @param string the mode used to open the file |
||||
* @param int holds additional flags set by the streams API |
||||
* @param string not used |
||||
* |
||||
* @return bool |
||||
* @access public |
||||
*/ |
||||
function stream_open($path, $mode, $options, &$opened_path) |
||||
{ |
||||
if (!preg_match('/^rb?\+?$/', $mode)) { |
||||
return false; |
||||
} |
||||
$url = parse_url($path); |
||||
if (empty($url['host'])) { |
||||
return false; |
||||
} |
||||
$this->db_index = (int)$url['host']; |
||||
if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
||||
return false; |
||||
} |
||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
||||
$this->lob_index = (int)$url['user']; |
||||
if (!isset($db->datatype->lobs[$this->lob_index])) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_read() |
||||
|
||||
/** |
||||
* read stream |
||||
* |
||||
* @param int number of bytes to read |
||||
* |
||||
* @return string |
||||
* @access public |
||||
*/ |
||||
function stream_read($count) |
||||
{ |
||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
||||
$db->datatype->_retrieveLOB($db->datatype->lobs[$this->lob_index]); |
||||
|
||||
$data = $db->datatype->_readLOB($db->datatype->lobs[$this->lob_index], $count); |
||||
$length = strlen($data); |
||||
if ($length == 0) { |
||||
$db->datatype->lobs[$this->lob_index]['endOfLOB'] = true; |
||||
} |
||||
$db->datatype->lobs[$this->lob_index]['position'] += $length; |
||||
return $data; |
||||
} |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_write() |
||||
|
||||
/** |
||||
* write stream, note implemented |
||||
* |
||||
* @param string data |
||||
* |
||||
* @return int |
||||
* @access public |
||||
*/ |
||||
function stream_write($data) |
||||
{ |
||||
return 0; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_tell() |
||||
|
||||
/** |
||||
* return the current position |
||||
* |
||||
* @return int current position |
||||
* @access public |
||||
*/ |
||||
function stream_tell() |
||||
{ |
||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
||||
return $db->datatype->lobs[$this->lob_index]['position']; |
||||
} |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_eof() |
||||
|
||||
/** |
||||
* Check if stream reaches EOF |
||||
* |
||||
* @return bool |
||||
* @access public |
||||
*/ |
||||
function stream_eof() |
||||
{ |
||||
if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
||||
return true; |
||||
} |
||||
|
||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
||||
$result = $db->datatype->_endOfLOB($db->datatype->lobs[$this->lob_index]); |
||||
if (version_compare(phpversion(), "5.0", ">=") |
||||
&& version_compare(phpversion(), "5.1", "<") |
||||
) { |
||||
return !$result; |
||||
} |
||||
return $result; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_seek() |
||||
|
||||
/** |
||||
* Seek stream, not implemented |
||||
* |
||||
* @param int offset |
||||
* @param int whence |
||||
* |
||||
* @return bool |
||||
* @access public |
||||
*/ |
||||
function stream_seek($offset, $whence) |
||||
{ |
||||
return false; |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_stat() |
||||
|
||||
/** |
||||
* return information about stream |
||||
* |
||||
* @access public |
||||
*/ |
||||
function stream_stat() |
||||
{ |
||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
||||
return array( |
||||
'db_index' => $this->db_index, |
||||
'lob_index' => $this->lob_index, |
||||
); |
||||
} |
||||
} |
||||
// }}} |
||||
|
||||
// {{{ stream_close() |
||||
|
||||
/** |
||||
* close stream |
||||
* |
||||
* @access public |
||||
*/ |
||||
function stream_close() |
||||
{ |
||||
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) { |
||||
$db =& $GLOBALS['_MDB2_databases'][$this->db_index]; |
||||
if (isset($db->datatype->lobs[$this->lob_index])) { |
||||
$db->datatype->_destroyLOB($db->datatype->lobs[$this->lob_index]); |
||||
unset($db->datatype->lobs[$this->lob_index]); |
||||
} |
||||
} |
||||
} |
||||
// }}} |
||||
} |
||||
|
||||
// register streams wrapper |
||||
if (!stream_wrapper_register("MDB2LOB", "MDB2_LOB")) { |
||||
MDB2::raiseError(); |
||||
return false; |
||||
} |
||||
|
||||
?> |
||||
Loading…
Reference in new issue