/[cvs]/nfo/php/libs/net.php.pear/DB/odbc.php
ViewVC logotype

Contents of /nfo/php/libs/net.php.pear/DB/odbc.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Tue Oct 29 19:11:41 2002 UTC (21 years, 8 months ago) by cvsjoko
Branch: MAIN
CVS Tags: HEAD
+ new pear-libraries

1 <?php
2 //
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4 |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Author: Stig Bakken <ssb@fast.no> |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: odbc.php,v 1.54 2002/02/28 08:27:11 sebastian Exp $
20 //
21 // Database independent query interface definition for PHP's ODBC
22 // extension.
23 //
24
25 //
26 // XXX legend:
27 // More info on ODBC errors could be found here:
28 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
29 //
30 // XXX ERRORMSG: The error message from the odbc function should
31 // be registered here.
32 //
33
34 require_once 'DB/common.php';
35
36 class DB_odbc extends DB_common
37 {
38 // {{{ properties
39
40 var $connection;
41 var $phptype, $dbsyntax;
42 var $row = array();
43
44 // }}}
45 // {{{ constructor
46
47 function DB_odbc()
48 {
49 $this->DB_common();
50 $this->phptype = 'odbc';
51 $this->dbsyntax = 'sql92';
52 $this->features = array(
53 'prepare' => true,
54 'pconnect' => true,
55 'transactions' => false,
56 'limit' => 'emulate'
57 );
58 $this->errorcode_map = array(
59 '01004' => DB_ERROR_TRUNCATED,
60 '07001' => DB_ERROR_MISMATCH,
61 '21S01' => DB_ERROR_MISMATCH,
62 '21S02' => DB_ERROR_MISMATCH,
63 '22003' => DB_ERROR_INVALID_NUMBER,
64 '22008' => DB_ERROR_INVALID_DATE,
65 '22012' => DB_ERROR_DIVZERO,
66 '23000' => DB_ERROR_CONSTRAINT,
67 '24000' => DB_ERROR_INVALID,
68 '34000' => DB_ERROR_INVALID,
69 '37000' => DB_ERROR_SYNTAX,
70 '42000' => DB_ERROR_SYNTAX,
71 'IM001' => DB_ERROR_UNSUPPORTED,
72 'S0000' => DB_ERROR_NOSUCHTABLE,
73 'S0001' => DB_ERROR_NOT_FOUND,
74 'S0002' => DB_ERROR_NOT_FOUND,
75 'S0011' => DB_ERROR_ALREADY_EXISTS,
76 'S0012' => DB_ERROR_NOT_FOUND,
77 'S0021' => DB_ERROR_ALREADY_EXISTS,
78 'S0022' => DB_ERROR_NOT_FOUND,
79 'S1009' => DB_ERROR_INVALID,
80 'S1090' => DB_ERROR_INVALID,
81 'S1C00' => DB_ERROR_NOT_CAPABLE
82 );
83 }
84
85 // }}}
86 // {{{ connect()
87
88 /**
89 * Connect to a database and log in as the specified user.
90 *
91 * @param $dsn the data source name (see DB::parseDSN for syntax)
92 * @param $persistent (optional) whether the connection should
93 * be persistent
94 *
95 * @return int DB_OK on success, a DB error code on failure
96 */
97 function connect($dsninfo, $persistent = false)
98 {
99 if (!DB::assertExtension('odbc'))
100 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
101
102 $this->dsn = $dsninfo;
103 if (!empty($dsninfo['dbsyntax'])) {
104 $this->dbsyntax = $dsninfo['dbsyntax'];
105 }
106 switch ($this->dbsyntax) {
107 case 'solid':
108 $this->features = array(
109 'prepare' => true,
110 'pconnect' => true,
111 'transactions' => true
112 );
113 $default_dsn = 'localhost';
114 break;
115 case 'navision':
116 // the Navision driver doesn't support fetch row by number
117 $this->features['limit'] = false;
118 break;
119 default:
120 break;
121 }
122 $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
123 $user = $dsninfo['username'];
124 $pw = $dsninfo['password'];
125 if ($this->provides('pconnect')) {
126 $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
127 } else {
128 $connect_function = 'odbc_connect';
129 }
130 $conn = @$connect_function($dbhost, $user, $pw);
131 if (!is_resource($conn)) {
132 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
133 null, $this->errorNative());
134 }
135 $this->connection = $conn;
136 return DB_OK;
137 }
138
139 // }}}
140 // {{{ disconnect()
141
142 function disconnect()
143 {
144 $err = @odbc_close($this->connection);
145 $this->connection = null;
146 return $err;
147 }
148
149 // }}}
150 // {{{ simpleQuery()
151
152 /**
153 * Send a query to ODBC and return the results as a ODBC resource
154 * identifier.
155 *
156 * @param $query the SQL query
157 *
158 * @return int returns a valid ODBC result for successful SELECT
159 * queries, DB_OK for other successful queries. A DB error code
160 * is returned on failure.
161 */
162 function simpleQuery($query)
163 {
164 $this->last_query = $query;
165 $query = $this->modifyQuery($query);
166 $result = @odbc_exec($this->connection, $query);
167 if (!$result) {
168 return $this->odbcRaiseError(); // XXX ERRORMSG
169 }
170 // Determine which queries that should return data, and which
171 // should return an error code only.
172 if (DB::isManip($query)) {
173 $this->manip_result = $result; // For affectedRows()
174 return DB_OK;
175 }
176 $this->row[$result] = 0;
177 $this->manip_result = 0;
178 return $result;
179 }
180
181 // }}}
182 // {{{ nextResult()
183
184 /**
185 * Move the internal odbc result pointer to the next available result
186 *
187 * @param a valid fbsql result resource
188 *
189 * @access public
190 *
191 * @return true if a result is available otherwise return false
192 */
193 function nextResult($result)
194 {
195 return odbc_next_result($result);
196 }
197
198 // }}}
199 // {{{ fetchRow()
200
201 function fetchRow($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
202 {
203 if ($fetchmode == DB_FETCHMODE_DEFAULT) {
204 $fetchmode = $this->fetchmode;
205 }
206 $res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
207 if ($res !== DB_OK) {
208 return $res;
209 }
210 return $arr;
211 }
212
213 // }}}
214 // {{{ fetchInto()
215
216 function fetchInto($result, &$row, $fetchmode, $rownum=null)
217 {
218 $row = array();
219 if ($rownum !== null) {
220 $rownum++; // ODBC first row is 1
221 if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
222 $cols = odbc_fetch_into($result, $rownum, &$row);
223 } else {
224 $cols = odbc_fetch_into($result, $rownum, $row);
225 }
226 } else {
227 if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
228 $cols = odbc_fetch_into($result, &$row);
229 } else {
230 $cols = odbc_fetch_into($result, $row);
231 }
232 }
233
234 if (!$cols) {
235 /* XXX FIXME: doesn't work with unixODBC and easysoft
236 (get corrupted $errno values)
237 if ($errno = odbc_error($this->connection)) {
238 return $this->RaiseError($errno);
239 }*/
240 return null;
241 }
242 if ($fetchmode !== DB_FETCHMODE_ORDERED) {
243 for ($i = 0; $i < count($row); $i++) {
244 $colName = odbc_field_name($result, $i+1);
245 $a[$colName] = $row[$i];
246 }
247 $row = $a;
248 }
249 return DB_OK;
250 }
251
252 // }}}
253 // {{{ freeResult()
254
255 function freeResult($result)
256 {
257 if (is_resource($result)) {
258 // Always return true
259 return odbc_free_result($result);
260 }
261 if (!isset($this->prepare_tokens[(int)$result])) {
262 return false;
263 }
264 unset($this->prepare_tokens[(int)$result]);
265 unset($this->prepare_types[(int)$result]);
266 return true;
267 }
268
269 // }}}
270 // {{{ numCols()
271
272 function numCols($result)
273 {
274 $cols = @odbc_num_fields($result);
275 if (!$cols) {
276 return $this->odbcRaiseError();
277 }
278 return $cols;
279 }
280
281 // }}}
282 // {{{ affectedRows()
283
284 /**
285 * Returns the number of rows affected by a manipulative query
286 * (INSERT, DELETE, UPDATE)
287 * @return mixed int affected rows, 0 when non manip queries or
288 * DB error on error
289 */
290 function affectedRows()
291 {
292 if (empty($this->manip_result)) { // In case of SELECT stms
293 return 0;
294 }
295 $nrows = odbc_num_rows($this->manip_result);
296 if ($nrows == -1) {
297 return $this->odbcRaiseError();
298 }
299 return $nrows;
300 }
301
302 // }}}
303 // {{{ numRows()
304
305 /**
306 * ODBC may or may not support counting rows in the result set of
307 * SELECTs.
308 *
309 * @param $result the odbc result resource
310 * @return the number of rows, or 0
311 */
312 function numRows($result)
313 {
314 $nrows = odbc_num_rows($result);
315 if ($nrows == -1) {
316 return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
317 }
318 return $nrows;
319 }
320
321 // }}}
322 // {{{ errorNative()
323
324 /**
325 * Get the native error code of the last error (if any) that
326 * occured on the current connection.
327 *
328 * @access public
329 *
330 * @return int ODBC error code
331 */
332
333 function errorNative()
334 {
335 if (!isset($this->connection) || !is_resource($this->connection)) {
336 return odbc_error() . ' ' . odbc_errormsg();
337 }
338 return odbc_error($this->connection) . ' ' . odbc_errormsg($this->connection);
339 }
340
341 // }}}
342 // {{{ nextId()
343
344 /**
345 * Get the next value in a sequence. We emulate sequences
346 * for odbc. Will create the sequence if it does not exist.
347 *
348 * @access public
349 *
350 * @param $seq_name the name of the sequence
351 *
352 * @param $ondemand whether to create the sequence table on demand
353 * (default is true)
354 *
355 * @return a sequence integer, or a DB error
356 */
357 function nextId($seq_name, $ondemand = true)
358 {
359 $seqname = $this->getSequenceName($seq_name);
360 $repeat = 0;
361 do {
362 $result = $this->query("update ${seqname} set id = id + 1");
363 if ($ondemand && DB::isError($result) &&
364 $result->getCode() == DB_ERROR_NOT_FOUND) {
365 $repeat = 1;
366 $result = $this->createSequence($seq_name);
367 if (DB::isError($result)) {
368 return $result;
369 }
370 $result = $this->query("insert into ${seqname} (id) values(0)");
371 } else {
372 $repeat = 0;
373 }
374 } while ($repeat);
375
376 if (DB::isError($result)) {
377 return $result;
378 }
379
380 $result = $this->query("select id from ${seqname}");
381 if (DB::isError($result)) {
382 return $result;
383 }
384
385 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
386 if (DB::isError($row || !$row)) {
387 return $row;
388 }
389
390 return $row['id'];
391 }
392
393 // }}}
394 // {{{ createSequence()
395
396 function createSequence($seq_name)
397 {
398 $seqname = $this->getSequenceName($seq_name);
399 return $this->query("CREATE TABLE ${seqname} ".
400 '(id bigint NOT NULL,'.
401 ' PRIMARY KEY(id))');
402 }
403
404 // }}}
405 // {{{ dropSequence()
406
407 function dropSequence($seq_name)
408 {
409 $seqname = $this->getSequenceName($seq_name);
410 return $this->query("DROP TABLE ${seqname}");
411 }
412
413 // }}}
414 // {{{ autoCommit()
415
416 function autoCommit($onoff = false)
417 {
418 if (!@odbc_autocommit($this->connection, $onoff)) {
419 return $this->odbcRaiseError();
420 }
421 return DB_OK;
422 }
423
424 // }}}
425 // {{{ commit()
426
427 function commit()
428 {
429 if (!@odbc_commit($this->connection)) {
430 return $this->odbcRaiseError();
431 }
432 return DB_OK;
433 }
434
435 // }}}
436 // {{{ rollback()
437
438 function rollback()
439 {
440 if (!@odbc_rollback($this->connection)) {
441 return $this->odbcRaiseError();
442 }
443 return DB_OK;
444 }
445
446 // }}}
447 // {{{ odbcRaiseError()
448
449 function odbcRaiseError($errno = null)
450 {
451 if ($errno === null) {
452 $errno = $this->errorCode(odbc_error($this->connection));
453 }
454 return $this->raiseError($errno, null, null, null,
455 $this->errorNative());
456 }
457
458 // }}}
459 // {{{ getSpecialQuery()
460
461 /**
462 * Returns the query needed to get some backend info
463 * @param string $type What kind of info you want to retrieve
464 * @return string The SQL query string
465 */
466 function getSpecialQuery($type)
467 {
468 switch ($type) {
469 case 'tables':
470 default:
471 return null;
472 }
473 return $sql;
474 }
475
476 // }}}
477
478 }
479
480 // Local variables:
481 // tab-width: 4
482 // c-basic-offset: 4
483 // End:
484 ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed