为什么sqlx的copyin语句挂起?

时间:2016-11-02 11:51:00

标签: postgresql go sqlx

我写了一个玩具应用程序来试验通过sqlx使用Postgresql。我使用

进行了大量插入工作
pq.CopyIn

作为预备陈述的内容

stmt, _ := tx.Preparex(pq.CopyIn(tablename, column, column, ...)

然后我会继续向我正在创建的大量插入添加行。

tx.Exec(..., ..., ...)

然后最终执行准备好的声明

stmt.Exec()

这之前完美无缺,但现在我回到它并尝试执行此代码,它挂在

stmt.Exec

我在代码中遗漏了什么,或者这与数据库引擎有关,没有响应。

这是我的完整代码。

package main

import (
    _ "database/sql"
    "fmt"
    "log"
    "encoding/json"
    "io/ioutil"
    "os"

    "github.com/jmoiron/sqlx"
    "github.com/lib/pq"
)

var schema = `
    CREATE TABLE IF NOT EXISTS contact (
        id Serial,
        first_name text,
        last_name text,
        email text
);`

type Contact struct {
    Id int            `json:"-"`
    First_name string `json:"first_name"`
    Last_name string  `json:"last_name"`
    Email string      `json:"email"`
}

type Contacts struct {
    Contacts []Contact `json:"contacts"`
}

func (c *Contacts) createFromJSON(json_str []byte) error {
    b := []byte(json_str)
    err := json.Unmarshal(b, &c)
    if err != nil {
        log.Fatal(err)
    }

    return err
}

func (c *Contacts) save(db *sqlx.DB) error {
    tx := db.MustBegin()

    stmt, _ := tx.Preparex(pq.CopyIn("contact", "first_name", "last_name", "email"))

    for _, contact := range c.Contacts {
        tx.Exec(contact.First_name, contact.Last_name, contact.Email)

    }

    _, err := stmt.Exec()

    if err != nil {
        log.Fatal(err)
        return err
    }
    err = stmt.Close()
    if err != nil {
        log.Fatal(err)
        return err
    }

    tx.Commit()

    return nil
}

func connect() (*sqlx.DB, error) {
    db, err := sqlx.Connect("postgres", "user=pqgotest dbname=pqgotest sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }

    return db, err
}


func createTables(db *sqlx.DB) {
    db.MustExec(schema)
}


func main() {
    db, err := connect()
    if err != nil {
        os.Exit(1)
    }

    createTables(db)
    contactsJson, e := ioutil.ReadFile("./contacts.json")
    if e != nil {
        fmt.Printf("File error: %v\n", e)
        os.Exit(1)
    }

    tx := db.MustBegin()
    tx.MustExec("DELETE FROM contact")
    tx.Commit()

    contacts := new(Contacts)

    contacts.createFromJSON(contactsJson)

    contacts.save(db)

    people := new(Contacts)
    db.Select(people.Contacts, "SELECT * FROM contact ORDER BY email,id ASC")

    for _, contact := range people.Contacts {
        contact_json, err := json.Marshal(contact)
        if err != nil {
            log.Fatal(err)
            os.Exit(1)
        }
        fmt.Printf("%s\n", contact_json)
    }


}

我也可以包含contacts.json文件的内容,如果有帮助的话。

更新

是的,最终显而易见。我是从tx创建一个声明,

stmt, _ := tx.Preparex(pq.CopyIn(tablename, column, column, ...)

并且对此进一步增加应该是stmt

stmt.Exec(..., ..., ...)

另一个与问题没有直接关系的错误是我将一组联系人插入struct Contacts的Contacts字段中

people := new(Contacts)
db.Select(people.Contacts, "SELECT * FROM contact ORDER BY email,id ASC")

应该将指针传递给Contacts的Contacts数组字段的db的Select方法,如此

db.Select(&people.Contacts, "SELECT * FROM contact ORDER BY email,id ASC")

如果人们稍后尝试运行此代码,并想知道为什么它不会将结果打印到控制台。

1 个答案:

答案 0 :(得分:1)

https://godoc.org/github.com/lib/pq中的批量导入部分,它应该是

stmt.Exec(contact.First_name, contact.Last_name, contact.Email)