cvs: /php4/pear DB.php Makefile.in /php4/pear/DB common.php mysql.php odbc.php

From: 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); }

« previous php.version4 (#9722) next »