/**
   * Kick-offer
   *
   * @param sql sql string
   * @return an intance
   * @throws SQLException
   */
  private Instance runClientSQL(String sql) throws SQLException {
    Instance instance;
    try {
      Map<String, String> hints = new HashMap<String, String>();
      Map<String, String> aliases = new HashMap<String, String>();

      // If the client forget to end with a semi-colon, append it.
      if (!sql.contains(";")) {
        sql += ";";
      }

      Odps odps = connHanlde.getOdps();
      instance = SQLTask.run(odps, odps.getDefaultProject(), sql, "SQL", hints, aliases);
      LogView logView = new LogView(odps);
      if (connHanlde.getLogviewHost() != null) {
        logView.setLogViewHost(connHanlde.getLogviewHost());
      }

      String logViewUrl = logView.generateLogView(instance, 7 * 24);
      connHanlde.log.fine("Run SQL: " + sql);
      connHanlde.log.info(logViewUrl);
      warningChain = new SQLWarning(logViewUrl);
    } catch (OdpsException e) {
      connHanlde.log.severe("fail to run sql: " + sql);
      throw new SQLException(e);
    }
    return instance;
  }
 /**
  * Blocked SQL runner, do not print any log information
  *
  * @param sql sql string
  * @throws SQLException
  */
 private void runSilentSQL(String sql) throws SQLException {
   try {
     long begin = System.currentTimeMillis();
     Odps odps = connHanlde.getOdps();
     SQLTask.run(odps, sql).waitForSuccess();
     long end = System.currentTimeMillis();
     connHanlde.log.fine("It took me " + (end - begin) + " ms to run SQL: " + sql);
   } catch (OdpsException e) {
     throw new SQLException(e);
   }
 }
  @Override
  public ResultSet executeQuery(String sql) throws SQLException {
    checkClosed();
    beforeExecute();

    long begin = System.currentTimeMillis();

    // Create a temp table for querying ResultSet and ensure its creation.
    // If the table can not be created (CANCELLED/FAIL), an exception will be caused.
    // Once the table has been created, it will last until the Statement is closed,
    // or another query is started.
    String tempTempTable = "jdbc_temp_tbl_" + UUID.randomUUID().toString().replaceAll("-", "_");

    try {
      executeInstance =
          runClientSQL(
              "create table "
                  + tempTempTable
                  + " lifecycle "
                  + connHanlde.lifecycle
                  + " as "
                  + sql);

      boolean complete = false;
      while (!complete) {
        try {
          Thread.sleep(POOLING_INTERVAL);
        } catch (InterruptedException e) {
          break;
        }

        Instance.TaskStatus.Status status;
        try {
          status = executeInstance.getTaskStatus().get("SQL").getStatus();
        } catch (NullPointerException e) {
          continue;
        }
        switch (status) {
          case SUCCESS:
            complete = true;
            break;
          case FAILED:
            String reason = executeInstance.getTaskResults().get("SQL");
            connHanlde.log.fine("create temp table failed: " + reason);
            throw new SQLException("create temp table failed: " + reason, "FAILED");
          case CANCELLED:
            connHanlde.log.info("create temp table cancelled");
            throw new SQLException("create temp table cancelled", "CANCELLED");
          case WAITING:
          case RUNNING:
          case SUSPENDED:
            break;
        }
      }
    } catch (OdpsException e) {
      connHanlde.log.fine("create temp table failed: " + e.getMessage());
      throw new SQLException(e);
    }

    // If we arrive here, the temp table must be effective
    tempTable = tempTempTable;
    long end = System.currentTimeMillis();
    connHanlde.log.fine("It took me " + (end - begin) + " ms to create " + tempTable);

    // Read schema
    begin = System.currentTimeMillis();
    List<String> columnNames = new ArrayList<String>();
    List<OdpsType> columnSqlTypes = new ArrayList<OdpsType>();
    try {
      Table table = connHanlde.getOdps().tables().get(tempTable);
      table.reload();
      for (Column col : table.getSchema().getColumns()) {
        columnNames.add(col.getName());
        columnSqlTypes.add(col.getType());
      }
    } catch (OdpsException e) {
      throw new SQLException(e);
    }
    OdpsResultSetMetaData meta = new OdpsResultSetMetaData(columnNames, columnSqlTypes);
    end = System.currentTimeMillis();
    connHanlde.log.fine("It took me " + (end - begin) + " ms to read the table schema");

    // Create a download session through tunnel
    DownloadSession session;
    try {
      TableTunnel tunnel = new TableTunnel(connHanlde.getOdps());
      String project_name = connHanlde.getOdps().getDefaultProject();
      session = tunnel.createDownloadSession(project_name, tempTable);
      connHanlde.log.info("create download session id=" + session.getId());
    } catch (TunnelException e) {
      throw new SQLException(e);
    }

    resultSet =
        isResultSetScrollable
            ? new OdpsScollResultSet(this, meta, session)
            : new OdpsForwardResultSet(this, meta, session);

    return resultSet;
  }