Blame view

framework/library/pdo/PDOStatement_mysql.class.php 11 KB
4d84a934   曹明   初始代码提交
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
<?php
/** File PDOStatement_mysql.class.php	*
 *(C) Andrea Giammarchi [2005/10/13]	*/

/**
 * Class PDOStatement_mysql
 * 	This class is used from class PDO_mysql to manage a MySQL database.
 *	  Look at PDO.clas.php file comments to know more about MySQL connection.
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO.class.php
 * 			PDO_mysql.class.php
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Mail		andrea [ at ] 3site [ dot ] it
 * @Date		2005/10/13
 * @LastModified	2006/01/29 09:30 [fixed execute bug]
 * @Version		0.1b - tested
 */
class PDOStatement_mysql {

	/**
	 * 'Private' variables:
	 *	__connection:Resource		Database connection
		 *	__dbinfo:Array			Array with 4 elements used to manage connection
		 *	  __persistent:Boolean		Connection mode, is true on persistent, false on normal (deafult) connection
		 *	  __query:String			Last query used
		 *	  __result:Resource		Last result from last query
		 *	  __fetchmode:Integer		constant PDO_FETCH_* result mode
		 *	  __errorCode:String		Last error string code
		 *	  __errorInfo:Array		Last error informations, code, number, details
		 *	  __boundParams:Array		Stored bindParam
	 */
	var $__connection;
	var $__dbinfo;
	var $__persistent = false;
	var $__query = '';
	var $__result = null;
	var $__fetchmode = PDO::FETCH_BOTH;
	var $__errorCode = '';
	var $__errorInfo = Array('');
	var $__boundParams = Array();

	/**
	 * Public constructor:
	 *	Called from PDO to create a PDOStatement for this database
		 *	   	new PDOStatement_sqlite( &$__query:String, &$__connection:Resource, $__dbinfo:Array )
	 * @Param	String		query to prepare
		 * @Param	Resource	database connection
		 * @Param	Array		4 elements array to manage connection
	 */
	function PDOStatement_mysql(&$__query, &$__connection, &$__dbinfo) {
		$this->__query = &$__query;
		$this->__connection = &$__connection;
		$this->__dbinfo = &$__dbinfo;
	}

	/**
	 * Public method:
	 *	Replace ? or :named values to execute prepared query
		 *	   	this->bindParam( $mixed:Mixed, &$variable:Mixed, $type:Integer, $lenght:Integer ):Void
		 * @Param	Mixed		Integer or String to replace prepared value
		 * @Param	Mixed		variable to replace
		 * @Param	Integer		this variable is not used but respects PDO original accepted parameters
		 * @Param	Integer		this variable is not used but respects PDO original accepted parameters
	 */
	function bindParam($mixed, &$variable, $type = null, $lenght = null) {
		if(is_string($mixed))
			$this->__boundParams[$mixed] = $variable;
		else
			array_push($this->__boundParams, $variable);
	}

	/**
	 * Public method:
	 *	Checks if query was valid and returns how may fields returns
		 *	   	this->columnCount( void ):Void
	 */
	function columnCount() {
		$result = 0;
		if(!is_null($this->__result))
			$result = mysql_num_fields($this->__result);
		return $result;
	}

	/**
	 * Public method:
	 *	Returns a code rappresentation of an error
		 *	   	this->errorCode( void ):String
		 * @Return	String		String rappresentation of the error
	 */
	function errorCode() {
		return $this->__errorCode;
	}

	/**
	 * Public method:
	 *	Returns an array with error informations
		 *	   	this->errorInfo( void ):Array
		 * @Return	Array		Array with 3 keys:
		 * 				0 => error code
		 *							  1 => error number
		 *							  2 => error string
	 */
	function errorInfo() {
		return $this->__errorInfo;
	}

	/**
	 * Public method:
	 *	Excecutes a query and returns true on success or false.
		 *	   	this->exec( $array:Array ):Boolean
		 * @Param	Array		If present, it should contain all replacements for prepared query
		 * @Return	Boolean		true if query has been done without errors, false otherwise
	 */
	function execute($array = Array()) {
		if(count($this->__boundParams) > 0)
			$array = &$this->__boundParams;
		$__query = $this->__query;
		if(count($array) > 0) {
			foreach($array as $k => $v) {
				if(!is_int($k) || substr($k, 0, 1) === ':') {
					if(!isset($tempf))
						$tempf = $tempr = array();
					array_push($tempf, $k);
					if (strexists($v, '\u')) {
						$v = str_replace('\u', '\\\\u', $v);
					}
					if (strexists($v, '\"')) {
						$v = str_replace('\"', '\\\\"', $v);
					}
					array_push($tempr, '"'.mysql_escape_string($v).'"');
				}
				else {
					$parse = create_function('$v', 'return \'"\'.mysql_escape_string($v).\'"\';');
					$__query = preg_replace("/(\?)/e", '$parse($array[$k++]);', $__query);
					break;
				}
			}
			if(isset($tempf)) {
				foreach ($tempf as $k=>$v) {
					$search[$k] = '/' . preg_quote($tempf[$k],'`') . '\b/';
				}
				$__query = preg_replace($search, $tempr, $__query);
				//$__query = str_replace($tempf, $tempr, $__query);
			}
		}
		if(is_null($this->__result = &$this->__uquery($__query)))
			$keyvars = false;
		else
			$keyvars = true;
		$this->__boundParams = array();
		return $keyvars;
	}

	/**
	 * Public method:
	 *	Returns, if present, next row of executed query or false.
		 *	   	this->fetch( $mode:Integer, $cursor:Integer, $offset:Integer ):Mixed
		 * @Param	Integer		PDO_FETCH_* constant to know how to read next row, default PDO_FETCH_BOTH
		 * 				NOTE: if $mode is omitted is used default setted mode, PDO_FETCH_BOTH
		 * @Param	Integer		this variable is not used but respects PDO original accepted parameters
		 * @Param	Integer		this variable is not used but respects PDO original accepted parameters
		 * @Return	Mixed		Next row of executed query or false if there is nomore.
	 */
	function fetch($mode = PDO_FETCH_ASSOC, $cursor = null, $offset = null) {
		if(func_num_args() == 0)
			$mode = &$this->__fetchmode;
		$result = false;
		if(!is_null($this->__result)) {
			switch($mode) {
				case PDO::FETCH_NUM:
					$result = mysql_fetch_row($this->__result);
					break;
				case PDO::FETCH_ASSOC:
					$result = mysql_fetch_assoc($this->__result);
					break;
				case PDO::FETCH_OBJ:
					$result = mysql_fetch_object($this->__result);
					break;
				case PDO::FETCH_BOTH:
				default:
					$result = mysql_fetch_array($this->__result);
					break;
			}
		}
		if(!$result)
			$this->__result = null;
		return $result;
	}

	/**
	 * Public method:
	 *	Returns an array with all rows of executed query.
		 *	   	this->fetchAll( $mode:Integer ):Array
		 * @Param	Integer		PDO_FETCH_* constant to know how to read all rows, default PDO_FETCH_BOTH
		 * 				NOTE: this doesn't work as fetch method, then it will use always PDO_FETCH_BOTH
		 *									if this param is omitted
		 * @Return	Array		An array with all fetched rows
	 */
	function fetchAll($mode = PDO_FETCH_ASSOC) {
		$result = array();
		if(!is_null($this->__result)) {
			switch($mode) {
				case PDO::FETCH_NUM:
					while($r = mysql_fetch_row($this->__result))
						array_push($result, $r);
					break;
				case PDO::FETCH_ASSOC:
					while($r = mysql_fetch_assoc($this->__result))
						array_push($result, $r);
					break;
				case PDO::FETCH_OBJ:
					while($r = mysql_fetch_object($this->__result))
						array_push($result, $r);
					break;
				case PDO::FETCH_BOTH:
				default:
					while($r = mysql_fetch_array($this->__result))
						array_push($result, $r);
					break;
			}
		}
		$this->__result = null;
		return $result;
	}

	/**
	 * Public method:
	 *	Returns, if present, first column of next row of executed query
		 *	   	this->fetchSingle( void ):Mixed
		 * @Return	Mixed		Null or next row's first column
	 */
	function fetchSingle() {
		$result = null;
		if(!is_null($this->__result)) {
			$result = @mysql_fetch_row($this->__result);
			if($result)
				$result = $result[0];
			else
				$this->__result = null;
		}
		return $result;
	}

	function fetchColumn($column=0) {
		$row = mysql_fetch_row($this->__result);
		return $row[$column];
	}

	/**
	 * Public method:
	 *	Returns number of last affected database rows
		 *	   	this->rowCount( void ):Integer
		 * @Return	Integer		number of last affected rows
		 * 				NOTE: works with INSERT, UPDATE and DELETE query type
	 */
	function rowCount() {
		return mysql_affected_rows($this->__connection);
	}


	// NOT TOTALLY SUPPORTED PUBLIC METHODS
		/**
	 * Public method:
	 *	Quotes correctly a string for this database
		 *	   	this->getAttribute( $attribute:Integer ):Mixed
		 * @Param	Integer		a constant [	PDO_ATTR_SERVER_INFO,
		 * 						PDO_ATTR_SERVER_VERSION,
		 *											  PDO_ATTR_CLIENT_VERSION,
		 *											  PDO_ATTR_PERSISTENT	]
		 * @Return	Mixed		correct information or false
	 */
	function getAttribute($attribute) {
		$result = false;
		switch($attribute) {
			case PDO_ATTR_SERVER_INFO:
				$result = mysql_get_host_info($this->__connection);
				break;
			case PDO_ATTR_SERVER_VERSION:
				$result = mysql_get_server_info($this->__connection);
				break;
			case PDO_ATTR_CLIENT_VERSION:
				$result = mysql_get_client_info();
				break;
			case PDO_ATTR_PERSISTENT:
				$result = $this->__persistent;
				break;
		}
		return $result;
	}

	/**
	 * Public method:
	 *	Sets database attributes, in this version only connection mode.
		 *	   	this->setAttribute( $attribute:Integer, $mixed:Mixed ):Boolean
		 * @Param	Integer		PDO_* constant, in this case only PDO_ATTR_PERSISTENT
		 * @Param	Mixed		value for PDO_* constant, in this case a Boolean value
		 * 				true for permanent connection, false for default not permament connection
		 * @Return	Boolean		true on change, false otherwise
	 */
	function setAttribute($attribute, $mixed) {
		$result = false;
		if($attribute === PDO_ATTR_PERSISTENT && $mixed != $this->__persistent) {
			$result = true;
			$this->__persistent = (boolean) $mixed;
			mysql_close($this->__connection);
			if($this->__persistent === true)
				$this->__connection = &mysql_pconnect($this->__dbinfo[0], $this->__dbinfo[1], $this->__dbinfo[2]);
			else
				$this->__connection = &mysql_connect($this->__dbinfo[0], $this->__dbinfo[1], $this->__dbinfo[2]);
			mysql_select_db($this->__dbinfo[3], $this->__connection);
		}
		return $result;
	}

	/**
	 * Public method:
	 *	Sets default fetch mode to use with this->fetch() method.
		 *	   	this->setFetchMode( $mode:Integer ):Boolean
		 * @Param	Integer		PDO_FETCH_* constant to use while reading an execute query with fetch() method.
		 * 				NOTE: PDO_FETCH_LAZY and PDO_FETCH_BOUND are not supported
		 * @Return	Boolean		true on change, false otherwise
	 */
	function setFetchMode($mode) {
		$result = false;
		switch($mode) {
			case PDO_FETCH_NUM:
			case PDO_FETCH_ASSOC:
			case PDO_FETCH_OBJ:
			case PDO_FETCH_BOTH:
				$result = true;
				$this->__fetchmode = &$mode;
				break;
		}
		return $result;
	}


	// UNSUPPORTED PUBLIC METHODS
		function bindColumn($mixewd, &$param, $type = null, $max_length = null, $driver_option = null) {
		return false;
	}

	function __setErrors($er) {
		if(!is_resource($this->__connection)) {
			$errno = mysql_errno();
			$errst = mysql_error();
		}
		else {
			$errno = mysql_errno($this->__connection);
			$errst = mysql_error($this->__connection);
		}
		$this->__errorCode = &$er;
		$this->__errorInfo = Array($this->__errorCode, $errno, $errst);
		$this->__result = null;
	}

	function __uquery(&$query) {
		if(!@$query = mysql_query($query, $this->__connection)) {
			$this->__setErrors('SQLER');
			$query = null;
		}
		return $query;
	}

}
?>