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

Contents of /nfo/php/libs/net.php.pear/DB/fbsql.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: Frank M. Kromann <frank@frontbase.com> |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: fbsql.php,v 1.14 2002/02/28 08:27:08 sebastian Exp $
20 //
21 // Database independent query interface definition for PHP's FrontBase
22 // extension.
23 //
24
25 //
26 // XXX legend:
27 //
28 // XXX ERRORMSG: The error message from the fbsql function should
29 // be registered here.
30 //
31
32 require_once "DB/common.php";
33
34 class DB_fbsql extends DB_common
35 {
36 // {{{ properties
37
38 var $connection;
39 var $phptype, $dbsyntax;
40 var $prepare_tokens = array();
41 var $prepare_types = array();
42 var $num_rows = array();
43 var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
44
45 // }}}
46 // {{{ constructor
47
48 /**
49 * DB_fbsql constructor.
50 *
51 * @access public
52 */
53
54 function DB_fbsql()
55 {
56 $this->DB_common();
57 $this->phptype = 'fbsql';
58 $this->dbsyntax = 'fbsql';
59 $this->features = array(
60 'prepare' => false,
61 'pconnect' => true,
62 'transactions' => true,
63 'limit' => 'emulate'
64 );
65 $this->errorcode_map = array(
66 1004 => DB_ERROR_CANNOT_CREATE,
67 1005 => DB_ERROR_CANNOT_CREATE,
68 1006 => DB_ERROR_CANNOT_CREATE,
69 1007 => DB_ERROR_ALREADY_EXISTS,
70 1008 => DB_ERROR_CANNOT_DROP,
71 1046 => DB_ERROR_NODBSELECTED,
72 1050 => DB_ERROR_ALREADY_EXISTS,
73 1051 => DB_ERROR_NOSUCHTABLE,
74 1054 => DB_ERROR_NOSUCHFIELD,
75 1062 => DB_ERROR_ALREADY_EXISTS,
76 1064 => DB_ERROR_SYNTAX,
77 1100 => DB_ERROR_NOT_LOCKED,
78 1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
79 1146 => DB_ERROR_NOSUCHTABLE,
80 );
81 }
82
83 // }}}
84
85 // {{{ connect()
86
87 /**
88 * Connect to a database and log in as the specified user.
89 *
90 * @param $dsn the data source name (see DB::parseDSN for syntax)
91 * @param $persistent (optional) whether the connection should
92 * be persistent
93 * @access public
94 * @return int DB_OK on success, a DB error on failure
95 */
96
97 function connect($dsninfo, $persistent = false)
98 {
99 if (!DB::assertExtension('fbsql'))
100 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
101
102 $this->dsn = $dsninfo;
103 $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
104 $user = $dsninfo['username'];
105 $pw = $dsninfo['password'];
106
107 $connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect';
108
109 ini_set('track_errors', true);
110 if ($dbhost && $user && $pw) {
111 $conn = @$connect_function($dbhost, $user, $pw);
112 } elseif ($dbhost && $user) {
113 $conn = @$connect_function($dbhost, $user);
114 } elseif ($dbhost) {
115 $conn = @$connect_function($dbhost);
116 } else {
117 $conn = false;
118 }
119 ini_restore("track_errors");
120 if (empty($conn)) {
121 if (empty($php_errormsg)) {
122 return $this->raiseError(DB_ERROR_CONNECT_FAILED);
123 } else {
124 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
125 null, $php_errormsg);
126 }
127 }
128
129 if ($dsninfo['database']) {
130 if (!fbsql_select_db($dsninfo['database'], $conn)) {
131 return $this->fbsqlRaiseError();
132 }
133 }
134
135 $this->connection = $conn;
136 return DB_OK;
137 }
138
139 // }}}
140 // {{{ disconnect()
141
142 /**
143 * Log out and disconnect from the database.
144 *
145 * @access public
146 *
147 * @return bool TRUE on success, FALSE if not connected.
148 */
149 function disconnect()
150 {
151 $ret = fbsql_close($this->connection);
152 $this->connection = null;
153 return $ret;
154 }
155
156 // }}}
157 // {{{ simpleQuery()
158
159 /**
160 * Send a query to fbsql and return the results as a fbsql resource
161 * identifier.
162 *
163 * @param the SQL query
164 *
165 * @access public
166 *
167 * @return mixed returns a valid fbsql result for successful SELECT
168 * queries, DB_OK for other successful queries. A DB error is
169 * returned on failure.
170 */
171 function simpleQuery($query)
172 {
173 $this->last_query = $query;
174 $query = $this->modifyQuery($query);
175 $result = @fbsql_query("$query;", $this->connection);
176 if (!$result) {
177 return $this->fbsqlRaiseError();
178 }
179 // Determine which queries that should return data, and which
180 // should return an error code only.
181 if (DB::isManip($query)) {
182 return DB_OK;
183 }
184 $numrows = $this->numrows($result);
185 if (is_object($numrows)) {
186 return $numrows;
187 }
188 $this->num_rows[$result] = $numrows;
189 return $result;
190 }
191
192 // }}}
193 // {{{ nextResult()
194
195 /**
196 * Move the internal fbsql result pointer to the next available result
197 *
198 * @param a valid fbsql result resource
199 *
200 * @access public
201 *
202 * @return true if a result is available otherwise return false
203 */
204 function nextResult($result)
205 {
206 return @fbsql_next_result($result);
207 }
208
209 // }}}
210 // {{{ fetchRow()
211
212 /**
213 * Fetch and return a row of data (it uses fetchInto for that)
214 * @param $result fbsql result identifier
215 * @param $fetchmode format of fetched row array
216 * @param $rownum the absolute row number to fetch
217 *
218 * @return array a row of data, or false on error
219 */
220 function fetchRow($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
221 {
222 if ($fetchmode == DB_FETCHMODE_DEFAULT) {
223 $fetchmode = $this->fetchmode;
224 }
225 $res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
226 if ($res !== DB_OK) {
227 return $res;
228 }
229 return $arr;
230 }
231
232 // }}}
233 // {{{ fetchInto()
234
235 /**
236 * Fetch a row and insert the data into an existing array.
237 *
238 * @param $result fbsql result identifier
239 * @param $arr (reference) array where data from the row is stored
240 * @param $fetchmode how the array data should be indexed
241 * @param $rownum the row number to fetch
242 * @access public
243 *
244 * @return int DB_OK on success, a DB error on failure
245 */
246 function fetchInto($result, &$arr, $fetchmode, $rownum=null)
247 {
248 if ($rownum !== null) {
249 if (!@fbsql_data_seek($result, $rownum)) {
250 return null;
251 }
252 }
253 if ($fetchmode & DB_FETCHMODE_ASSOC) {
254 $arr = @fbsql_fetch_array($result, FBSQL_ASSOC);
255 } else {
256 $arr = @fbsql_fetch_row($result);
257 }
258 if (!$arr) {
259 $errno = @fbsql_errno($this->connection);
260 if (!$errno) {
261 return NULL;
262 }
263 return $this->fbsqlRaiseError($errno);
264 }
265 return DB_OK;
266 }
267
268 // }}}
269 // {{{ freeResult()
270
271 /**
272 * Free the internal resources associated with $result.
273 *
274 * @param $result fbsql result identifier or DB statement identifier
275 *
276 * @access public
277 *
278 * @return bool TRUE on success, FALSE if $result is invalid
279 */
280 function freeResult($result)
281 {
282 if (is_resource($result)) {
283 return fbsql_free_result($result);
284 }
285
286 if (!isset($this->prepare_tokens[(int)$result])) {
287 return false;
288 }
289
290 unset($this->prepare_tokens[(int)$result]);
291 unset($this->prepare_types[(int)$result]);
292
293 return true;
294 }
295
296 // }}}
297 // {{{ autoCommit()
298
299 function autoCommit($onoff=false)
300 {
301 if ($onoff) {
302 $this->query("SET COMMIT TRUE");
303 } else {
304 $this->query("SET COMMIT FALSE");
305 }
306 }
307
308 // }}}
309 // {{{ commit()
310
311 function commit()
312 {
313 fbsql_commit();
314 }
315
316 // }}}
317 // {{{ rollback()
318
319 function rollback()
320 {
321 fbsql_rollback();
322 }
323
324 // }}}
325 // {{{ numCols()
326
327 /**
328 * Get the number of columns in a result set.
329 *
330 * @param $result fbsql result identifier
331 *
332 * @access public
333 *
334 * @return int the number of columns per row in $result
335 */
336 function numCols($result)
337 {
338 $cols = @fbsql_num_fields($result);
339
340 if (!$cols) {
341 return $this->fbsqlRaiseError();
342 }
343
344 return $cols;
345 }
346
347 // }}}
348 // {{{ numRows()
349
350 /**
351 * Get the number of rows in a result set.
352 *
353 * @param $result fbsql result identifier
354 *
355 * @access public
356 *
357 * @return int the number of rows in $result
358 */
359 function numRows($result)
360 {
361 $rows = @fbsql_num_rows($result);
362 if ($rows === null) {
363 return $this->fbsqlRaiseError();
364 }
365 return $rows;
366 }
367
368 // }}}
369 // {{{ affectedRows()
370
371 /**
372 * Gets the number of rows affected by the data manipulation
373 * query. For other queries, this function returns 0.
374 *
375 * @return number of rows affected by the last query
376 */
377
378 function affectedRows()
379 {
380 if (DB::isManip($this->last_query)) {
381 $result = @fbsql_affected_rows($this->connection);
382 } else {
383 $result = 0;
384 }
385 return $result;
386 }
387
388 // }}}
389 // {{{ errorNative()
390
391 /**
392 * Get the native error code of the last error (if any) that
393 * occured on the current connection.
394 *
395 * @access public
396 *
397 * @return int native fbsql error code
398 */
399
400 function errorNative()
401 {
402 return fbsql_errno($this->connection);
403 }
404
405 // }}}
406 // {{{ nextId()
407
408 /**
409 * Get the next value in a sequence. We emulate sequences
410 * for fbsql. Will create the sequence if it does not exist.
411 *
412 * @access public
413 *
414 * @param $seq_name the name of the sequence
415 *
416 * @param $ondemand whether to create the sequence table on demand
417 * (default is true)
418 *
419 * @return a sequence integer, or a DB error
420 */
421 function nextId($seq_name, $ondemand = true)
422 {
423 $sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
424 $repeat = 0;
425 do {
426 $seqname = sprintf($this->getOption("seqname_format"), $sqn);
427 $result = $this->query("INSERT INTO ${seqname} VALUES(NULL)");
428 if ($ondemand && DB::isError($result) &&
429 $result->getCode() == DB_ERROR_NOSUCHTABLE) {
430 $repeat = 1;
431 $result = $this->createSequence($seq_name);
432 if (DB::isError($result)) {
433 return $result;
434 }
435 } else {
436 $repeat = 0;
437 }
438 } while ($repeat);
439 if (DB::isError($result)) {
440 return $result;
441 }
442 return fbsql_insert_id($this->connection);
443 }
444
445 // }}}
446 // {{{ createSequence()
447
448 function createSequence($seq_name)
449 {
450 $sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
451 $seqname = sprintf($this->getOption("seqname_format"), $sqn);
452 return $this->query("CREATE TABLE ${seqname} ".
453 '(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
454 ' PRIMARY KEY(id))');
455 }
456
457 // }}}
458 // {{{ dropSequence()
459
460 function dropSequence($seq_name)
461 {
462 $sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
463 $seqname = sprintf($this->getOption("seqname_format"), $sqn);
464 return $this->query("DROP TABLE ${seqname} RESTRICT");
465 }
466
467 // }}}
468 // {{{ modifyQuery()
469
470 function modifyQuery($query)
471 {
472 if ($this->options['optimize'] == 'portability') {
473 // "DELETE FROM table" gives 0 affected rows in fbsql.
474 // This little hack lets you know how many rows were deleted.
475 if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
476 $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
477 'DELETE FROM \1 WHERE 1=1', $query);
478 }
479 }
480 return $query;
481 }
482
483 // }}}
484 // {{{ fbsqlRaiseError()
485
486 function fbsqlRaiseError($errno = null)
487 {
488 if ($errno === null) {
489 $errno = $this->errorCode(fbsql_errno($this->connection));
490 }
491 return $this->raiseError($errno, null, null, null,
492 fbsql_error($this->connection));
493 }
494
495 // }}}
496 // {{{ tableInfo()
497
498 function tableInfo($result, $mode = null) {
499 $count = 0;
500 $id = 0;
501 $res = array();
502
503 /*
504 * depending on $mode, metadata returns the following values:
505 *
506 * - mode is false (default):
507 * $result[]:
508 * [0]["table"] table name
509 * [0]["name"] field name
510 * [0]["type"] field type
511 * [0]["len"] field length
512 * [0]["flags"] field flags
513 *
514 * - mode is DB_TABLEINFO_ORDER
515 * $result[]:
516 * ["num_fields"] number of metadata records
517 * [0]["table"] table name
518 * [0]["name"] field name
519 * [0]["type"] field type
520 * [0]["len"] field length
521 * [0]["flags"] field flags
522 * ["order"][field name] index of field named "field name"
523 * The last one is used, if you have a field name, but no index.
524 * Test: if (isset($result['meta']['myfield'])) { ...
525 *
526 * - mode is DB_TABLEINFO_ORDERTABLE
527 * the same as above. but additionally
528 * ["ordertable"][table name][field name] index of field
529 * named "field name"
530 *
531 * this is, because if you have fields from different
532 * tables with the same field name * they override each
533 * other with DB_TABLEINFO_ORDER
534 *
535 * you can combine DB_TABLEINFO_ORDER and
536 * DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
537 * DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
538 */
539
540 // if $result is a string, then we want information about a
541 // table without a resultset
542 if (is_string($result)) {
543 $id = @fbsql_list_fields($this->dsn['database'],
544 $result, $this->connection);
545 if (empty($id)) {
546 return $this->fbsqlRaiseError();
547 }
548 } else { // else we want information about a resultset
549 $id = $result;
550 if (empty($id)) {
551 return $this->fbsqlRaiseError();
552 }
553 }
554
555 $count = @fbsql_num_fields($id);
556
557 // made this IF due to performance (one if is faster than $count if's)
558 if (empty($mode)) {
559 for ($i=0; $i<$count; $i++) {
560 $res[$i]['table'] = @fbsql_field_table ($id, $i);
561 $res[$i]['name'] = @fbsql_field_name ($id, $i);
562 $res[$i]['type'] = @fbsql_field_type ($id, $i);
563 $res[$i]['len'] = @fbsql_field_len ($id, $i);
564 $res[$i]['flags'] = @fbsql_field_flags ($id, $i);
565 }
566 } else { // full
567 $res["num_fields"]= $count;
568
569 for ($i=0; $i<$count; $i++) {
570 $res[$i]['table'] = @fbsql_field_table ($id, $i);
571 $res[$i]['name'] = @fbsql_field_name ($id, $i);
572 $res[$i]['type'] = @fbsql_field_type ($id, $i);
573 $res[$i]['len'] = @fbsql_field_len ($id, $i);
574 $res[$i]['flags'] = @fbsql_field_flags ($id, $i);
575 if ($mode & DB_TABLEINFO_ORDER) {
576 $res['order'][$res[$i]['name']] = $i;
577 }
578 if ($mode & DB_TABLEINFO_ORDERTABLE) {
579 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
580 }
581 }
582 }
583
584 // free the result only if we were called on a table
585 if (is_string($result)) {
586 @fbsql_free_result($id);
587 }
588 return $res;
589 }
590
591 // }}}
592 // {{{ getSpecialQuery()
593
594 /**
595 * Returns the query needed to get some backend info
596 * @param string $type What kind of info you want to retrieve
597 * @return string The SQL query string
598 */
599 function getSpecialQuery($type)
600 {
601 switch ($type) {
602 case 'tables':
603 $sql = 'select "table_name" from information_schema.tables';
604 break;
605 default:
606 return null;
607 }
608 return $sql;
609 }
610
611 // }}}
612 }
613
614 // TODO/wishlist:
615 // longReadlen
616 // binmode
617
618 ?>

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