diff options
Diffstat (limited to 'vendor/github.com/denisenkom/go-mssqldb/bulkcopy.go')
-rw-r--r-- | vendor/github.com/denisenkom/go-mssqldb/bulkcopy.go | 117 |
1 files changed, 73 insertions, 44 deletions
diff --git a/vendor/github.com/denisenkom/go-mssqldb/bulkcopy.go b/vendor/github.com/denisenkom/go-mssqldb/bulkcopy.go index 3b319af893..1d5eacb381 100644 --- a/vendor/github.com/denisenkom/go-mssqldb/bulkcopy.go +++ b/vendor/github.com/denisenkom/go-mssqldb/bulkcopy.go @@ -7,9 +7,10 @@ import ( "fmt" "math" "reflect" - "strconv" "strings" "time" + + "github.com/denisenkom/go-mssqldb/internal/decimal" ) type Bulk struct { @@ -42,6 +43,11 @@ type BulkOptions struct { type DataValue interface{} +const ( + sqlDateFormat = "2006-01-02" + sqlTimeFormat = "2006-01-02 15:04:05.999999999Z07:00" +) + func (cn *Conn) CreateBulk(table string, columns []string) (_ *Bulk) { b := Bulk{ctx: context.Background(), cn: cn, tablename: table, headerSent: false, columnsName: columns} b.Debug = false @@ -334,7 +340,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) case int64: intvalue = val default: - err = fmt.Errorf("mssql: invalid type for int column") + err = fmt.Errorf("mssql: invalid type for int column: %T", val) return } @@ -361,7 +367,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) case int64: floatvalue = float64(val) default: - err = fmt.Errorf("mssql: invalid type for float column: %s", val) + err = fmt.Errorf("mssql: invalid type for float column: %T %s", val, val) return } @@ -380,7 +386,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) case []byte: res.buffer = val default: - err = fmt.Errorf("mssql: invalid type for nvarchar column: %s", val) + err = fmt.Errorf("mssql: invalid type for nvarchar column: %T %s", val, val) return } res.ti.Size = len(res.buffer) @@ -392,14 +398,14 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) case []byte: res.buffer = val default: - err = fmt.Errorf("mssql: invalid type for varchar column: %s", val) + err = fmt.Errorf("mssql: invalid type for varchar column: %T %s", val, val) return } res.ti.Size = len(res.buffer) case typeBit, typeBitN: if reflect.TypeOf(val).Kind() != reflect.Bool { - err = fmt.Errorf("mssql: invalid type for bit column: %s", val) + err = fmt.Errorf("mssql: invalid type for bit column: %T %s", val, val) return } res.ti.TypeId = typeBitN @@ -413,18 +419,31 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) case time.Time: res.buffer = encodeDateTime2(val, int(col.ti.Scale)) res.ti.Size = len(res.buffer) + case string: + var t time.Time + if t, err = time.Parse(sqlTimeFormat, val); err != nil { + return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) + } + res.buffer = encodeDateTime2(t, int(col.ti.Scale)) + res.ti.Size = len(res.buffer) default: - err = fmt.Errorf("mssql: invalid type for datetime2 column: %s", val) + err = fmt.Errorf("mssql: invalid type for datetime2 column: %T %s", val, val) return } case typeDateTimeOffsetN: switch val := val.(type) { case time.Time: - res.buffer = encodeDateTimeOffset(val, int(res.ti.Scale)) + res.buffer = encodeDateTimeOffset(val, int(col.ti.Scale)) + res.ti.Size = len(res.buffer) + case string: + var t time.Time + if t, err = time.Parse(sqlTimeFormat, val); err != nil { + return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) + } + res.buffer = encodeDateTimeOffset(t, int(col.ti.Scale)) res.ti.Size = len(res.buffer) - default: - err = fmt.Errorf("mssql: invalid type for datetimeoffset column: %s", val) + err = fmt.Errorf("mssql: invalid type for datetimeoffset column: %T %s", val, val) return } case typeDateN: @@ -432,69 +451,79 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) case time.Time: res.buffer = encodeDate(val) res.ti.Size = len(res.buffer) + case string: + var t time.Time + if t, err = time.ParseInLocation(sqlDateFormat, val, time.UTC); err != nil { + return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) + } + res.buffer = encodeDate(t) + res.ti.Size = len(res.buffer) default: - err = fmt.Errorf("mssql: invalid type for date column: %s", val) + err = fmt.Errorf("mssql: invalid type for date column: %T %s", val, val) return } case typeDateTime, typeDateTimeN, typeDateTim4: + var t time.Time switch val := val.(type) { case time.Time: - if col.ti.Size == 4 { - res.buffer = encodeDateTim4(val) - res.ti.Size = len(res.buffer) - } else if col.ti.Size == 8 { - res.buffer = encodeDateTime(val) - res.ti.Size = len(res.buffer) - } else { - err = fmt.Errorf("mssql: invalid size of column") + t = val + case string: + if t, err = time.Parse(sqlTimeFormat, val); err != nil { + return res, fmt.Errorf("bulk: unable to convert string to date: %v", err) } - default: - err = fmt.Errorf("mssql: invalid type for datetime column: %s", val) + err = fmt.Errorf("mssql: invalid type for datetime column: %T %s", val, val) + return + } + + if col.ti.Size == 4 { + res.buffer = encodeDateTim4(t) + res.ti.Size = len(res.buffer) + } else if col.ti.Size == 8 { + res.buffer = encodeDateTime(t) + res.ti.Size = len(res.buffer) + } else { + err = fmt.Errorf("mssql: invalid size of column %d", col.ti.Size) } // case typeMoney, typeMoney4, typeMoneyN: case typeDecimal, typeDecimalN, typeNumeric, typeNumericN: - var value float64 + prec := col.ti.Prec + scale := col.ti.Scale + var dec decimal.Decimal switch v := val.(type) { case int: - value = float64(v) + dec = decimal.Int64ToDecimalScale(int64(v), 0) case int8: - value = float64(v) + dec = decimal.Int64ToDecimalScale(int64(v), 0) case int16: - value = float64(v) + dec = decimal.Int64ToDecimalScale(int64(v), 0) case int32: - value = float64(v) + dec = decimal.Int64ToDecimalScale(int64(v), 0) case int64: - value = float64(v) + dec = decimal.Int64ToDecimalScale(int64(v), 0) case float32: - value = float64(v) + dec, err = decimal.Float64ToDecimalScale(float64(v), scale) case float64: - value = v + dec, err = decimal.Float64ToDecimalScale(float64(v), scale) case string: - if value, err = strconv.ParseFloat(v, 64); err != nil { - return res, fmt.Errorf("bulk: unable to convert string to float: %v", err) - } + dec, err = decimal.StringToDecimalScale(v, scale) default: - return res, fmt.Errorf("unknown value for decimal: %#v", v) + return res, fmt.Errorf("unknown value for decimal: %T %#v", v, v) } - perc := col.ti.Prec - scale := col.ti.Scale - var dec Decimal - dec, err = Float64ToDecimalScale(value, scale) if err != nil { return res, err } - dec.prec = perc + dec.SetPrec(prec) var length byte switch { - case perc <= 9: + case prec <= 9: length = 4 - case perc <= 19: + case prec <= 19: length = 8 - case perc <= 28: + case prec <= 28: length = 12 default: length = 16 @@ -504,7 +533,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) // first byte length written by typeInfo.writer res.ti.Size = int(length) + 1 // second byte sign - if value < 0 { + if !dec.IsPositive() { buf[0] = 0 } else { buf[0] = 1 @@ -527,7 +556,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) res.ti.Size = len(val) res.buffer = val default: - err = fmt.Errorf("mssql: invalid type for Binary column: %s", val) + err = fmt.Errorf("mssql: invalid type for Binary column: %T %s", val, val) return } case typeGuid: @@ -536,7 +565,7 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error) res.ti.Size = len(val) res.buffer = val default: - err = fmt.Errorf("mssql: invalid type for Guid column: %s", val) + err = fmt.Errorf("mssql: invalid type for Guid column: %T %s", val, val) return } |