

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# AWS AppSync JavaScript referência da função de resolução para Amazon RDS
<a name="resolver-reference-rds-js"></a>

A função e o resolvedor do AWS AppSync RDS permitem que os desenvolvedores enviem SQL consultas para um banco de dados de cluster do Amazon Aurora usando a API de dados do RDS e recuperem o resultado dessas consultas. Você pode escrever SQL instruções que são enviadas para a API de dados usando AWS AppSync o modelo `sql` com tag de `rds` módulo ou usando as funções `remove` auxiliares`select`, `insert``update`, e do `rds` módulo. AWS AppSync utiliza a [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html)ação do RDS Data Service para executar instruções SQL no banco de dados. 

**Tópicos**
+ [Modelo marcado com SQL](#sql-tagged-templates)
+ [Criar declarações](#creating-statements)
+ [Recuperação de dados](#retrieving-data)
+ [Funções do utilitário](#utility-functions)
+ [SQL Select](#utility-functions-select)
+ [SQL Insert](#utility-functions-insert)
+ [SQL Update](#utility-functions-update)
+ [SQL Delete](#utility-functions-delete)
+ [Conversão](#casting)

## Modelo marcado com SQL
<a name="sql-tagged-templates"></a>

AWS AppSync O modelo `sql` marcado permite que você crie uma declaração estática que pode receber valores dinâmicos em tempo de execução usando expressões de modelo. AWS AppSync cria um mapa variável a partir dos valores da expressão para criar uma [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html)consulta que é enviada para a API de dados sem servidor do Amazon Aurora. Com esse método, não é possível que valores dinâmicos transmitidos em runtime modifiquem a declaração original, o que pode causar uma execução não intencional. Todos os valores dinâmicos são transmitidos como parâmetros, não podem modificar a declaração original e não são executados pelo banco de dados. Isso torna a consulta menos vulnerável a ataques de injeção de SQL.

**nota**  
Em todos os casos, ao redigir declarações SQL, é necessário seguir as diretrizes de segurança para lidar adequadamente com os dados recebidos como entrada.

**nota**  
O modelo marcado com `sql` só aceita a transmissão de valores de variáveis. Não é possível usar uma expressão para especificar dinamicamente nomes de colunas ou de tabelas. No entanto, é possível usar funções de utilitário para criar declarações dinâmicas.

No exemplo a seguir, criamos uma consulta que filtra com base no valor do argumento `col` definido dinamicamente na consulta do GraphQL em runtime. O valor só pode ser adicionado à declaração usando a expressão de tag:

```
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);
}
```

Ao transmitir todos os valores dinâmicos pelo mapa de variáveis, contamos com o mecanismo de banco de dados para processar e higienizar os valores com segurança.

## Criar declarações
<a name="creating-statements"></a>

Funções e resolvedores podem interagir com bancos de dados MySQL e PostgreSQL. Use `createMySQLStatement` e `createPgStatement`, respectivamente, para criar declarações. Por exemplo, `createMySQLStatement` pode criar uma consulta MySQL. Essas funções aceitam até duas declarações, o que é útil quando uma solicitação deve recuperar os resultados imediatamente. Com MySQL, é possível fazer o seguinte:

```
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);
}
```

**nota**  
`createPgStatement` e `createMySQLStatement` não inserem caracteres de escape nem citam declarações criadas com o modelo marcado com `sql`.

## Recuperação de dados
<a name="retrieving-data"></a>

O resultado da declaração SQL executada está disponível no manipulador de respostas, no objeto `context.result`. O resultado é uma string JSON com os [elementos de resposta](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html#API_ExecuteStatement_ResponseElements) da ação `ExecuteStatement`. Quando analisado, o resultado tem o seguinte formato:

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

É possível usar o utilitário `toJsonObject` para transformar o resultado em uma lista de objetos JSON representando as linhas exibidas. Por exemplo:

```
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]
}
```

Observe que o `toJsonObject` exibe uma matriz de resultados das declarações. Se você forneceu uma declaração, o tamanho da matriz será `1`. Se você forneceu duas declarações, o tamanho da matriz será `2`. Cada resultado na matriz contém `0` ou mais linhas. `toJsonObject` exibirá `null` se o valor do resultado for inválido ou inesperado.

## Funções do utilitário
<a name="utility-functions"></a>

Você pode usar os auxiliares utilitários do módulo AWS AppSync RDS para interagir com seu banco de dados.

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

O utilitário `select` cria uma declaração `SELECT` para consultar o banco de dados relacional. 

**Uso básico**

Na forma básica, é possível especificar a tabela que deseja consultar:

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

export function request(ctx) {

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

Observe também que é possível especificar o esquema no identificador da tabela:

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

export function request(ctx) {

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

**Especificar colunas**

É possível especificar colunas com a propriedade `columns`. Se isso não for definido como um valor, o padrão será `*`:

```
export function request(ctx) {

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

Também é possível especificar a tabela de uma coluna:

```
export function request(ctx) {

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

**Limites e deslocamentos**:

É possível aplicar `limit` e `offset` à consulta:

```
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
    }));
}
```

**Ordenar por**

É possível classificar os resultados com a propriedade `orderBy`. Forneça uma matriz de objetos especificando a coluna e uma propriedade `dir` opcional:

```
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'}]
    }));
}
```

**Filtros**

É possível criar filtros usando o objeto de condição especial:

```
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'}}
    }));
}
```

Também é possível combinar filtros:

```
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}}
    }));
}
```

Também é possível criar declarações `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 } }
        ]}
    }));
}
```

Também é possível negar uma condição com `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 } }
        ]}
    }));
}
```

Também é possível usar os seguintes operadores para comparar valores:


| 
| 
| Operador | Description | Tipos de valores possíveis | 
| --- |--- |--- |
| eq | Equal | número, string, booleano | 
| ne | Not equal | número, string, booleano | 
| le | Menor ou igual a | número, string | 
| lt | Menor que | número, string | 
| idade | Maior ou igual a | número, string | 
| gt | Maior que | número, string | 
| contém | Like | string | 
| NÃO contém | Não é como | string | 
| Começa com | Começa com o prefixo | string | 
| entre | Entre dois valores | número, string | 
| O atributo existe | O atributo não é nulo | número, string, booleano | 
| size | verifica o comprimento do elemento | string | 

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

O utilitário `insert` oferece uma maneira simples de inserir itens de linha única no banco de dados com a operação `INSERT`.

**Inserções de item único**

Para inserir um item, especifique a tabela e, depois, transmita o objeto de valores. As chaves do objeto são associadas às colunas da tabela. São inseridos automaticamente caracteres de escape nos nomes das colunas e os valores são enviados ao banco de dados usando o mapa de variáveis:

```
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)
}
```

**Caso de uso do MySQL**

É possível combinar um `insert` seguido por um `select` para recuperar a linha inserida:

```
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)
}
```

**Caso de uso do Postgres**

Com o Postgres, é possível usar [https://www.postgresql.org/docs/current/dml-returning.html](https://www.postgresql.org/docs/current/dml-returning.html) para obter dados da linha que você inseriu. Ele aceita `*` ou uma matriz de nomes de colunas:

```
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>

O utilitário `update` permite atualizar as linhas existentes. É possível usar o objeto de condição para aplicar alterações às colunas especificadas em todas as linhas que atendam à condição. Por exemplo, digamos que temos um esquema que nos permita fazer essa mutação. Queremos atualizar o `name` de `Person` com o valor `id` de `3`, mas somente se os conhecermos (`known_since`) desde o ano `2000`:

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

Nosso resolvedor de atualização é semelhante a:

```
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)
}
```

Podemos adicionar uma verificação à nossa condição para garantir que somente a linha que tem a chave primária `id` igual a `3` seja atualizada. Da mesma forma, para Postgres `inserts`, é possível usar `returning` para exibir os dados modificados. 

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

O utilitário `remove` permite excluir as linhas existentes. É possível usar o objeto de condição em todas as linhas que atendam à condição. Observe que `delete` é uma palavra-chave reservada em JavaScript. `remove`deve ser usado em vez disso:

```
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)
}
```

## Conversão
<a name="casting"></a>

Em alguns casos, convém ter maior especificidade sobre o tipo de objeto correto a ser usado na declaração. Você pode usar as dicas de tipo fornecidas para especificar o tipo dos seus parâmetros. AWS AppSync suporta os [mesmos tipos de dicas](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html#rdsdtataservice-Type-SqlParameter-typeHint) da API de dados. Você pode converter seus parâmetros usando as `typeHint` funções do AWS AppSync `rds` módulo. 

O exemplo a seguir permite enviar uma matriz como um valor que é convertido como um objeto JSON. Usamos o operador `->` para recuperar o elemento `index` `2` na matriz JSON:

```
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
}
```

A conversão também é útil ao processar e comparar `DATE`, `TIME` e `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)
}
```

Veja outro exemplo de como enviar a data e a hora atuais:

```
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)}`)
}
```

**Dicas de tipo disponíveis**
+ `typeHint.DATE`: o parâmetro correspondente é enviado como objeto do tipo `DATE` ao banco de dados. O formato aceito é `YYYY-MM-DD`.
+ `typeHint.DECIMAL`: o parâmetro correspondente é enviado como objeto do tipo `DECIMAL` ao banco de dados.
+ `typeHint.JSON`: o parâmetro correspondente é enviado como objeto do tipo `JSON` ao banco de dados.
+ `typeHint.TIME`: o valor de parâmetro de string correspondente é enviado como objeto do tipo `TIME` ao banco de dados. O formato aceito é `HH:MM:SS[.FFF]`. 
+ `typeHint.TIMESTAMP`: o valor de parâmetro de string correspondente é enviado como objeto do tipo `TIMESTAMP` ao banco de dados. O formato aceito é `YYYY-MM-DD HH:MM:SS[.FFF]`.
+ `typeHint.UUID`: o valor de parâmetro de string correspondente é enviado como objeto do tipo `UUID` ao banco de dados.