mysqli.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,588 行 · 第 1/3 页

JAVA
1,588
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Charles Reich */package com.caucho.quercus.lib.db;import com.caucho.quercus.QuercusException;import com.caucho.quercus.UnimplementedException;import com.caucho.quercus.annotation.Optional;import com.caucho.quercus.annotation.ResourceType;import com.caucho.quercus.annotation.ReturnNullAsFalse;import com.caucho.quercus.env.BooleanValue;import com.caucho.quercus.env.Env;import com.caucho.quercus.env.LongValue;import com.caucho.quercus.env.StringValue;import com.caucho.quercus.env.UnicodeValueImpl;import com.caucho.quercus.env.Value;import com.caucho.util.L10N;import java.io.UnsupportedEncodingException;import java.sql.Connection;import java.sql.DataTruncation;import java.sql.DatabaseMetaData;import java.sql.Driver;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Statement;import java.util.ArrayList;import java.util.logging.Level;import java.util.logging.Logger;/** * mysqli object oriented API facade */@ResourceType("mysql link")public class Mysqli extends JdbcConnectionResource {  private static final Logger log = Logger.getLogger(Mysqli.class.getName());  private static final L10N L = new L10N(Mysqli.class);    protected static final String DRIVER    = "com.mysql.jdbc.Driver";  /**   * mysqli_multi_query populates _resultValues   * NB: any updates (ie: INSERT, UPDATE, DELETE) will   * have the update counts ignored.   *   * Has been stored tells moreResults whether the   * _nextResultValue has been stored already.   * If so, more results will return true only if   * there is another result.   *   * _hasBeenStored is set to true by default.   * if _hasBeenUsed == false, then   * _resultValues.get(_nextResultValue)   * is ready to be used by the next call to   * mysqli_store_result or mysqli_use_result.   */  private ArrayList<JdbcResultResource> _resultValues    = new ArrayList<JdbcResultResource>();  private int _nextResultValue = 0;  private boolean _hasBeenUsed = true;  private static volatile String _checkedDriverVersion = null;  private static Object _checkDriverLock = new Object();  private LastSqlType _lastSql;  /**    * This is the constructor for the mysqli class.    * It can be invoked by PHP or and by Java code.    */  public Mysqli(Env env,                @Optional("localhost") StringValue host,                @Optional StringValue user,                @Optional StringValue password,                @Optional StringValue db,                @Optional("3306") int port,                @Optional StringValue socket)  {    super(env);    String hostStr;    if (host.length() == 0)      hostStr = "localhost";    else      hostStr = host.toString();    connectInternal(env, hostStr, user.toString(), password.toString(),                    db.toString(), port, socket.toString(),                    0, null, null);  }  /**   * This constructor can only be invoked by other method   * implementations in the mysql and mysqli modules. It   * accepts String arguments and supports additional   * arguments not available in the mysqli constructor.   */  Mysqli(Env env,         String host,         String user,         String password,         String db,         int port,         String socket,         int flags,         String driver,         String url)  {    super(env);    if (host == null || host.length() == 0)      host = "localhost";    connectInternal(env, host, user, password, db, port, socket,		    flags, driver, url);  }  protected Mysqli(Env env)  {    super(env);  }  public String getResourceType()  {    return "mysql link";  }  public boolean isLastSqlDescribe()  {    return _lastSql == LastSqlType.DESCRIBE;  }    /**   * Connects to the underlying database.   */  protected Connection connectImpl(Env env,                                   String host,                                   String userName,                                   String password,                                   String dbname,                                   int port,                                   String socket,                                   int flags,                                   String driver,                                   String url)  {    if (isConnected()) {      env.warning(L.l("Connection is already opened to '{0}'", this));      return null;    }    if (port <= 0) {      port = 3306;    }    try {      if (host == null || host.equals("")) {        host = "localhost";      }      if (driver == null || driver.equals("")) {        driver = DRIVER;      }      if (url == null || url.equals("")) {        url = getUrl(host, port, dbname, ENCODING,                     (flags & MysqliModule.MYSQL_CLIENT_INTERACTIVE) != 0,                     (flags & MysqliModule.MYSQL_CLIENT_COMPRESS) != 0,                     (flags & MysqliModule.MYSQL_CLIENT_SSL) != 0);      }            Connection jConn = env.getConnection(driver, url, userName, password);      checkDriverVersion(env, jConn);      return jConn;    } catch (SQLException e) {      env.warning(L.l("A link to the server could not be established.\n  url={0}\n  driver={1}\n  {2}", url, driver, e.toString()), e);      env.setSpecialValue("mysqli.connectErrno", new LongValue(e.getErrorCode()));      env.setSpecialValue("mysqli.connectError", env.createString(e.getMessage()));      return null;    } catch (Exception e) {      env.warning(L.l("A link to the server could not be established.\n  url={0}\n  driver={1}\n  {2}", url, driver, e.toString()), e);      env.setSpecialValue("mysqli.connectError", env.createString(e.toString()));      return null;    }  }    protected static String getUrl(String host,                                 int port,                                 String dbname,                                 String encoding,                                 boolean useInteractive,                                 boolean useCompression,                                 boolean useSsl)  {    StringBuilder urlBuilder = new StringBuilder();        urlBuilder.append("jdbc:mysql://");    urlBuilder.append(host);    urlBuilder.append(":");    urlBuilder.append(port);    urlBuilder.append("/");    urlBuilder.append(dbname);    // Ignore MYSQL_CLIENT_LOCAL_FILES and MYSQL_CLIENT_IGNORE_SPACE flags.    if (useInteractive) {      char sep = (urlBuilder.indexOf("?") < 0) ? '?' : '&';      urlBuilder.append(sep);      urlBuilder.append("interactiveClient=true");    }    if (useCompression) {      char sep = (urlBuilder.indexOf("?") < 0) ? '?' : '&';      urlBuilder.append(sep);      urlBuilder.append("useCompression=true");    }    if (useSsl) {      char sep = (urlBuilder.indexOf("?") < 0) ? '?' : '&';      urlBuilder.append(sep);      urlBuilder.append("useSSL=true");    }    // Explicitly indicate that we want iso-8859-1 encoding so    // we would know what encoding to use to convert StringValues    // to Strings    // php/140b    if (encoding != null) {      char sep = urlBuilder.indexOf("?") < 0 ? '?' : '&';      urlBuilder.append(sep);      urlBuilder.append("characterEncoding=");      urlBuilder.append(encoding);    }/*    //urlBuilder.append("&useInformationSchema=true");        // required to get the result table name alias,    // doesn't work in mysql JDBC 5.1.6, but set it anyways in case    // the mysql guys fix it    //    // php/141p    urlBuilder.append("&useOldAliasMetadataBehavior=true");*/    return urlBuilder.toString();  }  /**   * Quercus function to get the field 'affected_rows'.   */  public int getaffected_rows()  {    return affected_rows();  }    /**   * returns the number of affected rows.   */  public int affected_rows()  {    return validateConnection().getAffectedRows();  }  /**   * sets the autocommit mode   */  public boolean autocommit(boolean isAutoCommit)  {    return validateConnection().setAutoCommit(isAutoCommit);  }  /**   * Changes the user and database   *   * @param user the new user   * @param password the new password   * @param db the new database   */  public boolean change_user(StringValue user, StringValue password, StringValue db)  {    // XXX: Docs for mysqli_change_user indicate that if new user authorization fails,    // then the existing user perms are retained.    close(getEnv());        String userStr;    String passwordStr;    String dbStr;    if (user.length() == 0) {      userStr = getUserName();    } else {      userStr = user.toString();    }    if (password.length() == 0)      passwordStr = getPassword();    else      passwordStr = password.toString();    if (db.length() == 0)      dbStr = getCatalog().toString();    else      dbStr = db.toString();    return connectInternal(getEnv(), _host, userStr, passwordStr,                           dbStr, _port, _socket, _flags, _driver, _url);  }  /**   * Returns the client encoding.   *   * XXX: stubbed out. has to be revised once we   * figure out what to do with character encoding   */  public StringValue character_set_name(Env env)  {    return env.createString(getCharacterSetName());  }  /**   * Alias for character_set_name   */  public StringValue client_encoding(Env env)  {    return character_set_name(env);  }  /**   * Quercus function to get the field 'errno'.   */  public int geterrno()  {    return errno();  }    /**   * Returns the error code for the most recent function call   */  public int errno()  {    if (isConnected())      return getErrorCode();    else      return 0;  }  /**   * Quercus function to get the field 'error'.   */  public StringValue geterror(Env env)  {    return error(env);  }  /**   * Escapes the string   */  public StringValue escape_string(StringValue str)  {    return real_escape_string(str);  }  /**   * Quercus function to get the field 'client_info'.   */  public StringValue getclient_info(Env env)  {    return getClientInfo(env);  }  /**   * Returns the client information.   */  static StringValue getClientInfo(Env env)  {    String version = env.getQuercus().getMysqlVersion();    if (version != null) {      // php/1f2h      // Initialized to a specific version via:      // <init mysql-version="X.X.X">    } else {      // php/142h      if (_checkedDriverVersion != null && _checkedDriverVersion != "") {        // A connection has already been made and the driver        // version has been validated.        version = _checkedDriverVersion;      } else {        // A connection has not been made or a valid driver        // version was not found. The JDBC API provides no        // way to get the release number without a connection,        // so just grab the major and minor number and use        // zero for the release number.        try {          Driver driver = DriverManager.getDriver("jdbc:mysql://localhost/");          version = driver.getMajorVersion() + "." +                    driver.getMinorVersion() + ".00";        }        catch (SQLException e) {          version = "0.00.00";        }      }    }    return env.createString(version);  }  /**   * Quercus function to get the field 'client_version'.   */  public int getclient_version(Env env)  {    return MysqliModule.mysqli_get_client_version(env);  }    /**   * Returns the database name.   */  public Value get_dbname(Env env)  {    return getCatalog();  }    /**   * Quercus function to get the field 'host_info'.   */  public StringValue gethost_info(Env env)  {    return get_host_info(env);  }    /**   * Returns the host information.   */  public StringValue get_host_info(Env env)  {    return env.createString(getHost() + " via TCP socket");  }  /**   * Returns the host name.   */  public StringValue get_host_name(Env env)  {    return env.createString(getHost());  }  /**   * Quercus function to get the field 'info'.   */  public Value getinfo(Env env)  {    return info(env);  }  /**   * Return info string about the most recently executed   * query. Documentation for mysql_info() indicates that   * only some kinds of INSERT, UPDATE, LOAD, and ALTER   * statements return results. A SELECT statement always   * returns FALSE. The ConnectorJ module should provide a   * way to get this result string since it is read from   * the server, but that is not supported. This function   * errors on the side of returning more results than   * it should since it is an acceptable compromise.   */  Value info(Env env) {    if (getResultResource() != null) {      // Last SQL statement was a SELECT      return BooleanValue.FALSE;    }    // INSERT result:      "Records: 23 Duplicates: 0 Warnings: 0"    // LOAD result:        "Records: 42 Deleted: 0 Skipped: 0 Warnings: 0"    // ALTER TABLE result: "Records: 60 Duplicates: 0 Warnings: 0"    // UPDATE result:      "Rows matched: 1  Changed: 1  Warnings: 0"    StringBuilder buff = new StringBuilder();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?