ibase.php
来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· PHP 代码 · 共 785 行 · 第 1/2 页
PHP
785 行
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Sterling Hughes <sterling@php.net> |
// | Maintainer: Daniel Convissor <danielc@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: ibase.php 3355 2005-06-11 22:14:40Z nbm $
// Bugs:
// - If dbsyntax is not firebird, the limitQuery may fail
require_once 'DB/common.php';
/**
* Database independent query interface definition for PHP's Interbase
* extension.
*
* @package DB
* @version $Id: ibase.php 3355 2005-06-11 22:14:40Z nbm $
* @category Database
* @author Sterling Hughes <sterling@php.net>
*/
class DB_ibase extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $autocommit = 1;
var $manip_query = array();
// }}}
// {{{ constructor
function DB_ibase()
{
$this->DB_common();
$this->phptype = 'ibase';
$this->dbsyntax = 'ibase';
$this->features = array(
'prepare' => true,
'pconnect' => true,
'transactions' => true,
'limit' => false
);
// just a few of the tons of Interbase error codes listed in the
// Language Reference section of the Interbase manual
$this->errorcode_map = array(
-104 => DB_ERROR_SYNTAX,
-150 => DB_ERROR_ACCESS_VIOLATION,
-151 => DB_ERROR_ACCESS_VIOLATION,
-155 => DB_ERROR_NOSUCHTABLE,
88 => DB_ERROR_NOSUCHTABLE,
-157 => DB_ERROR_NOSUCHFIELD,
-158 => DB_ERROR_VALUE_COUNT_ON_ROW,
-170 => DB_ERROR_MISMATCH,
-171 => DB_ERROR_MISMATCH,
-172 => DB_ERROR_INVALID,
-204 => DB_ERROR_INVALID,
-205 => DB_ERROR_NOSUCHFIELD,
-206 => DB_ERROR_NOSUCHFIELD,
-208 => DB_ERROR_INVALID,
-219 => DB_ERROR_NOSUCHTABLE,
-297 => DB_ERROR_CONSTRAINT,
-530 => DB_ERROR_CONSTRAINT,
-607 => DB_ERROR_NOSUCHTABLE,
-803 => DB_ERROR_CONSTRAINT,
-551 => DB_ERROR_ACCESS_VIOLATION,
-552 => DB_ERROR_ACCESS_VIOLATION,
-922 => DB_ERROR_NOSUCHDB,
-923 => DB_ERROR_CONNECT_FAILED,
-924 => DB_ERROR_CONNECT_FAILED
);
}
// }}}
// {{{ connect()
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('interbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$dbhost = $dsninfo['hostspec'] ?
($dsninfo['hostspec'] . ':' . $dsninfo['database']) :
$dsninfo['database'];
$connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect';
$params = array();
$params[] = $dbhost;
$params[] = $dsninfo['username'] ? $dsninfo['username'] : null;
$params[] = $dsninfo['password'] ? $dsninfo['password'] : null;
$params[] = isset($dsninfo['charset']) ? $dsninfo['charset'] : null;
$params[] = isset($dsninfo['buffers']) ? $dsninfo['buffers'] : null;
$params[] = isset($dsninfo['dialect']) ? $dsninfo['dialect'] : null;
$params[] = isset($dsninfo['role']) ? $dsninfo['role'] : null;
$conn = @call_user_func_array($connect_function, $params);
if (!$conn) {
return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED);
}
$this->connection = $conn;
if ($this->dsn['dbsyntax'] == 'firebird') {
$this->features['limit'] = 'alter';
}
return DB_OK;
}
// }}}
// {{{ disconnect()
function disconnect()
{
$ret = @ibase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @ibase_query($this->connection, $query);
if (!$result) {
return $this->ibaseRaiseError();
}
if ($this->autocommit && $ismanip) {
@ibase_commit($this->connection);
}
// Determine which queries that should return data, and which
// should return an error code only.
return $ismanip ? DB_OK : $result;
}
// }}}
// {{{ modifyLimitQuery()
/**
* This method is used by backends to alter limited queries
* Uses the new FIRST n SKIP n Firebird 1.0 syntax, so it is
* only compatible with Firebird 1.x
*
* @param string $query query to modify
* @param integer $from the row to start to fetching
* @param integer $count the numbers of rows to fetch
*
* @return the new (modified) query
* @author Ludovico Magnocavallo <ludo@sumatrasolutions.com>
* @access private
*/
function modifyLimitQuery($query, $from, $count, $params = array())
{
if ($this->dsn['dbsyntax'] == 'firebird') {
//$from++; // SKIP starts from 1, ie SKIP 1 starts from the first record
// (cox) Seems that SKIP starts in 0
$query = preg_replace('/^\s*select\s(.*)$/is',
"SELECT FIRST $count SKIP $from $1", $query);
}
return $query;
}
// }}}
// {{{ nextResult()
/**
* Move the internal ibase result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* @param resource $result query result identifier
* @param array $arr (reference) array where data from the row
* should be placed
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch
*
* @return mixed DB_OK on success, null when end of result set is
* reached or on failure
*
* @see DB_result::fetchInto()
* @access private
*/
function fetchInto($result, &$arr, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
if (function_exists('ibase_fetch_assoc')) {
$arr = @ibase_fetch_assoc($result);
} else {
$arr = get_object_vars(ibase_fetch_object($result));
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @ibase_fetch_row($result);
}
if (!$arr) {
if ($errmsg = @ibase_errmsg()) {
return $this->ibaseRaiseError(null, $errmsg);
} else {
return null;
}
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
function freeResult($result)
{
return @ibase_free_result($result);
}
// }}}
// {{{ freeQuery()
function freeQuery($query)
{
@ibase_free_query($query);
return true;
}
// }}}
// {{{ numCols()
function numCols($result)
{
$cols = @ibase_num_fields($result);
if (!$cols) {
return $this->ibaseRaiseError();
}
return $cols;
}
// }}}
// {{{ prepare()
/**
* Prepares a query for multiple execution with execute().
*
* prepare() requires a generic query as string like <code>
* INSERT INTO numbers VALUES (?, ?, ?)
* </code>. The <kbd>?</kbd> characters are placeholders.
*
* Three types of placeholders can be used:
* + <kbd>?</kbd> a quoted scalar value, i.e. strings, integers
* + <kbd>!</kbd> value is inserted 'as is'
* + <kbd>&</kbd> requires a file name. The file's contents get
* inserted into the query (i.e. saving binary
* data in a db)
*
* Use backslashes to escape placeholder characters if you don't want
* them to be interpreted as placeholders. Example: <code>
* "UPDATE foo SET col=? WHERE col='over \& under'"
* </code>
*
* @param string $query query to be prepared
* @return mixed DB statement resource on success. DB_Error on failure.
*/
function prepare($query)
{
$tokens = preg_split('/((?<!\\\)[&?!])/', $query, -1,
PREG_SPLIT_DELIM_CAPTURE);
$token = 0;
$types = array();
$newquery = '';
foreach ($tokens as $key => $val) {
switch ($val) {
case '?':
$types[$token++] = DB_PARAM_SCALAR;
break;
case '&':
$types[$token++] = DB_PARAM_OPAQUE;
break;
case '!':
$types[$token++] = DB_PARAM_MISC;
break;
default:
$tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val);
$newquery .= $tokens[$key] . '?';
}
}
$newquery = substr($newquery, 0, -1);
$this->last_query = $query;
$newquery = $this->modifyQuery($newquery);
$stmt = @ibase_prepare($this->connection, $newquery);
$this->prepare_types[(int)$stmt] = $types;
$this->manip_query[(int)$stmt] = DB::isManip($query);
return $stmt;
}
// }}}
// {{{ execute()
/**
* Executes a DB statement prepared with prepare().
*
* @param resource $stmt a DB statement resource returned from prepare()
* @param mixed $data array, string or numeric data to be used in
* execution of the statement. Quantity of items
* passed must match quantity of placeholders in
* query: meaning 1 for non-array items or the
* quantity of elements in the array.
* @return object a new DB_Result or a DB_Error when fail
* @see DB_ibase::prepare()
* @access public
*/
function &execute($stmt, $data = array())
{
if (!is_array($data)) {
$data = array($data);
}
$types =& $this->prepare_types[(int)$stmt];
if (count($types) != count($data)) {
$tmp =& $this->raiseError(DB_ERROR_MISMATCH);
return $tmp;
}
$i = 0;
foreach ($data as $key => $value) {
if ($types[$i] == DB_PARAM_MISC) {
/*
* ibase doesn't seem to have the ability to pass a
* parameter along unchanged, so strip off quotes from start
* and end, plus turn two single quotes to one single quote,
* in order to avoid the quotes getting escaped by
* ibase and ending up in the database.
*/
$data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]);
$data[$key] = str_replace("''", "'", $data[$key]);
} elseif ($types[$i] == DB_PARAM_OPAQUE) {
$fp = @fopen($data[$key], 'rb');
if (!$fp) {
$tmp =& $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
return $tmp;
}
$data[$key] = fread($fp, filesize($data[$key]));
fclose($fp);
}
$i++;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?