aws / aws-appsync-community

The AWS AppSync community
https://aws.amazon.com/appsync
Apache License 2.0
507 stars 32 forks source link

Experiencing different behavior on multiple environments when using AppSync with RDS (Aurora PostgreSQL) #284

Open mostafa-aboelnaga opened 1 year ago

mostafa-aboelnaga commented 1 year ago

I have been using AWS CDK to deploy a BE stack that consists of mainly AppSync + RDS (Aurora PostgreSQL v11_16 Serverless) into several environments. I had an example mutation where I would insert a string value (AWSEmail) email and a timestamp value (AWSDateTime) subscribedUntil into a table accordingly. I've made this using a UNIT VTL resolver, here's the request mapping template:

{
    "version": "2018-05-29",
    "statements": [
        $util.toJson("INSERT INTO ""Users"" (email, ""subscribedUntil"") VALUES (:email, :subscribedUntil)"),
        $util.toJson("SELECT * FROM ""Users"" WHERE email = :email")
    ],
    "variableMap": {
        ":email": $util.toJson($ctx.args.input.email),
        ":subscribedUntil": $util.toJson($ctx.args.input.subscribedUntil)
    }
}

As mentioned at the very end of this documentation the variable map simply concatenates the variables into the SQL statements for the RDS to execute, so it just makes things more readable.

This expected behavior is actually happening in two of my environments, but when I tried creating a new third environment and deploy same resources with the same configurations using CDK, the mutation behaved differently.

How different? Well, it seems that AppSync didn't just concatenate these variables into the SQL statements, instead it somehow made them into parameters, and made it as what I would call a prepared statement(?)

I extracted the logs of that mutation's execution from the RDS for the different environments:

What's wrong with this parametrization of the statements? Other than the fact that this is different from the documented behavior, it makes it that those supplied values are passed as VARCHAR params into the statements, so that now RDS is erroring out that values are supplied as VARCHAR when the subscribedUntil column is expecting a timestamp:

"RDSHttp:{\"message\":\"ERROR: column \\\"subscribedUntil\\\" is of type timestamp with time zone but expression is of type character varying\\n  Hint: You will need to rewrite or cast the expression.\\n  Position: 60; SQLState: 42804\"}"

I'm thinking that the expected behavior (in 1st and 2nd) concatenated them into the statements, having them wrapped with single quotes made them of type unspecified or unknown, so that SQL figured out their types based on the columns they were being inserted into? but on the other environment (3rd or new ones) would have them explicitly parameterized as VARCHARs

Questions:

  1. Were there any changes related to AppSync that would cause such parametrization?
  2. How can I make sure that all my environments would have the same behavior in terms of the communication between AppSync and RDS other than using CDK to define every resource and configurations?
  3. What's the best way to map values into statements?
  4. Should I always explicitly cast the values being passed into SQL statements with their intended types?
tvmendoza commented 1 year ago

Hi there,

Thanks for bringing this issue. Can you email me at tonamv@amazon.com? We will work with you to get this sorted out.

Thanks

Tona