unique_cache.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. package storage
  2. import "strings"
  3. // UNIQUE caches use the constraint encoder, not the coarser SELECT candidate
  4. // encoder. Owners are actual durable keys, preserving NULL and legacy-key rules.
  5. // Validation and publication hold the table's exclusive gate. cacheMu protects
  6. // cache membership and removals from shared-gate point deletes.
  7. type uniqueIndexCache struct {
  8. table string
  9. values map[string]map[string]bool
  10. keys map[string]string
  11. }
  12. type uniqueCacheChange struct {
  13. name string
  14. cache *uniqueIndexCache
  15. values map[string]*string // nil removes a key or represents a NULL index value
  16. }
  17. type uniqueCachePlan []uniqueCacheChange
  18. func (m *TableManager) prepareUniqueRows(table string, entries map[string]*overlayEntry) (uniqueCachePlan, error) {
  19. indexes, err := m.uniqueIndexes(table)
  20. if err != nil {
  21. return nil, err
  22. }
  23. return m.prepareUniqueRowsWith(table, entries, indexes)
  24. }
  25. // prepareUniqueRowsWith is prepareUniqueRows against an explicit UNIQUE index
  26. // list, so a transaction validates its staged rows against the indexes it can
  27. // see rather than the committed catalog alone.
  28. func (m *TableManager) prepareUniqueRowsWith(table string, entries map[string]*overlayEntry, indexes []*Index) (uniqueCachePlan, error) {
  29. if len(indexes) == 0 {
  30. return nil, nil
  31. }
  32. caches, err := m.ensureUniqueCaches(table, indexes)
  33. if err != nil {
  34. return nil, err
  35. }
  36. plan := make(uniqueCachePlan, 0, len(indexes))
  37. for _, idx := range indexes {
  38. cache := caches[idx.Name]
  39. change := uniqueCacheChange{name: strings.ToLower(idx.Name), cache: cache, values: make(map[string]*string, len(entries))}
  40. seen := make(map[string]bool)
  41. for key, entry := range entries {
  42. change.values[key] = nil
  43. if entry.absent {
  44. continue
  45. }
  46. value, isNull, err := m.encodeUniqueValue(entry.row, idx.Columns)
  47. if err != nil {
  48. return nil, err
  49. }
  50. if isNull {
  51. continue
  52. }
  53. if seen[value] {
  54. return nil, &UniqueViolationError{Constraint: idx.Name}
  55. }
  56. seen[value] = true
  57. for owner := range cache.values[value] {
  58. if _, replaced := entries[owner]; !replaced {
  59. return nil, &UniqueViolationError{Constraint: idx.Name}
  60. }
  61. }
  62. change.values[key] = &value
  63. }
  64. plan = append(plan, change)
  65. }
  66. return plan, nil
  67. }
  68. func (m *TableManager) ensureUniqueCaches(table string, indexes []*Index) (map[string]*uniqueIndexCache, error) {
  69. caches := make(map[string]*uniqueIndexCache, len(indexes))
  70. var missing []*Index
  71. m.cacheMu.RLock()
  72. for _, idx := range indexes {
  73. if cache := m.uniqueCache[strings.ToLower(idx.Name)]; cache != nil && cacheableColumnIndex(idx) {
  74. caches[idx.Name] = cache
  75. } else {
  76. missing = append(missing, idx)
  77. }
  78. }
  79. m.cacheMu.RUnlock()
  80. if len(missing) == 0 {
  81. return caches, nil
  82. }
  83. for _, idx := range missing {
  84. caches[idx.Name] = &uniqueIndexCache{table: strings.ToLower(table), values: make(map[string]map[string]bool), keys: make(map[string]string)}
  85. }
  86. err := m.pool.WithClient(func(client *KVClient) (retErr error) {
  87. cursor, err := client.ScanWithLimit([]byte(m.dataPrefix(table)), scanPageSize)
  88. if err != nil {
  89. return err
  90. }
  91. defer func() {
  92. if err := cursor.Close(); retErr == nil {
  93. retErr = err
  94. }
  95. }()
  96. for {
  97. entries, done, err := cursor.Next()
  98. if err != nil {
  99. return err
  100. }
  101. for _, entry := range entries {
  102. row, err := decodeRow(entry.Value)
  103. if err != nil {
  104. return err
  105. }
  106. for _, idx := range missing {
  107. value, isNull, err := m.encodeUniqueValue(row, idx.Columns)
  108. if err != nil {
  109. return err
  110. }
  111. if !isNull {
  112. caches[idx.Name].add(string(entry.Key), value)
  113. }
  114. }
  115. }
  116. if done {
  117. return nil
  118. }
  119. }
  120. })
  121. if err != nil {
  122. return nil, err
  123. }
  124. m.cacheMu.Lock()
  125. for _, idx := range missing {
  126. if cacheableColumnIndex(idx) {
  127. m.uniqueCache[strings.ToLower(idx.Name)] = caches[idx.Name]
  128. }
  129. }
  130. m.cacheMu.Unlock()
  131. return caches, nil
  132. }
  133. // Expression evaluators have no determinism contract. Rebuild these constraints
  134. // for each validation rather than freezing time/random/function-dependent values.
  135. func cacheableColumnIndex(index *Index) bool {
  136. for _, column := range index.Columns {
  137. if column.Expression != "" {
  138. return false
  139. }
  140. }
  141. return true
  142. }
  143. func (c *uniqueIndexCache) remove(key string) {
  144. value, ok := c.keys[key]
  145. if !ok {
  146. return
  147. }
  148. delete(c.keys, key)
  149. delete(c.values[value], key)
  150. if len(c.values[value]) == 0 {
  151. delete(c.values, value)
  152. }
  153. }
  154. func (c *uniqueIndexCache) add(key, value string) {
  155. if c.values[value] == nil {
  156. c.values[value] = make(map[string]bool)
  157. }
  158. c.values[value][key] = true
  159. c.keys[key] = value
  160. }
  161. // Apply only after durable success. accepted is used by the storage bulk API,
  162. // which can commit several batches; SQL statements use one atomic transaction.
  163. func (m *TableManager) applyUniquePlan(plan uniqueCachePlan, accepted map[string]bool) {
  164. if len(plan) == 0 {
  165. return
  166. }
  167. m.cacheMu.Lock()
  168. defer m.cacheMu.Unlock()
  169. for _, change := range plan {
  170. if m.uniqueCache[change.name] != change.cache {
  171. continue
  172. }
  173. for key := range change.values {
  174. if accepted == nil || accepted[key] {
  175. change.cache.remove(key)
  176. }
  177. }
  178. for key, value := range change.values {
  179. if value != nil && (accepted == nil || accepted[key]) {
  180. change.cache.add(key, *value)
  181. }
  182. }
  183. }
  184. }
  185. // A transport failure may hide a durable write. Drop derived state and make
  186. // earlier predicate/scan snapshots retry rather than trusting an unknown outcome.
  187. // Callers retain their normal table publication gate.
  188. func (m *TableManager) invalidateWriteFailure(table string) {
  189. m.InvalidateCache(table)
  190. m.bumpIndexPredicateWildcard(table)
  191. m.bumpGeneration(table)
  192. }
  193. func (m *TableManager) removeUniqueKey(table, key string) {
  194. m.cacheMu.Lock()
  195. defer m.cacheMu.Unlock()
  196. for _, cache := range m.uniqueCache {
  197. if cache.table == strings.ToLower(table) {
  198. cache.remove(key)
  199. }
  200. }
  201. }