예제 #1
0
 @Override
 public Value getValue(Session session) {
   query.setSession(session);
   ResultInterface result = query.query(2);
   try {
     int rowcount = result.getRowCount();
     if (rowcount > 1) {
       throw DbException.get(ErrorCode.SCALAR_SUBQUERY_CONTAINS_MORE_THAN_ONE_ROW);
     }
     Value v;
     if (rowcount <= 0) {
       v = ValueNull.INSTANCE;
     } else {
       result.next();
       Value[] values = result.currentRow();
       if (result.getVisibleColumnCount() == 1) {
         v = values[0];
       } else {
         v = ValueArray.get(values);
       }
     }
     return v;
   } finally {
     result.close();
   }
 }
예제 #2
0
 private void sendRow(ResultInterface result) throws IOException {
   if (result.next()) {
     transfer.writeBoolean(true);
     Value[] v = result.currentRow();
     for (int i = 0; i < result.getVisibleColumnCount(); i++) {
       if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_12) {
         transfer.writeValue(v[i]);
       } else {
         writeValue(v[i]);
       }
     }
   } else {
     transfer.writeBoolean(false);
   }
 }
예제 #3
0
 // 总共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();
   }
 }