Type readDataType(RowInputBinary in) throws IOException {

    int typeCode = in.readType();
    long size = in.readLong();
    int scale = in.readInt();

    return Type.getType(typeCode, 0, size, scale);
  }
  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;
  }