mcpField
R
redshift-api

redshift-api

github.com/anthropicsデータ・データベース7439 回インストール3 週間前に更新
リポジトリ

redshift-api について

Amazon Redshift Data API のクエリと管理操作を、ガイダンスとスクリプトで支援するスキルです。Data API を使うデータワークフロー向けに、非同期実行、状態確認、結果のページング取得をまとめ、カタログ参照やバッチ、キャンセルも扱います。

主な機能

  1. 01SQL の送信とステートメント状態の確認
  2. 02クエリ結果のページング取得とデコード
  3. 03ID による再開またはキャンセル
  4. 04トランザクション内で複数ステートメントを実行
  5. 05データベース、スキーマ、テーブル、列の参照

活用シーン

  1. 01クエリを実行しページング結果を取得
  2. 02待機タイムアウト後に ID で処理を再開
  3. 03テーブル構造の確認やトランザクションバッチの実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/anthropics/claude-tag-plugins --skill redshift-api

インストール後、Claude Code で/redshift-apiを入力して読み込まれたか確認します。

同梱ファイルreferences/api.mdscripts/rs_query.sh

詳細

Amazon Redshift Data API では、すべての呼び出しが https://redshift-data.<region>.amazonaws.com/ への POST であり、 Content-Type: application/x-amz-json-1.1 と X-Amz-Target: RedshiftData.<Action> を指定します。REST 形式のパスはありません。API は完全に非同期です。ステートメントを送信して Id を受け取り、完了するまで DescribeStatement をポーリングし、その後 GetStatementResult で結果をページ単位で取得します。 scripts/rs_query.sh(操作 1)がこの一連の処理を代わりに実行します。同じ呼び出しはプロビジョンドクラスターと Serverless の両方で使えます。異なるのは接続先フィールドだけです。

リクエストの設定

認証はランタイムが処理します。この API へのリクエストは、ワークスペースに設定された認証情報で署名されるため、設定作業は不要です。AWS キーを取得したり、自分でリクエストに署名したりしないでください。AccessDeniedException が継続して発生する場合、その認証情報はこのワークスペースに設定されていません。認証のデバッグではなく、その旨を報告してください。

実際に必要な設定は 2 つあります。

1. リージョン — エンドポイントのホスト名に含まれています。

export AWS_DEFAULT_REGION="us-east-1"        # the region your cluster / workgroup is in

2. 接続先 — Data API が接続するクラスター/ワークグループとデータベースです。いずれかを選び、対応する JSON フィールドを RS_TARGET に設定してください。以下の手順では、これを各リクエスト本文にマージします。

  • Serverless — WorkgroupName を渡します。設定された ID はデータベースユーザーにマッピングされます。最も簡単な方法です。
  • プロビジョンド、一時認証情報 — ClusterIdentifier と DbUser を渡します。Data API が内部でデータベースの認証情報を解決します。
  • プロビジョンドまたは Serverless、Secrets Manager — データベースのログイン情報を保持するシークレットを指す SecretArn を渡します。

該当する設定を一度だけ行います。

export RS_DATABASE="dev"
# Serverless:
export RS_TARGET='{"WorkgroupName": "my-workgroup"}'
# — or provisioned + temp creds:
# export RS_TARGET='{"ClusterIdentifier": "my-cluster", "DbUser": "my_user"}'
# — or either + Secrets Manager:
# export RS_TARGET='{"ClusterIdentifier": "my-cluster", "SecretArn": "arn:aws:secretsmanager:us-east-1:123456789012:secret:rs-creds-AbCdEf"}'

以下で使用するヘルパー。 1 つの関数で、エンドポイント、ヘッダー、アクション名をまとめて指定します。Authorization ヘッダーはプレースホルダーであり、ランタイムが実際の署名に置き換えます。

rsapi() {
  local action="$1"
  curl -sS "https://redshift-data.${AWS_DEFAULT_REGION}.amazonaws.com/" \
    -H "Content-Type: application/x-amz-json-1.1" \
    -H "X-Amz-Target: RedshiftData.${action}" \
    -H "Authorization: placeholder" \
    -d "${2:?rsapi needs a JSON body as the second argument}"
}

動作確認 — データベースを一覧表示します。Databases 配列を含む 200 が返れば、ワークスペースが正しく接続され、接続先も正しいことを確認できます。エラーには、失敗したレイヤーが示されます。

rsapi ListDatabases "$(jq -n --argjson t "$RS_TARGET" --arg db "$RS_DATABASE" \
  '$t + {Database: $db}')" | jq .

基本操作

データベースに接続するすべてのアクションで、同じ接続先のマージ済み本文、$t + {Database: $db, ...} を使用します。エラーは期待される形式ではなく、{"__type": "<Exception>", "message": "..."} として返されます。どの呼び出しでも、トップレベルのフィールド(Id、Status、Records など)が存在しない場合は、エラーの内容が返されています。表示して処理を停止してください。

1. クエリを実行する(scripts/rs_query.sh)

同梱のスクリプトを使って SQL を実行します(パスはこのスキルのディレクトリからの相対パスです)。ExecuteStatement で送信し、終端状態になるまで DescribeStatement をポーリングし、NextToken を使って GetStatementResult から結果をページ単位で取得して、型情報を含む 1 キーのセルオブジェクトをデコードします。

scripts/rs_query.sh \
  'SELECT event_name, COUNT(*) AS n FROM public.events
   WHERE event_date >= :start GROUP BY 1 ORDER BY 2 DESC LIMIT 20' \
  --param start=2024-01-01 --name top-events
  • SQL は 1 つの引数として指定するか、標準入力から渡します。インスタンス固有の設定には、上記の AWS_DEFAULT_REGION/RS_TARGET/RS_DATABASE を使用します。--database を指定するとデータベースを上書きできます。
  • --param NAME=VALUE(複数回指定可能)で :NAME プレースホルダーにバインドします。値は常に文字列であり、データベース側で型変換されます。--name を指定すると StatementName が設定され、クエリが ListStatements に表示されます。
  • --max-rows N は取得する行数の上限です(デフォルトは 10000、0 = すべて)。--json を指定すると、ヘッダー付き TSV の代わりに、1 行につき 1 つの JSON オブジェクトを出力します。ステートメント ID、ステータス、実行時間、行数は stderr に出力されます。
  • 終了コード:0 は成功、1 は送信失敗または SQL の FAILED/ABORTED(API 自体のメッセージを stderr に出力)、2 は --max-wait 秒(デフォルトは 600)の経過後に待機を中断した場合です。ステートメント ID は stderr に出力されます。操作 2 で再開してください。

スクリプトでエラーが発生した場合は、内容を確認してください。これは通常の curl と jq です。references/api.md を参照してデバッグしてください。 BatchExecuteStatement とサブステートメントの結果、セッションの再利用(SessionKeepAliveSeconds/SessionId)、ResultFormat: CSV、キャンセル、またはカタログの閲覧には、以下のアクションを使用してください。

2. IDでステートメントを再開する(DescribeStatement → GetStatementResult)

スクリプトが終了コード2(タイムアウト)で終了した場合や、別の場所でステートメント ID を取得した場合は、直接ポーリングして取得します。

rsapi DescribeStatement "$(jq -n --arg id "$ID" '{Id: $id}')" \
  | jq '{Status, Duration, ResultRows, HasResultSet, Error}'
rsapi GetStatementResult "$(jq -n --arg id "$ID" '{Id: $id}')" \
  | jq -r '.Records[]? | [.[] | if .isNull then null else to_entries[0].value end] | @tsv'
  • Status は SUBMITTED、PICKED、STARTED、FINISHED、FAILED、ABORTED のいずれかです。行を含むのは HasResultSet: true の FINISHED のみです。FAILED の場合、SQL エラーは .Error に格納されます。Duration の単位は ナノ秒 です。
  • 結果のセルは、1つのキーを持つ型付きオブジェクトです(「エラー処理」の注意点を参照)。列名と型は、最初のページの .ColumnMetadata にあります。続きのページは NextToken で取得します。ページサイズを指定するパラメーターはありません。DescribeStatement.ResultRows には、最初から合計行数が格納されています。
3. 実行中のステートメントをキャンセルする(CancelStatement)
rsapi CancelStatement "$(jq -n --arg id "$ID" '{Id: $id}')" | jq .
# {"Status": true} on success — best-effort, check DescribeStatement to confirm.
4. 1回の呼び出しで複数のステートメントを実行する(BatchExecuteStatement)

すべてのステートメントは1つのトランザクションで実行され、すべてコミットされるか、すべてロールバックされます。

rsapi BatchExecuteStatement "$(jq -n --argjson t "$RS_TARGET" --arg db "$RS_DATABASE" '$t + {
    Database: $db,
    Sqls: ["CREATE TEMP TABLE tmp AS SELECT 1 AS x", "SELECT * FROM tmp"]
  }')" | jq '{Id}'

親 Id に対する DescribeStatement は、SubStatements[] 配列を返します。各サブステートメントには独自の Id(親 ID に :1、:2、…を付加したもの)、Status、HasResultSet があります。各サブステートメントの結果は、それぞれの GetStatementResult 呼び出しで取得します。

5. 最近のステートメントを一覧表示する(ListStatements)
rsapi ListStatements '{"MaxResults": 20, "Status": "ALL"}' \
  | jq '.Statements[] | {Id, StatementName, Status, QueryString: (.QueryString[0:80]), CreatedAt}'

Status フィルター:SUBMITTED、PICKED、STARTED、FINISHED、FAILED、ABORTED、ALL。指定しない場合は、完了したステートメントのみが一覧表示されます。MaxResults は0~100です。RoleLevel のデフォルトは true です(同じ IAM ロールを引き受けているすべてのユーザーのステートメントを含みます)。false に設定すると、このセッションのステートメントのみが表示されます。

6. カタログを参照する(ListDatabases / ListSchemas / ListTables / DescribeTable)

4つのアクションすべてで、統合されたターゲット本文を指定します。パターンでは SQL の LIKE ワイルドカード(%、_)を使用します。

  • ListDatabases — Databases[](文字列)
  • ListSchemas — SchemaPattern(任意)— Schemas[](文字列)
  • ListTables — SchemaPattern、TablePattern — Tables[] {schema, name, type} — type は TABLE/VIEW/SYSTEM TABLE/GLOBAL TEMPORARY/LOCAL TEMPORARY/ALIAS/SYNONYM のいずれかです
  • DescribeTable — Schema、Table — ColumnList[] {name, typeName, nullable, length, precision}
rsapi ListTables "$(jq -n --argjson t "$RS_TARGET" --arg db "$RS_DATABASE" \
  '$t + {Database: $db, SchemaPattern: "public", TablePattern: "ev%"}')" | jq '.Tables'

JSON フィールド名は PascalCase です(workgroup-name ではなく WorkgroupName)。4つのアクションすべてでページネーションが行われます(NextToken)。各アクションの本文の形式については、references/api.md を参照してください。

ページネーション

GetStatementResult、ListStatements、ListDatabases、ListSchemas、ListTables、DescribeTable はすべて同じ方式を使用します。次のページがある場合、レスポンスに NextToken が含まれます。次のリクエスト本文で NextToken として渡してください。値がなくなったら終了です。

レート制限

  • アクティブなステートメント — クラスターまたはワークグループごとに、最大500件のアクティブなステートメント(SUBMITTED/STARTED)を実行できます。上限を超えると、送信は ActiveStatementsExceededException で失敗します。
  • 結果サイズ — ステートメントあたり500 MB(gzip 圧縮後)、1行あたり64 KBです。これを超える結果は失敗します。LIMIT を追加するか、UNLOAD ... TO 's3://...' を使用してください。
  • 結果の保持期間 — 24時間です。その後は GetStatementResult が ResourceNotFoundException を返します。
  • ステートメントの実行時間 — 最大24時間です。クエリ文字列 — 最大100 KBです。
  • API レート — アカウント/リージョンごとに固定され、調整できない TPS クォータがあります。DescribeStatement は100、ExecuteStatement は30、GetStatementResult は20、BatchExecuteStatement は20、CancelStatement、ListStatements、ListDatabases、ListSchemas、ListTables、DescribeTable はそれぞれ 3 TPS のみです。上限を超えると ThrottlingException(HTTP 400)が返されます。間隔を空けて再試行し、短時間に連続してポーリングしないでください。

エラー処理

エラーは {"__type": "<Exception>", "message": "..."} として返されます(HTTP 400/403/500)。__type フィールドが判別子です。

  • ValidationException (400) — パラメーターが不正です。よくある例:ClusterIdentifier と WorkgroupName を両方指定する、またはどちらも指定しない、Database が不足している、フィールドの大文字・小文字が正しくない。
  • ActiveStatementsExceededException (400) — 実行中のステートメントが多すぎます。ListStatements {"Status":"STARTED"} で実行中のものを確認できます。
  • ActiveSessionsExceededException (400) — 開いているセッションが500を超えています。SessionKeepAliveSeconds の指定をやめるか、アイドル状態のセッションが期限切れになるまで待ってください。
  • ExecuteStatementException (500) — DB がリクエストを受け取る前に送信に失敗しました。クラスター名またはワークグループ名が間違っている、クラスターに到達できない、DbUser が不正であるなどの原因が考えられます。RS_TARGET を確認してください。
  • ResourceNotFoundException (400) — ステートメント ID が不明、または24時間以上経過しています。
  • BatchExecuteStatementException (500) — バッチ内のステートメントが失敗し、トランザクション全体がロールバックされました。SubStatements[].Error を確認してください。
  • DatabaseConnectionException / QueryTimeoutException — カタログ呼び出しでデータベースに接続できなかったか、タイムアウトしました。接続先が稼働していることを確認し、再試行してください。
  • AccessDeniedException (403) — 認証情報にはクラスターまたはワークグループの ARN に対する redshift-data:* が必要です。さらに、接続モードに応じて redshift:GetClusterCredentials / redshift-serverless:GetCredentials / secretsmanager:GetSecretValue も必要です。不足している権限を報告してください。
  • InternalServerException (500) — ClientToken を渡さない限り、ExecuteStatement は冪等ではありません。書き込みを再試行する前に ListStatements を確認してください。
  • DescribeStatement の Status: FAILED — 送信後に SQL が失敗しました。.Error で SQL のエラーメッセージを確認してください。

注意点が2つあります。

  • ExecuteStatement が200を返しても、クエリの成功を意味しません。 SQL エラーは後から DescribeStatement の Status: FAILED として現れます。結果を取得する前に必ずポーリングしてください。
  • セルの値は型情報を持つ1キーのオブジェクトであり、単なる値ではありません。 longValue は JSON の数値で、 isNull: true は別の形式です。単純な .value の読み取りでは何も返されず、型付きキーに対して jq の // を連結すると false / 0 で問題が起きます。to_entries[0].value を使用してください。

さらに詳しく

references/api.md には完全なカタログがあり、各アクションのリクエスト/レスポンス形式(生の HTTP 向けの PascalCase)、 SqlParameter のバインド形式、ColumnMetadata のフィールド、バッチ用の SubStatementData、セッションの再利用(SessionKeepAliveSeconds / SessionId)、クォータ表を確認できます。上記で扱っていないアクションや、生の HTTP リクエスト本文の正確な形式を確認する必要がある場合は、こちらをお読みください。

コメント