2017-03-31 00:03:13 +00:00
|
|
|
package mssql
|
|
|
|
|
|
|
|
import (
|
2018-07-06 16:09:34 +00:00
|
|
|
"context"
|
2017-03-31 00:03:13 +00:00
|
|
|
"database/sql/driver"
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
type copyin struct {
|
2018-07-06 16:09:34 +00:00
|
|
|
cn *Conn
|
|
|
|
bulkcopy *Bulk
|
2017-03-31 00:03:13 +00:00
|
|
|
closed bool
|
|
|
|
}
|
|
|
|
|
2018-07-06 16:09:34 +00:00
|
|
|
type serializableBulkConfig struct {
|
2017-03-31 00:03:13 +00:00
|
|
|
TableName string
|
|
|
|
ColumnsName []string
|
2018-07-06 16:09:34 +00:00
|
|
|
Options BulkOptions
|
2017-03-31 00:03:13 +00:00
|
|
|
}
|
|
|
|
|
2018-07-06 16:09:34 +00:00
|
|
|
func (d *Driver) OpenConnection(dsn string) (*Conn, error) {
|
|
|
|
return d.open(context.Background(), dsn)
|
2017-03-31 00:03:13 +00:00
|
|
|
}
|
|
|
|
|
2018-07-06 16:09:34 +00:00
|
|
|
func (c *Conn) prepareCopyIn(ctx context.Context, query string) (_ driver.Stmt, err error) {
|
2017-03-31 00:03:13 +00:00
|
|
|
config_json := query[11:]
|
|
|
|
|
2018-07-06 16:09:34 +00:00
|
|
|
bulkconfig := serializableBulkConfig{}
|
2017-03-31 00:03:13 +00:00
|
|
|
err = json.Unmarshal([]byte(config_json), &bulkconfig)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-07-06 16:09:34 +00:00
|
|
|
bulkcopy := c.CreateBulkContext(ctx, bulkconfig.TableName, bulkconfig.ColumnsName)
|
2017-03-31 00:03:13 +00:00
|
|
|
bulkcopy.Options = bulkconfig.Options
|
|
|
|
|
|
|
|
ci := ©in{
|
|
|
|
cn: c,
|
|
|
|
bulkcopy: bulkcopy,
|
|
|
|
}
|
|
|
|
|
|
|
|
return ci, nil
|
|
|
|
}
|
|
|
|
|
2018-07-06 16:09:34 +00:00
|
|
|
func CopyIn(table string, options BulkOptions, columns ...string) string {
|
|
|
|
bulkconfig := &serializableBulkConfig{TableName: table, Options: options, ColumnsName: columns}
|
2017-03-31 00:03:13 +00:00
|
|
|
|
|
|
|
config_json, err := json.Marshal(bulkconfig)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stmt := "INSERTBULK " + string(config_json)
|
|
|
|
|
|
|
|
return stmt
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *copyin) NumInput() int {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *copyin) Query(v []driver.Value) (r driver.Rows, err error) {
|
2018-07-06 16:09:34 +00:00
|
|
|
panic("should never be called")
|
2017-03-31 00:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) {
|
|
|
|
if ci.closed {
|
2018-10-15 21:36:55 +00:00
|
|
|
return nil, errors.New("copyin query is closed")
|
2017-03-31 00:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(v) == 0 {
|
|
|
|
rowCount, err := ci.bulkcopy.Done()
|
|
|
|
ci.closed = true
|
|
|
|
return driver.RowsAffected(rowCount), err
|
|
|
|
}
|
|
|
|
|
|
|
|
t := make([]interface{}, len(v))
|
|
|
|
for i, val := range v {
|
|
|
|
t[i] = val
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ci.bulkcopy.AddRow(t)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return driver.RowsAffected(0), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *copyin) Close() (err error) {
|
|
|
|
return nil
|
|
|
|
}
|