Re: [phplib] Please, include Interbase support in PHPLIB From: Max Derkachev (kot <email protected>)
Date: 10/20/00

"Victor M. Varela" wrote:

> I think that Gregor Ibic's Interbase module must be included in PHPLIB
> distribution. It seems to work fine.

I've made another PHPLIB Interbase extension, which covers more php/interbase
api functions, than Gregor's.
With my patch to php interbase module applied (posted to php-dev, php-db and
php-general a week ago) native interbase affected_rows functionality could
also be achieved.
Only metadata method had not been implemented.
My module is not tested enough, so use it carefully. Feel free to use it and
hack it.
Unfortunately I don't have enough time to test it now, cause the project I'm
working on now does not use interbase yet.
I'd be happy to hear any comments, how it works, and see fixes and updates.
I'd be also happy to see it in PHPLIB distro as well :).

--
Best regards,
Max A. Derkachev mailto:kot <email protected>
Symbol-Plus Publishing Ltd.
phone: +7 (812) 265-0054, 265-1228, phone/fax: 567-8775
http://www.Books.Ru -- All Books of Russia

<?php /* Interbase module for PHPLIB Copyright (c) 2000 Maxim Derkachev <kot <email protected>> License: GNU Library GPL ver. 2 (June 1991) */

class DB_Sql { /* public: connection parameters */ var $Host = 'localhost'; var $Database = ""; var $User = ""; var $Password = ""; var $Charset = "ISO8859_1"; /* public: configuration parameters */ var $Auto_Free = 1; ## Set to 1 for automatic freeing var $Debug = 0; ## Set to 1 for debugging messages. var $Halt_On_Error = "yes"; ## "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore errror, but spit a warning)

/* public: result array and current row number */ var $Record = array(); var $Row;

/* public: current error number and error text */ var $Errno = 0; var $Error = "";

/* public: this is an api revision, not a CVS revision. */ var $type = "interbase"; var $revision = "1.0";

/* private: link and query handles */ var $Link_ID = 0; var $Query_ID = 0; var $Last_Query ; // last query passed to $this->query(); var $Transactions = array (); var $Trans_ID = 0; var $Auto_commit = true; var $Trans_opts = array ('readonly' => 4, 'read_commited' => 8, 'consistency' => 16, 'nowait' => 32 ); var $Result_stack = array();

/* public: constructor */ function DB_Sql($query = "", $auto_commit=true) { $this->query($query); if ($auto_commit != $this->Auto_commit) $this->Auto_commit = $auto_commit; }

/* public: some trivial reporting */ function link_id() { return $this->Link_ID; }

function query_id() { return $this->Query_ID; }

function trans_id() { return $this->Trans_ID; }

/* public: connection management */ function connect($Database = "", $Host = "", $User = "", $Password = "", $Charset='', $Role='') { /* Handle defaults */ if ("" == $Database) $Database = $this->Database; if ("" == $Host) $Host = $this->Host; if ("" == $User) $User = $this->User; if ("" == $Password) $Password = $this->Password; if ('' == $Charset) $Charset = $this->Charset; /* establish connection, select database */ if ( 0 == $this->Link_ID ) { $this->Link_ID=ibase_pconnect($Host.":".$Database, $User, $Password, $Charset, $Role); $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; if (!$this->Link_ID) { $this->halt("pconnect($Host:$Database, $User, \$Password) failed."); return 0; }

} return $this->Link_ID; }

function trans_start($trans_opts='') { $opts_val = 0; if ($trans_opts) { $trans_opts = strtolower ($trans_opts) ; $opts = preg_split("/\s*\,\s*/", $trans_opts); foreach ($opts as $opt) { if ($this->Trans_opts[$opt]) $opts_val += $this->Trans_opts[$opt]; } }

$this->Trans_ID = ibase_trans($opts_val, $this->Link_ID); $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; return ($this->Trans_ID); } function commit($trans_id=0) { if (!$trans_id && $this->Trans_ID) { $trans_id = $this->Trans_ID; $this->Trans_ID = 0; $ret = ibase_commit($trans_id); } elseif ($trans_id) { $ret = ibase_commit($trans_id); } $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; return $ret; }

function rollback($trans_id=0) { if (!$trans_id && $this->Trans_ID) { $trans_id = $this->Trans_ID; $this->Trans_ID = 0; $ret = ibase_rollback($trans_id) ; } elseif ($trans_id) { $ret = ibase_rollback($trans_id); } $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; return $ret; }

/* public: discard the query result */ function free() {  <email protected>($this->Query_ID); $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; $this->Result_stack = array (); $this->Query_ID = 0; }

/* public: perform a query */ function query($Query_String ) { /* No empty queries, please, since PHP4 chokes on them. */ if ($Query_String == "") /* The empty query string is passed on from the constructor, * when calling the class without a query, e.g. in situations * like these: '$db = new DB_Sql_Subclass;' */ return 0;

if (!$this->connect()) { return 0; /* we already complained in connect() about that. */ };

# New query, discard previous result. if ($this->Query_ID) { $this->free(); }

if ($this->Debug) printf("Debug: query = %s<br>\n", $Query_String); $this->Last_Query = $Query_String;

$Link_ID = ($this->Trans_ID) ? $this->Trans_ID : $this->Link_ID; $this->Query_ID = ibase_query($Link_ID, $Query_String); $this->Row = 0; $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; if (!$this->Query_ID) { $this->halt("Invalid SQL: ".$Query_String); }

# Will return nada if it fails. That's fine. return $this->Query_ID; }

/* public: walk result set */ function next_record() { if (!$this->Query_ID) { $this->halt("next_record called with no query pending."); return 0; }

if (($this->Row + 1) > count ($this->Result_stack) ) { // do we have next row // already fetched? $this->Record = ibase_fetch_object($this->Query_ID); $this->Row += 1; $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; $stat = is_object($this->Record); if ($stat) { $this->Record = (array) $this->Record; if (!$this->Auto_Free) $this->Result_stack[] = $this->Record; } if (!$stat && $this->Auto_Free) $this->free(); } else { // the row is in pre-fetched rows $stat = 1; $this->Record = $this->Result_stack[$this->Row]; $this->Row += 1; } return $stat; }

/* public: position in result set */ function seek($pos = 0) { end ($this->Result_stack); $last_key = key ($this->Result_stack); reset ($this->Result_stack); if ($pos > $last_key) { while ($last_key < $pos) { if (!$this->next_record()) { if ($this->Auto_commit) $this->commit(); $this->halt("seek($pos) failed: result has ".$this->num_rows()." rows"); return 0; } $last_key++; } } else { $this->Row = $pos; }

return 1; }

/* public: table locking */ function lock($table, $mode="write") { // not available return true; } function unlock() { // not available return true; }

/* public: evaluate the result (size, width) */ function affected_rows() { // works when my ibase patch applied // if the query is insert, update or select - returns affected rows count // else 0 if (eregi ("^[[:space:]]*(INSERT|UPDATE|DELETE){1}[[:space:]]",strtoupper($this->Last_Query) ) ) return ibase_affected_rows(); else return 0; }

function num_rows() { // this function should not be called often, especially on queries that take long // time to execute - it will execute a similar query, and it could take a long // also it won't work with 'select distinct ...', since num_rows won't show // distinct rows count, but all rows count if (eregi("^[[:space:]]*SELECT[[:space:]]",strtoupper($this->Last_Query) ) ) { $from_pos = strpos(strtoupper($this->Last_Query),"FROM"); $query = "SELECT count(*) ". substr($this->Last_Query, $from_pos); $link = ($this->Trans_ID) ? $this->Trans_ID : $this->Link_ID; $handle = ibase_query($link, $query); $res = ibase_fetch_row($handle); $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; return $res[0]; } else return 0; }

function num_fields() { return ibase_num_fields($this->Query_ID); }

/* public: shorthand notation */ function nf() { return $this->num_rows(); }

function np() { print $this->num_rows(); }

function f($Name) { return $this->Record[$Name]; }

function p($Name) { print $this->Record[$Name]; }

/* public: sequence numbers $seq_name is a generator name for inique id generation $pace is a value on which the generator should be raised this mechanism is preferred in interbase and much more reliable then sequence table mechanism, as in the mysql module */ function nextid($seq_name, $pace = 1) { $this->connect(); $query = "select gen_id($seq_name, $pace) from".' rdb$database '; // rdb$database always have only 1 record, so the generator won't increment twice or // more :) $handle = ibase_query($this->Link_ID, $query); $res = ibase_fetch_row($handle); $nextid = $res[0]; $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; }

/* public: return table metadata */ //TODO!!! not implemented yet function metadata($table='',$full=false) { $count = 0; $id = 0; $res = array();

/* * Due to compatibility problems with Table we changed the behavior * of metadata(); * depending on $full, metadata returns the following values: * * - full is false (default): * $result[]: * [0]["table"] table name * [0]["name"] field name * [0]["type"] field type * [0]["len"] field length * [0]["flags"] field flags * * - full is true * $result[]: * ["num_fields"] number of metadata records * [0]["table"] table name * [0]["name"] field name * [0]["type"] field type * [0]["len"] field length * [0]["flags"] field flags * ["meta"][field name] index of field named "field name" * The last one is used, if you have a field name, but no index. * Test: if (isset($result['meta']['myfield'])) { ... */

return $res; }

/* private: error handling */ function halt($msg) { $this->Errno = ($this->Error = ibase_errmsg()) ? 1 : 0; if ($this->Halt_On_Error == "no") return;

$this->haltmsg($msg);

if ($this->Halt_On_Error != "report") die("Session halted."); }

function haltmsg($msg) { printf("</td></tr></table><b>Database error:</b> %s<br>\n", $msg); printf("<b>Interbase Error</b>: %s (%s)<br>\n", $this->Errno, $this->Error); }

function table_names() { $this->query('select rdb$relation_name from rdb$relations where rdb$system_flag = 0'); $i=0; while ($info=ibase_fetch_row($this->Query_ID)) { $return[$i]["table_name"]= $info[0]; $return[$i]["tablespace_name"]=$this->Database; $return[$i]["database"]=$this->Database; $i++; } return $return; } } ?>

--------------------------------------------------------------------- To unsubscribe, e-mail: phplib-unsubscribe <email protected> For additional commands, e-mail: phplib-help <email protected>