| // +----------------------------------------------------------------------+ // // $Id$ // require_once 'MDB2/Driver/Reverse/Common.php'; /** * MDB2 MSSQL driver for the schema reverse engineering module * * @package MDB2 * @category Database * @author Lukas Smith */ class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common { // }}} // {{{ tableInfo() /** * Returns information about a table or a result set * * NOTE: only supports 'table' and 'flags' if $result * is a table name. * * @param object|string $result MDB2_result object from a query or a * string containing the name of a table. * While this also accepts a query result * resource identifier, this behavior is * deprecated. * @param int $mode a valid tableInfo mode * * @return array an associative array with the information requested. * A MDB2_Error object on failure. * * @see MDB2_Driver_Common::tableInfo() */ function tableInfo($result, $mode = null) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } if (is_string($result)) { /* * Probably received a table name. * Create a result resource identifier. */ $id = $db->_doQuery("SELECT TOP 0 * FROM [$result]"); if (PEAR::isError($id)) { return $id; } $got_string = true; } elseif (MDB2::isResultCommon($result)) { /* * Probably received a result object. * Extract the result resource identifier. */ $id = $result->getResource(); $got_string = false; } else { /* * Probably received a result resource identifier. * Copy it. * Deprecated. Here for compatibility only. */ $id = $result; $got_string = false; } if (!is_resource($id)) { return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA); } if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { if ($db->options['field_case'] == CASE_LOWER) { $case_func = 'strtolower'; } else { $case_func = 'strtoupper'; } } else { $case_func = 'strval'; } $count = @mssql_num_fields($id); $res = array(); if ($mode) { $res['num_fields'] = $count; } for ($i = 0; $i < $count; $i++) { $res[$i] = array( 'table' => $got_string ? $case_func($result) : '', 'name' => $case_func(@mssql_field_name($id, $i)), 'type' => @mssql_field_type($id, $i), 'len' => @mssql_field_length($id, $i), // We only support flags for table 'flags' => $got_string ? $this->_mssql_field_flags($result, @mssql_field_name($id, $i)) : '', ); 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; } } // free the result only if we were called on a table if ($got_string) { @mssql_free_result($id); } return $res; } // }}} // {{{ _mssql_field_flags() /** * Get a column's flags * * Supports "not_null", "primary_key", * "auto_increment" (mssql identity), "timestamp" (mssql timestamp), * "unique_key" (mssql unique index, unique check or primary_key) and * "multiple_key" (multikey index) * * mssql timestamp is NOT similar to the mysql timestamp so this is maybe * not useful at all - is the behaviour of mysql_field_flags that primary * keys are alway unique? is the interpretation of multiple_key correct? * * @param string $table the table name * @param string $column the field name * * @return string the flags * * @access protected * @author Joern Barthel */ function _mssql_field_flags($table, $column) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } static $tableName = null; static $flags = array(); if ($table != $tableName) { $flags = array(); $tableName = $table; // get unique and primary keys $res = $db->queryAll("EXEC SP_HELPINDEX[$table]", null, MDB2_FETCHMODE_ASSOC); foreach ($res as $val) { $keys = explode(', ', $val['index_keys']); if (sizeof($keys) > 1) { foreach ($keys as $key) { $this->_add_flag($flags[$key], 'multiple_key'); } } if (strpos($val['index_description'], 'primary key')) { foreach ($keys as $key) { $this->_add_flag($flags[$key], 'primary_key'); } } elseif (strpos($val['index_description'], 'unique')) { foreach ($keys as $key) { $this->_add_flag($flags[$key], 'unique_key'); } } } // get auto_increment, not_null and timestamp $res = $db->queryAll("EXEC SP_COLUMNS[$table]", null, MDB2_FETCHMODE_ASSOC); foreach ($res as $val) { $val = array_change_key_case($val, $db->options['field_case']); if ($val['nullable'] == '0') { $this->_add_flag($flags[$val['column_name']], 'not_null'); } if (strpos($val['type_name'], 'identity')) { $this->_add_flag($flags[$val['column_name']], 'auto_increment'); } if (strpos($val['type_name'], 'timestamp')) { $this->_add_flag($flags[$val['column_name']], 'timestamp'); } } } if (array_key_exists($column, $flags)) { return(implode(' ', $flags[$column])); } return ''; } // }}} // {{{ _add_flag() /** * Adds a string to the flags array if the flag is not yet in there * - if there is no flag present the array is created * * @param array &$array the reference to the flag-array * @param string $value the flag value * * @return void * * @access protected * @author Joern Barthel */ function _add_flag(&$array, $value) { if (!is_array($array)) { $array = array($value); } elseif (!in_array($value, $array)) { array_push($array, $value); } } } ?>