1. Import
This commit is contained in:
90
html/illt/DB/IDEAS
Normal file
90
html/illt/DB/IDEAS
Normal 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
15
html/illt/DB/MAINTAINERS
Normal 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
38
html/illt/DB/STATUS
Normal 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
45
html/illt/DB/TESTERS
Normal 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
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
123
html/illt/DB/dbase.php
Normal 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
618
html/illt/DB/fbsql.php
Normal 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
592
html/illt/DB/ibase.php
Normal 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
323
html/illt/DB/ifx.php
Normal 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
210
html/illt/DB/msql.php
Normal 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
500
html/illt/DB/mssql.php
Normal 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
847
html/illt/DB/mysql.php
Normal 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
664
html/illt/DB/oci8.php
Normal 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
484
html/illt/DB/odbc.php
Normal 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
810
html/illt/DB/pgsql.php
Normal 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
444
html/illt/DB/storage.php
Normal 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
251
html/illt/DB/sybase.php
Normal 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:
|
||||
*/
|
||||
?>
|
||||
Reference in New Issue
Block a user