

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Utilizzo di Aurora Serverless v2 con AWS AppSync
<a name="tutorial-rds-resolvers"></a>

Connect l'API GraphQL ai database Aurora Serverless utilizzando. AWS AppSync Questa integrazione consente di eseguire istruzioni SQL tramite query, mutazioni e sottoscrizioni GraphQL, offrendoti un modo flessibile di interagire con i tuoi dati relazionali.

**Nota**  
In questo tutorial viene utilizzata la regione `US-EAST-1`.

**Vantaggi**
+ Perfetta integrazione tra GraphQL e database relazionali
+ Capacità di eseguire operazioni SQL tramite interfacce GraphQL
+ Scalabilità senza server con Aurora Serverless v2
+ Accesso sicuro ai dati tramite AWS Secrets Manager
+ Protezione contro l'SQL injection tramite la sanificazione degli input
+ Funzionalità di interrogazione flessibili, tra cui operazioni di filtraggio e intervallo

**Casi di utilizzo comune**
+ Creazione di applicazioni scalabili con requisiti di dati relazionali
+ La creazione di APIs ciò richiede sia la flessibilità GraphQL che le funzionalità del database SQL
+ Gestione delle operazioni sui dati tramite mutazioni e query GraphQL
+ Implementazione di modelli di accesso sicuri al database

In questo tutorial, imparerai quanto segue.
+ Configura un cluster Aurora Serverless v2
+ Abilita la funzionalità Data API
+ Crea e configura strutture di database
+ Definizione degli schemi GraphQL per le operazioni del database
+ Implementa resolver per query e mutazioni
+ Proteggi l'accesso ai dati mediante un'adeguata sanificazione degli input
+ Esegui varie operazioni di database tramite interfacce GraphQL

**Topics**
+ [Configurazione del cluster di database](#create-cluster)
+ [Abilitazione dell'API di dati](#enable-data-api)
+ [Creazione di un database e di una tabella](#create-database-and-table)
+ [Schema GraphQL](#graphql-schema)
+ [Connect la tua API alle operazioni del database](#configuring-resolvers)
+ [Modifica i tuoi dati tramite l'API](#run-mutations)
+ [Recupera i tuoi dati](#run-queries)
+ [Proteggi l'accesso ai dati](#input-sanitization)

## Configurazione del cluster di database
<a name="create-cluster"></a>

Prima di aggiungere un'origine dati Amazon RDS a AWS AppSync, devi prima abilitare una Data API su un cluster Aurora Serverless v2 **e** configurare un utilizzo segreto. *Gestione dei segreti AWS* È possibile creare un cluster Aurora Serverless v2 utilizzando: AWS CLI

```
aws rds create-db-cluster \
    --db-cluster-identifier appsync-tutorial \
    --engine aurora-mysql \
    --engine-version 8.0 \
    --serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=1 \
    --master-username USERNAME \
    --master-user-password COMPLEX_PASSWORD \
    --enable-http-endpoint
```

Verrà restituito un ARN per il cluster.

Dopo aver creato il cluster, è necessario aggiungere un'istanza Aurora Serverless v2 utilizzando il comando seguente.

```
aws rds create-db-instance \
    --db-cluster-identifier appsync-tutorial \
    --db-instance-identifier appsync-tutorial-instance-1 \
    --db-instance-class db.serverless \
    --engine aurora-mysql
```

**Nota**  
L'attivazione di questi endpoint richiede tempo. Puoi verificarne lo stato nella console Amazon RDS nella scheda **Connettività e sicurezza** del cluster. Puoi anche controllare lo stato del tuo cluster con il seguente AWS CLI comando.   

```
aws rds describe-db-clusters \
    --db-cluster-identifier appsync-tutorial \
    --query "DBClusters[0].Status"
```

È possibile creare un *Secret* utilizzando la Gestione dei segreti AWS Console o AWS CLI con un file di input come il seguente utilizzando la `USERNAME` e `COMPLEX_PASSWORD` del passaggio precedente.

```
{
    "username": "USERNAME",
    "password": "COMPLEX_PASSWORD"
}
```

Passalo come parametro a AWS CLI:

```
aws secretsmanager create-secret --name HttpRDSSecret --secret-string file://creds.json --region us-east-1
```

Verrà restituito un ARN per il segreto.

 **Prendi nota dell'ARN** del cluster Aurora Serverless e di Secret per utilizzarli successivamente nella AppSync console durante la creazione di un'origine dati.

## Abilitazione dell'API di dati
<a name="enable-data-api"></a>

È possibile abilitare l'API di dati sul cluster [seguendo le istruzioni nella documentazione di RDS](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html). L'API Data deve essere abilitata prima di aggiungerla come fonte di dati. AppSync 

## Creazione di un database e di una tabella
<a name="create-database-and-table"></a>

Dopo aver abilitato la Data API, puoi assicurarti che funzioni con il `aws rds-data execute-statement` comando contenuto in AWS CLI. Ciò garantirà che il cluster Aurora Serverless sia configurato correttamente prima di aggiungerlo all'API. AppSync Innanzitutto, creare un database denominato *TESTDB* con il parametro `--sql`, in questo modo:

```
aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:123456789000:cluster:http-endpoint-test" \
--schema "mysql"  --secret-arn "arn:aws:secretsmanager:us-east-1:123456789000:secret:testHttp2-AmNvc1"  \
--region us-east-1 --sql "create DATABASE TESTDB"
```

Se la creazione viene eseguita senza errori, aggiungere una tabella con il comando *create table*:

```
aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:123456789000:cluster:http-endpoint-test" \
 --schema "mysql"  --secret-arn "arn:aws:secretsmanager:us-east-1:123456789000:secret:testHttp2-AmNvc1" \
 --region us-east-1 \
 --sql "create table Pets(id varchar(200), type varchar(200), price float)" --database "TESTDB"
```

Se tutto è stato eseguito senza problemi, puoi passare all'aggiunta del cluster come fonte di dati AppSync nell'API.

## Schema GraphQL
<a name="graphql-schema"></a>

Ora che l'API di Aurora Serverless è operativa e dispone di una tabella, creeremo uno schema GraphQL e collegheremo i resolver per l'esecuzione di mutazioni e sottoscrizioni. Crea una nuova API nella AWS AppSync console, vai alla pagina **Schema** e inserisci quanto segue:

```
type Mutation {
    createPet(input: CreatePetInput!): Pet
    updatePet(input: UpdatePetInput!): Pet
    deletePet(input: DeletePetInput!): Pet
}

input CreatePetInput {
    type: PetType
    price: Float!
}

input UpdatePetInput {
id: ID!
    type: PetType
    price: Float!
}

input DeletePetInput {
    id: ID!
}

type Pet {
    id: ID!
    type: PetType
    price: Float
}

enum PetType {
    dog
    cat
    fish
    bird
    gecko
}

type Query {
    getPet(id: ID!): Pet
    listPets: [Pet]
    listPetsByPriceRange(min: Float, max: Float): [Pet]
}

schema {
    query: Query
    mutation: Mutation
}
```

 Salvare lo schema con **Save (Salva)**, accedere alla pagina **Data Sources (Origini dati)** e creare una nuova origine dati. Selezionare **Relational database (Database relazionale)** come tipo di origine dati e fornire un nome intellegibile. Utilizzare il nome del database creato nell'ultima fase e l'**ARN del cluster** in cui tale nome è stato creato. Per il **ruolo** puoi AppSync creare un nuovo ruolo o crearne uno con una politica simile alla seguente:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds-data:BatchExecuteStatement",
                "rds-data:BeginTransaction",
                "rds-data:CommitTransaction",
                "rds-data:ExecuteStatement",
                "rds-data:RollbackTransaction"
            ],
            "Resource": [
                "arn:aws:rds:us-east-1:111122223333:cluster:mydbcluster",
                "arn:aws:rds:us-east-1:111122223333:cluster:mydbcluster:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Resource": [
            "arn:aws:secretsmanager:us-east-1:111122223333:secret:mysecret",
            "arn:aws:secretsmanager:us-east-1:111122223333:secret:mysecret:*"
            ]
        }
    ]
}
```

------

Esistono due **istruzioni** in questa policy a cui viene concesso l'accesso basato sul ruolo. La prima **risorsa** è il cluster Aurora Serverless e la seconda è l'ARN. Gestione dei segreti AWS **Dovrai fornire **ENTRAMBI** ARNs nella configurazione dell'origine AppSync dati prima di fare clic su Crea.**

Passalo come parametro a AWS CLI.

```
aws secretsmanager create-secret \
  --name HttpRDSSecret \
  --secret-string file://creds.json \
  --region us-east-1
```

Verrà restituito un ARN per il segreto. Prendi nota dell'ARN del tuo cluster Aurora Serverless e di Secret per dopo quando crei un'origine dati nella console. AWS AppSync 

### Costruisci la struttura del tuo database
<a name="create-database-and-table"></a>

Dopo aver abilitato la tua Data API, puoi assicurarti che funzioni con il `aws rds-data execute-statement` comando contenuto in AWS CLI. Ciò garantirà che il cluster Aurora Serverless v2 sia configurato correttamente prima di aggiungerlo all'API. AWS AppSync Innanzitutto, crea un database chiamato *TESTDB* con il `--sql` parametro seguente.

```
aws rds-data execute-statement \
                --resource-arn "arn:aws:rds:us-east-1:111122223333:cluster:appsync-tutorial" \
                --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333:secret:appsync-tutorial-rds-secret"  \
                --region us-east-1 \
                --sql "create DATABASE TESTDB"
```

Se viene eseguito senza errori, aggiungete una tabella con il seguente comando *create table*.

```
aws rds-data execute-statement \
      --resource-arn "arn:aws:rds:us-east-1:111122223333:cluster:http-endpoint-test" \
      --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333:secret:testHttp2-AmNvc1" \
      --region us-east-1 \
      --sql "create table Pets(id varchar(200), type varchar(200), price float)" \
      --database "TESTDB"
```

### Progetta la tua interfaccia API
<a name="graphql-schema"></a>

Dopo che Aurora Serverless v2 Data API è attiva e funzionante con una tabella, crea uno schema GraphQL e collega i resolver per eseguire mutazioni e sottoscrizioni. Crea una nuova API nella console, vai alla pagina **Schema** nella AWS AppSync console e inserisci quanto segue.

```
type Mutation {
        createPet(input: CreatePetInput!): Pet
        updatePet(input: UpdatePetInput!): Pet
        deletePet(input: DeletePetInput!): Pet
    }
    
    input CreatePetInput {
        type: PetType
        price: Float!
    }
    
    input UpdatePetInput {
        id: ID!
        type: PetType
        price: Float!
    }
    
    input DeletePetInput {
        id: ID!
    }
    
    type Pet {
        id: ID!
        type: PetType
        price: Float
    }
    
    enum PetType {
        dog
        cat
        fish
        bird
        gecko
    }
    
    type Query {
        getPet(id: ID!): Pet
        listPets: [Pet]
        listPetsByPriceRange(min: Float, max: Float): [Pet]
    }
    
    schema {
        query: Query
        mutation: Mutation
    }
```

 Salvare lo schema con **Save (Salva)**, accedere alla pagina **Data Sources (Origini dati)** e creare una nuova origine dati. Scegli **Database relazionale** per il tipo di **origine dati** e fornisci un nome descrittivo. Utilizzare il nome del database creato nell'ultima fase e l'**ARN del cluster** in cui tale nome è stato creato. Per il **ruolo** puoi AWS AppSync creare un nuovo ruolo o crearne uno con una politica simile alla seguente.

------
#### [ JSON ]

****  

```
{
        "Version":"2012-10-17",		 	 	 
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "rds-data:BatchExecuteStatement",
                    "rds-data:BeginTransaction",
                    "rds-data:CommitTransaction",
                    "rds-data:ExecuteStatement",
                    "rds-data:RollbackTransaction"
                ],
                "Resource": [
                    "arn:aws:rds:us-east-1:111122223333:cluster:mydbcluster",
                    "arn:aws:rds:us-east-1:111122223333:cluster:mydbcluster:*"
                ]
            },
            {
                "Effect": "Allow",
                "Action": [
                    "secretsmanager:GetSecretValue"
                ],
                "Resource": [
                "arn:aws:secretsmanager:us-east-1:111122223333:secret:mysecret",
                "arn:aws:secretsmanager:us-east-1:111122223333:secret:mysecret:*"
                ]
            }
        ]
    }
```

------

Esistono due **istruzioni** in questa policy a cui viene concesso l'accesso basato sul ruolo. La prima **risorsa** è il cluster Aurora Serverless v2 e la seconda è l'ARN. Gestione dei segreti AWS **Dovrai fornire **ENTRAMBI** ARNs nella configurazione dell'origine AWS AppSync dati prima di fare clic su Crea.**

## Connect la tua API alle operazioni del database
<a name="configuring-resolvers"></a>

Ora che abbiamo uno schema GraphQL valido e un'origine dati RDS, puoi collegare i resolver ai campi GraphQL dello schema. La nostra API offrirà le seguenti funzionalità:

1. *crea un animale domestico usando il campo Mutation.createPet*

1. *aggiorna un animale domestico usando il campo Mutation.updatePet*

1. *elimina un animale domestico usando il campo Mutation.deletePet*

1. *ottenine un singolo utilizzo tramite il campo query.getPET*

1. *elenca tutto usando il campo query.listPets*

1. *elenca gli animali domestici in una fascia di prezzo utilizzando il comando Query. listPetsByPriceRange*campo

### Mutation.createPet
<a name="mutation-createpet"></a>

Dall'editor dello schema nella AWS AppSync console, sul lato destro scegli **Attach Resolver for**. `createPet(input: CreatePetInput!): Pet` Scegliere l'origine dati RDS. Aggiungere il modello seguente nella sezione **request mapping template (modello di mappatura della richiesta)**:

```
#set($id=$utils.autoId())
{
"version": "2018-05-29",
    "statements": [
        "insert into Pets VALUES (:ID, :TYPE, :PRICE)",
        "select * from Pets WHERE id = :ID"
    ],
    "variableMap": {
        ":ID": "$ctx.args.input.id",
        ":TYPE": $util.toJson($ctx.args.input.type),
        ":PRICE": $util.toJson($ctx.args.input.price)
    }
}
```

**Il sistema esegue le istruzioni SQL in sequenza, in base all'ordine nell'array delle istruzioni.** I risultati verranno restituiti nello stesso ordine. Poiché si tratta di una mutazione, verrà eseguita un'istruzione *select* dopo l'*inserimento per recuperare i valori confermati* al fine di popolare il modello di mappatura delle risposte GraphQL.

Aggiungere il modello seguente nella sezione **response mapping template (modello di mappatura della risposta)**:

```
$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])
```

Poiché le *istruzioni* contengono due query SQL, è necessario specificare il secondo risultato nella matrice restituita dal database con: `$utils.rds.toJsonString($ctx.result))[1][0])`.

### Mutation.updatePet
<a name="mutation-updatepet"></a>

**Dall'editor dello schema nella AWS AppSync console, scegli Attach Resolver for.** `updatePet(input: UpdatePetInput!): Pet` Scegli la tua fonte di **dati RDS.** Nella sezione del **modello di mappatura della richiesta**, aggiungi il seguente modello.

```
{
"version": "2018-05-29",
    "statements": [
        $util.toJson("update Pets set type=:TYPE, price=:PRICE WHERE id=:ID"),
        $util.toJson("select * from Pets WHERE id = :ID")
    ],
    "variableMap": {
        ":ID": "$ctx.args.input.id",
        ":TYPE": $util.toJson($ctx.args.input.type),
        ":PRICE": $util.toJson($ctx.args.input.price)
    }
}
```

Nella sezione **modello di mappatura delle risposte**, aggiungi il seguente modello.

```
$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])
```

### Mutation.deletePet
<a name="mutation-deletepet"></a>

Dall'editor dello schema nella AWS AppSync console, scegli **Attach Resolver** for. `deletePet(input: DeletePetInput!): Pet` Scegli la tua fonte di **dati RDS.** Nella sezione del **modello di mappatura della richiesta**, aggiungi il seguente modello.

```
{
"version": "2018-05-29",
    "statements": [
        $util.toJson("select * from Pets WHERE id=:ID"),
        $util.toJson("delete from Pets WHERE id=:ID")
    ],
    "variableMap": {
        ":ID": "$ctx.args.input.id"
    }
}
```

Nella sezione **modello di mappatura delle risposte**, aggiungi il seguente modello.

```
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])
```

### Query.getPet
<a name="query-getpet"></a>

Ora che le mutazioni sono state create per il tuo schema, collega le tre query per mostrare come ottenere singoli elementi, elenchi e applicare il filtro SQL. **Dall'**editor dello schema** nella AWS AppSync console, scegli Attach Resolver for.** `getPet(id: ID!): Pet` Scegli la tua fonte di **dati RDS.** Nella sezione del **modello di mappatura della richiesta**, aggiungi il seguente modello.

```
{
"version": "2018-05-29",
        "statements": [
            $util.toJson("select * from Pets WHERE id=:ID")
    ],
    "variableMap": {
        ":ID": "$ctx.args.id"
    }
}
```

Aggiungere il modello seguente nella sezione **response mapping template (modello di mappatura della risposta)**:

```
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])
```

### Query.listPets
<a name="query-listpets"></a>

Dall'editor dello schema nella AWS AppSync console, sul lato destro scegli **Attach Resolver** for. `getPet(id: ID!): Pet` Scegli la tua fonte di **dati RDS.** Nella sezione del **modello di mappatura della richiesta**, aggiungi il seguente modello.

```
{
    "version": "2018-05-29",
    "statements": [
        "select * from Pets"
    ]
}
```

Nella sezione **modello di mappatura delle risposte**, aggiungi il seguente modello.

```
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
```

### Interrogazione. listPetsByPriceRange
<a name="query-listpetsbypricerange"></a>

Dall'editor dello schema nella AWS AppSync console, sul lato destro scegli **Attach Resolver for**. `getPet(id: ID!): Pet` Scegli la tua fonte di **dati RDS.** Nella sezione del **modello di mappatura della richiesta**, aggiungi il seguente modello.

```
{
    "version": "2018-05-29",
    "statements": [
            "select * from Pets where price > :MIN and price < :MAX"
    ],

    "variableMap": {
        ":MAX": $util.toJson($ctx.args.max),
        ":MIN": $util.toJson($ctx.args.min)
    }
}
```

Aggiungere il modello seguente nella sezione **response mapping template (modello di mappatura della risposta)**:

```
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
```

## Modifica i tuoi dati tramite l'API
<a name="run-mutations"></a>

Ora che sono stati configurati tutti i resolver con le istruzioni SQL e l'API GraphQL è stata collegata all'API di dati per Aurora Serverless, è possibile iniziare a eseguire mutazioni e query. Nella AWS AppSync console, scegli la scheda **Query** e inserisci quanto segue per creare un animale domestico:

```
mutation add {
    createPet(input : { type:fish, price:10.0 }){
        id
        type
        price
    }
}
```

La risposta dovrebbe contenere l'*id*, il *type (tipo)* e il *price (prezzo)*, come indicato di seguito:

```
{
  "data": {
    "createPet": {
      "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a",
      "type": "fish",
      "price": "10.0"
    }
  }
}
```

È possibile modificare questo elemento eseguendo la mutazione *updatePet*:

```
mutation update {
    updatePet(input : {
        id: ID_PLACEHOLDER,
        type:bird,
        price:50.0
    }){
        id
        type
        price
    }
}
```

Abbiamo utilizzato l'*id* che è stato restituito dall'operazione *createPet* precedente. Questo sarà un valore univoco per il record poiché il resolver si è basato su `$util.autoId()`. È possibile eliminare un record in modo analogo:

```
mutation delete {
    deletePet(input : {id:ID_PLACEHOLDER}){
        id
        type
        price
    }
}
```

Creare di alcuni record con la prima mutazione con valori diversi per *price (prezzo)*, quindi eseguire alcune query.

## Recupera i tuoi dati
<a name="run-queries"></a>

Sempre nella scheda **Queries** della console, usa la seguente istruzione per elencare tutti i record che hai creato.

```
query allpets {
    listPets {
        id
        type
        price
    }
}
```

*Sfrutta il predicato SQL *WHERE* presente `where price > :MIN and price < :MAX` nel nostro modello di mappatura per Query. listPetsByPriceRange*con la seguente query GraphQL:

```
query petsByPriceRange {
    listPetsByPriceRange(min:1, max:11) {
        id
        type
        price
    }
}
```

Si dovrebbero visualizzare solo i record con *price (prezzo)* superiore a \$11 o inferiore a \$110. Infine, è possibile eseguire le query per recuperare singoli record, nel modo seguente:

```
query onePet {
    getPet(id:ID_PLACEHOLDER){
        id
        type
        price
    }
}
```

## Proteggi l'accesso ai dati
<a name="input-sanitization"></a>

L'iniezione SQL è una vulnerabilità di sicurezza nelle applicazioni di database. Si verifica quando gli aggressori inseriscono codice SQL dannoso attraverso i campi di input dell'utente. Ciò può consentire l'accesso non autorizzato ai dati del database. Si consiglia di convalidare e disinfettare attentamente tutti gli input dell'utente prima dell'elaborazione, utilizzandoli `variableMap` per la protezione dagli attacchi di SQL injection. Se non vengono utilizzate mappe variabili, è responsabilità dell'utente sanificare gli argomenti delle loro operazioni GraphQL. Un possibile modo è fornire fasi di convalida specifiche dell'input nel modello di mappatura della richiesta prima dell'esecuzione di un'istruzione SQL sull'API di dati. Vediamo come possiamo modificare il modello di mappatura della richiesta dell'esempio `listPetsByPriceRange`. Anziché basarsi esclusivamente sull'input dell'utente, è possibile procedere nel modo seguente:

```
#set($validMaxPrice = $util.matches("\d{1,3}[,\\.]?(\\d{1,2})?",$ctx.args.maxPrice))

#set($validMinPrice = $util.matches("\d{1,3}[,\\.]?(\\d{1,2})?",$ctx.args.minPrice))


#if (!$validMaxPrice || !$validMinPrice)
    $util.error("Provided price input is not valid.")
#end
{
    "version": "2018-05-29",
    "statements": [
            "select * from Pets where price > :MIN and price < :MAX"
    ],

    "variableMap": {
        ":MAX": $util.toJson($ctx.args.maxPrice),
        ":MIN": $util.toJson($ctx.args.minPrice)
    }
}
```

Un altro modo per proteggersi da input anomali durante l'esecuzione di resolver sull'API di dati consiste nell'utilizzare istruzioni preparate assieme a procedure memorizzate e input parametrici. Ad esempio, nel resolver per `listPets`, definire la procedura seguente che esegue il *select* come istruzione preparata:

```
CREATE PROCEDURE listPets (IN type_param VARCHAR(200))
  BEGIN
     PREPARE stmt FROM 'SELECT * FROM Pets where type=?';
     SET @type = type_param;
     EXECUTE stmt USING @type;
     DEALLOCATE PREPARE stmt;
  END
```

Crealo nella tua istanza Aurora Serverless v2.

```
aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:xxxxxxxxxxxx:cluster:http-endpoint-test" \
--schema "mysql"  --secret-arn "arn:aws:secretsmanager:us-east-1:xxxxxxxxxxxx:secret:httpendpoint-xxxxxx"  \
--region us-east-1  --database "DB_NAME" \
--sql "CREATE PROCEDURE listPets (IN type_param VARCHAR(200)) BEGIN PREPARE stmt FROM 'SELECT * FROM Pets where type=?'; SET @type = type_param; EXECUTE stmt USING @type; DEALLOCATE PREPARE stmt; END"
```

Il codice del resolver risultante per listPets è semplificato poiché ora è sufficiente chiamare la procedura memorizzata. Come minimo, qualsiasi input di stringa deve avere le virgolette singole tra caratteri di [escape](#escaped).

```
#set ($validType = $util.isString($ctx.args.type) && !$util.isNullOrBlank($ctx.args.type))
#if (!$validType)
    $util.error("Input for 'type' is not valid.", "ValidationError")
#end

{
    "version": "2018-05-29",
    "statements": [
        "CALL listPets(:type)"
    ]
    "variableMap": {
        ":type": $util.toJson($ctx.args.type.replace("'", "''"))
    }
}
```

### Utilizzo delle stringhe di escape
<a name="escaped"></a>

Usa virgolette singole per contrassegnare l'inizio e la fine delle stringhe letterali in un'istruzione SQL, ad esempio.. `'some string value'`. Per consentire l'utilizzo di valori stringa con uno o più caratteri virgolette singole (`'`) all'interno di una stringa, ciascuna virgoletta deve essere sostituita con due virgolette singole (`''`). Ad esempio, se la stringa di input è `Nadia's dog`, inserisci il carattere di escape per l'istruzione SQL come segue

```
update Pets set type='Nadia''s dog' WHERE id='1'
```