mattn / go-adodb

Microsoft ActiveX Object DataBase driver for go that using exp/sql
http://mattn.kaoriya.net/
MIT License
142 stars 36 forks source link

How to get VT_VARIANT values from result? #34

Closed coussej closed 6 years ago

coussej commented 6 years ago

Hi, first of all thanks for all the work you've put into making both this and go-ole.

I need to get data out of a custom proprietary time series database for which an OLEDB driver is supplied. I managed to get things up and running for timestamp and integer parameters, but the driver returns certain values as VT_VARIANT to allow mutiple datatype to be returned in the same column.

For example: image

Here the value column is of type variant. The resulting object in the interface is of type *ole.VARIANT, but the VT is always empty:

    rows, err := db.Query(queryData)
    if err != nil {
        fmt.Println("select", err)
        return
    }
    defer rows.Close()

    fmt.Println(rows.Columns())
    ct, _ := rows.ColumnTypes()
    fmt.Println(ct[0].Name(), ct[0].DatabaseTypeName(), ct[0].ScanType())

    for rows.Next() {
        var timestamp time.Time
        var value interface{}
        err = rows.Scan(&timestamp, &value)
        if err != nil {
            fmt.Println("scan", err)
            return
        }
        fmt.Println(timestamp, value)
    }
2018-04-27 13:37:28 +0200 CEST &{VT_EMPTY 0 0 0 131693095766368559 [0 0 0 0 0 0 0 0]}
2018-04-27 13:42:04 +0200 CEST &{VT_EMPTY 0 0 0 131693100061366196 [0 0 0 0 0 0 0 0]}
2018-04-27 13:44:35 +0200 CEST &{VT_EMPTY 0 0 0 131693100061341924 [0 0 0 0 0 0 0 0]}
2018-04-27 13:45:07 +0200 CEST &{VT_EMPTY 0 0 0 131693100061317651 [0 0 0 0 0 0 0 0]}
2018-04-27 13:45:39 +0200 CEST &{VT_EMPTY 0 0 0 131693104356260674 [0 0 0 0 0 0 0 0]}
2018-04-27 14:09:17 +0200 CEST &{VT_EMPTY 0 0 0 131693117241186835 [0 0 0 0 0 0 0 0]}
2018-04-27 14:10:18 +0200 CEST &{VT_EMPTY 0 0 0 131693117241211108 [0 0 0 0 0 0 0 0]}
2018-04-27 14:12:51 +0200 CEST &{VT_EMPTY 0 0 0 131693117241186835 [0 0 0 0 0 0 0 0]}
2018-04-27 14:14:48 +0200 CEST &{VT_EMPTY 0 0 0 131693121536178404 [0 0 0 0 0 0 0 0]}
2018-04-27 14:23:38 +0200 CEST &{VT_EMPTY 0 0 0 131693125831121427 [0 0 0 0 0 0 0 0]}
2018-04-27 14:24:12 +0200 CEST &{VT_EMPTY 0 0 0 131693125831097154 [0 0 0 0 0 0 0 0]}
2018-04-27 14:24:58 +0200 CEST &{VT_EMPTY 0 0 0 131693125831066814 [0 0 0 0 0 0 0 0]}
2018-04-27 14:30:48 +0200 CEST &{VT_EMPTY 0 0 0 131693130126058382 [0 0 0 0 0 0 0 0]}

How should I handle this type of column?

Any ideas are much appreciated, spent almost a full day I trying different things šŸ˜ž Thanks in advance!!!

mattn commented 6 years ago

Could you please try this patch to go-adodb?

diff --git a/adodb.go b/adodb.go
index 9edfb4a..e5faac0 100644
--- a/adodb.go
+++ b/adodb.go
@@ -528,9 +528,11 @@ func (rc *AdodbRows) Next(dest []driver.Value) error {
            }
            dest[i] = (*[1 << 30]byte)(unsafe.Pointer(uintptr(sa.Data)))[0:elems]
        }
+       if typ.Val != 12 {
+           val.Clear()
+       }
        typ.Clear()
        sc.Clear()
-       val.Clear()
        field.Release()
    }
    rv, err := oleutil.CallMethod(rc.rc, "MoveNext")
coussej commented 6 years ago

This seems to work! I now get an ole.VARIANT with VT_R4 as type, and I can get to the underlying value. Great! šŸŽ‰

I had the same issue with VT_BSTR, where they would return as VT_EMPTY, but with your patch this is now also fixed.

My sincere thanks for looking into this (and so quickly!).

mattn commented 6 years ago

Okay, I'll merge this patch above.