private static Result newResult(Session session, DataInput dataInput, RowInputBinary in, int mode)
      throws IOException, HsqlException {

    Result result = newResult(mode);
    int length = dataInput.readInt();

    in.resetRow(0, length);

    byte[] byteArray = in.getBuffer();
    final int offset = 4;

    dataInput.readFully(byteArray, offset, length - offset);

    switch (mode) {
      case ResultConstants.GETSESSIONATTR:
        result.statementReturnType = in.readByte();
        break;

      case ResultConstants.DISCONNECT:
      case ResultConstants.RESETSESSION:
      case ResultConstants.STARTTRAN:
        break;

      case ResultConstants.PREPARE:
        result.setStatementType(in.readByte());

        result.mainString = in.readString();
        result.rsProperties = in.readByte();
        result.generateKeys = in.readByte();

        if (result.generateKeys == ResultConstants.RETURN_GENERATED_KEYS_COL_NAMES
            || result.generateKeys == ResultConstants.RETURN_GENERATED_KEYS_COL_INDEXES) {
          result.generatedMetaData = new ResultMetaData(in);
        }
        break;

      case ResultConstants.CLOSE_RESULT:
        result.id = in.readLong();
        break;

      case ResultConstants.FREESTMT:
        result.statementID = in.readLong();
        break;

      case ResultConstants.EXECDIRECT:
        result.updateCount = in.readInt();
        result.fetchSize = in.readInt();
        result.statementReturnType = in.readByte();
        result.mainString = in.readString();
        result.rsProperties = in.readByte();
        result.queryTimeout = in.readShort();
        result.generateKeys = in.readByte();

        if (result.generateKeys == ResultConstants.RETURN_GENERATED_KEYS_COL_NAMES
            || result.generateKeys == ResultConstants.RETURN_GENERATED_KEYS_COL_INDEXES) {
          result.generatedMetaData = new ResultMetaData(in);
        }
        break;

      case ResultConstants.CONNECT:
        result.databaseName = in.readString();
        result.mainString = in.readString();
        result.subString = in.readString();
        result.zoneString = in.readString();
        result.updateCount = in.readInt();
        break;

      case ResultConstants.ERROR:
      case ResultConstants.WARNING:
        result.mainString = in.readString();
        result.subString = in.readString();
        result.errorCode = in.readInt();
        break;

      case ResultConstants.CONNECTACKNOWLEDGE:
        result.databaseID = in.readInt();
        result.sessionID = in.readLong();
        result.databaseName = in.readString();
        result.mainString = in.readString();
        break;

      case ResultConstants.UPDATECOUNT:
        result.updateCount = in.readInt();
        break;

      case ResultConstants.ENDTRAN:
        {
          int type = in.readInt();

          result.setActionType(type); // endtran type

          switch (type) {
            case ResultConstants.TX_SAVEPOINT_NAME_RELEASE:
            case ResultConstants.TX_SAVEPOINT_NAME_ROLLBACK:
              result.mainString = in.readString(); // savepoint name
              break;

            case ResultConstants.TX_COMMIT:
            case ResultConstants.TX_ROLLBACK:
            case ResultConstants.TX_COMMIT_AND_CHAIN:
            case ResultConstants.TX_ROLLBACK_AND_CHAIN:
            case ResultConstants.PREPARECOMMIT:
              break;

            default:
              throw Error.runtimeError(ErrorCode.U_S0500, "Result");
          }

          break;
        }
      case ResultConstants.SETCONNECTATTR:
        {
          int type = in.readInt(); // attr type

          result.setConnectionAttrType(type);

          switch (type) {
            case ResultConstants.SQL_ATTR_SAVEPOINT_NAME:
              result.mainString = in.readString(); // savepoint name
              break;

              //  case ResultConstants.SQL_ATTR_AUTO_IPD :
              //      - always true
              //  default: throw - case never happens
            default:
              throw Error.runtimeError(ErrorCode.U_S0500, "Result");
          }

          break;
        }
      case ResultConstants.PREPARE_ACK:
        result.statementReturnType = in.readByte();
        result.statementID = in.readLong();
        result.rsProperties = in.readByte();
        result.metaData = new ResultMetaData(in);
        result.parameterMetaData = new ResultMetaData(in);
        break;

      case ResultConstants.CALL_RESPONSE:
        result.updateCount = in.readInt();
        result.fetchSize = in.readInt();
        result.statementID = in.readLong();
        result.statementReturnType = in.readByte();
        result.rsProperties = in.readByte();
        result.metaData = new ResultMetaData(in);
        result.valueData = readSimple(in, result.metaData);
        break;

      case ResultConstants.EXECUTE:
        result.updateCount = in.readInt();
        result.fetchSize = in.readInt();
        result.statementID = in.readLong();
        result.rsProperties = in.readByte();
        result.queryTimeout = in.readShort();

        Statement statement = session.statementManager.getStatement(session, result.statementID);

        if (statement == null) {

          // invalid statement
          result.mode = ResultConstants.EXECUTE_INVALID;
          result.valueData = ValuePool.emptyObjectArray;

          break;
        }

        result.statement = statement;
        result.metaData = result.statement.getParametersMetaData();
        result.valueData = readSimple(in, result.metaData);
        break;

      case ResultConstants.UPDATE_RESULT:
        {
          result.id = in.readLong();

          int type = in.readInt();

          result.setActionType(type);

          result.metaData = new ResultMetaData(in);
          result.valueData = readSimple(in, result.metaData);

          break;
        }
      case ResultConstants.BATCHEXECRESPONSE:
      case ResultConstants.BATCHEXECUTE:
      case ResultConstants.BATCHEXECDIRECT:
      case ResultConstants.SETSESSIONATTR:
        {
          result.updateCount = in.readInt();
          result.fetchSize = in.readInt();
          result.statementID = in.readLong();
          result.queryTimeout = in.readShort();
          result.metaData = new ResultMetaData(in);

          result.navigator.readSimple(in, result.metaData);

          break;
        }
      case ResultConstants.PARAM_METADATA:
        {
          result.metaData = new ResultMetaData(in);

          result.navigator.read(in, result.metaData);

          break;
        }
      case ResultConstants.REQUESTDATA:
        {
          result.id = in.readLong();
          result.updateCount = in.readInt();
          result.fetchSize = in.readInt();

          break;
        }
      case ResultConstants.DATAHEAD:
      case ResultConstants.DATA:
      case ResultConstants.GENERATED:
        {
          result.id = in.readLong();
          result.updateCount = in.readInt();
          result.fetchSize = in.readInt();
          result.rsProperties = in.readByte();
          result.metaData = new ResultMetaData(in);
          result.navigator = new RowSetNavigatorClient();

          result.navigator.read(in, result.metaData);

          break;
        }
      case ResultConstants.DATAROWS:
        {
          result.metaData = new ResultMetaData(in);
          result.navigator = new RowSetNavigatorClient();

          result.navigator.read(in, result.metaData);

          break;
        }
      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "Result");
    }

    return result;
  }
  ResultMetaData(RowInputBinary in) throws IOException {

    type = in.readInt();
    columnCount = in.readInt();

    switch (type) {
      case UPDATE_RESULT_METADATA:
      case SIMPLE_RESULT_METADATA:
        {
          columnTypes = new Type[columnCount];

          for (int i = 0; i < columnCount; i++) {
            int type = in.readType();

            columnTypes[i] = Type.getDefaultType(type);
          }

          return;
        }
      case GENERATED_INDEX_METADATA:
        {
          colIndexes = new int[columnCount];

          for (int i = 0; i < columnCount; i++) {
            colIndexes[i] = in.readInt();
          }

          return;
        }
      case GENERATED_NAME_METADATA:
        {
          columnLabels = new String[columnCount];

          for (int i = 0; i < columnCount; i++) {
            columnLabels[i] = in.readString();
          }

          return;
        }
      case PARAM_METADATA:
        {
          columnTypes = new Type[columnCount];
          columnLabels = new String[columnCount];
          paramModes = new byte[columnCount];
          paramNullable = new byte[columnCount];

          for (int i = 0; i < columnCount; i++) {
            columnTypes[i] = readDataType(in);
            columnLabels[i] = in.readString();

            decodeParamColumnAttrs(in.readByte(), i);
          }

          return;
        }
      case RESULT_METADATA:
        {
          extendedColumnCount = in.readInt();
          columnTypes = new Type[extendedColumnCount];
          columnLabels = new String[columnCount];
          columns = new ColumnBase[columnCount];

          if (columnCount != extendedColumnCount) {
            colIndexes = new int[columnCount];
          }

          for (int i = 0; i < extendedColumnCount; i++) {
            Type type = readDataType(in);

            columnTypes[i] = type;
          }

          for (int i = 0; i < columnCount; i++) {
            columnLabels[i] = in.readString();

            String catalog = in.readString();
            String schema = in.readString();
            String table = in.readString();
            String name = in.readString();
            ColumnBase column = new ColumnBase(catalog, schema, table, name);

            column.setType(columnTypes[i]);
            decodeTableColumnAttrs(in.readByte(), column);

            columns[i] = column;
          }

          if (columnCount != extendedColumnCount) {
            for (int i = 0; i < columnCount; i++) {
              colIndexes[i] = in.readInt();
            }
          }

          return;
        }
      default:
        {
          throw Error.runtimeError(ErrorCode.U_S0500, "ResultMetaData");
        }
    }
  }