Редакция 2 | Только различия | Учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 2 | Редакция 13 | ||
---|---|---|---|
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 | * The PEAR DB driver for PHP's ifx extension
|
6 | * The PEAR DB driver for PHP's ifx extension
|
7 | * for interacting with Informix databases
|
7 | * for interacting with Informix databases
|
8 | *
|
8 | *
|
9 | * PHP versions 4 and 5
|
9 | * PHP versions 4 and 5
|
10 | *
|
10 | *
|
11 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
11 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
12 | * that is available through the world-wide-web at the following URI:
|
12 | * that is available through the world-wide-web at the following URI:
|
13 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
13 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
14 | * the PHP License and are unable to obtain it through the web, please
|
14 | * the PHP License and are unable to obtain it through the web, please
|
15 | * send a note to license@php.net so we can mail you a copy immediately.
|
15 | * send a note to license@php.net so we can mail you a copy immediately.
|
16 | *
|
16 | *
|
17 | * @category Database
|
17 | * @category Database
|
18 | * @package DB
|
18 | * @package DB
|
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: ifx.php,v 1.75 2007/07/06 05:19:21 aharvey Exp $
|
23 | * @version CVS: $Id: ifx.php,v 1.75 2007/07/06 05:19:21 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 DB_common class so it can be extended from
|
28 | * Obtain the DB_common class so it can be extended from
|
29 | */
|
29 | */
|
30 | require_once 'DB/common.php'; |
30 | require_once 'DB/common.php'; |
31 | 31 | ||
32 | /**
|
32 | /**
|
33 | * The methods PEAR DB uses to interact with PHP's ifx extension
|
33 | * The methods PEAR DB uses to interact with PHP's ifx extension
|
34 | * for interacting with Informix databases
|
34 | * for interacting with Informix databases
|
35 | *
|
35 | *
|
36 | * These methods overload the ones declared in DB_common.
|
36 | * These methods overload the ones declared in DB_common.
|
37 | *
|
37 | *
|
38 | * More info on Informix errors can be found at:
|
38 | * More info on Informix errors can be found at:
|
39 | * http://www.informix.com/answers/english/ierrors.htm
|
39 | * http://www.informix.com/answers/english/ierrors.htm
|
40 | *
|
40 | *
|
41 | * TODO:
|
41 | * TODO:
|
42 | * - set needed env Informix vars on connect
|
42 | * - set needed env Informix vars on connect
|
43 | * - implement native prepare/execute
|
43 | * - implement native prepare/execute
|
44 | *
|
44 | *
|
45 | * @category Database
|
45 | * @category Database
|
46 | * @package DB
|
46 | * @package DB
|
47 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
47 | * @author Tomas V.V.Cox <cox@idecnet.com>
|
48 | * @author Daniel Convissor <danielc@php.net>
|
48 | * @author Daniel Convissor <danielc@php.net>
|
49 | * @copyright 1997-2007 The PHP Group
|
49 | * @copyright 1997-2007 The PHP Group
|
50 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
50 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
51 | * @version Release: 1.7.13
|
51 | * @version Release: 1.7.13
|
52 | * @link http://pear.php.net/package/DB
|
52 | * @link http://pear.php.net/package/DB
|
53 | */
|
53 | */
|
54 | class DB_ifx extends DB_common |
54 | class DB_ifx extends DB_common |
55 | {
|
55 | {
|
56 | // {{{ properties
|
56 | // {{{ properties
|
57 | 57 | ||
58 | /**
|
58 | /**
|
59 | * The DB driver type (mysql, oci8, odbc, etc.)
|
59 | * The DB driver type (mysql, oci8, odbc, etc.)
|
60 | * @var string
|
60 | * @var string
|
61 | */
|
61 | */
|
62 | var $phptype = 'ifx'; |
62 | var $phptype = 'ifx'; |
63 | 63 | ||
64 | /**
|
64 | /**
|
65 | * The database syntax variant to be used (db2, access, etc.), if any
|
65 | * The database syntax variant to be used (db2, access, etc.), if any
|
66 | * @var string
|
66 | * @var string
|
67 | */
|
67 | */
|
68 | var $dbsyntax = 'ifx'; |
68 | var $dbsyntax = 'ifx'; |
69 | 69 | ||
70 | /**
|
70 | /**
|
71 | * The capabilities of this DB implementation
|
71 | * The capabilities of this DB implementation
|
72 | *
|
72 | *
|
73 | * The 'new_link' element contains the PHP version that first provided
|
73 | * The 'new_link' element contains the PHP version that first provided
|
74 | * new_link support for this DBMS. Contains false if it's unsupported.
|
74 | * new_link support for this DBMS. Contains false if it's unsupported.
|
75 | *
|
75 | *
|
76 | * Meaning of the 'limit' element:
|
76 | * Meaning of the 'limit' element:
|
77 | * + 'emulate' = emulate with fetch row by number
|
77 | * + 'emulate' = emulate with fetch row by number
|
78 | * + 'alter' = alter the query
|
78 | * + 'alter' = alter the query
|
79 | * + false = skip rows
|
79 | * + false = skip rows
|
80 | *
|
80 | *
|
81 | * @var array
|
81 | * @var array
|
82 | */
|
82 | */
|
83 | var $features = array( |
83 | var $features = array( |
84 | 'limit' => 'emulate', |
84 | 'limit' => 'emulate', |
85 | 'new_link' => false, |
85 | 'new_link' => false, |
86 | 'numrows' => 'emulate', |
86 | 'numrows' => 'emulate', |
87 | 'pconnect' => true, |
87 | 'pconnect' => true, |
88 | 'prepare' => false, |
88 | 'prepare' => false, |
89 | 'ssl' => false, |
89 | 'ssl' => false, |
90 | 'transactions' => true, |
90 | 'transactions' => true, |
91 | ); |
91 | ); |
92 | 92 | ||
93 | /**
|
93 | /**
|
94 | * A mapping of native error codes to DB error codes
|
94 | * A mapping of native error codes to DB error codes
|
95 | * @var array
|
95 | * @var array
|
96 | */
|
96 | */
|
97 | var $errorcode_map = array( |
97 | var $errorcode_map = array( |
98 | '-201' => DB_ERROR_SYNTAX, |
98 | '-201' => DB_ERROR_SYNTAX, |
99 | '-206' => DB_ERROR_NOSUCHTABLE, |
99 | '-206' => DB_ERROR_NOSUCHTABLE, |
100 | '-217' => DB_ERROR_NOSUCHFIELD, |
100 | '-217' => DB_ERROR_NOSUCHFIELD, |
101 | '-236' => DB_ERROR_VALUE_COUNT_ON_ROW, |
101 | '-236' => DB_ERROR_VALUE_COUNT_ON_ROW, |
102 | '-239' => DB_ERROR_CONSTRAINT, |
102 | '-239' => DB_ERROR_CONSTRAINT, |
103 | '-253' => DB_ERROR_SYNTAX, |
103 | '-253' => DB_ERROR_SYNTAX, |
104 | '-268' => DB_ERROR_CONSTRAINT, |
104 | '-268' => DB_ERROR_CONSTRAINT, |
105 | '-292' => DB_ERROR_CONSTRAINT_NOT_NULL, |
105 | '-292' => DB_ERROR_CONSTRAINT_NOT_NULL, |
106 | '-310' => DB_ERROR_ALREADY_EXISTS, |
106 | '-310' => DB_ERROR_ALREADY_EXISTS, |
107 | '-316' => DB_ERROR_ALREADY_EXISTS, |
107 | '-316' => DB_ERROR_ALREADY_EXISTS, |
108 | '-319' => DB_ERROR_NOT_FOUND, |
108 | '-319' => DB_ERROR_NOT_FOUND, |
109 | '-329' => DB_ERROR_NODBSELECTED, |
109 | '-329' => DB_ERROR_NODBSELECTED, |
110 | '-346' => DB_ERROR_CONSTRAINT, |
110 | '-346' => DB_ERROR_CONSTRAINT, |
111 | '-386' => DB_ERROR_CONSTRAINT_NOT_NULL, |
111 | '-386' => DB_ERROR_CONSTRAINT_NOT_NULL, |
112 | '-391' => DB_ERROR_CONSTRAINT_NOT_NULL, |
112 | '-391' => DB_ERROR_CONSTRAINT_NOT_NULL, |
113 | '-554' => DB_ERROR_SYNTAX, |
113 | '-554' => DB_ERROR_SYNTAX, |
114 | '-691' => DB_ERROR_CONSTRAINT, |
114 | '-691' => DB_ERROR_CONSTRAINT, |
115 | '-692' => DB_ERROR_CONSTRAINT, |
115 | '-692' => DB_ERROR_CONSTRAINT, |
116 | '-703' => DB_ERROR_CONSTRAINT_NOT_NULL, |
116 | '-703' => DB_ERROR_CONSTRAINT_NOT_NULL, |
117 | '-1202' => DB_ERROR_DIVZERO, |
117 | '-1202' => DB_ERROR_DIVZERO, |
118 | '-1204' => DB_ERROR_INVALID_DATE, |
118 | '-1204' => DB_ERROR_INVALID_DATE, |
119 | '-1205' => DB_ERROR_INVALID_DATE, |
119 | '-1205' => DB_ERROR_INVALID_DATE, |
120 | '-1206' => DB_ERROR_INVALID_DATE, |
120 | '-1206' => DB_ERROR_INVALID_DATE, |
121 | '-1209' => DB_ERROR_INVALID_DATE, |
121 | '-1209' => DB_ERROR_INVALID_DATE, |
122 | '-1210' => DB_ERROR_INVALID_DATE, |
122 | '-1210' => DB_ERROR_INVALID_DATE, |
123 | '-1212' => DB_ERROR_INVALID_DATE, |
123 | '-1212' => DB_ERROR_INVALID_DATE, |
124 | '-1213' => DB_ERROR_INVALID_NUMBER, |
124 | '-1213' => DB_ERROR_INVALID_NUMBER, |
125 | ); |
125 | ); |
126 | 126 | ||
127 | /**
|
127 | /**
|
128 | * The raw database connection created by PHP
|
128 | * The raw database connection created by PHP
|
129 | * @var resource
|
129 | * @var resource
|
130 | */
|
130 | */
|
131 | var $connection; |
131 | var $connection; |
132 | 132 | ||
133 | /**
|
133 | /**
|
134 | * The DSN information for connecting to a database
|
134 | * The DSN information for connecting to a database
|
135 | * @var array
|
135 | * @var array
|
136 | */
|
136 | */
|
137 | var $dsn = array(); |
137 | var $dsn = array(); |
138 | 138 | ||
139 | 139 | ||
140 | /**
|
140 | /**
|
141 | * Should data manipulation queries be committed automatically?
|
141 | * Should data manipulation queries be committed automatically?
|
142 | * @var bool
|
142 | * @var bool
|
143 | * @access private
|
143 | * @access private
|
144 | */
|
144 | */
|
145 | var $autocommit = true; |
145 | var $autocommit = true; |
146 | 146 | ||
147 | /**
|
147 | /**
|
148 | * The quantity of transactions begun
|
148 | * The quantity of transactions begun
|
149 | *
|
149 | *
|
150 | * {@internal While this is private, it can't actually be designated
|
150 | * {@internal While this is private, it can't actually be designated
|
151 | * private in PHP 5 because it is directly accessed in the test suite.}}
|
151 | * private in PHP 5 because it is directly accessed in the test suite.}}
|
152 | *
|
152 | *
|
153 | * @var integer
|
153 | * @var integer
|
154 | * @access private
|
154 | * @access private
|
155 | */
|
155 | */
|
156 | var $transaction_opcount = 0; |
156 | var $transaction_opcount = 0; |
157 | 157 | ||
158 | /**
|
158 | /**
|
159 | * The number of rows affected by a data manipulation query
|
159 | * The number of rows affected by a data manipulation query
|
160 | * @var integer
|
160 | * @var integer
|
161 | * @access private
|
161 | * @access private
|
162 | */
|
162 | */
|
163 | var $affected = 0; |
163 | var $affected = 0; |
164 | 164 | ||
165 | 165 | ||
166 | // }}}
|
166 | // }}}
|
167 | // {{{ constructor
|
167 | // {{{ constructor
|
168 | 168 | ||
169 | /**
|
169 | /**
|
170 | * This constructor calls <kbd>$this->DB_common()</kbd>
|
170 | * This constructor calls <kbd>$this->DB_common()</kbd>
|
171 | *
|
171 | *
|
172 | * @return void
|
172 | * @return void
|
173 | */
|
173 | */
|
174 | function DB_ifx() |
174 | function DB_ifx() |
175 | {
|
175 | {
|
176 | $this->DB_common(); |
176 | $this->DB_common(); |
177 | }
|
177 | }
|
178 | 178 | ||
179 | // }}}
|
179 | // }}}
|
180 | // {{{ connect()
|
180 | // {{{ connect()
|
181 | 181 | ||
182 | /**
|
182 | /**
|
183 | * Connect to the database server, log in and open the database
|
183 | * Connect to the database server, log in and open the database
|
184 | *
|
184 | *
|
185 | * Don't call this method directly. Use DB::connect() instead.
|
185 | * Don't call this method directly. Use DB::connect() instead.
|
186 | *
|
186 | *
|
187 | * @param array $dsn the data source name
|
187 | * @param array $dsn the data source name
|
188 | * @param bool $persistent should the connection be persistent?
|
188 | * @param bool $persistent should the connection be persistent?
|
189 | *
|
189 | *
|
190 | * @return int DB_OK on success. A DB_Error object on failure.
|
190 | * @return int DB_OK on success. A DB_Error object on failure.
|
191 | */
|
191 | */
|
192 | function connect($dsn, $persistent = false) |
192 | function connect($dsn, $persistent = false) |
193 | {
|
193 | {
|
194 | if (!PEAR::loadExtension('informix') && |
194 | if (!PEAR::loadExtension('informix') && |
195 | !PEAR::loadExtension('Informix')) |
195 | !PEAR::loadExtension('Informix')) |
196 | {
|
196 | {
|
197 | return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
197 | return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
198 | }
|
198 | }
|
199 | 199 | ||
200 | $this->dsn = $dsn; |
200 | $this->dsn = $dsn; |
201 | if ($dsn['dbsyntax']) { |
201 | if ($dsn['dbsyntax']) { |
202 | $this->dbsyntax = $dsn['dbsyntax']; |
202 | $this->dbsyntax = $dsn['dbsyntax']; |
203 | }
|
203 | }
|
204 | 204 | ||
205 | $dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : ''; |
205 | $dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : ''; |
206 | $dbname = $dsn['database'] ? $dsn['database'] . $dbhost : ''; |
206 | $dbname = $dsn['database'] ? $dsn['database'] . $dbhost : ''; |
207 | $user = $dsn['username'] ? $dsn['username'] : ''; |
207 | $user = $dsn['username'] ? $dsn['username'] : ''; |
208 | $pw = $dsn['password'] ? $dsn['password'] : ''; |
208 | $pw = $dsn['password'] ? $dsn['password'] : ''; |
209 | 209 | ||
210 | $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; |
210 | $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; |
211 | 211 | ||
212 | $this->connection = @$connect_function($dbname, $user, $pw); |
212 | $this->connection = @$connect_function($dbname, $user, $pw); |
213 | if (!is_resource($this->connection)) { |
213 | if (!is_resource($this->connection)) { |
214 | return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED); |
214 | return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED); |
215 | }
|
215 | }
|
216 | return DB_OK; |
216 | return DB_OK; |
217 | }
|
217 | }
|
218 | 218 | ||
219 | // }}}
|
219 | // }}}
|
220 | // {{{ disconnect()
|
220 | // {{{ disconnect()
|
221 | 221 | ||
222 | /**
|
222 | /**
|
223 | * Disconnects from the database server
|
223 | * Disconnects from the database server
|
224 | *
|
224 | *
|
225 | * @return bool TRUE on success, FALSE on failure
|
225 | * @return bool TRUE on success, FALSE on failure
|
226 | */
|
226 | */
|
227 | function disconnect() |
227 | function disconnect() |
228 | {
|
228 | {
|
229 | $ret = @ifx_close($this->connection); |
229 | $ret = @ifx_close($this->connection); |
230 | $this->connection = null; |
230 | $this->connection = null; |
231 | return $ret; |
231 | return $ret; |
232 | }
|
232 | }
|
233 | 233 | ||
234 | // }}}
|
234 | // }}}
|
235 | // {{{ simpleQuery()
|
235 | // {{{ simpleQuery()
|
236 | 236 | ||
237 | /**
|
237 | /**
|
238 | * Sends a query to the database server
|
238 | * Sends a query to the database server
|
239 | *
|
239 | *
|
240 | * @param string the SQL query string
|
240 | * @param string the SQL query string
|
241 | *
|
241 | *
|
242 | * @return mixed + a PHP result resrouce for successful SELECT queries
|
242 | * @return mixed + a PHP result resrouce for successful SELECT queries
|
243 | * + the DB_OK constant for other successful queries
|
243 | * + the DB_OK constant for other successful queries
|
244 | * + a DB_Error object on failure
|
244 | * + a DB_Error object on failure
|
245 | */
|
245 | */
|
246 | function simpleQuery($query) |
246 | function simpleQuery($query) |
247 | {
|
247 | {
|
248 | $ismanip = $this->_checkManip($query); |
248 | $ismanip = $this->_checkManip($query); |
249 | $this->last_query = $query; |
249 | $this->last_query = $query; |
250 | $this->affected = null; |
250 | $this->affected = null; |
251 | if (preg_match('/(SELECT|EXECUTE)/i', $query)) { //TESTME: Use !DB::isManip()? |
251 | if (preg_match('/(SELECT|EXECUTE)/i', $query)) { //TESTME: Use !DB::isManip()? |
252 | // the scroll is needed for fetching absolute row numbers
|
252 | // the scroll is needed for fetching absolute row numbers
|
253 | // in a select query result
|
253 | // in a select query result
|
254 | $result = @ifx_query($query, $this->connection, IFX_SCROLL); |
254 | $result = @ifx_query($query, $this->connection, IFX_SCROLL); |
255 | } else { |
255 | } else { |
256 | if (!$this->autocommit && $ismanip) { |
256 | if (!$this->autocommit && $ismanip) { |
257 | if ($this->transaction_opcount == 0) { |
257 | if ($this->transaction_opcount == 0) { |
258 | $result = @ifx_query('BEGIN WORK', $this->connection); |
258 | $result = @ifx_query('BEGIN WORK', $this->connection); |
259 | if (!$result) { |
259 | if (!$result) { |
260 | return $this->ifxRaiseError(); |
260 | return $this->ifxRaiseError(); |
261 | }
|
261 | }
|
262 | }
|
262 | }
|
263 | $this->transaction_opcount++; |
263 | $this->transaction_opcount++; |
264 | }
|
264 | }
|
265 | $result = @ifx_query($query, $this->connection); |
265 | $result = @ifx_query($query, $this->connection); |
266 | }
|
266 | }
|
267 | if (!$result) { |
267 | if (!$result) { |
268 | return $this->ifxRaiseError(); |
268 | return $this->ifxRaiseError(); |
269 | }
|
269 | }
|
270 | $this->affected = @ifx_affected_rows($result); |
270 | $this->affected = @ifx_affected_rows($result); |
271 | // Determine which queries should return data, and which
|
271 | // Determine which queries should return data, and which
|
272 | // should return an error code only.
|
272 | // should return an error code only.
|
273 | if (preg_match('/(SELECT|EXECUTE)/i', $query)) { |
273 | if (preg_match('/(SELECT|EXECUTE)/i', $query)) { |
274 | return $result; |
274 | return $result; |
275 | }
|
275 | }
|
276 | // XXX Testme: free results inside a transaction
|
276 | // XXX Testme: free results inside a transaction
|
277 | // may cause to stop it and commit the work?
|
277 | // may cause to stop it and commit the work?
|
278 | 278 | ||
279 | // Result has to be freed even with a insert or update
|
279 | // Result has to be freed even with a insert or update
|
280 | @ifx_free_result($result); |
280 | @ifx_free_result($result); |
281 | 281 | ||
282 | return DB_OK; |
282 | return DB_OK; |
283 | }
|
283 | }
|
284 | 284 | ||
285 | // }}}
|
285 | // }}}
|
286 | // {{{ nextResult()
|
286 | // {{{ nextResult()
|
287 | 287 | ||
288 | /**
|
288 | /**
|
289 | * Move the internal ifx result pointer to the next available result
|
289 | * Move the internal ifx result pointer to the next available result
|
290 | *
|
290 | *
|
291 | * @param a valid fbsql result resource
|
291 | * @param a valid fbsql result resource
|
292 | *
|
292 | *
|
293 | * @access public
|
293 | * @access public
|
294 | *
|
294 | *
|
295 | * @return true if a result is available otherwise return false
|
295 | * @return true if a result is available otherwise return false
|
296 | */
|
296 | */
|
297 | function nextResult($result) |
297 | function nextResult($result) |
298 | {
|
298 | {
|
299 | return false; |
299 | return false; |
300 | }
|
300 | }
|
301 | 301 | ||
302 | // }}}
|
302 | // }}}
|
303 | // {{{ affectedRows()
|
303 | // {{{ affectedRows()
|
304 | 304 | ||
305 | /**
|
305 | /**
|
306 | * Determines the number of rows affected by a data maniuplation query
|
306 | * Determines the number of rows affected by a data maniuplation query
|
307 | *
|
307 | *
|
308 | * 0 is returned for queries that don't manipulate data.
|
308 | * 0 is returned for queries that don't manipulate data.
|
309 | *
|
309 | *
|
310 | * @return int the number of rows. A DB_Error object on failure.
|
310 | * @return int the number of rows. A DB_Error object on failure.
|
311 | */
|
311 | */
|
312 | function affectedRows() |
312 | function affectedRows() |
313 | {
|
313 | {
|
314 | if ($this->_last_query_manip) { |
314 | if ($this->_last_query_manip) { |
315 | return $this->affected; |
315 | return $this->affected; |
316 | } else { |
316 | } else { |
317 | return 0; |
317 | return 0; |
318 | }
|
318 | }
|
319 | }
|
319 | }
|
320 | 320 | ||
321 | // }}}
|
321 | // }}}
|
322 | // {{{ fetchInto()
|
322 | // {{{ fetchInto()
|
323 | 323 | ||
324 | /**
|
324 | /**
|
325 | * Places a row from the result set into the given array
|
325 | * Places a row from the result set into the given array
|
326 | *
|
326 | *
|
327 | * Formating of the array and the data therein are configurable.
|
327 | * Formating of the array and the data therein are configurable.
|
328 | * See DB_result::fetchInto() for more information.
|
328 | * See DB_result::fetchInto() for more information.
|
329 | *
|
329 | *
|
330 | * This method is not meant to be called directly. Use
|
330 | * This method is not meant to be called directly. Use
|
331 | * DB_result::fetchInto() instead. It can't be declared "protected"
|
331 | * DB_result::fetchInto() instead. It can't be declared "protected"
|
332 | * because DB_result is a separate object.
|
332 | * because DB_result is a separate object.
|
333 | *
|
333 | *
|
334 | * @param resource $result the query result resource
|
334 | * @param resource $result the query result resource
|
335 | * @param array $arr the referenced array to put the data in
|
335 | * @param array $arr the referenced array to put the data in
|
336 | * @param int $fetchmode how the resulting array should be indexed
|
336 | * @param int $fetchmode how the resulting array should be indexed
|
337 | * @param int $rownum the row number to fetch (0 = first row)
|
337 | * @param int $rownum the row number to fetch (0 = first row)
|
338 | *
|
338 | *
|
339 | * @return mixed DB_OK on success, NULL when the end of a result set is
|
339 | * @return mixed DB_OK on success, NULL when the end of a result set is
|
340 | * reached or on failure
|
340 | * reached or on failure
|
341 | *
|
341 | *
|
342 | * @see DB_result::fetchInto()
|
342 | * @see DB_result::fetchInto()
|
343 | */
|
343 | */
|
344 | function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
344 | function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
345 | {
|
345 | {
|
346 | if (($rownum !== null) && ($rownum < 0)) { |
346 | if (($rownum !== null) && ($rownum < 0)) { |
347 | return null; |
347 | return null; |
348 | }
|
348 | }
|
349 | if ($rownum === null) { |
349 | if ($rownum === null) { |
350 | /*
|
350 | /*
|
351 | * Even though fetch_row() should return the next row if
|
351 | * Even though fetch_row() should return the next row if
|
352 | * $rownum is null, it doesn't in all cases. Bug 598.
|
352 | * $rownum is null, it doesn't in all cases. Bug 598.
|
353 | */
|
353 | */
|
354 | $rownum = 'NEXT'; |
354 | $rownum = 'NEXT'; |
355 | } else { |
355 | } else { |
356 | // Index starts at row 1, unlike most DBMS's starting at 0.
|
356 | // Index starts at row 1, unlike most DBMS's starting at 0.
|
357 | $rownum++; |
357 | $rownum++; |
358 | }
|
358 | }
|
359 | if (!$arr = @ifx_fetch_row($result, $rownum)) { |
359 | if (!$arr = @ifx_fetch_row($result, $rownum)) { |
360 | return null; |
360 | return null; |
361 | }
|
361 | }
|
362 | if ($fetchmode !== DB_FETCHMODE_ASSOC) { |
362 | if ($fetchmode !== DB_FETCHMODE_ASSOC) { |
363 | $i=0; |
363 | $i=0; |
364 | $order = array(); |
364 | $order = array(); |
365 | foreach ($arr as $val) { |
365 | foreach ($arr as $val) { |
366 | $order[$i++] = $val; |
366 | $order[$i++] = $val; |
367 | }
|
367 | }
|
368 | $arr = $order; |
368 | $arr = $order; |
369 | } elseif ($fetchmode == DB_FETCHMODE_ASSOC && |
369 | } elseif ($fetchmode == DB_FETCHMODE_ASSOC && |
370 | $this->options['portability'] & DB_PORTABILITY_LOWERCASE) |
370 | $this->options['portability'] & DB_PORTABILITY_LOWERCASE) |
371 | {
|
371 | {
|
372 | $arr = array_change_key_case($arr, CASE_LOWER); |
372 | $arr = array_change_key_case($arr, CASE_LOWER); |
373 | }
|
373 | }
|
374 | if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
374 | if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
375 | $this->_rtrimArrayValues($arr); |
375 | $this->_rtrimArrayValues($arr); |
376 | }
|
376 | }
|
377 | if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
377 | if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
378 | $this->_convertNullArrayValuesToEmpty($arr); |
378 | $this->_convertNullArrayValuesToEmpty($arr); |
379 | }
|
379 | }
|
380 | return DB_OK; |
380 | return DB_OK; |
381 | }
|
381 | }
|
382 | 382 | ||
383 | // }}}
|
383 | // }}}
|
384 | // {{{ numCols()
|
384 | // {{{ numCols()
|
385 | 385 | ||
386 | /**
|
386 | /**
|
387 | * Gets the number of columns in a result set
|
387 | * Gets the number of columns in a result set
|
388 | *
|
388 | *
|
389 | * This method is not meant to be called directly. Use
|
389 | * This method is not meant to be called directly. Use
|
390 | * DB_result::numCols() instead. It can't be declared "protected"
|
390 | * DB_result::numCols() instead. It can't be declared "protected"
|
391 | * because DB_result is a separate object.
|
391 | * because DB_result is a separate object.
|
392 | *
|
392 | *
|
393 | * @param resource $result PHP's query result resource
|
393 | * @param resource $result PHP's query result resource
|
394 | *
|
394 | *
|
395 | * @return int the number of columns. A DB_Error object on failure.
|
395 | * @return int the number of columns. A DB_Error object on failure.
|
396 | *
|
396 | *
|
397 | * @see DB_result::numCols()
|
397 | * @see DB_result::numCols()
|
398 | */
|
398 | */
|
399 | function numCols($result) |
399 | function numCols($result) |
400 | {
|
400 | {
|
401 | if (!$cols = @ifx_num_fields($result)) { |
401 | if (!$cols = @ifx_num_fields($result)) { |
402 | return $this->ifxRaiseError(); |
402 | return $this->ifxRaiseError(); |
403 | }
|
403 | }
|
404 | return $cols; |
404 | return $cols; |
405 | }
|
405 | }
|
406 | 406 | ||
407 | // }}}
|
407 | // }}}
|
408 | // {{{ freeResult()
|
408 | // {{{ freeResult()
|
409 | 409 | ||
410 | /**
|
410 | /**
|
411 | * Deletes the result set and frees the memory occupied by the result set
|
411 | * Deletes the result set and frees the memory occupied by the result set
|
412 | *
|
412 | *
|
413 | * This method is not meant to be called directly. Use
|
413 | * This method is not meant to be called directly. Use
|
414 | * DB_result::free() instead. It can't be declared "protected"
|
414 | * DB_result::free() instead. It can't be declared "protected"
|
415 | * because DB_result is a separate object.
|
415 | * because DB_result is a separate object.
|
416 | *
|
416 | *
|
417 | * @param resource $result PHP's query result resource
|
417 | * @param resource $result PHP's query result resource
|
418 | *
|
418 | *
|
419 | * @return bool TRUE on success, FALSE if $result is invalid
|
419 | * @return bool TRUE on success, FALSE if $result is invalid
|
420 | *
|
420 | *
|
421 | * @see DB_result::free()
|
421 | * @see DB_result::free()
|
422 | */
|
422 | */
|
423 | function freeResult($result) |
423 | function freeResult($result) |
424 | {
|
424 | {
|
425 | return is_resource($result) ? ifx_free_result($result) : false; |
425 | return is_resource($result) ? ifx_free_result($result) : false; |
426 | }
|
426 | }
|
427 | 427 | ||
428 | // }}}
|
428 | // }}}
|
429 | // {{{ autoCommit()
|
429 | // {{{ autoCommit()
|
430 | 430 | ||
431 | /**
|
431 | /**
|
432 | * Enables or disables automatic commits
|
432 | * Enables or disables automatic commits
|
433 | *
|
433 | *
|
434 | * @param bool $onoff true turns it on, false turns it off
|
434 | * @param bool $onoff true turns it on, false turns it off
|
435 | *
|
435 | *
|
436 | * @return int DB_OK on success. A DB_Error object if the driver
|
436 | * @return int DB_OK on success. A DB_Error object if the driver
|
437 | * doesn't support auto-committing transactions.
|
437 | * doesn't support auto-committing transactions.
|
438 | */
|
438 | */
|
439 | function autoCommit($onoff = true) |
439 | function autoCommit($onoff = true) |
440 | {
|
440 | {
|
441 | // XXX if $this->transaction_opcount > 0, we should probably
|
441 | // XXX if $this->transaction_opcount > 0, we should probably
|
442 | // issue a warning here.
|
442 | // issue a warning here.
|
443 | $this->autocommit = $onoff ? true : false; |
443 | $this->autocommit = $onoff ? true : false; |
444 | return DB_OK; |
444 | return DB_OK; |
445 | }
|
445 | }
|
446 | 446 | ||
447 | // }}}
|
447 | // }}}
|
448 | // {{{ commit()
|
448 | // {{{ commit()
|
449 | 449 | ||
450 | /**
|
450 | /**
|
451 | * Commits the current transaction
|
451 | * Commits the current transaction
|
452 | *
|
452 | *
|
453 | * @return int DB_OK on success. A DB_Error object on failure.
|
453 | * @return int DB_OK on success. A DB_Error object on failure.
|
454 | */
|
454 | */
|
455 | function commit() |
455 | function commit() |
456 | {
|
456 | {
|
457 | if ($this->transaction_opcount > 0) { |
457 | if ($this->transaction_opcount > 0) { |
458 | $result = @ifx_query('COMMIT WORK', $this->connection); |
458 | $result = @ifx_query('COMMIT WORK', $this->connection); |
459 | $this->transaction_opcount = 0; |
459 | $this->transaction_opcount = 0; |
460 | if (!$result) { |
460 | if (!$result) { |
461 | return $this->ifxRaiseError(); |
461 | return $this->ifxRaiseError(); |
462 | }
|
462 | }
|
463 | }
|
463 | }
|
464 | return DB_OK; |
464 | return DB_OK; |
465 | }
|
465 | }
|
466 | 466 | ||
467 | // }}}
|
467 | // }}}
|
468 | // {{{ rollback()
|
468 | // {{{ rollback()
|
469 | 469 | ||
470 | /**
|
470 | /**
|
471 | * Reverts the current transaction
|
471 | * Reverts the current transaction
|
472 | *
|
472 | *
|
473 | * @return int DB_OK on success. A DB_Error object on failure.
|
473 | * @return int DB_OK on success. A DB_Error object on failure.
|
474 | */
|
474 | */
|
475 | function rollback() |
475 | function rollback() |
476 | {
|
476 | {
|
477 | if ($this->transaction_opcount > 0) { |
477 | if ($this->transaction_opcount > 0) { |
478 | $result = @ifx_query('ROLLBACK WORK', $this->connection); |
478 | $result = @ifx_query('ROLLBACK WORK', $this->connection); |
479 | $this->transaction_opcount = 0; |
479 | $this->transaction_opcount = 0; |
480 | if (!$result) { |
480 | if (!$result) { |
481 | return $this->ifxRaiseError(); |
481 | return $this->ifxRaiseError(); |
482 | }
|
482 | }
|
483 | }
|
483 | }
|
484 | return DB_OK; |
484 | return DB_OK; |
485 | }
|
485 | }
|
486 | 486 | ||
487 | // }}}
|
487 | // }}}
|
488 | // {{{ ifxRaiseError()
|
488 | // {{{ ifxRaiseError()
|
489 | 489 | ||
490 | /**
|
490 | /**
|
491 | * Produces a DB_Error object regarding the current problem
|
491 | * Produces a DB_Error object regarding the current problem
|
492 | *
|
492 | *
|
493 | * @param int $errno if the error is being manually raised pass a
|
493 | * @param int $errno if the error is being manually raised pass a
|
494 | * DB_ERROR* constant here. If this isn't passed
|
494 | * DB_ERROR* constant here. If this isn't passed
|
495 | * the error information gathered from the DBMS.
|
495 | * the error information gathered from the DBMS.
|
496 | *
|
496 | *
|
497 | * @return object the DB_Error object
|
497 | * @return object the DB_Error object
|
498 | *
|
498 | *
|
499 | * @see DB_common::raiseError(),
|
499 | * @see DB_common::raiseError(),
|
500 | * DB_ifx::errorNative(), DB_ifx::errorCode()
|
500 | * DB_ifx::errorNative(), DB_ifx::errorCode()
|
501 | */
|
501 | */
|
502 | function ifxRaiseError($errno = null) |
502 | function ifxRaiseError($errno = null) |
503 | {
|
503 | {
|
504 | if ($errno === null) { |
504 | if ($errno === null) { |
505 | $errno = $this->errorCode(ifx_error()); |
505 | $errno = $this->errorCode(ifx_error()); |
506 | }
|
506 | }
|
507 | return $this->raiseError($errno, null, null, null, |
507 | return $this->raiseError($errno, null, null, null, |
508 | $this->errorNative()); |
508 | $this->errorNative()); |
509 | }
|
509 | }
|
510 | 510 | ||
511 | // }}}
|
511 | // }}}
|
512 | // {{{ errorNative()
|
512 | // {{{ errorNative()
|
513 | 513 | ||
514 | /**
|
514 | /**
|
515 | * Gets the DBMS' native error code and message produced by the last query
|
515 | * Gets the DBMS' native error code and message produced by the last query
|
516 | *
|
516 | *
|
517 | * @return string the DBMS' error code and message
|
517 | * @return string the DBMS' error code and message
|
518 | */
|
518 | */
|
519 | function errorNative() |
519 | function errorNative() |
520 | {
|
520 | {
|
521 | return @ifx_error() . ' ' . @ifx_errormsg(); |
521 | return @ifx_error() . ' ' . @ifx_errormsg(); |
522 | }
|
522 | }
|
523 | 523 | ||
524 | // }}}
|
524 | // }}}
|
525 | // {{{ errorCode()
|
525 | // {{{ errorCode()
|
526 | 526 | ||
527 | /**
|
527 | /**
|
528 | * Maps native error codes to DB's portable ones.
|
528 | * Maps native error codes to DB's portable ones.
|
529 | *
|
529 | *
|
530 | * Requires that the DB implementation's constructor fills
|
530 | * Requires that the DB implementation's constructor fills
|
531 | * in the <var>$errorcode_map</var> property.
|
531 | * in the <var>$errorcode_map</var> property.
|
532 | *
|
532 | *
|
533 | * @param string $nativecode error code returned by the database
|
533 | * @param string $nativecode error code returned by the database
|
534 | * @return int a portable DB error code, or DB_ERROR if this DB
|
534 | * @return int a portable DB error code, or DB_ERROR if this DB
|
535 | * implementation has no mapping for the given error code.
|
535 | * implementation has no mapping for the given error code.
|
536 | */
|
536 | */
|
537 | function errorCode($nativecode) |
537 | function errorCode($nativecode) |
538 | {
|
538 | {
|
539 | if (ereg('SQLCODE=(.*)]', $nativecode, $match)) { |
539 | if (ereg('SQLCODE=(.*)]', $nativecode, $match)) { |
540 | $code = $match[1]; |
540 | $code = $match[1]; |
541 | if (isset($this->errorcode_map[$code])) { |
541 | if (isset($this->errorcode_map[$code])) { |
542 | return $this->errorcode_map[$code]; |
542 | return $this->errorcode_map[$code]; |
543 | }
|
543 | }
|
544 | }
|
544 | }
|
545 | return DB_ERROR; |
545 | return DB_ERROR; |
546 | }
|
546 | }
|
547 | 547 | ||
548 | // }}}
|
548 | // }}}
|
549 | // {{{ tableInfo()
|
549 | // {{{ tableInfo()
|
550 | 550 | ||
551 | /**
|
551 | /**
|
552 | * Returns information about a table or a result set
|
552 | * Returns information about a table or a result set
|
553 | *
|
553 | *
|
554 | * NOTE: only supports 'table' if <var>$result</var> is a table name.
|
554 | * NOTE: only supports 'table' if <var>$result</var> is a table name.
|
555 | *
|
555 | *
|
556 | * If analyzing a query result and the result has duplicate field names,
|
556 | * If analyzing a query result and the result has duplicate field names,
|
557 | * an error will be raised saying
|
557 | * an error will be raised saying
|
558 | * <samp>can't distinguish duplicate field names</samp>.
|
558 | * <samp>can't distinguish duplicate field names</samp>.
|
559 | *
|
559 | *
|
560 | * @param object|string $result DB_result object from a query or a
|
560 | * @param object|string $result DB_result object from a query or a
|
561 | * string containing the name of a table.
|
561 | * string containing the name of a table.
|
562 | * While this also accepts a query result
|
562 | * While this also accepts a query result
|
563 | * resource identifier, this behavior is
|
563 | * resource identifier, this behavior is
|
564 | * deprecated.
|
564 | * deprecated.
|
565 | * @param int $mode a valid tableInfo mode
|
565 | * @param int $mode a valid tableInfo mode
|
566 | *
|
566 | *
|
567 | * @return array an associative array with the information requested.
|
567 | * @return array an associative array with the information requested.
|
568 | * A DB_Error object on failure.
|
568 | * A DB_Error object on failure.
|
569 | *
|
569 | *
|
570 | * @see DB_common::tableInfo()
|
570 | * @see DB_common::tableInfo()
|
571 | * @since Method available since Release 1.6.0
|
571 | * @since Method available since Release 1.6.0
|
572 | */
|
572 | */
|
573 | function tableInfo($result, $mode = null) |
573 | function tableInfo($result, $mode = null) |
574 | {
|
574 | {
|
575 | if (is_string($result)) { |
575 | if (is_string($result)) { |
576 | /*
|
576 | /*
|
577 | * Probably received a table name.
|
577 | * Probably received a table name.
|
578 | * Create a result resource identifier.
|
578 | * Create a result resource identifier.
|
579 | */
|
579 | */
|
580 | $id = @ifx_query("SELECT * FROM $result WHERE 1=0", |
580 | $id = @ifx_query("SELECT * FROM $result WHERE 1=0", |
581 | $this->connection); |
581 | $this->connection); |
582 | $got_string = true; |
582 | $got_string = true; |
583 | } elseif (isset($result->result)) { |
583 | } elseif (isset($result->result)) { |
584 | /*
|
584 | /*
|
585 | * Probably received a result object.
|
585 | * Probably received a result object.
|
586 | * Extract the result resource identifier.
|
586 | * Extract the result resource identifier.
|
587 | */
|
587 | */
|
588 | $id = $result->result; |
588 | $id = $result->result; |
589 | $got_string = false; |
589 | $got_string = false; |
590 | } else { |
590 | } else { |
591 | /*
|
591 | /*
|
592 | * Probably received a result resource identifier.
|
592 | * Probably received a result resource identifier.
|
593 | * Copy it.
|
593 | * Copy it.
|
594 | */
|
594 | */
|
595 | $id = $result; |
595 | $id = $result; |
596 | $got_string = false; |
596 | $got_string = false; |
597 | }
|
597 | }
|
598 | 598 | ||
599 | if (!is_resource($id)) { |
599 | if (!is_resource($id)) { |
600 | return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); |
600 | return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); |
601 | }
|
601 | }
|
602 | 602 | ||
603 | $flds = @ifx_fieldproperties($id); |
603 | $flds = @ifx_fieldproperties($id); |
604 | $count = @ifx_num_fields($id); |
604 | $count = @ifx_num_fields($id); |
605 | 605 | ||
606 | if (count($flds) != $count) { |
606 | if (count($flds) != $count) { |
607 | return $this->raiseError("can't distinguish duplicate field names"); |
607 | return $this->raiseError("can't distinguish duplicate field names"); |
608 | }
|
608 | }
|
609 | 609 | ||
610 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
610 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
611 | $case_func = 'strtolower'; |
611 | $case_func = 'strtolower'; |
612 | } else { |
612 | } else { |
613 | $case_func = 'strval'; |
613 | $case_func = 'strval'; |
614 | }
|
614 | }
|
615 | 615 | ||
616 | $i = 0; |
616 | $i = 0; |
617 | $res = array(); |
617 | $res = array(); |
618 | 618 | ||
619 | if ($mode) { |
619 | if ($mode) { |
620 | $res['num_fields'] = $count; |
620 | $res['num_fields'] = $count; |
621 | }
|
621 | }
|
622 | 622 | ||
623 | foreach ($flds as $key => $value) { |
623 | foreach ($flds as $key => $value) { |
624 | $props = explode(';', $value); |
624 | $props = explode(';', $value); |
625 | $res[$i] = array( |
625 | $res[$i] = array( |
626 | 'table' => $got_string ? $case_func($result) : '', |
626 | 'table' => $got_string ? $case_func($result) : '', |
627 | 'name' => $case_func($key), |
627 | 'name' => $case_func($key), |
628 | 'type' => $props[0], |
628 | 'type' => $props[0], |
629 | 'len' => $props[1], |
629 | 'len' => $props[1], |
630 | 'flags' => $props[4] == 'N' ? 'not_null' : '', |
630 | 'flags' => $props[4] == 'N' ? 'not_null' : '', |
631 | ); |
631 | ); |
632 | if ($mode & DB_TABLEINFO_ORDER) { |
632 | if ($mode & DB_TABLEINFO_ORDER) { |
633 | $res['order'][$res[$i]['name']] = $i; |
633 | $res['order'][$res[$i]['name']] = $i; |
634 | }
|
634 | }
|
635 | if ($mode & DB_TABLEINFO_ORDERTABLE) { |
635 | if ($mode & DB_TABLEINFO_ORDERTABLE) { |
636 | $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
636 | $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
637 | }
|
637 | }
|
638 | $i++; |
638 | $i++; |
639 | }
|
639 | }
|
640 | 640 | ||
641 | // free the result only if we were called on a table
|
641 | // free the result only if we were called on a table
|
642 | if ($got_string) { |
642 | if ($got_string) { |
643 | @ifx_free_result($id); |
643 | @ifx_free_result($id); |
644 | }
|
644 | }
|
645 | return $res; |
645 | return $res; |
646 | }
|
646 | }
|
647 | 647 | ||
648 | // }}}
|
648 | // }}}
|
649 | // {{{ getSpecialQuery()
|
649 | // {{{ getSpecialQuery()
|
650 | 650 | ||
651 | /**
|
651 | /**
|
652 | * Obtains the query string needed for listing a given type of objects
|
652 | * Obtains the query string needed for listing a given type of objects
|
653 | *
|
653 | *
|
654 | * @param string $type the kind of objects you want to retrieve
|
654 | * @param string $type the kind of objects you want to retrieve
|
655 | *
|
655 | *
|
656 | * @return string the SQL query string or null if the driver doesn't
|
656 | * @return string the SQL query string or null if the driver doesn't
|
657 | * support the object type requested
|
657 | * support the object type requested
|
658 | *
|
658 | *
|
659 | * @access protected
|
659 | * @access protected
|
660 | * @see DB_common::getListOf()
|
660 | * @see DB_common::getListOf()
|
661 | */
|
661 | */
|
662 | function getSpecialQuery($type) |
662 | function getSpecialQuery($type) |
663 | {
|
663 | {
|
664 | switch ($type) { |
664 | switch ($type) { |
665 | case 'tables': |
665 | case 'tables': |
666 | return 'SELECT tabname FROM systables WHERE tabid >= 100'; |
666 | return 'SELECT tabname FROM systables WHERE tabid >= 100'; |
667 | default: |
667 | default: |
668 | return null; |
668 | return null; |
669 | }
|
669 | }
|
670 | }
|
670 | }
|
671 | 671 | ||
672 | // }}}
|
672 | // }}}
|
673 | 673 | ||
674 | }
|
674 | }
|
675 | 675 | ||
676 | /*
|
676 | /*
|
677 | * Local variables:
|
677 | * Local variables:
|
678 | * tab-width: 4
|
678 | * tab-width: 4
|
679 | * c-basic-offset: 4
|
679 | * c-basic-offset: 4
|
680 | * End:
|
680 | * End:
|
681 | */
|
681 | */
|
682 | 682 | ||
683 | ?>
|
683 | ?>
|
684 | 684 |