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 + -
显示快捷键?