

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon RDS のAWS AppSync JavaScript リゾルバー関数リファレンス
<a name="resolver-reference-rds-js"></a>

 AWS AppSync RDS 関数とリゾルバーを使用すると、デベロッパーは RDS Data API を使用して Amazon Aurora クラスターデータベースにSQLクエリを送信し、これらのクエリの結果を取得できます。 AWS AppSyncの`rds`モジュール`sql`タグ付きテンプレートを使用するか、`rds`モジュールの `select`、`insert`、、および `remove`ヘルパー関数を使用して`update`、Data API に送信されるSQLステートメントを記述できます。 は、RDS Data Service の [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html)アクション AWS AppSync を利用して、データベースに対して SQL ステートメントを実行します。

**トピック**
+ [SQL タグ付きテンプレート](#sql-tagged-templates)
+ [ステートメントの作成](#creating-statements)
+ [データの取得](#retrieving-data)
+ [ユーティリティ関数](#utility-functions)
+ [SQL SELECT](#utility-functions-select)
+ [SQL INSERT](#utility-functions-insert)
+ [SQL UPDATE](#utility-functions-update)
+ [SQL DELETE](#utility-functions-delete)
+ [キャスティング](#casting)

## SQL タグ付きテンプレート
<a name="sql-tagged-templates"></a>

AWS AppSyncの`sql`タグ付けされたテンプレートを使用すると、テンプレート式を使用して実行時に動的値を受信できる静的ステートメントを作成できます。 は式値から変数マップ AWS AppSync を構築して、Amazon Aurora Serverless Data API に送信される[https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html)クエリを構築します。この方法では、実行時に渡される動的な値によって元のステートメントを変更することができないため、意図しない実行が発生する可能性があります。動的な値はすべてパラメータとして渡され、元のステートメントを変更することはできず、データベースによって実行されることもありません。これにより、クエリが SQL インジェクション攻撃を受けにくくなります。

**注記**  
いずれの場合も、SQL ステートメントを作成するときは、セキュリティガイドラインに従って、入力として受け取ったデータを適切に処理する必要があります。

**注記**  
`sql` タグ付きテンプレートは変数値の受け渡しのみをサポートします。式を使用して列名やテーブル名を動的に指定することはできません。ただし、ユーティリティ関数を使用して動的ステートメントを作成することはできます。

次の例では、実行時に GraphQL クエリで動的に設定される `col` 引数の値に基づいてフィルタリングするクエリを作成します。この値は、タグ式を使用してのみステートメントに追加できます。

```
import { sql, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
  const query = sql`
SELECT * FROM table 
WHERE column = ${ctx.args.col}`
  ;
  return createMySQLStatement(query);
}
```

すべての動的な値を変数マップに渡すことで、データベースエンジンに依存して値を安全に処理し、サニタイズします。

## ステートメントの作成
<a name="creating-statements"></a>

関数とリゾルバーは、MySQL データベースと PostgreSQL データベースとやり取りできます。`createMySQLStatement` と `createPgStatement` をそれぞれ使用してステートメントを作成します。例えば、`createMySQLStatement` は MySQL クエリを作成できます。これらの関数は最大 2 つのステートメントを受け付けるので、リクエストですぐに結果を取得する必要がある場合に便利です。MySQL では、以下のことが可能です。

```
import { sql, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { id, text } = ctx.args;
    const s1 = sql`insert into Post(id, text) values(${id}, ${text})`;
    const s2 = sql`select * from Post where id = ${id}`;
    return createMySQLStatement(s1, s2);
}
```

**注記**  
`createPgStatement` および `createMySQLStatement` は、`sql` タグ付きテンプレートで作成されたステートメントをエスケープしたり、引用したりすることはありません。

## データの取得
<a name="retrieving-data"></a>

実行された SQL ステートメントの結果は、`context.result` オブジェクトのレスポンスハンドラで参照できます。結果は、`ExecuteStatement` アクションからの[レスポンス要素](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html#API_ExecuteStatement_ResponseElements)を含む JSON 文字列です。解析された結果は次のとおりです。

```
type SQLStatementResults = {
    sqlStatementResults: {
        records: any[];
        columnMetadata: any[];
        numberOfRecordsUpdated: number;
        generatedFields?: any[]
    }[]
}
```

`toJsonObject` ユーティリティを使用して、返された行を表す JSON オブジェクトのリストに結果を変換できます。例えば、次のようになります。

```
import { toJsonObject } from '@aws-appsync/utils/rds';

export function response(ctx) {
    const { error, result } = ctx;
    if (error) {
        return util.appendError(
            error.message,
            error.type,
            result
        )
    }
    return toJsonObject(result)[1][0]
}
```

`toJsonObject` はステートメントの結果の配列を返すことに注意してください。1 つのステートメントを指定した場合、配列の長さは `1` です。2 つのステートメントを指定した場合、配列の長さは `2` です。配列内の各結果には、`0` 以上の行が含まれます。結果の値が無効な場合や予期しないものである場合、`toJsonObject` は `null` を返します。

## ユーティリティ関数
<a name="utility-functions"></a>

 AWS AppSync RDS モジュールのユーティリティヘルパーを使用して、データベースとやり取りできます。

### SQL SELECT
<a name="utility-functions-select"></a>

`select` ユーティリティは、リレーショナルデータベースにクエリを実行する `SELECT` ステートメントを作成します。

**基本的な使用法**

基本的な形式では、クエリを実行するテーブルを指定できます。

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement: 
    // "SELECT * FROM "persons"
    return createPgStatement(select({table: 'persons'}));
}
```

なお、テーブル識別子でスキーマを指定することもできます。

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement:
    // SELECT * FROM "private"."persons"
    return createPgStatement(select({table: 'private.persons'}));
}
```

**列の指定**

`columns` プロパティで列を指定できます。これを値に設定しない場合、デフォルトでは `*` になります。

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name']
    }));
}
```

また、列のテーブルも指定できます。

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "persons"."name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'persons.name']
    }));
}
```

**LIMIT と OFFSET**

`limit` と `offset` をクエリに適用できます。

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name"
    // FROM "persons"
    // LIMIT :limit
    // OFFSET :offset
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        limit: 10,
        offset: 40
    }));
}
```

**ORDER BY**

結果は `orderBy` プロパティを使用してソートできます。列とオプションの `dir` プロパティを指定するオブジェクトの配列を指定します。

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name" FROM "persons"
    // ORDER BY "name", "id" DESC
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        orderBy: [{column: 'name'}, {column: 'id', dir: 'DESC'}]
    }));
}
```

**フィルター**

特殊条件オブジェクトを使用してフィルターを構築できます。

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}}
    }));
}
```

以下のフィルターを組み合わせることもできます。

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME and "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}, id: {gt: 10}}
    }));
}
```

また、`OR` ステートメントも作成できます。

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME OR "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { or: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

`not` を使用して条件を無効にすることもできます。

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE NOT ("name" = :NAME AND "id" > :ID)
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { not: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

以下の演算子を使用して、値を比較することもできます。


| 
| 
| 演算子 | 説明 | 可能な値型 | 
| --- |--- |--- |
| eq | Equal | number, string, boolean | 
| ne | Not equal | number, string, boolean | 
| le | Less than or equal | number, string | 
| lt | Less than | number, string | 
| ge | Greater than or equal | number, string | 
| gt | Greater than | number, string | 
| contains | Like | string | 
| notContains | Not like | string | 
| beginsWith | Starts with prefix | string | 
| between | Between two values | number, string | 
| attributeExists | The attribute is not null | number, string, boolean | 
| size | checks the length of the element | string | 

### SQL INSERT
<a name="utility-functions-insert"></a>

`insert` ユーティリティによって、`INSERT` オペレーションを使用してデータベースに単一行の項目を簡単に挿入できます。

**単一項目の挿入**

項目を挿入するには、テーブルを指定して、値のオブジェクトを渡します。オブジェクトキーはテーブルの列にマッピングされます。列名は自動的にエスケープされ、値は変数マップを使用してデータベースに送信されます。

```
import { insert, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({ table: 'persons', values });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    return createMySQLStatement(insertStatement)
}
```

**MySQL ユースケース**

`insert` の後に `select` を組み合わせて、挿入した行を取得できます。

```
import { insert, select, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({  table: 'persons', values });
    const selectStatement = select({
        table: 'persons',
        columns: '*',
        where: { id: { eq: values.id } },
        limit: 1,
    });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    // and
    // SELECT *
    // FROM `persons`
    // WHERE `id` = :ID
    return createMySQLStatement(insertStatement, selectStatement)
}
```

**Postgres のユースケース**

Postgres では、[https://www.postgresql.org/docs/current/dml-returning.html](https://www.postgresql.org/docs/current/dml-returning.html) を使用して、挿入した行からデータを取得できます。`*` または列名の配列が受け入れられます。

```
import { insert, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({
        table: 'persons',
        values,
        returning: '*'
    });

    // Generates statement:
    // INSERT INTO "persons"("name")
    // VALUES(:NAME)
    // RETURNING *
    return createPgStatement(insertStatement)
}
```

### SQL UPDATE
<a name="utility-functions-update"></a>

`update` ユーティリティでは、既存の行を更新できます。条件オブジェクトを使用すると、条件を満たすすべての行の指定された列に変更を適用できます。例えば、このミューテーションを可能にするスキーマがあるとします。`Person` の `name` を `3` の `id` 値で更新したいのですが、これは `2000` 年以降にそれら (`known_since`) がわかっている場合に限ります。

```
mutation Update {
    updatePerson(
        input: {id: 3, name: "Jon"},
        condition: {known_since: {ge: "2000"}}
    ) {
    id
    name
  }
}
```

更新リゾルバーは以下のようになります。

```
import { update, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id, ...values }, condition } = ctx.args;
    const where = {
        ...condition,
        id: { eq: id },
    };
    const updateStatement = update({
        table: 'persons',
        values,
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // UPDATE "persons"
    // SET "name" = :NAME, "birthday" = :BDAY, "country" = :COUNTRY
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

条件にチェックを追加して、`3` と等しいプライマリキー `id` を持つ行だけが更新されるようにすることができます。同様に、Postgres `inserts` の場合も、`returning` を使用して変更されたデータを返すことができます。

### SQL DELETE
<a name="utility-functions-delete"></a>

`remove` ユーティリティでは、既存の行を削除できます。条件オブジェクトは、条件を満たすすべての行で使用できます。なお、`delete` はJavaScriptの予約キーワードです。代わりに `remove` を使ってください。

```
import { remove, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id }, condition } = ctx.args;
    const where = { ...condition, id: { eq: id } };
    const deleteStatement = remove({
        table: 'persons',
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // DELETE "persons"
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

## キャスティング
<a name="casting"></a>

ステートメントで使用する正しいオブジェクト型に関して、さらに特異度が必要となる場合もあるでしょう。指定された型ヒントを使用してパラメータのタイプを指定できます。 は Data API [と同じ型ヒント](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html#rdsdtataservice-Type-SqlParameter-typeHint) AWS AppSync をサポートします。モジュールの `typeHint`関数を使用してパラメータを AWS AppSync `rds`キャストできます。

次の例では、JSON オブジェクトとしてキャストされた値として配列を送信できます。`->` 演算子を使用して JSON 配列内にある `index` `2` の要素を取得します。

```
import { sql, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const arr = ctx.args.list_of_ids
    const statement = sql`select ${typeHint.JSON(arr)}->2 as value`
    return createPgStatement(statement)
}

export function response(ctx) {
    return toJsonObject(ctx.result)[0][0].value
}
```

キャスティングは、`DATE`、`TIME`、`TIMESTAMP` の処理や比較を行うときにも役立ちます。

```
import { select, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const when = ctx.args.when
    const statement = select({
        table: 'persons',
        where: { createdAt : { gt: typeHint.DATETIME(when) } }
    })
    return createPgStatement(statement)
}
```

現在の日付と時刻を送信する方法について別の例を以下に示します。

```
import { sql, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const now = util.time.nowFormatted('YYYY-MM-dd HH:mm:ss')
    return createPgStatement(sql`select ${typeHint.TIMESTAMP(now)}`)
}
```

**使用可能な型ヒント**
+ `typeHint.DATE` - 対応するパラメータが、`DATE` 型のオブジェクトとしてデータベースに送信されます。受け入れられる形式は `YYYY-MM-DD` です。
+ `typeHint.DECIMAL` - 対応するパラメータが、`DECIMAL` 型のオブジェクトとしてデータベースに送信されます。
+ `typeHint.JSON` - 対応するパラメータが、`JSON` 型のオブジェクトとしてデータベースに送信されます。
+ `typeHint.TIME` - 対応する文字列パラメータ値が、`TIME` 型のオブジェクトとしてデータベースに送信されます。受け入れられる形式は `HH:MM:SS[.FFF]` です。
+ `typeHint.TIMESTAMP` - 対応する文字列パラメータ値が、`TIMESTAMP` 型のオブジェクトとしてデータベースに送信されます。受け入れられる形式は `YYYY-MM-DD HH:MM:SS[.FFF]` です。
+ `typeHint.UUID` - 対応する文字列パラメータ値が、`UUID` 型のオブジェクトとしてデータベースに送信されます。