- fixed #1485032 and updated MDB2 package+drivers
| | |
| | | CHANGELOG RoundCube Webmail |
| | | --------------------------- |
| | | |
| | | 2008/05/02 (alec) |
| | | ---------- |
| | | - Updated MDB2 package to version 2.5.0b1 |
| | | - Updated MDB2 pgsql, mysql, mysqli, sqlite drivers to version 1.5.0b1 |
| | | - Updated MDB2 mssql driver to version 1.3.0b1 |
| | | - Fixed identities saving when using MDB2 pgsql driver (#1485032) |
| | | |
| | | 2008/05/01 (alec) |
| | | ---------- |
| | | - Fix BCC header reset (#1484997) |
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: MDB2.php,v 1.307 2007/11/10 13:29:05 quipo Exp $
|
| | | // $Id: MDB2.php,v 1.318 2008/03/08 14:18:38 quipo Exp $
|
| | | //
|
| | |
|
| | | /**
|
| | |
| | | define('MDB2_ERROR_MANAGER_PARSE', -33);
|
| | | define('MDB2_ERROR_LOADMODULE', -34);
|
| | | define('MDB2_ERROR_INSUFFICIENT_DATA', -35);
|
| | | define('MDB2_ERROR_NO_PERMISSION', -36);
|
| | |
|
| | | // }}}
|
| | | // {{{ Verbose constants
|
| | | /**
|
| | |
| | | */
|
| | | function apiVersion()
|
| | | {
|
| | | return '2.5.0a2';
|
| | | return '2.5.0b1';
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | MDB2_ERROR_LOADMODULE => 'error while including on demand module',
|
| | | MDB2_ERROR_TRUNCATED => 'truncated',
|
| | | MDB2_ERROR_DEADLOCK => 'deadlock detected',
|
| | | MDB2_ERROR_NO_PERMISSION => 'no permission',
|
| | | );
|
| | | }
|
| | |
|
| | |
| | | //"username/password@[//]host[:port][/service_name]"
|
| | | //e.g. "scott/tiger@//mymachine:1521/oracle"
|
| | | $proto_opts = $dsn;
|
| | | $dsn = null;
|
| | | $dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1);
|
| | | } elseif (strpos($dsn, '/') !== false) {
|
| | | list($proto_opts, $dsn) = explode('/', $dsn, 2);
|
| | | } else {
|
| | |
| | | 'LOBs' => false,
|
| | | 'replace' => false,
|
| | | 'sub_selects' => false,
|
| | | 'triggers' => false,
|
| | | 'auto_increment' => false,
|
| | | 'primary_key' => false,
|
| | | 'result_introspection' => false,
|
| | |
| | | * <li>$options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes</li>
|
| | | * <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li>
|
| | | * <li>$options['bindname_format'] -> string: regular expression pattern for named parameters
|
| | | * <li>$options['max_identifiers_length'] -> integer: max identifier length</li>
|
| | | * </ul>
|
| | | *
|
| | | * @var array
|
| | |
| | | 'nativetype_map_callback' => array(),
|
| | | 'lob_allow_url_include' => false,
|
| | | 'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)',
|
| | | 'max_identifiers_length' => 30,
|
| | | );
|
| | |
|
| | | /**
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ databaseExists()
|
| | |
|
| | | /**
|
| | | * check if given database name is exists?
|
| | | *
|
| | | * @param string $name name of the database that should be checked
|
| | | *
|
| | | * @return mixed true/false on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function databaseExists($name)
|
| | | {
|
| | | return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
| | | 'method not implemented', __FUNCTION__);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ setCharset($charset, $connection = null)
|
| | |
|
| | | /**
|
| | |
| | | {
|
| | | $previous_database_name = (isset($this->database_name)) ? $this->database_name : '';
|
| | | $this->database_name = $name;
|
| | | if (!empty($this->connected_database_name) && ($this->connected_database_name != $this->database_name)) {
|
| | | $this->disconnect(false);
|
| | | }
|
| | | return $previous_database_name;
|
| | | }
|
| | |
|
| | |
| | | return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
|
| | | 'key value '.$name.' may not be NULL', __FUNCTION__);
|
| | | }
|
| | | $condition[] = $name . '=' . $value;
|
| | | $condition[] = $this->quoteIdentifier($name, true) . '=' . $value;
|
| | | }
|
| | | }
|
| | | if (empty($condition)) {
|
| | |
| | | }
|
| | |
|
| | | $condition = ' WHERE '.implode(' AND ', $condition);
|
| | | $query = "DELETE FROM $table$condition";
|
| | | $query = 'DELETE FROM ' . $this->quoteIdentifier($table, true) . $condition;
|
| | | $result =& $this->_doQuery($query, true, $connection);
|
| | | if (!PEAR::isError($result)) {
|
| | | $affected_rows = $this->_affectedRows($connection, $result);
|
| | | $insert = implode(', ', array_keys($values));
|
| | | $insert = '';
|
| | | foreach ($values as $key => $value) {
|
| | | $insert .= ($insert?', ':'') . $this->quoteIdentifier($key, true);
|
| | | }
|
| | | $values = implode(', ', $values);
|
| | | $query = "INSERT INTO $table ($insert) VALUES ($values)";
|
| | | $query = 'INSERT INTO '. $this->quoteIdentifier($table, true) . "($insert) VALUES ($values)";
|
| | | $result =& $this->_doQuery($query, true, $connection);
|
| | | if (!PEAR::isError($result)) {
|
| | | $affected_rows += $this->_affectedRows($connection, $result);;
|
| | |
| | | return $err;
|
| | | }
|
| | | }
|
| | | } while ($ignore['escape'] && $query[($end_quote - 1)] == $ignore['escape']);
|
| | | } while ($ignore['escape'] && $query[($end_quote - 1)] == $ignore['escape'] && $end_quote-1 != $start_quote);
|
| | | $position = $end_quote + 1;
|
| | | return $position;
|
| | | }
|
| | |
| | | $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
|
| | | $parameters = array_keys($values);
|
| | | foreach ($parameters as $key => $parameter) {
|
| | | $this->db->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $this->db->expectError(MDB2_ERROR_NOT_FOUND);
|
| | | $err = $this->bindValue($parameter, $values[$parameter], $types[$key]);
|
| | | $this->db->popExpect();
|
| | | $this->db->popErrorHandling();
|
| | | if (PEAR::isError($err)) {
|
| | | if ($err->getCode() == MDB2_ERROR_NOT_FOUND) {
|
| | | //ignore (extra value for missing placeholder)
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: Common.php,v 1.128 2007/11/09 20:54:58 quipo Exp $
|
| | | // $Id: Common.php,v 1.137 2008/02/17 18:53:40 afz Exp $ |
| | |
|
| | | require_once 'MDB2/LOB.php';
|
| | |
|
| | |
| | | $charset = empty($field['charset']) ? '' :
|
| | | ' '.$this->_getCharsetFieldDeclaration($field['charset']);
|
| | |
|
| | | $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; |
| | | $default = '';
|
| | | if (array_key_exists('default', $field)) {
|
| | | if ($field['default'] === '') {
|
| | |
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | | if (empty($field['notnull'])) {
|
| | | $field['default'] = null;
|
| | | } else {
|
| | | $valid_default_values = $this->getValidTypes();
|
| | | $field['default'] = $valid_default_values[$field['type']];
|
| | | }
|
| | | if ($field['default'] === ''
|
| | | && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
|
| | | ) {
|
| | | if ($field['default'] === ''&& ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)) { |
| | | $field['default'] = ' ';
|
| | | }
|
| | | }
|
| | | if (!is_null($field['default'])) { |
| | | $default = ' DEFAULT '.$this->quote($field['default'], $field['type']);
|
| | | } elseif (empty($field['notnull'])) {
|
| | | $default = ' DEFAULT NULL';
|
| | | }
|
| | |
|
| | | $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
|
| | | } |
| | |
|
| | | $collation = empty($field['collation']) ? '' :
|
| | | ' '.$this->_getCollationFieldDeclaration($field['collation']);
|
| | | |
| | | return $charset.$default.$notnull.$collation;
|
| | | }
|
| | |
|
| | |
| | | {
|
| | | $value = (string)$value;
|
| | | $value = preg_replace('/[^\d\.,\-+eE]/', '', $value);
|
| | | if (preg_match('/[^.0-9]/', $value)) {
|
| | | if (preg_match('/[^\.\d]/', $value)) { |
| | | if (strpos($value, ',')) {
|
| | | // 1000,00
|
| | | if (!strpos($value, '.')) {
|
| | |
| | | // | Daniel Convissor <danielc@php.net> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mssql.php,v 1.59 2007/12/03 20:59:50 quipo Exp $
|
| | | // $Id: mssql.php,v 1.65 2008/02/19 14:54:17 afz Exp $ |
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Datatype/Common.php';
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _getDeclaration()
|
| | |
|
| | | /**
|
| | | * Obtain DBMS specific SQL code portion needed to declare a generic type
|
| | | * field to be used in statements like CREATE TABLE.
|
| | | *
|
| | | * @param string $name name the field to be declared.
|
| | | * @param array $field associative array with the name of the properties
|
| | | * of the field being declared as array indexes. Currently, the types
|
| | | * of supported field properties are as follows:
|
| | | *
|
| | | * length
|
| | | * Integer value that determines the maximum length of the text
|
| | | * field. If this argument is missing the field should be
|
| | | * declared to have the longest length allowed by the DBMS.
|
| | | *
|
| | | * default
|
| | | * Text value to be used as default for this field.
|
| | | *
|
| | | * notnull
|
| | | * Boolean flag that indicates whether this field is constrained
|
| | | * to not be set to null.
|
| | | * @return string DBMS specific SQL code portion that should be used to
|
| | | * declare the specified field.
|
| | | * @access protected
|
| | | */
|
| | | function _getDeclarationOptions($field)
|
| | | {
|
| | | $charset = empty($field['charset']) ? '' :
|
| | | ' '.$this->_getCharsetFieldDeclaration($field['charset']);
|
| | |
|
| | | $default = '';
|
| | | if (array_key_exists('default', $field)) {
|
| | | if ($field['default'] === '') {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | | $field['default'] = empty($field['notnull'])
|
| | | ? null : $this->valid_default_values[$field['type']];
|
| | | if ($field['default'] === ''
|
| | | && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
|
| | | ) {
|
| | | $field['default'] = ' ';
|
| | | }
|
| | | }
|
| | | $default = ' DEFAULT '.$this->quote($field['default'], $field['type']);
|
| | | } elseif (empty($field['notnull'])) {
|
| | | $default = ' DEFAULT NULL';
|
| | | }
|
| | |
|
| | | $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
|
| | | if ($default == ' DEFAULT NULL' && $notnull == ' NULL') {
|
| | | $notnull = '';
|
| | | }
|
| | |
|
| | | $collation = empty($field['collation']) ? '' :
|
| | | ' '.$this->_getCollationFieldDeclaration($field['collation']);
|
| | | return $charset.$default.$notnull.$collation;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _getIntegerDeclaration()
|
| | |
|
| | | /**
|
| | |
| | | return $db;
|
| | | }
|
| | |
|
| | | $default = $autoinc = '';;
|
| | | $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; |
| | | $default = $autoinc = ''; |
| | | if (!empty($field['autoincrement'])) {
|
| | | $autoinc = ' IDENTITY PRIMARY KEY';
|
| | | } elseif (array_key_exists('default', $field)) {
|
| | | if ($field['default'] === '') {
|
| | | $field['default'] = empty($field['notnull']) ? null : 0;
|
| | | $field['default'] = 0; |
| | | }
|
| | | $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
|
| | | } elseif (empty($field['notnull'])) {
|
| | | $default = ' DEFAULT NULL';
|
| | | if (is_null($field['default'])) { |
| | | $default = ' DEFAULT (null)'; |
| | | } else { |
| | | $default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')'; |
| | | } |
| | | }
|
| | |
|
| | | $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
|
| | | if ($default == ' DEFAULT NULL' && $notnull == ' NULL') {
|
| | | $notnull = '';
|
| | | }
|
| | | if (!empty($field['unsigned'])) {
|
| | | $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
|
| | | }
|
| | | |
| | | $name = $db->quoteIdentifier($name, true);
|
| | | return $name.' '.$this->getTypeDeclaration($field).$default.$notnull.$autoinc;
|
| | | return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc; |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | if (!$quote) {
|
| | | return $value;
|
| | | }
|
| | | $value = bin2hex("0x".$this->_readFile($value));
|
| | | $value = '0x'.bin2hex($this->_readFile($value)); |
| | | return $value;
|
| | | }
|
| | |
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mysql.php,v 1.62 2007/11/09 20:54:58 quipo Exp $
|
| | | // $Id: mysql.php,v 1.65 2008/02/22 19:23:49 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Datatype/Common.php';
|
| | |
| | | $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.$autoinc;
|
| | | return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mysqli.php,v 1.61 2007/11/09 20:54:58 quipo Exp $
|
| | | // $Id: mysqli.php,v 1.63 2008/02/22 19:23:49 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Datatype/Common.php';
|
| | |
| | | $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.$autoinc;
|
| | | return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | case 'tinytext':
|
| | | case 'mediumtext':
|
| | | case 'longtext':
|
| | | case 'text':
|
| | | case 'text':
|
| | | case 'varchar':
|
| | | $fixed = false;
|
| | |
| | | // | Author: Paul Cooper <pgc@ucecom.com> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: pgsql.php,v 1.88 2007/11/09 20:54:58 quipo Exp $
|
| | | // $Id: pgsql.php,v 1.91 2008/03/09 12:28:08 quipo Exp $
|
| | |
|
| | | require_once 'MDB2/Driver/Datatype/Common.php';
|
| | |
|
| | |
| | | $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';
|
| | |
| | | break;
|
| | | case 'datetime':
|
| | | case 'timestamp':
|
| | | case 'timestamptz':
|
| | | $type[] = 'timestamp';
|
| | | $length = null;
|
| | | break;
|
| | |
| | | $length = null;
|
| | | break;
|
| | | case 'float':
|
| | | case 'float4':
|
| | | case 'float8':
|
| | | case 'double':
|
| | | case 'real':
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: sqlite.php,v 1.65 2007/12/03 20:59:51 quipo Exp $
|
| | | // $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Datatype/Common.php';
|
| | |
| | | $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';
|
| | |
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | |
|
| | | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
| | | 'unknown database attribute type: '.$db_type, __FUNCTION__);
|
| | | }
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: Common.php,v 1.19 2007/09/09 13:47:36 quipo Exp $ |
| | | // $Id: Common.php,v 1.21 2008/02/17 18:51:39 quipo Exp $
|
| | | // |
| | | |
| | | /** |
| | |
| | | * 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 |
| | | */ |
| | |
| | | * - 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 |
| | | */ |
| | |
| | | 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;
|
| | | } |
| | | |
| | | // }}} |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ 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() |
| | | |
| | | /** |
| | |
| | | * @param string $value1 |
| | | * @param string $value2 |
| | | * @param string $values... |
| | | *
|
| | | * @return string to concatenate two strings |
| | | * @access public |
| | | */ |
| | |
| | | * 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 |
| | | */ |
| | |
| | | * 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 |
| | | */ |
| | |
| | | * 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 |
| | | */ |
| | |
| | | // +----------------------------------------------------------------------+ |
| | | // | PHP versions 4 and 5 | |
| | | // +----------------------------------------------------------------------+ |
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith | |
| | | // | All rights reserved. | |
| | | // +----------------------------------------------------------------------+ |
| | |
| | | // | Author: Frank M. Kromann <frank@kromann.info> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: mssql.php,v 1.15 2007/08/11 16:02:22 quipo Exp $ |
| | | // $Id: mssql.php,v 1.16 2008/02/17 18:54:08 quipo Exp $
|
| | | // |
| | | |
| | | require_once 'MDB2/Driver/Function/Common.php'; |
| | |
| | | */ |
| | | class MDB2_Driver_Function_mssql extends MDB2_Driver_Function_Common |
| | | { |
| | | // }}} |
| | | // {{{ executeStoredProc() |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ unixtimestamp()
|
| | |
|
| | | /**
|
| | | * return string to call a function to get the unix timestamp from a iso timestamp
|
| | | *
|
| | | * @param string $expression
|
| | | *
|
| | | * @return string to call a variable with the timestamp
|
| | | * @access public
|
| | | */
|
| | | function unixtimestamp($expression)
|
| | | {
|
| | | return 'DATEDIFF(second, \'19700101\', '. $expression.') + DATEDIFF(second, GETDATE(), GETUTCDATE())';
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ substring() |
| | | |
| | | /** |
| | |
| | | // +----------------------------------------------------------------------+ |
| | | // | PHP versions 4 and 5 | |
| | | // +----------------------------------------------------------------------+ |
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith | |
| | | // | All rights reserved. | |
| | | // +----------------------------------------------------------------------+ |
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: mysql.php,v 1.11 2007/01/12 11:29:12 quipo Exp $ |
| | | // $Id: mysql.php,v 1.12 2008/02/17 18:54:08 quipo Exp $
|
| | | // |
| | | |
| | | require_once 'MDB2/Driver/Function/Common.php'; |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ 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() |
| | | |
| | | /** |
| | |
| | | // +----------------------------------------------------------------------+ |
| | | // | PHP versions 4 and 5 | |
| | | // +----------------------------------------------------------------------+ |
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith | |
| | | // | All rights reserved. | |
| | | // +----------------------------------------------------------------------+ |
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: mysqli.php,v 1.13 2007/01/12 11:29:12 quipo Exp $ |
| | | // $Id: mysqli.php,v 1.14 2008/02/17 18:54:08 quipo Exp $
|
| | | // |
| | | |
| | | require_once 'MDB2/Driver/Function/Common.php'; |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ 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() |
| | | |
| | | /** |
| | |
| | | // +----------------------------------------------------------------------+ |
| | | // | PHP versions 4 and 5 | |
| | | // +----------------------------------------------------------------------+ |
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith | |
| | | // | All rights reserved. | |
| | | // +----------------------------------------------------------------------+ |
| | |
| | | // | Author: Paul Cooper <pgc@ucecom.com> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: pgsql.php,v 1.9 2006/06/12 21:48:43 lsmith Exp $ |
| | | // $Id: pgsql.php,v 1.10 2008/02/17 18:54:08 quipo Exp $
|
| | | |
| | | require_once 'MDB2/Driver/Function/Common.php'; |
| | | |
| | |
| | | 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\', TIMESTAMP '. $expression.'))';
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ random() |
| | | |
| | | /** |
| | |
| | | // +----------------------------------------------------------------------+ |
| | | // | PHP versions 4 and 5 | |
| | | // +----------------------------------------------------------------------+ |
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith | |
| | | // | All rights reserved. | |
| | | // +----------------------------------------------------------------------+ |
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: sqlite.php,v 1.8 2006/06/13 22:55:55 lsmith Exp $ |
| | | // $Id: sqlite.php,v 1.10 2008/02/17 18:54:08 quipo Exp $
|
| | | // |
| | | |
| | | require_once 'MDB2/Driver/Function/Common.php'; |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ 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() |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ 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;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | } |
| | | ?> |
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
| | | // | POSSIBILITY OF SUCH DAMAGE. |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // | Authors: Lukas Smith <smith@pooteeweet.org> |
|
| | | // | Lorenzo Alberton <l.alberton@quipo.it> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: Common.php,v 1.68 2007/12/03 20:59:15 quipo Exp $
|
| | | // $Id: Common.php,v 1.71 2008/02/12 23:12:27 quipo Exp $
|
| | | //
|
| | |
|
| | | /**
|
| | | * @package MDB2
|
| | | * @category Database
|
| | | * @author Lukas Smith <smith@pooteeweet.org>
|
| | | * @author Lorenzo Alberton <l.alberton@quipo.it>
|
| | | */
|
| | |
|
| | | /**
|
| | |
| | | * @access public
|
| | | */
|
| | | function createDatabase($database, $options = array())
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | |
|
| | | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
| | | 'method not implemented', __FUNCTION__);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ alterDatabase()
|
| | |
|
| | | /**
|
| | | * alter an existing database
|
| | | *
|
| | | * @param string $name name of the database that should be created
|
| | | * @param array $options array with charset, collation info
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function alterDatabase($database, $options = array())
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ 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("DELETE FROM $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;
|
| | | }
|
| | |
|
| | | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
|
| | | 'method not implemented', __FUNCTION__);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ alterTable()
|
| | |
|
| | | /**
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Lorenzo Alberton <l.alberton@quipo.it> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mssql.php,v 1.93 2007/12/03 20:59:15 quipo Exp $
|
| | | // $Id: mssql.php,v 1.109 2008/03/05 12:55:57 afz Exp $ |
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Manager/Common.php';
|
| | |
| | | $query .= ' COLLATE ' . $options['collation'];
|
| | | }
|
| | | 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, collation 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 = ''; |
| | | if (!empty($options['name'])) { |
| | | $query .= ' MODIFY NAME = ' .$db->quoteIdentifier($options['name'], true); |
| | | } |
| | | if (!empty($options['collation'])) { |
| | | $query .= ' COLLATE ' . $options['collation']; |
| | | } |
| | | if (!empty($query)) { |
| | | $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true) . $query; |
| | | return $db->standaloneQuery($query, null, true); |
| | | } |
| | | return MDB2_OK; |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ 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] |
| | | * |
| | | * NB: you have to run the NSControl Create utility to enable VACUUM |
| | | * |
| | | * @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; |
| | | } |
| | | $timeout = isset($options['timeout']) ? (int)$options['timeout'] : 300; |
| | | |
| | | $query = 'NSControl Create'; |
| | | $result = $db->exec($query); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | |
| | | return $db->exec('EXEC NSVacuum '.$timeout); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ alterTable()
|
| | |
|
| | | /**
|
| | |
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | | $name_quoted = $db->quoteIdentifier($name, true); |
| | |
|
| | | foreach ($changes as $change_name => $change) {
|
| | | switch ($change_name) {
|
| | | case 'add':
|
| | | break;
|
| | | case 'remove':
|
| | | break;
|
| | | case 'name':
|
| | | case 'rename':
|
| | | case 'add': |
| | | case 'change':
|
| | | case 'name': |
| | | break; |
| | | default:
|
| | | return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
|
| | | 'change type "'.$change_name.'" not yet supported', __FUNCTION__);
|
| | |
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | $query = '';
|
| | | if (!empty($changes['add']) && is_array($changes['add'])) {
|
| | | foreach ($changes['add'] as $field_name => $field) {
|
| | | if ($query) {
|
| | | $query.= ', ';
|
| | | } else {
|
| | | $query.= 'ADD COLUMN ';
|
| | | }
|
| | | $query.= $db->getDeclaration($field['type'], $field_name, $field);
|
| | | }
|
| | | }
|
| | | $idxname_format = $db->getOption('idxname_format'); |
| | | $db->setOption('idxname_format', '%s'); |
| | |
|
| | | if (!empty($changes['remove']) && is_array($changes['remove'])) {
|
| | | $result = $this->_dropConflictingIndices($name, array_keys($changes['remove'])); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | $result = $this->_dropConflictingConstraints($name, array_keys($changes['remove'])); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | |
| | | $query = ''; |
| | | foreach ($changes['remove'] as $field_name => $field) {
|
| | | if ($query) {
|
| | | $query.= ', ';
|
| | | }
|
| | | $field_name = $db->quoteIdentifier($field_name, true);
|
| | | $query.= 'DROP COLUMN ' . $field_name;
|
| | | $query.= 'COLUMN ' . $field_name; |
| | | } |
| | | |
| | | $result = $db->exec("ALTER TABLE $name_quoted DROP $query"); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | }
|
| | | }
|
| | |
|
| | | if (!$query) {
|
| | | 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("sp_rename '$name_quoted.$field_name', '".$field['name']."', 'COLUMN'"); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!empty($changes['add']) && is_array($changes['add'])) { |
| | | $query = ''; |
| | | foreach ($changes['add'] as $field_name => $field) { |
| | | if ($query) { |
| | | $query.= ', '; |
| | | } else { |
| | | $query.= 'ADD '; |
| | | } |
| | | $query.= $db->getDeclaration($field['type'], $field_name, $field); |
| | | } |
| | | |
| | | $result = $db->exec("ALTER TABLE $name_quoted $query"); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | } |
| | | |
| | | $dropped_indices = array(); |
| | | $dropped_constraints = array(); |
| | | |
| | | if (!empty($changes['change']) && is_array($changes['change'])) { |
| | | $dropped = $this->_dropConflictingIndices($name, array_keys($changes['change'])); |
| | | if (PEAR::isError($dropped)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $dropped; |
| | | } |
| | | $dropped_indices = array_merge($dropped_indices, $dropped); |
| | | $dropped = $this->_dropConflictingConstraints($name, array_keys($changes['change'])); |
| | | if (PEAR::isError($dropped)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $dropped; |
| | | } |
| | | $dropped_constraints = array_merge($dropped_constraints, $dropped); |
| | | |
| | | foreach ($changes['change'] as $field_name => $field) { |
| | | //MSSQL doesn't allow multiple ALTER COLUMNs in one query |
| | | $query = 'ALTER COLUMN '; |
| | | |
| | | //MSSQL doesn't allow changing the DEFAULT value of a field in altering mode |
| | | if (array_key_exists('default', $field['definition'])) { |
| | | unset($field['definition']['default']); |
| | | } |
| | | |
| | | $query .= $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']); |
| | | $result = $db->exec("ALTER TABLE $name_quoted $query"); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // restore the dropped conflicting indices and constraints |
| | | foreach ($dropped_indices as $index_name => $index) { |
| | | $result = $this->createIndex($name, $index_name, $index); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | } |
| | | foreach ($dropped_constraints as $constraint_name => $constraint) { |
| | | $result = $this->createConstraint($name, $constraint_name, $constraint); |
| | | if (PEAR::isError($result)) { |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | return $result; |
| | | } |
| | | } |
| | | |
| | | $db->setOption('idxname_format', $idxname_format); |
| | | |
| | | if (!empty($changes['name'])) { |
| | | $new_name = $db->quoteIdentifier($changes['name'], true); |
| | | $result = $db->exec("sp_rename '$name_quoted', '$new_name'"); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | |
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | $name = $db->quoteIdentifier($name, true);
|
| | | return $db->exec("ALTER TABLE $name $query");
|
| | | // }}} |
| | | // {{{ _dropConflictingIndices() |
| | | |
| | | /** |
| | | * Drop the indices that prevent a successful ALTER TABLE action |
| | | * |
| | | * @param string $table table name |
| | | * @param array $fields array of names of the fields affected by the change |
| | | * |
| | | * @return array dropped indices definitions |
| | | */ |
| | | function _dropConflictingIndices($table, $fields) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $dropped = array(); |
| | | $index_names = $this->listTableIndexes($table); |
| | | if (PEAR::isError($index_names)) { |
| | | return $index_names; |
| | | } |
| | | $db->loadModule('Reverse'); |
| | | $indexes = array(); |
| | | foreach ($index_names as $index_name) { |
| | | $idx_def = $db->reverse->getTableIndexDefinition($table, $index_name); |
| | | if (!PEAR::isError($idx_def)) { |
| | | $indexes[$index_name] = $idx_def; |
| | | } |
| | | } |
| | | foreach ($fields as $field_name) { |
| | | foreach ($indexes as $index_name => $index) { |
| | | if (!isset($dropped[$index_name]) && array_key_exists($field_name, $index['fields'])) { |
| | | $dropped[$index_name] = $index; |
| | | $result = $this->dropIndex($table, $index_name); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $dropped; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ _dropConflictingConstraints() |
| | | |
| | | /** |
| | | * Drop the constraints that prevent a successful ALTER TABLE action |
| | | * |
| | | * @param string $table table name |
| | | * @param array $fields array of names of the fields affected by the change |
| | | * |
| | | * @return array dropped constraints definitions |
| | | */ |
| | | function _dropConflictingConstraints($table, $fields) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $dropped = array(); |
| | | $constraint_names = $this->listTableConstraints($table); |
| | | if (PEAR::isError($constraint_names)) { |
| | | return $constraint_names; |
| | | } |
| | | $db->loadModule('Reverse'); |
| | | $constraints = array(); |
| | | foreach ($constraint_names as $constraint_name) { |
| | | $cons_def = $db->reverse->getTableConstraintDefinition($table, $constraint_name); |
| | | if (!PEAR::isError($cons_def)) { |
| | | $constraints[$constraint_name] = $cons_def; |
| | | } |
| | | } |
| | | foreach ($fields as $field_name) { |
| | | foreach ($constraints as $constraint_name => $constraint) { |
| | | if (!isset($dropped[$constraint_name]) && array_key_exists($field_name, $constraint['fields'])) { |
| | | $dropped[$constraint_name] = $constraint; |
| | | $result = $this->dropConstraint($table, $constraint_name); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | // also drop implicit DEFAULT constraints |
| | | $default = $this->_getTableFieldDefaultConstraint($table, $field_name); |
| | | if (!PEAR::isError($default) && !empty($default)) { |
| | | $result = $this->dropConstraint($table, $default); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $dropped; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ _getTableFieldDefaultConstraint() |
| | | |
| | | /** |
| | | * Get the default constraint for a table field |
| | | * |
| | | * @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 name of default constraint on success, a MDB2 error on failure |
| | | * @access private |
| | | */ |
| | | function _getTableFieldDefaultConstraint($table, $field) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $table = $db->quoteIdentifier($table, true); |
| | | $field = $db->quote($field, 'text'); |
| | | $query = "SELECT OBJECT_NAME(syscolumns.cdefault) |
| | | FROM syscolumns |
| | | WHERE syscolumns.id = object_id('$table') |
| | | AND syscolumns.name = $field |
| | | AND syscolumns.cdefault <> 0"; |
| | | return $db->queryOne($query); |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mysql.php,v 1.100 2007/12/03 20:59:15 quipo Exp $
|
| | | // $Id: mysql.php,v 1.108 2008/03/11 19:58:12 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Manager/Common.php';
|
| | |
| | | $name = $db->quoteIdentifier($name, true);
|
| | | $query = 'CREATE DATABASE ' . $name;
|
| | | if (!empty($options['charset'])) {
|
| | | $query .= ' DEFAULT CHARACTER SET ' . $options['charset'];
|
| | | $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text');
|
| | | }
|
| | | if (!empty($options['collation'])) {
|
| | | $query .= ' COLLATE ' . $options['collation'];
|
| | | $query .= ' COLLATE ' . $db->quote($options['collation'], 'text');
|
| | | }
|
| | | $result = $db->exec($query);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | return $db->standaloneQuery($query, null, true);
|
| | | }
|
| | | return MDB2_OK;
|
| | |
|
| | | // }}}
|
| | | // {{{ alterDatabase()
|
| | |
|
| | | /**
|
| | | * alter an existing database
|
| | | *
|
| | | * @param string $name name of the database that is intended to be changed
|
| | | * @param array $options array with charset, collation 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['charset'])) {
|
| | | $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text');
|
| | | }
|
| | | if (!empty($options['collation'])) {
|
| | | $query .= ' COLLATE ' . $db->quote($options['collation'], 'text');
|
| | | }
|
| | | return $db->standaloneQuery($query, null, true);
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | |
|
| | | $name = $db->quoteIdentifier($name, true);
|
| | | $query = "DROP DATABASE $name";
|
| | | $result = $db->exec($query);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | return MDB2_OK;
|
| | | return $db->standaloneQuery($query, null, true);
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | return $db;
|
| | | }
|
| | |
|
| | | // if we have an AUTO_INCREMENT column and a PK on more than one field,
|
| | | // we have to handle it differently...
|
| | | $autoincrement = null;
|
| | | if (empty($options['primary'])) {
|
| | | $pk_fields = array();
|
| | | foreach ($fields as $fieldname => $def) {
|
| | | if (!empty($def['primary'])) {
|
| | | $pk_fields[$fieldname] = true;
|
| | | }
|
| | | if (!empty($def['autoincrement'])) {
|
| | | $autoincrement = $fieldname;
|
| | | }
|
| | | }
|
| | | if (!is_null($autoincrement) && count($pk_fields) > 1) {
|
| | | $options['primary'] = $pk_fields;
|
| | | } else {
|
| | | // the PK constraint is on max one field => OK
|
| | | $autoincrement = null;
|
| | | }
|
| | | }
|
| | |
|
| | | $query = $this->_getCreateTableQuery($name, $fields, $options);
|
| | | if (PEAR::isError($query)) {
|
| | | return $query;
|
| | | }
|
| | |
|
| | | if (!is_null($autoincrement)) {
|
| | | // we have to remove the PK clause added by _getIntegerDeclaration()
|
| | | $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query);
|
| | | }
|
| | |
|
| | | $options_strings = array();
|
| | |
| | | $result = $db->exec($query);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ dropTable()
|
| | |
|
| | | /**
|
| | | * drop an existing table
|
| | | *
|
| | | * @param string $name name of the table that should be dropped
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function dropTable($name)
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | |
|
| | | //delete the triggers associated to existing FK constraints
|
| | | $constraints = $this->listTableConstraints($name);
|
| | | if (!PEAR::isError($constraints) && !empty($constraints)) {
|
| | | $db->loadModule('Reverse', null, true);
|
| | | foreach ($constraints as $constraint) {
|
| | | $definition = $db->reverse->getTableConstraintDefinition($name, $constraint);
|
| | | if (!PEAR::isError($definition) && !empty($definition['foreign'])) {
|
| | | $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | return parent::dropTable($name);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ 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;
|
| | | }
|
| | |
|
| | | if (empty($table)) {
|
| | | $table = $this->listTables();
|
| | | if (PEAR::isError($table)) {
|
| | | return $table;
|
| | | }
|
| | | }
|
| | | if (is_array($table)) {
|
| | | foreach (array_keys($table) as $k) {
|
| | | $table[$k] = $db->quoteIdentifier($table[$k], true);
|
| | | }
|
| | | $table = implode(', ', $table);
|
| | | } else {
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | }
|
| | | |
| | | $result = $db->exec('OPTIMIZE TABLE '.$table);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | if (!empty($options['analyze'])) {
|
| | | return $db->exec('ANALYZE TABLE '.$table);
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
| | | * 'last_login' => array()
|
| | | * )
|
| | | * )
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | |
| | | 'invalid definition, could not create constraint', __FUNCTION__);
|
| | | }
|
| | |
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | $query = "ALTER TABLE $table ADD $type $name";
|
| | | $table_quoted = $db->quoteIdentifier($table, true);
|
| | | $query = "ALTER TABLE $table_quoted ADD $type $name";
|
| | | if (!empty($definition['foreign'])) {
|
| | | $query .= ' FOREIGN KEY ';
|
| | | }
|
| | |
| | | $query .= ' ('. implode(', ', $referenced_fields) . ')';
|
| | | $query .= $this->_getAdvancedFKOptions($definition);
|
| | | }
|
| | | return $db->exec($query);
|
| | | $res = $db->exec($query);
|
| | | if (PEAR::isError($res)) {
|
| | | return $res;
|
| | | }
|
| | | if (!empty($definition['foreign'])) {
|
| | | return $this->_createFKTriggers($table, array($name => $definition));
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | return $db;
|
| | | }
|
| | |
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | if ($primary || strtolower($name) == 'primary') {
|
| | | $query = "ALTER TABLE $table DROP PRIMARY KEY";
|
| | | } else {
|
| | | $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY';
|
| | | return $db->exec($query);
|
| | | }
|
| | |
|
| | | //is it a FK constraint? If so, also delete the associated triggers
|
| | | $db->loadModule('Reverse', null, true);
|
| | | $definition = $db->reverse->getTableConstraintDefinition($table, $name);
|
| | | if (!PEAR::isError($definition) && !empty($definition['foreign'])) {
|
| | | //first drop the FK enforcing triggers
|
| | | $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | //then drop the constraint itself
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | $name = $db->quoteIdentifier($db->getIndexName($name), true);
|
| | | $query = "ALTER TABLE $table DROP FOREIGN KEY $name";
|
| | | return $db->exec($query);
|
| | | }
|
| | |
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | $name = $db->quoteIdentifier($db->getIndexName($name), true);
|
| | | $query = "ALTER TABLE $table DROP INDEX $name";
|
| | | }
|
| | | return $db->exec($query);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _createFKTriggers()
|
| | |
|
| | | /**
|
| | | * Create triggers to enforce the FOREIGN KEY constraint on the table
|
| | | *
|
| | | * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql,
|
| | | * we call a non-existent procedure to raise the FK violation message.
|
| | | * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877
|
| | | *
|
| | | * @param string $table table name
|
| | | * @param array $foreign_keys FOREIGN KEY definitions
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access private
|
| | | */
|
| | | function _createFKTriggers($table, $foreign_keys)
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | | // create triggers to enforce FOREIGN KEY constraints
|
| | | if ($db->supports('triggers') && !empty($foreign_keys)) {
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | foreach ($foreign_keys as $fkname => $fkdef) {
|
| | | if (empty($fkdef)) {
|
| | | continue;
|
| | | }
|
| | | //set actions to 'RESTRICT' if not set
|
| | | $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']);
|
| | | $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']);
|
| | |
|
| | | $trigger_names = array(
|
| | | 'insert' => $fkname.'_insert_trg',
|
| | | 'update' => $fkname.'_update_trg',
|
| | | 'pk_update' => $fkname.'_pk_update_trg',
|
| | | 'pk_delete' => $fkname.'_pk_delete_trg',
|
| | | );
|
| | | $table_fields = array_keys($fkdef['fields']);
|
| | | $referenced_fields = array_keys($fkdef['references']['fields']);
|
| | |
|
| | | //create the ON [UPDATE|DELETE] triggers on the primary table
|
| | | $restrict_action = ' IF (SELECT ';
|
| | | $aliased_fields = array();
|
| | | foreach ($table_fields as $field) {
|
| | | $aliased_fields[] = $table .'.'.$field .' AS '.$field;
|
| | | }
|
| | | $restrict_action .= implode(',', $aliased_fields)
|
| | | .' FROM '.$table
|
| | | .' WHERE ';
|
| | | $conditions = array();
|
| | | $new_values = array();
|
| | | $null_values = array();
|
| | | for ($i=0; $i<count($table_fields); $i++) {
|
| | | $conditions[] = $table_fields[$i] .' = OLD.'.$referenced_fields[$i];
|
| | | $new_values[] = $table_fields[$i] .' = NEW.'.$referenced_fields[$i];
|
| | | $null_values[] = $table_fields[$i] .' = NULL';
|
| | | }
|
| | | $restrict_action .= implode(' AND ', $conditions).') IS NOT NULL'
|
| | | .' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
|
| | | .' END IF;';
|
| | |
|
| | | $cascade_action_update = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
|
| | | $cascade_action_delete = 'DELETE FROM '.$table.' WHERE '.implode(' AND ', $conditions). ';';
|
| | | $setnull_action = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
|
| | |
|
| | | if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
|
| | | $db->loadModule('Reverse', null, true);
|
| | | $default_values = array();
|
| | | foreach ($table_fields as $table_field) {
|
| | | $field_definition = $db->reverse->getTableFieldDefinition($table, $field);
|
| | | if (PEAR::isError($field_definition)) {
|
| | | return $field_definition;
|
| | | }
|
| | | $default_values[] = $table_field .' = '. $field_definition[0]['default'];
|
| | | }
|
| | | $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
|
| | | }
|
| | |
|
| | | $query = 'CREATE TRIGGER %s'
|
| | | .' %s ON '.$fkdef['references']['table']
|
| | | .' FOR EACH ROW BEGIN '
|
| | | .' SET FOREIGN_KEY_CHECKS = 0; '; //only really needed for ON UPDATE CASCADE
|
| | |
|
| | | if ('CASCADE' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $cascade_action_update;
|
| | | } elseif ('SET NULL' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action;
|
| | | } elseif ('SET DEFAULT' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action;
|
| | | } elseif ('NO ACTION' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update');
|
| | | } else {
|
| | | //'RESTRICT'
|
| | | $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update');
|
| | | }
|
| | | if ('CASCADE' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $cascade_action_delete;
|
| | | } elseif ('SET NULL' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action;
|
| | | } elseif ('SET DEFAULT' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action;
|
| | | } elseif ('NO ACTION' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete');
|
| | | } else {
|
| | | //'RESTRICT'
|
| | | $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete');
|
| | | }
|
| | | $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
|
| | | $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
|
| | |
|
| | | $db->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $db->expectError(MDB2_ERROR_CANNOT_CREATE);
|
| | | $result = $db->exec($sql_delete);
|
| | | $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table';
|
| | | $db->popExpect();
|
| | | $db->popErrorHandling();
|
| | | if (PEAR::isError($result)) {
|
| | | if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
|
| | | return $result;
|
| | | }
|
| | | $db->warnings[] = $expected_errmsg;
|
| | | }
|
| | | $db->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $db->expectError(MDB2_ERROR_CANNOT_CREATE);
|
| | | $result = $db->exec($sql_update);
|
| | | $db->popExpect();
|
| | | $db->popErrorHandling();
|
| | | if (PEAR::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
|
| | | if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
|
| | | return $result;
|
| | | }
|
| | | $db->warnings[] = $expected_errmsg;
|
| | | }
|
| | | }
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _dropFKTriggers()
|
| | |
|
| | | /**
|
| | | * Drop the triggers created to enforce the FOREIGN KEY constraint on the table
|
| | | *
|
| | | * @param string $table table name
|
| | | * @param string $fkname FOREIGN KEY constraint name
|
| | | * @param string $referenced_table referenced table name
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access private
|
| | | */
|
| | | function _dropFKTriggers($table, $fkname, $referenced_table)
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | |
|
| | | $triggers = $this->listTableTriggers($table);
|
| | | $triggers2 = $this->listTableTriggers($referenced_table);
|
| | | if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) {
|
| | | $triggers = array_merge($triggers, $triggers2);
|
| | | $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i';
|
| | | foreach ($triggers as $trigger) {
|
| | | if (preg_match($pattern, $trigger)) {
|
| | | $result = $db->exec('DROP TRIGGER '.$trigger);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | $query = 'SHOW CREATE TABLE '. $db->escape($table);
|
| | | $definition = $db->queryOne($query, 'text', 1);
|
| | | if (!PEAR::isError($definition) && !empty($definition)) {
|
| | | $pattern = '/\bCONSTRAINT\s+([^\s]+)\s+FOREIGN KEY\b/i';
|
| | | if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 1) {
|
| | | $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims';
|
| | | if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) {
|
| | | foreach ($matches[1] as $constraint) {
|
| | | $result[$constraint] = true;
|
| | | }
|
| | |
| | | $query .= ' '.implode(' ', $options_strings);
|
| | | }
|
| | | $res = $db->exec($query);
|
| | |
|
| | | if (PEAR::isError($res)) {
|
| | | return $res;
|
| | | }
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mysqli.php,v 1.87 2007/12/03 20:59:15 quipo Exp $
|
| | | // $Id: mysqli.php,v 1.95 2008/03/11 19:58:12 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Manager/Common.php';
|
| | |
| | | $name = $db->quoteIdentifier($name, true);
|
| | | $query = 'CREATE DATABASE ' . $name;
|
| | | if (!empty($options['charset'])) {
|
| | | $query .= ' DEFAULT CHARACTER SET ' . $options['charset'];
|
| | | $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text');
|
| | | }
|
| | | if (!empty($options['collation'])) {
|
| | | $query .= ' COLLATE ' . $options['collation'];
|
| | | $query .= ' COLLATE ' . $db->quote($options['collation'], 'text');
|
| | | }
|
| | | $result = $db->exec($query);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | return $db->standaloneQuery($query, null, true);
|
| | | }
|
| | | return MDB2_OK;
|
| | |
|
| | | // }}}
|
| | | // {{{ alterDatabase()
|
| | |
|
| | | /**
|
| | | * alter an existing database
|
| | | *
|
| | | * @param string $name name of the database that is intended to be changed
|
| | | * @param array $options array with charset, collation 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['charset'])) {
|
| | | $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text');
|
| | | }
|
| | | if (!empty($options['collation'])) {
|
| | | $query .= ' COLLATE ' . $db->quote($options['collation'], 'text');
|
| | | }
|
| | | return $db->standaloneQuery($query, null, true);
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | |
|
| | | $name = $db->quoteIdentifier($name, true);
|
| | | $query = "DROP DATABASE $name";
|
| | | $result = $db->exec($query);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | return MDB2_OK;
|
| | | return $db->standaloneQuery($query, null, true);
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | return $db;
|
| | | }
|
| | |
|
| | | // if we have an AUTO_INCREMENT column and a PK on more than one field,
|
| | | // we have to handle it differently...
|
| | | $autoincrement = null;
|
| | | if (empty($options['primary'])) {
|
| | | $pk_fields = array();
|
| | | foreach ($fields as $fieldname => $def) {
|
| | | if (!empty($def['primary'])) {
|
| | | $pk_fields[$fieldname] = true;
|
| | | }
|
| | | if (!empty($def['autoincrement'])) {
|
| | | $autoincrement = $fieldname;
|
| | | }
|
| | | }
|
| | | if (!is_null($autoincrement) && count($pk_fields) > 1) {
|
| | | $options['primary'] = $pk_fields;
|
| | | } else {
|
| | | // the PK constraint is on max one field => OK
|
| | | $autoincrement = null;
|
| | | }
|
| | | }
|
| | |
|
| | | $query = $this->_getCreateTableQuery($name, $fields, $options);
|
| | | if (PEAR::isError($query)) {
|
| | | return $query;
|
| | | }
|
| | |
|
| | | if (!is_null($autoincrement)) {
|
| | | // we have to remove the PK clause added by _getIntegerDeclaration()
|
| | | $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query);
|
| | | }
|
| | |
|
| | | $options_strings = array();
|
| | |
| | | $result = $db->exec($query);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ dropTable()
|
| | |
|
| | | /**
|
| | | * drop an existing table
|
| | | *
|
| | | * @param string $name name of the table that should be dropped
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function dropTable($name)
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | |
|
| | | //delete the triggers associated to existing FK constraints
|
| | | $constraints = $this->listTableConstraints($name);
|
| | | if (!PEAR::isError($constraints) && !empty($constraints)) {
|
| | | $db->loadModule('Reverse', null, true);
|
| | | foreach ($constraints as $constraint) {
|
| | | $definition = $db->reverse->getTableConstraintDefinition($name, $constraint);
|
| | | if (!PEAR::isError($definition) && !empty($definition['foreign'])) {
|
| | | $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | return parent::dropTable($name);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ 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;
|
| | | }
|
| | |
|
| | | if (empty($table)) {
|
| | | $table = $this->listTables();
|
| | | if (PEAR::isError($table)) {
|
| | | return $table;
|
| | | }
|
| | | }
|
| | | if (is_array($table)) {
|
| | | foreach (array_keys($table) as $k) {
|
| | | $table[$k] = $db->quoteIdentifier($table[$k], true);
|
| | | }
|
| | | $table = implode(', ', $table);
|
| | | } else {
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | }
|
| | |
|
| | | $result = $db->exec('OPTIMIZE TABLE '.$table);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | if (!empty($options['analyze'])) {
|
| | | return $db->exec('ANALYZE TABLE '.$table);
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
| | | * 'last_login' => array()
|
| | | * )
|
| | | * )
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | |
| | | 'invalid definition, could not create constraint', __FUNCTION__);
|
| | | }
|
| | |
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | $query = "ALTER TABLE $table ADD $type $name";
|
| | | $table_quoted = $db->quoteIdentifier($table, true);
|
| | | $query = "ALTER TABLE $table_quoted ADD $type $name";
|
| | | if (!empty($definition['foreign'])) {
|
| | | $query .= ' FOREIGN KEY ';
|
| | | }
|
| | |
| | | $query .= ' ('. implode(', ', $referenced_fields) . ')';
|
| | | $query .= $this->_getAdvancedFKOptions($definition);
|
| | | }
|
| | | return $db->exec($query);
|
| | | $res = $db->exec($query);
|
| | | if (PEAR::isError($res)) {
|
| | | return $res;
|
| | | }
|
| | | if (!empty($definition['foreign'])) {
|
| | | return $this->_createFKTriggers($table, array($name => $definition));
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | return $db;
|
| | | }
|
| | |
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | if ($primary || strtolower($name) == 'primary') {
|
| | | $query = "ALTER TABLE $table DROP PRIMARY KEY";
|
| | | } else {
|
| | | $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY';
|
| | | return $db->exec($query);
|
| | | }
|
| | | |
| | | //is it a FK constraint? If so, also delete the associated triggers
|
| | | $db->loadModule('Reverse', null, true);
|
| | | $definition = $db->reverse->getTableConstraintDefinition($table, $name);
|
| | | if (!PEAR::isError($definition) && !empty($definition['foreign'])) {
|
| | | //first drop the FK enforcing triggers
|
| | | $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | //then drop the constraint itself
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | $name = $db->quoteIdentifier($db->getIndexName($name), true);
|
| | | $query = "ALTER TABLE $table DROP FOREIGN KEY $name";
|
| | | return $db->exec($query);
|
| | | }
|
| | |
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | $name = $db->quoteIdentifier($db->getIndexName($name), true);
|
| | | $query = "ALTER TABLE $table DROP INDEX $name";
|
| | | }
|
| | | return $db->exec($query);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _createFKTriggers()
|
| | |
|
| | | /**
|
| | | * Create triggers to enforce the FOREIGN KEY constraint on the table
|
| | | *
|
| | | * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql,
|
| | | * we call a non-existent procedure to raise the FK violation message.
|
| | | * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877
|
| | | *
|
| | | * @param string $table table name
|
| | | * @param array $foreign_keys FOREIGN KEY definitions
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access private
|
| | | */
|
| | | function _createFKTriggers($table, $foreign_keys)
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | | // create triggers to enforce FOREIGN KEY constraints
|
| | | if ($db->supports('triggers') && !empty($foreign_keys)) {
|
| | | $table = $db->quoteIdentifier($table, true);
|
| | | foreach ($foreign_keys as $fkname => $fkdef) {
|
| | | if (empty($fkdef)) {
|
| | | continue;
|
| | | }
|
| | | //set actions to 'RESTRICT' if not set
|
| | | $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']);
|
| | | $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']);
|
| | |
|
| | | $trigger_names = array(
|
| | | 'insert' => $fkname.'_insert_trg',
|
| | | 'update' => $fkname.'_update_trg',
|
| | | 'pk_update' => $fkname.'_pk_update_trg',
|
| | | 'pk_delete' => $fkname.'_pk_delete_trg',
|
| | | );
|
| | | $table_fields = array_keys($fkdef['fields']);
|
| | | $referenced_fields = array_keys($fkdef['references']['fields']);
|
| | |
|
| | | //create the ON [UPDATE|DELETE] triggers on the primary table
|
| | | $restrict_action = ' IF (SELECT ';
|
| | | $aliased_fields = array();
|
| | | foreach ($table_fields as $field) {
|
| | | $aliased_fields[] = $table .'.'.$field .' AS '.$field;
|
| | | }
|
| | | $restrict_action .= implode(',', $aliased_fields)
|
| | | .' FROM '.$table
|
| | | .' WHERE ';
|
| | | $conditions = array();
|
| | | $new_values = array();
|
| | | $null_values = array();
|
| | | for ($i=0; $i<count($table_fields); $i++) {
|
| | | $conditions[] = $table_fields[$i] .' = OLD.'.$referenced_fields[$i];
|
| | | $new_values[] = $table_fields[$i] .' = NEW.'.$referenced_fields[$i];
|
| | | $null_values[] = $table_fields[$i] .' = NULL';
|
| | | }
|
| | | $restrict_action .= implode(' AND ', $conditions).') IS NOT NULL'
|
| | | .' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
|
| | | .' END IF;';
|
| | |
|
| | | $cascade_action_update = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
|
| | | $cascade_action_delete = 'DELETE FROM '.$table.' WHERE '.implode(' AND ', $conditions). ';';
|
| | | $setnull_action = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
|
| | |
|
| | | if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
|
| | | $db->loadModule('Reverse', null, true);
|
| | | $default_values = array();
|
| | | foreach ($table_fields as $table_field) {
|
| | | $field_definition = $db->reverse->getTableFieldDefinition($table, $field);
|
| | | if (PEAR::isError($field_definition)) {
|
| | | return $field_definition;
|
| | | }
|
| | | $default_values[] = $table_field .' = '. $field_definition[0]['default'];
|
| | | }
|
| | | $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
|
| | | }
|
| | |
|
| | | $query = 'CREATE TRIGGER %s'
|
| | | .' %s ON '.$fkdef['references']['table']
|
| | | .' FOR EACH ROW BEGIN '
|
| | | .' SET FOREIGN_KEY_CHECKS = 0; '; //only really needed for ON UPDATE CASCADE
|
| | |
|
| | | if ('CASCADE' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $cascade_action_update;
|
| | | } elseif ('SET NULL' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action;
|
| | | } elseif ('SET DEFAULT' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action;
|
| | | } elseif ('NO ACTION' == $fkdef['onupdate']) {
|
| | | $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update');
|
| | | } else {
|
| | | //'RESTRICT'
|
| | | $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update');
|
| | | }
|
| | | if ('CASCADE' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $cascade_action_delete;
|
| | | } elseif ('SET NULL' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action;
|
| | | } elseif ('SET DEFAULT' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action;
|
| | | } elseif ('NO ACTION' == $fkdef['ondelete']) {
|
| | | $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete');
|
| | | } else {
|
| | | //'RESTRICT'
|
| | | $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete');
|
| | | }
|
| | | $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
|
| | | $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
|
| | |
|
| | | $db->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $db->expectError(MDB2_ERROR_CANNOT_CREATE); |
| | | $result = $db->exec($sql_delete);
|
| | | $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table';
|
| | | $db->popExpect();
|
| | | $db->popErrorHandling();
|
| | | if (PEAR::isError($result)) {
|
| | | if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
|
| | | return $result;
|
| | | }
|
| | | $db->warnings[] = $expected_errmsg;
|
| | | }
|
| | | $db->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $db->expectError(MDB2_ERROR_CANNOT_CREATE);
|
| | | $result = $db->exec($sql_update);
|
| | | $db->popExpect();
|
| | | $db->popErrorHandling();
|
| | | if (PEAR::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
|
| | | if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
|
| | | return $result;
|
| | | }
|
| | | $db->warnings[] = $expected_errmsg;
|
| | | }
|
| | | }
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _dropFKTriggers()
|
| | |
|
| | | /**
|
| | | * Drop the triggers created to enforce the FOREIGN KEY constraint on the table
|
| | | *
|
| | | * @param string $table table name
|
| | | * @param string $fkname FOREIGN KEY constraint name
|
| | | * @param string $referenced_table referenced table name
|
| | | *
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access private
|
| | | */
|
| | | function _dropFKTriggers($table, $fkname, $referenced_table)
|
| | | {
|
| | | $db =& $this->getDBInstance();
|
| | | if (PEAR::isError($db)) {
|
| | | return $db;
|
| | | }
|
| | |
|
| | | $triggers = $this->listTableTriggers($table);
|
| | | $triggers2 = $this->listTableTriggers($referenced_table);
|
| | | if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) {
|
| | | $triggers = array_merge($triggers, $triggers2);
|
| | | $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i';
|
| | | foreach ($triggers as $trigger) {
|
| | | if (preg_match($pattern, $trigger)) {
|
| | | $result = $db->exec('DROP TRIGGER '.$trigger);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | $query = 'SHOW CREATE TABLE '. $db->escape($table);
|
| | | $definition = $db->queryOne($query, 'text', 1);
|
| | | if (!PEAR::isError($definition) && !empty($definition)) {
|
| | | $pattern = '/\bCONSTRAINT\s+([^\s]+)\s+FOREIGN KEY\b/i';
|
| | | if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 1) {
|
| | | $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims';
|
| | | if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) {
|
| | | foreach ($matches[1] as $constraint) {
|
| | | $result[$constraint] = true;
|
| | | }
|
| | |
| | | }
|
| | | if ($type) {
|
| | | $options_strings[] = "ENGINE = $type";
|
| | | }
|
| | |
|
| | | if (!empty($options_strings)) {
|
| | | $query.= ' '.implode(' ', $options_strings);
|
| | | }
|
| | |
|
| | | $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))";
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Paul Cooper <pgc@ucecom.com> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: pgsql.php,v 1.74 2007/12/03 20:59:15 quipo Exp $
|
| | | // $Id: pgsql.php,v 1.82 2008/03/05 12:55:57 afz Exp $ |
| | |
|
| | | require_once 'MDB2/Driver/Manager/Common.php';
|
| | |
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ 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()
|
| | |
|
| | | /**
|
| | |
| | | }
|
| | |
|
| | | $name = $db->quoteIdentifier($name, true);
|
| | | return $db->standaloneQuery("DROP DATABASE $name", null, true);
|
| | | $query = "DROP DATABASE $name"; |
| | | return $db->standaloneQuery($query, null, true); |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | $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); |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | if (!empty($changes['add']) && is_array($changes['add'])) {
|
| | | foreach ($changes['add'] as $field_name => $field) {
|
| | | $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
|
| | | 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['remove']) && is_array($changes['remove'])) {
|
| | | foreach ($changes['remove'] as $field_name => $field) {
|
| | | if (!empty($changes['rename']) && is_array($changes['rename'])) { |
| | | foreach ($changes['rename'] as $field_name => $field) { |
| | | $field_name = $db->quoteIdentifier($field_name, true);
|
| | | $query = 'DROP ' . $field_name;
|
| | | $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 (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;
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | }
|
| | |
|
| | | $table = $db->quote($table, 'text');
|
| | | $subquery = "SELECT indexrelid FROM pg_index, pg_class";
|
| | | $subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')";
|
| | | $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
|
| | | $query = 'SELECT conname |
| | | FROM pg_constraint, pg_class |
| | | WHERE pg_constraint.conrelid = pg_class.oid |
| | | AND relname = ' .$table; |
| | | $constraints = $db->queryCol($query);
|
| | | if (PEAR::isError($constraints)) {
|
| | | return $constraints;
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith, Lorenzo Alberton |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Lorenzo Alberton <l.alberton@quipo.it> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: sqlite.php,v 1.72 2007/12/03 20:59:15 quipo Exp $
|
| | | // $Id: sqlite.php,v 1.74 2008/03/05 11:08:53 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Manager/Common.php';
|
| | |
| | |
|
| | | $name = $db->quoteIdentifier($name, true);
|
| | | return $db->exec("DROP 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($table)) {
|
| | | $query .= ' '.$db->quoteIdentifier($table, true);
|
| | | }
|
| | | return $db->exec($query);
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | if (PEAR::isError($table_def)) {
|
| | | return $table_def;
|
| | | }
|
| | | if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $table_def, $tmp)) {
|
| | | if (preg_match("/\bPRIMARY\s+KEY\b/i", $table_def, $tmp)) {
|
| | | $result['primary'] = true;
|
| | | }
|
| | |
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id: Common.php,v 1.41 2007/09/09 13:47:36 quipo Exp $ |
| | | // $Id: Common.php,v 1.42 2008/01/12 12:50:58 quipo Exp $
|
| | | // |
| | | |
| | | /** |
| | |
| | | } |
| | | } |
| | | |
| | | $res = array();
|
| | |
|
| | | if ($mode) { |
| | | $res['num_fields'] = count($fields); |
| | | } |
| | |
| | | // | Lorenzo Alberton <l.alberton@quipo.it> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mssql.php,v 1.48 2007/11/25 13:38:29 quipo Exp $
|
| | | // $Id: mssql.php,v 1.49 2008/02/17 15:30:57 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Reverse/Common.php';
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Lorenzo Alberton <l.alberton@quipo.it> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: pgsql.php,v 1.68 2007/11/25 13:38:29 quipo Exp $
|
| | | // $Id: pgsql.php,v 1.70 2008/03/13 20:38:09 quipo Exp $
|
| | |
|
| | | require_once 'MDB2/Driver/Reverse/Common.php';
|
| | |
|
| | |
| | | $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.conkey)
|
| | | LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey)
|
| | | WHERE c.conname = %s
|
| | | AND t.relname = ' . $db->quote($definition['references']['table'], 'text');
|
| | | $constraint_name_mdb2 = $db->getIndexName($constraint_name);
|
| | |
| | | WHEN 24 THEN 'UPDATE, DELETE'
|
| | | WHEN 12 THEN 'INSERT, DELETE'
|
| | | END AS trigger_event,
|
| | | trg.tgenabled AS trigger_enabled,
|
| | | 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,
|
| | |
| | | // | Lorenzo Alberton <l.alberton@quipo.it> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: sqlite.php,v 1.78 2007/12/01 10:46:13 quipo Exp $
|
| | | // $Id: sqlite.php,v 1.79 2008/03/05 11:08:53 quipo Exp $
|
| | | //
|
| | |
|
| | | require_once 'MDB2/Driver/Reverse/Common.php';
|
| | |
| | | }
|
| | | 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+
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith, Frank M. Kromann |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Frank M. Kromann <frank@kromann.info> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mssql.php,v 1.161 2007/11/18 17:52:00 quipo Exp $
|
| | | // $Id: mssql.php,v 1.174 2008/03/08 14:18:39 quipo Exp $
|
| | | //
|
| | | // {{{ Class MDB2_Driver_mssql
|
| | | /**
|
| | |
| | | $this->supported['LOBs'] = true;
|
| | | $this->supported['replace'] = 'emulated';
|
| | | $this->supported['sub_selects'] = true;
|
| | | $this->supported['triggers'] = true;
|
| | | $this->supported['auto_increment'] = true;
|
| | | $this->supported['primary_key'] = true;
|
| | | $this->supported['result_introspection'] = true;
|
| | |
| | | $this->supported['pattern_escaping'] = true;
|
| | | $this->supported['new_link'] = true;
|
| | |
|
| | | $this->options['DBA_username'] = false;
|
| | | $this->options['DBA_password'] = false;
|
| | | $this->options['database_device'] = false;
|
| | | $this->options['database_size'] = false;
|
| | | $this->options['max_identifiers_length'] = 128; // MS Access: 64
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | * @return array
|
| | | * @access public
|
| | | */
|
| | | function errorInfo($error = null)
|
| | | function errorInfo($error = null, $connection = null)
|
| | | {
|
| | | if (is_null($connection)) {
|
| | | $connection = $this->connection;
|
| | | }
|
| | |
|
| | | $native_code = null;
|
| | | if ($this->connection) {
|
| | | $result = @mssql_query('select @@ERROR as ErrorCode', $this->connection);
|
| | | if ($connection) {
|
| | | $result = @mssql_query('select @@ERROR as ErrorCode', $connection);
|
| | | if ($result) {
|
| | | $native_code = @mssql_result($result, 0, 0);
|
| | | @mssql_free_result($result);
|
| | |
| | | 336 => MDB2_ERROR_SYNTAX,
|
| | | 515 => MDB2_ERROR_CONSTRAINT_NOT_NULL,
|
| | | 547 => MDB2_ERROR_CONSTRAINT,
|
| | | 911 => MDB2_ERROR_NOT_FOUND,
|
| | | 1018 => MDB2_ERROR_SYNTAX,
|
| | | 1035 => MDB2_ERROR_SYNTAX,
|
| | | 1801 => MDB2_ERROR_ALREADY_EXISTS,
|
| | | 1913 => MDB2_ERROR_ALREADY_EXISTS,
|
| | | 2209 => MDB2_ERROR_SYNTAX,
|
| | | 2223 => MDB2_ERROR_SYNTAX,
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _doConnect()
|
| | |
|
| | | /**
|
| | | * do the grunt work of the connect
|
| | | *
|
| | | * @return connection on success or MDB2 Error Object on failure
|
| | | * @access protected
|
| | | */
|
| | | function _doConnect($username, $password, $persistent = false)
|
| | | {
|
| | | if (!PEAR::loadExtension($this->phptype) && !PEAR::loadExtension('sybase_ct')) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | |
|
| | | $params = array(
|
| | | $this->dsn['hostspec'] ? $this->dsn['hostspec'] : 'localhost',
|
| | | $username ? $username : null,
|
| | | $password ? $password : null,
|
| | | );
|
| | | if ($this->dsn['port']) {
|
| | | $params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port'];
|
| | | }
|
| | | if (!$persistent) {
|
| | | if (isset($this->dsn['new_link'])
|
| | | && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)
|
| | | ) {
|
| | | $params[] = true;
|
| | | } else {
|
| | | $params[] = false;
|
| | | }
|
| | | }
|
| | |
|
| | | $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
|
| | |
|
| | | $connection = @call_user_func_array($connect_function, $params);
|
| | | if ($connection <= 0) {
|
| | | return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | | 'unable to establish a connection', __FUNCTION__, __FUNCTION__);
|
| | | }
|
| | |
|
| | | @mssql_query('SET ANSI_NULL_DFLT_ON ON', $connection);
|
| | |
|
| | | if (!empty($this->dsn['charset'])) {
|
| | | $result = $this->setCharset($this->dsn['charset'], $connection);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | }
|
| | |
|
| | | if ((bool)ini_get('mssql.datetimeconvert')) {
|
| | | @ini_set('mssql.datetimeconvert', '0');
|
| | | }
|
| | |
|
| | | if (empty($this->dsn['disable_iso_date'])) {
|
| | | @mssql_query('SET DATEFORMAT ymd', $connection);
|
| | | }
|
| | |
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ connect()
|
| | |
|
| | | /**
|
| | |
| | | $this->disconnect(false);
|
| | | }
|
| | |
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | |
|
| | | $params = array(
|
| | | $this->dsn['hostspec'] ? $this->dsn['hostspec'] : 'localhost',
|
| | | $this->dsn['username'] ? $this->dsn['username'] : null,
|
| | | $this->dsn['password'] ? $this->dsn['password'] : null,
|
| | | $connection = $this->_doConnect(
|
| | | $this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->options['persistent']
|
| | | );
|
| | | if ($this->dsn['port']) {
|
| | | $params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port'];
|
| | | }
|
| | | if (!$this->options['persistent']) {
|
| | | if (isset($this->dsn['new_link'])
|
| | | && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)
|
| | | ) {
|
| | | $params[] = true;
|
| | | } else {
|
| | | $params[] = false;
|
| | | }
|
| | | }
|
| | |
|
| | | $connect_function = $this->options['persistent'] ? 'mssql_pconnect' : 'mssql_connect';
|
| | |
|
| | | $connection = @call_user_func_array($connect_function, $params);
|
| | | if ($connection <= 0) {
|
| | | return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | | 'unable to establish a connection', __FUNCTION__, __FUNCTION__);
|
| | | }
|
| | |
|
| | | if (!empty($this->dsn['charset'])) {
|
| | | $result = $this->setCharset($this->dsn['charset'], $connection);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | }
|
| | |
|
| | | if ((bool)ini_get('mssql.datetimeconvert')) {
|
| | | @ini_set('mssql.datetimeconvert', '0');
|
| | | }
|
| | |
|
| | | if (empty($this->dsn['disable_iso_date'])) {
|
| | | @mssql_query('SET DATEFORMAT ymd', $connection);
|
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $this->connection = $connection;
|
| | |
| | | }
|
| | |
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ databaseExists()
|
| | |
|
| | | /**
|
| | | * check if given database name is exists?
|
| | | *
|
| | | * @param string $name name of the database that should be checked
|
| | | *
|
| | | * @return mixed true/false on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function databaseExists($name)
|
| | | {
|
| | | $connection = $this->_doConnect($this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->options['persistent']);
|
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $result = @mssql_select_db($name, $connection);
|
| | | $errorInfo = $this->errorInfo(null, $connection);
|
| | | @mssql_close($connection);
|
| | | if (!$result) {
|
| | | if ($errorInfo[0] != MDB2_ERROR_NOT_FOUND) {
|
| | | exit;
|
| | | $result = $this->raiseError($errorInfo[0], null, null, $errorInfo[2], __FUNCTION__);
|
| | | return $result;
|
| | | }
|
| | | $result = false;
|
| | | }
|
| | |
|
| | | return $result;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | }
|
| | | }
|
| | | return parent::disconnect($force);
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ standaloneQuery()
|
| | |
|
| | | /**
|
| | | * execute a query as DBA
|
| | | *
|
| | | * @param string $query the SQL query
|
| | | * @param mixed $types array that contains the types of the columns in
|
| | | * the result set
|
| | | * @param boolean $is_manip if the query is a manipulation query
|
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function &standaloneQuery($query, $types = null, $is_manip = false)
|
| | | {
|
| | | $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username'];
|
| | | $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password'];
|
| | | $connection = $this->_doConnect($user, $pass, $this->options['persistent']);
|
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $offset = $this->offset;
|
| | | $limit = $this->limit;
|
| | | $this->offset = $this->limit = 0;
|
| | | $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
|
| | | |
| | | $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name);
|
| | | if (!PEAR::isError($result)) {
|
| | | $result = $this->_affectedRows($connection, $result);
|
| | | }
|
| | |
|
| | | @mssql_close($connection);
|
| | | return $result;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | // cache server_info
|
| | | $this->connected_server_info = $server_info;
|
| | | if (!$native && !PEAR::isError($server_info)) {
|
| | | if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $server_info, $tmp)) {
|
| | | if (preg_match('/(\d+)\.(\d+)\.(\d+)/', $server_info, $tmp)) {
|
| | | $server_info = array(
|
| | | 'major' => $tmp[1],
|
| | | 'minor' => $tmp[2],
|
| | |
| | | {
|
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
|
| | | $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
|
| | | $this->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $this->expectError(MDB2_ERROR_NOSUCHTABLE);
|
| | |
|
| | | $seq_val = $this->_checkSequence($sequence_name);
|
| | |
| | | }
|
| | | $result =& $this->_doQuery($query, true);
|
| | | $this->popExpect();
|
| | | $this->popErrorHandling();
|
| | | if (PEAR::isError($result)) {
|
| | | if ($ondemand && !$this->_checkSequence($sequence_name)) {
|
| | | $this->loadModule('Manager', null, true);
|
| | |
| | | *
|
| | | * @param string $table name of the table into which a new row was inserted
|
| | | * @param string $field name of the field into which a new row was inserted
|
| | | *
|
| | | * @return mixed MDB2 Error Object or id
|
| | | * @access public
|
| | | */
|
| | |
| | | if (is_array($server_info) && !is_null($server_info['major'])
|
| | | && $server_info['major'] >= 8
|
| | | ) {
|
| | | $query = "SELECT SCOPE_IDENTITY()";
|
| | | $query = "SELECT IDENT_CURRENT('$table')";
|
| | | } else {
|
| | | $query = "SELECT @@IDENTITY";
|
| | | if (!is_null($table)) {
|
| | | $query .= ' FROM '.$this->quoteIdentifier($table, true);
|
| | | }
|
| | | }
|
| | |
|
| | | return $this->queryOne($query, 'integer');
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mysql.php,v 1.195 2007/11/10 13:27:03 quipo Exp $
|
| | | // $Id: mysql.php,v 1.208 2008/03/13 03:31:55 afz Exp $ |
| | | //
|
| | |
|
| | | /**
|
| | |
| | | $this->supported['LOBs'] = true;
|
| | | $this->supported['replace'] = true;
|
| | | $this->supported['sub_selects'] = 'emulated';
|
| | | $this->supported['triggers'] = false; |
| | | $this->supported['auto_increment'] = true;
|
| | | $this->supported['primary_key'] = true;
|
| | | $this->supported['result_introspection'] = true;
|
| | |
| | | $this->supported['pattern_escaping'] = true;
|
| | | $this->supported['new_link'] = true;
|
| | |
|
| | | $this->options['DBA_username'] = false; |
| | | $this->options['DBA_password'] = false; |
| | | $this->options['default_table_type'] = '';
|
| | | $this->options['max_identifiers_length'] = 64; |
| | | |
| | | $this->_reCheckSupportedOptions(); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ _reCheckSupportedOptions() |
| | | |
| | | /** |
| | | * If the user changes certain options, other capabilities may depend |
| | | * on the new settings, so we need to check them (again). |
| | | * |
| | | * @access private |
| | | */ |
| | | function _reCheckSupportedOptions() |
| | | { |
| | | $this->supported['transactions'] = $this->options['use_transactions']; |
| | | $this->supported['savepoints'] = $this->options['use_transactions']; |
| | | if ($this->options['default_table_type']) { |
| | | switch (strtoupper($this->options['default_table_type'])) { |
| | | case 'BLACKHOLE': |
| | | case 'MEMORY': |
| | | case 'ARCHIVE': |
| | | case 'CSV': |
| | | case 'HEAP': |
| | | case 'ISAM': |
| | | case 'MERGE': |
| | | case 'MRG_ISAM': |
| | | case 'ISAM': |
| | | case 'MRG_MYISAM': |
| | | case 'MYISAM': |
| | | $this->supported['savepoints'] = false; |
| | | $this->supported['transactions'] = false; |
| | | $this->warnings[] = $this->options['default_table_type'] . |
| | | ' is not a supported default table type'; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function setOption($option, $value) |
| | | |
| | | /** |
| | | * set the option for the db class |
| | | * |
| | | * @param string option name |
| | | * @param mixed value for the option |
| | | * |
| | | * @return mixed MDB2_OK or MDB2 Error Object |
| | | * |
| | | * @access public |
| | | */ |
| | | function setOption($option, $value) |
| | | { |
| | | $res = parent::setOption($option, $value); |
| | | $this->_reCheckSupportedOptions(); |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | 1216 => MDB2_ERROR_CONSTRAINT,
|
| | | 1217 => MDB2_ERROR_CONSTRAINT,
|
| | | 1227 => MDB2_ERROR_ACCESS_VIOLATION,
|
| | | 1235 => MDB2_ERROR_CANNOT_CREATE, |
| | | 1299 => MDB2_ERROR_INVALID_DATE,
|
| | | 1300 => MDB2_ERROR_INVALID,
|
| | | 1304 => MDB2_ERROR_ALREADY_EXISTS,
|
| | |
| | | 1542 => MDB2_ERROR_CANNOT_DROP,
|
| | | 1546 => MDB2_ERROR_CONSTRAINT,
|
| | | 1582 => MDB2_ERROR_CONSTRAINT,
|
| | | 2003 => MDB2_ERROR_CONNECT_FAILED, |
| | | 2019 => MDB2_ERROR_INVALID, |
| | | );
|
| | | }
|
| | | if ($this->options['portability'] & MDB2_PORTABILITY_ERRORS) {
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ connect()
|
| | | // {{{ _doConnect() |
| | |
|
| | | /**
|
| | | * Connect to the database
|
| | | * do the grunt work of the connect |
| | | *
|
| | | * @return true on success, MDB2 Error Object on failure
|
| | | * @return connection on success or MDB2 Error Object on failure |
| | | * @access protected |
| | | */
|
| | | function connect()
|
| | | function _doConnect($username, $password, $persistent = false) |
| | | {
|
| | | if (is_resource($this->connection)) {
|
| | | //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
|
| | | if (MDB2::areEquals($this->connected_dsn, $this->dsn)
|
| | | && $this->opened_persistent == $this->options['persistent']
|
| | | && $this->connected_database_name == $this->database_name
|
| | | ) {
|
| | | return MDB2_OK;
|
| | | }
|
| | | $this->disconnect(false);
|
| | | }
|
| | |
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | |
| | | $params[0].= ':' . $this->dsn['port'];
|
| | | }
|
| | | }
|
| | | $params[] = $this->dsn['username'] ? $this->dsn['username'] : null;
|
| | | $params[] = $this->dsn['password'] ? $this->dsn['password'] : null;
|
| | | if (!$this->options['persistent']) {
|
| | | $params[] = $username ? $username : null; |
| | | $params[] = $password ? $password : null; |
| | | if (!$persistent) { |
| | | if (isset($this->dsn['new_link'])
|
| | | && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)
|
| | | ) {
|
| | |
| | | $params[] = isset($this->dsn['client_flags'])
|
| | | ? $this->dsn['client_flags'] : null;
|
| | | }
|
| | | $connect_function = $this->options['persistent'] ? 'mysql_pconnect' : 'mysql_connect';
|
| | | $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; |
| | |
|
| | | $connection = @call_user_func_array($connect_function, $params);
|
| | | if (!$connection) {
|
| | |
| | | if (!empty($this->dsn['charset'])) {
|
| | | $result = $this->setCharset($this->dsn['charset'], $connection);
|
| | | if (PEAR::isError($result)) {
|
| | | $this->disconnect(false); |
| | | return $result;
|
| | | }
|
| | | } |
| | | |
| | | return $connection; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ connect() |
| | | |
| | | /** |
| | | * Connect to the database |
| | | * |
| | | * @return MDB2_OK on success, MDB2 Error Object on failure |
| | | * @access public |
| | | */ |
| | | function connect() |
| | | { |
| | | if (is_resource($this->connection)) { |
| | | //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 |
| | | if (MDB2::areEquals($this->connected_dsn, $this->dsn) |
| | | && $this->opened_persistent == $this->options['persistent'] |
| | | ) { |
| | | return MDB2_OK; |
| | | } |
| | | $this->disconnect(false); |
| | | } |
| | | |
| | | $connection = $this->_doConnect( |
| | | $this->dsn['username'], |
| | | $this->dsn['password'], |
| | | $this->options['persistent'] |
| | | ); |
| | | if (PEAR::isError($connection)) { |
| | | return $connection; |
| | | }
|
| | |
|
| | | $this->connection = $connection;
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | $this->supported['transactions'] = $this->options['use_transactions'];
|
| | | if ($this->options['default_table_type']) {
|
| | | switch (strtoupper($this->options['default_table_type'])) {
|
| | | case 'BLACKHOLE':
|
| | | case 'MEMORY':
|
| | | case 'ARCHIVE':
|
| | | case 'CSV':
|
| | | case 'HEAP':
|
| | | case 'ISAM':
|
| | | case 'MERGE':
|
| | | case 'MRG_ISAM':
|
| | | case 'ISAM':
|
| | | case 'MRG_MYISAM':
|
| | | case 'MYISAM':
|
| | | $this->supported['transactions'] = false;
|
| | | $this->warnings[] = $this->options['default_table_type'] .
|
| | | ' is not a supported default table type';
|
| | | break;
|
| | | }
|
| | | }
|
| | | |
| | | $this->_getServerCapabilities();
|
| | |
|
| | | return MDB2_OK;
|
| | |
| | | /**
|
| | | * Set the charset on the current connection
|
| | | *
|
| | | * @param string charset
|
| | | * @param string charset (or array(charset, collation)) |
| | | * @param resource connection handle
|
| | | *
|
| | | * @return true on success, MDB2 Error Object on failure
|
| | |
| | | return $connection;
|
| | | }
|
| | | }
|
| | | $collation = null; |
| | | if (is_array($charset) && 2 == count($charset)) { |
| | | $collation = array_pop($charset); |
| | | $charset = array_pop($charset); |
| | | } |
| | | $query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'";
|
| | | if (!is_null($collation)) { |
| | | $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; |
| | | } |
| | | return $this->_doQuery($query, true, $connection);
|
| | | } |
| | | |
| | | // }}} |
| | | // {{{ databaseExists() |
| | | |
| | | /** |
| | | * check if given database name is exists? |
| | | * |
| | | * @param string $name name of the database that should be checked |
| | | * |
| | | * @return mixed true/false on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function databaseExists($name) |
| | | { |
| | | $connection = $this->_doConnect($this->dsn['username'], |
| | | $this->dsn['password'], |
| | | $this->options['persistent']); |
| | | if (PEAR::isError($connection)) { |
| | | return $connection; |
| | | } |
| | | |
| | | $result = @mysql_select_db($name, $connection); |
| | | @mysql_close($connection); |
| | | |
| | | return $result; |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | }
|
| | | }
|
| | | return parent::disconnect($force);
|
| | | } |
| | | |
| | | // }}} |
| | | // {{{ standaloneQuery() |
| | | |
| | | /** |
| | | * execute a query as DBA |
| | | * |
| | | * @param string $query the SQL query |
| | | * @param mixed $types array that contains the types of the columns in |
| | | * the result set |
| | | * @param boolean $is_manip if the query is a manipulation query |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function &standaloneQuery($query, $types = null, $is_manip = false) |
| | | { |
| | | $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; |
| | | $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; |
| | | $connection = $this->_doConnect($user, $pass, $this->options['persistent']); |
| | | if (PEAR::isError($connection)) { |
| | | return $connection; |
| | | } |
| | | |
| | | $offset = $this->offset; |
| | | $limit = $this->limit; |
| | | $this->offset = $this->limit = 0; |
| | | $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); |
| | | |
| | | $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); |
| | | if (!PEAR::isError($result)) { |
| | | $result = $this->_affectedRows($connection, $result); |
| | | } |
| | | |
| | | @mysql_close($connection); |
| | | return $result; |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | //set defaults
|
| | | $this->supported['sub_selects'] = 'emulated';
|
| | | $this->supported['prepared_statements'] = 'emulated';
|
| | | $this->supported['triggers'] = false; |
| | | $this->start_transaction = false;
|
| | | $this->varchar_max_length = 255;
|
| | |
|
| | | $server_info = $this->getServerVersion();
|
| | | if (is_array($server_info)) {
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.0', '<')) {
|
| | | $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch']; |
| | | |
| | | if (!version_compare($server_version, '4.1.0', '<')) { |
| | | $this->supported['sub_selects'] = true;
|
| | | $this->supported['prepared_statements'] = true;
|
| | | }
|
| | |
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.14', '<')
|
| | | || !version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.1', '<')
|
| | | ) {
|
| | | $this->supported['savepoints'] = true;
|
| | | // SAVEPOINTs were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB) |
| | | if (version_compare($server_version, '4.1.0', '>=')) { |
| | | if (version_compare($server_version, '4.1.1', '<')) { |
| | | $this->supported['savepoints'] = false; |
| | | } |
| | | } elseif (version_compare($server_version, '4.0.14', '<')) { |
| | | $this->supported['savepoints'] = false; |
| | | }
|
| | |
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.11', '<')) {
|
| | | if (!version_compare($server_version, '4.0.11', '<')) { |
| | | $this->start_transaction = true;
|
| | | }
|
| | |
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) {
|
| | | if (!version_compare($server_version, '5.0.3', '<')) { |
| | | $this->varchar_max_length = 65532;
|
| | | } |
| | | |
| | | if (!version_compare($server_version, '5.0.2', '<')) { |
| | | $this->supported['triggers'] = true; |
| | | }
|
| | | }
|
| | | }
|
| | |
| | | return $connection;
|
| | | }
|
| | | static $prep_statement_counter = 1;
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++;
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); |
| | | $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); |
| | | $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text');
|
| | | $statement =& $this->_doQuery($query, true, $connection);
|
| | | if (PEAR::isError($statement)) {
|
| | |
| | | $query .= ',';
|
| | | $values.= ',';
|
| | | }
|
| | | $query.= $name;
|
| | | $query.= $this->quoteIdentifier($name, true); |
| | | if (isset($fields[$name]['null']) && $fields[$name]['null']) {
|
| | | $value = 'NULL';
|
| | | } else {
|
| | |
| | | return $connection;
|
| | | }
|
| | |
|
| | | $table = $this->quoteIdentifier($table, true); |
| | | $query = "REPLACE INTO $table ($query) VALUES ($values)";
|
| | | $result =& $this->_doQuery($query, true, $connection);
|
| | | if (PEAR::isError($result)) {
|
| | |
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
|
| | | $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
|
| | | $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
|
| | | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
| | | $this->expectError(MDB2_ERROR_NOSUCHTABLE);
|
| | | $result =& $this->_doQuery($query, true);
|
| | | $this->popExpect();
|
| | | $this->popErrorHandling(); |
| | | if (PEAR::isError($result)) {
|
| | | if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
|
| | | $this->loadModule('Manager', null, true);
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: mysqli.php,v 1.176 2007/11/10 13:27:03 quipo Exp $
|
| | | // $Id: mysqli.php,v 1.188 2008/03/13 03:31:55 afz Exp $ |
| | | //
|
| | |
|
| | | /**
|
| | |
| | | $this->supported['LOBs'] = true;
|
| | | $this->supported['replace'] = true;
|
| | | $this->supported['sub_selects'] = 'emulated';
|
| | | $this->supported['triggers'] = false; |
| | | $this->supported['auto_increment'] = true;
|
| | | $this->supported['primary_key'] = true;
|
| | | $this->supported['result_introspection'] = true;
|
| | |
| | | $this->supported['pattern_escaping'] = true;
|
| | | $this->supported['new_link'] = true;
|
| | |
|
| | | $this->options['DBA_username'] = false; |
| | | $this->options['DBA_password'] = false; |
| | | $this->options['default_table_type'] = '';
|
| | | $this->options['multi_query'] = false;
|
| | | $this->options['max_identifiers_length'] = 64; |
| | | |
| | | $this->_reCheckSupportedOptions(); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ _reCheckSupportedOptions() |
| | | |
| | | /** |
| | | * If the user changes certain options, other capabilities may depend |
| | | * on the new settings, so we need to check them (again). |
| | | * |
| | | * @access private |
| | | */ |
| | | function _reCheckSupportedOptions() |
| | | { |
| | | $this->supported['transactions'] = $this->options['use_transactions']; |
| | | $this->supported['savepoints'] = $this->options['use_transactions']; |
| | | if ($this->options['default_table_type']) { |
| | | switch (strtoupper($this->options['default_table_type'])) { |
| | | case 'BLACKHOLE': |
| | | case 'MEMORY': |
| | | case 'ARCHIVE': |
| | | case 'CSV': |
| | | case 'HEAP': |
| | | case 'ISAM': |
| | | case 'MERGE': |
| | | case 'MRG_ISAM': |
| | | case 'ISAM': |
| | | case 'MRG_MYISAM': |
| | | case 'MYISAM': |
| | | $this->supported['savepoints'] = false; |
| | | $this->supported['transactions'] = false; |
| | | $this->warnings[] = $this->options['default_table_type'] . |
| | | ' is not a supported default table type'; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ function setOption($option, $value) |
| | | |
| | | /** |
| | | * set the option for the db class |
| | | * |
| | | * @param string option name |
| | | * @param mixed value for the option |
| | | * |
| | | * @return mixed MDB2_OK or MDB2 Error Object |
| | | * |
| | | * @access public |
| | | */ |
| | | function setOption($option, $value) |
| | | { |
| | | $res = parent::setOption($option, $value); |
| | | $this->_reCheckSupportedOptions(); |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | 1216 => MDB2_ERROR_CONSTRAINT,
|
| | | 1217 => MDB2_ERROR_CONSTRAINT,
|
| | | 1227 => MDB2_ERROR_ACCESS_VIOLATION,
|
| | | 1235 => MDB2_ERROR_CANNOT_CREATE, |
| | | 1299 => MDB2_ERROR_INVALID_DATE,
|
| | | 1300 => MDB2_ERROR_INVALID,
|
| | | 1304 => MDB2_ERROR_ALREADY_EXISTS,
|
| | |
| | | 1542 => MDB2_ERROR_CANNOT_DROP,
|
| | | 1546 => MDB2_ERROR_CONSTRAINT,
|
| | | 1582 => MDB2_ERROR_CONSTRAINT,
|
| | | 2003 => MDB2_ERROR_CONNECT_FAILED, |
| | | 2019 => MDB2_ERROR_INVALID,
|
| | | );
|
| | | }
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ _doConnect() |
| | | |
| | | /** |
| | | * do the grunt work of the connect |
| | | * |
| | | * @return connection on success or MDB2 Error Object on failure |
| | | * @access protected |
| | | */ |
| | | function _doConnect($username, $password, $persistent = false) |
| | | { |
| | | if (!PEAR::loadExtension($this->phptype)) { |
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); |
| | | } |
| | | |
| | | $connection = @mysqli_init(); |
| | | if (!empty($this->dsn['charset']) && defined('MYSQLI_SET_CHARSET_NAME')) { |
| | | @mysqli_options($connection, MYSQLI_SET_CHARSET_NAME, $this->dsn['charset']); |
| | | } |
| | | |
| | | if ($this->options['ssl']) { |
| | | @mysqli_ssl_set( |
| | | $connection, |
| | | empty($this->dsn['key']) ? null : $this->dsn['key'], |
| | | empty($this->dsn['cert']) ? null : $this->dsn['cert'], |
| | | empty($this->dsn['ca']) ? null : $this->dsn['ca'], |
| | | empty($this->dsn['capath']) ? null : $this->dsn['capath'], |
| | | empty($this->dsn['cipher']) ? null : $this->dsn['cipher'] |
| | | ); |
| | | } |
| | | |
| | | if (!@mysqli_real_connect( |
| | | $connection, |
| | | $this->dsn['hostspec'], |
| | | $username, |
| | | $password, |
| | | $this->database_name, |
| | | $this->dsn['port'], |
| | | $this->dsn['socket'] |
| | | )) { |
| | | if (($err = @mysqli_connect_error()) != '') { |
| | | return $this->raiseError(null, |
| | | null, null, $err, __FUNCTION__); |
| | | } else { |
| | | return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, |
| | | 'unable to establish a connection', __FUNCTION__); |
| | | } |
| | | } |
| | | |
| | | if (!empty($this->dsn['charset']) && !defined('MYSQLI_SET_CHARSET_NAME')) { |
| | | $result = $this->setCharset($this->dsn['charset'], $connection); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | |
| | | return $connection; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ connect()
|
| | |
|
| | | /**
|
| | |
| | | $this->connection = 0;
|
| | | }
|
| | |
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | |
|
| | | $connection = @mysqli_init();
|
| | | if (!empty($this->dsn['charset']) && defined('MYSQLI_SET_CHARSET_NAME')) {
|
| | | @mysqli_options($connection, MYSQLI_SET_CHARSET_NAME, $this->dsn['charset']);
|
| | | }
|
| | |
|
| | |
|
| | | if ($this->options['ssl']) {
|
| | | @mysqli_ssl_set(
|
| | | $connection,
|
| | | empty($this->dsn['key']) ? null : $this->dsn['key'],
|
| | | empty($this->dsn['cert']) ? null : $this->dsn['cert'],
|
| | | empty($this->dsn['ca']) ? null : $this->dsn['ca'],
|
| | | empty($this->dsn['capath']) ? null : $this->dsn['capath'],
|
| | | empty($this->dsn['cipher']) ? null : $this->dsn['cipher']
|
| | | );
|
| | | }
|
| | |
|
| | | if (!@mysqli_real_connect(
|
| | | $connection,
|
| | | $this->dsn['hostspec'],
|
| | | $connection = $this->_doConnect( |
| | | $this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->database_name,
|
| | | $this->dsn['port'],
|
| | | $this->dsn['socket']
|
| | | )) {
|
| | |
|
| | | if (($err = @mysqli_connect_error()) != '') {
|
| | | return $this->raiseError(null,
|
| | | null, null, $err, __FUNCTION__);
|
| | | } else {
|
| | | return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | | 'unable to establish a connection', __FUNCTION__);
|
| | | }
|
| | | }
|
| | |
|
| | | if (!empty($this->dsn['charset']) && !defined('MYSQLI_SET_CHARSET_NAME')) {
|
| | | $result = $this->setCharset($this->dsn['charset'], $connection);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | }
|
| | | $this->dsn['password'] |
| | | ); |
| | | if (PEAR::isError($connection)) { |
| | | return $connection; |
| | | }
|
| | |
|
| | | $this->connection = $connection;
|
| | | $this->connected_dsn = $this->dsn;
|
| | | $this->connected_database_name = $this->database_name;
|
| | | $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
|
| | |
|
| | | $this->supported['transactions'] = $this->options['use_transactions'];
|
| | | if ($this->options['default_table_type']) {
|
| | | switch (strtoupper($this->options['default_table_type'])) {
|
| | | case 'BLACKHOLE':
|
| | | case 'MEMORY':
|
| | | case 'ARCHIVE':
|
| | | case 'CSV':
|
| | | case 'HEAP':
|
| | | case 'ISAM':
|
| | | case 'MERGE':
|
| | | case 'MRG_ISAM':
|
| | | case 'ISAM':
|
| | | case 'MRG_MYISAM':
|
| | | case 'MYISAM':
|
| | | $this->supported['transactions'] = false;
|
| | | $this->warnings[] = $this->options['default_table_type'] .
|
| | | ' is not a supported default table type';
|
| | | break;
|
| | | }
|
| | | }
|
| | |
|
| | | $this->_getServerCapabilities();
|
| | |
|
| | |
| | | /**
|
| | | * Set the charset on the current connection
|
| | | *
|
| | | * @param string charset
|
| | | * @param string charset (or array(charset, collation)) |
| | | * @param resource connection handle
|
| | | *
|
| | | * @return true on success, MDB2 Error Object on failure
|
| | |
| | | return $connection;
|
| | | }
|
| | | }
|
| | | $collation = null; |
| | | if (is_array($charset) && 2 == count($charset)) { |
| | | $collation = array_pop($charset); |
| | | $charset = array_pop($charset); |
| | | } |
| | | $client_info = mysqli_get_client_version();
|
| | | if (OS_WINDOWS && ((40111 > $client_info) ||
|
| | | ((50000 <= $client_info) && (50006 > $client_info)))
|
| | | ) {
|
| | | $query = "SET NAMES '".mysqli_real_escape_string($connection, $charset)."'";
|
| | | if (!is_null($collation)) { |
| | | $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; |
| | | } |
| | | return $this->_doQuery($query, true, $connection);
|
| | | }
|
| | | if (!$result = mysqli_set_charset($connection, $charset)) {
|
| | |
| | | 'Could not set client character set', __FUNCTION__);
|
| | | return $err;
|
| | | }
|
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ databaseExists() |
| | | |
| | | /** |
| | | * check if given database name is exists? |
| | | * |
| | | * @param string $name name of the database that should be checked |
| | | * |
| | | * @return mixed true/false on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function databaseExists($name) |
| | | { |
| | | $connection = $this->_doConnect($this->dsn['username'], |
| | | $this->dsn['password']); |
| | | if (PEAR::isError($connection)) { |
| | | return $connection; |
| | | } |
| | | |
| | | $result = @mysqli_select_db($connection, $name); |
| | | @mysqli_close($connection); |
| | | |
| | | return $result;
|
| | | }
|
| | |
|
| | |
| | | }
|
| | | }
|
| | | return parent::disconnect($force);
|
| | | } |
| | | |
| | | // }}} |
| | | // {{{ standaloneQuery() |
| | | |
| | | /** |
| | | * execute a query as DBA |
| | | * |
| | | * @param string $query the SQL query |
| | | * @param mixed $types array that contains the types of the columns in |
| | | * the result set |
| | | * @param boolean $is_manip if the query is a manipulation query |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function &standaloneQuery($query, $types = null, $is_manip = false) |
| | | { |
| | | $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; |
| | | $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; |
| | | $connection = $this->_doConnect($user, $pass); |
| | | if (PEAR::isError($connection)) { |
| | | return $connection; |
| | | } |
| | | |
| | | $offset = $this->offset; |
| | | $limit = $this->limit; |
| | | $this->offset = $this->limit = 0; |
| | | $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); |
| | | |
| | | $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); |
| | | if (!PEAR::isError($result)) { |
| | | $result = $this->_affectedRows($connection, $result); |
| | | } |
| | | |
| | | @mysqli_close($connection); |
| | | return $result; |
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | //set defaults
|
| | | $this->supported['sub_selects'] = 'emulated';
|
| | | $this->supported['prepared_statements'] = 'emulated';
|
| | | $this->supported['triggers'] = false; |
| | | $this->start_transaction = false;
|
| | | $this->varchar_max_length = 255;
|
| | |
|
| | | $server_info = $this->getServerVersion();
|
| | | if (is_array($server_info)) {
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.0', '<')) {
|
| | | $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch']; |
| | | |
| | | if (!version_compare($server_version, '4.1.0', '<')) { |
| | | $this->supported['sub_selects'] = true;
|
| | | $this->supported['prepared_statements'] = true;
|
| | | }
|
| | |
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.14', '<')
|
| | | || !version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.1', '<')
|
| | | ) {
|
| | | $this->supported['savepoints'] = true;
|
| | | // SAVEPOINTS were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB) |
| | | if (version_compare($server_version, '4.1.0', '>=')) { |
| | | if (version_compare($server_version, '4.1.1', '<')) { |
| | | $this->supported['savepoints'] = false; |
| | | } |
| | | } elseif (version_compare($server_version, '4.0.14', '<')) { |
| | | $this->supported['savepoints'] = false; |
| | | }
|
| | |
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.11', '<')) {
|
| | | if (!version_compare($server_version, '4.0.11', '<')) { |
| | | $this->start_transaction = true;
|
| | | }
|
| | |
|
| | | if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) {
|
| | | if (!version_compare($server_version, '5.0.3', '<')) { |
| | | $this->varchar_max_length = 65532;
|
| | | } |
| | | |
| | | if (!version_compare($server_version, '5.0.2', '<')) { |
| | | $this->supported['triggers'] = true; |
| | | }
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | if (!$is_manip) {
|
| | | static $prep_statement_counter = 1;
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++;
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); |
| | | $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); |
| | | $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text');
|
| | |
|
| | | $statement =& $this->_doQuery($query, true, $connection);
|
| | |
| | | $query .= ',';
|
| | | $values.= ',';
|
| | | }
|
| | | $query.= $name;
|
| | | $query.= $this->quoteIdentifier($name, true); |
| | | if (isset($fields[$name]['null']) && $fields[$name]['null']) {
|
| | | $value = 'NULL';
|
| | | } else {
|
| | |
| | | return $connection;
|
| | | }
|
| | |
|
| | | $table = $this->quoteIdentifier($table, true); |
| | | $query = "REPLACE INTO $table ($query) VALUES ($values)";
|
| | | $result =& $this->_doQuery($query, true, $connection);
|
| | | if (PEAR::isError($result)) {
|
| | |
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
|
| | | $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
|
| | | $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
|
| | | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
| | | $this->expectError(MDB2_ERROR_NOSUCHTABLE);
|
| | | $result =& $this->_doQuery($query, true);
|
| | | $this->popExpect();
|
| | | $this->popErrorHandling(); |
| | | if (PEAR::isError($result)) {
|
| | | if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
|
| | | $this->loadModule('Manager', null, true);
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Paul Cooper <pgc@ucecom.com> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: pgsql.php,v 1.186 2007/11/10 13:27:03 quipo Exp $
|
| | | // $Id: pgsql.php,v 1.197 2008/03/08 14:18:39 quipo Exp $
|
| | |
|
| | | /**
|
| | | * MDB2 PostGreSQL driver
|
| | |
| | | $this->supported['LOBs'] = true;
|
| | | $this->supported['replace'] = 'emulated';
|
| | | $this->supported['sub_selects'] = true;
|
| | | $this->supported['triggers'] = true;
|
| | | $this->supported['auto_increment'] = 'emulated';
|
| | | $this->supported['primary_key'] = true;
|
| | | $this->supported['result_introspection'] = true;
|
| | |
| | | $this->supported['pattern_escaping'] = true;
|
| | | $this->supported['new_link'] = true;
|
| | |
|
| | | $this->options['DBA_username'] = false;
|
| | | $this->options['DBA_password'] = false;
|
| | | $this->options['multi_query'] = false;
|
| | | $this->options['disable_smart_seqname'] = false;
|
| | | $this->options['max_identifiers_length'] = 63;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | $native_msg = 'Database connection has been lost.';
|
| | | $error_code = MDB2_ERROR_CONNECT_FAILED;
|
| | | }
|
| | | } else {
|
| | | $native_msg = @pg_last_error();
|
| | | }
|
| | |
|
| | | static $error_regexps;
|
| | |
| | | => MDB2_ERROR_NOSUCHFIELD,
|
| | | '/(relation|sequence|table).*does not exist|class .* not found/i'
|
| | | => MDB2_ERROR_NOSUCHTABLE,
|
| | | '/database .* does not exist/'
|
| | | => MDB2_ERROR_NOT_FOUND,
|
| | | '/index .* does not exist/'
|
| | | => MDB2_ERROR_NOT_FOUND,
|
| | | '/database .* already exists/i'
|
| | | => MDB2_ERROR_ALREADY_EXISTS,
|
| | | '/relation .* already exists/i'
|
| | | => MDB2_ERROR_ALREADY_EXISTS,
|
| | | '/(divide|division) by zero$/i'
|
| | |
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | | if (version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {
|
| | | if (is_resource($connection) && version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {
|
| | | $text = @pg_escape_string($connection, $text);
|
| | | } else {
|
| | | $text = @pg_escape_string($text);
|
| | |
| | | // {{{ _doConnect()
|
| | |
|
| | | /**
|
| | | * Does the grunt work of connecting to the database
|
| | | * Do the grunt work of connecting to the database
|
| | | *
|
| | | * @return mixed connection resource on success, MDB2 Error Object on failure
|
| | | * @access protected
|
| | | **/
|
| | | function _doConnect($database_name, $persistent = false)
|
| | | */
|
| | | function _doConnect($username, $password, $database_name, $persistent = false)
|
| | | {
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | | |
| | | if ($database_name == '') {
|
| | | $database_name = 'template1';
|
| | | }
|
| | |
| | | if ($database_name) {
|
| | | $params[0].= ' dbname=\'' . addslashes($database_name) . '\'';
|
| | | }
|
| | | if ($this->dsn['username']) {
|
| | | $params[0].= ' user=\'' . addslashes($this->dsn['username']) . '\'';
|
| | | if ($username) {
|
| | | $params[0].= ' user=\'' . addslashes($username) . '\'';
|
| | | }
|
| | | if ($this->dsn['password']) {
|
| | | $params[0].= ' password=\'' . addslashes($this->dsn['password']) . '\'';
|
| | | if ($password) {
|
| | | $params[0].= ' password=\'' . addslashes($password) . '\'';
|
| | | }
|
| | | if (!empty($this->dsn['options'])) {
|
| | | $params[0].= ' options=' . $this->dsn['options'];
|
| | |
| | | }
|
| | |
|
| | | $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
|
| | |
|
| | | $connection = @call_user_func_array($connect_function, $params);
|
| | | if (!$connection) {
|
| | | return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | |
| | | *
|
| | | * @return true on success, MDB2 Error Object on failure
|
| | | * @access public
|
| | | **/
|
| | | */
|
| | | function connect()
|
| | | {
|
| | | if (is_resource($this->connection)) {
|
| | |
| | | $this->disconnect(false);
|
| | | }
|
| | |
|
| | | if (!PEAR::loadExtension($this->phptype)) {
|
| | | return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
|
| | | 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
|
| | | }
|
| | |
|
| | | if ($this->database_name) {
|
| | | $connection = $this->_doConnect($this->database_name, $this->options['persistent']);
|
| | | $connection = $this->_doConnect($this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->database_name,
|
| | | $this->options['persistent']);
|
| | | if (PEAR::isError($connection)) {
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $this->connection = $connection;
|
| | | $this->connected_dsn = $this->dsn;
|
| | | $this->connected_database_name = $this->database_name;
|
| | | $this->opened_persistent = $this->options['persistent'];
|
| | | $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
|
| | | }
|
| | |
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | |
| | | return $connection;
|
| | | }
|
| | | }
|
| | |
|
| | | if (is_array($charset)) {
|
| | | $charset = array_shift($charset);
|
| | | $this->warnings[] = 'postgresql does not support setting client collation';
|
| | | }
|
| | | $result = @pg_set_client_encoding($connection, $charset);
|
| | | if ($result == -1) {
|
| | | return $this->raiseError(null, null, null,
|
| | | 'Unable to set client charset: '.$charset, __FUNCTION__);
|
| | | }
|
| | | return MDB2_OK;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ databaseExists()
|
| | |
|
| | | /**
|
| | | * check if given database name is exists?
|
| | | *
|
| | | * @param string $name name of the database that should be checked
|
| | | *
|
| | | * @return mixed true/false on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function databaseExists($name)
|
| | | {
|
| | | $res = $this->_doConnect($this->dsn['username'],
|
| | | $this->dsn['password'],
|
| | | $this->escape($name),
|
| | | $this->options['persistent']);
|
| | | if (!PEAR::isError($res)) {
|
| | | return true;
|
| | | }
|
| | |
|
| | | return false;
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | | */
|
| | | function &standaloneQuery($query, $types = null, $is_manip = false)
|
| | | {
|
| | | $connection = $this->_doConnect('template1', false);
|
| | | $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username'];
|
| | | $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password'];
|
| | | $connection = $this->_doConnect($user, $pass, $this->database_name, $this->options['persistent']);
|
| | | if (PEAR::isError($connection)) {
|
| | | $err =& $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
|
| | | 'Cannot connect to template1', __FUNCTION__);
|
| | | return $err;
|
| | | return $connection;
|
| | | }
|
| | |
|
| | | $offset = $this->offset;
|
| | |
| | | $this->offset = $this->limit = 0;
|
| | | $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
|
| | |
|
| | | $result =& $this->_doQuery($query, $is_manip, $connection, false);
|
| | | @pg_close($connection);
|
| | | if (PEAR::isError($result)) {
|
| | | return $result;
|
| | | $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name);
|
| | | if (!PEAR::isError($result)) {
|
| | | if ($is_manip) {
|
| | | $result = $this->_affectedRows($connection, $result);
|
| | | } else {
|
| | | $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset);
|
| | | }
|
| | | }
|
| | |
|
| | | if ($is_manip) {
|
| | | $affected_rows = $this->_affectedRows($connection, $result);
|
| | | return $affected_rows;
|
| | | }
|
| | | $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset);
|
| | | @pg_close($connection);
|
| | | return $result;
|
| | | }
|
| | |
|
| | |
| | | return $connection;
|
| | | }
|
| | | static $prep_statement_counter = 1;
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++;
|
| | | $statement_name = strtolower($statement_name);
|
| | | $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand()));
|
| | | $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']);
|
| | | if ($pgtypes === false) {
|
| | | $result = @pg_prepare($connection, $statement_name, $query);
|
| | | if (!$result) {
|
| | |
| | | WHERE d.adrelid = a.attrelid
|
| | | AND d.adnum = a.attnum
|
| | | AND a.atthasdef
|
| | | ) FROM 'nextval[^\']*\'([^\']*)')
|
| | | ) FROM 'nextval[^'']*''([^'']*)')
|
| | | FROM pg_attribute a
|
| | | LEFT JOIN pg_class c ON c.oid = a.attrelid
|
| | | LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef
|
| | |
| | | {
|
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
|
| | | $query = "SELECT NEXTVAL('$sequence_name')";
|
| | | $this->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $this->expectError(MDB2_ERROR_NOSUCHTABLE);
|
| | | $result = $this->queryOne($query, 'integer');
|
| | | $this->popExpect();
|
| | | $this->popErrorHandling();
|
| | | if (PEAR::isError($result)) {
|
| | | if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
|
| | | $this->loadModule('Manager', null, true);
|
| | |
| | | return $this->queryOne('SELECT lastval()', 'integer');
|
| | | }
|
| | | $seq = $table.(empty($field) ? '' : '_'.$field);
|
| | | $sequence_name = $this->getSequenceName($seq);
|
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true);
|
| | | return $this->queryOne("SELECT currval('$sequence_name')", 'integer');
|
| | | }
|
| | |
|
| | |
| | | // +----------------------------------------------------------------------+
|
| | | // | PHP versions 4 and 5 |
|
| | | // +----------------------------------------------------------------------+
|
| | | // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
|
| | | // | Stig. S. Bakken, Lukas Smith |
|
| | | // | All rights reserved. |
|
| | | // +----------------------------------------------------------------------+
|
| | |
| | | // | Author: Lukas Smith <smith@pooteeweet.org> |
|
| | | // +----------------------------------------------------------------------+
|
| | | //
|
| | | // $Id: sqlite.php,v 1.152 2007/11/27 07:44:41 quipo Exp $
|
| | | // $Id: sqlite.php,v 1.158 2008/03/08 14:18:39 quipo Exp $
|
| | | //
|
| | |
|
| | | /**
|
| | |
| | | $this->supported['transactions'] = true;
|
| | | $this->supported['savepoints'] = false;
|
| | | $this->supported['sub_selects'] = true;
|
| | | $this->supported['triggers'] = true;
|
| | | $this->supported['auto_increment'] = true;
|
| | | $this->supported['primary_key'] = false; // requires alter table implementation
|
| | | $this->supported['result_introspection'] = false; // not implemented
|
| | |
| | | $this->supported['pattern_escaping'] = false;
|
| | | $this->supported['new_link'] = false;
|
| | |
|
| | | $this->options['DBA_username'] = false;
|
| | | $this->options['DBA_password'] = false;
|
| | | $this->options['base_transaction_name'] = '___php_MDB2_sqlite_auto_commit_off';
|
| | | $this->options['fixed_float'] = 0;
|
| | | $this->options['database_path'] = '';
|
| | | $this->options['database_extension'] = '';
|
| | | $this->options['server_version'] = '';
|
| | | $this->options['max_identifiers_length'] = 128; //no real limit
|
| | | }
|
| | |
|
| | | // }}}
|
| | |
| | |
|
| | | // PHP 5.2+ prepends the function name to $php_errormsg, so we need
|
| | | // this hack to work around it, per bug #9599.
|
| | | $native_msg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $native_msg);
|
| | | $native_msg = preg_replace('/^sqlite[a-z_]+\(\)[^:]*: /', '', $native_msg);
|
| | |
|
| | | if (is_null($error)) {
|
| | | static $error_regexps;
|
| | |
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ databaseExists()
|
| | |
|
| | | /**
|
| | | * check if given database name is exists?
|
| | | *
|
| | | * @param string $name name of the database that should be checked
|
| | | *
|
| | | * @return mixed true/false on success, a MDB2 error on failure
|
| | | * @access public
|
| | | */
|
| | | function databaseExists($name)
|
| | | {
|
| | | $database_file = $this->_getDatabaseFile($name);
|
| | | $result = file_exists($database_file);
|
| | | return $result;
|
| | | }
|
| | |
|
| | | // }}}
|
| | | // {{{ disconnect()
|
| | |
|
| | | /**
|
| | |
| | | $query .= ',';
|
| | | $values.= ',';
|
| | | }
|
| | | $query.= $name;
|
| | | $query.= $this->quoteIdentifier($name, true);
|
| | | if (isset($fields[$name]['null']) && $fields[$name]['null']) {
|
| | | $value = 'NULL';
|
| | | } else {
|
| | |
| | | return $connection;
|
| | | }
|
| | |
|
| | | $table = $this->quoteIdentifier($table, true);
|
| | | $query = "REPLACE INTO $table ($query) VALUES ($values)";
|
| | | $result =& $this->_doQuery($query, true, $connection);
|
| | | if (PEAR::isError($result)) {
|
| | |
| | | $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
|
| | | $seqcol_name = $this->options['seqcol_name'];
|
| | | $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
|
| | | $this->pushErrorHandling(PEAR_ERROR_RETURN);
|
| | | $this->expectError(MDB2_ERROR_NOSUCHTABLE);
|
| | | $result =& $this->_doQuery($query, true);
|
| | | $this->popExpect();
|
| | | $this->popErrorHandling();
|
| | | if (PEAR::isError($result)) {
|
| | | if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
|
| | | $this->loadModule('Manager', null, true);
|