parent
e97c7ae806
commit
e1818675d2
@ -1,385 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Robin Appelman |
||||
* @copyright 2011 Robin Appelman icewind1991@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
require_once 'MDB2/Driver/Datatype/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 SQLite driver |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Datatype_sqlite3 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 AUTOINCREMENT'; |
||||
} 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); |
||||
if($autoinc) { |
||||
return $name.' '.$this->getTypeDeclaration($field).$autoinc; |
||||
}else{ |
||||
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); |
||||
} |
||||
|
||||
// }}} |
||||
} |
@ -1,136 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Robin Appelman |
||||
* @copyright 2011 Robin Appelman icewind1991@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
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_sqlite3 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 '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) |
||||
{ |
||||
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
@ -1,33 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Robin Appelman |
||||
* @copyright 2011 Robin Appelman icewind1991@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
require_once 'MDB2/Driver/Native/Common.php'; |
||||
|
||||
/** |
||||
* MDB2 SQLite driver for the native module |
||||
* |
||||
* @package MDB2 |
||||
* @category Database |
||||
* @author Lukas Smith <smith@pooteeweet.org> |
||||
*/ |
||||
class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common |
||||
{ |
||||
} |
@ -1,586 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Robin Appelman |
||||
* @copyright 2011 Robin Appelman icewind1991@gmail.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
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_sqlite3 extends MDB2_Driver_Reverse_Common |
||||
{ |
||||
/** |
||||
* Remove SQL comments from the field definition |
||||
* |
||||
* @access private |
||||
*/ |
||||
function _removeComments($sql) { |
||||
$lines = explode("\n", $sql); |
||||
foreach ($lines as $k => $line) { |
||||
$pieces = explode('--', $line); |
||||
if (count($pieces) > 1 && (substr_count($pieces[0], '\'') % 2) == 0) { |
||||
$lines[$k] = substr($line, 0, strpos($line, '--')); |
||||
} |
||||
} |
||||
return implode("\n", $lines); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
function _getTableColumns($sql) |
||||
{ |
||||
$db =$this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
$start_pos = strpos($sql, '('); |
||||
$end_pos = strrpos($sql, ')'); |
||||
$column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1); |
||||
// replace the decimal length-places-separator with a colon |
||||
$column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def); |
||||
$column_def = $this->_removeComments($column_def); |
||||
$column_sql = explode(',', $column_def); |
||||
$columns = array(); |
||||
$count = count($column_sql); |
||||
if ($count == 0) { |
||||
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
||||
'unexpected empty table column definition list', __FUNCTION__); |
||||
} |
||||
$regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|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)?( AUTOINCREMENT)?( 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[10]) && strlen($matches[10])) { |
||||
$columns[$j]['autoincrement'] = true; |
||||
$columns[$j]['notnull']=true; |
||||
} |
||||
if (isset($matches[10]) && strlen($matches[10])) { |
||||
$columns[$j]['autoincrement'] = true; |
||||
$columns[$j]['notnull']=true; |
||||
} |
||||
if (isset($matches[13]) && strlen($matches[13])) { |
||||
$default = $matches[13]; |
||||
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[14]) && strlen($matches[14])) { |
||||
$columns[$j]['notnull'] = ($matches[14] === ' 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 = explode(',', $column_names); |
||||
|
||||
if (preg_match("/^create unique/", $sql)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table index', __FUNCTION__); |
||||
} |
||||
|
||||
$definition = array(); |
||||
$count = count($column_names); |
||||
for ($i=0; $i<$count; ++$i) { |
||||
$column_name = strtok($column_names[$i], ' '); |
||||
$collation = strtok(' '); |
||||
$definition['fields'][$column_name] = array( |
||||
'position' => $i+1 |
||||
); |
||||
if (!empty($collation)) { |
||||
$definition['fields'][$column_name]['sorting'] = |
||||
($collation=='ASC' ? 'ascending' : 'descending'); |
||||
} |
||||
} |
||||
|
||||
if (empty($definition['fields'])) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing table index', __FUNCTION__); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTableConstraintDefinition() |
||||
|
||||
/** |
||||
* Get the stucture of a constraint into an array |
||||
* |
||||
* @param string $table_name name of table that should be used in method |
||||
* @param string $constraint_name name of constraint that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTableConstraintDefinition($table_name, $constraint_name) |
||||
{ |
||||
$db =$this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
list($schema, $table) = $this->splitTableSchema($table_name); |
||||
|
||||
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND "; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text'); |
||||
} else { |
||||
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text'); |
||||
} |
||||
$query.= ' AND sql NOT NULL ORDER BY name'; |
||||
$constraint_name_mdb2 = $db->getIndexName($constraint_name); |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text')); |
||||
} else { |
||||
$qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text')); |
||||
} |
||||
$sql = $db->queryOne($qry, 'text'); |
||||
if (PEAR::isError($sql) || empty($sql)) { |
||||
// fallback to the given $index_name, without transformation |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text')); |
||||
} else { |
||||
$qry = sprintf($query, $db->quote($constraint_name, 'text')); |
||||
} |
||||
$sql = $db->queryOne($qry, 'text'); |
||||
} |
||||
if (PEAR::isError($sql)) { |
||||
return $sql; |
||||
} |
||||
//default values, eventually overridden |
||||
$definition = array( |
||||
'primary' => false, |
||||
'unique' => false, |
||||
'foreign' => false, |
||||
'check' => false, |
||||
'fields' => array(), |
||||
'references' => array( |
||||
'table' => '', |
||||
'fields' => array(), |
||||
), |
||||
'onupdate' => '', |
||||
'ondelete' => '', |
||||
'match' => '', |
||||
'deferrable' => false, |
||||
'initiallydeferred' => false, |
||||
); |
||||
if (!$sql) { |
||||
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND "; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text'); |
||||
} else { |
||||
$query.= 'name='.$db->quote($table, 'text'); |
||||
} |
||||
$query.= " AND sql NOT NULL ORDER BY name"; |
||||
$sql = $db->queryOne($query, 'text'); |
||||
if (PEAR::isError($sql)) { |
||||
return $sql; |
||||
} |
||||
if ($constraint_name == 'primary') { |
||||
// search in table definition for PRIMARY KEYs |
||||
if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) { |
||||
$definition['primary'] = true; |
||||
$definition['fields'] = array(); |
||||
$column_names = explode(',', $tmp[1]); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
return $definition; |
||||
} |
||||
if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) { |
||||
$definition['primary'] = true; |
||||
$definition['fields'] = array(); |
||||
$column_names = explode(',', $tmp[1]); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
return $definition; |
||||
} |
||||
} else { |
||||
// search in table definition for FOREIGN KEYs |
||||
$pattern = "/\bCONSTRAINT\b\s+%s\s+ |
||||
\bFOREIGN\s+KEY\b\s*\(([^\)]+)\)\s* |
||||
\bREFERENCES\b\s+([^\s]+)\s*\(([^\)]+)\)\s* |
||||
(?:\bMATCH\s*([^\s]+))?\s* |
||||
(?:\bON\s+UPDATE\s+([^\s,\)]+))?\s* |
||||
(?:\bON\s+DELETE\s+([^\s,\)]+))?\s* |
||||
/imsx"; |
||||
$found_fk = false; |
||||
if (preg_match(sprintf($pattern, $constraint_name_mdb2), $sql, $tmp)) { |
||||
$found_fk = true; |
||||
} elseif (preg_match(sprintf($pattern, $constraint_name), $sql, $tmp)) { |
||||
$found_fk = true; |
||||
} |
||||
if ($found_fk) { |
||||
$definition['foreign'] = true; |
||||
$definition['match'] = 'SIMPLE'; |
||||
$definition['onupdate'] = 'NO ACTION'; |
||||
$definition['ondelete'] = 'NO ACTION'; |
||||
$definition['references']['table'] = $tmp[2]; |
||||
$column_names = explode(',', $tmp[1]); |
||||
$colpos = 1; |
||||
foreach ($column_names as $column_name) { |
||||
$definition['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
$referenced_cols = explode(',', $tmp[3]); |
||||
$colpos = 1; |
||||
foreach ($referenced_cols as $column_name) { |
||||
$definition['references']['fields'][trim($column_name)] = array( |
||||
'position' => $colpos++ |
||||
); |
||||
} |
||||
if (isset($tmp[4])) { |
||||
$definition['match'] = $tmp[4]; |
||||
} |
||||
if (isset($tmp[5])) { |
||||
$definition['onupdate'] = $tmp[5]; |
||||
} |
||||
if (isset($tmp[6])) { |
||||
$definition['ondelete'] = $tmp[6]; |
||||
} |
||||
return $definition; |
||||
} |
||||
} |
||||
$sql = false; |
||||
} |
||||
if (!$sql) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
|
||||
$sql = strtolower($sql); |
||||
$start_pos = strpos($sql, '('); |
||||
$end_pos = strrpos($sql, ')'); |
||||
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1); |
||||
$column_names = explode(',', $column_names); |
||||
|
||||
if (!preg_match("/^create unique/", $sql)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
|
||||
$definition['unique'] = true; |
||||
$count = count($column_names); |
||||
for ($i=0; $i<$count; ++$i) { |
||||
$column_name = strtok($column_names[$i], " "); |
||||
$collation = strtok(" "); |
||||
$definition['fields'][$column_name] = array( |
||||
'position' => $i+1 |
||||
); |
||||
if (!empty($collation)) { |
||||
$definition['fields'][$column_name]['sorting'] = |
||||
($collation=='ASC' ? 'ascending' : 'descending'); |
||||
} |
||||
} |
||||
|
||||
if (empty($definition['fields'])) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
$constraint_name . ' is not an existing table constraint', __FUNCTION__); |
||||
} |
||||
return $definition; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ getTriggerDefinition() |
||||
|
||||
/** |
||||
* Get the structure of a trigger into an array |
||||
* |
||||
* EXPERIMENTAL |
||||
* |
||||
* WARNING: this function is experimental and may change the returned value |
||||
* at any time until labelled as non-experimental |
||||
* |
||||
* @param string $trigger name of trigger that should be used in method |
||||
* @return mixed data array on success, a MDB2 error on failure |
||||
* @access public |
||||
*/ |
||||
function getTriggerDefinition($trigger) |
||||
{ |
||||
$db =$this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
$query = "SELECT name as trigger_name, |
||||
tbl_name AS table_name, |
||||
sql AS trigger_body, |
||||
NULL AS trigger_type, |
||||
NULL AS trigger_event, |
||||
NULL AS trigger_comment, |
||||
1 AS trigger_enabled |
||||
FROM sqlite_master |
||||
WHERE type='trigger'"; |
||||
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
||||
$query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text'); |
||||
} else { |
||||
$query.= ' AND name='.$db->quote($trigger, 'text'); |
||||
} |
||||
$types = array( |
||||
'trigger_name' => 'text', |
||||
'table_name' => 'text', |
||||
'trigger_body' => 'text', |
||||
'trigger_type' => 'text', |
||||
'trigger_event' => 'text', |
||||
'trigger_comment' => 'text', |
||||
'trigger_enabled' => 'boolean', |
||||
); |
||||
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC); |
||||
if (PEAR::isError($def)) { |
||||
return $def; |
||||
} |
||||
if (empty($def)) { |
||||
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
||||
'it was not specified an existing trigger', __FUNCTION__); |
||||
} |
||||
if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) { |
||||
$def['trigger_type'] = strtoupper($tmp[1]); |
||||
$def['trigger_event'] = strtoupper($tmp[2]); |
||||
} |
||||
return $def; |
||||
} |
||||
|
||||
// }}} |
||||
// {{{ tableInfo() |
||||
|
||||
/** |
||||
* Returns information about a table |
||||
* |
||||
* @param string $result a string containing the name of a table |
||||
* @param int $mode a valid tableInfo mode |
||||
* |
||||
* @return array an associative array with the information requested. |
||||
* A MDB2_Error object on failure. |
||||
* |
||||
* @see MDB2_Driver_Common::tableInfo() |
||||
* @since Method available since Release 1.7.0 |
||||
*/ |
||||
function tableInfo($result, $mode = null) |
||||
{ |
||||
if (is_string($result)) { |
||||
return parent::tableInfo($result, $mode); |
||||
} |
||||
|
||||
$db =$this->getDBInstance(); |
||||
if (PEAR::isError($db)) { |
||||
return $db; |
||||
} |
||||
|
||||
return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null, |
||||
'This DBMS can not obtain tableInfo from result sets', __FUNCTION__); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue