convert.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. package DB
  2. import (
  3. "TsDB2/DB/core/types"
  4. "encoding/binary"
  5. "fmt"
  6. "math/big"
  7. "reflect"
  8. )
  9. // structToFieldValues 将结构体转换为 core.InsertRow 所需的 FieldValue 切片
  10. // activeColumns 为当前 DB schema 活跃列集合,只发送交集内的字段
  11. func structToFieldValues(obj interface{}, model *ModelInfo, activeColumns map[string]bool) ([]types.FieldValue, error) {
  12. v := reflect.ValueOf(obj)
  13. if v.Kind() == reflect.Ptr {
  14. v = v.Elem()
  15. }
  16. if v.Kind() != reflect.Struct {
  17. return nil, fmt.Errorf("vrtx: expected struct, got %s", v.Kind())
  18. }
  19. result := make([]types.FieldValue, 0, len(model.AllFields))
  20. for _, fd := range model.AllFields {
  21. // 跳过不在当前 DB schema 中的字段 (如已删除列、或 struct 有但 DB 没有)
  22. if activeColumns != nil && !activeColumns[fd.ColName] {
  23. continue
  24. }
  25. fv := findField(v, fd.Name, model.StructType)
  26. if !fv.IsValid() {
  27. // 字段不在结构体中 (如自动添加的 _id),用零值填充
  28. result = append(result, types.FieldValue{
  29. FieldName: []byte(fd.ColName),
  30. Value: zeroValue(fd),
  31. })
  32. continue
  33. }
  34. // 指针/接口字段为 nil, 且该列声明了 nullable → 显式 NULL。
  35. // 不做这一步的话, 接口里装的是"类型化 nil" (*T)(nil): core 侧的 `value == nil`
  36. // 判不出来, 会被当成零值写进去 —— "可空列永远存不出 NULL", 唯一约束的 NULL
  37. // 免除也就无从生效。只认指针/接口: nil 切片是"空值"而不是 NULL (空 blob 的
  38. // 既有语义必须保持), 非可空列则继续走"nil 当零值"的老路。
  39. if fd.Flag&types.FlagNullable != 0 && isNilPointerValue(fv) {
  40. result = append(result, types.FieldValue{
  41. FieldName: []byte(fd.ColName),
  42. Value: nil,
  43. })
  44. continue
  45. }
  46. val := normalizeValue(fv, fd)
  47. result = append(result, types.FieldValue{
  48. FieldName: []byte(fd.ColName),
  49. Value: val,
  50. })
  51. }
  52. return result, nil
  53. }
  54. // fieldValuesToStruct 将 core 查询结果的 FieldValue 切片反序列化到结构体
  55. func fieldValuesToStruct(fvs []types.FieldValue, model *ModelInfo, obj interface{}) error {
  56. v := reflect.ValueOf(obj)
  57. if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
  58. return fmt.Errorf("vrtx: obj must be a pointer to struct")
  59. }
  60. v = v.Elem()
  61. // 建立列名 → FieldValue 映射
  62. colMap := make(map[string]types.FieldValue, len(fvs))
  63. for _, fv := range fvs {
  64. colMap[string(fv.FieldName)] = fv
  65. }
  66. for _, fd := range model.AllFields {
  67. fv, ok := colMap[fd.ColName]
  68. if !ok {
  69. continue
  70. }
  71. target := findSettableField(v, fd.Name, model.StructType)
  72. if !target.IsValid() || !target.CanSet() {
  73. continue
  74. }
  75. if err := setFieldFromValue(target, fv.Value, fd); err != nil {
  76. return fmt.Errorf("vrtx: set field %s: %w", fd.Name, err)
  77. }
  78. }
  79. return nil
  80. }
  81. // findField 在结构体中查找字段 (支持嵌入结构体)
  82. func findField(v reflect.Value, name string, t reflect.Type) reflect.Value {
  83. // 直接查找
  84. if f := v.FieldByName(name); f.IsValid() {
  85. return f
  86. }
  87. // 在嵌入结构体中查找
  88. for i := 0; i < t.NumField(); i++ {
  89. sf := t.Field(i)
  90. if sf.Anonymous {
  91. fv := v.Field(i)
  92. if sf.Type == baseModelType || sf.Type == timeSeriesModelType {
  93. if inner := fv.FieldByName(name); inner.IsValid() {
  94. return inner
  95. }
  96. } else if sf.Type.Kind() == reflect.Struct {
  97. if inner := findField(fv, name, sf.Type); inner.IsValid() {
  98. return inner
  99. }
  100. }
  101. }
  102. }
  103. return reflect.Value{}
  104. }
  105. // findSettableField 同 findField 但确保返回可设置的字段
  106. func findSettableField(v reflect.Value, name string, t reflect.Type) reflect.Value {
  107. return findField(v, name, t)
  108. }
  109. // normalizeValue 将反射字段值转换为 core 可接受的值
  110. func normalizeValue(fv reflect.Value, fd FieldDef) interface{} {
  111. iface := fv.Interface()
  112. // 指针载体解一层: 可空列用 `*T` 表达 (nil 已在上层被转成显式 NULL, 走不到这里),
  113. // 非 nil 的指针要按 T 的值走下面的转换。不解这一层的话, *int64 会被 toUint64 的
  114. // "既不能 CanUint 也不能 CanInt" 分支静默变成 0 —— 可空列看着能写, 写进去全是零。
  115. //
  116. // 只给下面这些"由 normalizeValue 定值"的列型解引用; 扩展类型那组是"原样下传",
  117. // 其中 Int128 的载体本来就是 *big.Int (core 按指针识别), 绝不能解开。
  118. carrier := iface
  119. if fv.Kind() == reflect.Ptr && !fv.IsNil() {
  120. carrier = fv.Elem().Interface()
  121. }
  122. switch fd.FieldType {
  123. case types.FieldType_1byte:
  124. return uint8(toUint64(carrier))
  125. case types.FieldType_2byte:
  126. return toInt16(carrier)
  127. case types.FieldType_4byte:
  128. return toInt32(carrier)
  129. case types.FieldType_8byte:
  130. return toUint64(carrier)
  131. case types.FieldType_Int8:
  132. return toInt8(carrier)
  133. case types.FieldType_Int16:
  134. return toInt16(carrier)
  135. case types.FieldType_Int32:
  136. return toInt32(carrier)
  137. case types.FieldType_Int64:
  138. return toInt64(carrier)
  139. case types.FieldType_Float64:
  140. return toFloatVal(carrier)
  141. case types.FieldType_16byte, types.FieldType_32byte,
  142. types.FieldType_64byte, types.FieldType_128byte, types.FieldType_256byte:
  143. // 字符串 / []byte 载体【原样下传】: 补零与"超宽报错"都由 types.EncodeValue
  144. // 按列的实际宽度完成 —— 宽度只有一个权威来源 (见 FieldDef.Width)。
  145. //
  146. // 旧实现先在这里 toFixedBytes 一次, 而那个函数是 copy 进定长缓冲: 超宽部分被
  147. // 静默丢掉。`maxlen:10` 的列写 20 字节会成功落库并少掉一半内容, 调用方拿不到
  148. // 任何信号 —— 这正是列宽闸门要拦的事, 拦在 ORM 就会绕过它。
  149. switch carrier.(type) {
  150. case string, []byte:
  151. return carrier
  152. }
  153. // 数值载体 (16byte 兼作裸字节列的旧用法) 仍按列宽做 BigEndian 编码
  154. return toFixedBytes(carrier, int(fd.Width()))
  155. case types.FieldType_Dynamicbyte, types.FieldType_Blob:
  156. // 动态列必须送 []byte: 引擎侧对动态列只做 `value.([]byte)` 断言,
  157. // 送 string / 数值会在那里被明确拒绝 (见 core.writeFieldValueAt)。
  158. return toBytes(carrier)
  159. // ===== 扩展类型 =====
  160. //
  161. // 这几类一律"原样下传", 由 core 的 types.EncodeValue 做规范化与校验 ——
  162. // 它才是唯一知道列级参数 (Decimal 的 scale) 的地方。这里若先做一次宽松转换,
  163. // 反而会把"不能精确表示"的值悄悄变成另一个值 (例如 float64→float32 截断)。
  164. case types.FieldType_Bool:
  165. return iface
  166. case types.FieldType_Float32:
  167. return iface
  168. case types.FieldType_Decimal:
  169. return iface
  170. case types.FieldType_UUID:
  171. return iface
  172. case types.FieldType_Year:
  173. return iface
  174. case types.FieldType_Int128:
  175. return iface
  176. default:
  177. return iface
  178. }
  179. }
  180. // setFieldFromValue 将 core 返回值设置到结构体字段
  181. func setFieldFromValue(target reflect.Value, val interface{}, fd FieldDef) error {
  182. if val == nil {
  183. return nil // NULL: 字段保持零值 (指针载体即 nil), 正是"没读到值"的表示
  184. }
  185. // 指针目标先落一层: 可空列的载体是 `*T`, 而解码值是 T —— 分配元素后往里写。
  186. // 集中在这里做, 下面那些 setXxxField 就不用各自认识指针 (它们只管元素类型)。
  187. if target.Kind() == reflect.Ptr {
  188. if target.IsNil() {
  189. target.Set(reflect.New(target.Type().Elem()))
  190. }
  191. target = target.Elem()
  192. }
  193. switch v := val.(type) {
  194. case uint64:
  195. setIntField(target, int64(v))
  196. case int64:
  197. setIntField(target, v)
  198. case int32:
  199. setIntField(target, int64(v))
  200. case int16:
  201. setIntField(target, int64(v))
  202. case int8:
  203. setIntField(target, int64(v))
  204. case uint8:
  205. setIntField(target, int64(v))
  206. case float64:
  207. setFloatField(target, v)
  208. case float32:
  209. setFloatField(target, float64(v))
  210. case bool:
  211. if target.Kind() == reflect.Bool {
  212. target.SetBool(v)
  213. }
  214. case []byte:
  215. setBytesField(target, v, fd)
  216. case types.Decimal:
  217. setDecimalField(target, v)
  218. case types.UUID:
  219. setUUIDField(target, v)
  220. case *big.Int:
  221. setBigIntField(target, v)
  222. default:
  223. // 尝试直接设置 (同类型), 或填进同元素类型的指针字段
  224. // (struct 里写 `*types.Decimal` / `*big.Int` 时, 解码值是值类型)。
  225. rv := reflect.ValueOf(val)
  226. if !rv.IsValid() {
  227. return nil
  228. }
  229. switch {
  230. case rv.Type().AssignableTo(target.Type()):
  231. target.Set(rv)
  232. case target.Kind() == reflect.Ptr && rv.Type().AssignableTo(target.Type().Elem()):
  233. p := reflect.New(target.Type().Elem())
  234. p.Elem().Set(rv)
  235. target.Set(p)
  236. }
  237. }
  238. return nil
  239. }
  240. // setDecimalField 把解码出来的 Decimal 落到结构体字段。
  241. // 只做【无损】转换: 目标是有符号/无符号整数时要求 scale 为 0, 否则不写 —— 由调用方
  242. // 决定是要 string 还是 float 载体, 而不是在这里悄悄舍入。
  243. func setDecimalField(target reflect.Value, d types.Decimal) {
  244. switch {
  245. case target.Type() == reflect.TypeOf(types.Decimal{}):
  246. target.Set(reflect.ValueOf(d))
  247. case target.Kind() == reflect.Ptr && target.Type().Elem() == reflect.TypeOf(types.Decimal{}):
  248. p := reflect.New(target.Type().Elem())
  249. p.Elem().Set(reflect.ValueOf(d))
  250. target.Set(p)
  251. case target.Kind() == reflect.String:
  252. target.SetString(d.String())
  253. case target.Kind() == reflect.Float32, target.Kind() == reflect.Float64:
  254. target.SetFloat(d.Float64())
  255. case d.Scale() == 0:
  256. coef := d.Coefficient()
  257. switch target.Kind() {
  258. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  259. if coef.IsInt64() {
  260. target.SetInt(coef.Int64())
  261. }
  262. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  263. if coef.IsUint64() {
  264. target.SetUint(coef.Uint64())
  265. }
  266. }
  267. }
  268. }
  269. // setUUIDField 把解码出来的 UUID 落到结构体字段 (UUID / string / [16]byte / []byte)。
  270. func setUUIDField(target reflect.Value, u types.UUID) {
  271. switch {
  272. case target.Type() == reflect.TypeOf(types.UUID{}):
  273. target.Set(reflect.ValueOf(u))
  274. case target.Kind() == reflect.Ptr && target.Type().Elem() == reflect.TypeOf(types.UUID{}):
  275. p := reflect.New(target.Type().Elem())
  276. p.Elem().Set(reflect.ValueOf(u))
  277. target.Set(p)
  278. case target.Kind() == reflect.String:
  279. target.SetString(u.String())
  280. case target.Kind() == reflect.Array && target.Len() == types.UUIDSize && target.Type().Elem().Kind() == reflect.Uint8:
  281. reflect.Copy(target, reflect.ValueOf(u[:]))
  282. case target.Kind() == reflect.Slice && target.Type().Elem().Kind() == reflect.Uint8:
  283. target.SetBytes(append([]byte(nil), u[:]...))
  284. }
  285. }
  286. // setBigIntField 把解码出来的 *big.Int 落到结构体字段 (big.Int / *big.Int / string / 整数)。
  287. func setBigIntField(target reflect.Value, v *big.Int) {
  288. if v == nil {
  289. v = new(big.Int)
  290. }
  291. switch {
  292. case target.Type() == reflect.TypeOf(big.Int{}):
  293. target.Set(reflect.ValueOf(*new(big.Int).Set(v)))
  294. case target.Type() == reflect.TypeOf(&big.Int{}):
  295. target.Set(reflect.ValueOf(new(big.Int).Set(v)))
  296. case target.Type() == reflect.TypeOf(types.Decimal{}):
  297. if d, err := types.NewDecimal(v, 0); err == nil {
  298. target.Set(reflect.ValueOf(d))
  299. }
  300. case target.Kind() == reflect.String:
  301. target.SetString(v.String())
  302. case target.Kind() == reflect.Int, target.Kind() == reflect.Int8,
  303. target.Kind() == reflect.Int16, target.Kind() == reflect.Int32, target.Kind() == reflect.Int64:
  304. if v.IsInt64() {
  305. target.SetInt(v.Int64())
  306. }
  307. case target.Kind() == reflect.Uint, target.Kind() == reflect.Uint8,
  308. target.Kind() == reflect.Uint16, target.Kind() == reflect.Uint32, target.Kind() == reflect.Uint64:
  309. if v.IsUint64() {
  310. target.SetUint(v.Uint64())
  311. }
  312. }
  313. }
  314. func setIntField(target reflect.Value, val int64) {
  315. switch target.Kind() {
  316. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  317. target.SetInt(val)
  318. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  319. target.SetUint(uint64(val))
  320. case reflect.Float32, reflect.Float64:
  321. target.SetFloat(float64(val))
  322. case reflect.Bool:
  323. target.SetBool(val != 0)
  324. }
  325. }
  326. func setFloatField(target reflect.Value, val float64) {
  327. switch target.Kind() {
  328. case reflect.Float32, reflect.Float64:
  329. target.SetFloat(val)
  330. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  331. target.SetInt(int64(val))
  332. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  333. target.SetUint(uint64(val))
  334. }
  335. }
  336. func setBytesField(target reflect.Value, val []byte, fd FieldDef) {
  337. switch target.Kind() {
  338. case reflect.String:
  339. // 截断到第一个 null 字节
  340. s := string(val)
  341. for i, c := range s {
  342. if c == 0 {
  343. s = s[:i]
  344. break
  345. }
  346. }
  347. target.SetString(s)
  348. case reflect.Slice:
  349. if target.Type().Elem().Kind() == reflect.Uint8 {
  350. target.SetBytes(val)
  351. }
  352. }
  353. }
  354. // ===== 类型转换辅助函数 =====
  355. // isNilPointerValue 判断反射值是否为 nil 指针 / nil 接口 (nil 切片不算 —— 空值 ≠ NULL)。
  356. func isNilPointerValue(v reflect.Value) bool {
  357. switch v.Kind() {
  358. case reflect.Ptr, reflect.Interface:
  359. return v.IsNil()
  360. }
  361. return false
  362. }
  363. func toUint64(v interface{}) uint64 {
  364. switch val := v.(type) {
  365. case uint64:
  366. return val
  367. case int64:
  368. return uint64(val)
  369. case int:
  370. return uint64(val)
  371. case int32:
  372. return uint64(val)
  373. case uint32:
  374. return uint64(val)
  375. case int16:
  376. return uint64(val)
  377. case uint16:
  378. return uint64(val)
  379. case int8:
  380. return uint64(val)
  381. case uint8:
  382. return uint64(val)
  383. case float64:
  384. return uint64(val)
  385. case float32:
  386. return uint64(val)
  387. case bool:
  388. if val {
  389. return 1
  390. }
  391. return 0
  392. default:
  393. rv := reflect.ValueOf(v)
  394. if rv.CanUint() {
  395. return rv.Uint()
  396. }
  397. if rv.CanInt() {
  398. return uint64(rv.Int())
  399. }
  400. return 0
  401. }
  402. }
  403. // toInt64 把任意数值/反射值转成 int64, 供有符号整数列 (FieldType_Int*) 使用。
  404. //
  405. // 不走 toUint64 再强转: 对负整数那条路是"绕一圈无符号", 靠低位截断侥幸正确;
  406. // 但对负浮点是未定义行为 (Go 规范: 负浮点转无符号数结果实现相关)。直接按有符号取,
  407. // 语义明确, 且 toInt8/16/32 也一并收敛到这里。
  408. func toInt64(v interface{}) int64 {
  409. switch val := v.(type) {
  410. case int64:
  411. return val
  412. case int:
  413. return int64(val)
  414. case int32:
  415. return int64(val)
  416. case int16:
  417. return int64(val)
  418. case int8:
  419. return int64(val)
  420. case uint64:
  421. return int64(val)
  422. case uint:
  423. return int64(val)
  424. case uint32:
  425. return int64(val)
  426. case uint16:
  427. return int64(val)
  428. case uint8:
  429. return int64(val)
  430. case float64:
  431. return int64(val)
  432. case float32:
  433. return int64(val)
  434. case bool:
  435. if val {
  436. return 1
  437. }
  438. return 0
  439. default:
  440. rv := reflect.ValueOf(v)
  441. if !rv.IsValid() {
  442. return 0
  443. }
  444. switch rv.Kind() {
  445. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  446. return rv.Int()
  447. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  448. return int64(rv.Uint())
  449. case reflect.Float32, reflect.Float64:
  450. return int64(rv.Float())
  451. case reflect.Bool:
  452. if rv.Bool() {
  453. return 1
  454. }
  455. }
  456. return 0
  457. }
  458. }
  459. func toInt8(v interface{}) int8 { return int8(toInt64(v)) }
  460. func toInt16(v interface{}) int16 { return int16(toInt64(v)) }
  461. func toInt32(v interface{}) int32 { return int32(toInt64(v)) }
  462. // toFloatVal 把任意数值/反射值转成 float64, 供浮点列写入使用。
  463. // 注意这里不能经由 toUint64: 那会把小数部分先砍掉, 正是要避免的截断。
  464. func toFloatVal(v interface{}) float64 {
  465. switch val := v.(type) {
  466. case float64:
  467. return val
  468. case float32:
  469. return float64(val)
  470. case int64:
  471. return float64(val)
  472. case int:
  473. return float64(val)
  474. case int32:
  475. return float64(val)
  476. case uint32:
  477. return float64(val)
  478. case int16:
  479. return float64(val)
  480. case uint16:
  481. return float64(val)
  482. case int8:
  483. return float64(val)
  484. case uint8:
  485. return float64(val)
  486. case uint64:
  487. return float64(val)
  488. default:
  489. rv := reflect.ValueOf(v)
  490. if !rv.IsValid() {
  491. return 0
  492. }
  493. switch rv.Kind() {
  494. case reflect.Float32, reflect.Float64:
  495. return rv.Float()
  496. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  497. return float64(rv.Int())
  498. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  499. return float64(rv.Uint())
  500. case reflect.Bool:
  501. if rv.Bool() {
  502. return 1
  503. }
  504. }
  505. return 0
  506. }
  507. }
  508. func toFixedBytes(v interface{}, size int) []byte {
  509. buf := make([]byte, size)
  510. switch val := v.(type) {
  511. case string:
  512. copy(buf, val)
  513. case []byte:
  514. copy(buf, val)
  515. default:
  516. // 数值类型: BigEndian 编码
  517. rv := reflect.ValueOf(v)
  518. if rv.CanUint() {
  519. binary.BigEndian.PutUint64(buf, rv.Uint())
  520. } else if rv.CanInt() {
  521. binary.BigEndian.PutUint64(buf, uint64(rv.Int()))
  522. }
  523. }
  524. return buf
  525. }
  526. func toBytes(v interface{}) []byte {
  527. switch val := v.(type) {
  528. case []byte:
  529. return val
  530. case string:
  531. return []byte(val)
  532. default:
  533. return nil
  534. }
  535. }
  536. // getPKValue 从结构体中提取主键值
  537. // 负数直接拒绝: 引擎的主键号是无符号 uint64, int64 主键填负数会被静默转成一个极大的号,
  538. // 之后按自己写的值既查不到也删不掉 —— 报错比留下查不到的行好。
  539. func getPKValue(obj interface{}, model *ModelInfo) (uint64, error) {
  540. // PKInStruct 现在恒为 true (表必须内嵌基类, 键列总能对应到结构体字段)。
  541. // 保留这个分支作为兜底: 万一将来又出现"键列不在结构体里"的模型, 让它退回
  542. // "主键填 0 → 由引擎分配"的旧行为, 而不是去取一个不存在的字段。
  543. if !model.PKInStruct {
  544. return 0, nil // PK 不在结构体中,返回 0 让 core 自动分配
  545. }
  546. v := reflect.ValueOf(obj)
  547. if v.Kind() == reflect.Ptr {
  548. v = v.Elem()
  549. }
  550. pkDef := model.AllFields[model.PKIndex]
  551. fv := findField(v, pkDef.Name, model.StructType)
  552. if !fv.IsValid() {
  553. return 0, nil
  554. }
  555. if fv.CanInt() && fv.Int() < 0 {
  556. return 0, fmt.Errorf("%w: 字段 %s = %d 为负数, 主键必须是非负整数",
  557. ErrInvalidPrimaryKey, pkDef.Name, fv.Int())
  558. }
  559. return toUint64(fv.Interface()), nil
  560. }
  561. // setPKValue 设置结构体的主键值
  562. func setPKValue(obj interface{}, model *ModelInfo, pk uint64) {
  563. // 同 getPKValue: PKInStruct 恒为 true, 这里是防御性兜底。
  564. if !model.PKInStruct {
  565. return // PK 不在结构体中,无法回写
  566. }
  567. v := reflect.ValueOf(obj)
  568. if v.Kind() == reflect.Ptr {
  569. v = v.Elem()
  570. }
  571. pkDef := model.AllFields[model.PKIndex]
  572. fv := findField(v, pkDef.Name, model.StructType)
  573. if fv.IsValid() && fv.CanSet() {
  574. // 走 setIntField 而不是 SetUint: 自定义主键可以是 int64,
  575. // 而在有符号整数上调用 SetUint 会 panic。
  576. setIntField(fv, int64(pk))
  577. }
  578. }
  579. // zeroValue 返回字段类型的零值
  580. func zeroValue(fd FieldDef) interface{} {
  581. switch fd.FieldType {
  582. case types.FieldType_1byte:
  583. return uint8(0)
  584. case types.FieldType_2byte:
  585. return int16(0)
  586. case types.FieldType_4byte:
  587. return int32(0)
  588. case types.FieldType_8byte:
  589. return uint64(0)
  590. case types.FieldType_Int8:
  591. return int8(0)
  592. case types.FieldType_Int16:
  593. return int16(0)
  594. case types.FieldType_Int32:
  595. return int32(0)
  596. case types.FieldType_Int64:
  597. return int64(0)
  598. case types.FieldType_Float64:
  599. return float64(0)
  600. // ===== 扩展类型: 零值必须与"标准解码载体"同类型, 否则写入时 EncodeValue 认不出来 =====
  601. case types.FieldType_Bool:
  602. return false
  603. case types.FieldType_Float32:
  604. return float32(0)
  605. case types.FieldType_Decimal:
  606. return types.Decimal{}
  607. case types.FieldType_UUID:
  608. return types.UUID{}
  609. case types.FieldType_Year:
  610. return int16(0)
  611. case types.FieldType_Int128:
  612. return new(big.Int)
  613. case types.FieldType_Blob:
  614. return []byte{}
  615. default:
  616. // 动态列的"值"就是字节内容本身: 行内那 6 字节堆引用由引擎写入时生成,
  617. // 不能当成值送进去 (旧写法送 6 个零字节, 落盘是一条 6 字节的垃圾内容)。
  618. if types.IsDynamic(fd.FieldType) {
  619. return []byte{}
  620. }
  621. // 定长字符串列的零值 = 该列宽度个零字节。宽度必须取列声明 (fd.Width()),
  622. // 不是类型默认: `maxlen:1000` 的列按 256 补零会让 EncodeValue 的长度校验失败,
  623. // "写零值"这条路直接报错。
  624. if size := int(fd.Width()); size > 0 {
  625. return make([]byte, size)
  626. }
  627. return []byte{}
  628. }
  629. }