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

Annotation of /nfo/php/libs/net.php.pear/DB/ibase.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide 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 cvsjoko 1.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: Sterling Hughes <sterling@php.net> |
17     // +----------------------------------------------------------------------+
18     //
19     // $Id: ibase.php,v 1.36.2.2 2002/04/09 19:04:13 ssb Exp $
20     //
21     // Database independent query interface definition for PHP's Interbase
22     // extension.
23     //
24    
25     require_once 'DB/common.php';
26    
27     class DB_ibase extends DB_common
28     {
29     var $connection;
30     var $phptype, $dbsyntax;
31     var $autocommit = 1;
32     var $manip_query = array();
33    
34     function DB_ibase()
35     {
36     $this->DB_common();
37     $this->phptype = 'ibase';
38     $this->dbsyntax = 'ibase';
39     $this->features = array(
40     'prepare' => true,
41     'pconnect' => true,
42     'transactions' => true,
43     'limit' => false
44     );
45     // just a few of the tons of Interbase error codes listed in the
46     // Language Reference section of the Interbase manual
47     $this->errorcode_map = array(
48     -104 => DB_ERROR_SYNTAX,
49     -150 => DB_ERROR_ACCESS_VIOLATION,
50     -151 => DB_ERROR_ACCESS_VIOLATION,
51     -155 => DB_ERROR_NOSUCHTABLE,
52     -157 => DB_ERROR_NOSUCHFIELD,
53     -158 => DB_ERROR_VALUE_COUNT_ON_ROW,
54     -170 => DB_ERROR_MISMATCH,
55     -171 => DB_ERROR_MISMATCH,
56     -172 => DB_ERROR_INVALID,
57     -204 => DB_ERROR_INVALID,
58     -205 => DB_ERROR_NOSUCHFIELD,
59     -206 => DB_ERROR_NOSUCHFIELD,
60     -208 => DB_ERROR_INVALID,
61     -219 => DB_ERROR_NOSUCHTABLE,
62     -297 => DB_ERROR_CONSTRAINT,
63     -530 => DB_ERROR_CONSTRAINT,
64     -803 => DB_ERROR_CONSTRAINT,
65     -551 => DB_ERROR_ACCESS_VIOLATION,
66     -552 => DB_ERROR_ACCESS_VIOLATION,
67     -922 => DB_ERROR_NOSUCHDB,
68     -923 => DB_ERROR_CONNECT_FAILED,
69     -924 => DB_ERROR_CONNECT_FAILED
70     );
71     }
72    
73     function connect($dsninfo, $persistent = false)
74     {
75     if (!DB::assertExtension('interbase')) {
76     return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
77     }
78     $this->dsn = $dsninfo;
79     $user = $dsninfo['username'];
80     $pw = $dsninfo['password'];
81     $dbhost = $dsninfo['hostspec'] ?
82     ($dsninfo['hostspec'] . ':/' . $dsninfo['database']) :
83     $dsninfo['database'];
84    
85     $connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect';
86    
87     $params = array();
88     $params[] = $dbhost;
89     $params[] = !empty($user) ? $user : null;
90     $params[] = !empty($pw) ? $pw : null;
91     $params[] = isset($dsninfo['charset']) ? $dsninfo['charset'] : null;
92     $params[] = isset($dsninfo['buffers']) ? $dsninfo['buffers'] : null;
93     $params[] = isset($dsninfo['dialect']) ? $dsninfo['dialect'] : null;
94     $params[] = isset($dsninfo['role']) ? $dsninfo['role'] : null;
95    
96     /*
97     if ($dbhost && $user && $pw) {
98     $conn = $connect_function($dbhost, $user, $pw);
99     } elseif ($dbhost && $user) {
100     $conn = $connect_function($dbhost, $user);
101     } elseif ($dbhost) {
102     $conn = $connect_function($dbhost);
103     } else {
104     return $this->raiseError("no host, user or password");
105     }
106     */
107     $conn = @call_user_func_array($connect_function, $params);
108     if (!$conn) {
109     return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED);
110     }
111     $this->connection = $conn;
112     return DB_OK;
113     }
114    
115     function disconnect()
116     {
117     $ret = @ibase_close($this->connection);
118     $this->connection = null;
119     return $ret;
120     }
121    
122     function simpleQuery($query)
123     {
124     $ismanip = DB::isManip($query);
125     $this->last_query = $query;
126     $query = $this->modifyQuery($query);
127     $result = @ibase_query($this->connection, $query);
128     if (!$result) {
129     return $this->ibaseRaiseError();
130     }
131     if ($this->autocommit && $ismanip) {
132     ibase_commit($this->connection);
133     }
134     // Determine which queries that should return data, and which
135     // should return an error code only.
136     return DB::isManip($query) ? DB_OK : $result;
137     }
138    
139     // {{{ modifyLimitQuery()
140    
141     /**
142     * This method is used by backends to alter limited queries
143     * Uses the new FIRST n SKIP n Firebird 1.0 syntax, so it is
144     * only compatible with Firebird 1.x
145     *
146     * @param string $query query to modify
147     * @param integer $from the row to start to fetching
148     * @param integer $count the numbers of rows to fetch
149     *
150     * @return the new (modified) query
151     * @author Ludovico Magnocavallo <ludo@sumatrasolutions.com>
152     * @access private
153     */
154    
155     function modifyLimitQuery($query, $from, $count)
156     {
157     if ($this->dsn['dbsyntax'] == 'firebird') {
158     $from++; // SKIP starts from 1, ie SKIP 1 starts from the first record
159     $query = preg_replace('/^\s*select\s(.*)$/is',
160     "SELECT FIRST $count SKIP $from $1", $query);
161     }
162     return $query;
163     }
164    
165     // }}}
166    
167    
168     // {{{ nextResult()
169    
170     /**
171     * Move the internal ibase result pointer to the next available result
172     *
173     * @param a valid fbsql result resource
174     *
175     * @access public
176     *
177     * @return true if a result is available otherwise return false
178     */
179     function nextResult($result)
180     {
181     return false;
182     }
183    
184     // }}}
185    
186     function fetchInto($result, &$ar, $fetchmode, $rownum = null)
187     {
188     if ($rownum !== NULL) {
189     return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
190     }
191     if ($fetchmode & DB_FETCHMODE_ASSOC) {
192     $ar = get_object_vars(ibase_fetch_object($result));
193     if ($ar && $this->options['optimize'] == 'portability') {
194     $ar = array_change_key_case($ar, CASE_LOWER);
195     }
196     } else {
197     $ar = ibase_fetch_row($result);
198     }
199     if (!$ar) {
200     if ($errmsg = ibase_errmsg()) {
201     return $this->ibaseRaiseError(null, $errmsg);
202     } else {
203     return null;
204     }
205     }
206     return DB_OK;
207     }
208    
209     function freeResult()
210     {
211     if (is_resource($result)) {
212     return ibase_free_result($result);
213     }
214     if (!isset($this->prepare_tokens[(int)$result])) {
215     return false;
216     }
217     unset($this->prepare_tokens[(int)$result]);
218     unset($this->prepare_types[(int)$result]);
219     return true;
220     }
221    
222     function freeQuery($query)
223     {
224     ibase_free_query($query);
225     return true;
226     }
227    
228     function numCols($result)
229     {
230     $cols = ibase_num_fields($result);
231     if (!$cols) {
232     return $this->ibaseRaiseError();
233     }
234     return $cols;
235     }
236    
237     function prepare($query)
238     {
239     $this->last_query = $query;
240     $query = $this->modifyQuery($query);
241     $stmt = ibase_prepare($query);
242     $this->manip_query[(int)$stmt] = DB::isManip($query);
243     return $stmt;
244     }
245    
246     function execute($stmt, $data = false)
247     {
248     $result = ibase_execute($stmt, $data);
249     if (!$result) {
250     return $this->ibaseRaiseError();
251     }
252     if ($this->autocommit) {
253     ibase_commit($this->connection);
254     }
255     return DB::isManip($this->manip_query[(int)$stmt]) ? DB_OK : new DB_result($this, $result);
256     }
257    
258     function autoCommit($onoff = false)
259     {
260     $this->autocommit = $onoff ? 1 : 0;
261     return DB_OK;
262     }
263    
264     function commit()
265     {
266     return ibase_commit($this->connection);
267     }
268    
269     function rollback($trans_number)
270     {
271     return ibase_rollback($this->connection, $trans_number);
272     }
273    
274     function transactionInit($trans_args = 0)
275     {
276     return $trans_args ? ibase_trans($trans_args, $this->connection) : ibase_trans();
277     }
278    
279     // {{{ nextId()
280     /**
281     * Get the next value in a sequence.
282     *
283     * If the sequence does not exist, it will be created,
284     * unless $ondemand is false.
285     *
286     * @access public
287     * @param string $seq_name the name of the sequence
288     * @param bool $ondemand whether to create the sequence on demand
289     * @return a sequence integer, or a DB error
290     */
291     function nextId($seq_name, $ondemand = true)
292     {
293     $sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
294     $repeat = 0;
295     do {
296     $this->pushErrorHandling(PEAR_ERROR_RETURN);
297     $result = $this->query("SELECT GEN_ID(${sqn}_SEQ, 1) FROM RDB\$GENERATORS"
298     ." WHERE RDB\$GENERATOR_NAME='${sqn}_SEQ'");
299     $this->popErrorHandling();
300     if ($ondemand && DB::isError($result)) {
301     $repeat = 1;
302     $result = $this->createSequence($seq_name);
303     if (DB::isError($result)) {
304     return $result;
305     }
306     } else {
307     $repeat = 0;
308     }
309     } while ($repeat);
310     if (DB::isError($result)) {
311     return $result;
312     }
313     $arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
314     $result->free();
315     return $arr[0];
316     }
317    
318     // }}}
319     // {{{ createSequence()
320    
321     /**
322     * Create the sequence
323     *
324     * @param string $seq_name the name of the sequence
325     * @return mixed DB_OK on success or DB error on error
326     * @access public
327     */
328     function createSequence($seq_name)
329     {
330     $sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
331     $this->pushErrorHandling(PEAR_ERROR_RETURN);
332     $result = $this->query("CREATE GENERATOR ${sqn}_SEQ");
333     $this->popErrorHandling();
334    
335     return $result;
336     }
337    
338     // }}}
339     // {{{ dropSequence()
340    
341     /**
342     * Drop a sequence
343     *
344     * @param string $seq_name the name of the sequence
345     * @return mixed DB_OK on success or DB error on error
346     * @access public
347     */
348     function dropSequence($seq_name)
349     {
350     $sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
351     return $this->query("DELETE FROM RDB\$GENERATORS WHERE RDB\$GENERATOR_NAME='${sqn}_SEQ'");
352     }
353    
354     // }}}
355     // {{{ _ibaseFieldFlags()
356    
357     /**
358     * get the Flags of a Field
359     *
360     * @param string $field_name the name of the field
361     * @param string $table_name the name of the table
362     *
363     * @return string The flags of the field ("primary_key", "unique_key", "not_null"
364     * "default", "computed" and "blob" are supported)
365     * @access private
366     */
367     function _ibaseFieldFlags($field_name, $table_name)
368     {
369    
370     $sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE'
371     .' FROM RDB$INDEX_SEGMENTS I'
372     .' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME'
373     .' WHERE I.RDB$FIELD_NAME=\''.$field_name.'\''
374     .' AND R.RDB$RELATION_NAME=\''.$table_name.'\'';
375     $result = ibase_query($this->connection, $sql);
376     if (empty($result)) {
377     return $this->ibaseRaiseError();
378     }
379     if ($obj = @ibase_fetch_object($result)) {
380     ibase_free_result($result);
381     if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') {
382     $flags = 'primary_key ';
383     }
384     if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') {
385     $flags .= 'unique_key ';
386     }
387     }
388    
389     $sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,'
390     .' R.RDB$DEFAULT_SOURCE AS DSOURCE,'
391     .' F.RDB$FIELD_TYPE AS FTYPE,'
392     .' F.RDB$COMPUTED_SOURCE AS CSOURCE'
393     .' FROM RDB$RELATION_FIELDS R '
394     .' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME'
395     .' WHERE R.RDB$RELATION_NAME=\''.$table_name.'\''
396     .' AND R.RDB$FIELD_NAME=\''.$field_name.'\'';
397     $result = ibase_query($this->connection, $sql);
398     if (empty($result)) {
399     return $this->ibaseRaiseError();
400     }
401     if ($obj = @ibase_fetch_object($result)) {
402     ibase_free_result($result);
403     if (isset($obj->NFLAG)) {
404     $flags .= 'not_null ';
405     }
406     if (isset($obj->DSOURCE)) {
407     $flags .= 'default ';
408     }
409     if (isset($obj->CSOURCE)) {
410     $flags .= 'computed ';
411     }
412     if (isset($obj->FTYPE) && $obj->FTYPE == 261) {
413     $flags .= 'blob ';
414     }
415     }
416    
417     return trim($flags);
418     }
419    
420     // }}}
421     // {{{ tableInfo()
422    
423     /**
424     * Returns information about a table or a result set
425     *
426     * NOTE: doesn't support 'flags'and 'table' if called from a db_result
427     *
428     * @param mixed $resource Interbase result identifier or table name
429     * @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
430     * DB_TABLEINFO_ORDER)
431     *
432     * @return array An array with all the information
433     */
434     function tableInfo($result, $mode = null)
435     {
436     $count = 0;
437     $id = 0;
438     $res = array();
439    
440     /*
441     * depending on $mode, metadata returns the following values:
442     *
443     * - mode is false (default):
444     * $result[]:
445     * [0]["table"] table name
446     * [0]["name"] field name
447     * [0]["type"] field type
448     * [0]["len"] field length
449     * [0]["flags"] field flags
450     *
451     * - mode is DB_TABLEINFO_ORDER
452     * $result[]:
453     * ["num_fields"] number of metadata records
454     * [0]["table"] table name
455     * [0]["name"] field name
456     * [0]["type"] field type
457     * [0]["len"] field length
458     * [0]["flags"] field flags
459     * ["order"][field name] index of field named "field name"
460     * The last one is used, if you have a field name, but no index.
461     * Test: if (isset($result['meta']['myfield'])) { ...
462     *
463     * - mode is DB_TABLEINFO_ORDERTABLE
464     * the same as above. but additionally
465     * ["ordertable"][table name][field name] index of field
466     * named "field name"
467     *
468     * this is, because if you have fields from different
469     * tables with the same field name * they override each
470     * other with DB_TABLEINFO_ORDER
471     *
472     * you can combine DB_TABLEINFO_ORDER and
473     * DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
474     * DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
475     */
476    
477     // if $result is a string, then we want information about a
478     // table without a resultset
479    
480     if (is_string($result)) {
481     $id = ibase_query($this->connection,"SELECT * FROM $result");
482     if (empty($id)) {
483     return $this->ibaseRaiseError();
484     }
485     } else { // else we want information about a resultset
486     $id = $result;
487     if (empty($id)) {
488     return $this->ibaseRaiseError();
489     }
490     }
491    
492     $count = @ibase_num_fields($id);
493    
494     // made this IF due to performance (one if is faster than $count if's)
495     if (empty($mode)) {
496    
497     for ($i=0; $i<$count; $i++) {
498     $info = @ibase_field_info($id, $i);
499     $res[$i]['table'] = (is_string($result)) ? $result : '';
500     $res[$i]['name'] = $info['name'];
501     $res[$i]['type'] = $info['type'];
502     $res[$i]['len'] = $info['length'];
503     $res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
504     }
505    
506     } else { // full
507     $res["num_fields"]= $count;
508    
509     for ($i=0; $i<$count; $i++) {
510     $info = @ibase_field_info($id, $i);
511     $res[$i]['table'] = (is_string($result)) ? $result : '';
512     $res[$i]['name'] = $info['name'];
513     $res[$i]['type'] = $info['type'];
514     $res[$i]['len'] = $info['length'];
515     $res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
516     if ($mode & DB_TABLEINFO_ORDER) {
517     $res['order'][$res[$i]['name']] = $i;
518     }
519     if ($mode & DB_TABLEINFO_ORDERTABLE) {
520     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
521     }
522     }
523     }
524    
525     // free the result only if we were called on a table
526     if (is_resource($id)) {
527     ibase_free_result($id);
528     }
529     return $res;
530     }
531    
532     // }}}
533     // {{{ getSpecialQuery()
534    
535     /**
536     * Returns the query needed to get some backend info
537     * @param string $type What kind of info you want to retrieve
538     * @return string The SQL query string
539     */
540     function getSpecialQuery($type)
541     {
542     switch ($type) {
543     case 'tables':
544     default:
545     return null;
546     }
547     return $sql;
548     }
549    
550     // }}}
551     // {{{ ibaseRaiseError()
552    
553     function ibaseRaiseError($errno = null, $errmsg = null)
554     {
555     if ($errmsg === null)
556     $errmsg = ibase_errmsg();
557     // memo for the interbase php module hackers: we need something similar
558     // to mysql_errno() to retrieve error codes instead of this ugly hack
559     if (preg_match('/^([^0-9\-]+)([0-9\-]+)\s+(.*)$/', $errmsg, $m)) {
560     if ($errno === null) {
561     $ibase_errno = (int)$m[2];
562     // try to interpret Interbase error code (that's why we need ibase_errno()
563     // in the interbase module to return the real error code)
564     switch ($ibase_errno) {
565     case -204:
566     if (is_int(strpos($m[3], 'Table unknown'))) {
567     $errno = DB_ERROR_NOSUCHTABLE;
568     }
569     break;
570     default:
571     $errno = $this->errorCode($ibase_errno);
572     }
573     }
574     $errmsg = $m[2] . ' ' . $m[3];
575     }
576    
577     return $this->raiseError($errno, null, null, $errmsg,
578     $this->last_query);
579     }
580    
581     // }}}
582    
583     }
584    
585     /*
586     * Local variables:
587     * tab-width: 4
588     * c-basic-offset: 4
589     * End:
590     */
591    
592     ?>

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