cvs: /php4/pear DB.php /php4/pear/DB common.php mysql.php
| From: | Stig Bakken | Date: | Sun, 12 Dec 1999 15:56:27 +0000 |
| Subject: | cvs: /php4/pear DB.php /php4/pear/DB common.php mysql.php | ||
| Groups: | php.version4 | ||
| Request: | Send a blank email to php-version4+get-7825@lists.php.net to get a copy of this message | ||
ssb Sun Dec 12 10:56:27 1999 EDT
Modified files:
/php4/pear DB.php
/php4/pear/DB common.php mysql.php
Log:
- Documented classes, methods and constants in the source
- Defined DB_ERROR_NOSUCHTABLE and DB_ERROR_NOSUCHFIELD
- Renamed DB_common::capableOf to DB_common::provides
- Cleaned up the error code mapping
- Added simpleQuery method in DB_mysql
- Changed getXxx methods in DB_common to use simpleQuery
- Fixed bug in DB_common::getAssoc
Index: php4/pear/DB.php
diff -u php4/pear/DB.php:1.8 php4/pear/DB.php:1.9
--- php4/pear/DB.php:1.8 Wed Dec 8 08:49:09 1999
+++ php4/pear/DB.php Sun Dec 12 10:55:56 1999
@@ -17,11 +17,20 @@
// | |
// +----------------------------------------------------------------------+
//
+// $Id: DB.php,v 1.9 1999/12/12 15:55:56 ssb Exp $
+//
// Database independent query interface.
//
// {{{ Database independent error codes.
+/*
+ * The method mapErrorCode in each DB_dbtype implementation maps
+ * native error codes to one of these.
+ *
+ * If you add an error code here, make sure you also add a textual
+ * version of it in DB::errorMessage().
+ */
define("DB_OK", 0);
define("DB_ERROR", -1);
define("DB_ERROR_SYNTAX", -2);
@@ -40,39 +49,80 @@
define("DB_ERROR_CANNOT_CREATE", -15);
define("DB_ERROR_CANNOT_DELETE", -16);
define("DB_ERROR_CANNOT_DROP", -17);
+define("DB_ERROR_NOSUCHTABLE", -18);
+define("DB_ERROR_NOSUCHFIELD", -19);
// }}}
// {{{ Prepare/execute parameter types
+/*
+ * 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).
+ */
define("DB_PARAM_SCALAR", 1);
define("DB_PARAM_OPAQUE", 2);
// }}}
// {{{ Binary data modes
+/*
+ * These constants define different ways of returning binary data
+ * from queries. Again, this model has been borrowed from the ODBC
+ * extension.
+ *
+ * DB_BINMODE_PASSTHRU sends the data directly through to the browser
+ * when data is fetched from the database.
+ * DB_BINMODE_RETURN lets you return data as usual.
+ * DB_BINMODE_CONVERT returns data as well, only it is converted to
+ * hex format, for example the string "123" would become "313233".
+ */
define("DB_BINMODE_PASSTHRU", 1);
define("DB_BINMODE_RETURN", 2);
define("DB_BINMODE_CONVERT", 3);
// }}}
-// {{{ class DB
-
/**
- * This class implements a factory method for creating DB objects,
- * as well as some "static methods".
+ * The main "DB" class is simply a container class with some static
+ * methods for creating DB objects as well as some utility functions
+ * common to all parts of DB.
*
- * @version 100
+ * The object model of DB is as follows (indentation means inheritance):
+ *
+ * DB The main DB class. This is simply a utility class
+ * with some "static" methods for creating DB objects as
+ * well as common utility functions for other DB classes.
+ *
+ * DB_common The base for each DB implementation. Provides default
+ * | implementations (some would say virtual methods) for
+ * | the actual DB implementations as well as a bunch of
+ * | query utility functions.
+ * |
+ * +-DB_mysql The DB implementation for MySQL. Inherits DB_common.
+ * When calling DB::factory or DB::connect for MySQL
+ * connections, the object returned is an instance of this
+ * class.
+ *
+ * @version 1.00
* @author Stig Bakken <ssb@fast.no>
- * @since 4.0b4
+ * @since PHP 4.0
*/
class DB {
// {{{ factory()
/**
* Create a new DB object for the specified database type.
+ *
* @param $type database type
- * @return object a newly created DB object, or false on error
+ *
+ * @return object a newly created DB object, or a DB error code on
+ * error
*/
function factory($type) {
global $USED_PACKAGES;
@@ -93,6 +143,19 @@
// }}}
// {{{ connect()
+ /**
+ * Create a new DB object and connect to the specified database.
+ *
+ * @param $dsn "data source name", see the parseDSN method for a
+ * description of the dsn format.
+ *
+ * @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
+ */
function connect($dsn, $persistent = false) {
global $USED_PACKAGES;
@@ -109,7 +172,10 @@
}
$classname = 'DB_' . $type;
$obj = new $classname;
- $obj->connect(&$dsninfo, $persistent);
+ $err = $obj->connect(&$dsninfo, $persistent);
+ if (DB::isError($err)) {
+ return $err;
+ }
return $obj; // XXX ADDREF
}
@@ -118,10 +184,11 @@
/**
* Return the DB API version.
- * @return int the DB API version number
+ *
+ * @return double the DB API version number
*/
function apiVersion() {
- return 100;
+ return 1.00;
}
// }}}
@@ -129,8 +196,10 @@
/**
* Tell whether a result code from a DB method is an error.
- * @param $code result code
- * @return bool whether $code is an error
+ *
+ * @param $code result code
+ *
+ * @return bool whether $code is an error
*/
function isError($code) {
return is_int($code) && ($code < 0);
@@ -140,9 +209,12 @@
// {{{ errorMessage()
/**
- * Return a textual error message for an error code.
- * @param $code error code
- * @return string error message
+ * Return a textual error message for a DB error code.
+ *
+ * @param $code error code
+ *
+ * @return string error message, or false if the error code was
+ * not recognized
*/
function errorMessage($code) {
if (!is_array($errorMessages)) {
@@ -160,7 +232,12 @@
DB_ERROR_INVALID_NUMBER => "invalid number",
DB_ERROR_INVALID_DATE => "invalid date or time",
DB_ERROR_DIVZERO => "division by zero",
- DB_ERROR_NODBSELECTED => "no database selected"
+ DB_ERROR_NODBSELECTED => "no database selected",
+ DB_ERROR_CANNOT_CREATE => "can not create",
+ DB_ERROR_CANNOT_DELETE => "can not delete",
+ DB_ERROR_CANNOT_DROP => "can not drop",
+ DB_ERROR_NOSUCHTABLE => "no such table",
+ DB_ERROR_NOSUCHFIELD => "no such field"
);
}
return $errorMessages[$code];
@@ -260,18 +337,18 @@
// }}}
}
-// }}}
-// {{{ class DB_result
-
/**
* This class implements a wrapper for a DB result set.
* A new instance of this class will be returned by the DB implementation
* after processing a query that returns data.
*/
class DB_result {
+ // {{{ properties
+
var $dbh;
var $result;
+ // }}}
// {{{ DB_result()
/**
@@ -324,7 +401,7 @@
// {{{ free()
/**
- * Frees the resource for this result and reset ourselves.
+ * Frees the resources allocated for this result set.
* @return int error code
*/
function free() {
@@ -338,8 +415,6 @@
// }}}
}
-
-// }}}
// Local variables:
// tab-width: 4
Index: php4/pear/DB/common.php
diff -u php4/pear/DB/common.php:1.3 php4/pear/DB/common.php:1.4
--- php4/pear/DB/common.php:1.3 Sun Dec 12 04:26:58 1999
+++ php4/pear/DB/common.php Sun Dec 12 10:55:57 1999
@@ -17,15 +17,13 @@
// | |
// +----------------------------------------------------------------------+
//
-// Database independent query interface definition for PHP's MySQL
-// extension.
+// Base class for DB implementations.
//
//
// XXX legend:
//
-// XXX ERRORMSG: The error message from the mysql function should
-// be registered here.
+// XXX ERRORMSG: Needs a better way of dealing with errors.
// XXX ADDREF: As soon as Zend/PHP gets support for returning
// references, this return value should be made into
// a reference.
@@ -34,12 +32,16 @@
if ($GLOBALS['USED_PACKAGES']['DB/common']) return;
$GLOBALS['USED_PACKAGES']['DB/common'] = true;
+/**
+ * DB_common is a base class for DB implementations, and should be
+ * inherited by all such.
+ */
class DB_common {
// {{{ properties
- var $features;
- var $errorcode_map;
- var $type;
+ var $features; // assoc of capabilities for this DB implementation
+ var $errorcode_map; // assoc mapping native error codes to DB ones
+ var $type; // DB type (mysql, oci8, odbc etc.)
// }}}
// {{{ constructor
@@ -52,29 +54,71 @@
// }}}
// {{{ quoteString()
+ /**
+ * Quotes a string so it can be safely used within string delimiters
+ * in a query.
+ *
+ * @param $string the input string to quote
+ *
+ * @return string the quoted string
+ */
function quoteString($string) {
return str_replace("'", "\'", $string);
}
// }}}
- // {{{ capableOf()
+ // {{{ provides()
- function capableOf($feature) {
+ /**
+ * Tell whether a DB implementation or its backend extension
+ * supports a given feature.
+ *
+ * @param $feature name of the feature (see the DB class doc)
+ *
+ * @return bool whether this DB implementation supports $feature
+ */
+ function provides($feature) {
return $this->features[$feature];
}
// }}}
// {{{ 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($nativecode) {
- return $this->errorcode_map[$nativecode];
+ if ($this->errorcode_map[$nativecode]) {
+ return $this->errorcode_map[$nativecode];
+ }
+ //php_error(E_WARNING, get_class($this)."::errorCode: no mapping for $nativecode");
+ // Fall back to DB_ERROR if there was no mapping. Ideally,
+ // this should never happen.
+ return DB_ERROR;
}
// }}}
// {{{ errorMessage()
- function errorMessage($nativecode) {
- return DB::errorMessage($this->errorcode_map[$nativecode]);
+ /**
+ * Map a DB error code to a textual message. This is actually
+ * just a wrapper for DB::errorMessage().
+ *
+ * @param $dbcode the DB error code
+ *
+ * @return string the corresponding error message, of FALSE
+ * if the error code was unknown
+ */
+ function errorMessage($dbcode) {
+ return DB::errorMessage($this->errorcode_map[$dbcode]);
}
// }}}
@@ -89,16 +133,17 @@
* @param $query the SQL query
*/
function getOne($query) {
- $sth = $this->query($query);
+ $res = $this->simpleQuery($query);
if (DB::isError($sth)) {
return $sth;
}
- $row = $sth->fetchRow();
- $sth->free();
+ $row = $this->fetchRow($res);
if (DB::isError($row)) {
return $row;
}
- return $row[0];
+ $ret = &$row[0];
+ $this->freeResult($res);
+ return $ret;
}
// }}}
@@ -113,13 +158,16 @@
* 0, or a DB error code.
*/
function getRow($query) {
- $sth = $this->query($query);
- if (DB::isError($sth)) {
- return $sth;
+ $res = $this->simpleQuery($query);
+ if (DB::isError($res)) {
+ return $res;
+ }
+ $row = $this->fetchRow($res);
+ if (DB::isError($row)) {
+ return $row;
}
- $row = $sth->fetchRow();
- $sth->free();
- return $row;
+ $this->freeResult($res);
+ return $row; // XXX ADDREF
}
// }}}
@@ -167,36 +215,36 @@
* )
*
* Keep in mind that database functions in PHP usually return string
- * values regardless of the DBMS type.
+ * values for results regardless of the database's internal type.
*/
function getAssoc($query, $force_array = false) {
- $sth = $this->query($query);
- if (DB::isError($sth)) {
- return $sth;
+ $res = $this->simpleQuery($query);
+ if (DB::isError($res)) {
+ return $res;
}
- $cols = $sth->numCols();
+ $cols = $this->numCols($res);
if ($cols < 2) {
return DB_ERROR_TRUNCATED;
}
$results = array();
- // XXX the following code can be optimized!
if ($cols > 2 || $force_array) {
// return array values
- while (!DB::isError($row = $sth->fetchRow())) {
+ // XXX this part can be optimized
+ while (!DB::isError($row = $this->fetchRow($res))) {
reset($row);
- // we copy the row data into a new array
+ // we copy the row of data into a new array
// to get indices running from 0 again
for ($i = 1; $i < $cols; $i++) {
$results[$row[0]][$i-1] = $row[$i];
- $results[$row[0]][$k - 1] = $v;
}
}
} else {
// return scalar values
- while (!DB::isError($row = $sth->fetchRow())) {
+ while (!DB::isError($row = $this->fetchRow($res))) {
$results[$row[0]] = $row[1];
}
}
+ return $results; // XXX ADDREF
}
// }}}
Index: php4/pear/DB/mysql.php
diff -u php4/pear/DB/mysql.php:1.5 php4/pear/DB/mysql.php:1.6
--- php4/pear/DB/mysql.php:1.5 Fri Dec 10 10:02:35 1999
+++ php4/pear/DB/mysql.php Sun Dec 12 10:55:57 1999
@@ -56,12 +56,28 @@
'pconnect' => true,
'transactions' => false
);
+ $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,
+ 1146 => DB_ERROR_NOSUCHTABLE,
+ 1064 => DB_ERROR_SYNTAX,
+ 1054 => DB_ERROR_NOSUCHFIELD,
+ 1062 => DB_ERROR_ALREADY_EXISTS,
+ 1051 => DB_ERROR_NOSUCHTABLE
+ );
}
// }}}
// {{{ connect()
+ /**
+ * Connect
+ */
function connect($dsn, $persistent = false) {
if (is_array($dsn)) {
$dsninfo = &$dsn;
@@ -91,24 +107,37 @@
mysql_select_db($dsninfo['database'], $conn);
}
$this->connection = $conn;
- return $conn;
+ return DB_OK;
}
// }}}
// {{{ disconnect()
+ /**
+ * Log out and disconnect from the database.
+ *
+ * @return bool TRUE on success, FALSE if not connected.
+ */
function disconnect() {
- $err = mysql_close($this->connection); // XXX ERRORMSG
- return $err;
+ return mysql_close($this->connection); // XXX ERRORMSG
}
// }}}
// {{{ query()
+
+ /**
+ * Send a query to MySQL and return the results as a DB_result object.
+ *
+ * @param $query the SQL query
+ *
+ * @return object a DB_result object on success, a DB error code
+ * on failure
+ */
function query($query) {
$result = mysql_query($query, $this->connection);
if (!$result) {
- return $this->mapErrorCode(mysql_errno($this->connection));
+ return $this->errorCode(mysql_errno($this->connection));
}
// Determine which queries that should return data, and which
// should return an error code only.
@@ -121,13 +150,45 @@
}
// }}}
+ // {{{ simpleQuery()
+
+ /**
+ * Send a query to MySQL and return the results as a MySQL resource
+ * identifier.
+ *
+ * @param $query the SQL query
+ *
+ * @return int a valid MySQL result resource on success, a DB error
+ * code on failure.
+ */
+ function simpleQuery($query) {
+ $result = mysql_query($query, $this->connection);
+ if (!$result) {
+ return $this->errorCode(mysql_errno($this->connection));
+ }
+ // Determine which queries that should return data, and which
+ // should return an error code only.
+ if (eregi('SELECT', $query)) {
+ return $result;
+ } else {
+ return DB_OK;
+ }
+ }
+
+ // }}}
// {{{ fetchRow()
+ /**
+ * Fetch a row and return as array.
+ *
+ * @param $result MySQL result identifier
+ *
+ * @return int an array on success, a DB error code on failure
+ */
function fetchRow($result) {
$row = mysql_fetch_row($result);
if (!$row) {
- // XXX ERRORMSG
- return false;
+ return $this->errorCode(mysql_errno($this->connection));
}
return $row; // XXX ADDREF
}
@@ -135,11 +196,18 @@
// }}}
// {{{ 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
+ *
+ * @return int DB_OK on success, a DB error code on failure
+ */
function fetchInto($result, &$arr) {
$arr = mysql_fetch_row($result);
if (!$arr) {
- // XXX ERRORMSG
- return false;
+ return $this->errorCode(mysql_errno($this->connection));
}
return DB_OK;
}
@@ -147,54 +215,55 @@
// }}}
// {{{ freeResult()
+ /**
+ * Free the internal resources associated with $result.
+ *
+ * @param $result MySQL result identifier
+ *
+ * @return bool TRUE on success, FALSE if $result is invalid
+ */
function freeResult($result) {
- $err = mysql_free_result($result); // XXX ERRORMSG
- return $err;
+ return mysql_free_result($result);
}
// }}}
// {{{ numCols()
+ /**
+ * Get the number of columns in a result set.
+ *
+ * @param $result MySQL result identifier
+ *
+ * @return int the number of columns per row in $result
+ */
function numCols($result) {
$cols = mysql_num_fields($result);
if (!$cols) {
- return $this->mapErrorCode(mysql_errno($this->connection));
+ return $this->errorCode(mysql_errno($this->connection));
}
return $cols;
}
// }}}
- // {{{ mapErrorCode()
+ // {{{ errorNative()
- function mapErrorCode($nativecode) {
- if (!$codemap) {
- // XXX FIXME
- $codemap = 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
- );
- }
- if ($codemap[$nativecode]) {
- return $codemap[$nativecode];
- } else {
- php3_error(E_WARNING, "DB_mysql::mapErrorCode: no mapping for $nativecode");
- return false;
- }
+ /**
+ * Get the native error code of the last error (if any) that
+ * occured on the current connection.
+ *
+ * @return int native MySQL error code
+ */
+ function errorNative() {
+ return mysql_errno($this->connection);
}
- // }}}
+ // }}}
+ // Methods still not implemented:
// prepare
// execute
- // errorCode
- // errorMsg
- // errorNative
// longReadlen
- // binMode
+ // binmode
// autoCommit
// commit
// rollback