baopham / laravel-dynamodb

Eloquent syntax for DynamoDB
https://packagist.org/packages/baopham/dynamodb
MIT License
484 stars 128 forks source link

Invalid Query or Scan syntax with "single-table design" indexes #274

Open mnapoli opened 11 months ago

mnapoli commented 11 months ago

Describe the bug

When querying a table designed with "single-table design" practices, the package fails to escape index names.

Schema

The standard names for secondary indexes would be:

                'GSI-1-PK': '...',
                'GSI-1-SK': '...',
                etc.

Here's an example of a query I do in JavaScript on that table:

        TableName: ...,
        IndexName: 'GSI-1',
        KeyConditionExpression: '#indexName = :PK',
        ExpressionAttributeValues: {
            ':PK': `...`,
        },
        ExpressionAttributeNames: {
            // The `-` character is a reserved character in DynamoDB, so we need to escape it
            '#indexName': 'GSI-1-PK',
        },

That's what ExpressionAttributeNames is here for (to alias attribute names).

I think this package needs to do the same thing and escape attribute names. Can you confirm that this isn't the case currently?

I get the following error:

Error executing "Query" on "https://dynamodb.us-east-1.amazonaws.com"; AWS HTTP error: Client error: POST https://dynamodb.us-east-1.amazonaws.com resulted in a 400 Bad Request response: {"type":"com.amazon.coral.validate#ValidationException","message":"ExpressionAttributeNames contains invalid key: Synt (truncated...) ValidationException (client): ExpressionAttributeNames contains invalid key: Syntax error; key: "#GSI-1-PK" - {"type":"com.amazon.coral.validate#ValidationException","message":"ExpressionAttributeNames contains invalid key: Syntax error; key: \"#GSI-1-PK\""}

Most important part:

Syntax error; key: "#GSI-1-PK"

DynamoDB doesn't like the - in the names.

Debug info

Show the query that you're having trouble with by copy-pasting the result of:

Route::get('/', function () {
    return view('home', [
        'measures' => Measure::query()
            ->where('GSI-1-PK', '...')
            ->where('GSI-1-SK', '*')
            ->get(),
    ]);
});

Version info

nelson6e65 commented 11 months ago

Hi. Try to enable debug in config and then run the query only.

There will be some debug logs of your query in your .log file under storage/logs/xxx.log (you can use daily type and debug as min level in the laravel logs config).

I'll look into it this weekend. 🧐