DiceDB / dice

DiceDB is a redis-compliant, reactive, scalable, highly-available, unified cache optimized for modern hardware.
https://dicedb.io/
Other
6.86k stars 1.09k forks source link

Inconsistent Behaviour in http server : Big Integers are getting converted to float before storing thus losing their precision #1163

Open pg30 opened 1 month ago

pg30 commented 1 month ago

Steps to reproduce

Trying to set math.MinInt64

curl --location --request GET 'localhost:8082/set' \
--header 'Content-Type: application/json' \
--data '{
    "key" : "a",
    "value" : -9223372036854775808
}'
curl --location --request GET 'localhost:8082/get' \
--header 'Content-Type: application/json' \
--data '{
    "key" : "a"
}'

The result of get operation is

Expected output

{
    "status": "success",
    "data": -9223372036854775808
}

Observed output

{
    "status": "success",
    "data": "-9223372036854776000"
}

On further investigation, I observed that its happening while unmarshalling the request body in the http handler.

  1. In ParseHTTPRequest in redisCmdAdapter.go : we are converting the request body to map[string]interface{}
  2. Since the value type is interface{} golang considers the numbers as float which has precision limits upto 15 digits and thus converts it to scientific notation -9.223372036854776e+18 before storing in the DB
s4kh commented 1 month ago

Is this one being worked on? For the solution, should we try converting to string and use big.Int -> func (z *Int) SetString(s string, base int) (*Int, bool)

bigIntVal := new(big.Int)
if strValue, ok := value.(string); ok {
  bigInt, success := bigIntVal.SetString(strValue, 10)
  if !success {
    return errors.New("Error: Failed to convert string to big.Int")
  }
}
deydebaditya commented 3 weeks ago

@pg30 Raised a PR for the fix here: https://github.com/DiceDB/dice/pull/1227 Please do have a look.