Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TMssqlMetaData class file.
4
 *
5
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: TPgsqlMetaData.php 1866 2007-04-14 05:02:29Z wei $
10
 * @package System.Data.Common.Pgsql
11
 */
12
 
13
/**
14
 * Load the base TDbMetaData class.
15
 */
16
Prado::using('System.Data.Common.TDbMetaData');
17
Prado::using('System.Data.Common.Mssql.TMssqlTableInfo');
18
 
19
/**
20
 * TMssqlMetaData loads MSSQL database table and column information.
21
 *
22
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
23
 * @version $Id: TPgsqlMetaData.php 1866 2007-04-14 05:02:29Z wei $
24
 * @package System.Data.Common.Mssql
25
 * @since 3.1
26
 */
27
class TMssqlMetaData extends TDbMetaData
28
{
29
	/**
30
	 * @return string TDbTableInfo class name.
31
	 */
32
	protected function getTableInfoClass()
33
	{
34
		return 'TMssqlTableInfo';
35
	}
36
 
37
	/**
38
	 * Get the column definitions for given table.
39
	 * @param string table name.
40
	 * @return TMssqlTableInfo table information.
41
	 */
42
	protected function createTableInfo($table)
43
	{
44
		list($catalogName,$schemaName,$tableName) = $this->getCatalogSchemaTableName($table);
45
		$this->getDbConnection()->setActive(true);
46
		$sql = <<<EOD
47
				SELECT t.*,
48
                         c.*,
49
					columnproperty(object_id(c.table_schema + '.' + c.table_name), c.column_name,'IsIdentity') as IsIdentity
50
                    FROM INFORMATION_SCHEMA.TABLES t,
51
                         INFORMATION_SCHEMA.COLUMNS c
52
                   WHERE t.table_name = c.table_name
53
                     AND t.table_name = :table
54
EOD;
55
		if($schemaName!==null)
56
			$sql .= ' AND t.schema_name = :schema';
57
		if($catalogName!==null)
58
			$sql .= ' AND t.catalog_name = :catalog';
59
 
60
		$command = $this->getDbConnection()->createCommand($sql);
61
		$command->bindValue(':table', $tableName);
62
		if($schemaName!==null)
63
			$command->bindValue(':schema', $schemaName);
64
		if($catalogName!==null)
65
			$command->bindValue(':catalog', $catalogName);
66
 
67
		$tableInfo=null;
68
		foreach($command->query() as $col)
69
		{
70
			if($tableInfo===null)
71
				$tableInfo = $this->createNewTableInfo($col);
72
			$this->processColumn($tableInfo,$col);
73
		}
74
		if($tableInfo===null)
75
			throw new TDbException('dbmetadata_invalid_table_view', $table);
76
		return $tableInfo;
77
	}
78
 
79
	/**
80
	 * @param string table name
81
	 * @return array tuple($catalogName,$schemaName,$tableName)
82
	 */
83
	protected function getCatalogSchemaTableName($table)
84
	{
85
		//remove possible delimiters
86
		$result = explode('.', preg_replace('/\[|\]|"/', '', $table));
87
		if(count($result)===1)
88
			return array(null,null,$result[0]);
89
		if(count($result)===2)
90
			return array(null,$result[0],$result[1]);
91
		if(count($result)>2)
92
			return array($result[0],$result[1],$result[2]);
93
	}
94
 
95
	/**
96
	 * @param TMssqlTableInfo table information.
97
	 * @param array column information.
98
	 */
99
	protected function processColumn($tableInfo, $col)
100
	{
101
		$columnId = $col['COLUMN_NAME'];
102
 
103
		$info['ColumnName'] = "[$columnId]"; //quote the column names!
104
		$info['ColumnId'] = $columnId;
105
		$info['ColumnIndex'] = intval($col['ORDINAL_POSITION'])-1; //zero-based index
106
		if($col['IS_NULLABLE']!=='NO')
107
			$info['AllowNull'] = true;
108
		if($col['COLUMN_DEFAULT']!==null)
109
			$info['DefaultValue'] = $col['COLUMN_DEFAULT'];
110
 
111
		if(in_array($columnId, $tableInfo->getPrimaryKeys()))
112
			$info['IsPrimaryKey'] = true;
113
		if($this->isForeignKeyColumn($columnId, $tableInfo))
114
			$info['IsForeignKey'] = true;
115
 
116
		if($col['IsIdentity']==='1')
117
			$info['AutoIncrement'] = true;
118
		$info['DbType'] = $col['DATA_TYPE'];
119
		if($col['CHARACTER_MAXIMUM_LENGTH']!==null)
120
			$info['ColumnSize'] = intval($col['CHARACTER_MAXIMUM_LENGTH']);
121
		if($col['NUMERIC_PRECISION'] !== null)
122
			$info['NumericPrecision'] = intval($col['NUMERIC_PRECISION']);
123
		if($col['NUMERIC_SCALE']!==null)
124
			$info['NumericScale'] = intval($col['NUMERIC_SCALE']);
125
		$tableInfo->Columns[$columnId] = new TMssqlTableColumn($info);
126
	}
127
 
128
	/**
129
	 * @param string table schema name
130
	 * @param string table name.
131
	 * @return TMssqlTableInfo
132
	 */
133
	protected function createNewTableInfo($col)
134
	{
135
		$info['CatalogName'] = $col['TABLE_CATALOG'];
136
		$info['SchemaName'] = $col['TABLE_SCHEMA'];
137
		$info['TableName'] = $col['TABLE_NAME'];
138
		if($col['TABLE_TYPE']==='VIEW')
139
			$info['IsView'] = true;
140
		list($primary, $foreign) = $this->getConstraintKeys($col);
141
		$class = $this->getTableInfoClass();
142
		return new $class($info,$primary,$foreign);
143
	}
144
 
145
	/**
146
	 * Gets the primary and foreign key column details for the given table.
147
	 * @param string schema name
148
	 * @param string table name.
149
	 * @return array tuple ($primary, $foreign)
150
	 */
151
	protected function getConstraintKeys($col)
152
	{
153
		$sql = <<<EOD
154
		SELECT k.column_name field_name
155
		    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
156
		    LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
157
		      ON k.table_name = c.table_name
158
		     AND k.constraint_name = c.constraint_name
159
		   WHERE k.constraint_catalog = DB_NAME()
160
		AND
161
			c.constraint_type ='PRIMARY KEY'
162
		    AND k.table_name = :table
163
EOD;
164
		$command = $this->getDbConnection()->createCommand($sql);
165
		$command->bindValue(':table', $col['TABLE_NAME']);
166
		$primary = array();
167
		foreach($command->query()->readAll() as $field)
168
			$primary[] = $field['field_name'];
169
		$foreign = $this->getForeignConstraints($col);
170
		return array($primary,$foreign);
171
	}
172
 
173
	/**
174
	 * Gets foreign relationship constraint keys and table name
175
	 * @param string database name
176
	 * @param string table name
177
	 * @return array foreign relationship table name and keys.
178
	 */
179
	protected function getForeignConstraints($col)
180
	{
181
		//From http://msdn2.microsoft.com/en-us/library/aa175805(SQL.80).aspx
182
		$sql = <<<EOD
183
		SELECT
184
		     KCU1.CONSTRAINT_NAME AS 'FK_CONSTRAINT_NAME'
185
		   , KCU1.TABLE_NAME AS 'FK_TABLE_NAME'
186
		   , KCU1.COLUMN_NAME AS 'FK_COLUMN_NAME'
187
		   , KCU1.ORDINAL_POSITION AS 'FK_ORDINAL_POSITION'
188
		   , KCU2.CONSTRAINT_NAME AS 'UQ_CONSTRAINT_NAME'
189
		   , KCU2.TABLE_NAME AS 'UQ_TABLE_NAME'
190
		   , KCU2.COLUMN_NAME AS 'UQ_COLUMN_NAME'
191
		   , KCU2.ORDINAL_POSITION AS 'UQ_ORDINAL_POSITION'
192
		FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
193
		JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1
194
		ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG
195
		   AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
196
		   AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
197
		JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2
198
		ON KCU2.CONSTRAINT_CATALOG =
199
		RC.UNIQUE_CONSTRAINT_CATALOG
200
		   AND KCU2.CONSTRAINT_SCHEMA =
201
		RC.UNIQUE_CONSTRAINT_SCHEMA
202
		   AND KCU2.CONSTRAINT_NAME =
203
		RC.UNIQUE_CONSTRAINT_NAME
204
		   AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION
205
		WHERE KCU1.TABLE_NAME = :table
206
EOD;
207
		$command = $this->getDbConnection()->createCommand($sql);
208
		$command->bindValue(':table', $col['TABLE_NAME']);
209
		$fkeys=array();
210
		$catalogSchema = "[{$col['TABLE_CATALOG']}].[{$col['TABLE_SCHEMA']}]";
211
		foreach($command->query() as $info)
212
		{
213
			$fkeys[$info['FK_CONSTRAINT_NAME']]['keys'][$info['FK_COLUMN_NAME']] = $info['UQ_COLUMN_NAME'];
214
			$fkeys[$info['FK_CONSTRAINT_NAME']]['table'] = $info['UQ_TABLE_NAME'];
215
		}
216
		return count($fkeys) > 0 ? array_values($fkeys) : $fkeys;
217
	}
218
 
219
	/**
220
	 * @param string column name.
221
	 * @param TPgsqlTableInfo table information.
222
	 * @return boolean true if column is a foreign key.
223
	 */
224
	protected function isForeignKeyColumn($columnId, $tableInfo)
225
	{
226
		foreach($tableInfo->getForeignKeys() as $fk)
227
		{
228
			if(in_array($columnId, array_keys($fk['keys'])))
229
				return true;
230
		}
231
		return false;
232
	}
233
}
234