Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TDbCommand class file
4
 *
5
 * @author Qiang Xue <qiang.xue@gmail.com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: TDbCommand.php 2541 2008-10-21 15:05:13Z qiang.xue $
10
 * @package System.Data
11
 */
12
 
13
/**
14
 * TDbCommand class.
15
 *
16
 * TDbCommand represents an SQL statement to execute against a database.
17
 * It is usually created by calling {@link TDbConnection::createCommand}.
18
 * The SQL statement to be executed may be set via {@link setText Text}.
19
 *
20
 * To execute a non-query SQL (such as insert, delete, update), call
21
 * {@link execute}. To execute an SQL statement that returns result data set
22
 * (such as select), use {@link query} or its convenient versions {@link queryRow}
23
 * and {@link queryScalar}.
24
 *
25
 * If an SQL statement returns results (such as a SELECT SQL), the results
26
 * can be accessed via the returned {@link TDbDataReader}.
27
 *
28
 * TDbCommand supports SQL statment preparation and parameter binding.
29
 * Call {@link bindParameter} to bind a PHP variable to a parameter in SQL.
30
 * Call {@link bindValue} to bind a value to an SQL parameter.
31
 * When binding a parameter, the SQL statement is automatically prepared.
32
 * You may also call {@link prepare} to explicitly prepare an SQL statement.
33
 *
34
 * @author Qiang Xue <qiang.xue@gmail.com>
35
 * @version $Id: TDbCommand.php 2541 2008-10-21 15:05:13Z qiang.xue $
36
 * @package System.Data
37
 * @since 3.0
38
 */
39
class TDbCommand extends TComponent
40
{
41
	private $_connection;
42
	private $_text='';
43
	private $_statement=null;
44
 
45
	/**
46
	 * Constructor.
47
	 * @param TDbConnection the database connection
48
	 * @param string the SQL statement to be executed
49
	 */
50
	public function __construct(TDbConnection $connection,$text)
51
	{
52
		$this->_connection=$connection;
53
		$this->setText($text);
54
	}
55
 
56
	/**
57
	 * Set the statement to null when serializing.
58
	 */
59
	public function __sleep()
60
	{
61
		$this->_statement=null;
62
		return array_keys(get_object_vars($this));
63
	}
64
 
65
	/**
66
	 * @return string the SQL statement to be executed
67
	 */
68
	public function getText()
69
	{
70
		return $this->_text;
71
	}
72
 
73
	/**
74
	 * Specifies the SQL statement to be executed.
75
	 * Any previous execution will be terminated or cancel.
76
	 * @param string the SQL statement to be executed
77
	 */
78
	public function setText($value)
79
	{
80
		$this->_text=$value;
81
		$this->cancel();
82
	}
83
 
84
	/**
85
	 * @return TDbConnection the connection associated with this command
86
	 */
87
	public function getConnection()
88
	{
89
		return $this->_connection;
90
	}
91
 
92
	/**
93
	 * @return PDOStatement the underlying PDOStatement for this command
94
	 * It could be null if the statement is not prepared yet.
95
	 */
96
	public function getPdoStatement()
97
	{
98
		return $this->_statement;
99
	}
100
 
101
	/**
102
	 * Prepares the SQL statement to be executed.
103
	 * For complex SQL statement that is to be executed multiple times,
104
	 * this may improve performance.
105
	 * For SQL statement with binding parameters, this method is invoked
106
	 * automatically.
107
	 */
108
	public function prepare()
109
	{
110
		if($this->_statement==null)
111
		{
112
			try
113
			{
114
				$this->_statement=$this->getConnection()->getPdoInstance()->prepare($this->getText());
115
			}
116
			catch(Exception $e)
117
			{
118
				throw new TDbException('dbcommand_prepare_failed',$e->getMessage(),$this->getText());
119
			}
120
		}
121
	}
122
 
123
	/**
124
	 * Cancels the execution of the SQL statement.
125
	 */
126
	public function cancel()
127
	{
128
		$this->_statement=null;
129
	}
130
 
131
	/**
132
	 * Binds a parameter to the SQL statement to be executed.
133
	 * @param mixed Parameter identifier. For a prepared statement
134
	 * using named placeholders, this will be a parameter name of
135
	 * the form :name. For a prepared statement using question mark
136
	 * placeholders, this will be the 1-indexed position of the parameter.
137
	 * @param mixed Name of the PHP variable to bind to the SQL statement parameter
138
	 * @param int SQL data type of the parameter
139
	 * @param int length of the data type
140
	 * @see http://www.php.net/manual/en/function.PDOStatement-bindParam.php
141
	 */
142
	public function bindParameter($name, &$value, $dataType=null, $length=null)
143
	{
144
		$this->prepare();
145
		if($dataType===null)
146
			$this->_statement->bindParam($name,$value);
147
		else if($length===null)
148
			$this->_statement->bindParam($name,$value,$dataType);
149
		else
150
			$this->_statement->bindParam($name,$value,$dataType,$length);
151
	}
152
 
153
	/**
154
	 * Binds a value to a parameter.
155
	 * @param mixed Parameter identifier. For a prepared statement
156
	 * using named placeholders, this will be a parameter name of
157
	 * the form :name. For a prepared statement using question mark
158
	 * placeholders, this will be the 1-indexed position of the parameter.
159
	 * @param mixed The value to bind to the parameter
160
	 * @param int SQL data type of the parameter
161
	 * @see http://www.php.net/manual/en/function.PDOStatement-bindValue.php
162
	 */
163
	public function bindValue($name, $value, $dataType=null)
164
	{
165
		$this->prepare();
166
		if($dataType===null)
167
			$this->_statement->bindValue($name,$value);
168
		else
169
			$this->_statement->bindValue($name,$value,$dataType);
170
	}
171
 
172
	/**
173
	 * Executes the SQL statement.
174
	 * This method is meant only for executing non-query SQL statement.
175
	 * No result set will be returned.
176
	 * @return integer number of rows affected by the execution.
177
	 * @throws TDbException execution failed
178
	 */
179
	public function execute()
180
	{
181
		try
182
		{
183
			// Do not trace because it will remain even in
184
			// Performance mode or when pradolite.php is used
185
			// Prado::trace('Execute Command: '.$this->getDebugStatementText(), 'System.Data');
186
			if($this->_statement instanceof PDOStatement)
187
			{
188
				$this->_statement->execute();
189
				return $this->_statement->rowCount();
190
			}
191
			else
192
				return $this->getConnection()->getPdoInstance()->exec($this->getText());
193
		}
194
		catch(Exception $e)
195
		{
196
			throw new TDbException('dbcommand_execute_failed',$e->getMessage(),$this->getDebugStatementText());
197
		}
198
	}
199
 
200
	/**
201
	 * @return String prepared SQL text for debugging purposes.
202
	 */
203
	public function getDebugStatementText()
204
	{
205
		if(Prado::getApplication()->getMode() === TApplicationMode::Debug)
206
			return $this->_statement instanceof PDOStatement ?
207
				$this->_statement->queryString
208
				: $this->getText();
209
	}
210
 
211
	/**
212
	 * Executes the SQL statement and returns query result.
213
	 * This method is for executing an SQL query that returns result set.
214
	 * @return TDbDataReader the reader object for fetching the query result
215
	 * @throws TDbException execution failed
216
	 */
217
	public function query()
218
	{
219
		try
220
		{
221
			// Prado::trace('Query: '.$this->getDebugStatementText(), 'System.Data');
222
			if($this->_statement instanceof PDOStatement)
223
				$this->_statement->execute();
224
			else
225
				$this->_statement=$this->getConnection()->getPdoInstance()->query($this->getText());
226
			return new TDbDataReader($this);
227
		}
228
		catch(Exception $e)
229
		{
230
			throw new TDbException('dbcommand_query_failed',$e->getMessage(),$this->getDebugStatementText());
231
		}
232
	}
233
 
234
	/**
235
	 * Executes the SQL statement and returns the first row of the result.
236
	 * This is a convenient method of {@link query} when only the first row of data is needed.
237
	 * @param boolean whether the row should be returned as an associated array with
238
	 * column names as the keys or the array keys are column indexes (0-based).
239
	 * @return array the first row of the query result, false if no result.
240
	 * @throws TDbException execution failed
241
	 */
242
	public function queryRow($fetchAssociative=true)
243
	{
244
		try
245
		{
246
			// Prado::trace('Query Row: '.$this->getDebugStatementText(), 'System.Data');
247
			if($this->_statement instanceof PDOStatement)
248
				$this->_statement->execute();
249
			else
250
				$this->_statement=$this->getConnection()->getPdoInstance()->query($this->getText());
251
			$result=$this->_statement->fetch($fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
252
			$this->_statement->closeCursor();
253
			return $result;
254
		}
255
		catch(Exception $e)
256
		{
257
			throw new TDbException('dbcommand_query_failed',$e->getMessage(),$this->getDebugStatementText());
258
		}
259
	}
260
 
261
	/**
262
	 * Executes the SQL statement and returns the value of the first column in the first row of data.
263
	 * This is a convenient method of {@link query} when only a single scalar
264
	 * value is needed (e.g. obtaining the count of the records).
265
	 * @return mixed the value of the first column in the first row of the query result. False is returned if there is no value.
266
	 * @throws TDbException execution failed
267
	 */
268
	public function queryScalar()
269
	{
270
		try
271
		{
272
			// Prado::trace('Query Scalar: '.$this->getDebugStatementText(), 'System.Data');
273
			if($this->_statement instanceof PDOStatement)
274
				$this->_statement->execute();
275
			else
276
				$this->_statement=$this->getConnection()->getPdoInstance()->query($this->getText());
277
			$result=$this->_statement->fetchColumn();
278
			$this->_statement->closeCursor();
279
			if(is_resource($result) && get_resource_type($result)==='stream')
280
				return stream_get_contents($result);
281
			else
282
				return $result;
283
		}
284
		catch(Exception $e)
285
		{
286
			throw new TDbException('dbcommand_query_failed',$e->getMessage(),$this->getDebugStatementText());
287
		}
288
	}
289
 
290
	/**
291
	 * Executes the SQL statement and returns the first column of the result.
292
	 * This is a convenient method of {@link query} when only the first column of data is needed.
293
	 * Note, the column returned will contain the first element in each row of result.
294
	 * @return array the first column of the query result. Empty array if no result.
295
	 * @throws TDbException execution failed
296
	 * @since 3.1.2
297
	 */
298
	public function queryColumn()
299
	{
300
		$rows=$this->query()->readAll();
301
		$column=array();
302
		foreach($rows as $row)
303
			$column[]=current($row);
304
		return $column;
305
	}
306
}
307