Редакция 304 | Редакция 459 | К новейшей редакции | Только различия | Не учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 304 | Редакция 305 | ||
---|---|---|---|
1 | <?php
|
1 | <?php
|
2 | 2 | ||
3 | /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
3 | /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
4 | 4 | ||
5 | /**
|
5 | /**
|
6 | * Database independent query interface
|
6 | * Database independent query interface
|
7 | *
|
7 | *
|
8 | * PHP versions 4 and 5
|
8 | * PHP versions 4 and 5
|
9 | *
|
9 | *
|
10 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
10 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
11 | * that is available through the world-wide-web at the following URI:
|
11 | * that is available through the world-wide-web at the following URI:
|
12 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
12 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
13 | * the PHP License and are unable to obtain it through the web, please
|
13 | * the PHP License and are unable to obtain it through the web, please
|
14 | * send a note to license@php.net so we can mail you a copy immediately.
|
14 | * send a note to license@php.net so we can mail you a copy immediately.
|
15 | *
|
15 | *
|
16 | * @category Database
|
16 | * @category Database
|
17 | * @package DB
|
17 | * @package DB
|
18 | * @author Stig Bakken <ssb@php.net>
|
18 | * @author Stig Bakken <ssb@php.net>
|
19 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
19 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
20 | * @author Daniel Convissor <danielc@php.net>
|
20 | * @author Daniel Convissor <danielc@php.net>
|
21 | * @copyright 1997-2007 The PHP Group
|
21 | * @copyright 1997-2007 The PHP Group
|
22 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
22 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
23 | * @version CVS: $Id: DB.php,v 1.88 2007/08/12 05:27:25 aharvey Exp $
|
23 | * @version CVS: $Id: DB.php,v 1.88 2007/08/12 05:27:25 aharvey Exp $
|
24 | * @link http://pear.php.net/package/DB
|
24 | * @link http://pear.php.net/package/DB
|
25 | */
|
25 | */
|
26 | 26 | ||
27 | /**
|
27 | /**
|
28 | * Obtain the PEAR class so it can be extended from
|
28 | * Obtain the PEAR class so it can be extended from
|
29 | */
|
29 | */
|
30 | require_once 'PEAR.php'; |
30 | require_once dirname(__FILE__).'/PEAR.php'; |
31 | 31 | ||
32 | 32 | ||
33 | // {{{ constants
|
33 | // {{{ constants
|
34 | // {{{ error codes
|
34 | // {{{ error codes
|
35 | 35 | ||
36 | /**#@+
|
36 | /**#@+
|
37 | * One of PEAR DB's portable error codes.
|
37 | * One of PEAR DB's portable error codes.
|
38 | * @see DB_common::errorCode(), DB::errorMessage()
|
38 | * @see DB_common::errorCode(), DB::errorMessage()
|
39 | *
|
39 | *
|
40 | * {@internal If you add an error code here, make sure you also add a textual
|
40 | * {@internal If you add an error code here, make sure you also add a textual
|
41 | * version of it in DB::errorMessage().}}
|
41 | * version of it in DB::errorMessage().}}
|
42 | */
|
42 | */
|
43 | 43 | ||
44 | /**
|
44 | /**
|
45 | * The code returned by many methods upon success
|
45 | * The code returned by many methods upon success
|
46 | */
|
46 | */
|
47 | define('DB_OK', 1); |
47 | define('DB_OK', 1); |
48 | 48 | ||
49 | /**
|
49 | /**
|
50 | * Unkown error
|
50 | * Unkown error
|
51 | */
|
51 | */
|
52 | define('DB_ERROR', -1); |
52 | define('DB_ERROR', -1); |
53 | 53 | ||
54 | /**
|
54 | /**
|
55 | * Syntax error
|
55 | * Syntax error
|
56 | */
|
56 | */
|
57 | define('DB_ERROR_SYNTAX', -2); |
57 | define('DB_ERROR_SYNTAX', -2); |
58 | 58 | ||
59 | /**
|
59 | /**
|
60 | * Tried to insert a duplicate value into a primary or unique index
|
60 | * Tried to insert a duplicate value into a primary or unique index
|
61 | */
|
61 | */
|
62 | define('DB_ERROR_CONSTRAINT', -3); |
62 | define('DB_ERROR_CONSTRAINT', -3); |
63 | 63 | ||
64 | /**
|
64 | /**
|
65 | * An identifier in the query refers to a non-existant object
|
65 | * An identifier in the query refers to a non-existant object
|
66 | */
|
66 | */
|
67 | define('DB_ERROR_NOT_FOUND', -4); |
67 | define('DB_ERROR_NOT_FOUND', -4); |
68 | 68 | ||
69 | /**
|
69 | /**
|
70 | * Tried to create a duplicate object
|
70 | * Tried to create a duplicate object
|
71 | */
|
71 | */
|
72 | define('DB_ERROR_ALREADY_EXISTS', -5); |
72 | define('DB_ERROR_ALREADY_EXISTS', -5); |
73 | 73 | ||
74 | /**
|
74 | /**
|
75 | * The current driver does not support the action you attempted
|
75 | * The current driver does not support the action you attempted
|
76 | */
|
76 | */
|
77 | define('DB_ERROR_UNSUPPORTED', -6); |
77 | define('DB_ERROR_UNSUPPORTED', -6); |
78 | 78 | ||
79 | /**
|
79 | /**
|
80 | * The number of parameters does not match the number of placeholders
|
80 | * The number of parameters does not match the number of placeholders
|
81 | */
|
81 | */
|
82 | define('DB_ERROR_MISMATCH', -7); |
82 | define('DB_ERROR_MISMATCH', -7); |
83 | 83 | ||
84 | /**
|
84 | /**
|
85 | * A literal submitted did not match the data type expected
|
85 | * A literal submitted did not match the data type expected
|
86 | */
|
86 | */
|
87 | define('DB_ERROR_INVALID', -8); |
87 | define('DB_ERROR_INVALID', -8); |
88 | 88 | ||
89 | /**
|
89 | /**
|
90 | * The current DBMS does not support the action you attempted
|
90 | * The current DBMS does not support the action you attempted
|
91 | */
|
91 | */
|
92 | define('DB_ERROR_NOT_CAPABLE', -9); |
92 | define('DB_ERROR_NOT_CAPABLE', -9); |
93 | 93 | ||
94 | /**
|
94 | /**
|
95 | * A literal submitted was too long so the end of it was removed
|
95 | * A literal submitted was too long so the end of it was removed
|
96 | */
|
96 | */
|
97 | define('DB_ERROR_TRUNCATED', -10); |
97 | define('DB_ERROR_TRUNCATED', -10); |
98 | 98 | ||
99 | /**
|
99 | /**
|
100 | * A literal number submitted did not match the data type expected
|
100 | * A literal number submitted did not match the data type expected
|
101 | */
|
101 | */
|
102 | define('DB_ERROR_INVALID_NUMBER', -11); |
102 | define('DB_ERROR_INVALID_NUMBER', -11); |
103 | 103 | ||
104 | /**
|
104 | /**
|
105 | * A literal date submitted did not match the data type expected
|
105 | * A literal date submitted did not match the data type expected
|
106 | */
|
106 | */
|
107 | define('DB_ERROR_INVALID_DATE', -12); |
107 | define('DB_ERROR_INVALID_DATE', -12); |
108 | 108 | ||
109 | /**
|
109 | /**
|
110 | * Attempt to divide something by zero
|
110 | * Attempt to divide something by zero
|
111 | */
|
111 | */
|
112 | define('DB_ERROR_DIVZERO', -13); |
112 | define('DB_ERROR_DIVZERO', -13); |
113 | 113 | ||
114 | /**
|
114 | /**
|
115 | * A database needs to be selected
|
115 | * A database needs to be selected
|
116 | */
|
116 | */
|
117 | define('DB_ERROR_NODBSELECTED', -14); |
117 | define('DB_ERROR_NODBSELECTED', -14); |
118 | 118 | ||
119 | /**
|
119 | /**
|
120 | * Could not create the object requested
|
120 | * Could not create the object requested
|
121 | */
|
121 | */
|
122 | define('DB_ERROR_CANNOT_CREATE', -15); |
122 | define('DB_ERROR_CANNOT_CREATE', -15); |
123 | 123 | ||
124 | /**
|
124 | /**
|
125 | * Could not drop the database requested because it does not exist
|
125 | * Could not drop the database requested because it does not exist
|
126 | */
|
126 | */
|
127 | define('DB_ERROR_CANNOT_DROP', -17); |
127 | define('DB_ERROR_CANNOT_DROP', -17); |
128 | 128 | ||
129 | /**
|
129 | /**
|
130 | * An identifier in the query refers to a non-existant table
|
130 | * An identifier in the query refers to a non-existant table
|
131 | */
|
131 | */
|
132 | define('DB_ERROR_NOSUCHTABLE', -18); |
132 | define('DB_ERROR_NOSUCHTABLE', -18); |
133 | 133 | ||
134 | /**
|
134 | /**
|
135 | * An identifier in the query refers to a non-existant column
|
135 | * An identifier in the query refers to a non-existant column
|
136 | */
|
136 | */
|
137 | define('DB_ERROR_NOSUCHFIELD', -19); |
137 | define('DB_ERROR_NOSUCHFIELD', -19); |
138 | 138 | ||
139 | /**
|
139 | /**
|
140 | * The data submitted to the method was inappropriate
|
140 | * The data submitted to the method was inappropriate
|
141 | */
|
141 | */
|
142 | define('DB_ERROR_NEED_MORE_DATA', -20); |
142 | define('DB_ERROR_NEED_MORE_DATA', -20); |
143 | 143 | ||
144 | /**
|
144 | /**
|
145 | * The attempt to lock the table failed
|
145 | * The attempt to lock the table failed
|
146 | */
|
146 | */
|
147 | define('DB_ERROR_NOT_LOCKED', -21); |
147 | define('DB_ERROR_NOT_LOCKED', -21); |
148 | 148 | ||
149 | /**
|
149 | /**
|
150 | * The number of columns doesn't match the number of values
|
150 | * The number of columns doesn't match the number of values
|
151 | */
|
151 | */
|
152 | define('DB_ERROR_VALUE_COUNT_ON_ROW', -22); |
152 | define('DB_ERROR_VALUE_COUNT_ON_ROW', -22); |
153 | 153 | ||
154 | /**
|
154 | /**
|
155 | * The DSN submitted has problems
|
155 | * The DSN submitted has problems
|
156 | */
|
156 | */
|
157 | define('DB_ERROR_INVALID_DSN', -23); |
157 | define('DB_ERROR_INVALID_DSN', -23); |
158 | 158 | ||
159 | /**
|
159 | /**
|
160 | * Could not connect to the database
|
160 | * Could not connect to the database
|
161 | */
|
161 | */
|
162 | define('DB_ERROR_CONNECT_FAILED', -24); |
162 | define('DB_ERROR_CONNECT_FAILED', -24); |
163 | 163 | ||
164 | /**
|
164 | /**
|
165 | * The PHP extension needed for this DBMS could not be found
|
165 | * The PHP extension needed for this DBMS could not be found
|
166 | */
|
166 | */
|
167 | define('DB_ERROR_EXTENSION_NOT_FOUND',-25); |
167 | define('DB_ERROR_EXTENSION_NOT_FOUND',-25); |
168 | 168 | ||
169 | /**
|
169 | /**
|
170 | * The present user has inadequate permissions to perform the task requestd
|
170 | * The present user has inadequate permissions to perform the task requestd
|
171 | */
|
171 | */
|
172 | define('DB_ERROR_ACCESS_VIOLATION', -26); |
172 | define('DB_ERROR_ACCESS_VIOLATION', -26); |
173 | 173 | ||
174 | /**
|
174 | /**
|
175 | * The database requested does not exist
|
175 | * The database requested does not exist
|
176 | */
|
176 | */
|
177 | define('DB_ERROR_NOSUCHDB', -27); |
177 | define('DB_ERROR_NOSUCHDB', -27); |
178 | 178 | ||
179 | /**
|
179 | /**
|
180 | * Tried to insert a null value into a column that doesn't allow nulls
|
180 | * Tried to insert a null value into a column that doesn't allow nulls
|
181 | */
|
181 | */
|
182 | define('DB_ERROR_CONSTRAINT_NOT_NULL',-29); |
182 | define('DB_ERROR_CONSTRAINT_NOT_NULL',-29); |
183 | /**#@-*/
|
183 | /**#@-*/
|
184 | 184 | ||
185 | 185 | ||
186 | // }}}
|
186 | // }}}
|
187 | // {{{ prepared statement-related
|
187 | // {{{ prepared statement-related
|
188 | 188 | ||
189 | 189 | ||
190 | /**#@+
|
190 | /**#@+
|
191 | * Identifiers for the placeholders used in prepared statements.
|
191 | * Identifiers for the placeholders used in prepared statements.
|
192 | * @see DB_common::prepare()
|
192 | * @see DB_common::prepare()
|
193 | */
|
193 | */
|
194 | 194 | ||
195 | /**
|
195 | /**
|
196 | * Indicates a scalar (<kbd>?</kbd>) placeholder was used
|
196 | * Indicates a scalar (<kbd>?</kbd>) placeholder was used
|
197 | *
|
197 | *
|
198 | * Quote and escape the value as necessary.
|
198 | * Quote and escape the value as necessary.
|
199 | */
|
199 | */
|
200 | define('DB_PARAM_SCALAR', 1); |
200 | define('DB_PARAM_SCALAR', 1); |
201 | 201 | ||
202 | /**
|
202 | /**
|
203 | * Indicates an opaque (<kbd>&</kbd>) placeholder was used
|
203 | * Indicates an opaque (<kbd>&</kbd>) placeholder was used
|
204 | *
|
204 | *
|
205 | * The value presented is a file name. Extract the contents of that file
|
205 | * The value presented is a file name. Extract the contents of that file
|
206 | * and place them in this column.
|
206 | * and place them in this column.
|
207 | */
|
207 | */
|
208 | define('DB_PARAM_OPAQUE', 2); |
208 | define('DB_PARAM_OPAQUE', 2); |
209 | 209 | ||
210 | /**
|
210 | /**
|
211 | * Indicates a misc (<kbd>!</kbd>) placeholder was used
|
211 | * Indicates a misc (<kbd>!</kbd>) placeholder was used
|
212 | *
|
212 | *
|
213 | * The value should not be quoted or escaped.
|
213 | * The value should not be quoted or escaped.
|
214 | */
|
214 | */
|
215 | define('DB_PARAM_MISC', 3); |
215 | define('DB_PARAM_MISC', 3); |
216 | /**#@-*/
|
216 | /**#@-*/
|
217 | 217 | ||
218 | 218 | ||
219 | // }}}
|
219 | // }}}
|
220 | // {{{ binary data-related
|
220 | // {{{ binary data-related
|
221 | 221 | ||
222 | 222 | ||
223 | /**#@+
|
223 | /**#@+
|
224 | * The different ways of returning binary data from queries.
|
224 | * The different ways of returning binary data from queries.
|
225 | */
|
225 | */
|
226 | 226 | ||
227 | /**
|
227 | /**
|
228 | * Sends the fetched data straight through to output
|
228 | * Sends the fetched data straight through to output
|
229 | */
|
229 | */
|
230 | define('DB_BINMODE_PASSTHRU', 1); |
230 | define('DB_BINMODE_PASSTHRU', 1); |
231 | 231 | ||
232 | /**
|
232 | /**
|
233 | * Lets you return data as usual
|
233 | * Lets you return data as usual
|
234 | */
|
234 | */
|
235 | define('DB_BINMODE_RETURN', 2); |
235 | define('DB_BINMODE_RETURN', 2); |
236 | 236 | ||
237 | /**
|
237 | /**
|
238 | * Converts the data to hex format before returning it
|
238 | * Converts the data to hex format before returning it
|
239 | *
|
239 | *
|
240 | * For example the string "123" would become "313233".
|
240 | * For example the string "123" would become "313233".
|
241 | */
|
241 | */
|
242 | define('DB_BINMODE_CONVERT', 3); |
242 | define('DB_BINMODE_CONVERT', 3); |
243 | /**#@-*/
|
243 | /**#@-*/
|
244 | 244 | ||
245 | 245 | ||
246 | // }}}
|
246 | // }}}
|
247 | // {{{ fetch modes
|
247 | // {{{ fetch modes
|
248 | 248 | ||
249 | 249 | ||
250 | /**#@+
|
250 | /**#@+
|
251 | * Fetch Modes.
|
251 | * Fetch Modes.
|
252 | * @see DB_common::setFetchMode()
|
252 | * @see DB_common::setFetchMode()
|
253 | */
|
253 | */
|
254 | 254 | ||
255 | /**
|
255 | /**
|
256 | * Indicates the current default fetch mode should be used
|
256 | * Indicates the current default fetch mode should be used
|
257 | * @see DB_common::$fetchmode
|
257 | * @see DB_common::$fetchmode
|
258 | */
|
258 | */
|
259 | define('DB_FETCHMODE_DEFAULT', 0); |
259 | define('DB_FETCHMODE_DEFAULT', 0); |
260 | 260 | ||
261 | /**
|
261 | /**
|
262 | * Column data indexed by numbers, ordered from 0 and up
|
262 | * Column data indexed by numbers, ordered from 0 and up
|
263 | */
|
263 | */
|
264 | define('DB_FETCHMODE_ORDERED', 1); |
264 | define('DB_FETCHMODE_ORDERED', 1); |
265 | 265 | ||
266 | /**
|
266 | /**
|
267 | * Column data indexed by column names
|
267 | * Column data indexed by column names
|
268 | */
|
268 | */
|
269 | define('DB_FETCHMODE_ASSOC', 2); |
269 | define('DB_FETCHMODE_ASSOC', 2); |
270 | 270 | ||
271 | /**
|
271 | /**
|
272 | * Column data as object properties
|
272 | * Column data as object properties
|
273 | */
|
273 | */
|
274 | define('DB_FETCHMODE_OBJECT', 3); |
274 | define('DB_FETCHMODE_OBJECT', 3); |
275 | 275 | ||
276 | /**
|
276 | /**
|
277 | * For multi-dimensional results, make the column name the first level
|
277 | * For multi-dimensional results, make the column name the first level
|
278 | * of the array and put the row number in the second level of the array
|
278 | * of the array and put the row number in the second level of the array
|
279 | *
|
279 | *
|
280 | * This is flipped from the normal behavior, which puts the row numbers
|
280 | * This is flipped from the normal behavior, which puts the row numbers
|
281 | * in the first level of the array and the column names in the second level.
|
281 | * in the first level of the array and the column names in the second level.
|
282 | */
|
282 | */
|
283 | define('DB_FETCHMODE_FLIPPED', 4); |
283 | define('DB_FETCHMODE_FLIPPED', 4); |
284 | /**#@-*/
|
284 | /**#@-*/
|
285 | 285 | ||
286 | /**#@+
|
286 | /**#@+
|
287 | * Old fetch modes. Left here for compatibility.
|
287 | * Old fetch modes. Left here for compatibility.
|
288 | */
|
288 | */
|
289 | define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); |
289 | define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); |
290 | define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); |
290 | define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); |
291 | define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); |
291 | define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); |
292 | /**#@-*/
|
292 | /**#@-*/
|
293 | 293 | ||
294 | 294 | ||
295 | // }}}
|
295 | // }}}
|
296 | // {{{ tableInfo() && autoPrepare()-related
|
296 | // {{{ tableInfo() && autoPrepare()-related
|
297 | 297 | ||
298 | 298 | ||
299 | /**#@+
|
299 | /**#@+
|
300 | * The type of information to return from the tableInfo() method.
|
300 | * The type of information to return from the tableInfo() method.
|
301 | *
|
301 | *
|
302 | * Bitwised constants, so they can be combined using <kbd>|</kbd>
|
302 | * Bitwised constants, so they can be combined using <kbd>|</kbd>
|
303 | * and removed using <kbd>^</kbd>.
|
303 | * and removed using <kbd>^</kbd>.
|
304 | *
|
304 | *
|
305 | * @see DB_common::tableInfo()
|
305 | * @see DB_common::tableInfo()
|
306 | *
|
306 | *
|
307 | * {@internal Since the TABLEINFO constants are bitwised, if more of them are
|
307 | * {@internal Since the TABLEINFO constants are bitwised, if more of them are
|
308 | * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}}
|
308 | * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}}
|
309 | */
|
309 | */
|
310 | define('DB_TABLEINFO_ORDER', 1); |
310 | define('DB_TABLEINFO_ORDER', 1); |
311 | define('DB_TABLEINFO_ORDERTABLE', 2); |
311 | define('DB_TABLEINFO_ORDERTABLE', 2); |
312 | define('DB_TABLEINFO_FULL', 3); |
312 | define('DB_TABLEINFO_FULL', 3); |
313 | /**#@-*/
|
313 | /**#@-*/
|
314 | 314 | ||
315 | 315 | ||
316 | /**#@+
|
316 | /**#@+
|
317 | * The type of query to create with the automatic query building methods.
|
317 | * The type of query to create with the automatic query building methods.
|
318 | * @see DB_common::autoPrepare(), DB_common::autoExecute()
|
318 | * @see DB_common::autoPrepare(), DB_common::autoExecute()
|
319 | */
|
319 | */
|
320 | define('DB_AUTOQUERY_INSERT', 1); |
320 | define('DB_AUTOQUERY_INSERT', 1); |
321 | define('DB_AUTOQUERY_UPDATE', 2); |
321 | define('DB_AUTOQUERY_UPDATE', 2); |
322 | /**#@-*/
|
322 | /**#@-*/
|
323 | 323 | ||
324 | 324 | ||
325 | // }}}
|
325 | // }}}
|
326 | // {{{ portability modes
|
326 | // {{{ portability modes
|
327 | 327 | ||
328 | 328 | ||
329 | /**#@+
|
329 | /**#@+
|
330 | * Portability Modes.
|
330 | * Portability Modes.
|
331 | *
|
331 | *
|
332 | * Bitwised constants, so they can be combined using <kbd>|</kbd>
|
332 | * Bitwised constants, so they can be combined using <kbd>|</kbd>
|
333 | * and removed using <kbd>^</kbd>.
|
333 | * and removed using <kbd>^</kbd>.
|
334 | *
|
334 | *
|
335 | * @see DB_common::setOption()
|
335 | * @see DB_common::setOption()
|
336 | *
|
336 | *
|
337 | * {@internal Since the PORTABILITY constants are bitwised, if more of them are
|
337 | * {@internal Since the PORTABILITY constants are bitwised, if more of them are
|
338 | * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}}
|
338 | * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}}
|
339 | */
|
339 | */
|
340 | 340 | ||
341 | /**
|
341 | /**
|
342 | * Turn off all portability features
|
342 | * Turn off all portability features
|
343 | */
|
343 | */
|
344 | define('DB_PORTABILITY_NONE', 0); |
344 | define('DB_PORTABILITY_NONE', 0); |
345 | 345 | ||
346 | /**
|
346 | /**
|
347 | * Convert names of tables and fields to lower case
|
347 | * Convert names of tables and fields to lower case
|
348 | * when using the get*(), fetch*() and tableInfo() methods
|
348 | * when using the get*(), fetch*() and tableInfo() methods
|
349 | */
|
349 | */
|
350 | define('DB_PORTABILITY_LOWERCASE', 1); |
350 | define('DB_PORTABILITY_LOWERCASE', 1); |
351 | 351 | ||
352 | /**
|
352 | /**
|
353 | * Right trim the data output by get*() and fetch*()
|
353 | * Right trim the data output by get*() and fetch*()
|
354 | */
|
354 | */
|
355 | define('DB_PORTABILITY_RTRIM', 2); |
355 | define('DB_PORTABILITY_RTRIM', 2); |
356 | 356 | ||
357 | /**
|
357 | /**
|
358 | * Force reporting the number of rows deleted
|
358 | * Force reporting the number of rows deleted
|
359 | */
|
359 | */
|
360 | define('DB_PORTABILITY_DELETE_COUNT', 4); |
360 | define('DB_PORTABILITY_DELETE_COUNT', 4); |
361 | 361 | ||
362 | /**
|
362 | /**
|
363 | * Enable hack that makes numRows() work in Oracle
|
363 | * Enable hack that makes numRows() work in Oracle
|
364 | */
|
364 | */
|
365 | define('DB_PORTABILITY_NUMROWS', 8); |
365 | define('DB_PORTABILITY_NUMROWS', 8); |
366 | 366 | ||
367 | /**
|
367 | /**
|
368 | * Makes certain error messages in certain drivers compatible
|
368 | * Makes certain error messages in certain drivers compatible
|
369 | * with those from other DBMS's
|
369 | * with those from other DBMS's
|
370 | *
|
370 | *
|
371 | * + mysql, mysqli: change unique/primary key constraints
|
371 | * + mysql, mysqli: change unique/primary key constraints
|
372 | * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
|
372 | * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
|
373 | *
|
373 | *
|
374 | * + odbc(access): MS's ODBC driver reports 'no such field' as code
|
374 | * + odbc(access): MS's ODBC driver reports 'no such field' as code
|
375 | * 07001, which means 'too few parameters.' When this option is on
|
375 | * 07001, which means 'too few parameters.' When this option is on
|
376 | * that code gets mapped to DB_ERROR_NOSUCHFIELD.
|
376 | * that code gets mapped to DB_ERROR_NOSUCHFIELD.
|
377 | */
|
377 | */
|
378 | define('DB_PORTABILITY_ERRORS', 16); |
378 | define('DB_PORTABILITY_ERRORS', 16); |
379 | 379 | ||
380 | /**
|
380 | /**
|
381 | * Convert null values to empty strings in data output by
|
381 | * Convert null values to empty strings in data output by
|
382 | * get*() and fetch*()
|
382 | * get*() and fetch*()
|
383 | */
|
383 | */
|
384 | define('DB_PORTABILITY_NULL_TO_EMPTY', 32); |
384 | define('DB_PORTABILITY_NULL_TO_EMPTY', 32); |
385 | 385 | ||
386 | /**
|
386 | /**
|
387 | * Turn on all portability features
|
387 | * Turn on all portability features
|
388 | */
|
388 | */
|
389 | define('DB_PORTABILITY_ALL', 63); |
389 | define('DB_PORTABILITY_ALL', 63); |
390 | /**#@-*/
|
390 | /**#@-*/
|
391 | 391 | ||
392 | // }}}
|
392 | // }}}
|
393 | 393 | ||
394 | 394 | ||
395 | // }}}
|
395 | // }}}
|
396 | // {{{ class DB
|
396 | // {{{ class DB
|
397 | 397 | ||
398 | /**
|
398 | /**
|
399 | * Database independent query interface
|
399 | * Database independent query interface
|
400 | *
|
400 | *
|
401 | * The main "DB" class is simply a container class with some static
|
401 | * The main "DB" class is simply a container class with some static
|
402 | * methods for creating DB objects as well as some utility functions
|
402 | * methods for creating DB objects as well as some utility functions
|
403 | * common to all parts of DB.
|
403 | * common to all parts of DB.
|
404 | *
|
404 | *
|
405 | * The object model of DB is as follows (indentation means inheritance):
|
405 | * The object model of DB is as follows (indentation means inheritance):
|
406 | * <pre>
|
406 | * <pre>
|
407 | * DB The main DB class. This is simply a utility class
|
407 | * DB The main DB class. This is simply a utility class
|
408 | * with some "static" methods for creating DB objects as
|
408 | * with some "static" methods for creating DB objects as
|
409 | * well as common utility functions for other DB classes.
|
409 | * well as common utility functions for other DB classes.
|
410 | *
|
410 | *
|
411 | * DB_common The base for each DB implementation. Provides default
|
411 | * DB_common The base for each DB implementation. Provides default
|
412 | * | implementations (in OO lingo virtual methods) for
|
412 | * | implementations (in OO lingo virtual methods) for
|
413 | * | the actual DB implementations as well as a bunch of
|
413 | * | the actual DB implementations as well as a bunch of
|
414 | * | query utility functions.
|
414 | * | query utility functions.
|
415 | * |
|
415 | * |
|
416 | * +-DB_mysql The DB implementation for MySQL. Inherits DB_common.
|
416 | * +-DB_mysql The DB implementation for MySQL. Inherits DB_common.
|
417 | * When calling DB::factory or DB::connect for MySQL
|
417 | * When calling DB::factory or DB::connect for MySQL
|
418 | * connections, the object returned is an instance of this
|
418 | * connections, the object returned is an instance of this
|
419 | * class.
|
419 | * class.
|
420 | * </pre>
|
420 | * </pre>
|
421 | *
|
421 | *
|
422 | * @category Database
|
422 | * @category Database
|
423 | * @package DB
|
423 | * @package DB
|
424 | * @author Stig Bakken <ssb@php.net>
|
424 | * @author Stig Bakken <ssb@php.net>
|
425 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
425 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
426 | * @author Daniel Convissor <danielc@php.net>
|
426 | * @author Daniel Convissor <danielc@php.net>
|
427 | * @copyright 1997-2007 The PHP Group
|
427 | * @copyright 1997-2007 The PHP Group
|
428 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
428 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
429 | * @version Release: 1.7.13
|
429 | * @version Release: 1.7.13
|
430 | * @link http://pear.php.net/package/DB
|
430 | * @link http://pear.php.net/package/DB
|
431 | */
|
431 | */
|
432 | class DB
|
432 | class DB
|
433 | {
|
433 | {
|
434 | // {{{ &factory()
|
434 | // {{{ &factory()
|
435 | 435 | ||
436 | /**
|
436 | /**
|
437 | * Create a new DB object for the specified database type but don't
|
437 | * Create a new DB object for the specified database type but don't
|
438 | * connect to the database
|
438 | * connect to the database
|
439 | *
|
439 | *
|
440 | * @param string $type the database type (eg "mysql")
|
440 | * @param string $type the database type (eg "mysql")
|
441 | * @param array $options an associative array of option names and values
|
441 | * @param array $options an associative array of option names and values
|
442 | *
|
442 | *
|
443 | * @return object a new DB object. A DB_Error object on failure.
|
443 | * @return object a new DB object. A DB_Error object on failure.
|
444 | *
|
444 | *
|
445 | * @see DB_common::setOption()
|
445 | * @see DB_common::setOption()
|
446 | */
|
446 | */
|
447 | function &factory($type, $options = false) |
447 | function &factory($type, $options = false) |
448 | {
|
448 | {
|
449 | if (!is_array($options)) { |
449 | if (!is_array($options)) { |
450 | $options = array('persistent' => $options); |
450 | $options = array('persistent' => $options); |
451 | }
|
451 | }
|
452 | 452 | ||
453 | if (isset($options['debug']) && $options['debug'] >= 2) { |
453 | if (isset($options['debug']) && $options['debug'] >= 2) { |
454 | // expose php errors with sufficient debug level
|
454 | // expose php errors with sufficient debug level
|
455 | include_once "DB/{$type}.php"; |
455 | include_once "DB/{$type}.php"; |
456 | } else { |
456 | } else { |
457 | @include_once "DB/{$type}.php"; |
457 | @include_once "DB/{$type}.php"; |
458 | }
|
458 | }
|
459 | 459 | ||
460 | $classname = "DB_${type}"; |
460 | $classname = "DB_${type}"; |
461 | 461 | ||
462 | if (!class_exists($classname)) { |
462 | if (!class_exists($classname)) { |
463 | $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
463 | $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
464 | "Unable to include the DB/{$type}.php"
|
464 | "Unable to include the DB/{$type}.php"
|
465 | . " file for '$dsn'", |
465 | . " file for '$dsn'", |
466 | 'DB_Error', true); |
466 | 'DB_Error', true); |
467 | return $tmp; |
467 | return $tmp; |
468 | }
|
468 | }
|
469 | 469 | ||
470 | @$obj = new $classname; |
470 | @$obj = new $classname; |
471 | 471 | ||
472 | foreach ($options as $option => $value) { |
472 | foreach ($options as $option => $value) { |
473 | $test = $obj->setOption($option, $value); |
473 | $test = $obj->setOption($option, $value); |
474 | if (DB::isError($test)) { |
474 | if (DB::isError($test)) { |
475 | return $test; |
475 | return $test; |
476 | }
|
476 | }
|
477 | }
|
477 | }
|
478 | 478 | ||
479 | return $obj; |
479 | return $obj; |
480 | }
|
480 | }
|
481 | 481 | ||
482 | // }}}
|
482 | // }}}
|
483 | // {{{ &connect()
|
483 | // {{{ &connect()
|
484 | 484 | ||
485 | /**
|
485 | /**
|
486 | * Create a new DB object including a connection to the specified database
|
486 | * Create a new DB object including a connection to the specified database
|
487 | *
|
487 | *
|
488 | * Example 1.
|
488 | * Example 1.
|
489 | * <code>
|
489 | * <code>
|
490 | * require_once 'DB.php';
|
490 | * require_once 'DB.php';
|
491 | *
|
491 | *
|
492 | * $dsn = 'pgsql://user:password@host/database';
|
492 | * $dsn = 'pgsql://user:password@host/database';
|
493 | * $options = array(
|
493 | * $options = array(
|
494 | * 'debug' => 2,
|
494 | * 'debug' => 2,
|
495 | * 'portability' => DB_PORTABILITY_ALL,
|
495 | * 'portability' => DB_PORTABILITY_ALL,
|
496 | * );
|
496 | * );
|
497 | *
|
497 | *
|
498 | * $db =& DB::connect($dsn, $options);
|
498 | * $db =& DB::connect($dsn, $options);
|
499 | * if (PEAR::isError($db)) {
|
499 | * if (PEAR::isError($db)) {
|
500 | * die($db->getMessage());
|
500 | * die($db->getMessage());
|
501 | * }
|
501 | * }
|
502 | * </code>
|
502 | * </code>
|
503 | *
|
503 | *
|
504 | * @param mixed $dsn the string "data source name" or array in the
|
504 | * @param mixed $dsn the string "data source name" or array in the
|
505 | * format returned by DB::parseDSN()
|
505 | * format returned by DB::parseDSN()
|
506 | * @param array $options an associative array of option names and values
|
506 | * @param array $options an associative array of option names and values
|
507 | *
|
507 | *
|
508 | * @return object a new DB object. A DB_Error object on failure.
|
508 | * @return object a new DB object. A DB_Error object on failure.
|
509 | *
|
509 | *
|
510 | * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(),
|
510 | * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(),
|
511 | * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(),
|
511 | * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(),
|
512 | * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(),
|
512 | * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(),
|
513 | * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(),
|
513 | * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(),
|
514 | * DB_sybase::connect()
|
514 | * DB_sybase::connect()
|
515 | *
|
515 | *
|
516 | * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError()
|
516 | * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError()
|
517 | */
|
517 | */
|
518 | function &connect($dsn, $options = array()) |
518 | function &connect($dsn, $options = array()) |
519 | {
|
519 | {
|
520 | $dsninfo = DB::parseDSN($dsn); |
520 | $dsninfo = DB::parseDSN($dsn); |
521 | $type = $dsninfo['phptype']; |
521 | $type = $dsninfo['phptype']; |
522 | 522 | ||
523 | if (!is_array($options)) { |
523 | if (!is_array($options)) { |
524 | /*
|
524 | /*
|
525 | * For backwards compatibility. $options used to be boolean,
|
525 | * For backwards compatibility. $options used to be boolean,
|
526 | * indicating whether the connection should be persistent.
|
526 | * indicating whether the connection should be persistent.
|
527 | */
|
527 | */
|
528 | $options = array('persistent' => $options); |
528 | $options = array('persistent' => $options); |
529 | }
|
529 | }
|
530 | 530 | ||
531 | if (isset($options['debug']) && $options['debug'] >= 2) { |
531 | if (isset($options['debug']) && $options['debug'] >= 2) { |
532 | // expose php errors with sufficient debug level
|
532 | // expose php errors with sufficient debug level
|
533 | include_once "DB/${type}.php"; |
533 | include_once "DB/${type}.php"; |
534 | } else { |
534 | } else { |
535 | @include_once "DB/${type}.php"; |
535 | @include_once "DB/${type}.php"; |
536 | }
|
536 | }
|
537 | 537 | ||
538 | $classname = "DB_${type}"; |
538 | $classname = "DB_${type}"; |
539 | if (!class_exists($classname)) { |
539 | if (!class_exists($classname)) { |
540 | $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
540 | $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, |
541 | "Unable to include the DB/{$type}.php"
|
541 | "Unable to include the DB/{$type}.php"
|
542 | . " file for '$dsn'", |
542 | . " file for '$dsn'", |
543 | 'DB_Error', true); |
543 | 'DB_Error', true); |
544 | return $tmp; |
544 | return $tmp; |
545 | }
|
545 | }
|
546 | 546 | ||
547 | @$obj = new $classname; |
547 | @$obj = new $classname; |
548 | 548 | ||
549 | foreach ($options as $option => $value) { |
549 | foreach ($options as $option => $value) { |
550 | $test = $obj->setOption($option, $value); |
550 | $test = $obj->setOption($option, $value); |
551 | if (DB::isError($test)) { |
551 | if (DB::isError($test)) { |
552 | return $test; |
552 | return $test; |
553 | }
|
553 | }
|
554 | }
|
554 | }
|
555 | 555 | ||
556 | $err = $obj->connect($dsninfo, $obj->getOption('persistent')); |
556 | $err = $obj->connect($dsninfo, $obj->getOption('persistent')); |
557 | if (DB::isError($err)) { |
557 | if (DB::isError($err)) { |
558 | if (is_array($dsn)) { |
558 | if (is_array($dsn)) { |
559 | $err->addUserInfo(DB::getDSNString($dsn, true)); |
559 | $err->addUserInfo(DB::getDSNString($dsn, true)); |
560 | } else { |
560 | } else { |
561 | $err->addUserInfo($dsn); |
561 | $err->addUserInfo($dsn); |
562 | }
|
562 | }
|
563 | return $err; |
563 | return $err; |
564 | }
|
564 | }
|
565 | 565 | ||
566 | return $obj; |
566 | return $obj; |
567 | }
|
567 | }
|
568 | 568 | ||
569 | // }}}
|
569 | // }}}
|
570 | // {{{ apiVersion()
|
570 | // {{{ apiVersion()
|
571 | 571 | ||
572 | /**
|
572 | /**
|
573 | * Return the DB API version
|
573 | * Return the DB API version
|
574 | *
|
574 | *
|
575 | * @return string the DB API version number
|
575 | * @return string the DB API version number
|
576 | */
|
576 | */
|
577 | function apiVersion() |
577 | function apiVersion() |
578 | {
|
578 | {
|
579 | return '1.7.13'; |
579 | return '1.7.13'; |
580 | }
|
580 | }
|
581 | 581 | ||
582 | // }}}
|
582 | // }}}
|
583 | // {{{ isError()
|
583 | // {{{ isError()
|
584 | 584 | ||
585 | /**
|
585 | /**
|
586 | * Determines if a variable is a DB_Error object
|
586 | * Determines if a variable is a DB_Error object
|
587 | *
|
587 | *
|
588 | * @param mixed $value the variable to check
|
588 | * @param mixed $value the variable to check
|
589 | *
|
589 | *
|
590 | * @return bool whether $value is DB_Error object
|
590 | * @return bool whether $value is DB_Error object
|
591 | */
|
591 | */
|
592 | function isError($value) |
592 | function isError($value) |
593 | {
|
593 | {
|
594 | return is_a($value, 'DB_Error'); |
594 | return is_a($value, 'DB_Error'); |
595 | }
|
595 | }
|
596 | 596 | ||
597 | // }}}
|
597 | // }}}
|
598 | // {{{ isConnection()
|
598 | // {{{ isConnection()
|
599 | 599 | ||
600 | /**
|
600 | /**
|
601 | * Determines if a value is a DB_<driver> object
|
601 | * Determines if a value is a DB_<driver> object
|
602 | *
|
602 | *
|
603 | * @param mixed $value the value to test
|
603 | * @param mixed $value the value to test
|
604 | *
|
604 | *
|
605 | * @return bool whether $value is a DB_<driver> object
|
605 | * @return bool whether $value is a DB_<driver> object
|
606 | */
|
606 | */
|
607 | function isConnection($value) |
607 | function isConnection($value) |
608 | {
|
608 | {
|
609 | return (is_object($value) && |
609 | return (is_object($value) && |
610 | is_subclass_of($value, 'db_common') && |
610 | is_subclass_of($value, 'db_common') && |
611 | method_exists($value, 'simpleQuery')); |
611 | method_exists($value, 'simpleQuery')); |
612 | }
|
612 | }
|
613 | 613 | ||
614 | // }}}
|
614 | // }}}
|
615 | // {{{ isManip()
|
615 | // {{{ isManip()
|
616 | 616 | ||
617 | /**
|
617 | /**
|
618 | * Tell whether a query is a data manipulation or data definition query
|
618 | * Tell whether a query is a data manipulation or data definition query
|
619 | *
|
619 | *
|
620 | * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
|
620 | * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
|
621 | * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
|
621 | * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
|
622 | * REVOKE.
|
622 | * REVOKE.
|
623 | *
|
623 | *
|
624 | * @param string $query the query
|
624 | * @param string $query the query
|
625 | *
|
625 | *
|
626 | * @return boolean whether $query is a data manipulation query
|
626 | * @return boolean whether $query is a data manipulation query
|
627 | */
|
627 | */
|
628 | function isManip($query) |
628 | function isManip($query) |
629 | {
|
629 | {
|
630 | $manips = 'INSERT|UPDATE|DELETE|REPLACE|' |
630 | $manips = 'INSERT|UPDATE|DELETE|REPLACE|' |
631 | . 'CREATE|DROP|' |
631 | . 'CREATE|DROP|' |
632 | . 'LOAD DATA|SELECT .* INTO .* FROM|COPY|' |
632 | . 'LOAD DATA|SELECT .* INTO .* FROM|COPY|' |
633 | . 'ALTER|GRANT|REVOKE|' |
633 | . 'ALTER|GRANT|REVOKE|' |
634 | . 'LOCK|UNLOCK'; |
634 | . 'LOCK|UNLOCK'; |
635 | if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { |
635 | if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { |
636 | return true; |
636 | return true; |
637 | }
|
637 | }
|
638 | return false; |
638 | return false; |
639 | }
|
639 | }
|
640 | 640 | ||
641 | // }}}
|
641 | // }}}
|
642 | // {{{ errorMessage()
|
642 | // {{{ errorMessage()
|
643 | 643 | ||
644 | /**
|
644 | /**
|
645 | * Return a textual error message for a DB error code
|
645 | * Return a textual error message for a DB error code
|
646 | *
|
646 | *
|
647 | * @param integer $value the DB error code
|
647 | * @param integer $value the DB error code
|
648 | *
|
648 | *
|
649 | * @return string the error message or false if the error code was
|
649 | * @return string the error message or false if the error code was
|
650 | * not recognized
|
650 | * not recognized
|
651 | */
|
651 | */
|
652 | function errorMessage($value) |
652 | function errorMessage($value) |
653 | {
|
653 | {
|
654 | static $errorMessages; |
654 | static $errorMessages; |
655 | if (!isset($errorMessages)) { |
655 | if (!isset($errorMessages)) { |
656 | $errorMessages = array( |
656 | $errorMessages = array( |
657 | DB_ERROR => 'unknown error', |
657 | DB_ERROR => 'unknown error', |
658 | DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', |
658 | DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', |
659 | DB_ERROR_ALREADY_EXISTS => 'already exists', |
659 | DB_ERROR_ALREADY_EXISTS => 'already exists', |
660 | DB_ERROR_CANNOT_CREATE => 'can not create', |
660 | DB_ERROR_CANNOT_CREATE => 'can not create', |
661 | DB_ERROR_CANNOT_DROP => 'can not drop', |
661 | DB_ERROR_CANNOT_DROP => 'can not drop', |
662 | DB_ERROR_CONNECT_FAILED => 'connect failed', |
662 | DB_ERROR_CONNECT_FAILED => 'connect failed', |
663 | DB_ERROR_CONSTRAINT => 'constraint violation', |
663 | DB_ERROR_CONSTRAINT => 'constraint violation', |
664 | DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', |
664 | DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', |
665 | DB_ERROR_DIVZERO => 'division by zero', |
665 | DB_ERROR_DIVZERO => 'division by zero', |
666 | DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', |
666 | DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', |
667 | DB_ERROR_INVALID => 'invalid', |
667 | DB_ERROR_INVALID => 'invalid', |
668 | DB_ERROR_INVALID_DATE => 'invalid date or time', |
668 | DB_ERROR_INVALID_DATE => 'invalid date or time', |
669 | DB_ERROR_INVALID_DSN => 'invalid DSN', |
669 | DB_ERROR_INVALID_DSN => 'invalid DSN', |
670 | DB_ERROR_INVALID_NUMBER => 'invalid number', |
670 | DB_ERROR_INVALID_NUMBER => 'invalid number', |
671 | DB_ERROR_MISMATCH => 'mismatch', |
671 | DB_ERROR_MISMATCH => 'mismatch', |
672 | DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', |
672 | DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', |
673 | DB_ERROR_NODBSELECTED => 'no database selected', |
673 | DB_ERROR_NODBSELECTED => 'no database selected', |
674 | DB_ERROR_NOSUCHDB => 'no such database', |
674 | DB_ERROR_NOSUCHDB => 'no such database', |
675 | DB_ERROR_NOSUCHFIELD => 'no such field', |
675 | DB_ERROR_NOSUCHFIELD => 'no such field', |
676 | DB_ERROR_NOSUCHTABLE => 'no such table', |
676 | DB_ERROR_NOSUCHTABLE => 'no such table', |
677 | DB_ERROR_NOT_CAPABLE => 'DB backend not capable', |
677 | DB_ERROR_NOT_CAPABLE => 'DB backend not capable', |
678 | DB_ERROR_NOT_FOUND => 'not found', |
678 | DB_ERROR_NOT_FOUND => 'not found', |
679 | DB_ERROR_NOT_LOCKED => 'not locked', |
679 | DB_ERROR_NOT_LOCKED => 'not locked', |
680 | DB_ERROR_SYNTAX => 'syntax error', |
680 | DB_ERROR_SYNTAX => 'syntax error', |
681 | DB_ERROR_UNSUPPORTED => 'not supported', |
681 | DB_ERROR_UNSUPPORTED => 'not supported', |
682 | DB_ERROR_TRUNCATED => 'truncated', |
682 | DB_ERROR_TRUNCATED => 'truncated', |
683 | DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', |
683 | DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', |
684 | DB_OK => 'no error', |
684 | DB_OK => 'no error', |
685 | ); |
685 | ); |
686 | }
|
686 | }
|
687 | 687 | ||
688 | if (DB::isError($value)) { |
688 | if (DB::isError($value)) { |
689 | $value = $value->getCode(); |
689 | $value = $value->getCode(); |
690 | }
|
690 | }
|
691 | 691 | ||
692 | return isset($errorMessages[$value]) ? $errorMessages[$value] |
692 | return isset($errorMessages[$value]) ? $errorMessages[$value] |
693 | : $errorMessages[DB_ERROR]; |
693 | : $errorMessages[DB_ERROR]; |
694 | }
|
694 | }
|
695 | 695 | ||
696 | // }}}
|
696 | // }}}
|
697 | // {{{ parseDSN()
|
697 | // {{{ parseDSN()
|
698 | 698 | ||
699 | /**
|
699 | /**
|
700 | * Parse a data source name
|
700 | * Parse a data source name
|
701 | *
|
701 | *
|
702 | * Additional keys can be added by appending a URI query string to the
|
702 | * Additional keys can be added by appending a URI query string to the
|
703 | * end of the DSN.
|
703 | * end of the DSN.
|
704 | *
|
704 | *
|
705 | * The format of the supplied DSN is in its fullest form:
|
705 | * The format of the supplied DSN is in its fullest form:
|
706 | * <code>
|
706 | * <code>
|
707 | * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
|
707 | * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
|
708 | * </code>
|
708 | * </code>
|
709 | *
|
709 | *
|
710 | * Most variations are allowed:
|
710 | * Most variations are allowed:
|
711 | * <code>
|
711 | * <code>
|
712 | * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
|
712 | * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
|
713 | * phptype://username:password@hostspec/database_name
|
713 | * phptype://username:password@hostspec/database_name
|
714 | * phptype://username:password@hostspec
|
714 | * phptype://username:password@hostspec
|
715 | * phptype://username@hostspec
|
715 | * phptype://username@hostspec
|
716 | * phptype://hostspec/database
|
716 | * phptype://hostspec/database
|
717 | * phptype://hostspec
|
717 | * phptype://hostspec
|
718 | * phptype(dbsyntax)
|
718 | * phptype(dbsyntax)
|
719 | * phptype
|
719 | * phptype
|
720 | * </code>
|
720 | * </code>
|
721 | *
|
721 | *
|
722 | * @param string $dsn Data Source Name to be parsed
|
722 | * @param string $dsn Data Source Name to be parsed
|
723 | *
|
723 | *
|
724 | * @return array an associative array with the following keys:
|
724 | * @return array an associative array with the following keys:
|
725 | * + phptype: Database backend used in PHP (mysql, odbc etc.)
|
725 | * + phptype: Database backend used in PHP (mysql, odbc etc.)
|
726 | * + dbsyntax: Database used with regards to SQL syntax etc.
|
726 | * + dbsyntax: Database used with regards to SQL syntax etc.
|
727 | * + protocol: Communication protocol to use (tcp, unix etc.)
|
727 | * + protocol: Communication protocol to use (tcp, unix etc.)
|
728 | * + hostspec: Host specification (hostname[:port])
|
728 | * + hostspec: Host specification (hostname[:port])
|
729 | * + database: Database to use on the DBMS server
|
729 | * + database: Database to use on the DBMS server
|
730 | * + username: User name for login
|
730 | * + username: User name for login
|
731 | * + password: Password for login
|
731 | * + password: Password for login
|
732 | */
|
732 | */
|
733 | function parseDSN($dsn) |
733 | function parseDSN($dsn) |
734 | {
|
734 | {
|
735 | $parsed = array( |
735 | $parsed = array( |
736 | 'phptype' => false, |
736 | 'phptype' => false, |
737 | 'dbsyntax' => false, |
737 | 'dbsyntax' => false, |
738 | 'username' => false, |
738 | 'username' => false, |
739 | 'password' => false, |
739 | 'password' => false, |
740 | 'protocol' => false, |
740 | 'protocol' => false, |
741 | 'hostspec' => false, |
741 | 'hostspec' => false, |
742 | 'port' => false, |
742 | 'port' => false, |
743 | 'socket' => false, |
743 | 'socket' => false, |
744 | 'database' => false, |
744 | 'database' => false, |
745 | ); |
745 | ); |
746 | 746 | ||
747 | if (is_array($dsn)) { |
747 | if (is_array($dsn)) { |
748 | $dsn = array_merge($parsed, $dsn); |
748 | $dsn = array_merge($parsed, $dsn); |
749 | if (!$dsn['dbsyntax']) { |
749 | if (!$dsn['dbsyntax']) { |
750 | $dsn['dbsyntax'] = $dsn['phptype']; |
750 | $dsn['dbsyntax'] = $dsn['phptype']; |
751 | }
|
751 | }
|
752 | return $dsn; |
752 | return $dsn; |
753 | }
|
753 | }
|
754 | 754 | ||
755 | // Find phptype and dbsyntax
|
755 | // Find phptype and dbsyntax
|
756 | if (($pos = strpos($dsn, '://')) !== false) { |
756 | if (($pos = strpos($dsn, '://')) !== false) { |
757 | $str = substr($dsn, 0, $pos); |
757 | $str = substr($dsn, 0, $pos); |
758 | $dsn = substr($dsn, $pos + 3); |
758 | $dsn = substr($dsn, $pos + 3); |
759 | } else { |
759 | } else { |
760 | $str = $dsn; |
760 | $str = $dsn; |
761 | $dsn = null; |
761 | $dsn = null; |
762 | }
|
762 | }
|
763 | 763 | ||
764 | // Get phptype and dbsyntax
|
764 | // Get phptype and dbsyntax
|
765 | // $str => phptype(dbsyntax)
|
765 | // $str => phptype(dbsyntax)
|
766 | if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { |
766 | if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { |
767 | $parsed['phptype'] = $arr[1]; |
767 | $parsed['phptype'] = $arr[1]; |
768 | $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; |
768 | $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; |
769 | } else { |
769 | } else { |
770 | $parsed['phptype'] = $str; |
770 | $parsed['phptype'] = $str; |
771 | $parsed['dbsyntax'] = $str; |
771 | $parsed['dbsyntax'] = $str; |
772 | }
|
772 | }
|
773 | 773 | ||
774 | if (!count($dsn)) { |
774 | if (!count($dsn)) { |
775 | return $parsed; |
775 | return $parsed; |
776 | }
|
776 | }
|
777 | 777 | ||
778 | // Get (if found): username and password
|
778 | // Get (if found): username and password
|
779 | // $dsn => username:password@protocol+hostspec/database
|
779 | // $dsn => username:password@protocol+hostspec/database
|
780 | if (($at = strrpos($dsn,'@')) !== false) { |
780 | if (($at = strrpos($dsn,'@')) !== false) { |
781 | $str = substr($dsn, 0, $at); |
781 | $str = substr($dsn, 0, $at); |
782 | $dsn = substr($dsn, $at + 1); |
782 | $dsn = substr($dsn, $at + 1); |
783 | if (($pos = strpos($str, ':')) !== false) { |
783 | if (($pos = strpos($str, ':')) !== false) { |
784 | $parsed['username'] = rawurldecode(substr($str, 0, $pos)); |
784 | $parsed['username'] = rawurldecode(substr($str, 0, $pos)); |
785 | $parsed['password'] = rawurldecode(substr($str, $pos + 1)); |
785 | $parsed['password'] = rawurldecode(substr($str, $pos + 1)); |
786 | } else { |
786 | } else { |
787 | $parsed['username'] = rawurldecode($str); |
787 | $parsed['username'] = rawurldecode($str); |
788 | }
|
788 | }
|
789 | }
|
789 | }
|
790 | 790 | ||
791 | // Find protocol and hostspec
|
791 | // Find protocol and hostspec
|
792 | 792 | ||
793 | if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { |
793 | if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { |
794 | // $dsn => proto(proto_opts)/database
|
794 | // $dsn => proto(proto_opts)/database
|
795 | $proto = $match[1]; |
795 | $proto = $match[1]; |
796 | $proto_opts = $match[2] ? $match[2] : false; |
796 | $proto_opts = $match[2] ? $match[2] : false; |
797 | $dsn = $match[3]; |
797 | $dsn = $match[3]; |
798 | 798 | ||
799 | } else { |
799 | } else { |
800 | // $dsn => protocol+hostspec/database (old format)
|
800 | // $dsn => protocol+hostspec/database (old format)
|
801 | if (strpos($dsn, '+') !== false) { |
801 | if (strpos($dsn, '+') !== false) { |
802 | list($proto, $dsn) = explode('+', $dsn, 2); |
802 | list($proto, $dsn) = explode('+', $dsn, 2); |
803 | }
|
803 | }
|
804 | if (strpos($dsn, '/') !== false) { |
804 | if (strpos($dsn, '/') !== false) { |
805 | list($proto_opts, $dsn) = explode('/', $dsn, 2); |
805 | list($proto_opts, $dsn) = explode('/', $dsn, 2); |
806 | } else { |
806 | } else { |
807 | $proto_opts = $dsn; |
807 | $proto_opts = $dsn; |
808 | $dsn = null; |
808 | $dsn = null; |
809 | }
|
809 | }
|
810 | }
|
810 | }
|
811 | 811 | ||
812 | // process the different protocol options
|
812 | // process the different protocol options
|
813 | $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; |
813 | $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; |
814 | $proto_opts = rawurldecode($proto_opts); |
814 | $proto_opts = rawurldecode($proto_opts); |
815 | if (strpos($proto_opts, ':') !== false) { |
815 | if (strpos($proto_opts, ':') !== false) { |
816 | list($proto_opts, $parsed['port']) = explode(':', $proto_opts); |
816 | list($proto_opts, $parsed['port']) = explode(':', $proto_opts); |
817 | }
|
817 | }
|
818 | if ($parsed['protocol'] == 'tcp') { |
818 | if ($parsed['protocol'] == 'tcp') { |
819 | $parsed['hostspec'] = $proto_opts; |
819 | $parsed['hostspec'] = $proto_opts; |
820 | } elseif ($parsed['protocol'] == 'unix') { |
820 | } elseif ($parsed['protocol'] == 'unix') { |
821 | $parsed['socket'] = $proto_opts; |
821 | $parsed['socket'] = $proto_opts; |
822 | }
|
822 | }
|
823 | 823 | ||
824 | // Get dabase if any
|
824 | // Get dabase if any
|
825 | // $dsn => database
|
825 | // $dsn => database
|
826 | if ($dsn) { |
826 | if ($dsn) { |
827 | if (($pos = strpos($dsn, '?')) === false) { |
827 | if (($pos = strpos($dsn, '?')) === false) { |
828 | // /database
|
828 | // /database
|
829 | $parsed['database'] = rawurldecode($dsn); |
829 | $parsed['database'] = rawurldecode($dsn); |
830 | } else { |
830 | } else { |
831 | // /database?param1=value1¶m2=value2
|
831 | // /database?param1=value1¶m2=value2
|
832 | $parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); |
832 | $parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); |
833 | $dsn = substr($dsn, $pos + 1); |
833 | $dsn = substr($dsn, $pos + 1); |
834 | if (strpos($dsn, '&') !== false) { |
834 | if (strpos($dsn, '&') !== false) { |
835 | $opts = explode('&', $dsn); |
835 | $opts = explode('&', $dsn); |
836 | } else { // database?param1=value1 |
836 | } else { // database?param1=value1 |
837 | $opts = array($dsn); |
837 | $opts = array($dsn); |
838 | }
|
838 | }
|
839 | foreach ($opts as $opt) { |
839 | foreach ($opts as $opt) { |
840 | list($key, $value) = explode('=', $opt); |
840 | list($key, $value) = explode('=', $opt); |
841 | if (!isset($parsed[$key])) { |
841 | if (!isset($parsed[$key])) { |
842 | // don't allow params overwrite
|
842 | // don't allow params overwrite
|
843 | $parsed[$key] = rawurldecode($value); |
843 | $parsed[$key] = rawurldecode($value); |
844 | }
|
844 | }
|
845 | }
|
845 | }
|
846 | }
|
846 | }
|
847 | }
|
847 | }
|
848 | 848 | ||
849 | return $parsed; |
849 | return $parsed; |
850 | }
|
850 | }
|
851 | 851 | ||
852 | // }}}
|
852 | // }}}
|
853 | // {{{ getDSNString()
|
853 | // {{{ getDSNString()
|
854 | 854 | ||
855 | /**
|
855 | /**
|
856 | * Returns the given DSN in a string format suitable for output.
|
856 | * Returns the given DSN in a string format suitable for output.
|
857 | *
|
857 | *
|
858 | * @param array|string the DSN to parse and format
|
858 | * @param array|string the DSN to parse and format
|
859 | * @param boolean true to hide the password, false to include it
|
859 | * @param boolean true to hide the password, false to include it
|
860 | * @return string
|
860 | * @return string
|
861 | */
|
861 | */
|
862 | function getDSNString($dsn, $hidePassword) { |
862 | function getDSNString($dsn, $hidePassword) { |
863 | /* Calling parseDSN will ensure that we have all the array elements
|
863 | /* Calling parseDSN will ensure that we have all the array elements
|
864 | * defined, and means that we deal with strings and array in the same
|
864 | * defined, and means that we deal with strings and array in the same
|
865 | * manner. */
|
865 | * manner. */
|
866 | $dsnArray = DB::parseDSN($dsn); |
866 | $dsnArray = DB::parseDSN($dsn); |
867 | 867 | ||
868 | if ($hidePassword) { |
868 | if ($hidePassword) { |
869 | $dsnArray['password'] = 'PASSWORD'; |
869 | $dsnArray['password'] = 'PASSWORD'; |
870 | }
|
870 | }
|
871 | 871 | ||
872 | /* Protocol is special-cased, as using the default "tcp" along with an
|
872 | /* Protocol is special-cased, as using the default "tcp" along with an
|
873 | * Oracle TNS connection string fails. */
|
873 | * Oracle TNS connection string fails. */
|
874 | if (is_string($dsn) && strpos($dsn, 'tcp') === false && $dsnArray['protocol'] == 'tcp') { |
874 | if (is_string($dsn) && strpos($dsn, 'tcp') === false && $dsnArray['protocol'] == 'tcp') { |
875 | $dsnArray['protocol'] = false; |
875 | $dsnArray['protocol'] = false; |
876 | }
|
876 | }
|
877 | 877 | ||
878 | // Now we just have to construct the actual string. This is ugly.
|
878 | // Now we just have to construct the actual string. This is ugly.
|
879 | $dsnString = $dsnArray['phptype']; |
879 | $dsnString = $dsnArray['phptype']; |
880 | if ($dsnArray['dbsyntax']) { |
880 | if ($dsnArray['dbsyntax']) { |
881 | $dsnString .= '('.$dsnArray['dbsyntax'].')'; |
881 | $dsnString .= '('.$dsnArray['dbsyntax'].')'; |
882 | }
|
882 | }
|
883 | $dsnString .= '://' |
883 | $dsnString .= '://' |
884 | .$dsnArray['username'] |
884 | .$dsnArray['username'] |
885 | .':' |
885 | .':' |
886 | .$dsnArray['password'] |
886 | .$dsnArray['password'] |
887 | .'@' |
887 | .'@' |
888 | .$dsnArray['protocol']; |
888 | .$dsnArray['protocol']; |
889 | if ($dsnArray['socket']) { |
889 | if ($dsnArray['socket']) { |
890 | $dsnString .= '('.$dsnArray['socket'].')'; |
890 | $dsnString .= '('.$dsnArray['socket'].')'; |
891 | }
|
891 | }
|
892 | if ($dsnArray['protocol'] && $dsnArray['hostspec']) { |
892 | if ($dsnArray['protocol'] && $dsnArray['hostspec']) { |
893 | $dsnString .= '+'; |
893 | $dsnString .= '+'; |
894 | }
|
894 | }
|
895 | $dsnString .= $dsnArray['hostspec']; |
895 | $dsnString .= $dsnArray['hostspec']; |
896 | if ($dsnArray['port']) { |
896 | if ($dsnArray['port']) { |
897 | $dsnString .= ':'.$dsnArray['port']; |
897 | $dsnString .= ':'.$dsnArray['port']; |
898 | }
|
898 | }
|
899 | $dsnString .= '/'.$dsnArray['database']; |
899 | $dsnString .= '/'.$dsnArray['database']; |
900 | 900 | ||
901 | /* Option handling. Unfortunately, parseDSN simply places options into
|
901 | /* Option handling. Unfortunately, parseDSN simply places options into
|
902 | * the top-level array, so we'll first get rid of the fields defined by
|
902 | * the top-level array, so we'll first get rid of the fields defined by
|
903 | * DB and see what's left. */
|
903 | * DB and see what's left. */
|
904 | unset($dsnArray['phptype'], |
904 | unset($dsnArray['phptype'], |
905 | $dsnArray['dbsyntax'], |
905 | $dsnArray['dbsyntax'], |
906 | $dsnArray['username'], |
906 | $dsnArray['username'], |
907 | $dsnArray['password'], |
907 | $dsnArray['password'], |
908 | $dsnArray['protocol'], |
908 | $dsnArray['protocol'], |
909 | $dsnArray['socket'], |
909 | $dsnArray['socket'], |
910 | $dsnArray['hostspec'], |
910 | $dsnArray['hostspec'], |
911 | $dsnArray['port'], |
911 | $dsnArray['port'], |
912 | $dsnArray['database'] |
912 | $dsnArray['database'] |
913 | ); |
913 | ); |
914 | if (count($dsnArray) > 0) { |
914 | if (count($dsnArray) > 0) { |
915 | $dsnString .= '?'; |
915 | $dsnString .= '?'; |
916 | $i = 0; |
916 | $i = 0; |
917 | foreach ($dsnArray as $key => $value) { |
917 | foreach ($dsnArray as $key => $value) { |
918 | if (++$i > 1) { |
918 | if (++$i > 1) { |
919 | $dsnString .= '&'; |
919 | $dsnString .= '&'; |
920 | }
|
920 | }
|
921 | $dsnString .= $key.'='.$value; |
921 | $dsnString .= $key.'='.$value; |
922 | }
|
922 | }
|
923 | }
|
923 | }
|
924 | 924 | ||
925 | return $dsnString; |
925 | return $dsnString; |
926 | }
|
926 | }
|
927 | 927 | ||
928 | // }}}
|
928 | // }}}
|
929 | }
|
929 | }
|
930 | 930 | ||
931 | // }}}
|
931 | // }}}
|
932 | // {{{ class DB_Error
|
932 | // {{{ class DB_Error
|
933 | 933 | ||
934 | /**
|
934 | /**
|
935 | * DB_Error implements a class for reporting portable database error
|
935 | * DB_Error implements a class for reporting portable database error
|
936 | * messages
|
936 | * messages
|
937 | *
|
937 | *
|
938 | * @category Database
|
938 | * @category Database
|
939 | * @package DB
|
939 | * @package DB
|
940 | * @author Stig Bakken <ssb@php.net>
|
940 | * @author Stig Bakken <ssb@php.net>
|
941 | * @copyright 1997-2007 The PHP Group
|
941 | * @copyright 1997-2007 The PHP Group
|
942 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
942 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
943 | * @version Release: 1.7.13
|
943 | * @version Release: 1.7.13
|
944 | * @link http://pear.php.net/package/DB
|
944 | * @link http://pear.php.net/package/DB
|
945 | */
|
945 | */
|
946 | class DB_Error extends PEAR_Error |
946 | class DB_Error extends PEAR_Error |
947 | {
|
947 | {
|
948 | // {{{ constructor
|
948 | // {{{ constructor
|
949 | 949 | ||
950 | /**
|
950 | /**
|
951 | * DB_Error constructor
|
951 | * DB_Error constructor
|
952 | *
|
952 | *
|
953 | * @param mixed $code DB error code, or string with error message
|
953 | * @param mixed $code DB error code, or string with error message
|
954 | * @param int $mode what "error mode" to operate in
|
954 | * @param int $mode what "error mode" to operate in
|
955 | * @param int $level what error level to use for $mode &
|
955 | * @param int $level what error level to use for $mode &
|
956 | * PEAR_ERROR_TRIGGER
|
956 | * PEAR_ERROR_TRIGGER
|
957 | * @param mixed $debuginfo additional debug info, such as the last query
|
957 | * @param mixed $debuginfo additional debug info, such as the last query
|
958 | *
|
958 | *
|
959 | * @see PEAR_Error
|
959 | * @see PEAR_Error
|
960 | */
|
960 | */
|
961 | function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, |
961 | function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, |
962 | $level = E_USER_NOTICE, $debuginfo = null) |
962 | $level = E_USER_NOTICE, $debuginfo = null) |
963 | {
|
963 | {
|
964 | if (is_int($code)) { |
964 | if (is_int($code)) { |
965 | $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, |
965 | $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, |
966 | $mode, $level, $debuginfo); |
966 | $mode, $level, $debuginfo); |
967 | } else { |
967 | } else { |
968 | $this->PEAR_Error("DB Error: $code", DB_ERROR, |
968 | $this->PEAR_Error("DB Error: $code", DB_ERROR, |
969 | $mode, $level, $debuginfo); |
969 | $mode, $level, $debuginfo); |
970 | }
|
970 | }
|
971 | }
|
971 | }
|
972 | 972 | ||
973 | // }}}
|
973 | // }}}
|
974 | }
|
974 | }
|
975 | 975 | ||
976 | // }}}
|
976 | // }}}
|
977 | // {{{ class DB_result
|
977 | // {{{ class DB_result
|
978 | 978 | ||
979 | /**
|
979 | /**
|
980 | * This class implements a wrapper for a DB result set
|
980 | * This class implements a wrapper for a DB result set
|
981 | *
|
981 | *
|
982 | * A new instance of this class will be returned by the DB implementation
|
982 | * A new instance of this class will be returned by the DB implementation
|
983 | * after processing a query that returns data.
|
983 | * after processing a query that returns data.
|
984 | *
|
984 | *
|
985 | * @category Database
|
985 | * @category Database
|
986 | * @package DB
|
986 | * @package DB
|
987 | * @author Stig Bakken <ssb@php.net>
|
987 | * @author Stig Bakken <ssb@php.net>
|
988 | * @copyright 1997-2007 The PHP Group
|
988 | * @copyright 1997-2007 The PHP Group
|
989 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
989 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
990 | * @version Release: 1.7.13
|
990 | * @version Release: 1.7.13
|
991 | * @link http://pear.php.net/package/DB
|
991 | * @link http://pear.php.net/package/DB
|
992 | */
|
992 | */
|
993 | class DB_result
|
993 | class DB_result
|
994 | {
|
994 | {
|
995 | // {{{ properties
|
995 | // {{{ properties
|
996 | 996 | ||
997 | /**
|
997 | /**
|
998 | * Should results be freed automatically when there are no more rows?
|
998 | * Should results be freed automatically when there are no more rows?
|
999 | * @var boolean
|
999 | * @var boolean
|
1000 | * @see DB_common::$options
|
1000 | * @see DB_common::$options
|
1001 | */
|
1001 | */
|
1002 | var $autofree; |
1002 | var $autofree; |
1003 | 1003 | ||
1004 | /**
|
1004 | /**
|
1005 | * A reference to the DB_<driver> object
|
1005 | * A reference to the DB_<driver> object
|
1006 | * @var object
|
1006 | * @var object
|
1007 | */
|
1007 | */
|
1008 | var $dbh; |
1008 | var $dbh; |
1009 | 1009 | ||
1010 | /**
|
1010 | /**
|
1011 | * The current default fetch mode
|
1011 | * The current default fetch mode
|
1012 | * @var integer
|
1012 | * @var integer
|
1013 | * @see DB_common::$fetchmode
|
1013 | * @see DB_common::$fetchmode
|
1014 | */
|
1014 | */
|
1015 | var $fetchmode; |
1015 | var $fetchmode; |
1016 | 1016 | ||
1017 | /**
|
1017 | /**
|
1018 | * The name of the class into which results should be fetched when
|
1018 | * The name of the class into which results should be fetched when
|
1019 | * DB_FETCHMODE_OBJECT is in effect
|
1019 | * DB_FETCHMODE_OBJECT is in effect
|
1020 | *
|
1020 | *
|
1021 | * @var string
|
1021 | * @var string
|
1022 | * @see DB_common::$fetchmode_object_class
|
1022 | * @see DB_common::$fetchmode_object_class
|
1023 | */
|
1023 | */
|
1024 | var $fetchmode_object_class; |
1024 | var $fetchmode_object_class; |
1025 | 1025 | ||
1026 | /**
|
1026 | /**
|
1027 | * The number of rows to fetch from a limit query
|
1027 | * The number of rows to fetch from a limit query
|
1028 | * @var integer
|
1028 | * @var integer
|
1029 | */
|
1029 | */
|
1030 | var $limit_count = null; |
1030 | var $limit_count = null; |
1031 | 1031 | ||
1032 | /**
|
1032 | /**
|
1033 | * The row to start fetching from in limit queries
|
1033 | * The row to start fetching from in limit queries
|
1034 | * @var integer
|
1034 | * @var integer
|
1035 | */
|
1035 | */
|
1036 | var $limit_from = null; |
1036 | var $limit_from = null; |
1037 | 1037 | ||
1038 | /**
|
1038 | /**
|
1039 | * The execute parameters that created this result
|
1039 | * The execute parameters that created this result
|
1040 | * @var array
|
1040 | * @var array
|
1041 | * @since Property available since Release 1.7.0
|
1041 | * @since Property available since Release 1.7.0
|
1042 | */
|
1042 | */
|
1043 | var $parameters; |
1043 | var $parameters; |
1044 | 1044 | ||
1045 | /**
|
1045 | /**
|
1046 | * The query string that created this result
|
1046 | * The query string that created this result
|
1047 | *
|
1047 | *
|
1048 | * Copied here incase it changes in $dbh, which is referenced
|
1048 | * Copied here incase it changes in $dbh, which is referenced
|
1049 | *
|
1049 | *
|
1050 | * @var string
|
1050 | * @var string
|
1051 | * @since Property available since Release 1.7.0
|
1051 | * @since Property available since Release 1.7.0
|
1052 | */
|
1052 | */
|
1053 | var $query; |
1053 | var $query; |
1054 | 1054 | ||
1055 | /**
|
1055 | /**
|
1056 | * The query result resource id created by PHP
|
1056 | * The query result resource id created by PHP
|
1057 | * @var resource
|
1057 | * @var resource
|
1058 | */
|
1058 | */
|
1059 | var $result; |
1059 | var $result; |
1060 | 1060 | ||
1061 | /**
|
1061 | /**
|
1062 | * The present row being dealt with
|
1062 | * The present row being dealt with
|
1063 | * @var integer
|
1063 | * @var integer
|
1064 | */
|
1064 | */
|
1065 | var $row_counter = null; |
1065 | var $row_counter = null; |
1066 | 1066 | ||
1067 | /**
|
1067 | /**
|
1068 | * The prepared statement resource id created by PHP in $dbh
|
1068 | * The prepared statement resource id created by PHP in $dbh
|
1069 | *
|
1069 | *
|
1070 | * This resource is only available when the result set was created using
|
1070 | * This resource is only available when the result set was created using
|
1071 | * a driver's native execute() method, not PEAR DB's emulated one.
|
1071 | * a driver's native execute() method, not PEAR DB's emulated one.
|
1072 | *
|
1072 | *
|
1073 | * Copied here incase it changes in $dbh, which is referenced
|
1073 | * Copied here incase it changes in $dbh, which is referenced
|
1074 | *
|
1074 | *
|
1075 | * {@internal Mainly here because the InterBase/Firebird API is only
|
1075 | * {@internal Mainly here because the InterBase/Firebird API is only
|
1076 | * able to retrieve data from result sets if the statemnt handle is
|
1076 | * able to retrieve data from result sets if the statemnt handle is
|
1077 | * still in scope.}}
|
1077 | * still in scope.}}
|
1078 | *
|
1078 | *
|
1079 | * @var resource
|
1079 | * @var resource
|
1080 | * @since Property available since Release 1.7.0
|
1080 | * @since Property available since Release 1.7.0
|
1081 | */
|
1081 | */
|
1082 | var $statement; |
1082 | var $statement; |
1083 | 1083 | ||
1084 | 1084 | ||
1085 | // }}}
|
1085 | // }}}
|
1086 | // {{{ constructor
|
1086 | // {{{ constructor
|
1087 | 1087 | ||
1088 | /**
|
1088 | /**
|
1089 | * This constructor sets the object's properties
|
1089 | * This constructor sets the object's properties
|
1090 | *
|
1090 | *
|
1091 | * @param object &$dbh the DB object reference
|
1091 | * @param object &$dbh the DB object reference
|
1092 | * @param resource $result the result resource id
|
1092 | * @param resource $result the result resource id
|
1093 | * @param array $options an associative array with result options
|
1093 | * @param array $options an associative array with result options
|
1094 | *
|
1094 | *
|
1095 | * @return void
|
1095 | * @return void
|
1096 | */
|
1096 | */
|
1097 | function DB_result(&$dbh, $result, $options = array()) |
1097 | function DB_result(&$dbh, $result, $options = array()) |
1098 | {
|
1098 | {
|
1099 | $this->autofree = $dbh->options['autofree']; |
1099 | $this->autofree = $dbh->options['autofree']; |
1100 | $this->dbh = &$dbh; |
1100 | $this->dbh = &$dbh; |
1101 | $this->fetchmode = $dbh->fetchmode; |
1101 | $this->fetchmode = $dbh->fetchmode; |
1102 | $this->fetchmode_object_class = $dbh->fetchmode_object_class; |
1102 | $this->fetchmode_object_class = $dbh->fetchmode_object_class; |
1103 | $this->parameters = $dbh->last_parameters; |
1103 | $this->parameters = $dbh->last_parameters; |
1104 | $this->query = $dbh->last_query; |
1104 | $this->query = $dbh->last_query; |
1105 | $this->result = $result; |
1105 | $this->result = $result; |
1106 | $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt; |
1106 | $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt; |
1107 | foreach ($options as $key => $value) { |
1107 | foreach ($options as $key => $value) { |
1108 | $this->setOption($key, $value); |
1108 | $this->setOption($key, $value); |
1109 | }
|
1109 | }
|
1110 | }
|
1110 | }
|
1111 | 1111 | ||
1112 | /**
|
1112 | /**
|
1113 | * Set options for the DB_result object
|
1113 | * Set options for the DB_result object
|
1114 | *
|
1114 | *
|
1115 | * @param string $key the option to set
|
1115 | * @param string $key the option to set
|
1116 | * @param mixed $value the value to set the option to
|
1116 | * @param mixed $value the value to set the option to
|
1117 | *
|
1117 | *
|
1118 | * @return void
|
1118 | * @return void
|
1119 | */
|
1119 | */
|
1120 | function setOption($key, $value = null) |
1120 | function setOption($key, $value = null) |
1121 | {
|
1121 | {
|
1122 | switch ($key) { |
1122 | switch ($key) { |
1123 | case 'limit_from': |
1123 | case 'limit_from': |
1124 | $this->limit_from = $value; |
1124 | $this->limit_from = $value; |
1125 | break; |
1125 | break; |
1126 | case 'limit_count': |
1126 | case 'limit_count': |
1127 | $this->limit_count = $value; |
1127 | $this->limit_count = $value; |
1128 | }
|
1128 | }
|
1129 | }
|
1129 | }
|
1130 | 1130 | ||
1131 | // }}}
|
1131 | // }}}
|
1132 | // {{{ fetchRow()
|
1132 | // {{{ fetchRow()
|
1133 | 1133 | ||
1134 | /**
|
1134 | /**
|
1135 | * Fetch a row of data and return it by reference into an array
|
1135 | * Fetch a row of data and return it by reference into an array
|
1136 | *
|
1136 | *
|
1137 | * The type of array returned can be controlled either by setting this
|
1137 | * The type of array returned can be controlled either by setting this
|
1138 | * method's <var>$fetchmode</var> parameter or by changing the default
|
1138 | * method's <var>$fetchmode</var> parameter or by changing the default
|
1139 | * fetch mode setFetchMode() before calling this method.
|
1139 | * fetch mode setFetchMode() before calling this method.
|
1140 | *
|
1140 | *
|
1141 | * There are two options for standardizing the information returned
|
1141 | * There are two options for standardizing the information returned
|
1142 | * from databases, ensuring their values are consistent when changing
|
1142 | * from databases, ensuring their values are consistent when changing
|
1143 | * DBMS's. These portability options can be turned on when creating a
|
1143 | * DBMS's. These portability options can be turned on when creating a
|
1144 | * new DB object or by using setOption().
|
1144 | * new DB object or by using setOption().
|
1145 | *
|
1145 | *
|
1146 | * + <var>DB_PORTABILITY_LOWERCASE</var>
|
1146 | * + <var>DB_PORTABILITY_LOWERCASE</var>
|
1147 | * convert names of fields to lower case
|
1147 | * convert names of fields to lower case
|
1148 | *
|
1148 | *
|
1149 | * + <var>DB_PORTABILITY_RTRIM</var>
|
1149 | * + <var>DB_PORTABILITY_RTRIM</var>
|
1150 | * right trim the data
|
1150 | * right trim the data
|
1151 | *
|
1151 | *
|
1152 | * @param int $fetchmode the constant indicating how to format the data
|
1152 | * @param int $fetchmode the constant indicating how to format the data
|
1153 | * @param int $rownum the row number to fetch (index starts at 0)
|
1153 | * @param int $rownum the row number to fetch (index starts at 0)
|
1154 | *
|
1154 | *
|
1155 | * @return mixed an array or object containing the row's data,
|
1155 | * @return mixed an array or object containing the row's data,
|
1156 | * NULL when the end of the result set is reached
|
1156 | * NULL when the end of the result set is reached
|
1157 | * or a DB_Error object on failure.
|
1157 | * or a DB_Error object on failure.
|
1158 | *
|
1158 | *
|
1159 | * @see DB_common::setOption(), DB_common::setFetchMode()
|
1159 | * @see DB_common::setOption(), DB_common::setFetchMode()
|
1160 | */
|
1160 | */
|
1161 | function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) |
1161 | function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) |
1162 | {
|
1162 | {
|
1163 | if ($fetchmode === DB_FETCHMODE_DEFAULT) { |
1163 | if ($fetchmode === DB_FETCHMODE_DEFAULT) { |
1164 | $fetchmode = $this->fetchmode; |
1164 | $fetchmode = $this->fetchmode; |
1165 | }
|
1165 | }
|
1166 | if ($fetchmode === DB_FETCHMODE_OBJECT) { |
1166 | if ($fetchmode === DB_FETCHMODE_OBJECT) { |
1167 | $fetchmode = DB_FETCHMODE_ASSOC; |
1167 | $fetchmode = DB_FETCHMODE_ASSOC; |
1168 | $object_class = $this->fetchmode_object_class; |
1168 | $object_class = $this->fetchmode_object_class; |
1169 | }
|
1169 | }
|
1170 | if (is_null($rownum) && $this->limit_from !== null) { |
1170 | if (is_null($rownum) && $this->limit_from !== null) { |
1171 | if ($this->row_counter === null) { |
1171 | if ($this->row_counter === null) { |
1172 | $this->row_counter = $this->limit_from; |
1172 | $this->row_counter = $this->limit_from; |
1173 | // Skip rows
|
1173 | // Skip rows
|
1174 | if ($this->dbh->features['limit'] === false) { |
1174 | if ($this->dbh->features['limit'] === false) { |
1175 | $i = 0; |
1175 | $i = 0; |
1176 | while ($i++ < $this->limit_from) { |
1176 | while ($i++ < $this->limit_from) { |
1177 | $this->dbh->fetchInto($this->result, $arr, $fetchmode); |
1177 | $this->dbh->fetchInto($this->result, $arr, $fetchmode); |
1178 | }
|
1178 | }
|
1179 | }
|
1179 | }
|
1180 | }
|
1180 | }
|
1181 | if ($this->row_counter >= ($this->limit_from + $this->limit_count)) |
1181 | if ($this->row_counter >= ($this->limit_from + $this->limit_count)) |
1182 | {
|
1182 | {
|
1183 | if ($this->autofree) { |
1183 | if ($this->autofree) { |
1184 | $this->free(); |
1184 | $this->free(); |
1185 | }
|
1185 | }
|
1186 | $tmp = null; |
1186 | $tmp = null; |
1187 | return $tmp; |
1187 | return $tmp; |
1188 | }
|
1188 | }
|
1189 | if ($this->dbh->features['limit'] === 'emulate') { |
1189 | if ($this->dbh->features['limit'] === 'emulate') { |
1190 | $rownum = $this->row_counter; |
1190 | $rownum = $this->row_counter; |
1191 | }
|
1191 | }
|
1192 | $this->row_counter++; |
1192 | $this->row_counter++; |
1193 | }
|
1193 | }
|
1194 | $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); |
1194 | $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); |
1195 | if ($res === DB_OK) { |
1195 | if ($res === DB_OK) { |
1196 | if (isset($object_class)) { |
1196 | if (isset($object_class)) { |
1197 | // The default mode is specified in the
|
1197 | // The default mode is specified in the
|
1198 | // DB_common::fetchmode_object_class property
|
1198 | // DB_common::fetchmode_object_class property
|
1199 | if ($object_class == 'stdClass') { |
1199 | if ($object_class == 'stdClass') { |
1200 | $arr = (object) $arr; |
1200 | $arr = (object) $arr; |
1201 | } else { |
1201 | } else { |
1202 | $arr = new $object_class($arr); |
1202 | $arr = new $object_class($arr); |
1203 | }
|
1203 | }
|
1204 | }
|
1204 | }
|
1205 | return $arr; |
1205 | return $arr; |
1206 | }
|
1206 | }
|
1207 | if ($res == null && $this->autofree) { |
1207 | if ($res == null && $this->autofree) { |
1208 | $this->free(); |
1208 | $this->free(); |
1209 | }
|
1209 | }
|
1210 | return $res; |
1210 | return $res; |
1211 | }
|
1211 | }
|
1212 | 1212 | ||
1213 | // }}}
|
1213 | // }}}
|
1214 | // {{{ fetchInto()
|
1214 | // {{{ fetchInto()
|
1215 | 1215 | ||
1216 | /**
|
1216 | /**
|
1217 | * Fetch a row of data into an array which is passed by reference
|
1217 | * Fetch a row of data into an array which is passed by reference
|
1218 | *
|
1218 | *
|
1219 | * The type of array returned can be controlled either by setting this
|
1219 | * The type of array returned can be controlled either by setting this
|
1220 | * method's <var>$fetchmode</var> parameter or by changing the default
|
1220 | * method's <var>$fetchmode</var> parameter or by changing the default
|
1221 | * fetch mode setFetchMode() before calling this method.
|
1221 | * fetch mode setFetchMode() before calling this method.
|
1222 | *
|
1222 | *
|
1223 | * There are two options for standardizing the information returned
|
1223 | * There are two options for standardizing the information returned
|
1224 | * from databases, ensuring their values are consistent when changing
|
1224 | * from databases, ensuring their values are consistent when changing
|
1225 | * DBMS's. These portability options can be turned on when creating a
|
1225 | * DBMS's. These portability options can be turned on when creating a
|
1226 | * new DB object or by using setOption().
|
1226 | * new DB object or by using setOption().
|
1227 | *
|
1227 | *
|
1228 | * + <var>DB_PORTABILITY_LOWERCASE</var>
|
1228 | * + <var>DB_PORTABILITY_LOWERCASE</var>
|
1229 | * convert names of fields to lower case
|
1229 | * convert names of fields to lower case
|
1230 | *
|
1230 | *
|
1231 | * + <var>DB_PORTABILITY_RTRIM</var>
|
1231 | * + <var>DB_PORTABILITY_RTRIM</var>
|
1232 | * right trim the data
|
1232 | * right trim the data
|
1233 | *
|
1233 | *
|
1234 | * @param array &$arr the variable where the data should be placed
|
1234 | * @param array &$arr the variable where the data should be placed
|
1235 | * @param int $fetchmode the constant indicating how to format the data
|
1235 | * @param int $fetchmode the constant indicating how to format the data
|
1236 | * @param int $rownum the row number to fetch (index starts at 0)
|
1236 | * @param int $rownum the row number to fetch (index starts at 0)
|
1237 | *
|
1237 | *
|
1238 | * @return mixed DB_OK if a row is processed, NULL when the end of the
|
1238 | * @return mixed DB_OK if a row is processed, NULL when the end of the
|
1239 | * result set is reached or a DB_Error object on failure
|
1239 | * result set is reached or a DB_Error object on failure
|
1240 | *
|
1240 | *
|
1241 | * @see DB_common::setOption(), DB_common::setFetchMode()
|
1241 | * @see DB_common::setOption(), DB_common::setFetchMode()
|
1242 | */
|
1242 | */
|
1243 | function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) |
1243 | function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) |
1244 | {
|
1244 | {
|
1245 | if ($fetchmode === DB_FETCHMODE_DEFAULT) { |
1245 | if ($fetchmode === DB_FETCHMODE_DEFAULT) { |
1246 | $fetchmode = $this->fetchmode; |
1246 | $fetchmode = $this->fetchmode; |
1247 | }
|
1247 | }
|
1248 | if ($fetchmode === DB_FETCHMODE_OBJECT) { |
1248 | if ($fetchmode === DB_FETCHMODE_OBJECT) { |
1249 | $fetchmode = DB_FETCHMODE_ASSOC; |
1249 | $fetchmode = DB_FETCHMODE_ASSOC; |
1250 | $object_class = $this->fetchmode_object_class; |
1250 | $object_class = $this->fetchmode_object_class; |
1251 | }
|
1251 | }
|
1252 | if (is_null($rownum) && $this->limit_from !== null) { |
1252 | if (is_null($rownum) && $this->limit_from !== null) { |
1253 | if ($this->row_counter === null) { |
1253 | if ($this->row_counter === null) { |
1254 | $this->row_counter = $this->limit_from; |
1254 | $this->row_counter = $this->limit_from; |
1255 | // Skip rows
|
1255 | // Skip rows
|
1256 | if ($this->dbh->features['limit'] === false) { |
1256 | if ($this->dbh->features['limit'] === false) { |
1257 | $i = 0; |
1257 | $i = 0; |
1258 | while ($i++ < $this->limit_from) { |
1258 | while ($i++ < $this->limit_from) { |
1259 | $this->dbh->fetchInto($this->result, $arr, $fetchmode); |
1259 | $this->dbh->fetchInto($this->result, $arr, $fetchmode); |
1260 | }
|
1260 | }
|
1261 | }
|
1261 | }
|
1262 | }
|
1262 | }
|
1263 | if ($this->row_counter >= ( |
1263 | if ($this->row_counter >= ( |
1264 | $this->limit_from + $this->limit_count)) |
1264 | $this->limit_from + $this->limit_count)) |
1265 | {
|
1265 | {
|
1266 | if ($this->autofree) { |
1266 | if ($this->autofree) { |
1267 | $this->free(); |
1267 | $this->free(); |
1268 | }
|
1268 | }
|
1269 | return null; |
1269 | return null; |
1270 | }
|
1270 | }
|
1271 | if ($this->dbh->features['limit'] === 'emulate') { |
1271 | if ($this->dbh->features['limit'] === 'emulate') { |
1272 | $rownum = $this->row_counter; |
1272 | $rownum = $this->row_counter; |
1273 | }
|
1273 | }
|
1274 | 1274 | ||
1275 | $this->row_counter++; |
1275 | $this->row_counter++; |
1276 | }
|
1276 | }
|
1277 | $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); |
1277 | $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); |
1278 | if ($res === DB_OK) { |
1278 | if ($res === DB_OK) { |
1279 | if (isset($object_class)) { |
1279 | if (isset($object_class)) { |
1280 | // default mode specified in the
|
1280 | // default mode specified in the
|
1281 | // DB_common::fetchmode_object_class property
|
1281 | // DB_common::fetchmode_object_class property
|
1282 | if ($object_class == 'stdClass') { |
1282 | if ($object_class == 'stdClass') { |
1283 | $arr = (object) $arr; |
1283 | $arr = (object) $arr; |
1284 | } else { |
1284 | } else { |
1285 | $arr = new $object_class($arr); |
1285 | $arr = new $object_class($arr); |
1286 | }
|
1286 | }
|
1287 | }
|
1287 | }
|
1288 | return DB_OK; |
1288 | return DB_OK; |
1289 | }
|
1289 | }
|
1290 | if ($res == null && $this->autofree) { |
1290 | if ($res == null && $this->autofree) { |
1291 | $this->free(); |
1291 | $this->free(); |
1292 | }
|
1292 | }
|
1293 | return $res; |
1293 | return $res; |
1294 | }
|
1294 | }
|
1295 | 1295 | ||
1296 | // }}}
|
1296 | // }}}
|
1297 | // {{{ numCols()
|
1297 | // {{{ numCols()
|
1298 | 1298 | ||
1299 | /**
|
1299 | /**
|
1300 | * Get the the number of columns in a result set
|
1300 | * Get the the number of columns in a result set
|
1301 | *
|
1301 | *
|
1302 | * @return int the number of columns. A DB_Error object on failure.
|
1302 | * @return int the number of columns. A DB_Error object on failure.
|
1303 | */
|
1303 | */
|
1304 | function numCols() |
1304 | function numCols() |
1305 | {
|
1305 | {
|
1306 | return $this->dbh->numCols($this->result); |
1306 | return $this->dbh->numCols($this->result); |
1307 | }
|
1307 | }
|
1308 | 1308 | ||
1309 | // }}}
|
1309 | // }}}
|
1310 | // {{{ numRows()
|
1310 | // {{{ numRows()
|
1311 | 1311 | ||
1312 | /**
|
1312 | /**
|
1313 | * Get the number of rows in a result set
|
1313 | * Get the number of rows in a result set
|
1314 | *
|
1314 | *
|
1315 | * @return int the number of rows. A DB_Error object on failure.
|
1315 | * @return int the number of rows. A DB_Error object on failure.
|
1316 | */
|
1316 | */
|
1317 | function numRows() |
1317 | function numRows() |
1318 | {
|
1318 | {
|
1319 | if ($this->dbh->features['numrows'] === 'emulate' |
1319 | if ($this->dbh->features['numrows'] === 'emulate' |
1320 | && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) |
1320 | && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) |
1321 | {
|
1321 | {
|
1322 | if ($this->dbh->features['prepare']) { |
1322 | if ($this->dbh->features['prepare']) { |
1323 | $res = $this->dbh->query($this->query, $this->parameters); |
1323 | $res = $this->dbh->query($this->query, $this->parameters); |
1324 | } else { |
1324 | } else { |
1325 | $res = $this->dbh->query($this->query); |
1325 | $res = $this->dbh->query($this->query); |
1326 | }
|
1326 | }
|
1327 | if (DB::isError($res)) { |
1327 | if (DB::isError($res)) { |
1328 | return $res; |
1328 | return $res; |
1329 | }
|
1329 | }
|
1330 | $i = 0; |
1330 | $i = 0; |
1331 | while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { |
1331 | while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { |
1332 | $i++; |
1332 | $i++; |
1333 | }
|
1333 | }
|
1334 | $count = $i; |
1334 | $count = $i; |
1335 | } else { |
1335 | } else { |
1336 | $count = $this->dbh->numRows($this->result); |
1336 | $count = $this->dbh->numRows($this->result); |
1337 | }
|
1337 | }
|
1338 | 1338 | ||
1339 | /* fbsql is checked for here because limit queries are implemented
|
1339 | /* fbsql is checked for here because limit queries are implemented
|
1340 | * using a TOP() function, which results in fbsql_num_rows still
|
1340 | * using a TOP() function, which results in fbsql_num_rows still
|
1341 | * returning the total number of rows that would have been returned,
|
1341 | * returning the total number of rows that would have been returned,
|
1342 | * rather than the real number. As a result, we'll just do the limit
|
1342 | * rather than the real number. As a result, we'll just do the limit
|
1343 | * calculations for fbsql in the same way as a database with emulated
|
1343 | * calculations for fbsql in the same way as a database with emulated
|
1344 | * limits. Unfortunately, we can't just do this in DB_fbsql::numRows()
|
1344 | * limits. Unfortunately, we can't just do this in DB_fbsql::numRows()
|
1345 | * because that only gets the result resource, rather than the full
|
1345 | * because that only gets the result resource, rather than the full
|
1346 | * DB_Result object. */
|
1346 | * DB_Result object. */
|
1347 | if (($this->dbh->features['limit'] === 'emulate' |
1347 | if (($this->dbh->features['limit'] === 'emulate' |
1348 | && $this->limit_from !== null) |
1348 | && $this->limit_from !== null) |
1349 | || $this->dbh->phptype == 'fbsql') { |
1349 | || $this->dbh->phptype == 'fbsql') { |
1350 | $limit_count = is_null($this->limit_count) ? $count : $this->limit_count; |
1350 | $limit_count = is_null($this->limit_count) ? $count : $this->limit_count; |
1351 | if ($count < $this->limit_from) { |
1351 | if ($count < $this->limit_from) { |
1352 | $count = 0; |
1352 | $count = 0; |
1353 | } elseif ($count < ($this->limit_from + $limit_count)) { |
1353 | } elseif ($count < ($this->limit_from + $limit_count)) { |
1354 | $count -= $this->limit_from; |
1354 | $count -= $this->limit_from; |
1355 | } else { |
1355 | } else { |
1356 | $count = $limit_count; |
1356 | $count = $limit_count; |
1357 | }
|
1357 | }
|
1358 | }
|
1358 | }
|
1359 | 1359 | ||
1360 | return $count; |
1360 | return $count; |
1361 | }
|
1361 | }
|
1362 | 1362 | ||
1363 | // }}}
|
1363 | // }}}
|
1364 | // {{{ nextResult()
|
1364 | // {{{ nextResult()
|
1365 | 1365 | ||
1366 | /**
|
1366 | /**
|
1367 | * Get the next result if a batch of queries was executed
|
1367 | * Get the next result if a batch of queries was executed
|
1368 | *
|
1368 | *
|
1369 | * @return bool true if a new result is available or false if not
|
1369 | * @return bool true if a new result is available or false if not
|
1370 | */
|
1370 | */
|
1371 | function nextResult() |
1371 | function nextResult() |
1372 | {
|
1372 | {
|
1373 | return $this->dbh->nextResult($this->result); |
1373 | return $this->dbh->nextResult($this->result); |
1374 | }
|
1374 | }
|
1375 | 1375 | ||
1376 | // }}}
|
1376 | // }}}
|
1377 | // {{{ free()
|
1377 | // {{{ free()
|
1378 | 1378 | ||
1379 | /**
|
1379 | /**
|
1380 | * Frees the resources allocated for this result set
|
1380 | * Frees the resources allocated for this result set
|
1381 | *
|
1381 | *
|
1382 | * @return bool true on success. A DB_Error object on failure.
|
1382 | * @return bool true on success. A DB_Error object on failure.
|
1383 | */
|
1383 | */
|
1384 | function free() |
1384 | function free() |
1385 | {
|
1385 | {
|
1386 | $err = $this->dbh->freeResult($this->result); |
1386 | $err = $this->dbh->freeResult($this->result); |
1387 | if (DB::isError($err)) { |
1387 | if (DB::isError($err)) { |
1388 | return $err; |
1388 | return $err; |
1389 | }
|
1389 | }
|
1390 | $this->result = false; |
1390 | $this->result = false; |
1391 | $this->statement = false; |
1391 | $this->statement = false; |
1392 | return true; |
1392 | return true; |
1393 | }
|
1393 | }
|
1394 | 1394 | ||
1395 | // }}}
|
1395 | // }}}
|
1396 | // {{{ tableInfo()
|
1396 | // {{{ tableInfo()
|
1397 | 1397 | ||
1398 | /**
|
1398 | /**
|
1399 | * @see DB_common::tableInfo()
|
1399 | * @see DB_common::tableInfo()
|
1400 | * @deprecated Method deprecated some time before Release 1.2
|
1400 | * @deprecated Method deprecated some time before Release 1.2
|
1401 | */
|
1401 | */
|
1402 | function tableInfo($mode = null) |
1402 | function tableInfo($mode = null) |
1403 | {
|
1403 | {
|
1404 | if (is_string($mode)) { |
1404 | if (is_string($mode)) { |
1405 | return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA); |
1405 | return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA); |
1406 | }
|
1406 | }
|
1407 | return $this->dbh->tableInfo($this, $mode); |
1407 | return $this->dbh->tableInfo($this, $mode); |
1408 | }
|
1408 | }
|
1409 | 1409 | ||
1410 | // }}}
|
1410 | // }}}
|
1411 | // {{{ getQuery()
|
1411 | // {{{ getQuery()
|
1412 | 1412 | ||
1413 | /**
|
1413 | /**
|
1414 | * Determine the query string that created this result
|
1414 | * Determine the query string that created this result
|
1415 | *
|
1415 | *
|
1416 | * @return string the query string
|
1416 | * @return string the query string
|
1417 | *
|
1417 | *
|
1418 | * @since Method available since Release 1.7.0
|
1418 | * @since Method available since Release 1.7.0
|
1419 | */
|
1419 | */
|
1420 | function getQuery() |
1420 | function getQuery() |
1421 | {
|
1421 | {
|
1422 | return $this->query; |
1422 | return $this->query; |
1423 | }
|
1423 | }
|
1424 | 1424 | ||
1425 | // }}}
|
1425 | // }}}
|
1426 | // {{{ getRowCounter()
|
1426 | // {{{ getRowCounter()
|
1427 | 1427 | ||
1428 | /**
|
1428 | /**
|
1429 | * Tells which row number is currently being processed
|
1429 | * Tells which row number is currently being processed
|
1430 | *
|
1430 | *
|
1431 | * @return integer the current row being looked at. Starts at 1.
|
1431 | * @return integer the current row being looked at. Starts at 1.
|
1432 | */
|
1432 | */
|
1433 | function getRowCounter() |
1433 | function getRowCounter() |
1434 | {
|
1434 | {
|
1435 | return $this->row_counter; |
1435 | return $this->row_counter; |
1436 | }
|
1436 | }
|
1437 | 1437 | ||
1438 | // }}}
|
1438 | // }}}
|
1439 | }
|
1439 | }
|
1440 | 1440 | ||
1441 | // }}}
|
1441 | // }}}
|
1442 | // {{{ class DB_row
|
1442 | // {{{ class DB_row
|
1443 | 1443 | ||
1444 | /**
|
1444 | /**
|
1445 | * PEAR DB Row Object
|
1445 | * PEAR DB Row Object
|
1446 | *
|
1446 | *
|
1447 | * The object contains a row of data from a result set. Each column's data
|
1447 | * The object contains a row of data from a result set. Each column's data
|
1448 | * is placed in a property named for the column.
|
1448 | * is placed in a property named for the column.
|
1449 | *
|
1449 | *
|
1450 | * @category Database
|
1450 | * @category Database
|
1451 | * @package DB
|
1451 | * @package DB
|
1452 | * @author Stig Bakken <ssb@php.net>
|
1452 | * @author Stig Bakken <ssb@php.net>
|
1453 | * @copyright 1997-2007 The PHP Group
|
1453 | * @copyright 1997-2007 The PHP Group
|
1454 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
1454 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
1455 | * @version Release: 1.7.13
|
1455 | * @version Release: 1.7.13
|
1456 | * @link http://pear.php.net/package/DB
|
1456 | * @link http://pear.php.net/package/DB
|
1457 | * @see DB_common::setFetchMode()
|
1457 | * @see DB_common::setFetchMode()
|
1458 | */
|
1458 | */
|
1459 | class DB_row
|
1459 | class DB_row
|
1460 | {
|
1460 | {
|
1461 | // {{{ constructor
|
1461 | // {{{ constructor
|
1462 | 1462 | ||
1463 | /**
|
1463 | /**
|
1464 | * The constructor places a row's data into properties of this object
|
1464 | * The constructor places a row's data into properties of this object
|
1465 | *
|
1465 | *
|
1466 | * @param array the array containing the row's data
|
1466 | * @param array the array containing the row's data
|
1467 | *
|
1467 | *
|
1468 | * @return void
|
1468 | * @return void
|
1469 | */
|
1469 | */
|
1470 | function DB_row(&$arr) |
1470 | function DB_row(&$arr) |
1471 | {
|
1471 | {
|
1472 | foreach ($arr as $key => $value) { |
1472 | foreach ($arr as $key => $value) { |
1473 | $this->$key = &$arr[$key]; |
1473 | $this->$key = &$arr[$key]; |
1474 | }
|
1474 | }
|
1475 | }
|
1475 | }
|
1476 | 1476 | ||
1477 | // }}}
|
1477 | // }}}
|
1478 | }
|
1478 | }
|
1479 | 1479 | ||
1480 | // }}}
|
1480 | // }}}
|
1481 | 1481 | ||
1482 | /*
|
1482 | /*
|
1483 | * Local variables:
|
1483 | * Local variables:
|
1484 | * tab-width: 4
|
1484 | * tab-width: 4
|
1485 | * c-basic-offset: 4
|
1485 | * c-basic-offset: 4
|
1486 | * End:
|
1486 | * End:
|
1487 | */
|
1487 | */
|
1488 | 1488 | ||
1489 | ?>
|
1489 | ?>
|
1490 | 1490 |