ステートメントのキャンセル

ステートメントのキャンセルに推奨される方法は、クエリが実行されているアプリケーションのインターフェイス(Snowflakeウェブインターフェイスのワークシートなど)またはSnowflake ODBC または JDBC ドライバーによって提供されるキャンセル API を使用することです。ただし、場合によっては、SQL を使用してクエリをキャンセルする必要があります。

Snowflakeは、実行中/アクティブなステートメントをキャンセルするための SQL の使用をサポートする次の機能を提供します。

次のJavaサンプルコードは、 SYSTEM$CANCEL_ALL_QUERIES および他のSnowflake関数を使用して、5秒後に現在のセッションで実行中のステートメントをキャンセルします。

  1. サンプルコードは、最初に CURRENT_SESSION に対して SQL コマンドを発行して、セッション識別子を取得します。

  2. 次に、5秒後に実行されるタスクを作成します。このタスクは、セッション識別子を SYSTEM$CANCEL_ALL_QUERIES へのパラメーターとして使用します。

  3. 次に、 GENERATOR テーブル関数を使用して実行時間の長いステートメントが実行され、120秒間の行が生成されます。

public void testCancelQuery() throws IOException, SQLException
{
  Statement         statement         = null;
  ResultSet         resultSet         = null;
  ResultSetMetaData resultSetMetaData = null;
  final Connection  connection        = getConnection(true);
  try
  {
    // Get the current session identifier
    Statement getSessionIdStmt = connection.createStatement();
    resultSet                  = getSessionIdStmt.executeQuery("SELECT current_session()");
    resultSetMetaData          = resultSet.getMetaData();
    assertTrue(resultSet.next());
    final int sessionId = resultSet.getInt(1);

    // Use Timer to cancel all queries of session in 5 seconds
    Timer timer = new Timer();
    timer.schedule( new TimerTask()
    {
      @Override
      public void run()
      {
        try
        {
          // Cancel all queries on session
          PreparedStatement cancelAll;
          cancelAll = connection.prepareStatement(
                                    "call system$cancel_all_queries(?)");

          // bind the session identifier as first argument
          cancelAll.setInt(1, sessionId);
          cancelAll.executeQuery();
        }
        catch (SQLException ex)
        {
          logger.log(Level.SEVERE, "Cancel failed with exception {}", ex);
        }
      }
    }, 5000);

    // Use the internal row generator to execute a query for 120 seconds
    statement = connection.createStatement();
    resultSet = statement.executeQuery(
                   "SELECT count(*) FROM TABLE(generator(timeLimit => 120))");
    resultSetMetaData = resultSet.getMetaData();
    statement.close();
  }
  catch (SQLException ex)
  {
    // assert the sqlstate is what we expect (QUERY CANCELLED)
    assertEquals("sqlstate mismatch",
                 SqlState.QUERY_CANCELED, ex.getSQLState());
  }
  catch (Throwable ex)
  {
    logger.log(Level.SEVERE, "Test failed with exception: ", ex);
  }
  finally
  {
    if (resultSet != null)
      resultSet.close();
    if (statement != null)
      statement.close();
    // close connection
    if (connection != null)
      connection.close();
  }
}