cvs: /php4/pear DB.php /php4/pear/DB common.php mysql.php

From: 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

« previous php.version4 (#7825) next »