summaryrefslogtreecommitdiff
path: root/lib/prado/framework/Data/Common/TDbMetaData.php
blob: d44cd0bac7f58a2639e1d7f99915aba67912df2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<?php
/**
 * TDbMetaData class file.
 *
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 * @link https://github.com/pradosoft/prado
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
 * @package System.Data.Common
 */

/**
 * TDbMetaData is the base class for retrieving metadata information, such as
 * table and columns information, from a database connection.
 *
 * Use the {@link getTableInfo} method to retrieve a table information.
 *
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
 * @package System.Data.Common
 * @since 3.1
 */
abstract class TDbMetaData extends TComponent
{
	private $_tableInfoCache=array();
	private $_connection;

	/**
	 * @var array
	 */
	protected static $delimiterIdentifier = array('[', ']', '"', '`', "'");

	/**
	 * @param TDbConnection database connection.
	 */
	public function __construct($conn)
	{
		$this->_connection=$conn;
	}

	/**
	 * @return TDbConnection database connection.
	 */
	public function getDbConnection()
	{
		return $this->_connection;
	}

	/**
	 * Obtain database specific TDbMetaData class using the driver name of the database connection.
	 * @param TDbConnection database connection.
	 * @return TDbMetaData database specific TDbMetaData.
	 */
	public static function getInstance($conn)
	{
		$conn->setActive(true); //must be connected before retrieving driver name
		$driver = $conn->getDriverName();
		switch(strtolower($driver))
		{
			case 'pgsql':
				Prado::using('System.Data.Common.Pgsql.TPgsqlMetaData');
				return new TPgsqlMetaData($conn);
			case 'mysqli':
			case 'mysql':
				Prado::using('System.Data.Common.Mysql.TMysqlMetaData');
				return new TMysqlMetaData($conn);
			case 'sqlite': //sqlite 3
			case 'sqlite2': //sqlite 2
				Prado::using('System.Data.Common.Sqlite.TSqliteMetaData');
				return new TSqliteMetaData($conn);
			case 'mssql': // Mssql driver on windows hosts
			case 'sqlsrv': // sqlsrv driver on windows hosts
			case 'dblib': // dblib drivers on linux (and maybe others os) hosts
				Prado::using('System.Data.Common.Mssql.TMssqlMetaData');
				return new TMssqlMetaData($conn);
			case 'oci':
				Prado::using('System.Data.Common.Oracle.TOracleMetaData');
				return new TOracleMetaData($conn);
//			case 'ibm':
//				Prado::using('System.Data.Common.IbmDb2.TIbmDb2MetaData');
//				return new TIbmDb2MetaData($conn);
			default:
				throw new TDbException('ar_invalid_database_driver',$driver);
		}
	}

	/**
	 * Obtains table meta data information for the current connection and given table name.
	 * @param string table or view name
	 * @return TDbTableInfo table information.
	 */
	public function getTableInfo($tableName=null)
	{
		$key = $tableName===null?$this->getDbConnection()->getConnectionString():$tableName;
		if(!isset($this->_tableInfoCache[$key]))
		{
			$class = $this->getTableInfoClass();
			$tableInfo = $tableName===null ? new $class : $this->createTableInfo($tableName);
			$this->_tableInfoCache[$key] = $tableInfo;
		}
		return $this->_tableInfoCache[$key];
	}

	/**
	 * Creates a command builder for a given table name.
	 * @param string table name.
	 * @return TDbCommandBuilder command builder instance for the given table.
	 */
	public function createCommandBuilder($tableName=null)
	{
		return $this->getTableInfo($tableName)->createCommandBuilder($this->getDbConnection());
	}

	/**
	 * This method should be implemented by decendent classes.
	 * @return TDbTableInfo driver dependent create builder.
	 */
	abstract protected function createTableInfo($tableName);

	/**
	 * @return string TDbTableInfo class name.
	 */
	protected function getTableInfoClass()
	{
		return 'TDbTableInfo';
	}

	/**
	 * Quotes a table name for use in a query.
	 * @param string $name table name
	 * @param string $lft left delimiter
	 * @param string $rgt right delimiter
	 * @return string the properly quoted table name
	 */
	public function quoteTableName($name)
	{
		$name = str_replace(self::$delimiterIdentifier, '', $name);

		$args = func_get_args();
		$rgt = $lft = isset($args[1]) ? $args[1] : '';
		$rgt = isset($args[2]) ? $args[2] : $rgt;

		if(strpos($name, '.')===false)
			return $lft . $name . $rgt;
		$names=explode('.', $name);
		foreach($names as &$n)
			$n = $lft . $n . $rgt;
		return implode('.', $names);
	}

	/**
	 * Quotes a column name for use in a query.
	 * @param string $name column name
	 * @param string $lft left delimiter
	 * @param string $rgt right delimiter
	 * @return string the properly quoted column name
	 */
	public function quoteColumnName($name)
	{
		$args = func_get_args();
		$rgt = $lft = isset($args[1]) ? $args[1] : '';
		$rgt = isset($args[2]) ? $args[2] : $rgt;

		return $lft . str_replace(self::$delimiterIdentifier, '', $name) . $rgt;
	}

	/**
	 * Quotes a column alias for use in a query.
	 * @param string $name column alias
	 * @param string $lft left delimiter
	 * @param string $rgt right delimiter
	 * @return string the properly quoted column alias
	 */
	public function quoteColumnAlias($name)
	{
		$args = func_get_args();
		$rgt = $lft = isset($args[1]) ? $args[1] : '';
		$rgt = isset($args[2]) ? $args[2] : $rgt;

		return $lft . str_replace(self::$delimiterIdentifier, '', $name) . $rgt;
	}

        /**
	 * Returns all table names in the database.
	 * This method should be overridden by child classes in order to support this feature
	 * because the default implementation simply throws an exception.
	 * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
	 * If not empty, the returned table names will be prefixed with the schema name.
	 * @return array all table names in the database.
	 */
	abstract public function findTableNames($schema='');
}