1. Import

This commit is contained in:
2026-03-29 10:34:57 +02:00
parent b0e00c1259
commit a1129565af
4899 changed files with 3007593 additions and 0 deletions

90
html/illt/DB/IDEAS Normal file
View File

@@ -0,0 +1,90 @@
Abstracted Types (Stig)
-----------------------
DB needs a set of types representing the most commonly used types in
all backends. This type set could also be geared towards integration
with things like XML-RPC/SOAP implementations, HTML form classes, etc.
Real Query Parser (Stig)
------------------------
With a real query parser, DB can implement more of its portability
based on the query, instead of having support functions for
everything. One example would be LIMIT, another "INSERT
... RETURNING".
Portable transactions (Stig)
----------------------------
If DB can parse queries enough to determine what tables are affected
by queries, it should be possible to make a replayable transaction
log. GNOME uses an XML format for configuration data that lets you
checkpoint state once in a while, and revert to that state later.
With a similar approach for transactions in DB we can implement
portable transactions and checkpointing even for the databases that
don't support them.
Error reporting clean-up/debug (Tomas)
-------------------------------------
Now each driver has its own raiseError method, common has a raiseError and
DB has a DB_error class and its own isError() method. This error stuff
overhead could be simplified with only one raiseError, droping the DB Error
class and also the DB::isError() (use the PEAR.php ones instead).
Other idea could be to add a system for allowing people access to all the
queries sended by PEAR DB to the backend. Also a new PEAR_ERROR_DEBUG
flag that automatically (show|triggers) debug info, perhaps
with a new PEAR_(Warning|Debug) object.
Quote clean-up (Stig)
---------------------
1. Keep quote and quoteString, but move quoting of strings back into
quoteString and make quote call it for strings.
2. Add an optional "operator" parameter to quote that is one of "=",
"<", ">" or "<>" that will be inserted in front of the quoted value
unless it is NULL, in which case it will be converted to "IS" (for
"=") or "IS NOT" (for the others).
Auto free statements (Tomas)
----------------------------
By setting a param in query() or for the hole DB instance, PEAR DB
could auto-free results in DB_result->fetch(Into|Row) when the driver
returns false.
Datatypes in prepare syntax (Tomas)
-----------------------------------
Extend the actual prepare/execute placeholders to support data types, both
to check the data introduced to the query and to "cast" the result
to native php data types. Ex:
$sql = "INSERT INTO table VALUES ({{int(4)}}, {{bool}}, {{date('Y-m-d')}})";
$row = $db->query($sql, array(8, 't', '2001-04-1'));
Format: {{<data_type>(<param1>,<param2>)}}
"param" could be the max lenght of the data, date formats, not_null
checks or default values.
Other ideas could be:
1)
$sql = "INSERT INTO table VALUES (?, ?, ?)";
$sth = $db->prepare($sql, array('int(4)', 'bool', 'date');
$res = $db->execute($sth, array($a, $b, $c);
2)
$sql = "INSERT INTO table VALUES (?, ?, ?)";
$params = array(
0 => array($a, 'int(4)'),
1 => array($b, 'bool')
);
$res = $db->query($sql, $params);
Auto connect feature (Tomas)
----------------------------
Add the ability to create for example a light and dump DB object which
will only set up the connection when needed. With that people could
create the DB object in a common prepend or default file without the
need to waste system resources if the use of the database is finally
not needed.

15
html/illt/DB/MAINTAINERS Normal file
View File

@@ -0,0 +1,15 @@
Maintainers for DB database backends/drivers:
ibase : Ludovico Magnocavallo <ludo@sumatrasolutions.com>
msql :
mssql : Frank M. Kromann <frank@frontbase.com>
mysql : Stig Bakken <ssb@fast.no>
oci8 : Tomas V.V.Cox <cox@idecnet.com>
odbc : Tomas V.V.Cox <cox@idecnet.com>
pgsql : Rui Hirokawa <rui_hirokawa@ybb.ne.jp>
Stig Bakken <ssb@fast.no>
sybase :
ifx : Tomas V.V.Cox <cox@idecnet.com>
fbsql : Frank M. Kromann <frank@frontbase.com>
dbase : Tomas V.V.Cox <cox@idecnet.com>
ldap : Ludovico Magnocavallo <ludo@sumatrasolutions.com>

38
html/illt/DB/STATUS Normal file
View File

@@ -0,0 +1,38 @@
DB driver feature matrix:
Symbols:
"x" - implemented, but without tests
"t" - implemented, but one or more tests fail
"T" - implemented, passing all tests
"e" - emulated, without tests
"E" - emulated, passing all tests
"n" - returns "not capable"
"-" - no implementation of this feature
fbsql ifx mssql oci8 pgsql
FEATURE | ibase | msql | mysql | odbc | sybase
simpleQuery x T x x x T T x T x
numCols x T x x x T T x T x
numRows x n n x x T E x T n
errorNative x n x n n T x x T n
prepare/execute e x e e e E T e E e
sequences e T n n n E T n T n
affectedRows x n x x n T T x T x
fetch modes x T x x x T T x T x
fetch row by number x n x x x x n x x x
transactions x x n n x x x x x n
auto-commit x x n n n n x x x n
error mapping x x e - - T T x E -
tableInfo x n n n x T n n x n
Info returned by getListOf
fbsql ifx mssql oci8 pgsql
TYPE | ibase | msql | mysql | odbc | sybase
tables x - - - x x x - x x
views - - - - x n - - x x
users - - - - - x - - x -
databases - - - - - x - - x -
functions - - - - - - - - x -

45
html/illt/DB/TESTERS Normal file
View File

@@ -0,0 +1,45 @@
How to run tests
----------------
1) First you need the "run-tests.php" script located at the root
directory of the PHP 4 source tar ball.
2) Download the lastest PEAR DB from CVS:
Where you want to place Pear files
# cd /usr/local/lib
Log to the repository (use "phpfi" as password):
# cvs -d :pserver:cvsread@cvs.php.net:/repository login
# cvs -d :pserver:cox@cvs.php.net:/repository co php4/run-tests.php
# cvs -d :pserver:cvsread@cvs.php.net:/repository co php4/pear
# cd php4
# php -f run-tests.php -- <test file or directory>
<test file or directory> can be:
pear/DB/tests: Common PEAR DB tests
pear/DB/tests/<backend>: Specific backend tests
pear/DB/tests/driver: Common tests for all the drivers
DB tester matrix
----------------
B - A - C - K - E - N - D - S
TESTER ibase ifx msql mssql mysql oci8 odbc pgsql sybase fbsql
John Horton - X - - - - - - - -
Tim Zickus - - - - - X - - - -
Tim Parkin - - - - - X - - - -
Paul Gardiner - X - - - - - - - -
Daniel, Adam - - - - - X - - - -
szii@sziisoft.com - - - - - - X¹ - - -
jmh3@linuxfreak.com - - - - - - - X - -
Kevin Henrikson - - - - - X - - - -
Stig Bakken - - - - X - - X - -
Chuck Hagenbuch - - - X - - - - - -
Ludovico Magnocavallo X - - - - - - - - -
MISSING TESTERS - - X - - - - - X X
Comments:
[1]: ODBC using IBM DB2

1282
html/illt/DB/common.php Normal file

File diff suppressed because it is too large Load Diff

123
html/illt/DB/dbase.php Normal file
View File

@@ -0,0 +1,123 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: dbase.php,v 1.2 2002/02/28 08:27:08 sebastian Exp $
//
// Database independent query interface definition for PHP's dbase
// extension.
//
// XXX legend:
// You have to compile your PHP with the --enable-dbase option
//
require_once "DB/common.php";
class DB_dbase extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $res_row = array();
var $result = 0;
// }}}
// {{{ constructor
/**
* DB_mysql constructor.
*
* @access public
*/
function DB_dbase()
{
$this->DB_common();
$this->phptype = 'dbase';
$this->dbsyntax = 'dbase';
$this->features = array(
'prepare' => false,
'pconnect' => false,
'transactions' => false,
'limit' => false
);
$this->errorcode_map = array();
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('dbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
ob_start();
$conn = dbase_open($dsninfo['database'], 0);
$error = ob_get_contents();
ob_end_clean();
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null,
null, null, strip_tags($error));
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = dbase_close($this->connection);
$this->connection = null;
return $ret;
}
function &query($query = null)
{
// emulate result resources
$this->res_row[$this->result] = 0;
return new DB_result($this, $this->result++);
}
function fetchInto($res, &$row, $fetchmode, $rownum = null)
{
if ($rownum === null) {
$rownum = $this->res_row[$res]++;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$row = @dbase_get_record_with_names($this->connection, $rownum);
} else {
$row = @dbase_get_record($this->connection, $rownum);
}
if (!$row) {
return null;
}
return DB_OK;
}
function numCols($foo)
{
return dbase_numfields($this->connection);
}
function numRows($foo)
{
return dbase_numrecords($this->connection);
}
}
?>

618
html/illt/DB/fbsql.php Normal file
View File

@@ -0,0 +1,618 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: Frank M. Kromann <frank@frontbase.com> |
// +----------------------------------------------------------------------+
//
// $Id: fbsql.php,v 1.14 2002/02/28 08:27:08 sebastian Exp $
//
// Database independent query interface definition for PHP's FrontBase
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the fbsql function should
// be registered here.
//
require_once "DB/common.php";
class DB_fbsql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $num_rows = array();
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
// }}}
// {{{ constructor
/**
* DB_fbsql constructor.
*
* @access public
*/
function DB_fbsql()
{
$this->DB_common();
$this->phptype = 'fbsql';
$this->dbsyntax = 'fbsql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'emulate'
);
$this->errorcode_map = array(
1004 => DB_ERROR_CANNOT_CREATE,
1005 => DB_ERROR_CANNOT_CREATE,
1006 => DB_ERROR_CANNOT_CREATE,
1007 => DB_ERROR_ALREADY_EXISTS,
1008 => DB_ERROR_CANNOT_DROP,
1046 => DB_ERROR_NODBSELECTED,
1050 => DB_ERROR_ALREADY_EXISTS,
1051 => DB_ERROR_NOSUCHTABLE,
1054 => DB_ERROR_NOSUCHFIELD,
1062 => DB_ERROR_ALREADY_EXISTS,
1064 => DB_ERROR_SYNTAX,
1100 => DB_ERROR_NOT_LOCKED,
1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
1146 => DB_ERROR_NOSUCHTABLE,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
* @access public
* @return int DB_OK on success, a DB error on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('fbsql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect';
ini_set('track_errors', true);
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = @$connect_function($dbhost);
} else {
$conn = false;
}
ini_restore("track_errors");
if (empty($conn)) {
if (empty($php_errormsg)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $php_errormsg);
}
}
if ($dsninfo['database']) {
if (!fbsql_select_db($dsninfo['database'], $conn)) {
return $this->fbsqlRaiseError();
}
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @access public
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = fbsql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to fbsql and return the results as a fbsql resource
* identifier.
*
* @param the SQL query
*
* @access public
*
* @return mixed returns a valid fbsql result for successful SELECT
* queries, DB_OK for other successful queries. A DB error is
* returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @fbsql_query("$query;", $this->connection);
if (!$result) {
return $this->fbsqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if (DB::isManip($query)) {
return DB_OK;
}
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
return $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal fbsql 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 @fbsql_next_result($result);
}
// }}}
// {{{ fetch_assoc()
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result fbsql result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result fbsql result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
* @access public
*
* @return int DB_OK on success, a DB error on failure
*/
function fetchInto($result, &$arr, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@fbsql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @fbsql_fetch_array($result, FBSQL_ASSOC);
} else {
$arr = @fbsql_fetch_row($result);
}
if (!$arr) {
$errno = @fbsql_errno($this->connection);
if (!$errno) {
return NULL;
}
return $this->fbsqlRaiseError($errno);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result fbsql result identifier or DB statement identifier
*
* @access public
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return fbsql_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
// }}}
// {{{ autoCommit()
function autoCommit($onoff=false)
{
if ($onoff) {
$this->query("SET COMMIT TRUE");
} else {
$this->query("SET COMMIT FALSE");
}
}
// }}}
// {{{ commit()
function commit()
{
fbsql_commit();
}
// }}}
// {{{ rollback()
function rollback()
{
fbsql_rollback();
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result fbsql result identifier
*
* @access public
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @fbsql_num_fields($result);
if (!$cols) {
return $this->fbsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result fbsql result identifier
*
* @access public
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @fbsql_num_rows($result);
if ($rows === null) {
return $this->fbsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @fbsql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int native fbsql error code
*/
function errorNative()
{
return fbsql_errno($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for fbsql. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
$repeat = 0;
do {
$seqname = sprintf($this->getOption("seqname_format"), $sqn);
$result = $this->query("INSERT INTO ${seqname} VALUES(NULL)");
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $result;
}
return fbsql_insert_id($this->connection);
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
$seqname = sprintf($this->getOption("seqname_format"), $sqn);
return $this->query("CREATE TABLE ${seqname} ".
'(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
' PRIMARY KEY(id))');
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$sqn = preg_replace('/[^a-z0-9_]/i', '_', $seq_name);
$seqname = sprintf($this->getOption("seqname_format"), $sqn);
return $this->query("DROP TABLE ${seqname} RESTRICT");
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query)
{
if ($this->options['optimize'] == 'portability') {
// "DELETE FROM table" gives 0 affected rows in fbsql.
// This little hack lets you know how many rows were deleted.
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
// }}}
// {{{ fbsqlRaiseError()
function fbsqlRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(fbsql_errno($this->connection));
}
return $this->raiseError($errno, null, null, null,
fbsql_error($this->connection));
}
// }}}
// {{{ tableInfo()
function tableInfo($result, $mode = null) {
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $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
* ["order"][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'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = @fbsql_list_fields($this->dsn['database'],
$result, $this->connection);
if (empty($id)) {
return $this->fbsqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->fbsqlRaiseError();
}
}
$count = @fbsql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @fbsql_field_table ($id, $i);
$res[$i]['name'] = @fbsql_field_name ($id, $i);
$res[$i]['type'] = @fbsql_field_type ($id, $i);
$res[$i]['len'] = @fbsql_field_len ($id, $i);
$res[$i]['flags'] = @fbsql_field_flags ($id, $i);
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @fbsql_field_table ($id, $i);
$res[$i]['name'] = @fbsql_field_name ($id, $i);
$res[$i]['type'] = @fbsql_field_type ($id, $i);
$res[$i]['len'] = @fbsql_field_len ($id, $i);
$res[$i]['flags'] = @fbsql_field_flags ($id, $i);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@fbsql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = 'select "table_name" from information_schema.tables';
break;
default:
return null;
}
return $sql;
}
// }}}
}
// TODO/wishlist:
// longReadlen
// binmode
?>

592
html/illt/DB/ibase.php Normal file
View File

@@ -0,0 +1,592 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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> |
// +----------------------------------------------------------------------+
//
// $Id: ibase.php,v 1.36.2.2 2002/04/09 19:04:13 ssb Exp $
//
// Database independent query interface definition for PHP's Interbase
// extension.
//
require_once 'DB/common.php';
class DB_ibase extends DB_common
{
var $connection;
var $phptype, $dbsyntax;
var $autocommit = 1;
var $manip_query = array();
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,
-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,
-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
);
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('interbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ?
($dsninfo['hostspec'] . ':/' . $dsninfo['database']) :
$dsninfo['database'];
$connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect';
$params = array();
$params[] = $dbhost;
$params[] = !empty($user) ? $user : null;
$params[] = !empty($pw) ? $pw : 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;
/*
if ($dbhost && $user && $pw) {
$conn = $connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = $connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = $connect_function($dbhost);
} else {
return $this->raiseError("no host, user or password");
}
*/
$conn = @call_user_func_array($connect_function, $params);
if (!$conn) {
return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED);
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = @ibase_close($this->connection);
$this->connection = null;
return $ret;
}
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 DB::isManip($query) ? 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)
{
if ($this->dsn['dbsyntax'] == 'firebird') {
$from++; // SKIP starts from 1, ie SKIP 1 starts from the first record
$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;
}
// }}}
function fetchInto($result, &$ar, $fetchmode, $rownum = null)
{
if ($rownum !== NULL) {
return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE);
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$ar = get_object_vars(ibase_fetch_object($result));
if ($ar && $this->options['optimize'] == 'portability') {
$ar = array_change_key_case($ar, CASE_LOWER);
}
} else {
$ar = ibase_fetch_row($result);
}
if (!$ar) {
if ($errmsg = ibase_errmsg()) {
return $this->ibaseRaiseError(null, $errmsg);
} else {
return null;
}
}
return DB_OK;
}
function freeResult()
{
if (is_resource($result)) {
return ibase_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
function freeQuery($query)
{
ibase_free_query($query);
return true;
}
function numCols($result)
{
$cols = ibase_num_fields($result);
if (!$cols) {
return $this->ibaseRaiseError();
}
return $cols;
}
function prepare($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$stmt = ibase_prepare($query);
$this->manip_query[(int)$stmt] = DB::isManip($query);
return $stmt;
}
function execute($stmt, $data = false)
{
$result = ibase_execute($stmt, $data);
if (!$result) {
return $this->ibaseRaiseError();
}
if ($this->autocommit) {
ibase_commit($this->connection);
}
return DB::isManip($this->manip_query[(int)$stmt]) ? DB_OK : new DB_result($this, $result);
}
function autoCommit($onoff = false)
{
$this->autocommit = $onoff ? 1 : 0;
return DB_OK;
}
function commit()
{
return ibase_commit($this->connection);
}
function rollback($trans_number)
{
return ibase_rollback($this->connection, $trans_number);
}
function transactionInit($trans_args = 0)
{
return $trans_args ? ibase_trans($trans_args, $this->connection) : ibase_trans();
}
// {{{ nextId()
/**
* Get the next value in a sequence.
*
* If the sequence does not exist, it will be created,
* unless $ondemand is false.
*
* @access public
* @param string $seq_name the name of the sequence
* @param bool $ondemand whether to create the sequence on demand
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("SELECT GEN_ID(${sqn}_SEQ, 1) FROM RDB\$GENERATORS"
." WHERE RDB\$GENERATOR_NAME='${sqn}_SEQ'");
$this->popErrorHandling();
if ($ondemand && DB::isError($result)) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $result;
}
$arr = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Create the sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function createSequence($seq_name)
{
$sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("CREATE GENERATOR ${sqn}_SEQ");
$this->popErrorHandling();
return $result;
}
// }}}
// {{{ dropSequence()
/**
* Drop a sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function dropSequence($seq_name)
{
$sqn = strtoupper(preg_replace('/[^a-z0-9_]/i', '_', $seq_name));
return $this->query("DELETE FROM RDB\$GENERATORS WHERE RDB\$GENERATOR_NAME='${sqn}_SEQ'");
}
// }}}
// {{{ _ibaseFieldFlags()
/**
* get the Flags of a Field
*
* @param string $field_name the name of the field
* @param string $table_name the name of the table
*
* @return string The flags of the field ("primary_key", "unique_key", "not_null"
* "default", "computed" and "blob" are supported)
* @access private
*/
function _ibaseFieldFlags($field_name, $table_name)
{
$sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE'
.' FROM RDB$INDEX_SEGMENTS I'
.' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME'
.' WHERE I.RDB$FIELD_NAME=\''.$field_name.'\''
.' AND R.RDB$RELATION_NAME=\''.$table_name.'\'';
$result = ibase_query($this->connection, $sql);
if (empty($result)) {
return $this->ibaseRaiseError();
}
if ($obj = @ibase_fetch_object($result)) {
ibase_free_result($result);
if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') {
$flags = 'primary_key ';
}
if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') {
$flags .= 'unique_key ';
}
}
$sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,'
.' R.RDB$DEFAULT_SOURCE AS DSOURCE,'
.' F.RDB$FIELD_TYPE AS FTYPE,'
.' F.RDB$COMPUTED_SOURCE AS CSOURCE'
.' FROM RDB$RELATION_FIELDS R '
.' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME'
.' WHERE R.RDB$RELATION_NAME=\''.$table_name.'\''
.' AND R.RDB$FIELD_NAME=\''.$field_name.'\'';
$result = ibase_query($this->connection, $sql);
if (empty($result)) {
return $this->ibaseRaiseError();
}
if ($obj = @ibase_fetch_object($result)) {
ibase_free_result($result);
if (isset($obj->NFLAG)) {
$flags .= 'not_null ';
}
if (isset($obj->DSOURCE)) {
$flags .= 'default ';
}
if (isset($obj->CSOURCE)) {
$flags .= 'computed ';
}
if (isset($obj->FTYPE) && $obj->FTYPE == 261) {
$flags .= 'blob ';
}
}
return trim($flags);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support 'flags'and 'table' if called from a db_result
*
* @param mixed $resource Interbase result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $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
* ["order"][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'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = ibase_query($this->connection,"SELECT * FROM $result");
if (empty($id)) {
return $this->ibaseRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->ibaseRaiseError();
}
}
$count = @ibase_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$info = @ibase_field_info($id, $i);
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = $info['name'];
$res[$i]['type'] = $info['type'];
$res[$i]['len'] = $info['length'];
$res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$info = @ibase_field_info($id, $i);
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = $info['name'];
$res[$i]['type'] = $info['type'];
$res[$i]['len'] = $info['length'];
$res[$i]['flags'] = (is_string($result)) ? $this->_ibaseFieldFlags($info['name'], $result) : '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_resource($id)) {
ibase_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
// {{{ ibaseRaiseError()
function ibaseRaiseError($errno = null, $errmsg = null)
{
if ($errmsg === null)
$errmsg = ibase_errmsg();
// memo for the interbase php module hackers: we need something similar
// to mysql_errno() to retrieve error codes instead of this ugly hack
if (preg_match('/^([^0-9\-]+)([0-9\-]+)\s+(.*)$/', $errmsg, $m)) {
if ($errno === null) {
$ibase_errno = (int)$m[2];
// try to interpret Interbase error code (that's why we need ibase_errno()
// in the interbase module to return the real error code)
switch ($ibase_errno) {
case -204:
if (is_int(strpos($m[3], 'Table unknown'))) {
$errno = DB_ERROR_NOSUCHTABLE;
}
break;
default:
$errno = $this->errorCode($ibase_errno);
}
}
$errmsg = $m[2] . ' ' . $m[3];
}
return $this->raiseError($errno, null, null, $errmsg,
$this->last_query);
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

323
html/illt/DB/ifx.php Normal file
View File

@@ -0,0 +1,323 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id: ifx.php,v 1.18 2002/02/28 08:27:09 sebastian Exp $
//
// Database independent query interface definition for PHP's Informix
// extension.
//
// Legend:
// For more info on Informix errors see:
// http://www.informix.com/answers/english/ierrors.htm
//
// TODO:
// - set needed env Informix vars on connect
// - implement native prepare/execute
require_once 'DB/common.php';
class DB_ifx extends DB_common
{
var $connection;
var $affected = 0;
var $dsn = array();
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
function DB_ifx()
{
$this->phptype = 'ifx';
$this->dbsyntax = 'ifx';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
$this->errorcode_map = array(
'-201' => DB_ERROR_SYNTAX,
'-206' => DB_ERROR_NOSUCHTABLE,
'-217' => DB_ERROR_NOSUCHFIELD,
'-329' => DB_ERROR_NODBSELECTED,
'-1204' => DB_ERROR_INVALID_DATE,
'-1205' => DB_ERROR_INVALID_DATE,
'-1206' => DB_ERROR_INVALID_DATE,
'-1209' => DB_ERROR_INVALID_DATE,
'-1210' => DB_ERROR_INVALID_DATE,
'-1212' => DB_ERROR_INVALID_DATE
);
}
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect(&$dsninfo, $persistent = false)
{
if (!DB::assertExtension('informix'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$dbhost = $dsninfo['hostspec'] ? '@' . $dsninfo['hostspec'] : '';
$dbname = $dsninfo['database'] ? $dsninfo['database'] . $dbhost : '';
$user = $dsninfo['username'] ? $dsninfo['username'] : '';
$pw = $dsninfo['password'] ? $dsninfo['password'] : '';
$connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect';
$this->connection = @$connect_function($dbname, $user, $pw);
if (!is_resource($this->connection)) {
return $this->ifxraiseError(DB_ERROR_CONNECT_FAILED);
}
return DB_OK;
}
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @ifx_close($this->connection);
$this->connection = null;
return $ret;
}
/**
* Send a query to Informix and return the results as a
* Informix resource identifier.
*
* @param $query the SQL query
*
* @return int returns a valid Informix result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
if (preg_match('/(SELECT)/i', $query)) { //TESTME: Use !DB::isManip()?
// the scroll is needed for fetching absolute row numbers
// in a select query result
$result = @ifx_query($query, $this->connection, IFX_SCROLL);
} else {
$result = @ifx_query($query, $this->connection);
}
if (!$result) {
return $this->ifxraiseError();
}
$this->affected = ifx_affected_rows ($result);
// Determine which queries that should return data, and which
// should return an error code only.
if (preg_match('/(SELECT)/i', $query)) {
return $result;
}
return DB_OK;
}
// {{{ nextResult()
/**
* Move the internal ifx 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;
}
// }}}
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns an _estimate_ value.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
return $this->affected;
}
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result Informix result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
/**
* Fetch a row and return as array.
*
* @param $result Informix result identifier
* @param $row (reference) array where data from the row is stored
* @param $fetchmode how the resulting array should be indexed
* @param $rownum the row number to fetch
*
* @return int an array on success, a DB error code on failure, NULL
* if there is no more data
*/
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
if (($rownum !== null) && ($rownum < 0)) {
return null;
}
// if $rownum is null, fetch row will return the next row
if (!$row = @ifx_fetch_row($result, $rownum)) {
return null;
}
if ($fetchmode !== DB_FETCHMODE_ASSOC) {
$i=0;
$order = array();
foreach ($row as $key => $val) {
$order[$i++] = $val;
}
$row = $order;
}
return DB_OK;
}
function numRows($result)
{
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
/**
* Get the number of columns in a result set.
*
* @param $result Informix result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
if (!$cols = @ifx_num_fields($result)) {
return $this->ifxraiseError();
}
return $cols;
}
/**
* Free the internal resources associated with $result.
*
* @param $result Informix result identifier
*
* @return bool TRUE on success, DB_error on error
*/
function freeResult($result)
{
if (is_resource($result)) {
if (!@ifx_free_result($result)) {
return $this->ifxraiseError();
}
return true;
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
function ifxraiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(ifx_error());
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
/**
* Map native error codes to DB's portable ones. Requires that
* the DB implementation's constructor fills in the $errorcode_map
* property.
*
* @return int a portable DB error code, or DB_ERROR if this DB
* implementation has no mapping for the given error code.
*/
function errorCode($nativecode)
{
if (ereg('SQLCODE=(.*)]', $nativecode, $match)) {
$code = $match[1];
if (isset($this->errorcode_map[$code])) {
return $this->errorcode_map[$code];
}
}
return DB_ERROR;
}
/**
* Get the native error message of the last error (if any) that
* occured on the current connection.
*
* @return int native Informix error code
*/
function errorNative()
{
return ifx_error() . ' ' . ifx_errormsg();
}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
}
?>

210
html/illt/DB/msql.php Normal file
View File

@@ -0,0 +1,210 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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> |
// +----------------------------------------------------------------------+
//
// $Id: msql.php,v 1.25 2002/02/28 08:27:10 sebastian Exp $
//
// Database independent query interface definition for PHP's Mini-SQL
// extension.
//
require_once 'DB/common.php';
class DB_msql extends DB_common
{
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
function DB_msql()
{
$this->DB_common();
$this->phptype = 'msql';
$this->dbsyntax = 'msql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('msql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$connect_function = $persistent ? 'msql_pconnect' : 'msql_connect';
if ($dbhost && $user && $pw) {
$conn = $connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = $connect_function($dbhost,$user);
} else {
$conn = $connect_function($dbhost);
}
if (!$conn) {
$this->raiseError(DB_ERROR_CONNECT_FAILED);
}
if (!@msql_select_db($dsninfo['database'], $conn)){
return $this->raiseError(DB_ERROR_NODBSELECTED);
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = @msql_close($this->connection);
$this->connection = null;
return $ret;
}
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @msql_query($query, $this->connection);
if (!$result) {
return $this->raiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// {{{ nextResult()
/**
* Move the internal msql 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;
}
// }}}
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
function fetchInto($result, &$ar, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@msql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$ar = @msql_fetch_array($result, MSQL_ASSOC);
} else {
$ar = @msql_fetch_row($result);
}
if (!$ar) {
if ($error = msql_error()) {
return $this->raiseError($error);
} else {
return null;
}
}
return DB_OK;
}
function freeResult($result)
{
if (is_resource($result)) {
return @msql_free_result($result);
}
if (!isset($this->prepare_tokens[$result])) {
return false;
}
unset($this->prepare_tokens[$result]);
unset($this->prepare_types[$result]);
return true;
}
function numCols($result)
{
$cols = @msql_num_fields($result);
if (!$cols) {
return $this->raiseError();
}
return $cols;
}
function numRows($result)
{
$rows = @msql_num_rows($result);
if (!$rows) {
return $this->raiseError();
}
return $rows;
}
/**
* Gets the number of rows affected by a query.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
return @msql_affected_rows($this->connection);
}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
}
?>

500
html/illt/DB/mssql.php Normal file
View File

@@ -0,0 +1,500 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php,v 1.40 2002/02/28 08:27:10 sebastian Exp $
//
// Database independent query interface definition for PHP's Microsoft SQL Server
// extension.
//
require_once 'DB/common.php';
class DB_mssql extends DB_common
{
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $autocommit = true;
function DB_mssql()
{
$this->DB_common();
$this->phptype = 'mssql';
$this->dbsyntax = 'mssql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'emulate'
);
// XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
$this->errorcode_map = array(
);
}
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('mssql') && !DB::assertExtension('sybase')
&& !DB::assertExtension('sybase_ct'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} else {
$conn = @$connect_function($dbhost);
}
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, mssql_get_last_message());
}
if ($dsninfo['database']) {
if (!@mssql_select_db($dsninfo['database'], $conn)) {
return $this->raiseError(DB_ERROR_NODBSELECTED, null, null,
null, mssql_get_last_message());
}
}
$this->connection = $conn;
return DB_OK;
}
function disconnect()
{
$ret = @mssql_close($this->connection);
$this->connection = null;
return $ret;
}
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @mssql_query('BEGIN TRAN', $this->connection);
if (!$result) {
return $this->mssqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @mssql_query($query, $this->connection);
if (!$result) {
return $this->mssqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return $ismanip ? DB_OK : $result;
}
// {{{ nextResult()
/**
* Move the internal mssql 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 mssql_next_result($result);
}
// }}}
function &fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
function fetchInto($result, &$ar, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@mssql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$ar = @mssql_fetch_array($result);
} else {
$ar = @mssql_fetch_row($result);
}
if (!$ar) {
/* This throws informative error messages,
don't use it for now
if ($msg = mssql_get_last_message()) {
return $this->raiseError($msg);
}
*/
return null;
}
return DB_OK;
}
function freeResult($result)
{
if (is_resource($result)) {
return @mssql_free_result($result);
}
if (!isset($this->prepare_tokens[$result])) {
return false;
}
unset($this->prepare_tokens[$result]);
unset($this->prepare_types[$result]);
return true;
}
function numCols($result)
{
$cols = @mssql_num_fields($result);
if (!$cols) {
return $this->mssqlRaiseError();
}
return $cols;
}
function numRows($result)
{
$rows = @mssql_num_rows($result);
if ($rows === false) {
return $this->mssqlRaiseError();
}
return $rows;
}
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
$result = @mssql_query('COMMIT TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @mssql_query('ROLLBACK TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$res = @mssql_query('select @@rowcount', $this->connection);
if (!$res) {
return $this->mssqlRaiseError();
}
$ar = @mssql_fetch_row($res);
if (!$ar) {
$result = 0;
} else {
@mssql_free_result($res);
$result = $ar[0];
}
} else {
$result = 0;
}
return $result;
}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MSSQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
{
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$result = $this->query("SELECT @@IDENTITY FROM $seqname");
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
return $result[0];
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("CREATE TABLE $seqname ".
'([id] [int] IDENTITY (1, 1) NOT NULL ,' .
'[vapor] [int] NULL)');
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE $seqname");
}
// }}}
function errorCode()
{
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$error_code = $this->getOne('select @@ERROR as ErrorCode');
$this->popErrorHandling();
// XXX Debug
if (!isset($this->errorcode_map[$error_code])) {
return DB_ERROR;
}
return $error_code;
}
function mssqlRaiseError($code = null)
{
if ($code !== null) {
$code = $this->errorCode();
if (DB::isError($code)) {
return $this->raiseError($code);
}
}
return $this->raiseError($code, null, null, null,
mssql_get_last_message());
}
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support table name and flags if called from a db_result
*
* @param mixed $resource SQL Server result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $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
* ["order"][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'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = mssql_query("SELECT * FROM $result", $this->connection);
if (empty($id)) {
return $this->mssqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->mssqlRaiseError();
}
}
$count = @mssql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @mssql_field_name($id, $i);
$res[$i]['type'] = @mssql_field_type($id, $i);
$res[$i]['len'] = @mssql_field_length($id, $i);
$res[$i]['flags'] = '';
}
} else { // full
$res['num_fields']= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @mssql_field_name($id, $i);
$res[$i]['type'] = @mssql_field_type($id, $i);
$res[$i]['len'] = @mssql_field_length($id, $i);
$res[$i]['flags'] = '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@mssql_free_result($id);
}
return $res;
}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "select name from sysobjects where type = 'U' order by name";
break;
case 'views':
$sql = "select name from sysobjects where type = 'V'";
break;
default:
return null;
}
return $sql;
}
// }}}
}
?>

847
html/illt/DB/mysql.php Normal file
View File

@@ -0,0 +1,847 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: Stig Bakken <ssb@fast.no> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.89.2.1 2002/04/09 19:04:14 ssb Exp $
//
// Database independent query interface definition for PHP's MySQL
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the mysql function should
// be registered here.
//
require_once "DB/common.php";
class DB_mysql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $num_rows = array();
var $transaction_opcount = 0;
var $autocommit = true;
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
var $_db = false;
// }}}
// {{{ constructor
/**
* DB_mysql constructor.
*
* @access public
*/
function DB_mysql()
{
$this->DB_common();
$this->phptype = 'mysql';
$this->dbsyntax = 'mysql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
1004 => DB_ERROR_CANNOT_CREATE,
1005 => DB_ERROR_CANNOT_CREATE,
1006 => DB_ERROR_CANNOT_CREATE,
1007 => DB_ERROR_ALREADY_EXISTS,
1008 => DB_ERROR_CANNOT_DROP,
1046 => DB_ERROR_NODBSELECTED,
1050 => DB_ERROR_ALREADY_EXISTS,
1051 => DB_ERROR_NOSUCHTABLE,
1054 => DB_ERROR_NOSUCHFIELD,
1062 => DB_ERROR_ALREADY_EXISTS,
1064 => DB_ERROR_SYNTAX,
1100 => DB_ERROR_NOT_LOCKED,
1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
1146 => DB_ERROR_NOSUCHTABLE,
1048 => DB_ERROR_CONSTRAINT,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
* @access public
* @return int DB_OK on success, a DB error on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('mysql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
if (isset($dsninfo['protocol']) && $dsninfo['protocol'] == 'unix') {
$dbhost = ':' . $dsninfo['socket'];
} else {
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
if (!empty($dsninfo['port'])) {
$dbhost .= ':' . $dsninfo['port'];
}
}
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
@ini_set('track_errors', true);
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = @$connect_function($dbhost);
} else {
$conn = false;
}
@ini_restore('track_errors');
if (empty($conn)) {
if (($err = @mysql_error()) != '') {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $err);
} elseif (empty($php_errormsg)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $php_errormsg);
}
}
if ($dsninfo['database']) {
if (!@mysql_select_db($dsninfo['database'], $conn)) {
switch(mysql_errno($conn)) {
case 1049:
return $this->raiseError(DB_ERROR_NOSUCHDB, null, null,
null, mysql_error($conn));
break;
case 1044:
return $this->raiseError(DB_ERROR_ACCESS_VIOLATION, null, null,
null, mysql_error($conn));
break;
default:
return $this->raiseError(DB_ERROR, null, null,
null, mysql_error($conn));
break;
}
}
// fix to allow calls to different databases in the same script
$this->_db = $dsninfo['database'];
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @access public
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = mysql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to MySQL and return the results as a MySQL resource
* identifier.
*
* @param the SQL query
*
* @access public
*
* @return mixed returns a valid MySQL result for successful SELECT
* queries, DB_OK for other successful queries. A DB error is
* returned on failure.
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @mysql_query('SET AUTOCOMMIT=0', $this->connection);
$result = @mysql_query('BEGIN', $this->connection);
if (!$result) {
return $this->mysqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @mysql_query($query, $this->connection);
if (!$result) {
return $this->mysqlRaiseError();
}
if (is_resource($result)) {
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
return $result;
}
return DB_OK;
}
// }}}
// {{{ nextResult()
/**
* Move the internal mysql 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;
}
// }}}
// {{{ fetch_assoc()
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result MySQL result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result MySQL result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
* @access public
*
* @return int DB_OK on success, a DB error on failure
*/
function fetchInto($result, &$arr, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@mysql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @mysql_fetch_array($result, MYSQL_ASSOC);
} else {
$arr = @mysql_fetch_row($result);
}
if (!$arr) {
$errno = @mysql_errno($this->connection);
if (!$errno) {
return NULL;
}
return $this->mysqlRaiseError($errno);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result MySQL result identifier or DB statement identifier
*
* @access public
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return mysql_free_result($result);
}
$result = (int)$result; // $result is a prepared query handle
if (!isset($this->prepare_tokens[$result])) {
return false;
}
// [ssb]: WTF? unset($this->prepare_types[$result]) makes PHP
// crash on my laptop (4.1.2 as well as 4.3.0-dev)
$copy = $this->prepare_types;
unset($copy[$result]);
$this->prepare_types = $copy;
// unset($this->prepare_types[$result]);
$copy = $this->prepare_tokens;
unset($copy[$result]);
$this->prepare_tokens = $copy;
// unset($this->prepare_tokens[$result]);
return true;
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result MySQL result identifier
*
* @access public
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @mysql_num_fields($result);
if (!$cols) {
return $this->mysqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result MySQL result identifier
*
* @access public
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @mysql_num_rows($result);
if ($rows === null) {
return $this->mysqlRaiseError();
}
return $rows;
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mysql_query('COMMIT', $this->connection);
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mysqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mysql_query('ROLLBACK', $this->connection);
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mysqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @mysql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int native MySQL error code
*/
function errorNative()
{
return mysql_errno($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MySQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param string $seq_name the name of the sequence
*
* @param bool $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return mixed a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("UPDATE ${seqname} ".
'SET id=LAST_INSERT_ID(id+1)');
$this->popErrorHandling();
if ($result == DB_OK) {
/** COMMON CASE **/
$id = mysql_insert_id($this->connection);
if ($id != 0) {
return $id;
}
/** EMPTY SEQ TABLE **/
// Sequence table must be empty for some reason, so fill it and return 1
// Obtain a user-level lock
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
if (DB::isError($result)) {
return $this->raiseError($result);
}
if ($result == 0) {
// Failed to get the lock, bail with a DB_ERROR_NOT_LOCKED error
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
}
// add the default value
$result = $this->query("REPLACE INTO ${seqname} VALUES (0)");
if (DB::isError($result)) {
return $this->raiseError($result);
}
// Release the lock
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
if (DB::isError($result)) {
return $this->raiseError($result);
}
// We know what the result will be, so no need to try again
return 1;
/** ONDEMAND TABLE CREATION **/
} elseif ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE)
{
$result = $this->createSequence($seq_name);
// Since createSequence initializes the ID to be 1,
// we do not need to retrieve the ID again (or we will get 2)
if (DB::isError($result)) {
return $this->raiseError($result);
} else {
// First ID of a newly created sequence is 1
return 1;
}
/** BACKWARDS COMPAT **/
} elseif (DB::isError($result) &&
$result->getCode() == DB_ERROR_ALREADY_EXISTS)
{
// see _BCsequence() comment
$result = $this->_BCsequence($seqname);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$repeat = 1;
}
} while ($repeat);
return $this->raiseError($result);
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query("CREATE TABLE ${seqname} ".
'(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
' PRIMARY KEY(id))');
if (DB::isError($res)) {
return $res;
}
// insert yields value 1, nextId call will generate ID 2
return $this->query("INSERT INTO ${seqname} VALUES(0)");
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE ${seqname}");
}
// }}}
/**
* Bacwards Compatibility with old sequence emulation implementation
* (clean up the dupes)
* @param string $seqname The sequence name to clean up
* @return mixed DB_Error or true
*/
function _BCsequence($seqname)
{
// Obtain a user-level lock... this will release any previous
// application locks, but unlike LOCK TABLES, it does not abort
// the current transaction and is much less frequently used.
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
if (DB::isError($result)) {
return $result;
}
if ($result == 0) {
// Failed to get the lock, can't do the conversion, bail
// with a DB_ERROR_NOT_LOCKED error
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
}
$highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
if (DB::isError($highest_id)) {
return $highest_id;
}
// This should kill all rows except the highest
// We should probably do something if $highest_id isn't
// numeric, but I'm at a loss as how to handle that...
$result = $this->query("DELETE FROM ${seqname} WHERE id <> $highest_id");
if (DB::isError($result)) {
return $result;
}
// If another thread has been waiting for this lock,
// it will go thru the above procedure, but will have no
// real effect
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
if (DB::isError($result)) {
return $result;
}
return true;
}
// {{{ quote()
/**
* Quote the given string so it can be safely used within string delimiters
* in a query.
* @param $string mixed Data to be quoted
* @return mixed "NULL" string, quoted string or original data
*/
function quote($str = null)
{
switch (strtolower(gettype($str))) {
case 'null':
return 'NULL';
case 'integer':
return $str;
case 'string':
default:
return "'".mysql_escape_string($str)."'";
}
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query, $subject = null)
{
if ($this->options['optimize'] == 'portability') {
// "DELETE FROM table" gives 0 affected rows in MySQL.
// This little hack lets you know how many rows were deleted.
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
// }}}
// {{{ modifyLimitQuery()
function modifyLimitQuery($query, $from, $count)
{
$query = $query . " LIMIT $from, $count";
return $query;
}
// }}}
// {{{ mysqlRaiseError()
function mysqlRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(mysql_errno($this->connection));
}
return $this->raiseError($errno, null, null, null,
@mysql_errno($this->connection) . " ** " .
@mysql_error($this->connection));
}
// }}}
// {{{ tableInfo()
function tableInfo($result, $mode = null) {
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $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
* ["order"][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'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = @mysql_list_fields($this->dsn['database'],
$result, $this->connection);
if (empty($id)) {
return $this->mysqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->mysqlRaiseError();
}
}
$count = @mysql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @mysql_field_table ($id, $i);
$res[$i]['name'] = @mysql_field_name ($id, $i);
$res[$i]['type'] = @mysql_field_type ($id, $i);
$res[$i]['len'] = @mysql_field_len ($id, $i);
$res[$i]['flags'] = @mysql_field_flags ($id, $i);
}
} else { // full
$res['num_fields']= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @mysql_field_table ($id, $i);
$res[$i]['name'] = @mysql_field_name ($id, $i);
$res[$i]['type'] = @mysql_field_type ($id, $i);
$res[$i]['len'] = @mysql_field_len ($id, $i);
$res[$i]['flags'] = @mysql_field_flags ($id, $i);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@mysql_free_result($id);
}
return $res;
}
// }}}
// {{{ getTablesQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "SHOW TABLES";
break;
case 'views':
return DB_ERROR_NOT_CAPABLE;
case 'users':
$sql = "select distinct User from user";
if($this->dsn['database'] != 'mysql') {
$dsn = $this->dsn;
$dsn['database'] = 'mysql';
if (DB::isError($db = DB::connect($dsn))) {
return $db;
}
$sql = $db->getCol($sql);
$db->disconnect();
// XXX Fixme the mysql driver should take care of this
if (!@mysql_select_db($this->dsn['database'], $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
}
return $sql;
break;
case 'databases':
$sql = "SHOW DATABASES";
break;
default:
return null;
}
return $sql;
}
// }}}
// TODO/wishlist:
// longReadlen
// binmode
}
?>

664
html/illt/DB/oci8.php Normal file
View File

@@ -0,0 +1,664 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: James L. Pine <jlp@valinux.com> |
// +----------------------------------------------------------------------+
//
// $Id: oci8.php,v 1.47.2.1 2002/04/09 19:04:15 ssb Exp $
//
// Database independent query interface definition for PHP's Oracle 8
// call-interface extension.
//
//
// be aware... OCIError() only appears to return anything when given a
// statement, so functions return the generic DB_ERROR instead of more
// useful errors that have to do with feedback from the database.
//
require_once 'DB/common.php';
class DB_oci8 extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $manip_query = array();
var $prepare_types = array();
var $autoCommit = 1;
var $last_stmt = false;
// }}}
// {{{ constructor
function DB_oci8()
{
$this->DB_common();
$this->phptype = 'oci8';
$this->dbsyntax = 'oci8';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
900 => DB_ERROR_SYNTAX,
904 => DB_ERROR_NOSUCHFIELD,
923 => DB_ERROR_SYNTAX,
942 => DB_ERROR_NOSUCHTABLE,
955 => DB_ERROR_ALREADY_EXISTS,
1476 => DB_ERROR_DIVZERO,
1722 => DB_ERROR_INVALID_NUMBER,
2289 => DB_ERROR_NOSUCHTABLE,
2291 => DB_ERROR_CONSTRAINT,
2449 => DB_ERROR_CONSTRAINT,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('oci8')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$hostspec = $dsninfo['hostspec'];
$connect_function = $persistent ? 'OCIPLogon' : 'OCILogon';
if ($hostspec) {
$conn = @$connect_function($user,$pw,$hostspec);
} elseif ($user || $pw) {
$conn = @$connect_function($user,$pw);
} else {
$conn = false;
}
if ($conn == false) {
$error = OCIError();
$error = (is_array($error)) ? $error['message'] : null;
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $error);
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @OCILogOff($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to oracle and return the results as an oci8 resource
* identifier.
*
* @param $query the SQL query
*
* @return int returns a valid oci8 result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @OCIParse($this->connection, $query);
if (!$result) {
return $this->oci8RaiseError();
}
if ($this->autoCommit) {
$success = @OCIExecute($result,OCI_COMMIT_ON_SUCCESS);
} else {
$success = @OCIExecute($result,OCI_DEFAULT);
}
if (!$success) {
return $this->oci8RaiseError($result);
}
$this->last_stmt=$result;
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal oracle result pointer to the next available result
*
* @param a valid oci8 result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetch_assoc()
/**
* Fetch a row and return as array.
*
* @param $result oci8 result identifier
* @param $fetchmode how the resulting array should be indexed
*
* @return int an array on success, a DB error code on failure, NULL
* if there is no more data
*/
function &fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$moredata = @OCIFetchInto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
} else {
$moredata = @OCIFetchInto($result, $row, OCI_RETURN_NULLS + OCI_RETURN_LOBS);
}
if (!$moredata) {
return NULL;
}
return $row;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result oci8 result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch (not yet supported)
*
* @return int DB_OK on success, a DB error code on failure
*/
function fetchInto($result, &$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=NULL)
{
if ($rownum !== NULL) {
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$moredata = @OCIFetchInto($result,$arr,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS);
if ($moredata && $this->options['optimize'] == 'portability') {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$moredata = @OCIFetchInto($result,$arr,OCI_RETURN_NULLS+OCI_RETURN_LOBS);
}
if (!$moredata) {
return NULL;
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result oci8 result identifier or DB statement identifier
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return @OCIFreeStatement($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
unset($this->manip_query[(int)$result]);
return true;
}
// }}}
// {{{ numRows()
function numRows($result)
{
// emulate numRows for Oracle. yuck.
if ($this->options['optimize'] == 'portability' &&
$result === $this->last_stmt) {
$countquery = preg_replace('/^\s*SELECT\s+(.*?)\s+FROM\s+/is',
'SELECT COUNT(*) FROM ',
$this->last_query);
$save_query = $this->last_query;
$save_stmt = $this->last_stmt;
$count = $this->query($countquery);
if (DB::isError($count) ||
DB::isError($row = $count->fetch_assoc(DB_FETCHMODE_ORDERED)))
{
$this->last_query = $save_query;
$this->last_stmt = $save_stmt;
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
return $row[0];
}
return $this->raiseError(DB_ERROR_NOT_CAPABLE);
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result oci8 result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @OCINumCols($result);
if (!$cols) {
return $this->oci8RaiseError($result);
}
return $cols;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that occured
* on the current connection. This does not work, as OCIError does
* not work unless given a statement. If OCIError does return
* something, so will this.
*
* @return int native oci8 error code
*/
function errorNative()
{
if (is_resource($this->last_stmt)) {
$error = @OCIError($this->last_stmt);
} else {
$error = @OCIError($this->connection);
}
if (is_array($error)) {
return $error['code'];
}
return false;
}
// }}}
// {{{ prepare()
/**
* Prepares a query for multiple execution with execute(). With
* oci8, this is emulated.
* @param $query query to be prepared
*
* @return DB statement resource
*/
function prepare($query)
{
$tokens = split('[\&\?]', $query);
$token = 0;
$types = array();
for ($i = 0; $i < strlen($query); $i++) {
switch ($query[$i]) {
case '?':
$types[$token++] = DB_PARAM_SCALAR;
break;
case '&':
$types[$token++] = DB_PARAM_OPAQUE;
break;
}
}
$binds = sizeof($tokens) - 1;
$newquery = '';
for ($i = 0; $i < $binds; $i++) {
$newquery .= $tokens[$i] . ":bind" . $i;
}
$newquery .= $tokens[$i];
$this->last_query = $query;
$newquery = $this->modifyQuery($newquery);
$stmt = @OCIParse($this->connection, $newquery);
$this->prepare_types[$stmt] = $types;
$this->manip_query[(int)$stmt] = DB::isManip($query);
return $stmt;
}
// }}}
// {{{ execute()
/**
* Executes a DB statement prepared with prepare().
*
* @param $stmt a DB statement resource (returned from prepare())
* @param $data data to be used in execution of the statement
*
* @return int returns an oci8 result resource for successful
* SELECT queries, DB_OK for other successful queries. A DB error
* code is returned on failure.
*/
function execute($stmt, $data = false)
{
$types=&$this->prepare_types[$stmt];
if (($size = sizeof($types)) != sizeof($data)) {
return $this->raiseError(DB_ERROR_MISMATCH);
}
for ($i = 0; $i < $size; $i++) {
if (is_array($data)) {
$pdata[$i] = &$data[$i];
}
else {
$pdata[$i] = &$data;
}
if ($types[$i] == DB_PARAM_OPAQUE) {
$fp = fopen($pdata[$i], "r");
$pdata[$i] = '';
if ($fp) {
while (($buf = fread($fp, 4096)) != false) {
$pdata[$i] .= $buf;
}
}
}
if (!@OCIBindByName($stmt, ":bind" . $i, $pdata[$i], -1)) {
return $this->oci8RaiseError($stmt);
}
}
if ($this->autoCommit) {
$success = @OCIExecute($stmt, OCI_COMMIT_ON_SUCCESS);
}
else {
$success = @OCIExecute($stmt, OCI_DEFAULT);
}
if (!$success) {
return $this->oci8RaiseError($stmt);
}
$this->last_stmt = $stmt;
if ($this->manip_query[(int)$stmt]) {
return DB_OK;
} else {
return new DB_result($this, $stmt);
}
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*
* @param $onoff true/false whether to autocommit
*/
function autoCommit($onoff = false)
{
$this->autoCommit = (bool)$onoff;;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit transactions on the current connection
*
* @return DB_ERROR or DB_OK
*/
function commit()
{
$result = @OCICommit($this->connection);
if (!$result) {
return $this->oci8RaiseError();
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back all uncommitted transactions on the current connection.
*
* @return DB_ERROR or DB_OK
*/
function rollback()
{
$result = @OCIRollback($this->connection);
if (!$result) {
return $this->oci8RaiseError();
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
if ($this->last_stmt === false) {
return $this->oci8RaiseError();
}
$result = @OCIRowCount($this->last_stmt);
if ($result === false) {
return $this->oci8RaiseError($this->last_stmt);
}
return $result;
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query)
{
// "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle
if (preg_match('/^\s*SELECT/i', $query) &&
!preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
return $query;
}
// }}}
// {{{ modifyLimitQuery()
/**
* Emulate the row limit support altering the query
*
* @param string $query The query to treat
* @param int $from The row to start to fetch from
* @param int $count The offset
* @return string The modified query
*
* @author Tomas V.V.Cox <cox@idecnet.com>
*/
function modifyLimitQuery($query, $from, $count)
{
// Let Oracle return the name of the columns instead of
// coding a "home" SQL parser
$q_fields = "SELECT * FROM ($query) WHERE NULL = NULL";
if (!$result = OCIParse($this->connection, $q_fields)) {
return $this->oci8RaiseError();
}
if (!OCIExecute($result, OCI_DEFAULT)) {
return $this->oci8RaiseError($result);
}
$ncols = OCINumCols($result);
$cols = array();
for ( $i = 1; $i <= $ncols; $i++ ) {
$cols[] = OCIColumnName($result, $i);
}
$fields = implode(', ', $cols);
// XXX Test that (tip by John Lim)
//if(preg_match('/^\s*SELECT\s+/is', $query, $match)) {
// // Introduce the FIRST_ROWS Oracle query optimizer
// $query = substr($query, strlen($match[0]), strlen($query));
// $query = "SELECT /* +FIRST_ROWS */ " . $query;
//}
// Construct the query
// more at: http://marc.theaimsgroup.com/?l=php-db&m=99831958101212&w=2
// Perhaps this could be optimized with the use of Unions
$from += 1; // in Oracle rownum starts at 1
$query = "SELECT $fields FROM".
" (SELECT rownum as linenum, $fields FROM".
" ($query)".
" WHERE rownum <= ". ($from + $count) .
") WHERE linenum >= $from";
return $query;
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MySQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->expectError(DB_ERROR_NOSUCHTABLE);
$result = $this->query("SELECT ${seqname}.nextval FROM dual");
$this->popExpect();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
return $arr[0];
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("CREATE SEQUENCE ${seqname}");
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP SEQUENCE ${seqname}");
}
// }}}
// {{{ oci8RaiseError()
function oci8RaiseError($errno = null)
{
if ($errno === null) {
$error = @OCIError($this->connection);
return $this->raiseError($this->errorCode($error['code']),
null, null, null, $error['message']);
} elseif (is_resource($errno)) {
$error = @OCIError($errno);
return $this->raiseError($this->errorCode($error['code']),
null, null, null, $error['message']);
}
return $this->raiseError($this->errorCode($errno));
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "SELECT table_name FROM user_tables";
break;
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

484
html/illt/DB/odbc.php Normal file
View File

@@ -0,0 +1,484 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: Stig Bakken <ssb@fast.no> |
// +----------------------------------------------------------------------+
//
// $Id: odbc.php,v 1.54 2002/02/28 08:27:11 sebastian Exp $
//
// Database independent query interface definition for PHP's ODBC
// extension.
//
//
// XXX legend:
// More info on ODBC errors could be found here:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
//
// XXX ERRORMSG: The error message from the odbc function should
// be registered here.
//
require_once 'DB/common.php';
class DB_odbc extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $row = array();
// }}}
// {{{ constructor
function DB_odbc()
{
$this->DB_common();
$this->phptype = 'odbc';
$this->dbsyntax = 'sql92';
$this->features = array(
'prepare' => true,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
$this->errorcode_map = array(
'01004' => DB_ERROR_TRUNCATED,
'07001' => DB_ERROR_MISMATCH,
'21S01' => DB_ERROR_MISMATCH,
'21S02' => DB_ERROR_MISMATCH,
'22003' => DB_ERROR_INVALID_NUMBER,
'22008' => DB_ERROR_INVALID_DATE,
'22012' => DB_ERROR_DIVZERO,
'23000' => DB_ERROR_CONSTRAINT,
'24000' => DB_ERROR_INVALID,
'34000' => DB_ERROR_INVALID,
'37000' => DB_ERROR_SYNTAX,
'42000' => DB_ERROR_SYNTAX,
'IM001' => DB_ERROR_UNSUPPORTED,
'S0000' => DB_ERROR_NOSUCHTABLE,
'S0001' => DB_ERROR_NOT_FOUND,
'S0002' => DB_ERROR_NOT_FOUND,
'S0011' => DB_ERROR_ALREADY_EXISTS,
'S0012' => DB_ERROR_NOT_FOUND,
'S0021' => DB_ERROR_ALREADY_EXISTS,
'S0022' => DB_ERROR_NOT_FOUND,
'S1009' => DB_ERROR_INVALID,
'S1090' => DB_ERROR_INVALID,
'S1C00' => DB_ERROR_NOT_CAPABLE
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('odbc'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
if (!empty($dsninfo['dbsyntax'])) {
$this->dbsyntax = $dsninfo['dbsyntax'];
}
switch ($this->dbsyntax) {
case 'solid':
$this->features = array(
'prepare' => true,
'pconnect' => true,
'transactions' => true
);
$default_dsn = 'localhost';
break;
case 'navision':
// the Navision driver doesn't support fetch row by number
$this->features['limit'] = false;
break;
default:
break;
}
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
if ($this->provides('pconnect')) {
$connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
} else {
$connect_function = 'odbc_connect';
}
$conn = @$connect_function($dbhost, $user, $pw);
if (!is_resource($conn)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $this->errorNative());
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
function disconnect()
{
$err = @odbc_close($this->connection);
$this->connection = null;
return $err;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to ODBC and return the results as a ODBC resource
* identifier.
*
* @param $query the SQL query
*
* @return int returns a valid ODBC result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @odbc_exec($this->connection, $query);
if (!$result) {
return $this->odbcRaiseError(); // XXX ERRORMSG
}
// Determine which queries that should return data, and which
// should return an error code only.
if (DB::isManip($query)) {
$this->manip_result = $result; // For affectedRows()
return DB_OK;
}
$this->row[$result] = 0;
$this->manip_result = 0;
return $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal odbc 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 odbc_next_result($result);
}
// }}}
// {{{ fetch_assoc()
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
$row = array();
if ($rownum !== null) {
$rownum++; // ODBC first row is 1
if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
$cols = odbc_fetch_into($result, $rownum, &$row);
} else {
$cols = odbc_fetch_into($result, $rownum, $row);
}
} else {
if (!function_exists('version_compare') || version_compare(phpversion(), "4.0.5", "lt")) {
$cols = odbc_fetch_into($result, &$row);
} else {
$cols = odbc_fetch_into($result, $row);
}
}
if (!$cols) {
/* XXX FIXME: doesn't work with unixODBC and easysoft
(get corrupted $errno values)
if ($errno = odbc_error($this->connection)) {
return $this->RaiseError($errno);
}*/
return null;
}
if ($fetchmode !== DB_FETCHMODE_ORDERED) {
for ($i = 0; $i < count($row); $i++) {
$colName = odbc_field_name($result, $i+1);
$a[$colName] = $row[$i];
}
$row = $a;
}
return DB_OK;
}
// }}}
// {{{ freeResult()
function freeResult($result)
{
if (is_resource($result)) {
// Always return true
return odbc_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
// }}}
// {{{ numCols()
function numCols($result)
{
$cols = @odbc_num_fields($result);
if (!$cols) {
return $this->odbcRaiseError();
}
return $cols;
}
// }}}
// {{{ affectedRows()
/**
* Returns the number of rows affected by a manipulative query
* (INSERT, DELETE, UPDATE)
* @return mixed int affected rows, 0 when non manip queries or
* DB error on error
*/
function affectedRows()
{
if (empty($this->manip_result)) { // In case of SELECT stms
return 0;
}
$nrows = odbc_num_rows($this->manip_result);
if ($nrows == -1) {
return $this->odbcRaiseError();
}
return $nrows;
}
// }}}
// {{{ numRows()
/**
* ODBC may or may not support counting rows in the result set of
* SELECTs.
*
* @param $result the odbc result resource
* @return the number of rows, or 0
*/
function numRows($result)
{
$nrows = odbc_num_rows($result);
if ($nrows == -1) {
return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
}
return $nrows;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int ODBC error code
*/
function errorNative()
{
if (!isset($this->connection) || !is_resource($this->connection)) {
return odbc_error() . ' ' . odbc_errormsg();
}
return odbc_error($this->connection) . ' ' . odbc_errormsg($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for odbc. Will create the sequence if it does not exist.
*
* @access public
*
* @param $seq_name the name of the sequence
*
* @param $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$result = $this->query("update ${seqname} set id = id + 1");
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOT_FOUND) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
$result = $this->query("insert into ${seqname} (id) values(0)");
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $result;
}
$result = $this->query("select id from ${seqname}");
if (DB::isError($result)) {
return $result;
}
$row = $result->fetch_assoc(DB_FETCHMODE_ASSOC);
if (DB::isError($row || !$row)) {
return $row;
}
return $row['id'];
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("CREATE TABLE ${seqname} ".
'(id bigint NOT NULL,'.
' PRIMARY KEY(id))');
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE ${seqname}");
}
// }}}
// {{{ autoCommit()
function autoCommit($onoff = false)
{
if (!@odbc_autocommit($this->connection, $onoff)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ commit()
function commit()
{
if (!@odbc_commit($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ rollback()
function rollback()
{
if (!@odbc_rollback($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ odbcRaiseError()
function odbcRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(odbc_error($this->connection));
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

810
html/illt/DB/pgsql.php Normal file
View File

@@ -0,0 +1,810 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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. |
// +----------------------------------------------------------------------+
// | Authors: Rui Hirokawa <rui_hirokawa@ybb.ne.jp> |
// | Stig Bakken <ssb@fast.no> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php,v 1.65.2.3 2002/04/10 08:38:42 edink Exp $
//
// Database independent query interface definition for PHP's PostgreSQL
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the pgsql function should
// be registered here.
//
require_once 'DB/common.php';
class DB_pgsql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $dsn = array();
var $row = array();
var $num_rows = array();
var $affected = 0;
var $autocommit = true;
var $fetchmode = DB_FETCHMODE_ORDERED;
// }}}
// {{{ constructor
function DB_pgsql()
{
$this->DB_common();
$this->phptype = 'pgsql';
$this->dbsyntax = 'pgsql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('pgsql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$protocol = (isset($dsninfo['protocol'])) ? $dsninfo['protocol'] : 'tcp';
$connstr = '';
if ($protocol == 'tcp') {
if ($dsninfo['hostspec']) {
$connstr = 'host=' . $dsninfo['hostspec'];
}
if ($dsninfo['port']) {
$connstr .= ' port=' . $dsninfo['port'];
}
}
if (isset($dsninfo['database'])) {
$connstr .= ' dbname=' . $dsninfo['database'];
}
if (!empty($dsninfo['username'])) {
$connstr .= ' user=' . $dsninfo['username'];
}
if (!empty($dsninfo['password'])) {
$connstr .= ' password=' . $dsninfo['password'];
}
if (!empty($dsninfo['options'])) {
$connstr .= ' options=' . $dsninfo['options'];
}
if (!empty($dsninfo['tty'])) {
$connstr .= ' tty=' . $dsninfo['tty'];
}
$connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
// catch error
ob_start();
$conn = $connect_function($connstr);
$error = ob_get_contents();
ob_end_clean();
if ($conn == false) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null,
null, null, strip_tags($error));
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @pg_close($this->connection); // XXX ERRORMSG
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to PostgreSQL and return the results as a
* PostgreSQL resource identifier.
*
* @param $query the SQL query
*
* @return int returns a valid PostgreSQL result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @pg_exec($this->connection, "begin;");
if (!$result) {
return $this->pgsqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @pg_exec($this->connection, $query);
if (!$result) {
return $this->pgsqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if ($ismanip) {
$this->affected = @pg_cmdtuples($result);
return DB_OK;
} elseif (preg_match('/^\s*\(?\s*SELECT\s+/si', $query) &&
!preg_match('/^\s*\(?\s*SELECT\s+INTO\s/si', $query)) {
/* PostgreSQL commands:
ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY,
CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH,
GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET,
REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW,
UNLISTEN, UPDATE, VACUUM
*/
$this->row[$result] = 0; // reset the row counter.
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
$this->affected = 0;
return $result;
} else {
$this->affected = 0;
return DB_OK;
}
}
// }}}
// {{{ nextResult()
/**
* Move the internal pgsql 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;
}
// }}}
// {{{ errorCode()
/**
* Map native error codes to DB's portable ones. Requires that
* the DB implementation's constructor fills in the $errorcode_map
* property.
*
* @param $nativecode the native error code, as returned by the backend
* database extension (string or integer)
*
* @return int a portable DB error code, or FALSE if this DB
* implementation has no mapping for the given error code.
*/
function errorCode($errormsg)
{
static $error_regexps;
if (empty($error_regexps)) {
$error_regexps = array(
'/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => DB_ERROR_NOSUCHTABLE,
'/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/' => DB_ERROR_ALREADY_EXISTS,
'/divide by zero$/' => DB_ERROR_DIVZERO,
'/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER,
'/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,
'/parser: parse error at or near \"/' => DB_ERROR_SYNTAX,
'/referential integrity violation/' => DB_ERROR_CONSTRAINT
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
// Fall back to DB_ERROR if there was no mapping.
return DB_ERROR;
}
// }}}
/**
* Fetch and return a row of data (it uses fetchInto for that)
* @param $result PostgreSQL result identifier
* @param $fetchmode format of fetched row array
* @param $rownum the absolute row number to fetch
*
* @return array a row of data, or false on error
*/
function fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result PostgreSQL result identifier
* @param $row (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
*
* @return int DB_OK on success, a DB error code on failure
*/
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
$rownum = ($rownum !== null) ? $rownum : $this->row[$result];
if ($rownum >= $this->num_rows[$result]) {
return null;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$row = @pg_fetch_array($result, $rownum, PGSQL_ASSOC);
} else {
$row = @pg_fetch_row($result, $rownum);
}
if (!$row) {
$err = pg_errormessage($this->connection);
if (!$err) {
return null;
}
return $this->pgsqlRaiseError();
}
$this->row[$result] = ++$rownum;
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result int PostgreSQL result identifier or DB statement identifier
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return @pg_freeresult($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
unset($this->row[(int)$result]);
unset($this->num_rows[(int)$result]);
$this->affected = 0;
return true;
}
// }}}
// {{{ quote()
/**
* Quote the given string so it can be safely used within string delimiters
* in a query.
* @param $string mixed Data to be quoted
* @return mixed "NULL" string, quoted string or original data
*/
function quote($str = null)
{
switch (strtolower(gettype($str))) {
case 'null':
return 'NULL';
case 'integer':
case 'double' :
return $str;
case 'string':
default:
$str = str_replace("'", "''", $str);
//PostgreSQL treats a backslash as an escape character.
$str = str_replace('\\', '\\\\', $str);
return "'$str'";
}
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result resource PostgreSQL result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @pg_numfields($result);
if (!$cols) {
return $this->pgsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result resource PostgreSQL result identifier
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @pg_numrows($result);
if ($rows === null) {
return $this->pgsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @return int native PostgreSQL error code
*/
function errorNative()
{
return pg_errormessage($this->connection);
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
// (disabled) hack to shut up error messages from libpq.a
//@fclose(@fopen("php://stderr", "w"));
$result = @pg_exec($this->connection, "end;");
$this->transaction_opcount = 0;
if (!$result) {
return $this->pgsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @pg_exec($this->connection, "abort;");
$this->transaction_opcount = 0;
if (!$result) {
return $this->pgsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return int number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
return $this->affected;
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence.
*
* We are using native PostgreSQL sequences. If a sequence does
* not exist, it will be created, unless $ondemand is false.
*
* @access public
* @param string $seq_name the name of the sequence
* @param bool $ondemand whether to create the sequence on demand
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("SELECT NEXTVAL('${seqname}')");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetch_assoc(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Create the sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("CREATE SEQUENCE ${seqname}");
$this->popErrorHandling();
return $result;
}
// }}}
// {{{ dropSequence()
/**
* Drop a sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP SEQUENCE ${seqname}");
}
// }}}
// {{{ modifyLimitQuery()
function modifyLimitQuery($query, $from, $count)
{
$query = $query . " LIMIT $count, $from";
return $query;
}
// }}}
// {{{ pgsqlRaiseError()
function pgsqlRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$err = $this->errorCode($native);
} else {
$err = $errno;
}
return $this->raiseError($err, null, null, null, $native);
}
// }}}
// {{{ _pgFieldFlags()
/**
* Flags of a Field
*
* @param int $resource PostgreSQL result identifier
* @param int $num_field the field number
*
* @return string The flags of the field ("not_null", "default_xx", "primary_key",
* "unique" and "multiple_key" are supported)
* @access private
*/
function _pgFieldFlags($resource, $num_field, $table_name)
{
$field_name = @pg_fieldname($resource, $num_field);
$result = pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef
FROM pg_attribute f, pg_class tab, pg_type typ
WHERE tab.relname = typ.typname
AND typ.typrelid = f.attrelid
AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
if (pg_numrows($result) > 0) {
$row = pg_fetch_row($result, 0);
$flags = ($row[0] == 't') ? 'not_null ' : '';
if ($row[1] == 't') {
$result = pg_exec($this->connection, "SELECT a.adsrc
FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a
WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
AND f.attrelid = a.adrelid AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
$row = pg_fetch_row($result, 0);
$num = str_replace('\'', '', $row[0]);
$flags .= "default_$num ";
}
}
$result = pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey
FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i
WHERE tab.relname = typ.typname
AND typ.typrelid = f.attrelid
AND f.attrelid = i.indrelid
AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
$count = pg_numrows($result);
for ($i = 0; $i < $count ; $i++) {
$row = pg_fetch_row($result, $i);
$keys = explode(" ", $row[2]);
if (in_array($num_field + 1, $keys)) {
$flags .= ($row[0] == 't') ? 'unique ' : '';
$flags .= ($row[1] == 't') ? 'primary ' : '';
if (count($keys) > 1)
$flags .= 'multiple_key ';
}
}
return trim($flags);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support table name and flags if called from a db_result
*
* @param mixed $resource PostgreSQL result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $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
* ["order"][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'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = pg_exec($this->connection,"SELECT * FROM $result");
if (empty($id)) {
return $this->pgsqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->pgsqlRaiseError();
}
}
$count = @pg_numfields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @pg_fieldname ($id, $i);
$res[$i]['type'] = @pg_fieldtype ($id, $i);
$res[$i]['len'] = @pg_fieldsize ($id, $i);
$res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldflags($id, $i, $result) : '';
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @pg_fieldname ($id, $i);
$res[$i]['type'] = @pg_fieldtype ($id, $i);
$res[$i]['len'] = @pg_fieldsize ($id, $i);
$res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldFlags($id, $i, $result) : '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_resource($id)) {
@pg_freeresult($id);
}
return $res;
}
// }}}
// {{{ getTablesQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables': {
$sql = "SELECT c.relname as \"Name\"
FROM pg_class c, pg_user u
WHERE c.relowner = u.usesysid AND c.relkind = 'r'
AND not exists (select 1 from pg_views where viewname = c.relname)
AND c.relname !~ '^pg_'
UNION
SELECT c.relname as \"Name\"
FROM pg_class c
WHERE c.relkind = 'r'
AND not exists (select 1 from pg_views where viewname = c.relname)
AND not exists (select 1 from pg_user where usesysid = c.relowner)
AND c.relname !~ '^pg_'";
break;
}
case 'views': {
// Table cols: viewname | viewowner | definition
$sql = "SELECT viewname FROM pg_views";
break;
}
case 'users': {
// cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil
$sql = 'SELECT usename FROM pg_user';
break;
}
case 'databases': {
$sql = 'SELECT datname FROM pg_database';
break;
}
case 'functions': {
$sql = 'SELECT proname FROM pg_proc';
break;
}
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

444
html/illt/DB/storage.php Normal file
View File

@@ -0,0 +1,444 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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: Stig Bakken <stig@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: storage.php,v 1.28 2002/02/28 08:27:11 sebastian Exp $
//
// DB_storage: a class that lets you return SQL data as objects that
// can be manipulated and that updates the database accordingly.
//
require_once "PEAR.php";
require_once "DB.php";
/**
* DB_storage provides an object interface to a table row. It lets
* you add, delete and change rows without using SQL.
*
* @author Stig Bakken <stig@php.net>
*
* @package DB
*/
class DB_storage extends PEAR
{
/** the name of the table (or view, if the backend database supports
updates in views) we hold data from */
var $_table = null;
/** which column(s) in the table contains primary keys, can be a
string for single-column primary keys, or an array of strings
for multiple-column primary keys */
var $_keycolumn = null;
/** DB connection handle used for all transactions */
var $_dbh = null;
/** an assoc with the names of database fields stored as properties
in this object */
var $_properties = array();
/** an assoc with the names of the properties in this object that
have been changed since they were fetched from the database */
var $_changes = array();
/** flag that decides if data in this object can be changed.
objects that don't have their table's key column in their
property lists will be flagged as read-only. */
var $_readonly = false;
/** function or method that implements a validator for fields that
are set, this validator function returns true if the field is
valid, false if not */
var $_validator = null;
/**
* Constructor
*
* @param $table string the name of the database table
*
* @param $keycolumn mixed string with name of key column, or array of
* strings if the table has a primary key of more than one column
*
* @param $dbh object database connection object
*
* @param $validator mixed function or method used to validate
* each new value, called with three parameters: the name of the
* field/column that is changing, a reference to the new value and
* a reference to this object
*
*/
function DB_storage($table, $keycolumn, &$dbh, $validator = null)
{
$this->PEAR('DB_Error');
$this->_table = $table;
$this->_keycolumn = $keycolumn;
$this->_dbh = $dbh;
$this->_readonly = false;
$this->_validator = $validator;
}
/**
* Utility method to build a "WHERE" clause to locate ourselves in
* the table.
*
* XXX future improvement: use rowids?
*
* @access private
*/
function _makeWhere($keyval = null)
{
if (is_array($this->_keycolumn)) {
if ($keyval === null) {
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) {
$keyval[] = $this->{$this->_keycolumn[$i]};
}
}
$whereclause = '';
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) {
if ($i > 0) {
$whereclause .= ' AND ';
}
$whereclause .= $this->_keycolumn[$i];
if (is_null($keyval[$i])) {
// there's not much point in having a NULL key,
// but we support it anyway
$whereclause .= ' IS NULL';
} else {
$whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]);
}
}
} else {
if ($keyval === null) {
$keyval = @$this->{$this->_keycolumn};
}
$whereclause = $this->_keycolumn;
if (is_null($keyval)) {
// there's not much point in having a NULL key,
// but we support it anyway
$whereclause .= ' IS NULL';
} else {
$whereclause .= ' = ' . $this->_dbh->quote($keyval);
}
}
return $whereclause;
}
/**
* Method used to initialize a DB_storage object from the
* configured table.
*
* @param $keyval mixed the key[s] of the row to fetch (string or array)
*
* @return int DB_OK on success, a DB error if not
*/
function setup($keyval)
{
$qval = $this->_dbh->quote($keyval);
$whereclause = $this->_makeWhere($keyval);
$query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause;
$sth = $this->_dbh->query($query);
if (DB::isError($sth)) {
return $sth;
}
$row = $sth->fetch_assoc(DB_FETCHMODE_ASSOC);
if (DB::isError($row)) {
return $row;
}
if (empty($row)) {
return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null,
$query, null, true);
}
foreach ($row as $key => $value) {
$this->_properties[$key] = true;
$this->$key = $value;
}
return DB_OK;
}
/**
* Create a new (empty) row in the configured table for this
* object.
*/
function insert($newpk)
{
if (is_array($this->_keycolumn)) {
$primarykey = $this->_keycolumn;
} else {
$primarykey = array($this->_keycolumn);
}
settype($newpk, "array");
for ($i = 0; $i < sizeof($primarykey); $i++) {
$pkvals[] = $this->_dbh->quote($newpk[$i]);
}
$sth = $this->_dbh->query("INSERT INTO $this->_table (" .
implode(",", $primarykey) . ") VALUES(" .
implode(",", $pkvals) . ")");
if (DB::isError($sth)) {
return $sth;
}
if (sizeof($newpk) == 1) {
$newpk = $newpk[0];
}
$this->setup($newpk);
}
/**
* Output a simple description of this DB_storage object.
* @return string object description
*/
function toString()
{
$info = get_class($this);
$info .= " (table=";
$info .= $this->_table;
$info .= ", keycolumn=";
if (is_array($this->_keycolumn)) {
$info .= "(" . implode(",", $this->_keycolumn) . ")";
} else {
$info .= $this->_keycolumn;
}
$info .= ", dbh=";
if (is_object($this->_dbh)) {
$info .= $this->_dbh->toString();
} else {
$info .= "null";
}
$info .= ")";
if (sizeof($this->_properties)) {
$info .= " [loaded, key=";
$keyname = $this->_keycolumn;
if (is_array($keyname)) {
$info .= "(";
for ($i = 0; $i < sizeof($keyname); $i++) {
if ($i > 0) {
$info .= ",";
}
$info .= $this->$keyname[$i];
}
$info .= ")";
} else {
$info .= $this->$keyname;
}
$info .= "]";
}
if (sizeof($this->_changes)) {
$info .= " [modified]";
}
return $info;
}
/**
* Dump the contents of this object to "standard output".
*/
function dump()
{
reset($this->_properties);
while (list($prop, $foo) = each($this->_properties)) {
print "$prop = ";
print htmlentities($this->$prop);
print "<BR>\n";
}
}
/**
* Static method used to create new DB storage objects.
* @param $data assoc. array where the keys are the names
* of properties/columns
* @return object a new instance of DB_storage or a subclass of it
*/
function &create($table, &$data)
{
$classname = get_class($this);
$obj = new $classname($table);
reset($data);
while (list($name, $value) = each($data)) {
$obj->_properties[$name] = true;
$obj->$name = &$value;
}
return $obj;
}
/**
* Loads data into this object from the given query. If this
* object already contains table data, changes will be saved and
* the object re-initialized first.
*
* @param $query SQL query
*
* @param $params parameter list in case you want to use
* prepare/execute mode
*
* @return int DB_OK on success, DB_WARNING_READ_ONLY if the
* returned object is read-only (because the object's specified
* key column was not found among the columns returned by $query),
* or another DB error code in case of errors.
*/
// XXX commented out for now
/*
function loadFromQuery($query, $params = null)
{
if (sizeof($this->_properties)) {
if (sizeof($this->_changes)) {
$this->store();
$this->_changes = array();
}
$this->_properties = array();
}
$rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params);
if (DB::isError($rowdata)) {
return $rowdata;
}
reset($rowdata);
$found_keycolumn = false;
while (list($key, $value) = each($rowdata)) {
if ($key == $this->_keycolumn) {
$found_keycolumn = true;
}
$this->_properties[$key] = true;
$this->$key = &$value;
unset($value); // have to unset, or all properties will
// refer to the same value
}
if (!$found_keycolumn) {
$this->_readonly = true;
return DB_WARNING_READ_ONLY;
}
return DB_OK;
}
*/
/**
* Modify an attriute value.
*/
function set($property, $newvalue)
{
// only change if $property is known and object is not
// read-only
if ($this->_readonly) {
return $this->raiseError(null, DB_WARNING_READ_ONLY, null,
null, null, null, true);
}
if (@isset($this->_properties[$property])) {
if (empty($this->_validator)) {
$valid = true;
} else {
$valid = @call_user_func($this->_validator,
$this->_table,
$property,
$newvalue,
$this->$property,
$this);
}
if ($valid) {
$this->$property = $newvalue;
@$this->_changes[$property]++;
} else {
return $this->raiseError(null, DB_ERROR_INVALID, null,
null, "invalid field: $property",
null, true);
}
return true;
}
return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null,
null, "unknown field: $property",
null, true);
}
/**
* Fetch an attribute value.
*
* @param string attribute name
*
* @return attribute contents, or null if the attribute name is
* unknown
*/
function &get($property)
{
// only return if $property is known
if (isset($this->_properties[$property])) {
return $this->$property;
}
return null;
}
/**
* Destructor, calls DB_storage::store() if there are changes
* that are to be kept.
*/
function _DB_storage()
{
if (empty($this->_discard) && sizeof($this->_changes)) {
$this->store();
}
$this->_properties = array();
$this->_changes = array();
$this->_table = null;
}
/**
* Stores changes to this object in the database.
*
* @return DB_OK or a DB error
*/
function store()
{
while (list($name, $changed) = each($this->_changes)) {
$params[] = &$this->$name;
$vars[] = $name . ' = ?';
}
if ($vars) {
$query = 'UPDATE ' . $this->_table . ' SET ' .
implode(', ', $vars) . ' WHERE ' .
$this->_makeWhere();
$stmt = $this->_dbh->prepare($query);
$res = $this->_dbh->execute($stmt, $params);
if (DB::isError($res)) {
return $res;
}
$this->_changes = array();
}
return DB_OK;
}
/**
* Remove the row represented by this object from the database.
*
* @return mixed DB_OK or a DB error
*/
function remove()
{
if ($this->_readonly) {
return $this->raiseError(null, DB_WARNING_READ_ONLY, null,
null, null, null, true);
}
$query = 'DELETE FROM ' . $this->_table .' WHERE '.
$this->_makeWhere();
$res = $this->_dbh->query($query);
if (DB::isError($res)) {
return $res;
}
foreach ($this->_properties as $prop => $foo) {
unset($this->$prop);
}
$this->_properties = array();
$this->_changes = array();
return DB_OK;
}
}
?>

251
html/illt/DB/sybase.php Normal file
View File

@@ -0,0 +1,251 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 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> |
// +----------------------------------------------------------------------+
//
// $Id: sybase.php,v 1.30 2002/02/28 08:27:11 sebastian Exp $
//
// Database independent query interface definition for PHP's Sybase
// extension.
//
require_once 'DB/common.php';
class DB_sybase extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
// }}}
// {{{ constructor
function DB_sybase()
{
$this->DB_common();
$this->phptype = 'sybase';
$this->dbsyntax = 'sybase';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => false,
'limit' => 'emulate'
);
}
// }}}
// {{{ connect()
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('sybase') && !DB::assertExtension('sybase_ct'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
$connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect';
if ($dbhost && $user && $pw) {
$conn = $connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = $connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = $connect_function($dbhost);
} else {
$conn = $connect_function();
}
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
}
if ($dsninfo['database']) {
if (!@sybase_select_db($dsninfo['database'], $conn)) {
return $this->raiseError(DB_ERROR_NODBSELECTED);
}
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
function disconnect()
{
$ret = @sybase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @sybase_query($query, $this->connection);
if (!$result) {
return $this->raiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return DB::isManip($query) ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal sybase 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;
}
// }}}
// {{{ fetch_assoc()
function &fetch_assoc($result, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode == DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$res = $this->fetchInto ($result, $arr, $fetchmode, $rownum);
if ($res !== DB_OK) {
return $res;
}
return $arr;
}
// }}}
// {{{ fetchInto()
function fetchInto($result, &$ar, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!sybase_data_seek($result, $rownum)) {
return $this->raiseError();
}
}
$ar = ($fetchmode & DB_FETCHMODE_ASSOC) ? @sybase_fetch_array($result) : @sybase_fetch_row($result);
if (!$ar) {
// reported not work as seems that sybase_get_last_message()
// always return a message here
//if ($errmsg = sybase_get_last_message()) {
// return $this->raiseError($errmsg);
//} else {
return null;
//}
}
return DB_OK;
}
// }}}
// {{{ freeResult()
function freeResult($result)
{
if (is_resource($result)) {
return @sybase_free_result($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
return true;
}
// }}}
// {{{ numCols()
function numCols($result)
{
$cols = @sybase_num_fields($result);
if (!$cols) {
return $this->raiseError();
}
return $cols;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @sybase_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "select name from sysobjects where type = 'U' order by name";
break;
case 'views':
$sql = "select name from sysobjects where type = 'V'";
break;
default:
return null;
}
return $sql;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>