Closed kekami closed 2 months ago
Hey👋 thanks for raising this! I'm going to transfer this over to our API repository for better assistance 🙂
@kekami Can you share the SQL table definitions for User and Worker, as well as the generated source schema.sql.ts? It's hard to pinpoint what the problem might be without a bit more detail.
Hey @palpatim Managed to create a smaller reproducible example of this one as well.
Table definitions
CREATE TABLE users (
id UUID PRIMARY KEY NOT NULL,
owner TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE workers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
owners TEXT[],
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
user_id UUID NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
);
schema.sql.ts
/* eslint-disable */
/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. */
import { a } from "@aws-amplify/data-schema";
import { configure } from "@aws-amplify/data-schema/internals";
import { secret } from "@aws-amplify/backend";
export const schema = configure({
database: {
identifier: "IDXrrO7OzwePLc4YSnk7J3Mw",
engine: "postgresql",
connectionUri: secret("SQL_CONNECTION_STRING_REPRO2")
}
}).schema({
"users": a.model({
id: a.id().required(),
owner: a.string(),
created_at: a.datetime(),
updated_at: a.datetime()
}).identifier([
"id"
]),
"workers": a.model({
id: a.id().required(),
owners: a.string().array(),
created_at: a.datetime(),
updated_at: a.datetime(),
user_id: a.id().required()
}).identifier([
"id"
])
});
resource.ts
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
import { schema as generatedSqlSchema } from "./schema.sql.js";
const sqlSchema = generatedSqlSchema
.renameModels(() => [
["users", "User"],
["workers", "Worker"],
])
.setRelationships((models) => [
models.User.relationships({
worker: a.hasOne("Worker", "user_id"),
}),
models.Worker.relationships({
user: a.belongsTo("User", "user_id"),
}),
])
.setAuthorization((models) => [
models.User.authorization((allow) => [
allow.ownerDefinedIn("owner"),
allow.groups(["admin"]),
]),
models.Worker.authorization((allow) => [
allow.ownersDefinedIn("owners"),
allow.groups(["admin"]),
]),
]);
export type Schema = ClientSchema<typeof sqlSchema>;
export const data = defineData({
schema: sqlSchema,
authorizationModes: {
defaultAuthorizationMode: "userPool",
apiKeyAuthorizationMode: {
expiresInDays: 30,
},
},
});
Also, worth mentioning, I noticed that the error only occurs when using userpool auth, but works fine with IAM auth.
The database is hosted on https://neon.tech/, not using AWS RDS if relevant.
Thanks for the repro, @kekami.
workers.user_id
in your query selection set? Since user_id
is a required field, I'm wondering if there is some validation that might be conflicting.Either way, we'll try digging into it locally.
Hi @palpatim
const { data, errors } = await client.models.User.list({
selectionSet: ["id", "worker.id"],
});
query MyQuery { listUsers { items { id worker { id } } } }
2. Same behaviour when including `worker.user_id` in both the JS client and AppSync console.
I suspect it has to do with owners
based auth, when the related object has an owners
array. Since the inverse query works, e.g.
query MyQuery {
listWorkers {
items {
id
user {
id
}
}
}
}
@palpatim Dug a little and found the reason, in the VTL for Connection Queries e.g.
## [Start] Invoke RDS Lambda data source. **
#if( $ctx.stash.deniedField )
#set( $result = {
"items": []
} )
#return($result)
#end
#set( $lambdaInput = {} )
#set( $lambdaInput.args = {} )
#set( $lambdaInput.table = "service_agreements" )
#set( $lambdaInput.operation = "LIST" )
#set( $lambdaInput.operationName = "ConnectionQuery" )
#set( $lambdaInput.args.metadata = {} )
#set( $lambdaInput.args.metadata.keys = [] )
#set( $lambdaInput.args.metadata.arrayFields = [] )
#set( $lambdaInput.args.metadata.nonScalarFields = [] )
#set( $lambdaInput.args.metadata.fieldMap = {} )
$util.qr($lambdaInput.args.metadata.fieldMap.putAll($util.defaultIfNull($context.stash.fieldMap, {})))
$util.qr($lambdaInput.args.putAll($util.defaultIfNull($context.arguments, {})))
#if( !$lambdaInput.args.filter )
#set( $lambdaInput.args.filter = {} )
#end
#if( !$util.isNullOrEmpty($ctx.stash.authFilter) )
#set( $lambdaInput.args.metadata.authFilter = $ctx.stash.authFilter )
#end
$util.qr($lambdaInput.args.filter.put("customer_id", {
"eq": $ctx.source.id
}))
$util.qr($lambdaInput.args.metadata.keys.addAll($util.defaultIfNull($ctx.stash.keys, [])))
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": $util.toJson($lambdaInput)
}
## [End] Invoke RDS Lambda data source. **
The problem is here:
#set( $lambdaInput.args.metadata.arrayFields = [] )
#set( $lambdaInput.args.metadata.nonScalarFields = [] )
These should be:
#set( $lambdaInput.args.metadata.arrayFields = ["owners"] )
#set( $lambdaInput.args.metadata.nonScalarFields = ["owners"] )
Not quite sure why they aren't being set though.
This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.
@kekami Thanks very much for your effort to troubleshoot and fix the issue, and for including tests in your PR! The fix is merged in https://github.com/aws-amplify/amplify-category-api/pull/2689, and will be pushed to latest
with our next release.
This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.
Environment information
Description
Getting the following error when querying a nested object.
Query:
Schema: