pdostatement.java

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

JAVA
1,549
字号
/* * 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 Sam */package com.caucho.quercus.lib.db;import com.caucho.quercus.UnimplementedException;import com.caucho.quercus.annotation.Optional;import com.caucho.quercus.annotation.ReadOnly;import com.caucho.quercus.annotation.Reference;import com.caucho.quercus.env.*;import com.caucho.quercus.lib.file.FileReadValue;import com.caucho.util.IntMap;import com.caucho.util.L10N;import com.caucho.vfs.ReadStream;import com.caucho.vfs.TempBuffer;import com.caucho.vfs.TempReadStream;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.logging.Level;import java.util.logging.Logger;/** * PDO object oriented API facade. */public class PDOStatement  implements Iterable<Value>, EnvCleanup{  private static final Logger log = Logger.getLogger(PDOStatement.class.getName());  private static final L10N L = new L10N(PDOStatement.class);  private static final Value[] NULL_VALUES = new Value[0];  //private static final Value FETCH_FAILURE = new NullValue() {};  //private static final Value FETCH_EXHAUSTED = new NullValue() {};  //private static final Value FETCH_CONTINUE = new NullValue() {};  //private static final Value FETCH_SUCCESS = new NullValue() {};    private static final int FETCH_FAILURE = 0;  private static final int FETCH_EXHAUSTED = 1;  private static final int FETCH_CONTINUE = 2;  private static final int FETCH_SUCCESS = 3;    private int _fetchErrorCode;  private final Env _env;  private final PDOError _error;  private final String _query;  private Statement _statement;  private PreparedStatement _preparedStatement;  private ResultSet _resultSet;  private ResultSetMetaData _resultSetMetaData;  private boolean _resultSetExhausted = true;  private String _lastInsertId;  private int _fetchMode = PDO.FETCH_BOTH;  private Value[] _fetchModeArgs = NULL_VALUES;  private ArrayList<BindColumn> _bindColumns;  private ArrayList<BindParam> _bindParams;  private IntMap _parameterNameMap;  PDOStatement(Env env, Connection conn,               String query, boolean isPrepared,               ArrayValue options)    throws SQLException  {    _env = env;    _error = new PDOError(_env);    _query = query;    env.addCleanup(this);    if (options != null && options.getSize() > 0) {      _env.notice(L.l("PDOStatement options unsupported"));    }    query = parseQueryString(query);    if (isPrepared) {      _statement = null;      int ch;      if (query.length() > 4	  && ((ch = query.charAt(0)) == 'c' || ch == 'C')	  && ((ch = query.charAt(1)) == 'a' || ch == 'A')	  && ((ch = query.charAt(2)) == 'l' || ch == 'L')	  && ((ch = query.charAt(3)) == 'l' || ch == 'L')) {	_preparedStatement = conn.prepareCall(query);      }      else	_preparedStatement = conn.prepareStatement(query);      // php/1s41 - oracle can't handle this      //_preparedStatement.setEscapeProcessing(false);    }    else {      _preparedStatement = null;      Statement statement = null;      try {        statement = conn.createStatement();        statement.setEscapeProcessing(false);        if (statement.execute(query)) {          _resultSet = statement.getResultSet();          _resultSetExhausted = false;        }        _statement = statement;        statement = null;      } finally {        try {          if (statement != null)            statement.close();        } catch (SQLException e) {          log.log(Level.FINE, e.toString(), e);        }      }    }  }  // side-effect, updates _parameterNameMap  private String parseQueryString(String query)  {    final int queryLength = query.length();    StringBuilder parsedQuery = new StringBuilder(queryLength);    int parameterCount = 0;    StringBuilder name = null;    int quote = 0;    for (int i = 0; i < queryLength + 1; i++) {      int ch = -1;      if (i < queryLength)        ch = query.charAt(i);      if (ch == '\'' || ch == '"') {        if (quote == 0)          quote = ch;        else if (quote == ch)          quote = 0;      }      else if (quote == 0 && ch == '?') {        parameterCount++;      }      else if (quote == 0 && ch == ':') {        parameterCount++;        name = new StringBuilder();        continue;      }      // XXX: check what characters are allowed      else if (name != null && (ch == -1 || !Character.isJavaIdentifierPart(ch))) {        if (_parameterNameMap == null)          _parameterNameMap = new IntMap();        _parameterNameMap.put(name.toString(), parameterCount);        parsedQuery.append('?');        name = null;      }      if (ch != -1) {        if (name != null)          name.append((char) ch);        else          parsedQuery.append((char) ch);      }    }    return parsedQuery.toString();  }  private boolean advanceResultSet()  {    if (_resultSet == null || _resultSetExhausted)      return false;    try {      boolean isNext =  _resultSet.next();      if (!isNext)        _resultSetExhausted = true;      if (!isNext)        return false;      if (_bindColumns != null) {        for (BindColumn bindColumn : _bindColumns)          if (!bindColumn.bind())            return false;      }      return isNext;    }    catch (SQLException ex) {      _error.error(ex);      return false;    }  }  public boolean bindColumn(Value column, @Reference Value var, @Optional("-1") int type)  {    if (_bindColumns == null)      _bindColumns = new ArrayList<BindColumn>();    try {      _bindColumns.add(new BindColumn(column, var, type));    }    catch (SQLException ex) {      _error.error(ex);      return false;    }    return true;  }  public boolean bindParam(Value parameter,                           @Reference Value variable,                           @Optional("-1") int dataType,                           @Optional("-1") int length,                           @Optional Value driverOptions)  {    if (length != -1)      throw new UnimplementedException("length");    if (!(driverOptions == null || driverOptions.isNull()))      throw new UnimplementedException("driverOptions");    if (dataType == -1)      dataType = PDO.PARAM_STR;    boolean isInputOutput = (dataType & PDO.PARAM_INPUT_OUTPUT) != 0;    if (isInputOutput) {      dataType = dataType & (~PDO.PARAM_INPUT_OUTPUT);      if (true) throw new UnimplementedException("PARAM_INPUT_OUTPUT");    }    switch (dataType) {      case PDO.PARAM_BOOL:      case PDO.PARAM_INT:      case PDO.PARAM_LOB:      case PDO.PARAM_NULL:      case PDO.PARAM_STMT:      case PDO.PARAM_STR:        break;      default:        _error.warning(L.l("unknown dataType `{0}'", dataType));        return false;    }    if (_bindParams == null)      _bindParams = new ArrayList<BindParam>();    BindParam bindParam = new BindParam(parameter, variable, dataType, length, driverOptions);    _bindParams.add(bindParam);    return true;  }  public boolean bindValue(Value parameter,                           Value value,                           @Optional("-1") int dataType)  {    return bindParam(parameter, value.toValue(), dataType, -1, null);  }  /**   * Closes the current cursor.   */  public boolean closeCursor()  {    if (_resultSet == null)      return false;    ResultSet resultSet = _resultSet;    _resultSet = null;    _resultSetMetaData = null;    _resultSetExhausted = true;    _lastInsertId = null;    try {      resultSet.close();    }    catch (SQLException e) {      _error.error(e);      return false;    }    return true;  }  /**   * Returns the number of columns.   */  public int columnCount()  {    if (_resultSet == null)      return 0;    try {      return getResultSetMetaData().getColumnCount();    }    catch (SQLException e) {      _error.error(e);      return 0;    }  }  public BindParam createBindParam(Value parameter, Value value, int dataType, int length, Value driverOptions)  {    return new BindParam(parameter, value, dataType, length, driverOptions);  }  public void close()  {    cleanup();  }  /**   * Implements the EnvCleanup interface.   */  public void cleanup()  {    ResultSet resultSet = _resultSet;    Statement statement = _statement;    PreparedStatement preparedStatement = _preparedStatement;    _resultSet = null;    _resultSetMetaData = null;    _resultSetExhausted = true;    _lastInsertId = null;    _statement = null;    _preparedStatement = null;    if (resultSet != null)  {      try {        resultSet.close();      }      catch (SQLException e) {        log.log(Level.WARNING, e.toString(), e);      }    }    if (statement != null)  {      try {        statement.close();      }      catch (SQLException e) {        log.log(Level.WARNING, e.toString(), e);      }    }    if (preparedStatement != null)  {      try {        preparedStatement.close();      }      catch (SQLException e) {        log.log(Level.WARNING, e.toString(), e);      }    }  }  public String errorCode()  {    return _error.errorCode();  }  public ArrayValue errorInfo()  {    return _error.errorInfo();  }  /**   * Execute the statement.   *   * @param inputParameters an array containing input values to correspond to   * the bound parameters for the statement.   *   * @return true for success, false for failure   */  public boolean execute(@Optional @ReadOnly Value inputParameters)  {    // XXX: s/b to do this with ArrayValue arg, but cannot differentiate between    // no args and bad arg that isn't an ArrayValue    ArrayValue parameters;    if (inputParameters instanceof ArrayValue)      parameters = (ArrayValue) inputParameters;    else if (inputParameters instanceof DefaultValue)      parameters = null;    else {      _env.warning(L.l("'{0}' is an unexpected argument, expected ArrayValue", inputParameters));      return false;    }    closeCursor();    try {      _preparedStatement.clearParameters();      _preparedStatement.clearWarnings();      if (parameters != null) {        for (Map.Entry<Value, Value> entry : parameters.entrySet()) {          Value key = entry.getKey();          if (key.isNumberConvertible()) {            if (! setParameter(key.toInt() + 1, entry.getValue(), -1))              return false;          }          else {            if (! setParameter(resolveParameter(key), entry.getValue(), -1))              return false;          }        }      }      else if (_bindParams != null) {        for (BindParam bindParam : _bindParams) {          if (!bindParam.apply())            return false;        }      }      if (_preparedStatement.execute()) {        _resultSet = _preparedStatement.getResultSet();        _resultSetExhausted = false;      }      SQLWarning sqlWarning = _preparedStatement.getWarnings();      if (sqlWarning != null) {        _error.error(sqlWarning);        return false;      }      return true;    } catch (SQLException e) {      _error.error(e);      return false;    }  }  /**   * Fetch the next row.   *   * @param fetchMode the mode, 0 to use the value set by {@link #setFetchMode}.   * @return a value, BooleanValue.FALSE if there are no more rows or an error occurs.   */  public Value fetch(@Optional int fetchMode,                     @Optional("-1") int cursorOrientation,                     @Optional("-1") int cursorOffset)  {    if (cursorOrientation != -1)      throw new UnimplementedException("fetch with cursorOrientation");    if (cursorOffset != -1)      throw new UnimplementedException("fetch with cursorOffset");    return fetchImpl(fetchMode, -1);  }  /**   *   * @param fetchMode   * @param columnIndex 0-based column index when fetchMode is FETCH_BOTH   */  public Value fetchAll(@Optional("0") int fetchMode, @Optional("-1") int columnIndex)  {    int effectiveFetchMode;

⌨️ 快捷键说明

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