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.

166 lines
3.9 KiB

  1. // Copyright 2019 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package core
  5. import (
  6. "fmt"
  7. "reflect"
  8. "strings"
  9. "time"
  10. )
  11. const (
  12. TWOSIDES = iota + 1
  13. ONLYTODB
  14. ONLYFROMDB
  15. )
  16. // Column defines database column
  17. type Column struct {
  18. Name string
  19. TableName string
  20. FieldName string
  21. SQLType SQLType
  22. IsJSON bool
  23. Length int
  24. Length2 int
  25. Nullable bool
  26. Default string
  27. Indexes map[string]int
  28. IsPrimaryKey bool
  29. IsAutoIncrement bool
  30. MapType int
  31. IsCreated bool
  32. IsUpdated bool
  33. IsDeleted bool
  34. IsCascade bool
  35. IsVersion bool
  36. DefaultIsEmpty bool
  37. EnumOptions map[string]int
  38. SetOptions map[string]int
  39. DisableTimeZone bool
  40. TimeZone *time.Location // column specified time zone
  41. Comment string
  42. }
  43. // NewColumn creates a new column
  44. func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable bool) *Column {
  45. return &Column{
  46. Name: name,
  47. TableName: "",
  48. FieldName: fieldName,
  49. SQLType: sqlType,
  50. Length: len1,
  51. Length2: len2,
  52. Nullable: nullable,
  53. Default: "",
  54. Indexes: make(map[string]int),
  55. IsPrimaryKey: false,
  56. IsAutoIncrement: false,
  57. MapType: TWOSIDES,
  58. IsCreated: false,
  59. IsUpdated: false,
  60. IsDeleted: false,
  61. IsCascade: false,
  62. IsVersion: false,
  63. DefaultIsEmpty: false,
  64. EnumOptions: make(map[string]int),
  65. Comment: "",
  66. }
  67. }
  68. // String generate column description string according dialect
  69. func (col *Column) String(d Dialect) string {
  70. sql := d.QuoteStr() + col.Name + d.QuoteStr() + " "
  71. sql += d.SqlType(col) + " "
  72. if col.IsPrimaryKey {
  73. sql += "PRIMARY KEY "
  74. if col.IsAutoIncrement {
  75. sql += d.AutoIncrStr() + " "
  76. }
  77. }
  78. if col.Default != "" {
  79. sql += "DEFAULT " + col.Default + " "
  80. }
  81. if d.ShowCreateNull() {
  82. if col.Nullable {
  83. sql += "NULL "
  84. } else {
  85. sql += "NOT NULL "
  86. }
  87. }
  88. return sql
  89. }
  90. // StringNoPk generate column description string according dialect without primary keys
  91. func (col *Column) StringNoPk(d Dialect) string {
  92. sql := d.QuoteStr() + col.Name + d.QuoteStr() + " "
  93. sql += d.SqlType(col) + " "
  94. if col.Default != "" {
  95. sql += "DEFAULT " + col.Default + " "
  96. }
  97. if d.ShowCreateNull() {
  98. if col.Nullable {
  99. sql += "NULL "
  100. } else {
  101. sql += "NOT NULL "
  102. }
  103. }
  104. return sql
  105. }
  106. // ValueOf returns column's filed of struct's value
  107. func (col *Column) ValueOf(bean interface{}) (*reflect.Value, error) {
  108. dataStruct := reflect.Indirect(reflect.ValueOf(bean))
  109. return col.ValueOfV(&dataStruct)
  110. }
  111. // ValueOfV returns column's filed of struct's value accept reflevt value
  112. func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) {
  113. var fieldValue reflect.Value
  114. fieldPath := strings.Split(col.FieldName, ".")
  115. if dataStruct.Type().Kind() == reflect.Map {
  116. keyValue := reflect.ValueOf(fieldPath[len(fieldPath)-1])
  117. fieldValue = dataStruct.MapIndex(keyValue)
  118. return &fieldValue, nil
  119. } else if dataStruct.Type().Kind() == reflect.Interface {
  120. structValue := reflect.ValueOf(dataStruct.Interface())
  121. dataStruct = &structValue
  122. }
  123. level := len(fieldPath)
  124. fieldValue = dataStruct.FieldByName(fieldPath[0])
  125. for i := 0; i < level-1; i++ {
  126. if !fieldValue.IsValid() {
  127. break
  128. }
  129. if fieldValue.Kind() == reflect.Struct {
  130. fieldValue = fieldValue.FieldByName(fieldPath[i+1])
  131. } else if fieldValue.Kind() == reflect.Ptr {
  132. if fieldValue.IsNil() {
  133. fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
  134. }
  135. fieldValue = fieldValue.Elem().FieldByName(fieldPath[i+1])
  136. } else {
  137. return nil, fmt.Errorf("field %v is not valid", col.FieldName)
  138. }
  139. }
  140. if !fieldValue.IsValid() {
  141. return nil, fmt.Errorf("field %v is not valid", col.FieldName)
  142. }
  143. return &fieldValue, nil
  144. }