nakagami / firebirdsql

Firebird RDBMS sql driver for Go (golang)
MIT License
220 stars 60 forks source link

DECFLOAT(x) incorrect result when have decimals Firebird 4.0 #130

Closed xhit closed 2 years ago

xhit commented 3 years ago

If value of column DECFLOAT(x) is a valid integer without decimal, returns the correct result, but if we have a number with decimal, so the value returned is not correct.

Example: 20.01 returns like 0.01 and 12.01 returns like 2.01

Example code:

package main

import (
    "database/sql"
    "fmt"
    "net/url"
"github.com/shopspring/decimal"
    _ "github.com/nakagami/firebirdsql"
)

func main() {

    //connecto to Firebird
    db, err := connectFirebird("localhost", "firebird/data/testdb", "usr", "password", 3052)
    if err != nil {
        panic(err)
    }

    defer db.Close()
    issue130(db)

}

func issue130(db *sql.DB) {

    tableName := "ISSUE130"

    queryDrop := `drop table "` + tableName + `";`

    db.Exec(queryDrop)

    queryCreate := `CREATE TABLE ` + tableName + ` ("a" DECFLOAT(34));`

    _, err := db.Exec(queryCreate)
    if err != nil {
        panic(err)
    }

    defer db.Exec(queryDrop)

    queryInsert := "insert into " + tableName + " (\"a\") values (?)"

    a, err := decimal.NewFromString("12.01")
    if err != nil {
        panic(err)
    }

    _, err = db.Exec(queryInsert, a)
    if err != nil {
        panic(err)
    }

    var t sql.NullFloat64

    if err := db.QueryRow(`SELECT "a" FROM ` + tableName).Scan(&t); err != nil {
        panic(err)
    }

    fmt.Println(t.Float64)
}

//connectFirebird : Conectar a la base de datos Firebird
func connectFirebird(host, database, username, password string, port int) (*sql.DB, error) {

    // default port
    if port == 0 {
        port = 3050
    }

    //Password in firebird dsn not accept spaces, so escape with url.QueryEscape

    // in form user:pass@host:port/database
    dsn := fmt.Sprintf("%s:%s@%s:%d/%s", username, url.QueryEscape(password), host, port, database)

    db, err := sql.Open("firebirdsql", dsn)

    if err != nil {
        return nil, err
    }

    err = db.Ping()

    if err != nil {
        return nil, err
    }

    return db, nil
}
nakagami commented 3 years ago

I have modified the test code and checked the values and they seem to be fine. How about it?

https://github.com/nakagami/firebirdsql/commit/1d8ebc461c653b465a444d240fa582bcdebe9821

xhit commented 3 years ago

The test works because numbers are two int and one decimal (1.1, -20.2, etc...) but fails when numbers is three integer and one decimal point (100.1, 156.2) and when you have two decimals points with two int (12.01, 90.56).

nakagami commented 3 years ago

I could see there was a mistake.

nakagami commented 3 years ago

Perhaps we could fix it.