本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
5.2KB

  1. // +build go1.9
  2. package mssql
  3. import (
  4. "database/sql"
  5. "database/sql/driver"
  6. "errors"
  7. "fmt"
  8. "reflect"
  9. "time"
  10. // "github.com/cockroachdb/apd"
  11. "github.com/golang-sql/civil"
  12. )
  13. // Type alias provided for compatibility.
  14. type MssqlDriver = Driver // Deprecated: users should transition to the new name when possible.
  15. type MssqlBulk = Bulk // Deprecated: users should transition to the new name when possible.
  16. type MssqlBulkOptions = BulkOptions // Deprecated: users should transition to the new name when possible.
  17. type MssqlConn = Conn // Deprecated: users should transition to the new name when possible.
  18. type MssqlResult = Result // Deprecated: users should transition to the new name when possible.
  19. type MssqlRows = Rows // Deprecated: users should transition to the new name when possible.
  20. type MssqlStmt = Stmt // Deprecated: users should transition to the new name when possible.
  21. var _ driver.NamedValueChecker = &Conn{}
  22. // VarChar parameter types.
  23. type VarChar string
  24. type NVarCharMax string
  25. type VarCharMax string
  26. // DateTime1 encodes parameters to original DateTime SQL types.
  27. type DateTime1 time.Time
  28. // DateTimeOffset encodes parameters to DateTimeOffset, preserving the UTC offset.
  29. type DateTimeOffset time.Time
  30. func convertInputParameter(val interface{}) (interface{}, error) {
  31. switch v := val.(type) {
  32. case VarChar:
  33. return val, nil
  34. case NVarCharMax:
  35. return val, nil
  36. case VarCharMax:
  37. return val, nil
  38. case DateTime1:
  39. return val, nil
  40. case DateTimeOffset:
  41. return val, nil
  42. case civil.Date:
  43. return val, nil
  44. case civil.DateTime:
  45. return val, nil
  46. case civil.Time:
  47. return val, nil
  48. // case *apd.Decimal:
  49. // return nil
  50. default:
  51. return driver.DefaultParameterConverter.ConvertValue(v)
  52. }
  53. }
  54. func (c *Conn) CheckNamedValue(nv *driver.NamedValue) error {
  55. switch v := nv.Value.(type) {
  56. case sql.Out:
  57. if c.outs == nil {
  58. c.outs = make(map[string]interface{})
  59. }
  60. c.outs[nv.Name] = v.Dest
  61. if v.Dest == nil {
  62. return errors.New("destination is a nil pointer")
  63. }
  64. dest_info := reflect.ValueOf(v.Dest)
  65. if dest_info.Kind() != reflect.Ptr {
  66. return errors.New("destination not a pointer")
  67. }
  68. if dest_info.IsNil() {
  69. return errors.New("destination is a nil pointer")
  70. }
  71. pointed_value := reflect.Indirect(dest_info)
  72. // don't allow pointer to a pointer, only pointer to a value can be handled
  73. // correctly
  74. if pointed_value.Kind() == reflect.Ptr {
  75. return errors.New("destination is a pointer to a pointer")
  76. }
  77. // Unwrap the Out value and check the inner value.
  78. val := pointed_value.Interface()
  79. if val == nil {
  80. return errors.New("MSSQL does not allow NULL value without type for OUTPUT parameters")
  81. }
  82. conv, err := convertInputParameter(val)
  83. if err != nil {
  84. return err
  85. }
  86. if conv == nil {
  87. // if we replace with nil we would lose type information
  88. nv.Value = sql.Out{Dest: val}
  89. } else {
  90. nv.Value = sql.Out{Dest: conv}
  91. }
  92. return nil
  93. case *ReturnStatus:
  94. *v = 0 // By default the return value should be zero.
  95. c.returnStatus = v
  96. return driver.ErrRemoveArgument
  97. case TVP:
  98. return nil
  99. default:
  100. var err error
  101. nv.Value, err = convertInputParameter(nv.Value)
  102. return err
  103. }
  104. }
  105. func (s *Stmt) makeParamExtra(val driver.Value) (res param, err error) {
  106. switch val := val.(type) {
  107. case VarChar:
  108. res.ti.TypeId = typeBigVarChar
  109. res.buffer = []byte(val)
  110. res.ti.Size = len(res.buffer)
  111. case VarCharMax:
  112. res.ti.TypeId = typeBigVarChar
  113. res.buffer = []byte(val)
  114. res.ti.Size = 0 // currently zero forces varchar(max)
  115. case NVarCharMax:
  116. res.ti.TypeId = typeNVarChar
  117. res.buffer = str2ucs2(string(val))
  118. res.ti.Size = 0 // currently zero forces nvarchar(max)
  119. case DateTime1:
  120. t := time.Time(val)
  121. res.ti.TypeId = typeDateTimeN
  122. res.buffer = encodeDateTime(t)
  123. res.ti.Size = len(res.buffer)
  124. case DateTimeOffset:
  125. res.ti.TypeId = typeDateTimeOffsetN
  126. res.ti.Scale = 7
  127. res.buffer = encodeDateTimeOffset(time.Time(val), int(res.ti.Scale))
  128. res.ti.Size = len(res.buffer)
  129. case civil.Date:
  130. res.ti.TypeId = typeDateN
  131. res.buffer = encodeDate(val.In(time.UTC))
  132. res.ti.Size = len(res.buffer)
  133. case civil.DateTime:
  134. res.ti.TypeId = typeDateTime2N
  135. res.ti.Scale = 7
  136. res.buffer = encodeDateTime2(val.In(time.UTC), int(res.ti.Scale))
  137. res.ti.Size = len(res.buffer)
  138. case civil.Time:
  139. res.ti.TypeId = typeTimeN
  140. res.ti.Scale = 7
  141. res.buffer = encodeTime(val.Hour, val.Minute, val.Second, val.Nanosecond, int(res.ti.Scale))
  142. res.ti.Size = len(res.buffer)
  143. case sql.Out:
  144. res, err = s.makeParam(val.Dest)
  145. res.Flags = fByRevValue
  146. case TVP:
  147. err = val.check()
  148. if err != nil {
  149. return
  150. }
  151. schema, name, errGetName := getSchemeAndName(val.TypeName)
  152. if errGetName != nil {
  153. return
  154. }
  155. res.ti.UdtInfo.TypeName = name
  156. res.ti.UdtInfo.SchemaName = schema
  157. res.ti.TypeId = typeTvp
  158. columnStr, tvpFieldIndexes, errCalTypes := val.columnTypes()
  159. if errCalTypes != nil {
  160. err = errCalTypes
  161. return
  162. }
  163. res.buffer, err = val.encode(schema, name, columnStr, tvpFieldIndexes)
  164. if err != nil {
  165. return
  166. }
  167. res.ti.Size = len(res.buffer)
  168. default:
  169. err = fmt.Errorf("mssql: unknown type for %T", val)
  170. }
  171. return
  172. }
  173. func scanIntoOut(name string, fromServer, scanInto interface{}) error {
  174. return convertAssign(scanInto, fromServer)
  175. }
上海开阖软件有限公司 沪ICP备12045867号-1