/** * Parse and prepare the given SQL statement. This method also checks if the connection has been * closed. * * @param sql the SQL statement * @return the prepared statement */ public Command prepareLocal(String sql) { if (closed) { throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "session closed"); } Command command; if (queryCacheSize > 0) { if (queryCache == null) { queryCache = SmallLRUCache.newInstance(queryCacheSize); modificationMetaID = database.getModificationMetaId(); } else { long newModificationMetaID = database.getModificationMetaId(); if (newModificationMetaID != modificationMetaID) { queryCache.clear(); modificationMetaID = newModificationMetaID; } command = queryCache.get(sql); if (command != null && command.canReuse()) { command.reuse(); return command; } } } Parser parser = new Parser(this); command = parser.prepareCommand(sql); if (queryCache != null) { if (command.isCacheable()) { queryCache.put(sql, command); } } return command; }
/** * Get or create a trace object for this module. * * @param module the module name * @return the trace object */ public synchronized Trace getTrace(String module) { Trace t = traces.get(module); if (t == null) { t = new Trace(writer, module); traces.put(module, t); } return t; }
private void writeValue(Value v) throws IOException { if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) { if (v instanceof ValueLobDb) { ValueLobDb lob = (ValueLobDb) v; if (lob.isStored()) { long id = lob.getLobId(); lobs.put(id, new CachedInputStream(null)); } } } transfer.writeValue(v); }
public PlanItem getBestPlanItem(Session session, int[] masks) { PlanItem item = new PlanItem(); item.cost = index.getCost(session, masks); IntArray masksArray = new IntArray(masks == null ? Utils.EMPTY_INT_ARRAY : masks); ViewIndex i2 = indexCache.get(masksArray); if (i2 == null || i2.getSession() != session) { i2 = new ViewIndex(this, index, session, masks); indexCache.put(masksArray, i2); } item.setIndex(i2); return item; }
public double getCost(Session session, int[] masks) { if (recursive) { return 1000; } IntArray masksArray = new IntArray(masks == null ? Utils.EMPTY_INT_ARRAY : masks); CostElement cachedCost = costCache.get(masksArray); if (cachedCost != null) { long time = System.currentTimeMillis(); if (time < cachedCost.evaluatedAt + Constants.VIEW_COST_CACHE_MAX_AGE) { return cachedCost.cost; } } Query q = (Query) session.prepare(querySQL, true); if (masks != null) { IntArray paramIndex = new IntArray(); for (int i = 0; i < masks.length; i++) { int mask = masks[i]; if (mask == 0) { continue; } paramIndex.add(i); } int len = paramIndex.size(); for (int i = 0; i < len; i++) { int idx = paramIndex.get(i); int mask = masks[idx]; int nextParamIndex = q.getParameters().size() + view.getParameterOffset(); if ((mask & IndexCondition.EQUALITY) != 0) { Parameter param = new Parameter(nextParamIndex); q.addGlobalCondition(param, idx, Comparison.EQUAL_NULL_SAFE); } else { if ((mask & IndexCondition.START) != 0) { Parameter param = new Parameter(nextParamIndex); q.addGlobalCondition(param, idx, Comparison.BIGGER_EQUAL); } if ((mask & IndexCondition.END) != 0) { Parameter param = new Parameter(nextParamIndex); q.addGlobalCondition(param, idx, Comparison.SMALLER_EQUAL); } } } String sql = q.getPlanSQL(); q = (Query) session.prepare(sql, true); } double cost = q.getCost(); cachedCost = new CostElement(); cachedCost.evaluatedAt = System.currentTimeMillis(); cachedCost.cost = cost; costCache.put(masksArray, cachedCost); return cost; }
// 总共18条命令,这里包含16条 // 下面这两条在run方法中特殊处理 // SESSION_CANCEL_STATEMENT // SESSION_CHECK_KEY // 分三种级别,从大到小: SESSION级、COMMAND级、RESULT级 private void process() throws IOException { int operation = transfer.readInt(); switch (operation) { case SessionRemote.SESSION_PREPARE_READ_PARAMS: case SessionRemote.SESSION_PREPARE: { int id = transfer.readInt(); String sql = transfer.readString(); int old = session.getModificationId(); Command command = session.prepareLocal(sql); boolean readonly = command.isReadOnly(); cache.addObject(id, command); boolean isQuery = command.isQuery(); ArrayList<? extends ParameterInterface> params = command.getParameters(); transfer .writeInt(getState(old)) .writeBoolean(isQuery) .writeBoolean(readonly) .writeInt(params.size()); if (operation == SessionRemote.SESSION_PREPARE_READ_PARAMS) { for (ParameterInterface p : params) { ParameterRemote.writeMetaData(transfer, p); } } transfer.flush(); break; } case SessionRemote.SESSION_CLOSE: { stop = true; closeSession(); transfer.writeInt(SessionRemote.STATUS_OK).flush(); close(); break; } case SessionRemote.COMMAND_COMMIT: { // 并不是通过org.h2.jdbc.JdbcConnection.commit()触发,此方法是通过发送COMMIT SQL触发 // 触发SessionRemote.COMMAND_COMMIT的是在集群环境下,通过org.h2.engine.SessionRemote.autoCommitIfCluster()触发 if (commit == null) { commit = session.prepareLocal("COMMIT"); } int old = session.getModificationId(); commit.executeUpdate(); transfer.writeInt(getState(old)).flush(); break; } case SessionRemote.COMMAND_GET_META_DATA: { int id = transfer.readInt(); int objectId = transfer.readInt(); Command command = (Command) cache.getObject(id, false); ResultInterface result = command.getMetaData(); cache.addObject(objectId, result); int columnCount = result.getVisibleColumnCount(); transfer.writeInt(SessionRemote.STATUS_OK).writeInt(columnCount).writeInt(0); for (int i = 0; i < columnCount; i++) { ResultColumn.writeColumn(transfer, result, i); } transfer.flush(); break; } case SessionRemote.COMMAND_EXECUTE_QUERY: { int id = transfer.readInt(); int objectId = transfer.readInt(); int maxRows = transfer.readInt(); int fetchSize = transfer.readInt(); Command command = (Command) cache.getObject(id, false); setParameters(command); int old = session.getModificationId(); ResultInterface result; synchronized (session) { result = command.executeQuery(maxRows, false); } cache.addObject(objectId, result); int columnCount = result.getVisibleColumnCount(); int state = getState(old); transfer.writeInt(state).writeInt(columnCount); int rowCount = result.getRowCount(); transfer.writeInt(rowCount); for (int i = 0; i < columnCount; i++) { ResultColumn.writeColumn(transfer, result, i); } int fetch = Math.min(rowCount, fetchSize); for (int i = 0; i < fetch; i++) { sendRow(result); } transfer.flush(); break; } case SessionRemote.COMMAND_EXECUTE_UPDATE: { int id = transfer.readInt(); Command command = (Command) cache.getObject(id, false); // if(command!=null)throw new Error(); setParameters(command); int old = session.getModificationId(); int updateCount; synchronized (session) { updateCount = command.executeUpdate(); } int status; if (session.isClosed()) { status = SessionRemote.STATUS_CLOSED; } else { status = getState(old); } transfer.writeInt(status).writeInt(updateCount).writeBoolean(session.getAutoCommit()); transfer.flush(); break; } case SessionRemote.COMMAND_CLOSE: { int id = transfer.readInt(); Command command = (Command) cache.getObject(id, true); if (command != null) { command.close(); cache.freeObject(id); } break; } case SessionRemote.RESULT_FETCH_ROWS: { int id = transfer.readInt(); int count = transfer.readInt(); ResultInterface result = (ResultInterface) cache.getObject(id, false); transfer.writeInt(SessionRemote.STATUS_OK); for (int i = 0; i < count; i++) { sendRow(result); } transfer.flush(); break; } case SessionRemote.RESULT_RESET: { int id = transfer.readInt(); ResultInterface result = (ResultInterface) cache.getObject(id, false); result.reset(); break; } case SessionRemote.RESULT_CLOSE: { int id = transfer.readInt(); ResultInterface result = (ResultInterface) cache.getObject(id, true); if (result != null) { result.close(); cache.freeObject(id); } break; } case SessionRemote.CHANGE_ID: { int oldId = transfer.readInt(); int newId = transfer.readInt(); Object obj = cache.getObject(oldId, false); cache.freeObject(oldId); cache.addObject(newId, obj); break; } case SessionRemote.SESSION_SET_ID: { sessionId = transfer.readString(); transfer.writeInt(SessionRemote.STATUS_OK).flush(); break; } case SessionRemote.SESSION_SET_AUTOCOMMIT: { boolean autoCommit = transfer.readBoolean(); session.setAutoCommit(autoCommit); transfer.writeInt(SessionRemote.STATUS_OK).flush(); break; } case SessionRemote.SESSION_HAS_PENDING_TRANSACTION: { transfer .writeInt(SessionRemote.STATUS_OK) .writeInt(session.hasPendingTransaction() ? 1 : 0) .flush(); break; } case SessionRemote.LOB_READ: { long lobId = transfer.readLong(); byte[] hmac; CachedInputStream in; boolean verifyMac; if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_11) { if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_12) { hmac = transfer.readBytes(); verifyMac = true; } else { hmac = null; verifyMac = false; } in = lobs.get(lobId); if (in == null && verifyMac) { in = new CachedInputStream(null); lobs.put(lobId, in); } } else { verifyMac = false; hmac = null; in = lobs.get(lobId); } long offset = transfer.readLong(); int length = transfer.readInt(); if (verifyMac) { transfer.verifyLobMac(hmac, lobId); } if (in == null) { throw DbException.get(ErrorCode.OBJECT_CLOSED); } if (in.getPos() != offset) { LobStorageInterface lobStorage = session.getDataHandler().getLobStorage(); InputStream lobIn = lobStorage.getInputStream(lobId, hmac, -1); in = new CachedInputStream(lobIn); lobs.put(lobId, in); lobIn.skip(offset); } // limit the buffer size length = Math.min(16 * Constants.IO_BUFFER_SIZE, length); byte[] buff = new byte[length]; length = IOUtils.readFully(in, buff, 0, length); transfer.writeInt(SessionRemote.STATUS_OK); transfer.writeInt(length); transfer.writeBytes(buff, 0, length); transfer.flush(); break; } default: trace("Unknown operation: " + operation); closeSession(); close(); } }