PHP Classes

File: Ibase.php

Recommend this page to a friend!
  Classes of Dmitry Koterov   DbSimple   Ibase.php   Download  
File: Ibase.php
Role: Class source
Content type: text/plain
Description: InterBase/FireBird driver
Class: DbSimple
Abstraction to access several SQL databases
Author: By
Last change:
Date: 17 years ago
Size: 9,591 bytes
 

Contents

Class file image Download
<?php
/**
 * DbSimple_Ibase: Interbase/Firebird database.
 * (C) 2005 Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * See http://www.gnu.org/copyleft/lesser.html
 *
 * Placeholders are emulated because of logging purposes.
 *
 * @version 2.x $Id: Ibase.php 63 2006-12-18 09:39:26Z tit $
 */
require_once dirname(__FILE__) . '/Generic.php';

/**
 * Best transaction parameters for script queries.
 * They never give us update conflicts (unlike others)!
 * Used by default.
 */
define('IBASE_BEST_TRANSACTION', IBASE_COMMITTED + IBASE_WAIT + IBASE_REC_VERSION);
define('IBASE_BEST_FETCH', IBASE_UNIXTIME);

/**
 * Database class for Interbase/Firebird.
 */

class DbSimple_Ibase extends DbSimple_Generic_Database
{
    var
$DbSimple_Ibase_BEST_TRANSACTION = IBASE_BEST_TRANSACTION;
    var
$DbSimple_Ibase_USE_NATIVE_PHOLDERS = true;
    var
$fetchFlags = IBASE_BEST_FETCH;
    var
$link;
    var
$trans;
    var
$prepareCache = array();

   
/**
     * constructor(string $dsn)
     * Connect to Interbase/Firebird.
     */
   
function DbSimple_Ibase($dsn)
    {
       
$p = DbSimple_Generic::parseDSN($dsn);
        if (!
is_callable('ibase_connect')) {
            return
$this->_setLastError("-1", "Interbase/Firebird extension is not loaded", "ibase_connect");
        }
       
$ok = $this->link = ibase_connect(
           
$p['host'] . (empty($p['port'])? "" : ":".$p['port']) .':'.preg_replace('{^/}s', '', $p['path']),
           
$p['user'],
           
$p['pass'],
            isset(
$p['CHARSET']) ? $p['CHARSET'] : 'win1251',
            isset(
$p['BUFFERS']) ? $p['BUFFERS'] : 0,
            isset(
$p['DIALECT']) ? $p['DIALECT'] : 3,
            isset(
$p['ROLE']) ? $p['ROLE'] : ''
       
);
        if (isset(
$p['TRANSACTION'])) $this->DbSimple_Ibase_BEST_TRANSACTION = eval($p['TRANSACTION'].";");
       
$this->_resetLastError();
        if (!
$ok) return $this->_setDbError('ibase_connect()');
    }

    function
_performEscape($s, $isIdent=false)
    {
        if (!
$isIdent)
            return
"'" . str_replace("'", "''", $s) . "'";
        else
            return
'"' . str_replace('"', '_', $s) . '"';
    }

    function
_performTransaction($parameters=null)
    {
        if (
$parameters === null) $parameters = $this->DbSimple_Ibase_BEST_TRANSACTION;
       
$this->trans = @ibase_trans($parameters, $this->link);
    }

    function&
_performNewBlob($blobid=null)
    {
       
$obj =& new DbSimple_Ibase_Blob($this, $blobid);
        return
$obj;
    }

    function
_performGetBlobFieldNames($result)
    {
       
$blobFields = array();
        for (
$i=ibase_num_fields($result)-1; $i>=0; $i--) {
           
$info = ibase_field_info($result, $i);
            if (
$info['type'] === "BLOB") $blobFields[] = $info['name'];
        }
        return
$blobFields;
    }

    function
_performGetPlaceholderIgnoreRe()
    {
        return
'
            " (?> [^"\\\\]+|\\\\"|\\\\)* " |
            \' (?> [^\'\\\\]+|\\\\\'|\\\\)* \' |
            ` (?> [^`]+ | ``)* ` | # backticks
            /\* .*? \*/ # comments
        '
;
    }

    function
_performCommit()
    {
        if (!
is_resource($this->trans)) return false;
        return @
ibase_commit($this->trans);
    }


    function
_performRollback()
    {
        if (!
is_resource($this->trans)) return false;
        return @
ibase_rollback($this->trans);
    }

    function
_performTransformQuery(&$queryMain, $how)
    {
       
// If we also need to calculate total number of found rows...
       
switch ($how) {
           
// Prepare total calculation (if possible)
           
case 'CALC_TOTAL':
               
// Not possible
               
return true;
       
           
// Perform total calculation.
           
case 'GET_TOTAL':
               
// TODO: GROUP BY ... -> COUNT(DISTINCT ...)
               
$re = '/^
                    (?> -- [^\r\n]* | \s+)*
                    (\s* SELECT \s+) #1
                        ((?:FIRST \s+ \S+ \s+ (?:SKIP \s+ \S+ \s+)? )?) #2
                    (.*?) #3
                    (\s+ FROM \s+ .*?) #4
                        ((?:\s+ ORDER \s+ BY \s+ .*)?) #5
                $/six'
;
               
$m = null;
                if (
preg_match($re, $queryMain[0], $m)) {
                   
$queryMain[0] = $m[1] . $this->_fieldList2Count($m[3]) . " AS C" . $m[4];
                   
$skipHead = substr_count($m[2], '?');
                    if (
$skipHead) array_splice($queryMain, 1, $skipHead);
                   
$skipTail = substr_count($m[5], '?');
                    if (
$skipTail) array_splice($queryMain, -$skipTail);
                }
                return
true;
        }
       
        return
false;
    }

    function
_performQuery($queryMain)
    {
       
$this->_lastQuery = $queryMain;
       
$this->_expandPlaceholders($queryMain, $this->DbSimple_Ibase_USE_NATIVE_PHOLDERS);

       
$hash = $queryMain[0];
       
        if (!isset(
$this->prepareCache[$hash])) {
           
$this->prepareCache[$hash] = @ibase_prepare($this->link, $queryMain[0]);
        } else {
           
// Prepare cache hit!
       
}

       
$prepared = $this->prepareCache[$hash];
        if (!
$prepared) return $this->_setDbError($queryMain[0]);
       
$queryMain[0] = $prepared;
       
$result = @call_user_func_array('ibase_execute', $queryMain);
       
// ATTENTION!!!
        // WE MUST save prepared ID (stored in $prepared variable) somewhere
        // before returning $result because of ibase destructor. Now it is done
        // by $this->prepareCache. When variable $prepared goes out of scope, it
        // is destroyed, and memory for result also freed by PHP. Totally we
        // got "Invalud statement handle" error message.
       
       
if ($result === false) return $this->_setDbError($queryMain[0]);
        if (!
is_resource($result)) {
           
// Non-SELECT queries return number of affected rows, SELECT - resource.
           
return @ibase_affected_rows($this->link);
        }
        return
$result;
    }

    function
_performFetch($result)
    {
       
// Select fetch mode.
       
$flags = $this->fetchFlags;
        if (empty(
$this->attributes['BLOB_OBJ'])) $flags = $flags | IBASE_TEXT;
        else
$flags = $flags & ~IBASE_TEXT;

       
$row = @ibase_fetch_assoc($result, $flags);
        if (
ibase_errmsg()) return $this->_setDbError($this->_lastQuery);
        if (
$row === false) return null;
        return
$row;
    }
   
   
    function
_setDbError($query)
    {
        return
$this->_setLastError(ibase_errcode(), ibase_errmsg(), $query);
    }
   
}

class
DbSimple_Ibase_Blob extends DbSimple_Generic_Blob
{
    var
$blob; // resourse link
   
var $id;
    var
$database;

    function
DbSimple_Ibase_Blob(&$database, $id=null)
    {
       
$this->database =& $database;
       
$this->id = $id;
       
$this->blob = null;
    }

    function
read($len)
    {
        if (
$this->id === false) return ''; // wr-only blob
       
if (!($e=$this->_firstUse())) return $e;
       
$data = @ibase_blob_get($this->blob, $len);
        if (
$data === false) return $this->_setDbError('read');
        return
$data;
    }

    function
write($data)
    {
        if (!(
$e=$this->_firstUse())) return $e;
       
$ok = @ibase_blob_add($this->blob, $data);
        if (
$ok === false) return $this->_setDbError('add data to');
        return
true;
    }

    function
close()
    {
        if (!(
$e=$this->_firstUse())) return $e;
        if (
$this->blob) {
           
$id = @ibase_blob_close($this->blob);
            if (
$id === false) return $this->_setDbError('close');
           
$this->blob = null;
        } else {
           
$id = null;
        }
        return
$this->id ? $this->id : $id;
    }

    function
length()
    {
        if (
$this->id === false) return 0; // wr-only blob
       
if (!($e=$this->_firstUse())) return $e;
       
$info = @ibase_blob_info($this->id);
        if (!
$info) return $this->_setDbError('get length of');
        return
$info[0];
    }

    function
_setDbError($query)
    {
       
$hId = $this->id === null ? "null" : ($this->id === false ? "false" : $this->id);
       
$query = "-- $query BLOB $hId";
       
$this->database->_setDbError($query);
    }

   
// Called on each blob use (reading or writing).
   
function _firstUse()
    {
       
// BLOB is opened - nothing to do.
       
if (is_resource($this->blob)) return true;
       
// Open or create blob.
       
if ($this->id !== null) {
           
$this->blob = @ibase_blob_open($this->id);
            if (
$this->blob === false) return $this->_setDbError('open');
        } else {
           
$this->blob = @ibase_blob_create($this->database->link);
            if (
$this->blob === false) return $this->_setDbError('create');
        }
        return
true;
    }
}

?>