Редакция 2 | Только различия | Не учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 2 | Редакция 48 | ||
---|---|---|---|
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 odbc extension
|
6 | * The PEAR DB driver for PHP's odbc extension
|
7 | * for interacting with databases via ODBC connections
|
7 | * for interacting with databases via ODBC connections
|
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 Stig Bakken <ssb@php.net>
|
19 | * @author Stig Bakken <ssb@php.net>
|
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: odbc.php,v 1.81 2007/07/06 05:19:21 aharvey Exp $
|
23 | * @version CVS: $Id: odbc.php,v 1.81 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 odbc extension
|
33 | * The methods PEAR DB uses to interact with PHP's odbc extension
|
34 | * for interacting with databases via ODBC connections
|
34 | * for interacting with databases via ODBC connections
|
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 ODBC errors could be found here:
|
38 | * More info on ODBC errors could be found here:
|
39 | * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
|
39 | * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
|
40 | *
|
40 | *
|
41 | * @category Database
|
41 | * @category Database
|
42 | * @package DB
|
42 | * @package DB
|
43 | * @author Stig Bakken <ssb@php.net>
|
43 | * @author Stig Bakken <ssb@php.net>
|
44 | * @author Daniel Convissor <danielc@php.net>
|
44 | * @author Daniel Convissor <danielc@php.net>
|
45 | * @copyright 1997-2007 The PHP Group
|
45 | * @copyright 1997-2007 The PHP Group
|
46 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
46 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
47 | * @version Release: 1.7.13
|
47 | * @version Release: 1.7.13
|
48 | * @link http://pear.php.net/package/DB
|
48 | * @link http://pear.php.net/package/DB
|
49 | */
|
49 | */
|
50 | class DB_odbc extends DB_common |
50 | class DB_odbc extends DB_common |
51 | {
|
51 | {
|
52 | // {{{ properties
|
52 | // {{{ properties
|
53 | 53 | ||
54 | /**
|
54 | /**
|
55 | * The DB driver type (mysql, oci8, odbc, etc.)
|
55 | * The DB driver type (mysql, oci8, odbc, etc.)
|
56 | * @var string
|
56 | * @var string
|
57 | */
|
57 | */
|
58 | var $phptype = 'odbc'; |
58 | var $phptype = 'odbc'; |
59 | 59 | ||
60 | /**
|
60 | /**
|
61 | * The database syntax variant to be used (db2, access, etc.), if any
|
61 | * The database syntax variant to be used (db2, access, etc.), if any
|
62 | * @var string
|
62 | * @var string
|
63 | */
|
63 | */
|
64 | var $dbsyntax = 'sql92'; |
64 | var $dbsyntax = 'sql92'; |
65 | 65 | ||
66 | /**
|
66 | /**
|
67 | * The capabilities of this DB implementation
|
67 | * The capabilities of this DB implementation
|
68 | *
|
68 | *
|
69 | * The 'new_link' element contains the PHP version that first provided
|
69 | * The 'new_link' element contains the PHP version that first provided
|
70 | * new_link support for this DBMS. Contains false if it's unsupported.
|
70 | * new_link support for this DBMS. Contains false if it's unsupported.
|
71 | *
|
71 | *
|
72 | * Meaning of the 'limit' element:
|
72 | * Meaning of the 'limit' element:
|
73 | * + 'emulate' = emulate with fetch row by number
|
73 | * + 'emulate' = emulate with fetch row by number
|
74 | * + 'alter' = alter the query
|
74 | * + 'alter' = alter the query
|
75 | * + false = skip rows
|
75 | * + false = skip rows
|
76 | *
|
76 | *
|
77 | * NOTE: The feature set of the following drivers are different than
|
77 | * NOTE: The feature set of the following drivers are different than
|
78 | * the default:
|
78 | * the default:
|
79 | * + solid: 'transactions' = true
|
79 | * + solid: 'transactions' = true
|
80 | * + navision: 'limit' = false
|
80 | * + navision: 'limit' = false
|
81 | *
|
81 | *
|
82 | * @var array
|
82 | * @var array
|
83 | */
|
83 | */
|
84 | var $features = array( |
84 | var $features = array( |
85 | 'limit' => 'emulate', |
85 | 'limit' => 'emulate', |
86 | 'new_link' => false, |
86 | 'new_link' => false, |
87 | 'numrows' => true, |
87 | 'numrows' => true, |
88 | 'pconnect' => true, |
88 | 'pconnect' => true, |
89 | 'prepare' => false, |
89 | 'prepare' => false, |
90 | 'ssl' => false, |
90 | 'ssl' => false, |
91 | 'transactions' => false, |
91 | 'transactions' => false, |
92 | ); |
92 | ); |
93 | 93 | ||
94 | /**
|
94 | /**
|
95 | * A mapping of native error codes to DB error codes
|
95 | * A mapping of native error codes to DB error codes
|
96 | * @var array
|
96 | * @var array
|
97 | */
|
97 | */
|
98 | var $errorcode_map = array( |
98 | var $errorcode_map = array( |
99 | '01004' => DB_ERROR_TRUNCATED, |
99 | '01004' => DB_ERROR_TRUNCATED, |
100 | '07001' => DB_ERROR_MISMATCH, |
100 | '07001' => DB_ERROR_MISMATCH, |
101 | '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW, |
101 | '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW, |
102 | '21S02' => DB_ERROR_MISMATCH, |
102 | '21S02' => DB_ERROR_MISMATCH, |
103 | '22001' => DB_ERROR_INVALID, |
103 | '22001' => DB_ERROR_INVALID, |
104 | '22003' => DB_ERROR_INVALID_NUMBER, |
104 | '22003' => DB_ERROR_INVALID_NUMBER, |
105 | '22005' => DB_ERROR_INVALID_NUMBER, |
105 | '22005' => DB_ERROR_INVALID_NUMBER, |
106 | '22008' => DB_ERROR_INVALID_DATE, |
106 | '22008' => DB_ERROR_INVALID_DATE, |
107 | '22012' => DB_ERROR_DIVZERO, |
107 | '22012' => DB_ERROR_DIVZERO, |
108 | '23000' => DB_ERROR_CONSTRAINT, |
108 | '23000' => DB_ERROR_CONSTRAINT, |
109 | '23502' => DB_ERROR_CONSTRAINT_NOT_NULL, |
109 | '23502' => DB_ERROR_CONSTRAINT_NOT_NULL, |
110 | '23503' => DB_ERROR_CONSTRAINT, |
110 | '23503' => DB_ERROR_CONSTRAINT, |
111 | '23504' => DB_ERROR_CONSTRAINT, |
111 | '23504' => DB_ERROR_CONSTRAINT, |
112 | '23505' => DB_ERROR_CONSTRAINT, |
112 | '23505' => DB_ERROR_CONSTRAINT, |
113 | '24000' => DB_ERROR_INVALID, |
113 | '24000' => DB_ERROR_INVALID, |
114 | '34000' => DB_ERROR_INVALID, |
114 | '34000' => DB_ERROR_INVALID, |
115 | '37000' => DB_ERROR_SYNTAX, |
115 | '37000' => DB_ERROR_SYNTAX, |
116 | '42000' => DB_ERROR_SYNTAX, |
116 | '42000' => DB_ERROR_SYNTAX, |
117 | '42601' => DB_ERROR_SYNTAX, |
117 | '42601' => DB_ERROR_SYNTAX, |
118 | 'IM001' => DB_ERROR_UNSUPPORTED, |
118 | 'IM001' => DB_ERROR_UNSUPPORTED, |
119 | 'S0000' => DB_ERROR_NOSUCHTABLE, |
119 | 'S0000' => DB_ERROR_NOSUCHTABLE, |
120 | 'S0001' => DB_ERROR_ALREADY_EXISTS, |
120 | 'S0001' => DB_ERROR_ALREADY_EXISTS, |
121 | 'S0002' => DB_ERROR_NOSUCHTABLE, |
121 | 'S0002' => DB_ERROR_NOSUCHTABLE, |
122 | 'S0011' => DB_ERROR_ALREADY_EXISTS, |
122 | 'S0011' => DB_ERROR_ALREADY_EXISTS, |
123 | 'S0012' => DB_ERROR_NOT_FOUND, |
123 | 'S0012' => DB_ERROR_NOT_FOUND, |
124 | 'S0021' => DB_ERROR_ALREADY_EXISTS, |
124 | 'S0021' => DB_ERROR_ALREADY_EXISTS, |
125 | 'S0022' => DB_ERROR_NOSUCHFIELD, |
125 | 'S0022' => DB_ERROR_NOSUCHFIELD, |
126 | 'S1009' => DB_ERROR_INVALID, |
126 | 'S1009' => DB_ERROR_INVALID, |
127 | 'S1090' => DB_ERROR_INVALID, |
127 | 'S1090' => DB_ERROR_INVALID, |
128 | 'S1C00' => DB_ERROR_NOT_CAPABLE, |
128 | 'S1C00' => DB_ERROR_NOT_CAPABLE, |
129 | ); |
129 | ); |
130 | 130 | ||
131 | /**
|
131 | /**
|
132 | * The raw database connection created by PHP
|
132 | * The raw database connection created by PHP
|
133 | * @var resource
|
133 | * @var resource
|
134 | */
|
134 | */
|
135 | var $connection; |
135 | var $connection; |
136 | 136 | ||
137 | /**
|
137 | /**
|
138 | * The DSN information for connecting to a database
|
138 | * The DSN information for connecting to a database
|
139 | * @var array
|
139 | * @var array
|
140 | */
|
140 | */
|
141 | var $dsn = array(); |
141 | var $dsn = array(); |
142 | 142 | ||
143 | 143 | ||
144 | /**
|
144 | /**
|
145 | * The number of rows affected by a data manipulation query
|
145 | * The number of rows affected by a data manipulation query
|
146 | * @var integer
|
146 | * @var integer
|
147 | * @access private
|
147 | * @access private
|
148 | */
|
148 | */
|
149 | var $affected = 0; |
149 | var $affected = 0; |
150 | 150 | ||
151 | 151 | ||
152 | // }}}
|
152 | // }}}
|
153 | // {{{ constructor
|
153 | // {{{ constructor
|
154 | 154 | ||
155 | /**
|
155 | /**
|
156 | * This constructor calls <kbd>$this->DB_common()</kbd>
|
156 | * This constructor calls <kbd>$this->DB_common()</kbd>
|
157 | *
|
157 | *
|
158 | * @return void
|
158 | * @return void
|
159 | */
|
159 | */
|
160 | function DB_odbc() |
160 | function DB_odbc() |
161 | {
|
161 | {
|
162 | $this->DB_common(); |
162 | $this->DB_common(); |
163 | }
|
163 | }
|
164 | 164 | ||
165 | // }}}
|
165 | // }}}
|
166 | // {{{ connect()
|
166 | // {{{ connect()
|
167 | 167 | ||
168 | /**
|
168 | /**
|
169 | * Connect to the database server, log in and open the database
|
169 | * Connect to the database server, log in and open the database
|
170 | *
|
170 | *
|
171 | * Don't call this method directly. Use DB::connect() instead.
|
171 | * Don't call this method directly. Use DB::connect() instead.
|
172 | *
|
172 | *
|
173 | * PEAR DB's odbc driver supports the following extra DSN options:
|
173 | * PEAR DB's odbc driver supports the following extra DSN options:
|
174 | * + cursor The type of cursor to be used for this connection.
|
174 | * + cursor The type of cursor to be used for this connection.
|
175 | *
|
175 | *
|
176 | * @param array $dsn the data source name
|
176 | * @param array $dsn the data source name
|
177 | * @param bool $persistent should the connection be persistent?
|
177 | * @param bool $persistent should the connection be persistent?
|
178 | *
|
178 | *
|
179 | * @return int DB_OK on success. A DB_Error object on failure.
|
179 | * @return int DB_OK on success. A DB_Error object on failure.
|
180 | */
|
180 | */
|
181 | function connect($dsn, $persistent = false) |
181 | function connect($dsn, $persistent = false) |
182 | {
|
182 | {
|
183 | if (!PEAR::loadExtension('odbc')) { |
183 | if (!PEAR::loadExtension('odbc')) { |
184 | return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
184 | return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); |
185 | }
|
185 | }
|
186 | 186 | ||
187 | $this->dsn = $dsn; |
187 | $this->dsn = $dsn; |
188 | if ($dsn['dbsyntax']) { |
188 | if ($dsn['dbsyntax']) { |
189 | $this->dbsyntax = $dsn['dbsyntax']; |
189 | $this->dbsyntax = $dsn['dbsyntax']; |
190 | }
|
190 | }
|
191 | switch ($this->dbsyntax) { |
191 | switch ($this->dbsyntax) { |
192 | case 'access': |
192 | case 'access': |
193 | case 'db2': |
193 | case 'db2': |
194 | case 'solid': |
194 | case 'solid': |
195 | $this->features['transactions'] = true; |
195 | $this->features['transactions'] = true; |
196 | break; |
196 | break; |
197 | case 'navision': |
197 | case 'navision': |
198 | $this->features['limit'] = false; |
198 | $this->features['limit'] = false; |
199 | }
|
199 | }
|
200 | 200 | ||
201 | /*
|
201 | /*
|
202 | * This is hear for backwards compatibility. Should have been using
|
202 | * This is hear for backwards compatibility. Should have been using
|
203 | * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
|
203 | * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
|
204 | */
|
204 | */
|
205 | if ($dsn['database']) { |
205 | if ($dsn['database']) { |
206 | $odbcdsn = $dsn['database']; |
206 | $odbcdsn = $dsn['database']; |
207 | } elseif ($dsn['hostspec']) { |
207 | } elseif ($dsn['hostspec']) { |
208 | $odbcdsn = $dsn['hostspec']; |
208 | $odbcdsn = $dsn['hostspec']; |
209 | } else { |
209 | } else { |
210 | $odbcdsn = 'localhost'; |
210 | $odbcdsn = 'localhost'; |
211 | }
|
211 | }
|
212 | 212 | ||
213 | $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect'; |
213 | $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect'; |
214 | 214 | ||
215 | if (empty($dsn['cursor'])) { |
215 | if (empty($dsn['cursor'])) { |
216 | $this->connection = @$connect_function($odbcdsn, $dsn['username'], |
216 | $this->connection = @$connect_function($odbcdsn, $dsn['username'], |
217 | $dsn['password']); |
217 | $dsn['password']); |
218 | } else { |
218 | } else { |
219 | $this->connection = @$connect_function($odbcdsn, $dsn['username'], |
219 | $this->connection = @$connect_function($odbcdsn, $dsn['username'], |
220 | $dsn['password'], |
220 | $dsn['password'], |
221 | $dsn['cursor']); |
221 | $dsn['cursor']); |
222 | }
|
222 | }
|
223 | 223 | ||
224 | if (!is_resource($this->connection)) { |
224 | if (!is_resource($this->connection)) { |
225 | return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
225 | return $this->raiseError(DB_ERROR_CONNECT_FAILED, |
226 | null, null, null, |
226 | null, null, null, |
227 | $this->errorNative()); |
227 | $this->errorNative()); |
228 | }
|
228 | }
|
229 | return DB_OK; |
229 | return DB_OK; |
230 | }
|
230 | }
|
231 | 231 | ||
232 | // }}}
|
232 | // }}}
|
233 | // {{{ disconnect()
|
233 | // {{{ disconnect()
|
234 | 234 | ||
235 | /**
|
235 | /**
|
236 | * Disconnects from the database server
|
236 | * Disconnects from the database server
|
237 | *
|
237 | *
|
238 | * @return bool TRUE on success, FALSE on failure
|
238 | * @return bool TRUE on success, FALSE on failure
|
239 | */
|
239 | */
|
240 | function disconnect() |
240 | function disconnect() |
241 | {
|
241 | {
|
242 | $err = @odbc_close($this->connection); |
242 | $err = @odbc_close($this->connection); |
243 | $this->connection = null; |
243 | $this->connection = null; |
244 | return $err; |
244 | return $err; |
245 | }
|
245 | }
|
246 | 246 | ||
247 | // }}}
|
247 | // }}}
|
248 | // {{{ simpleQuery()
|
248 | // {{{ simpleQuery()
|
249 | 249 | ||
250 | /**
|
250 | /**
|
251 | * Sends a query to the database server
|
251 | * Sends a query to the database server
|
252 | *
|
252 | *
|
253 | * @param string the SQL query string
|
253 | * @param string the SQL query string
|
254 | *
|
254 | *
|
255 | * @return mixed + a PHP result resrouce for successful SELECT queries
|
255 | * @return mixed + a PHP result resrouce for successful SELECT queries
|
256 | * + the DB_OK constant for other successful queries
|
256 | * + the DB_OK constant for other successful queries
|
257 | * + a DB_Error object on failure
|
257 | * + a DB_Error object on failure
|
258 | */
|
258 | */
|
259 | function simpleQuery($query) |
259 | function simpleQuery($query) |
260 | {
|
260 | {
|
261 | $this->last_query = $query; |
261 | $this->last_query = $query; |
262 | $query = $this->modifyQuery($query); |
262 | $query = $this->modifyQuery($query); |
263 | $result = @odbc_exec($this->connection, $query); |
263 | $result = @odbc_exec($this->connection, $query); |
264 | if (!$result) { |
264 | if (!$result) { |
265 | return $this->odbcRaiseError(); // XXX ERRORMSG |
265 | return $this->odbcRaiseError(); // XXX ERRORMSG |
266 | }
|
266 | }
|
267 | // Determine which queries that should return data, and which
|
267 | // Determine which queries that should return data, and which
|
268 | // should return an error code only.
|
268 | // should return an error code only.
|
269 | if ($this->_checkManip($query)) { |
269 | if ($this->_checkManip($query)) { |
270 | $this->affected = $result; // For affectedRows() |
270 | $this->affected = $result; // For affectedRows() |
271 | return DB_OK; |
271 | return DB_OK; |
272 | }
|
272 | }
|
273 | $this->affected = 0; |
273 | $this->affected = 0; |
274 | return $result; |
274 | return $result; |
275 | }
|
275 | }
|
276 | 276 | ||
277 | // }}}
|
277 | // }}}
|
278 | // {{{ nextResult()
|
278 | // {{{ nextResult()
|
279 | 279 | ||
280 | /**
|
280 | /**
|
281 | * Move the internal odbc result pointer to the next available result
|
281 | * Move the internal odbc result pointer to the next available result
|
282 | *
|
282 | *
|
283 | * @param a valid fbsql result resource
|
283 | * @param a valid fbsql result resource
|
284 | *
|
284 | *
|
285 | * @access public
|
285 | * @access public
|
286 | *
|
286 | *
|
287 | * @return true if a result is available otherwise return false
|
287 | * @return true if a result is available otherwise return false
|
288 | */
|
288 | */
|
289 | function nextResult($result) |
289 | function nextResult($result) |
290 | {
|
290 | {
|
291 | return @odbc_next_result($result); |
291 | return @odbc_next_result($result); |
292 | }
|
292 | }
|
293 | 293 | ||
294 | // }}}
|
294 | // }}}
|
295 | // {{{ fetchInto()
|
295 | // {{{ fetchInto()
|
296 | 296 | ||
297 | /**
|
297 | /**
|
298 | * Places a row from the result set into the given array
|
298 | * Places a row from the result set into the given array
|
299 | *
|
299 | *
|
300 | * Formating of the array and the data therein are configurable.
|
300 | * Formating of the array and the data therein are configurable.
|
301 | * See DB_result::fetchInto() for more information.
|
301 | * See DB_result::fetchInto() for more information.
|
302 | *
|
302 | *
|
303 | * This method is not meant to be called directly. Use
|
303 | * This method is not meant to be called directly. Use
|
304 | * DB_result::fetchInto() instead. It can't be declared "protected"
|
304 | * DB_result::fetchInto() instead. It can't be declared "protected"
|
305 | * because DB_result is a separate object.
|
305 | * because DB_result is a separate object.
|
306 | *
|
306 | *
|
307 | * @param resource $result the query result resource
|
307 | * @param resource $result the query result resource
|
308 | * @param array $arr the referenced array to put the data in
|
308 | * @param array $arr the referenced array to put the data in
|
309 | * @param int $fetchmode how the resulting array should be indexed
|
309 | * @param int $fetchmode how the resulting array should be indexed
|
310 | * @param int $rownum the row number to fetch (0 = first row)
|
310 | * @param int $rownum the row number to fetch (0 = first row)
|
311 | *
|
311 | *
|
312 | * @return mixed DB_OK on success, NULL when the end of a result set is
|
312 | * @return mixed DB_OK on success, NULL when the end of a result set is
|
313 | * reached or on failure
|
313 | * reached or on failure
|
314 | *
|
314 | *
|
315 | * @see DB_result::fetchInto()
|
315 | * @see DB_result::fetchInto()
|
316 | */
|
316 | */
|
317 | function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
317 | function fetchInto($result, &$arr, $fetchmode, $rownum = null) |
318 | {
|
318 | {
|
319 | $arr = array(); |
319 | $arr = array(); |
320 | if ($rownum !== null) { |
320 | if ($rownum !== null) { |
321 | $rownum++; // ODBC first row is 1 |
321 | $rownum++; // ODBC first row is 1 |
322 | if (version_compare(phpversion(), '4.2.0', 'ge')) { |
322 | if (version_compare(phpversion(), '4.2.0', 'ge')) { |
323 | $cols = @odbc_fetch_into($result, $arr, $rownum); |
323 | $cols = @odbc_fetch_into($result, $arr, $rownum); |
324 | } else { |
324 | } else { |
325 | $cols = @odbc_fetch_into($result, $rownum, $arr); |
325 | $cols = @odbc_fetch_into($result, $rownum, $arr); |
326 | }
|
326 | }
|
327 | } else { |
327 | } else { |
328 | $cols = @odbc_fetch_into($result, $arr); |
328 | $cols = @odbc_fetch_into($result, $arr); |
329 | }
|
329 | }
|
330 | if (!$cols) { |
330 | if (!$cols) { |
331 | return null; |
331 | return null; |
332 | }
|
332 | }
|
333 | if ($fetchmode !== DB_FETCHMODE_ORDERED) { |
333 | if ($fetchmode !== DB_FETCHMODE_ORDERED) { |
334 | for ($i = 0; $i < count($arr); $i++) { |
334 | for ($i = 0; $i < count($arr); $i++) { |
335 | $colName = @odbc_field_name($result, $i+1); |
335 | $colName = @odbc_field_name($result, $i+1); |
336 | $a[$colName] = $arr[$i]; |
336 | $a[$colName] = $arr[$i]; |
337 | }
|
337 | }
|
338 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
338 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
339 | $a = array_change_key_case($a, CASE_LOWER); |
339 | $a = array_change_key_case($a, CASE_LOWER); |
340 | }
|
340 | }
|
341 | $arr = $a; |
341 | $arr = $a; |
342 | }
|
342 | }
|
343 | if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
343 | if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { |
344 | $this->_rtrimArrayValues($arr); |
344 | $this->_rtrimArrayValues($arr); |
345 | }
|
345 | }
|
346 | if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
346 | if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { |
347 | $this->_convertNullArrayValuesToEmpty($arr); |
347 | $this->_convertNullArrayValuesToEmpty($arr); |
348 | }
|
348 | }
|
349 | return DB_OK; |
349 | return DB_OK; |
350 | }
|
350 | }
|
351 | 351 | ||
352 | // }}}
|
352 | // }}}
|
353 | // {{{ freeResult()
|
353 | // {{{ freeResult()
|
354 | 354 | ||
355 | /**
|
355 | /**
|
356 | * Deletes the result set and frees the memory occupied by the result set
|
356 | * Deletes the result set and frees the memory occupied by the result set
|
357 | *
|
357 | *
|
358 | * This method is not meant to be called directly. Use
|
358 | * This method is not meant to be called directly. Use
|
359 | * DB_result::free() instead. It can't be declared "protected"
|
359 | * DB_result::free() instead. It can't be declared "protected"
|
360 | * because DB_result is a separate object.
|
360 | * because DB_result is a separate object.
|
361 | *
|
361 | *
|
362 | * @param resource $result PHP's query result resource
|
362 | * @param resource $result PHP's query result resource
|
363 | *
|
363 | *
|
364 | * @return bool TRUE on success, FALSE if $result is invalid
|
364 | * @return bool TRUE on success, FALSE if $result is invalid
|
365 | *
|
365 | *
|
366 | * @see DB_result::free()
|
366 | * @see DB_result::free()
|
367 | */
|
367 | */
|
368 | function freeResult($result) |
368 | function freeResult($result) |
369 | {
|
369 | {
|
370 | return is_resource($result) ? odbc_free_result($result) : false; |
370 | return is_resource($result) ? odbc_free_result($result) : false; |
371 | }
|
371 | }
|
372 | 372 | ||
373 | // }}}
|
373 | // }}}
|
374 | // {{{ numCols()
|
374 | // {{{ numCols()
|
375 | 375 | ||
376 | /**
|
376 | /**
|
377 | * Gets the number of columns in a result set
|
377 | * Gets the number of columns in a result set
|
378 | *
|
378 | *
|
379 | * This method is not meant to be called directly. Use
|
379 | * This method is not meant to be called directly. Use
|
380 | * DB_result::numCols() instead. It can't be declared "protected"
|
380 | * DB_result::numCols() instead. It can't be declared "protected"
|
381 | * because DB_result is a separate object.
|
381 | * because DB_result is a separate object.
|
382 | *
|
382 | *
|
383 | * @param resource $result PHP's query result resource
|
383 | * @param resource $result PHP's query result resource
|
384 | *
|
384 | *
|
385 | * @return int the number of columns. A DB_Error object on failure.
|
385 | * @return int the number of columns. A DB_Error object on failure.
|
386 | *
|
386 | *
|
387 | * @see DB_result::numCols()
|
387 | * @see DB_result::numCols()
|
388 | */
|
388 | */
|
389 | function numCols($result) |
389 | function numCols($result) |
390 | {
|
390 | {
|
391 | $cols = @odbc_num_fields($result); |
391 | $cols = @odbc_num_fields($result); |
392 | if (!$cols) { |
392 | if (!$cols) { |
393 | return $this->odbcRaiseError(); |
393 | return $this->odbcRaiseError(); |
394 | }
|
394 | }
|
395 | return $cols; |
395 | return $cols; |
396 | }
|
396 | }
|
397 | 397 | ||
398 | // }}}
|
398 | // }}}
|
399 | // {{{ affectedRows()
|
399 | // {{{ affectedRows()
|
400 | 400 | ||
401 | /**
|
401 | /**
|
402 | * Determines the number of rows affected by a data maniuplation query
|
402 | * Determines the number of rows affected by a data maniuplation query
|
403 | *
|
403 | *
|
404 | * 0 is returned for queries that don't manipulate data.
|
404 | * 0 is returned for queries that don't manipulate data.
|
405 | *
|
405 | *
|
406 | * @return int the number of rows. A DB_Error object on failure.
|
406 | * @return int the number of rows. A DB_Error object on failure.
|
407 | */
|
407 | */
|
408 | function affectedRows() |
408 | function affectedRows() |
409 | {
|
409 | {
|
410 | if (empty($this->affected)) { // In case of SELECT stms |
410 | if (empty($this->affected)) { // In case of SELECT stms |
411 | return 0; |
411 | return 0; |
412 | }
|
412 | }
|
413 | $nrows = @odbc_num_rows($this->affected); |
413 | $nrows = @odbc_num_rows($this->affected); |
414 | if ($nrows == -1) { |
414 | if ($nrows == -1) { |
415 | return $this->odbcRaiseError(); |
415 | return $this->odbcRaiseError(); |
416 | }
|
416 | }
|
417 | return $nrows; |
417 | return $nrows; |
418 | }
|
418 | }
|
419 | 419 | ||
420 | // }}}
|
420 | // }}}
|
421 | // {{{ numRows()
|
421 | // {{{ numRows()
|
422 | 422 | ||
423 | /**
|
423 | /**
|
424 | * Gets the number of rows in a result set
|
424 | * Gets the number of rows in a result set
|
425 | *
|
425 | *
|
426 | * Not all ODBC drivers support this functionality. If they don't
|
426 | * Not all ODBC drivers support this functionality. If they don't
|
427 | * a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
|
427 | * a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
|
428 | *
|
428 | *
|
429 | * This method is not meant to be called directly. Use
|
429 | * This method is not meant to be called directly. Use
|
430 | * DB_result::numRows() instead. It can't be declared "protected"
|
430 | * DB_result::numRows() instead. It can't be declared "protected"
|
431 | * because DB_result is a separate object.
|
431 | * because DB_result is a separate object.
|
432 | *
|
432 | *
|
433 | * @param resource $result PHP's query result resource
|
433 | * @param resource $result PHP's query result resource
|
434 | *
|
434 | *
|
435 | * @return int the number of rows. A DB_Error object on failure.
|
435 | * @return int the number of rows. A DB_Error object on failure.
|
436 | *
|
436 | *
|
437 | * @see DB_result::numRows()
|
437 | * @see DB_result::numRows()
|
438 | */
|
438 | */
|
439 | function numRows($result) |
439 | function numRows($result) |
440 | {
|
440 | {
|
441 | $nrows = @odbc_num_rows($result); |
441 | $nrows = @odbc_num_rows($result); |
442 | if ($nrows == -1) { |
442 | if ($nrows == -1) { |
443 | return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED); |
443 | return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED); |
444 | }
|
444 | }
|
445 | if ($nrows === false) { |
445 | if ($nrows === false) { |
446 | return $this->odbcRaiseError(); |
446 | return $this->odbcRaiseError(); |
447 | }
|
447 | }
|
448 | return $nrows; |
448 | return $nrows; |
449 | }
|
449 | }
|
450 | 450 | ||
451 | // }}}
|
451 | // }}}
|
452 | // {{{ quoteIdentifier()
|
452 | // {{{ quoteIdentifier()
|
453 | 453 | ||
454 | /**
|
454 | /**
|
455 | * Quotes a string so it can be safely used as a table or column name
|
455 | * Quotes a string so it can be safely used as a table or column name
|
456 | *
|
456 | *
|
457 | * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
|
457 | * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
|
458 | * "Use ANSI quoted identifiers" when setting up the ODBC data source.
|
458 | * "Use ANSI quoted identifiers" when setting up the ODBC data source.
|
459 | *
|
459 | *
|
460 | * @param string $str identifier name to be quoted
|
460 | * @param string $str identifier name to be quoted
|
461 | *
|
461 | *
|
462 | * @return string quoted identifier string
|
462 | * @return string quoted identifier string
|
463 | *
|
463 | *
|
464 | * @see DB_common::quoteIdentifier()
|
464 | * @see DB_common::quoteIdentifier()
|
465 | * @since Method available since Release 1.6.0
|
465 | * @since Method available since Release 1.6.0
|
466 | */
|
466 | */
|
467 | function quoteIdentifier($str) |
467 | function quoteIdentifier($str) |
468 | {
|
468 | {
|
469 | switch ($this->dsn['dbsyntax']) { |
469 | switch ($this->dsn['dbsyntax']) { |
470 | case 'access': |
470 | case 'access': |
471 | return '[' . $str . ']'; |
471 | return '[' . $str . ']'; |
472 | case 'mssql': |
472 | case 'mssql': |
473 | case 'sybase': |
473 | case 'sybase': |
474 | return '[' . str_replace(']', ']]', $str) . ']'; |
474 | return '[' . str_replace(']', ']]', $str) . ']'; |
475 | case 'mysql': |
475 | case 'mysql': |
476 | case 'mysqli': |
476 | case 'mysqli': |
477 | return '`' . $str . '`'; |
477 | return '`' . $str . '`'; |
478 | default: |
478 | default: |
479 | return '"' . str_replace('"', '""', $str) . '"'; |
479 | return '"' . str_replace('"', '""', $str) . '"'; |
480 | }
|
480 | }
|
481 | }
|
481 | }
|
482 | 482 | ||
483 | // }}}
|
483 | // }}}
|
484 | // {{{ quote()
|
484 | // {{{ quote()
|
485 | 485 | ||
486 | /**
|
486 | /**
|
487 | * @deprecated Deprecated in release 1.6.0
|
487 | * @deprecated Deprecated in release 1.6.0
|
488 | * @internal
|
488 | * @internal
|
489 | */
|
489 | */
|
490 | function quote($str) |
490 | function quote($str) |
491 | {
|
491 | {
|
492 | return $this->quoteSmart($str); |
492 | return $this->quoteSmart($str); |
493 | }
|
493 | }
|
494 | 494 | ||
495 | // }}}
|
495 | // }}}
|
496 | // {{{ nextId()
|
496 | // {{{ nextId()
|
497 | 497 | ||
498 | /**
|
498 | /**
|
499 | * Returns the next free id in a sequence
|
499 | * Returns the next free id in a sequence
|
500 | *
|
500 | *
|
501 | * @param string $seq_name name of the sequence
|
501 | * @param string $seq_name name of the sequence
|
502 | * @param boolean $ondemand when true, the seqence is automatically
|
502 | * @param boolean $ondemand when true, the seqence is automatically
|
503 | * created if it does not exist
|
503 | * created if it does not exist
|
504 | *
|
504 | *
|
505 | * @return int the next id number in the sequence.
|
505 | * @return int the next id number in the sequence.
|
506 | * A DB_Error object on failure.
|
506 | * A DB_Error object on failure.
|
507 | *
|
507 | *
|
508 | * @see DB_common::nextID(), DB_common::getSequenceName(),
|
508 | * @see DB_common::nextID(), DB_common::getSequenceName(),
|
509 | * DB_odbc::createSequence(), DB_odbc::dropSequence()
|
509 | * DB_odbc::createSequence(), DB_odbc::dropSequence()
|
510 | */
|
510 | */
|
511 | function nextId($seq_name, $ondemand = true) |
511 | function nextId($seq_name, $ondemand = true) |
512 | {
|
512 | {
|
513 | $seqname = $this->getSequenceName($seq_name); |
513 | $seqname = $this->getSequenceName($seq_name); |
514 | $repeat = 0; |
514 | $repeat = 0; |
515 | do { |
515 | do { |
516 | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
516 | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
517 | $result = $this->query("update ${seqname} set id = id + 1"); |
517 | $result = $this->query("update ${seqname} set id = id + 1"); |
518 | $this->popErrorHandling(); |
518 | $this->popErrorHandling(); |
519 | if ($ondemand && DB::isError($result) && |
519 | if ($ondemand && DB::isError($result) && |
520 | $result->getCode() == DB_ERROR_NOSUCHTABLE) { |
520 | $result->getCode() == DB_ERROR_NOSUCHTABLE) { |
521 | $repeat = 1; |
521 | $repeat = 1; |
522 | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
522 | $this->pushErrorHandling(PEAR_ERROR_RETURN); |
523 | $result = $this->createSequence($seq_name); |
523 | $result = $this->createSequence($seq_name); |
524 | $this->popErrorHandling(); |
524 | $this->popErrorHandling(); |
525 | if (DB::isError($result)) { |
525 | if (DB::isError($result)) { |
526 | return $this->raiseError($result); |
526 | return $this->raiseError($result); |
527 | }
|
527 | }
|
528 | $result = $this->query("insert into ${seqname} (id) values(0)"); |
528 | $result = $this->query("insert into ${seqname} (id) values(0)"); |
529 | } else { |
529 | } else { |
530 | $repeat = 0; |
530 | $repeat = 0; |
531 | }
|
531 | }
|
532 | } while ($repeat); |
532 | } while ($repeat); |
533 | 533 | ||
534 | if (DB::isError($result)) { |
534 | if (DB::isError($result)) { |
535 | return $this->raiseError($result); |
535 | return $this->raiseError($result); |
536 | }
|
536 | }
|
537 | 537 | ||
538 | $result = $this->query("select id from ${seqname}"); |
538 | $result = $this->query("select id from ${seqname}"); |
539 | if (DB::isError($result)) { |
539 | if (DB::isError($result)) { |
540 | return $result; |
540 | return $result; |
541 | }
|
541 | }
|
542 | 542 | ||
543 | $row = $result->fetchRow(DB_FETCHMODE_ORDERED); |
543 | $row = $result->fetchRow(DB_FETCHMODE_ORDERED); |
544 | if (DB::isError($row || !$row)) { |
544 | if (DB::isError($row || !$row)) { |
545 | return $row; |
545 | return $row; |
546 | }
|
546 | }
|
547 | 547 | ||
548 | return $row[0]; |
548 | return $row[0]; |
549 | }
|
549 | }
|
550 | 550 | ||
551 | /**
|
551 | /**
|
552 | * Creates a new sequence
|
552 | * Creates a new sequence
|
553 | *
|
553 | *
|
554 | * @param string $seq_name name of the new sequence
|
554 | * @param string $seq_name name of the new sequence
|
555 | *
|
555 | *
|
556 | * @return int DB_OK on success. A DB_Error object on failure.
|
556 | * @return int DB_OK on success. A DB_Error object on failure.
|
557 | *
|
557 | *
|
558 | * @see DB_common::createSequence(), DB_common::getSequenceName(),
|
558 | * @see DB_common::createSequence(), DB_common::getSequenceName(),
|
559 | * DB_odbc::nextID(), DB_odbc::dropSequence()
|
559 | * DB_odbc::nextID(), DB_odbc::dropSequence()
|
560 | */
|
560 | */
|
561 | function createSequence($seq_name) |
561 | function createSequence($seq_name) |
562 | {
|
562 | {
|
563 | return $this->query('CREATE TABLE ' |
563 | return $this->query('CREATE TABLE ' |
564 | . $this->getSequenceName($seq_name) |
564 | . $this->getSequenceName($seq_name) |
565 | . ' (id integer NOT NULL,' |
565 | . ' (id integer NOT NULL,' |
566 | . ' PRIMARY KEY(id))'); |
566 | . ' PRIMARY KEY(id))'); |
567 | }
|
567 | }
|
568 | 568 | ||
569 | // }}}
|
569 | // }}}
|
570 | // {{{ dropSequence()
|
570 | // {{{ dropSequence()
|
571 | 571 | ||
572 | /**
|
572 | /**
|
573 | * Deletes a sequence
|
573 | * Deletes a sequence
|
574 | *
|
574 | *
|
575 | * @param string $seq_name name of the sequence to be deleted
|
575 | * @param string $seq_name name of the sequence to be deleted
|
576 | *
|
576 | *
|
577 | * @return int DB_OK on success. A DB_Error object on failure.
|
577 | * @return int DB_OK on success. A DB_Error object on failure.
|
578 | *
|
578 | *
|
579 | * @see DB_common::dropSequence(), DB_common::getSequenceName(),
|
579 | * @see DB_common::dropSequence(), DB_common::getSequenceName(),
|
580 | * DB_odbc::nextID(), DB_odbc::createSequence()
|
580 | * DB_odbc::nextID(), DB_odbc::createSequence()
|
581 | */
|
581 | */
|
582 | function dropSequence($seq_name) |
582 | function dropSequence($seq_name) |
583 | {
|
583 | {
|
584 | return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
584 | return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); |
585 | }
|
585 | }
|
586 | 586 | ||
587 | // }}}
|
587 | // }}}
|
588 | // {{{ autoCommit()
|
588 | // {{{ autoCommit()
|
589 | 589 | ||
590 | /**
|
590 | /**
|
591 | * Enables or disables automatic commits
|
591 | * Enables or disables automatic commits
|
592 | *
|
592 | *
|
593 | * @param bool $onoff true turns it on, false turns it off
|
593 | * @param bool $onoff true turns it on, false turns it off
|
594 | *
|
594 | *
|
595 | * @return int DB_OK on success. A DB_Error object if the driver
|
595 | * @return int DB_OK on success. A DB_Error object if the driver
|
596 | * doesn't support auto-committing transactions.
|
596 | * doesn't support auto-committing transactions.
|
597 | */
|
597 | */
|
598 | function autoCommit($onoff = false) |
598 | function autoCommit($onoff = false) |
599 | {
|
599 | {
|
600 | if (!@odbc_autocommit($this->connection, $onoff)) { |
600 | if (!@odbc_autocommit($this->connection, $onoff)) { |
601 | return $this->odbcRaiseError(); |
601 | return $this->odbcRaiseError(); |
602 | }
|
602 | }
|
603 | return DB_OK; |
603 | return DB_OK; |
604 | }
|
604 | }
|
605 | 605 | ||
606 | // }}}
|
606 | // }}}
|
607 | // {{{ commit()
|
607 | // {{{ commit()
|
608 | 608 | ||
609 | /**
|
609 | /**
|
610 | * Commits the current transaction
|
610 | * Commits the current transaction
|
611 | *
|
611 | *
|
612 | * @return int DB_OK on success. A DB_Error object on failure.
|
612 | * @return int DB_OK on success. A DB_Error object on failure.
|
613 | */
|
613 | */
|
614 | function commit() |
614 | function commit() |
615 | {
|
615 | {
|
616 | if (!@odbc_commit($this->connection)) { |
616 | if (!@odbc_commit($this->connection)) { |
617 | return $this->odbcRaiseError(); |
617 | return $this->odbcRaiseError(); |
618 | }
|
618 | }
|
619 | return DB_OK; |
619 | return DB_OK; |
620 | }
|
620 | }
|
621 | 621 | ||
622 | // }}}
|
622 | // }}}
|
623 | // {{{ rollback()
|
623 | // {{{ rollback()
|
624 | 624 | ||
625 | /**
|
625 | /**
|
626 | * Reverts the current transaction
|
626 | * Reverts the current transaction
|
627 | *
|
627 | *
|
628 | * @return int DB_OK on success. A DB_Error object on failure.
|
628 | * @return int DB_OK on success. A DB_Error object on failure.
|
629 | */
|
629 | */
|
630 | function rollback() |
630 | function rollback() |
631 | {
|
631 | {
|
632 | if (!@odbc_rollback($this->connection)) { |
632 | if (!@odbc_rollback($this->connection)) { |
633 | return $this->odbcRaiseError(); |
633 | return $this->odbcRaiseError(); |
634 | }
|
634 | }
|
635 | return DB_OK; |
635 | return DB_OK; |
636 | }
|
636 | }
|
637 | 637 | ||
638 | // }}}
|
638 | // }}}
|
639 | // {{{ odbcRaiseError()
|
639 | // {{{ odbcRaiseError()
|
640 | 640 | ||
641 | /**
|
641 | /**
|
642 | * Produces a DB_Error object regarding the current problem
|
642 | * Produces a DB_Error object regarding the current problem
|
643 | *
|
643 | *
|
644 | * @param int $errno if the error is being manually raised pass a
|
644 | * @param int $errno if the error is being manually raised pass a
|
645 | * DB_ERROR* constant here. If this isn't passed
|
645 | * DB_ERROR* constant here. If this isn't passed
|
646 | * the error information gathered from the DBMS.
|
646 | * the error information gathered from the DBMS.
|
647 | *
|
647 | *
|
648 | * @return object the DB_Error object
|
648 | * @return object the DB_Error object
|
649 | *
|
649 | *
|
650 | * @see DB_common::raiseError(),
|
650 | * @see DB_common::raiseError(),
|
651 | * DB_odbc::errorNative(), DB_common::errorCode()
|
651 | * DB_odbc::errorNative(), DB_common::errorCode()
|
652 | */
|
652 | */
|
653 | function odbcRaiseError($errno = null) |
653 | function odbcRaiseError($errno = null) |
654 | {
|
654 | {
|
655 | if ($errno === null) { |
655 | if ($errno === null) { |
656 | switch ($this->dbsyntax) { |
656 | switch ($this->dbsyntax) { |
657 | case 'access': |
657 | case 'access': |
658 | if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { |
658 | if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { |
659 | $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD; |
659 | $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD; |
660 | } else { |
660 | } else { |
661 | // Doing this in case mode changes during runtime.
|
661 | // Doing this in case mode changes during runtime.
|
662 | $this->errorcode_map['07001'] = DB_ERROR_MISMATCH; |
662 | $this->errorcode_map['07001'] = DB_ERROR_MISMATCH; |
663 | }
|
663 | }
|
664 | 664 | ||
665 | $native_code = odbc_error($this->connection); |
665 | $native_code = odbc_error($this->connection); |
666 | 666 | ||
667 | // S1000 is for "General Error." Let's be more specific.
|
667 | // S1000 is for "General Error." Let's be more specific.
|
668 | if ($native_code == 'S1000') { |
668 | if ($native_code == 'S1000') { |
669 | $errormsg = odbc_errormsg($this->connection); |
669 | $errormsg = odbc_errormsg($this->connection); |
670 | static $error_regexps; |
670 | static $error_regexps; |
671 | if (!isset($error_regexps)) { |
671 | if (!isset($error_regexps)) { |
672 | $error_regexps = array( |
672 | $error_regexps = array( |
673 | '/includes related records.$/i' => DB_ERROR_CONSTRAINT, |
673 | '/includes related records.$/i' => DB_ERROR_CONSTRAINT, |
674 | '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL, |
674 | '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL, |
675 | ); |
675 | ); |
676 | }
|
676 | }
|
677 | foreach ($error_regexps as $regexp => $code) { |
677 | foreach ($error_regexps as $regexp => $code) { |
678 | if (preg_match($regexp, $errormsg)) { |
678 | if (preg_match($regexp, $errormsg)) { |
679 | return $this->raiseError($code, |
679 | return $this->raiseError($code, |
680 | null, null, null, |
680 | null, null, null, |
681 | $native_code . ' ' . $errormsg); |
681 | $native_code . ' ' . $errormsg); |
682 | }
|
682 | }
|
683 | }
|
683 | }
|
684 | $errno = DB_ERROR; |
684 | $errno = DB_ERROR; |
685 | } else { |
685 | } else { |
686 | $errno = $this->errorCode($native_code); |
686 | $errno = $this->errorCode($native_code); |
687 | }
|
687 | }
|
688 | break; |
688 | break; |
689 | default: |
689 | default: |
690 | $errno = $this->errorCode(odbc_error($this->connection)); |
690 | $errno = $this->errorCode(odbc_error($this->connection)); |
691 | }
|
691 | }
|
692 | }
|
692 | }
|
693 | return $this->raiseError($errno, null, null, null, |
693 | return $this->raiseError($errno, null, null, null, |
694 | $this->errorNative()); |
694 | $this->errorNative()); |
695 | }
|
695 | }
|
696 | 696 | ||
697 | // }}}
|
697 | // }}}
|
698 | // {{{ errorNative()
|
698 | // {{{ errorNative()
|
699 | 699 | ||
700 | /**
|
700 | /**
|
701 | * Gets the DBMS' native error code and message produced by the last query
|
701 | * Gets the DBMS' native error code and message produced by the last query
|
702 | *
|
702 | *
|
703 | * @return string the DBMS' error code and message
|
703 | * @return string the DBMS' error code and message
|
704 | */
|
704 | */
|
705 | function errorNative() |
705 | function errorNative() |
706 | {
|
706 | {
|
707 | if (!is_resource($this->connection)) { |
707 | if (!is_resource($this->connection)) { |
708 | return @odbc_error() . ' ' . @odbc_errormsg(); |
708 | return @odbc_error() . ' ' . @odbc_errormsg(); |
709 | }
|
709 | }
|
710 | return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection); |
710 | return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection); |
711 | }
|
711 | }
|
712 | 712 | ||
713 | // }}}
|
713 | // }}}
|
714 | // {{{ tableInfo()
|
714 | // {{{ tableInfo()
|
715 | 715 | ||
716 | /**
|
716 | /**
|
717 | * Returns information about a table or a result set
|
717 | * Returns information about a table or a result set
|
718 | *
|
718 | *
|
719 | * @param object|string $result DB_result object from a query or a
|
719 | * @param object|string $result DB_result object from a query or a
|
720 | * string containing the name of a table.
|
720 | * string containing the name of a table.
|
721 | * While this also accepts a query result
|
721 | * While this also accepts a query result
|
722 | * resource identifier, this behavior is
|
722 | * resource identifier, this behavior is
|
723 | * deprecated.
|
723 | * deprecated.
|
724 | * @param int $mode a valid tableInfo mode
|
724 | * @param int $mode a valid tableInfo mode
|
725 | *
|
725 | *
|
726 | * @return array an associative array with the information requested.
|
726 | * @return array an associative array with the information requested.
|
727 | * A DB_Error object on failure.
|
727 | * A DB_Error object on failure.
|
728 | *
|
728 | *
|
729 | * @see DB_common::tableInfo()
|
729 | * @see DB_common::tableInfo()
|
730 | * @since Method available since Release 1.7.0
|
730 | * @since Method available since Release 1.7.0
|
731 | */
|
731 | */
|
732 | function tableInfo($result, $mode = null) |
732 | function tableInfo($result, $mode = null) |
733 | {
|
733 | {
|
734 | if (is_string($result)) { |
734 | if (is_string($result)) { |
735 | /*
|
735 | /*
|
736 | * Probably received a table name.
|
736 | * Probably received a table name.
|
737 | * Create a result resource identifier.
|
737 | * Create a result resource identifier.
|
738 | */
|
738 | */
|
739 | $id = @odbc_exec($this->connection, "SELECT * FROM $result"); |
739 | $id = @odbc_exec($this->connection, "SELECT * FROM $result"); |
740 | if (!$id) { |
740 | if (!$id) { |
741 | return $this->odbcRaiseError(); |
741 | return $this->odbcRaiseError(); |
742 | }
|
742 | }
|
743 | $got_string = true; |
743 | $got_string = true; |
744 | } elseif (isset($result->result)) { |
744 | } elseif (isset($result->result)) { |
745 | /*
|
745 | /*
|
746 | * Probably received a result object.
|
746 | * Probably received a result object.
|
747 | * Extract the result resource identifier.
|
747 | * Extract the result resource identifier.
|
748 | */
|
748 | */
|
749 | $id = $result->result; |
749 | $id = $result->result; |
750 | $got_string = false; |
750 | $got_string = false; |
751 | } else { |
751 | } else { |
752 | /*
|
752 | /*
|
753 | * Probably received a result resource identifier.
|
753 | * Probably received a result resource identifier.
|
754 | * Copy it.
|
754 | * Copy it.
|
755 | * Deprecated. Here for compatibility only.
|
755 | * Deprecated. Here for compatibility only.
|
756 | */
|
756 | */
|
757 | $id = $result; |
757 | $id = $result; |
758 | $got_string = false; |
758 | $got_string = false; |
759 | }
|
759 | }
|
760 | 760 | ||
761 | if (!is_resource($id)) { |
761 | if (!is_resource($id)) { |
762 | return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA); |
762 | return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA); |
763 | }
|
763 | }
|
764 | 764 | ||
765 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
765 | if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { |
766 | $case_func = 'strtolower'; |
766 | $case_func = 'strtolower'; |
767 | } else { |
767 | } else { |
768 | $case_func = 'strval'; |
768 | $case_func = 'strval'; |
769 | }
|
769 | }
|
770 | 770 | ||
771 | $count = @odbc_num_fields($id); |
771 | $count = @odbc_num_fields($id); |
772 | $res = array(); |
772 | $res = array(); |
773 | 773 | ||
774 | if ($mode) { |
774 | if ($mode) { |
775 | $res['num_fields'] = $count; |
775 | $res['num_fields'] = $count; |
776 | }
|
776 | }
|
777 | 777 | ||
778 | for ($i = 0; $i < $count; $i++) { |
778 | for ($i = 0; $i < $count; $i++) { |
779 | $col = $i + 1; |
779 | $col = $i + 1; |
780 | $res[$i] = array( |
780 | $res[$i] = array( |
781 | 'table' => $got_string ? $case_func($result) : '', |
781 | 'table' => $got_string ? $case_func($result) : '', |
782 | 'name' => $case_func(@odbc_field_name($id, $col)), |
782 | 'name' => $case_func(@odbc_field_name($id, $col)), |
783 | 'type' => @odbc_field_type($id, $col), |
783 | 'type' => @odbc_field_type($id, $col), |
784 | 'len' => @odbc_field_len($id, $col), |
784 | 'len' => @odbc_field_len($id, $col), |
785 | 'flags' => '', |
785 | 'flags' => '', |
786 | ); |
786 | ); |
787 | if ($mode & DB_TABLEINFO_ORDER) { |
787 | if ($mode & DB_TABLEINFO_ORDER) { |
788 | $res['order'][$res[$i]['name']] = $i; |
788 | $res['order'][$res[$i]['name']] = $i; |
789 | }
|
789 | }
|
790 | if ($mode & DB_TABLEINFO_ORDERTABLE) { |
790 | if ($mode & DB_TABLEINFO_ORDERTABLE) { |
791 | $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
791 | $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; |
792 | }
|
792 | }
|
793 | }
|
793 | }
|
794 | 794 | ||
795 | // free the result only if we were called on a table
|
795 | // free the result only if we were called on a table
|
796 | if ($got_string) { |
796 | if ($got_string) { |
797 | @odbc_free_result($id); |
797 | @odbc_free_result($id); |
798 | }
|
798 | }
|
799 | return $res; |
799 | return $res; |
800 | }
|
800 | }
|
801 | 801 | ||
802 | // }}}
|
802 | // }}}
|
803 | // {{{ getSpecialQuery()
|
803 | // {{{ getSpecialQuery()
|
804 | 804 | ||
805 | /**
|
805 | /**
|
806 | * Obtains the query string needed for listing a given type of objects
|
806 | * Obtains the query string needed for listing a given type of objects
|
807 | *
|
807 | *
|
808 | * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
|
808 | * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
|
809 | *
|
809 | *
|
810 | * @param string $type the kind of objects you want to retrieve
|
810 | * @param string $type the kind of objects you want to retrieve
|
811 | *
|
811 | *
|
812 | * @return string the list of objects requested
|
812 | * @return string the list of objects requested
|
813 | *
|
813 | *
|
814 | * @access protected
|
814 | * @access protected
|
815 | * @see DB_common::getListOf()
|
815 | * @see DB_common::getListOf()
|
816 | * @since Method available since Release 1.7.0
|
816 | * @since Method available since Release 1.7.0
|
817 | */
|
817 | */
|
818 | function getSpecialQuery($type) |
818 | function getSpecialQuery($type) |
819 | {
|
819 | {
|
820 | switch ($type) { |
820 | switch ($type) { |
821 | case 'databases': |
821 | case 'databases': |
822 | if (!function_exists('odbc_data_source')) { |
822 | if (!function_exists('odbc_data_source')) { |
823 | return null; |
823 | return null; |
824 | }
|
824 | }
|
825 | $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST); |
825 | $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST); |
826 | if (is_array($res)) { |
826 | if (is_array($res)) { |
827 | $out = array($res['server']); |
827 | $out = array($res['server']); |
828 | while($res = @odbc_data_source($this->connection, |
828 | while($res = @odbc_data_source($this->connection, |
829 | SQL_FETCH_NEXT)) |
829 | SQL_FETCH_NEXT)) |
830 | {
|
830 | {
|
831 | $out[] = $res['server']; |
831 | $out[] = $res['server']; |
832 | }
|
832 | }
|
833 | return $out; |
833 | return $out; |
834 | } else { |
834 | } else { |
835 | return $this->odbcRaiseError(); |
835 | return $this->odbcRaiseError(); |
836 | }
|
836 | }
|
837 | break; |
837 | break; |
838 | case 'tables': |
838 | case 'tables': |
839 | case 'schema.tables': |
839 | case 'schema.tables': |
840 | $keep = 'TABLE'; |
840 | $keep = 'TABLE'; |
841 | break; |
841 | break; |
842 | case 'views': |
842 | case 'views': |
843 | $keep = 'VIEW'; |
843 | $keep = 'VIEW'; |
844 | break; |
844 | break; |
845 | default: |
845 | default: |
846 | return null; |
846 | return null; |
847 | }
|
847 | }
|
848 | 848 | ||
849 | /*
|
849 | /*
|
850 | * Removing non-conforming items in the while loop rather than
|
850 | * Removing non-conforming items in the while loop rather than
|
851 | * in the odbc_tables() call because some backends choke on this:
|
851 | * in the odbc_tables() call because some backends choke on this:
|
852 | * odbc_tables($this->connection, '', '', '', 'TABLE')
|
852 | * odbc_tables($this->connection, '', '', '', 'TABLE')
|
853 | */
|
853 | */
|
854 | $res = @odbc_tables($this->connection); |
854 | $res = @odbc_tables($this->connection); |
855 | if (!$res) { |
855 | if (!$res) { |
856 | return $this->odbcRaiseError(); |
856 | return $this->odbcRaiseError(); |
857 | }
|
857 | }
|
858 | $out = array(); |
858 | $out = array(); |
859 | while ($row = odbc_fetch_array($res)) { |
859 | while ($row = odbc_fetch_array($res)) { |
860 | if ($row['TABLE_TYPE'] != $keep) { |
860 | if ($row['TABLE_TYPE'] != $keep) { |
861 | continue; |
861 | continue; |
862 | }
|
862 | }
|
863 | if ($type == 'schema.tables') { |
863 | if ($type == 'schema.tables') { |
864 | $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME']; |
864 | $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME']; |
865 | } else { |
865 | } else { |
866 | $out[] = $row['TABLE_NAME']; |
866 | $out[] = $row['TABLE_NAME']; |
867 | }
|
867 | }
|
868 | }
|
868 | }
|
869 | return $out; |
869 | return $out; |
870 | }
|
870 | }
|
871 | 871 | ||
872 | // }}}
|
872 | // }}}
|
873 | 873 | ||
874 | }
|
874 | }
|
875 | 875 | ||
876 | /*
|
876 | /*
|
877 | * Local variables:
|
877 | * Local variables:
|
878 | * tab-width: 4
|
878 | * tab-width: 4
|
879 | * c-basic-offset: 4
|
879 | * c-basic-offset: 4
|
880 | * End:
|
880 | * End:
|
881 | */
|
881 | */
|
882 | 882 | ||
883 | ?>
|
883 | ?>
|
884 | 884 |