cvs: /php4/pear DB.php Makefile.in /php4/pear/DB common.php mysql.php odbc.php
| From: | Stig Bakken | Date: | Thu, 03 Feb 2000 10:49:34 +0000 |
| Subject: | cvs: /php4/pear DB.php Makefile.in /php4/pear/DB common.php mysql.php odbc.php | ||
| Groups: | php.version4 | ||
| Request: | Send a blank email to php-version4+get-9722@lists.php.net to get a copy of this message | ||
ssb Thu Feb 3 11:49:34 2000 EDT
Modified files:
/php4/pear DB.php Makefile.in
/php4/pear/DB common.php mysql.php odbc.php
Log:
* Started playing around with alternatives to javadoc.
* Fixed the "make install" rule so it doesn't temporarily break the
installed scripts.
* implemented prepare/execute emulation for MySQL including file-reference
parameters (only binmode/binfetchlen remains now)
* started fixing up the ODBC backend
Index: php4/pear/DB.php
diff -u php4/pear/DB.php:1.10 php4/pear/DB.php:1.11
--- php4/pear/DB.php:1.10 Sat Jan 1 02:31:58 2000
+++ php4/pear/DB.php Thu Feb 3 11:49:03 2000
@@ -17,7 +17,7 @@
// | |
// +----------------------------------------------------------------------+
//
-// $Id: DB.php,v 1.10 2000/01/01 01:31:58 sas Exp $
+// $Id: DB.php,v 1.11 2000/02/03 10:49:03 ssb Exp $
//
// Database independent query interface.
//
@@ -51,6 +51,7 @@
define("DB_ERROR_CANNOT_DROP", -17);
define("DB_ERROR_NOSUCHTABLE", -18);
define("DB_ERROR_NOSUCHFIELD", -19);
+define("DB_ERROR_NEED_MORE_DATA", -20);
// }}}
// {{{ Prepare/execute parameter types
@@ -59,11 +60,12 @@
* These constants are used when storing information about prepared
* statements (using the "prepare" method in DB_dbtype).
*
- * The prepare/execute model in DB is borrowed from the ODBC extension,
- * in a query the "?" character means a scalar parameter, and a "*"
- * character means an opaque parameter. An opaque parameter is simply
- * a file name, the real data are in that file (useful for large blob
- * operations).
+ * The prepare/execute model in DB is mostly borrowed from the ODBC
+ * extension, in a query the "?" character means a scalar parameter.
+ * There is one extension though, a "*" character means an opaque
+ * parameter. An opaque parameter is simply a file name, the real
+ * data are in that file (useful for stuff like putting uploaded files
+ * into your database).
*/
define("DB_PARAM_SCALAR", 1);
define("DB_PARAM_OPAQUE", 2);
@@ -117,16 +119,17 @@
// {{{ factory()
/**
- * Create a new DB object for the specified database type.
+ * <purpose>Create a new DB object for the specified database
+ * type</purpose>
*
- * @param $type database type
+ * <param name="$type" type="string">database type</param>
*
- * @return object a newly created DB object, or a DB error code on
- * error
+ * <return type="object">a newly created DB object, or a DB error
+ * code on error</return>
*/
function factory($type) {
global $USED_PACKAGES;
- // "include" should be replaced with "use" once PHP gets it
+ // "include" should be replaced with "import" once PHP gets it
$pkgname = 'DB/' . $type;
if (!is_array($USED_PACKAGES) || !$USED_PACKAGES[$pkgname]) {
if (!@include("DB/${type}.php")) {
@@ -137,24 +140,26 @@
}
$classname = 'DB_' . $type;
$obj = new $classname;
- return $obj;
+ return $obj; // XXX ADDREF
}
// }}}
// {{{ connect()
/**
- * Create a new DB object and connect to the specified database.
+ * <purpose>Create a new DB object and connect to the specified
+ * database </purpose>
*
- * @param $dsn "data source name", see the parseDSN method for a
- * description of the dsn format.
+ * <param name="$dsn" type="string">"data source name", see
the
+ * <ref method="DB::parseDSN"/> method for a description of the
+ * dsn format.</param>
+ *
+ * <param name="$persistent" type="bool">whether this connection
+ * should be persistent. Ignored if the backend extension does
+ * not support persistent connections.</param>
*
- * @param $persistent (optional) whether this connection should be
- * persistent. Ignored if the backend extension does not support
- * persistent connections.
- *
- * @return object a newly created DB object, or a DB error code on
- * error
+ * <return type="object">a newly created DB object, or a DB error
+ * code on error</return>
*/
function connect($dsn, $persistent = false) {
global $USED_PACKAGES;
@@ -183,9 +188,9 @@
// {{{ apiVersion()
/**
- * Return the DB API version.
+ * <purpose>Return the DB API version</purpose>
*
- * @return double the DB API version number
+ * <return type="double">the DB API version number</return>
*/
function apiVersion() {
return 1.00;
@@ -195,11 +200,12 @@
// {{{ isError()
/**
- * Tell whether a result code from a DB method is an error.
+ * <purpose>Tell whether a result code from a DB method is an
+ * error</purpose>
*
- * @param $code result code
+ * <param name="$code" type="int">result code</param>
*
- * @return bool whether $code is an error
+ * <return type="bool">whether $code is an error</return>
*/
function isError($code) {
return is_int($code) && ($code < 0);
@@ -209,12 +215,13 @@
// {{{ errorMessage()
/**
- * Return a textual error message for a DB error code.
+ * <purpose>Return a textual error message for a DB error
+ * code</purpose>
*
- * @param $code error code
+ * <param name="$code" type="int">error code</param>
*
- * @return string error message, or false if the error code was
- * not recognized
+ * <return type="string">error message, or false if the error code
+ * was not recognized</return>
*/
function errorMessage($code) {
if (!is_array($errorMessages)) {
@@ -247,30 +254,50 @@
// {{{ parseDSN()
/**
+ * <purpose>Parse a data source name</purpose>
+ *
+ * <param name="$dsn" type="string">Data Source Name to be
+ * parsed</param>
+ *
+ * <desc>
+ * <para>
* Parse a data source name and return an associative array with
* the following keys:
- * phptype Database backend used in PHP (mysql, odbc etc.)
- * dbsyntax Database used with regards to SQL syntax etc.
- * protocol Communication protocol to use (tcp, unix etc.)
- * hostspec Host specification (hostname[:port])
- * database Database to use on the DBMS server
- * username User name for login
- * password Password for login
- *
+ * <dl>
+ * <dt>phptype</dt>
+ * <dd>Database backend used in PHP (mysql, odbc etc.)</dd>
+ * <dt>dbsyntax</dt>
+ * <dd>Database used with regards to SQL syntax etc.</dd>
+ * <dt>protocol</dt>
+ * <dd>Communication protocol to use (tcp, unix etc.)</dd>
+ * <dt>hostspec</dt>
+ * <dd>Host specification (hostname[:port])</dd>
+ * <dt>database</dt>
+ * <dd>Database to use on the DBMS server</dd>
+ * <dt>username</dt>
+ * <dd>User name for login</dd>
+ * <dt>password</dt>
+ * <dd>Password for login</dd>
+ * </dl>
+ * </para><para>
* The format of the supplied DSN is in its fullest form:
- * phptype(dbsyntax)://username:password@protocol+hostspec/database
+ * <ul>
+ * <li>phptype(dbsyntax)://username:password@protocol+hostspec/database</li>
+ * </ul>
* Most variations are allowed:
- * phptype://username:password@protocol+hostspec/database
- * phptype://username:password@hostspec/database
- * phptype://username:password@hostspec
- * phptype://hostspec/database
- * phptype://hostspec
- * phptype(dbsyntax)
- * phptype
- *
- * FALSE is returned on error.
+ * <ul>
+ * <li>phptype://username:password@protocol+hostspec/database</li>
+ * <li>phptype://username:password@hostspec/database</li>
+ * <li>phptype://username:password@hostspec</li>
+ * <li>phptype://hostspec/database</li>
+ * <li>phptype://hostspec</li>
+ * <li>phptype(dbsyntax)</li>
+ * <li>phptype</li>
+ * </ul>
+ * </para>
+ * </desc>
*
- * @param $dsn Data Source Name to be parsed
+ * <return type="bool">FALSE is returned on error</return>
*/
function parseDSN($dsn) {
$parsed = array(
Index: php4/pear/Makefile.in
diff -u php4/pear/Makefile.in:1.1 php4/pear/Makefile.in:1.2
--- php4/pear/Makefile.in:1.1 Thu Dec 30 03:59:34 1999
+++ php4/pear/Makefile.in Thu Feb 3 11:49:03 2000
@@ -11,7 +11,6 @@
peardir=$(prefix)/lib/php
pear_DBdir=$(prefix)/lib/php/DB
-
install-data-local:
-@$(mkinstalldirs) $(peardir) $(pear_DBdir) && \
$(INSTALL_DATA) $(srcdir)/DB.php $(peardir) && \
@@ -39,14 +38,16 @@
echo "creating phpize" && \
sed \
-e 's#@PREFIX@#$(prefix)#' \
- < $(srcdir)/phpize.in > $(bindir)/phpize && \
- chmod +x $(bindir)/phpize && \
+ < $(srcdir)/phpize.in > $(bindir)/phpize.tmp && \
+ chmod +x $(bindir)/phpize.tmp && \
+ mv $(bindir)/phpize.tmp $(bindir)/phpize && \
echo "creating php-config" && \
sed \
-e 's#@PREFIX@#$(prefix)#' \
-e 's#@PHPINCLUDEDIR@#$(phpincludedir)#g' \
- < $(srcdir)/php-config.in > $(bindir)/php-config && \
- chmod +x $(bindir)/php-config
+ < $(srcdir)/php-config.in > $(bindir)/php-config.tmp && \
+ chmod +x $(bindir)/php-config.tmp && \
+ mv $(bindir)/php-config.tmp $(bindir)/php-config &&
SRC_HEADERS = \
php.h \
@@ -68,7 +69,7 @@
STANDARD_HEADERS = \
php_output.h
-
+
HEADER_DIRS = \
Zend \
TSRM \
Index: php4/pear/DB/common.php
diff -u php4/pear/DB/common.php:1.5 php4/pear/DB/common.php:1.6
--- php4/pear/DB/common.php:1.5 Sat Jan 1 02:31:58 2000
+++ php4/pear/DB/common.php Thu Feb 3 11:49:04 2000
@@ -123,6 +123,27 @@
// }}}
+ // {{{ executeMultiple()
+
+ /**
+ * This function does several execute() calls on the same
+ * statement handle. $data must be an array indexed numerically
+ * from 0, one execute call is done for every "row" in the array.
+ *
+ * If an error occurs during execute(), executeMultiple() does not
+ * execute the unfinished rows, but rather returns that error.
+ */
+ function executeMultiple($stmt, &$data) {
+ for ($i = 0; $i < sizeof($data); $i++) {
+ $res = $this->execute($stmt, &$data[$i]);
+ if (DB::isError($res)) {
+ return $res;
+ }
+ }
+ return DB_OK;
+ }
+
+ // }}}
// {{{ getOne()
/**
Index: php4/pear/DB/mysql.php
diff -u php4/pear/DB/mysql.php:1.7 php4/pear/DB/mysql.php:1.8
--- php4/pear/DB/mysql.php:1.7 Sat Jan 1 02:31:58 2000
+++ php4/pear/DB/mysql.php Thu Feb 3 11:49:04 2000
@@ -41,16 +41,17 @@
// {{{ properties
var $connection;
- var $type;
- var $features;
+ var $phptype, $dbsyntax;
+ var $prepare_tokens = array();
+ var $prepare_types = array();
// }}}
// {{{ constructor
function DB_mysql() {
- $this->type = 'mysql';
- $this->syntax = 'mysql';
+ $this->phptype = 'mysql';
+ $this->dbsyntax = 'mysql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
@@ -76,7 +77,13 @@
// {{{ connect()
/**
- * 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($dsn, $persistent = false) {
if (is_array($dsn)) {
@@ -141,7 +148,7 @@
}
// Determine which queries that should return data, and which
// should return an error code only.
- if (eregi('SELECT', $query)) {
+ if (preg_match('/(SELECT|SHOW)/i', $query)) {
$resultObj = new DB_result($this, $result);
return $resultObj; // XXX ADDREF
} else {
@@ -158,8 +165,9 @@
*
* @param $query the SQL query
*
- * @return int a valid MySQL result resource on success, a DB error
- * code on failure.
+ * @return int returns a valid MySQL result for successful SELECT
+ * queries, DB_OK for other successful queries. A DB error code
+ * is returned on failure.
*/
function simpleQuery($query) {
$result = mysql_query($query, $this->connection);
@@ -168,7 +176,7 @@
}
// Determine which queries that should return data, and which
// should return an error code only.
- if (eregi('SELECT', $query)) {
+ if (stristr('SELECT', $query)) {
return $result;
} else {
return DB_OK;
@@ -218,12 +226,20 @@
/**
* Free the internal resources associated with $result.
*
- * @param $result MySQL result identifier
+ * @param $result MySQL result identifier or DB statement identifier
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result) {
- return mysql_free_result($result);
+ if (is_resource($result)) {
+ return mysql_free_result($result);
+ }
+ if (!isset($this->prepare_tokens[$result])) {
+ return false;
+ }
+ unset($this->prepare_tokens[$result]);
+ unset($this->prepare_types[$result]);
+ return true;
}
// }}}
@@ -258,15 +274,118 @@
}
// }}}
+ // {{{ prepare()
+
+ /**
+ * Prepares a query for multiple execution with execute(). With
+ * MySQL, this is emulated.
+ */
+ function prepare($query) {
+ $t = &$this->prepare_tokens;
+ $y = &$this->prepare_types;
+ $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;
+ }
+ }
+ $t[] = $tokens;
+ end($t);
+ $k = key($t);
+ $y[$k] = $types;
+ print "<pre>";var_dump($tokens);var_dump($types);print
"</pre>\n";
+ return $k;
+ }
+
+ // }}}
+ // {{{ execute()
+
+ /**
+ * @return int returns a MySQL 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) {
+ $p = &$this->prepare_tokens;
+ $stmt = 0; // XXX HORRIBLE HACK
+ if (!isset($p[$stmt]) || !is_array($p[$stmt]) || !sizeof($p[$stmt])) {
+ return DB_ERROR_INVALID;
+ }
+ $qq = &$p[$stmt];
+ $qp = sizeof($qq) - 1;
+ if ((!$data && $qp > 0) ||
+ (!is_array($data) && $qp > 1) ||
+ (is_array($data) && $qp > sizeof($data))) {
+ return DB_ERROR_NEED_MORE_DATA;
+ }
+ $realquery = $qq[0];
+ for ($i = 0; $i < $qp; $i++) {
+ $realquery .= "'";
+ if ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) {
+ $fp = @fopen($data[$i], "r");
+ $data = '';
+ if ($fp) {
+ while ($buf = fread($fp, 4096)) {
+ $data .= $buf;
+ }
+ }
+ . $this->quoteString($data[$i]) . "'";
+ $realquery .= $qq[$i + 1];
+ }
+ $result = mysql_query($realquery, $this->connection);
+ if (!$result) {
+ return $this->errorCode(mysql_errno($this->connection));
+ }
+ if (stristr('SELECT', $realquery)) {
+ return $result;
+ } else {
+ return DB_OK;
+ }
+ }
+
+ // }}}
+ // {{{ autoCommit()
+
+ /**
+ * Enable/disable automatic commits [not supported by MySQL]
+ */
+ function autoCommit($onoff = false) {
+ return DB_ERROR_NOT_CAPABLE;
+ }
+
+ // }}}
+ // {{{ commit()
+
+ /**
+ * Commit transactions on the current connection [not supported by MySQL]
+ */
+ function commit() {
+ return DB_ERROR_NOT_CAPABLE;
+ }
+
+ // }}}
+ // {{{ rollback()
+
+ /**
+ * Roll back all uncommitted transactions on the current connection.
+ * [not supported by MySQL]
+ */
+ function rollback() {
+ return DB_ERROR_NOT_CAPABLE;
+ }
+
+ // }}}
// Methods still not implemented:
- // prepare
- // execute
// longReadlen
// binmode
- // autoCommit
- // commit
- // rollback
}
// Local variables:
Index: php4/pear/DB/odbc.php
diff -u php4/pear/DB/odbc.php:1.3 php4/pear/DB/odbc.php:1.4
--- php4/pear/DB/odbc.php:1.3 Sat Jan 1 02:31:58 2000
+++ php4/pear/DB/odbc.php Thu Feb 3 11:49:04 2000
@@ -41,26 +41,109 @@
// {{{ properties
var $connection;
- var $type;
+ var $phptype, $dbsyntax;
// }}}
// {{{ constructor
function DB_odbc() {
- $this->type = 'odbc';
+ $this->phptype = 'odbc';
+ $this->dbsyntax = 'unknown';
+ // Let's be very pessimistic about the features of an odbc
+ // backend. The user has to specify the dbsyntax to access
+ // other features.
$this->features = array(
- 'prepare' => true,
+ 'prepare' => false,
'pconnect' => true,
- 'transactions' => true
+ 'transactions' => false
);
+ $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,
+ "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($dsn, $user, $pw) {
+ if (is_array($dsn)) {
+ $dsninfo = &$dsn;
+ } else {
+ $dsninfo = DB::parseDSN($dsn);
+ }
+ if (!$dsninfo || !$dsninfo['phptype']) {
+ return DB_ERROR; // XXX ERRORMSG
+ }
+ $this->dbsyntax = $dsninfo['dbsyntax'];
+ switch ($this->dbsyntax) {
+ case 'solid':
+ $this->features = array(
+ 'prepare' => true,
+ 'pconnect' => true,
+ 'transactions' => true
+ );
+ $default_dsn = 'localhost';
+ 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';
+ }
+ 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;
+ }
+ if ($conn == false) {
+ return DB_ERROR; // XXX ERRORMSG
+ }
+ $this->connection = $conn;
+ return DB_OK;
+
+
+
$this->connection = odbc_connect($dsn, $user, $pw);
}