

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# AWS AppSync JavaScript referencia de la función de resolución para Amazon RDS
<a name="resolver-reference-rds-js"></a>

La función y el solucionador de AWS AppSync RDS permiten a los desarrolladores enviar SQL consultas a una base de datos de clústeres de Amazon Aurora mediante la API de datos de RDS y obtener el resultado de estas consultas. Puede escribir SQL declaraciones que se envíen a la API de datos mediante la plantilla `sql` etiquetada como `rds` módulo AWS AppSync del módulo o mediante las funciones`select`, `insert``update`, y `remove` auxiliar del `rds` módulo. AWS AppSync utiliza la [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html)acción del servicio de datos de RDS para ejecutar sentencias SQL en la base de datos. 

**Temas**
+ [Plantilla con etiquetas SQL](#sql-tagged-templates)
+ [Creación de instrucciones](#creating-statements)
+ [Recuperación de datos](#retrieving-data)
+ [Funciones de utilidad](#utility-functions)
+ [Selección de SQL](#utility-functions-select)
+ [Inserción de SQL](#utility-functions-insert)
+ [Actualización de SQL](#utility-functions-update)
+ [Eliminación de SQL](#utility-functions-delete)
+ [Conversión](#casting)

## Plantilla con etiquetas SQL
<a name="sql-tagged-templates"></a>

AWS AppSync La plantilla `sql` etiquetada permite crear una sentencia estática que puede recibir valores dinámicos en tiempo de ejecución mediante el uso de expresiones de plantilla. AWS AppSync crea un mapa de variables a partir de los valores de la expresión para crear una [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html)consulta que se envía a la API de datos sin servidor de Amazon Aurora. Con este método, no es posible que los valores dinámicos pasados en tiempo de ejecución modifiquen la instrucción original, lo que podría provocar una ejecución no intencionada. Todos los valores dinámicos se pasan como parámetros, no pueden modificar la instrucción original y la base de datos no los ejecuta. Esto hace que la consulta sea menos vulnerable a los ataques de inyección de SQL.

**nota**  
En todos los casos, al escribir instrucciones SQL, debe seguir las pautas de seguridad para gestionar correctamente los datos que reciba como entrada.

**nota**  
La plantilla con etiquetas `sql` solo admite la transferencia de valores variables. No puede usar una expresión para especificar dinámicamente los nombres de las columnas o tablas. No obstante, puede usar funciones de utilidad para crear instrucciones dinámicas.

En el siguiente ejemplo, creamos una consulta que filtra en función del valor del argumento `col` que se establece dinámicamente en la consulta GraphQL en tiempo de ejecución. El valor solo se puede añadir a la instrucción mediante la expresión de etiquetas:

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

Al pasar todos los valores dinámicos por el mapa de variables, confiamos en el motor de la base de datos para gestionar y sanear los valores de forma segura.

## Creación de instrucciones
<a name="creating-statements"></a>

Las funciones y los solucionadores pueden interactuar con las bases de datos MySQL y PostgreSQL. Utilice `createMySQLStatement` y `createPgStatement`, respectivamente, para crear instrucciones. Por ejemplo, `createMySQLStatement` puede crear una consulta MySQL. Estas funciones aceptan hasta dos instrucciones, lo que resulta útil cuando una solicitud debe recuperar los resultados de forma inmediata. Con SQL, podría hacer:

```
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` y `createMySQLStatement` no escapa ni cita las instrucciones creadas con la plantilla etiquetada con `sql`.

## Recuperación de datos
<a name="retrieving-data"></a>

El resultado de la instrucción SQL ejecutada está disponible en el controlador de respuestas del objeto `context.result`. El resultado es una cadena JSON con los [elementos de respuesta](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html#API_ExecuteStatement_ResponseElements) de la acción `ExecuteStatement`. Por ejemplo, puede utilizar la siguiente forma:

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

Puede utilizar la utilidad `toJsonObject` para transformar el resultado en una lista de objetos JSON que representen las filas devueltas. Por ejemplo:

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

Tenga en cuenta que `toJsonObject` devuelve una matriz de resultados de la instrucción. Si proporcionó una instrucción, la longitud de la matriz es `1`. Si proporcionó dos instrucciones, la longitud de la matriz es `2`. Cada resultado de la matriz contiene `0` o más filas. `toJsonObject` devuelve `null` si el valor del resultado no es válido o no es esperado.

## Funciones de utilidad
<a name="utility-functions"></a>

Puede utilizar las utilidades auxiliares del módulo AWS AppSync RDS para interactuar con la base de datos.

### Selección de SQL
<a name="utility-functions-select"></a>

La utilidad `select` crea una instrucción `SELECT` para consultar la base de datos relacional. 

**Uso básico**

En su forma básica, puede especificar la tabla que desea consultar:

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

export function request(ctx) {

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

Tenga en cuenta que también puede especificar el esquema en el identificador de la tabla:

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

export function request(ctx) {

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

**Especificación de columnas**

Puede especificar columnas con la propiedad `columns`. Si no se establece en un valor, el valor predeterminado es `*`:

```
export function request(ctx) {

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

También puede especificar la tabla de una columna:

```
export function request(ctx) {

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

**Límites y desplazamientos**

Puede aplicar `limit` y `offset` a la 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**

Puede ordenar los resultados con la propiedad `orderBy`. Proporcione una matriz de objetos especificando la columna y una propiedad `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**

Puede crear filtros con el objeto de condición 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'}}
    }));
}
```

También puede 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}}
    }));
}
```

También puede crear instrucciones `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 } }
        ]}
    }));
}
```

También puede negar una condición con `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 } }
        ]}
    }));
}
```

También puede utilizar los siguientes operadores para comparar valores:


| 
| 
| Operador | Description (Descripción) | Tipos de valor posibles | 
| --- |--- |--- |
| eq | Igualdad | número, cadena, booleano | 
| ne | Desigualdad | número, cadena, booleano | 
| una mentira | Menor que o igual a | número, cadena | 
| lt | Menor que | número, cadena | 
| edad | Mayor que o igual a | número, cadena | 
| gt | Mayor que | número, cadena | 
| contains | Como | cadena | 
| no contiene | No como | cadena | 
| Empieza con | Empieza con el prefijo | cadena | 
| entre | Entre dos valores | número, cadena | 
| El atributo existe | El atributo no es nulo | número, cadena, booleano | 
| tamaño | comprueba la longitud del elemento | cadena | 

### Inserción de SQL
<a name="utility-functions-insert"></a>

La utilidad `insert` ofrece una forma sencilla de insertar elementos de una sola fila en la base de datos con la operación `INSERT`.

**Inserciones de un solo elemento**

Para insertar un elemento, especifique la tabla y, a continuación, transfiera su objeto de valores. Las claves de objetos se asignan a las columnas de la tabla. Los nombres de las columnas se escapan automáticamente y los valores se envían a la base de datos mediante el mapa de variables:

```
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 de MySQL**

Puede combinar un `insert` seguido de un `select` para recuperar la fila insertada:

```
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 de Postgres**

Con Postgres, puede usar [https://www.postgresql.org/docs/current/dml-returning.html](https://www.postgresql.org/docs/current/dml-returning.html) para obtener datos de la fila que insertó. Acepta `*` o una matriz de nombres de columna:

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

### Actualización de SQL
<a name="utility-functions-update"></a>

La utilidad `update` le permite actualizar las filas existentes. Puede utilizar el objeto de condición para aplicar cambios a las columnas especificadas en todas las filas que cumplan la condición. Por ejemplo, supongamos que tenemos un esquema que nos permite realizar esta mutación. Queremos actualizar el `name` de `Person` con el valor `id` de `3`, pero solo si los conocemos (`known_since`) desde el año `2000`:

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

Nuestro solucionador de actualización tendrá este aspecto:

```
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 añadir una comprobación a nuestra condición para asegurarnos de que solo se actualice la fila en la que la clave principal `3` sea igual a `id`. Del mismo modo, en el caso de `inserts` de Postgres, se puede utilizar `returning` para devolver los datos modificados. 

### Eliminación de SQL
<a name="utility-functions-delete"></a>

La utilidad `remove` le permite eliminar las filas existentes. Puede utilizar el objeto de condición en todas las filas que cumplan la condición. Tenga en cuenta que `delete` es una palabra clave reservada en JavaScript. `remove`debería usarse en su lugar:

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

## Conversión
<a name="casting"></a>

En algunos casos, es posible que desee más especificidad sobre el tipo de objeto correcto para usar en su instrucción. Puede utilizar las sugerencias de tipo proporcionadas para especificar el tipo de parámetros. AWS AppSync admite las [mismas sugerencias de tipo](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html#rdsdtataservice-Type-SqlParameter-typeHint) que la API de datos. Puede convertir sus parámetros mediante las `typeHint` funciones del AWS AppSync `rds` módulo. 

En el siguiente ejemplo puede enviar una matriz como un valor que se convierte en un objeto JSON. Usamos el operador `->` para recuperar el elemento en el `index` `2` en la 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
}
```

La conversión también resulta útil al manipular y comparar `DATE`, `TIME` y `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)
}
```

Aquí se muestra otro ejemplo de cómo puede enviar la fecha y hora actuales:

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

**Sugerencias de tipos disponibles**
+ `typeHint.DATE`: el parámetro correspondiente se envía como un objeto de tipo `DATE` a la base de datos. El formato aceptado es `YYYY-MM-DD`.
+ `typeHint.DECIMAL`: el parámetro correspondiente se envía como un objeto de tipo `DECIMAL` a la base de datos.
+ `typeHint.JSON`: el parámetro correspondiente se envía como un objeto de tipo `JSON` a la base de datos.
+ `typeHint.TIME`: el valor del parámetro de cadena correspondiente se envía como un objeto de tipo `TIME` a la base de datos. El formato aceptado es `HH:MM:SS[.FFF]`. 
+ `typeHint.TIMESTAMP`: el valor del parámetro de cadena correspondiente se envía como un objeto de tipo `TIMESTAMP` a la base de datos. El formato aceptado es `YYYY-MM-DD HH:MM:SS[.FFF]`.
+ `typeHint.UUID`: el valor del parámetro de cadena correspondiente se envía como un objeto de tipo `UUID` a la base de datos.