在Go中返回空/空白记录的ODBC

huangapple go评论89阅读模式
英文:

ODBC in Go Returning Null/Blank Records

问题

我正在尝试将一个基于 FileMaker 的后端数据库通过 ODBC 连接到 Go REST API。

我已经成功在 Windows 上安装了 FileMaker ODBC 驱动程序,并且 DSN 正常工作。

我正在使用 Go 中的 mgodbc 包来连接数据库。

然而,虽然连接成功(没有运行时错误),但是当我运行查询时,我只能得到空白/空记录。我有以下代码来创建数据库连接:

func NewDB(dataSourceName string) (*DB, error) {

    db, err := sql.Open("mgodbc", dataSourceName)
    if err != nil {
        return nil, err
    }
    if err = db.Ping(); err != nil {
        return nil, err
    }

    // TEST

    return &DB{db}, nil
}

这个函数在我的 main 方法中被调用,如下所示:db, err := md.NewDB("DSN=cet_registrations2;Uid=*****;Pwd=*****;")。然后我调用其中一个查询方法,并尝试将其读入一个模型 struct 中。为了简化查询,我做了如下修改:

func (db *DB) GetStudent(id int) (*Student, error) {

    s := new(Student)
    p := new(PersonalDetails)

    log.Println(id)

    rows, err := db.Query("SELECT FN_Gn_Pn FROM STUDENTS")

    i := 0
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()
    for rows.Next() {
        i++
        err := rows.Scan(&p.FirstName)
        log.Print(p.FirstName.String)
        log.Printf(strconv.Itoa(i))
        if err != nil {
            log.Fatal(err)
        }
    }
    err = rows.Err()
    if err != nil {
        log.Fatal(err)
    }

    s.ID = 34114
    s.Details = p

    return s, err
}

我将结果读入以下 struct 中:

import (
    "database/sql"

    u "sydney.edu.au/bric9018/cet.api/util"
)

type PersonalDetails struct {

    // Unique identifier for person
    ID int32 `json:"id,omitempty"`

    // First name of person
    FirstName sql.NullString `json:"firstName,omitempty"`

    // Last name of person.
    LastName sql.NullString `json:"lastName,omitempty"`

    // Person nominated preferrered name.
    PreferredName sql.NullString `json:"preferredName,omitempty"`

    // Person's SSO username for University systems
    Unikey sql.NullString `json:"unikey,omitempty"`

    // Person's personal email
    PersonalEmail sql.NullString `json:"personalEmail,omitempty"`

    // Sydney University email
    UniEmail sql.NullString `json:"uniEmail,omitempty"`

    // Person's date of birth
    Dob u.NullTime `json:"dob,omitempty"`
}

然而,当我使用 log.Print(p.FirstName.String) 打印扫描到模型中的值时,我得到完全空白的行。似乎没有任何值被读取到我的 struct 中。为什么会这样?

附注:当我在 SQL Server 中通过链接服务器连接到 FileMaker DB 并运行查询时,查询确实返回值。

英文:

I am trying to connect a Go REST API to a backend FileMaker based database over ODBC.

I have successfully installed the FileMaker ODBC drivers on Windows and the DSN is working.

I am using the mgodbc package in Go to connect to the DB.

However, while the connection works (no runtime error), I just get blank/null records back when I run a query. I have the following code to create a DB connection:

func NewDB(dataSourceName string) (*DB, error) {

	db, err := sql.Open("mgodbc", dataSourceName)
	if err != nil {
		return nil, err
	}
	if err = db.Ping(); err != nil {
		return nil, err
	}

	// TEST

	return &DB{db}, nil
}

This gets called from my main method as follows: db, err := md.NewDB("DSN=cet_registrations2;Uid=*****;Pwd=*****;"). I then call one of my query methods and try to read it into a model struct. I have simplified my query to make it easier:

func (db *DB) GetStudent(id int) (*Student, error) {

	s := new(Student)
	p := new(PersonalDetails)

	log.Println(id)

	rows, err := db.Query("SELECT FN_Gn_Pn FROM STUDENTS")

	i := 0
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	for rows.Next() {
		i++
		err := rows.Scan(&p.FirstName)
		log.Print(p.FirstName.String)
		log.Printf(strconv.Itoa(i))
		if err != nil {
			log.Fatal(err)
		}
	}
	err = rows.Err()
	if err != nil {
		log.Fatal(err)
	}

	s.ID = 34114
	s.Details = p

	return s, err
}

and I am reading into the following struct:

import (
	"database/sql"

	u "sydney.edu.au/bric9018/cet.api/util"
)

type PersonalDetails struct {

	// Unique identifier for person
	ID int32 `json:"id,omitempty"`

	// First name of person
	FirstName sql.NullString `json:"firstName,omitempty"`

	// Last name of person.
	LastName sql.NullString `json:"lastName,omitempty"`

	// Person nominated preferrered name.
	PreferredName sql.NullString `json:"preferredName,omitempty"`

	// Person's SSO username for University systems
	Unikey sql.NullString `json:"unikey,omitempty"`

	// Person's personal email
	PersonalEmail sql.NullString `json:"personalEmail,omitempty"`

	// Sydney University email
	UniEmail sql.NullString `json:"uniEmail,omitempty"`

	// Person's date of birth
	Dob u.NullTime `json:"dob,omitempty"`
}

However, I just get completely blank rows when I print the value scanned into the model using log.Print(p.FirstName.String). I don't seem to be getting any values read back by scan into my struct. Why is this?

P.S. the query definitely returns values when I run it in SQL Server over a linked server connection against the FileMaker DB.

答案1

得分: 1

Golang的ODBC驱动是系统ODBC驱动(odbc32.dll, unixODBC等)的包装器。如果在SQL Server中执行查询时得到任何结果,那么可以排除查询错误或系统驱动问题的可能性。那么问题可能出在Golang的驱动程序(mgodbc)方面。可能的问题包括:

  1. 由于数据类型不匹配/不支持(例如,将字符串存储为二进制等),驱动程序无法转换查询结果。因此,首先尝试将结果扫描到[]byte
  2. 由于错误,驱动程序无法转换查询结果。尝试使用另一个ODBC驱动程序

由于我们无法访问相关数据库,因此无法重现问题。要了解问题所在,请使用调试器。我个人使用Visual Studio Code。要设置调试器,请参考VS Code和Delve调试器

我猜测问题存在于mgodbc的Next函数(第781-1011行)。odbcNext函数的实现在这里(第35行)。该函数依赖于column.Value函数(第116-165行)来转换查询结果。使用调试器,您可以观察变量、表达式,并比较这些驱动程序如何处理查询结果的转换。

英文:

Golang odbc driver is a wrapper of system's odbc driver (odbc32.dll, unixODBC, etc). If you got any result when executing the query in SQL Server, it eliminates the probability of query error or system's driver problem. Then the problem will be in golang's driver (mgodbc) side. Possible issues:

  1. The driver failed to convert query result due to mismatch/unsupported data type (e.g. you store the string in the database table as binary, etc). So the first try was scan the result to []byte.
  2. The driver failed to convert query result due to bug. Try using another odbc driver.

Because the database in question is not available to us, its impossible for us to reproduce the problem. To learn what was the problem, please use debugger. Personally I'm using Visual Studio Code. To setup the debugger, please refer to VS Code and delve debugger.

My guess, the problem exist in mgodbc's Next function (line number 781-1011). The odbc's implementation of Next function is available here (line 35). The function relies on column.Value function (line 116-165) to convert the query result. Using debugger, you can observe variable(s), expression(s) and compare how these drivers handle query result conversion.

huangapple
  • 本文由 发表于 2017年4月26日 13:14:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/43625560.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定