From 2273d4117fd50ee44dcdaa28fd6444383dc403a0 Mon Sep 17 00:00:00 2001 From: alecpl Date: Tue, 26 Jan 2010 13:45:16 +0000 Subject: - Add support for MDB2's 'sqlsrv' driver (#1486395) --- program/lib/MDB2/Driver/Reverse/Common.php | 1028 ++++++++++++++-------------- 1 file changed, 516 insertions(+), 512 deletions(-) (limited to 'program/lib/MDB2/Driver/Reverse/Common.php') diff --git a/program/lib/MDB2/Driver/Reverse/Common.php b/program/lib/MDB2/Driver/Reverse/Common.php index 18e9da931..5d9f27ccb 100644 --- a/program/lib/MDB2/Driver/Reverse/Common.php +++ b/program/lib/MDB2/Driver/Reverse/Common.php @@ -1,513 +1,517 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Common.php,v 1.42 2008/01/12 12:50:58 quipo Exp $ -// - -/** - * @package MDB2 - * @category Database - */ - -/** - * These are constants for the tableInfo-function - * they are bitwised or'ed. so if there are more constants to be defined - * in the future, adjust MDB2_TABLEINFO_FULL accordingly - */ - -define('MDB2_TABLEINFO_ORDER', 1); -define('MDB2_TABLEINFO_ORDERTABLE', 2); -define('MDB2_TABLEINFO_FULL', 3); - -/** - * Base class for the schema reverse engineering module that is extended by each MDB2 driver - * - * To load this module in the MDB2 object: - * $mdb->loadModule('Reverse'); - * - * @package MDB2 - * @category Database - * @author Lukas Smith - */ -class MDB2_Driver_Reverse_Common extends MDB2_Module_Common -{ - // {{{ splitTableSchema() - - /** - * Split the "[owner|schema].table" notation into an array - * @access private - */ - function splitTableSchema($table) - { - $ret = array(); - if (strpos($table, '.') !== false) { - return explode('.', $table); - } - return array(null, $table); - } - - // }}} - // {{{ getTableFieldDefinition() - - /** - * Get the structure of a field into an array - * - * @param string $table name of table that should be used in method - * @param string $field name of field that should be used in method - * @return mixed data array on success, a MDB2 error on failure. - * The returned array contains an array for each field definition, - * with all or some of these indices, depending on the field data type: - * [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type] - * @access public - */ - function getTableFieldDefinition($table, $field) - { - $db =& $this->getDBInstance(); - if (PEAR::isError($db)) { - return $db; - } - - return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, - 'method not implemented', __FUNCTION__); - } - - // }}} - // {{{ getTableIndexDefinition() - - /** - * Get the structure of an index into an array - * - * @param string $table name of table that should be used in method - * @param string $index name of index that should be used in method - * @return mixed data array on success, a MDB2 error on failure - * The returned array has this structure: - * - * array ( - * [fields] => array ( - * [field1name] => array() // one entry per each field covered - * [field2name] => array() // by the index - * [field3name] => array( - * [sorting] => ascending - * ) - * ) - * ); - * - * @access public - */ - function getTableIndexDefinition($table, $index) - { - $db =& $this->getDBInstance(); - if (PEAR::isError($db)) { - return $db; - } - - return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, - 'method not implemented', __FUNCTION__); - } - - // }}} - // {{{ getTableConstraintDefinition() - - /** - * Get the structure of an constraints into an array - * - * @param string $table name of table that should be used in method - * @param string $index name of index that should be used in method - * @return mixed data array on success, a MDB2 error on failure - * The returned array has this structure: - *
-     *          array (
-     *              [primary] => 0
-     *              [unique]  => 0
-     *              [foreign] => 1
-     *              [check]   => 0
-     *              [fields] => array (
-     *                  [field1name] => array() // one entry per each field covered
-     *                  [field2name] => array() // by the index
-     *                  [field3name] => array(
-     *                      [sorting]  => ascending
-     *                      [position] => 3
-     *                  )
-     *              )
-     *              [references] => array(
-     *                  [table] => name
-     *                  [fields] => array(
-     *                      [field1name] => array(  //one entry per each referenced field
-     *                           [position] => 1
-     *                      )
-     *                  )
-     *              )
-     *              [deferrable] => 0
-     *              [initiallydeferred] => 0
-     *              [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
-     *              [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
-     *              [match] => SIMPLE|PARTIAL|FULL
-     *          );
-     *          
- * @access public - */ - function getTableConstraintDefinition($table, $index) - { - $db =& $this->getDBInstance(); - if (PEAR::isError($db)) { - return $db; - } - - return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, - 'method not implemented', __FUNCTION__); - } - - // }}} - // {{{ getSequenceDefinition() - - /** - * Get the structure of a sequence into an array - * - * @param string $sequence name of sequence that should be used in method - * @return mixed data array on success, a MDB2 error on failure - * The returned array has this structure: - *
-     *          array (
-     *              [start] => n
-     *          );
-     *          
- * @access public - */ - function getSequenceDefinition($sequence) - { - $db =& $this->getDBInstance(); - if (PEAR::isError($db)) { - return $db; - } - - $start = $db->currId($sequence); - if (PEAR::isError($start)) { - return $start; - } - if ($db->supports('current_id')) { - $start++; - } else { - $db->warnings[] = 'database does not support getting current - sequence value, the sequence value was incremented'; - } - $definition = array(); - if ($start != 1) { - $definition = array('start' => $start); - } - return $definition; - } - - // }}} - // {{{ getTriggerDefinition() - - /** - * Get the structure of a trigger into an array - * - * EXPERIMENTAL - * - * WARNING: this function is experimental and may change the returned value - * at any time until labelled as non-experimental - * - * @param string $trigger name of trigger that should be used in method - * @return mixed data array on success, a MDB2 error on failure - * The returned array has this structure: - *
-     *          array (
-     *              [trigger_name]    => 'trigger name',
-     *              [table_name]      => 'table name',
-     *              [trigger_body]    => 'trigger body definition',
-     *              [trigger_type]    => 'BEFORE' | 'AFTER',
-     *              [trigger_event]   => 'INSERT' | 'UPDATE' | 'DELETE'
-     *                  //or comma separated list of multiple events, when supported
-     *              [trigger_enabled] => true|false
-     *              [trigger_comment] => 'trigger comment',
-     *          );
-     *          
- * The oci8 driver also returns a [when_clause] index. - * @access public - */ - function getTriggerDefinition($trigger) - { - $db =& $this->getDBInstance(); - if (PEAR::isError($db)) { - return $db; - } - - return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, - 'method not implemented', __FUNCTION__); - } - - // }}} - // {{{ tableInfo() - - /** - * Returns information about a table or a result set - * - * The format of the resulting array depends on which $mode - * you select. The sample output below is based on this query: - *
-     *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
-     *    FROM tblFoo
-     *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
-     * 
- * - * - * - * The flags element contains a space separated list - * of extra information about the field. This data is inconsistent - * between DBMS's due to the way each DBMS works. - * + primary_key - * + unique_key - * + multiple_key - * + not_null - * - * Most DBMS's only provide the table and flags - * elements if $result is a table name. The following DBMS's - * provide full information from queries: - * + fbsql - * + mysql - * - * If the 'portability' option has MDB2_PORTABILITY_FIX_CASE - * turned on, the names of tables and fields will be lower or upper cased. - * - * @param object|string $result MDB2_result object from a query or a - * string containing the name of a table. - * While this also accepts a query result - * resource identifier, this behavior is - * deprecated. - * @param int $mode either unused or one of the tableInfo modes: - * MDB2_TABLEINFO_ORDERTABLE, - * MDB2_TABLEINFO_ORDER or - * MDB2_TABLEINFO_FULL (which does both). - * These are bitwise, so the first two can be - * combined using |. - * - * @return array an associative array with the information requested. - * A MDB2_Error object on failure. - * - * @see MDB2_Driver_Common::setOption() - */ - function tableInfo($result, $mode = null) - { - $db =& $this->getDBInstance(); - if (PEAR::isError($db)) { - return $db; - } - - if (!is_string($result)) { - return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, - 'method not implemented', __FUNCTION__); - } - - $db->loadModule('Manager', null, true); - $fields = $db->manager->listTableFields($result); - if (PEAR::isError($fields)) { - return $fields; - } - - $flags = array(); - - $idxname_format = $db->getOption('idxname_format'); - $db->setOption('idxname_format', '%s'); - - $indexes = $db->manager->listTableIndexes($result); - if (PEAR::isError($indexes)) { - $db->setOption('idxname_format', $idxname_format); - return $indexes; - } - - foreach ($indexes as $index) { - $definition = $this->getTableIndexDefinition($result, $index); - if (PEAR::isError($definition)) { - $db->setOption('idxname_format', $idxname_format); - return $definition; - } - if (count($definition['fields']) > 1) { - foreach ($definition['fields'] as $field => $sort) { - $flags[$field] = 'multiple_key'; - } - } - } - - $constraints = $db->manager->listTableConstraints($result); - if (PEAR::isError($constraints)) { - return $constraints; - } - - foreach ($constraints as $constraint) { - $definition = $this->getTableConstraintDefinition($result, $constraint); - if (PEAR::isError($definition)) { - $db->setOption('idxname_format', $idxname_format); - return $definition; - } - $flag = !empty($definition['primary']) - ? 'primary_key' : (!empty($definition['unique']) - ? 'unique_key' : false); - if ($flag) { - foreach ($definition['fields'] as $field => $sort) { - if (empty($flags[$field]) || $flags[$field] != 'primary_key') { - $flags[$field] = $flag; - } - } - } - } - - $res = array(); - - if ($mode) { - $res['num_fields'] = count($fields); - } - - foreach ($fields as $i => $field) { - $definition = $this->getTableFieldDefinition($result, $field); - if (PEAR::isError($definition)) { - $db->setOption('idxname_format', $idxname_format); - return $definition; - } - $res[$i] = $definition[0]; - $res[$i]['name'] = $field; - $res[$i]['table'] = $result; - $res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype'])); - // 'primary_key', 'unique_key', 'multiple_key' - $res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field]; - // not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]' - if (!empty($res[$i]['notnull'])) { - $res[$i]['flags'].= ' not_null'; - } - if (!empty($res[$i]['unsigned'])) { - $res[$i]['flags'].= ' unsigned'; - } - if (!empty($res[$i]['auto_increment'])) { - $res[$i]['flags'].= ' autoincrement'; - } - if (!empty($res[$i]['default'])) { - $res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']); - } - - if ($mode & MDB2_TABLEINFO_ORDER) { - $res['order'][$res[$i]['name']] = $i; - } - if ($mode & MDB2_TABLEINFO_ORDERTABLE) { - $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; - } - } - - $db->setOption('idxname_format', $idxname_format); - return $res; - } -} + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php 273526 2009-01-14 15:01:21Z quipo $ +// + +/** + * @package MDB2 + * @category Database + */ + +/** + * These are constants for the tableInfo-function + * they are bitwised or'ed. so if there are more constants to be defined + * in the future, adjust MDB2_TABLEINFO_FULL accordingly + */ + +define('MDB2_TABLEINFO_ORDER', 1); +define('MDB2_TABLEINFO_ORDERTABLE', 2); +define('MDB2_TABLEINFO_FULL', 3); + +/** + * Base class for the schema reverse engineering module that is extended by each MDB2 driver + * + * To load this module in the MDB2 object: + * $mdb->loadModule('Reverse'); + * + * @package MDB2 + * @category Database + * @author Lukas Smith + */ +class MDB2_Driver_Reverse_Common extends MDB2_Module_Common +{ + // {{{ splitTableSchema() + + /** + * Split the "[owner|schema].table" notation into an array + * + * @param string $table [schema and] table name + * + * @return array array(schema, table) + * @access private + */ + function splitTableSchema($table) + { + $ret = array(); + if (strpos($table, '.') !== false) { + return explode('.', $table); + } + return array(null, $table); + } + + // }}} + // {{{ getTableFieldDefinition() + + /** + * Get the structure of a field into an array + * + * @param string $table name of table that should be used in method + * @param string $field name of field that should be used in method + * @return mixed data array on success, a MDB2 error on failure. + * The returned array contains an array for each field definition, + * with all or some of these indices, depending on the field data type: + * [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type] + * @access public + */ + function getTableFieldDefinition($table, $field) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ getTableIndexDefinition() + + /** + * Get the structure of an index into an array + * + * @param string $table name of table that should be used in method + * @param string $index name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + * + * array ( + * [fields] => array ( + * [field1name] => array() // one entry per each field covered + * [field2name] => array() // by the index + * [field3name] => array( + * [sorting] => ascending + * ) + * ) + * ); + * + * @access public + */ + function getTableIndexDefinition($table, $index) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ getTableConstraintDefinition() + + /** + * Get the structure of an constraints into an array + * + * @param string $table name of table that should be used in method + * @param string $index name of index that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + *
+     *          array (
+     *              [primary] => 0
+     *              [unique]  => 0
+     *              [foreign] => 1
+     *              [check]   => 0
+     *              [fields] => array (
+     *                  [field1name] => array() // one entry per each field covered
+     *                  [field2name] => array() // by the index
+     *                  [field3name] => array(
+     *                      [sorting]  => ascending
+     *                      [position] => 3
+     *                  )
+     *              )
+     *              [references] => array(
+     *                  [table] => name
+     *                  [fields] => array(
+     *                      [field1name] => array(  //one entry per each referenced field
+     *                           [position] => 1
+     *                      )
+     *                  )
+     *              )
+     *              [deferrable] => 0
+     *              [initiallydeferred] => 0
+     *              [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [match] => SIMPLE|PARTIAL|FULL
+     *          );
+     *          
+ * @access public + */ + function getTableConstraintDefinition($table, $index) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ getSequenceDefinition() + + /** + * Get the structure of a sequence into an array + * + * @param string $sequence name of sequence that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + *
+     *          array (
+     *              [start] => n
+     *          );
+     *          
+ * @access public + */ + function getSequenceDefinition($sequence) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + $start = $db->currId($sequence); + if (PEAR::isError($start)) { + return $start; + } + if ($db->supports('current_id')) { + $start++; + } else { + $db->warnings[] = 'database does not support getting current + sequence value, the sequence value was incremented'; + } + $definition = array(); + if ($start != 1) { + $definition = array('start' => $start); + } + return $definition; + } + + // }}} + // {{{ getTriggerDefinition() + + /** + * Get the structure of a trigger into an array + * + * EXPERIMENTAL + * + * WARNING: this function is experimental and may change the returned value + * at any time until labelled as non-experimental + * + * @param string $trigger name of trigger that should be used in method + * @return mixed data array on success, a MDB2 error on failure + * The returned array has this structure: + *
+     *          array (
+     *              [trigger_name]    => 'trigger name',
+     *              [table_name]      => 'table name',
+     *              [trigger_body]    => 'trigger body definition',
+     *              [trigger_type]    => 'BEFORE' | 'AFTER',
+     *              [trigger_event]   => 'INSERT' | 'UPDATE' | 'DELETE'
+     *                  //or comma separated list of multiple events, when supported
+     *              [trigger_enabled] => true|false
+     *              [trigger_comment] => 'trigger comment',
+     *          );
+     *          
+ * The oci8 driver also returns a [when_clause] index. + * @access public + */ + function getTriggerDefinition($trigger) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * The format of the resulting array depends on which $mode + * you select. The sample output below is based on this query: + *
+     *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
+     *    FROM tblFoo
+     *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
+     * 
+ * + *
    + *
  • + * + * null (default) + *
    +     *   [0] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   [1] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldPhone
    +     *       [type] => string
    +     *       [len] => 20
    +     *       [flags] =>
    +     *   )
    +     *   [2] => Array (
    +     *       [table] => tblBar
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   
    + * + *
  • + * + * MDB2_TABLEINFO_ORDER + * + *

    In addition to the information found in the default output, + * a notation of the number of columns is provided by the + * num_fields element while the order + * element provides an array with the column names as the keys and + * their location index number (corresponding to the keys in the + * the default output) as the values.

    + * + *

    If a result set has identical field names, the last one is + * used.

    + * + *
    +     *   [num_fields] => 3
    +     *   [order] => Array (
    +     *       [fldId] => 2
    +     *       [fldTrans] => 1
    +     *   )
    +     *   
    + * + *
  • + * + * MDB2_TABLEINFO_ORDERTABLE + * + *

    Similar to MDB2_TABLEINFO_ORDER but adds more + * dimensions to the array in which the table names are keys and + * the field names are sub-keys. This is helpful for queries that + * join tables which have identical field names.

    + * + *
    +     *   [num_fields] => 3
    +     *   [ordertable] => Array (
    +     *       [tblFoo] => Array (
    +     *           [fldId] => 0
    +     *           [fldPhone] => 1
    +     *       )
    +     *       [tblBar] => Array (
    +     *           [fldId] => 2
    +     *       )
    +     *   )
    +     *   
    + * + *
  • + *
+ * + * The flags element contains a space separated list + * of extra information about the field. This data is inconsistent + * between DBMS's due to the way each DBMS works. + * + primary_key + * + unique_key + * + multiple_key + * + not_null + * + * Most DBMS's only provide the table and flags + * elements if $result is a table name. The following DBMS's + * provide full information from queries: + * + fbsql + * + mysql + * + * If the 'portability' option has MDB2_PORTABILITY_FIX_CASE + * turned on, the names of tables and fields will be lower or upper cased. + * + * @param object|string $result MDB2_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode either unused or one of the tableInfo modes: + * MDB2_TABLEINFO_ORDERTABLE, + * MDB2_TABLEINFO_ORDER or + * MDB2_TABLEINFO_FULL (which does both). + * These are bitwise, so the first two can be + * combined using |. + * + * @return array an associative array with the information requested. + * A MDB2_Error object on failure. + * + * @see MDB2_Driver_Common::setOption() + */ + function tableInfo($result, $mode = null) + { + $db =& $this->getDBInstance(); + if (PEAR::isError($db)) { + return $db; + } + + if (!is_string($result)) { + return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, + 'method not implemented', __FUNCTION__); + } + + $db->loadModule('Manager', null, true); + $fields = $db->manager->listTableFields($result); + if (PEAR::isError($fields)) { + return $fields; + } + + $flags = array(); + + $idxname_format = $db->getOption('idxname_format'); + $db->setOption('idxname_format', '%s'); + + $indexes = $db->manager->listTableIndexes($result); + if (PEAR::isError($indexes)) { + $db->setOption('idxname_format', $idxname_format); + return $indexes; + } + + foreach ($indexes as $index) { + $definition = $this->getTableIndexDefinition($result, $index); + if (PEAR::isError($definition)) { + $db->setOption('idxname_format', $idxname_format); + return $definition; + } + if (count($definition['fields']) > 1) { + foreach ($definition['fields'] as $field => $sort) { + $flags[$field] = 'multiple_key'; + } + } + } + + $constraints = $db->manager->listTableConstraints($result); + if (PEAR::isError($constraints)) { + return $constraints; + } + + foreach ($constraints as $constraint) { + $definition = $this->getTableConstraintDefinition($result, $constraint); + if (PEAR::isError($definition)) { + $db->setOption('idxname_format', $idxname_format); + return $definition; + } + $flag = !empty($definition['primary']) + ? 'primary_key' : (!empty($definition['unique']) + ? 'unique_key' : false); + if ($flag) { + foreach ($definition['fields'] as $field => $sort) { + if (empty($flags[$field]) || $flags[$field] != 'primary_key') { + $flags[$field] = $flag; + } + } + } + } + + $res = array(); + + if ($mode) { + $res['num_fields'] = count($fields); + } + + foreach ($fields as $i => $field) { + $definition = $this->getTableFieldDefinition($result, $field); + if (PEAR::isError($definition)) { + $db->setOption('idxname_format', $idxname_format); + return $definition; + } + $res[$i] = $definition[0]; + $res[$i]['name'] = $field; + $res[$i]['table'] = $result; + $res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype'])); + // 'primary_key', 'unique_key', 'multiple_key' + $res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field]; + // not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]' + if (!empty($res[$i]['notnull'])) { + $res[$i]['flags'].= ' not_null'; + } + if (!empty($res[$i]['unsigned'])) { + $res[$i]['flags'].= ' unsigned'; + } + if (!empty($res[$i]['auto_increment'])) { + $res[$i]['flags'].= ' autoincrement'; + } + if (!empty($res[$i]['default'])) { + $res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']); + } + + if ($mode & MDB2_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & MDB2_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + $db->setOption('idxname_format', $idxname_format); + return $res; + } +} ?> \ No newline at end of file -- cgit v1.2.3