deno-slack-sdk icon indicating copy to clipboard operation
deno-slack-sdk copied to clipboard

[BUG] Datastore query fails to match identical timestamp

Open mfcarroll opened this issue 9 months ago • 1 comments

The deno-slack versions

    "deno-slack-sdk/": "https://deno.land/x/[email protected]/",
    "deno-slack-api/": "https://deno.land/x/[email protected]/",

Deno runtime version

deno 2.1.9 (stable, release, aarch64-apple-darwin)
v8 13.0.245.12-rusty
typescript 5.6.2

OS info

ProductName:		macOS
ProductVersion:		15.2
BuildVersion:		24C101
Darwin Kernel Version 24.2.0: Fri Dec  6 19:02:41 PST 2024; root:xnu-11215.61.5~2/RELEASE_ARM64_T6030

Describe the bug

I'm trying to query a datastore for all items that share the same exact value for a timestamp field. A straight equals comparison fails. Providing a range succeeds, but bizarrely, only if the range is big enough.

Steps to reproduce

This is simplified from my app, but I reproduced the bug with just this datastore and the slack cli.

Datastore definition:

import { DefineDatastore, Schema } from "deno-slack-sdk/mod.ts";

const BugreportDatastore = DefineDatastore({
  name: "bugreport",
  primary_key: "channel_id",
  attributes: {
    channel_id: {
      type: Schema.types.string,
    },
    batch_ts: {
      type: Schema.slack.types.timestamp,
    },
  },
});

export interface ChannelData {
  channel_id: string;
  batch_ts: number;
}

export default BugreportDatastore;

Slack CLI steps with actual result:

% slack -w $WORKSPACE -a local datastore put --datastore bugreport '{
  "item": {
      "channel_id": "C12345ABC",
      "batch_ts": 1742941666.812
    }
}'
🎉  Stored below record in the datastore: bugreport

{
  "batch_ts": 1742941666.812,
  "channel_id": "C12345ABC"
}
% slack -w $WORKSPACE -a local datastore query '{                                                     
  "datastore": "bugreport",
  "expression": "#batch_ts = :batch_ts",
  "expression_attributes": { "#batch_ts": "batch_ts" },
  "expression_values": { ":batch_ts": 1742941666.812 }
}'
🎉  Retrieved 0 items from datastore: bugreport
% slack -w $WORKSPACE -a local datastore query '{                                                     
  "datastore": "bugreport",
  "expression": "#batch_ts BETWEEN :batch_ts1 AND :batch_ts2",
  "expression_attributes": { "#batch_ts": "batch_ts" },
  "expression_values": { ":batch_ts1": 1742941666, ":batch_ts2": 1742941667 }
}'
🎉  Retrieved 1 items from datastore: bugreport

{
  "batch_ts": 1742941666.812,
  "channel_id": "C12345ABC"
}
% slack -w $WORKSPACE -a local datastore query '{                                                     
  "datastore": "bugreport",
  "expression": "#batch_ts BETWEEN :batch_ts1 AND :batch_ts2",
  "expression_attributes": { "#batch_ts": "batch_ts" },
  "expression_values": { ":batch_ts1": 1742941666.81, ":batch_ts2": 1742941667.83 }
}'
🎉  Retrieved 0 items from datastore: bugreport

Expected result

All three queries should succeed.

Using Schema.types.number the behaviour is the same. Only with Schema.types.string was I able to get the query to work testing for equality. (That's fine for me in this instance as I only need exact matches.)

Interestingly, with using strings, the exact comparison succeeds whether I feed the expression value a string or a number, but the range behaviour seems really confusing. It's failing on numerical integers and numerical decimals with an integer value, but succeeding when either of those are presented as strings...

✅ "expression_values": { ":batch_ts1": "1742941666", ":batch_ts2": "1742941667" } ❌ "expression_values": { ":batch_ts1": 1742941666, ":batch_ts2": 1742941667 } ✅ "expression_values": { ":batch_ts1": "1742941666.81", ":batch_ts2": "1742941666.82" } ✅ "expression_values": { ":batch_ts1": 1742941666.81, ":batch_ts2": 1742941666.82 } ✅ "expression_values": { ":batch_ts1": "1742941666.0", ":batch_ts2": "1742941667.0" } ❌ "expression_values": { ":batch_ts1": 1742941666.0, ":batch_ts2": 1742941667.0 }

mfcarroll avatar Mar 26 '25 02:03 mfcarroll

Hi @mfcarroll thanks for highlighting this 🥇 I was myself surprised by this behavior

As you may already know datastores follow the same syntax as DynamoDB, I believe this is the same underlying issue as boto3/#665

The suggested workaround is to store the float as a string and then use Decimal to cast it

Let me know if this workaround works for you but I'm afraid their isn't much more I could do to resolve this

WilliamBergamin avatar Mar 26 '25 18:03 WilliamBergamin