@Override
  public AbstractQueryResult getResult(Object queriesObj, boolean streaming, boolean binaryProtocol)
      throws QueryException {
    RawPacket rawPacket = null;
    AbstractResultPacket resultPacket;
    try {
      rawPacket = packetFetcher.getReusableRawPacket();
      resultPacket = ReadResultPacketFactory.createResultPacket(rawPacket.getByteBuffer());

      if (resultPacket.getResultType() == AbstractResultPacket.ResultType.LOCALINFILE) {
        // Server request the local file (LOCAL DATA LOCAL INFILE)
        // We do accept general URLs, too. If the localInfileStream is
        // set, use that.

        InputStream is;
        if (localInfileInputStream == null) {
          if (!getUrlParser().getOptions().allowLocalInfile) {

            writer.writeEmptyPacket(rawPacket.getPacketSeq() + 1);
            throw new QueryException(
                "Usage of LOCAL INFILE is disabled. To use it enable it via the connection property allowLocalInfile=true",
                -1,
                ExceptionMapper.SqlStates.FEATURE_NOT_SUPPORTED.getSqlState());
          }
          LocalInfilePacket localInfilePacket = (LocalInfilePacket) resultPacket;
          String localInfile = localInfilePacket.getFileName();

          try {
            URL url = new URL(localInfile);
            is = url.openStream();
          } catch (IOException ioe) {
            try {
              is = new FileInputStream(localInfile);
            } catch (FileNotFoundException f) {
              writer.writeEmptyPacket(rawPacket.getPacketSeq() + 1);
              ReadResultPacketFactory.createResultPacket(packetFetcher);
              throw new QueryException("Could not send file : " + f.getMessage(), -1, "22000", f);
            }
          }
        } else {
          is = localInfileInputStream;
          localInfileInputStream = null;
        }

        writer.sendFile(is, rawPacket.getPacketSeq() + 1);
        is.close();
        resultPacket = ReadResultPacketFactory.createResultPacket(packetFetcher);
      }
    } catch (SocketTimeoutException ste) {
      this.close();
      throw new QueryException(
          "Could not read resultset: " + ste.getMessage(),
          -1,
          ExceptionMapper.SqlStates.CONNECTION_EXCEPTION.getSqlState(),
          ste);
    } catch (IOException e) {
      try {
        if (writer != null && rawPacket != null) {
          writer.writeEmptyPacket(rawPacket.getPacketSeq() + 1);
          ReadResultPacketFactory.createResultPacket(packetFetcher);
        }
      } catch (IOException ee) {
      }
      throw new QueryException(
          "Could not read resultset: " + e.getMessage(),
          -1,
          ExceptionMapper.SqlStates.CONNECTION_EXCEPTION.getSqlState(),
          e);
    }

    switch (resultPacket.getResultType()) {
      case ERROR:
        this.moreResults = false;
        this.hasWarnings = false;
        ErrorPacket ep = (ErrorPacket) resultPacket;
        throw new QueryException(ep.getMessage(), ep.getErrorNumber(), ep.getSqlState());

      case OK:
        final OkPacket okpacket = (OkPacket) resultPacket;
        serverStatus = okpacket.getServerStatus();
        this.moreResults = ((serverStatus & ServerStatus.MORE_RESULTS_EXISTS) != 0);
        this.hasWarnings = (okpacket.getWarnings() > 0);
        final AbstractQueryResult updateResult =
            new UpdateResult(
                okpacket.getAffectedRows(),
                okpacket.getWarnings(),
                okpacket.getMessage(),
                okpacket.getInsertId());
        return updateResult;
      case RESULTSET:
        this.hasWarnings = false;
        ResultSetPacket resultSetPacket = (ResultSetPacket) resultPacket;
        try {
          return this.createQueryResult(resultSetPacket, streaming, binaryProtocol);
        } catch (IOException e) {

          throw new QueryException(
              "Could not read result set: " + e.getMessage(),
              -1,
              ExceptionMapper.SqlStates.CONNECTION_EXCEPTION.getSqlState(),
              e);
        }
      default:
        throw new QueryException(
            "Could not parse result",
            (short) -1,
            ExceptionMapper.SqlStates.INTERRUPTED_EXCEPTION.getSqlState());
    }
  }
  @Override
  public PrepareResult prepare(String sql) throws QueryException {
    try {
      if (urlParser.getOptions().cachePrepStmts && prepareStatementCache.containsKey(sql)) {
        PrepareResult pr = prepareStatementCache.get(sql);
        pr.addUse();
        return pr;
      }

      SendPrepareStatementPacket sendPrepareStatementPacket = new SendPrepareStatementPacket(sql);
      sendPrepareStatementPacket.send(writer);

      ByteBuffer byteBuffer = packetFetcher.getReusableBuffer();

      if (byteBuffer.get(0) == -1) {
        ErrorPacket ep = new ErrorPacket(byteBuffer);
        String message = ep.getMessage();
        throw new QueryException(
            "Error preparing query: " + message, ep.getErrorNumber(), ep.getSqlState());
      }

      byte bit = byteBuffer.get(0);
      if (bit == 0) {
        /* Prepared Statement OK */
        Reader reader = new Reader(byteBuffer);
        reader.readByte(); /* skip field count */
        final int statementId = reader.readInt();
        final int numColumns = reader.readShort();
        final int numParams = reader.readShort();
        reader.readByte(); // reserved
        this.hasWarnings = reader.readShort() > 0;
        ColumnInformation[] params = new ColumnInformation[numParams];
        if (numParams > 0) {
          for (int i = 0; i < numParams; i++) {
            params[i] = new ColumnInformation(packetFetcher.getRawPacket().getByteBuffer());
          }
          readEofPacket();
        }
        ColumnInformation[] columns = new ColumnInformation[numColumns];
        if (numColumns > 0) {
          for (int i = 0; i < numColumns; i++) {
            columns[i] = new ColumnInformation(packetFetcher.getRawPacket().getByteBuffer());
          }
          readEofPacket();
        }
        PrepareResult prepareResult = new PrepareResult(statementId, columns, params);
        if (urlParser.getOptions().cachePrepStmts
            && sql != null
            && sql.length() < urlParser.getOptions().prepStmtCacheSqlLimit) {
          prepareStatementCache.putIfNone(sql, prepareResult);
        }
        //                if (log.isDebugEnabled()) log.debug("prepare statementId : " +
        // prepareResult.statementId);
        return prepareResult;
      } else {
        throw new QueryException("Unexpected packet returned by server, first byte " + bit);
      }
    } catch (IOException e) {
      throw new QueryException(
          e.getMessage(), -1, ExceptionMapper.SqlStates.CONNECTION_EXCEPTION.getSqlState(), e);
    }
  }