baopham / laravel-dynamodb

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

Accessors break query keys #232

Open alex-french opened 3 years ago

alex-french commented 3 years ago

Describe the bug

Where an accessor exists on a partition key, the key is passed through the accessor prior to query being executed, resulting in queries that can be incorrect.

Schema

Primary key: siteSensor (string) Partition key: dateFrom (string) No GSI

In the Eloquent model:

protected $primaryKey = 'siteSensor';
protected $compositeKey = ['siteSensor', 'dateFrom'];

I also use typical date mutator/accessor to convert from European dd/mm/YYYY to/from YYYY-mm-dd

        // Date mutators/accessors
    public function getDateFromAttribute($value)
    {
        return ( $value ? date('d/m/Y', strtotime($value) )  : null);
    }

    public function setDateFromAttribute($value)
    {
        $value = str_replace('/', '-', $value);
        $this->attributes['dateFrom'] = $value ? date('Y-m-d', strtotime($value)) : null;
    }

Debug info

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

"TableName" => "EnergyConversionFactorsDev"
    "KeyConditionExpression" => "#siteSensor = :a1 AND #dateFrom = :a2"
    "ExpressionAttributeNames" => array:2 [
      "#siteSensor" => "siteSensor"
      "#dateFrom" => "dateFrom"
    ]
    "ExpressionAttributeValues" => array:2 [
      ":a1" => array:1 [
        "S" => "aaaaaa#111"
      ]
      ":a2" => array:1 [
        "S" => "01/11/2020"
      ]
    ]

Note that the date string is being passed into the mutator first, then back to the accessor. Changing the date input string to 2020-11-01 does not make a difference since it still gets fed to the accessor.

Throwing a stack trace in the accessor shows that at vendor/baopham/dynamodb/src/DynamoDbModel.php:386 the following call is made, which subsequently passed the values throw the accessors:

$key[$name] = $this->getAttribute($name); Version info