2
0

table.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. package storage
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strings"
  6. )
  7. // Row represents a database row.
  8. type Row map[string]interface{}
  9. // TableManager manages table data operations.
  10. type TableManager struct {
  11. pool *KVPool
  12. schema *SchemaManager
  13. database string
  14. }
  15. // NewTableManager creates a new table manager.
  16. func NewTableManager(pool *KVPool, schema *SchemaManager, database string) *TableManager {
  17. return &TableManager{
  18. pool: pool,
  19. schema: schema,
  20. database: database,
  21. }
  22. }
  23. // dataKey returns the key for a row.
  24. func (m *TableManager) dataKey(table, pk string) string {
  25. return fmt.Sprintf("%s:_data:%s:%s", m.database, strings.ToLower(table), pk)
  26. }
  27. // dataPrefix returns the prefix for all rows in a table.
  28. func (m *TableManager) dataPrefix(table string) string {
  29. return fmt.Sprintf("%s:_data:%s:", m.database, strings.ToLower(table))
  30. }
  31. // Insert inserts a new row.
  32. func (m *TableManager) Insert(table string, row Row) error {
  33. schema, err := m.schema.GetSchema(table)
  34. if err != nil {
  35. return err
  36. }
  37. // Get primary key value
  38. pkValue, ok := row[schema.PrimaryKey]
  39. if !ok {
  40. // Try case-insensitive lookup
  41. for k, v := range row {
  42. if strings.EqualFold(k, schema.PrimaryKey) {
  43. pkValue = v
  44. ok = true
  45. break
  46. }
  47. }
  48. }
  49. // Check if PK is INTEGER PRIMARY KEY (implicit ROWID alias)
  50. pkCol, _ := schema.GetColumn(schema.PrimaryKey)
  51. isIntegerPK := pkCol != nil && isIntegerType(pkCol.Type)
  52. // Auto-generate ROWID if no primary key provided or if it's INTEGER PRIMARY KEY
  53. var rowid int64
  54. if !ok || pkValue == nil {
  55. if isIntegerPK || !ok {
  56. // Generate ROWID
  57. rowid, err = m.schema.GetNextRowID(table)
  58. if err != nil {
  59. return err
  60. }
  61. pkValue = rowid
  62. row[schema.PrimaryKey] = rowid
  63. ok = true
  64. } else {
  65. return fmt.Errorf("missing primary key: %s", schema.PrimaryKey)
  66. }
  67. } else if isIntegerPK {
  68. // User provided INTEGER PRIMARY KEY value - track it
  69. switch v := pkValue.(type) {
  70. case int64:
  71. rowid = v
  72. case float64:
  73. rowid = int64(v)
  74. case int:
  75. rowid = int64(v)
  76. default:
  77. rowid = 0
  78. }
  79. if rowid > 0 {
  80. m.schema.UpdateMaxRowID(table, rowid)
  81. }
  82. }
  83. pk := fmt.Sprintf("%v", pkValue)
  84. // Check for duplicate
  85. key := m.dataKey(table, pk)
  86. err = m.pool.WithClient(func(c *KVClient) error {
  87. _, err := c.Read(key)
  88. return err
  89. })
  90. if err == nil {
  91. return fmt.Errorf("duplicate primary key: %s", pk)
  92. }
  93. // Validate required columns
  94. for _, col := range schema.Columns {
  95. if !col.Nullable && col.Default == nil {
  96. val, hasVal := row[col.Name]
  97. if !hasVal {
  98. // Try case-insensitive lookup
  99. for k, v := range row {
  100. if strings.EqualFold(k, col.Name) {
  101. val = v
  102. hasVal = true
  103. break
  104. }
  105. }
  106. }
  107. if !hasVal || val == nil {
  108. return fmt.Errorf("missing required column: %s", col.Name)
  109. }
  110. }
  111. }
  112. // Normalize column names to match schema
  113. normalizedRow := make(Row)
  114. for _, col := range schema.Columns {
  115. for k, v := range row {
  116. if strings.EqualFold(k, col.Name) {
  117. normalizedRow[col.Name] = v
  118. break
  119. }
  120. }
  121. }
  122. // Apply defaults
  123. for _, col := range schema.Columns {
  124. if _, ok := normalizedRow[col.Name]; !ok && col.Default != nil {
  125. normalizedRow[col.Name] = col.Default
  126. }
  127. }
  128. // Store ROWID (use PK value for INTEGER PRIMARY KEY, otherwise generate)
  129. if rowid > 0 {
  130. normalizedRow["_rowid_"] = rowid
  131. } else {
  132. // Generate ROWID for non-integer primary keys
  133. newRowID, _ := m.schema.GetNextRowID(table)
  134. normalizedRow["_rowid_"] = newRowID
  135. }
  136. // Serialize row
  137. data, err := json.Marshal(normalizedRow)
  138. if err != nil {
  139. return fmt.Errorf("failed to serialize row: %w", err)
  140. }
  141. // Write row
  142. err = m.pool.WithClient(func(c *KVClient) error {
  143. return c.Write(key, string(data))
  144. })
  145. if err != nil {
  146. return err
  147. }
  148. // Update indexes
  149. m.updateIndexesForRow(table, normalizedRow, true)
  150. return nil
  151. }
  152. // updateIndexesForRow adds or removes index entries for a row.
  153. func (m *TableManager) updateIndexesForRow(table string, row Row, add bool) {
  154. indexes, err := m.schema.ListTableIndexes(table)
  155. if err != nil || len(indexes) == 0 {
  156. return
  157. }
  158. rowid, ok := row["_rowid_"].(float64)
  159. if !ok {
  160. if rid, ok := row["_rowid_"].(int64); ok {
  161. rowid = float64(rid)
  162. } else {
  163. return
  164. }
  165. }
  166. for _, idx := range indexes {
  167. columns := make([]string, len(idx.Columns))
  168. for i, col := range idx.Columns {
  169. columns[i] = col.Name
  170. }
  171. colValue := m.buildIndexValue(row, columns)
  172. if add {
  173. m.AddIndexEntry(idx.Name, colValue, int64(rowid))
  174. } else {
  175. m.RemoveIndexEntry(idx.Name, colValue, int64(rowid))
  176. }
  177. }
  178. }
  179. // Select retrieves rows from a table.
  180. func (m *TableManager) Select(table string, filter func(Row) bool) ([]Row, error) {
  181. if !m.schema.TableExists(table) {
  182. return nil, fmt.Errorf("table not found: %s", table)
  183. }
  184. prefix := m.dataPrefix(table)
  185. var values []string
  186. err := m.pool.WithClient(func(c *KVClient) error {
  187. var err error
  188. values, err = c.Reads(prefix)
  189. fmt.Printf("[DEBUG] Select: table=%s, database=%s, prefix=%s, values_count=%d\n", table, m.database, prefix, len(values))
  190. return err
  191. })
  192. if err != nil {
  193. return nil, err
  194. }
  195. rows := make([]Row, 0, len(values))
  196. for _, data := range values {
  197. var row Row
  198. if err := json.Unmarshal([]byte(data), &row); err != nil {
  199. fmt.Printf("[DEBUG] Select: failed to unmarshal row: %v\n", err)
  200. continue // Skip invalid rows
  201. }
  202. if filter == nil || filter(row) {
  203. rows = append(rows, row)
  204. }
  205. }
  206. fmt.Printf("[DEBUG] Select: returning %d rows\n", len(rows))
  207. return rows, nil
  208. }
  209. // SelectWithLimit retrieves rows with limit and offset.
  210. func (m *TableManager) SelectWithLimit(table string, filter func(Row) bool, limit, offset int) ([]Row, error) {
  211. rows, err := m.Select(table, filter)
  212. if err != nil {
  213. return nil, err
  214. }
  215. // Apply offset
  216. if offset > 0 {
  217. if offset >= len(rows) {
  218. return nil, nil
  219. }
  220. rows = rows[offset:]
  221. }
  222. // Apply limit
  223. if limit > 0 && limit < len(rows) {
  224. rows = rows[:limit]
  225. }
  226. return rows, nil
  227. }
  228. // Update updates rows matching the filter.
  229. func (m *TableManager) Update(table string, updates Row, filter func(Row) bool) (int, error) {
  230. schema, err := m.schema.GetSchema(table)
  231. if err != nil {
  232. return 0, err
  233. }
  234. // Get all rows
  235. rows, err := m.Select(table, filter)
  236. if err != nil {
  237. return 0, err
  238. }
  239. count := 0
  240. for _, row := range rows {
  241. // Remove old index entries before update
  242. m.updateIndexesForRow(table, row, false)
  243. // Apply updates
  244. for k, v := range updates {
  245. // Normalize column name
  246. for _, col := range schema.Columns {
  247. if strings.EqualFold(k, col.Name) {
  248. row[col.Name] = v
  249. break
  250. }
  251. }
  252. }
  253. // Get primary key
  254. pkValue := row[schema.PrimaryKey]
  255. pk := fmt.Sprintf("%v", pkValue)
  256. // Serialize row
  257. data, err := json.Marshal(row)
  258. if err != nil {
  259. continue
  260. }
  261. // Write back
  262. key := m.dataKey(table, pk)
  263. err = m.pool.WithClient(func(c *KVClient) error {
  264. return c.Write(key, string(data))
  265. })
  266. if err == nil {
  267. // Add new index entries after update
  268. m.updateIndexesForRow(table, row, true)
  269. count++
  270. }
  271. }
  272. return count, nil
  273. }
  274. // UpdateFunc updates rows matching the filter using a function to compute new values.
  275. // The updateFn receives the current row and returns the updates to apply.
  276. func (m *TableManager) UpdateFunc(table string, updateFn func(Row) (Row, error), filter func(Row) bool) (int, error) {
  277. schema, err := m.schema.GetSchema(table)
  278. if err != nil {
  279. return 0, err
  280. }
  281. // Get all rows
  282. rows, err := m.Select(table, filter)
  283. if err != nil {
  284. return 0, err
  285. }
  286. count := 0
  287. for _, row := range rows {
  288. // Remove old index entries before update
  289. m.updateIndexesForRow(table, row, false)
  290. // Compute updates using the provided function
  291. updates, err := updateFn(row)
  292. if err != nil {
  293. return count, err
  294. }
  295. // Apply updates
  296. for k, v := range updates {
  297. // Normalize column name
  298. for _, col := range schema.Columns {
  299. if strings.EqualFold(k, col.Name) {
  300. row[col.Name] = v
  301. break
  302. }
  303. }
  304. }
  305. // Get primary key
  306. pkValue := row[schema.PrimaryKey]
  307. pk := fmt.Sprintf("%v", pkValue)
  308. // Serialize row
  309. data, err := json.Marshal(row)
  310. if err != nil {
  311. continue
  312. }
  313. // Write back
  314. key := m.dataKey(table, pk)
  315. err = m.pool.WithClient(func(c *KVClient) error {
  316. return c.Write(key, string(data))
  317. })
  318. if err == nil {
  319. // Add new index entries after update
  320. m.updateIndexesForRow(table, row, true)
  321. count++
  322. }
  323. }
  324. return count, nil
  325. }
  326. // Delete deletes rows matching the filter.
  327. func (m *TableManager) Delete(table string, filter func(Row) bool) (int, error) {
  328. schema, err := m.schema.GetSchema(table)
  329. if err != nil {
  330. return 0, err
  331. }
  332. // Get all rows
  333. rows, err := m.Select(table, filter)
  334. if err != nil {
  335. return 0, err
  336. }
  337. count := 0
  338. for _, row := range rows {
  339. // Remove index entries before deleting row
  340. m.updateIndexesForRow(table, row, false)
  341. pkValue := row[schema.PrimaryKey]
  342. pk := fmt.Sprintf("%v", pkValue)
  343. key := m.dataKey(table, pk)
  344. err = m.pool.WithClient(func(c *KVClient) error {
  345. return c.Delete(key)
  346. })
  347. if err == nil {
  348. count++
  349. }
  350. }
  351. return count, nil
  352. }
  353. // GetByPK retrieves a row by primary key.
  354. func (m *TableManager) GetByPK(table string, pk string) (Row, error) {
  355. if !m.schema.TableExists(table) {
  356. return nil, fmt.Errorf("table not found: %s", table)
  357. }
  358. key := m.dataKey(table, pk)
  359. var data string
  360. err := m.pool.WithClient(func(c *KVClient) error {
  361. var err error
  362. data, err = c.Read(key)
  363. return err
  364. })
  365. if err != nil {
  366. if err == ErrKeyNotFound {
  367. return nil, fmt.Errorf("row not found: %s", pk)
  368. }
  369. return nil, err
  370. }
  371. var row Row
  372. if err := json.Unmarshal([]byte(data), &row); err != nil {
  373. return nil, fmt.Errorf("failed to parse row: %w", err)
  374. }
  375. return row, nil
  376. }
  377. // Count returns the number of rows in a table.
  378. func (m *TableManager) Count(table string, filter func(Row) bool) (int, error) {
  379. rows, err := m.Select(table, filter)
  380. if err != nil {
  381. return 0, err
  382. }
  383. return len(rows), nil
  384. }
  385. // Truncate removes all rows from a table.
  386. func (m *TableManager) Truncate(table string) (int, error) {
  387. return m.Delete(table, nil)
  388. }
  389. // isIntegerType checks if a type name is an integer type.
  390. func isIntegerType(typeName string) bool {
  391. t := strings.ToUpper(typeName)
  392. switch t {
  393. case "INTEGER", "INT", "SMALLINT", "BIGINT", "TINYINT", "MEDIUMINT":
  394. return true
  395. }
  396. return false
  397. }
  398. // IsRowIDColumn checks if a column name is a ROWID alias.
  399. func IsRowIDColumn(name string) bool {
  400. n := strings.ToLower(name)
  401. return n == "rowid" || n == "oid" || n == "_rowid_"
  402. }
  403. // Index entry methods - leveraging radix trie for prefix-based lookups
  404. // Format: {database}:idx:{index_name}:{column_value} → JSON array of rowids
  405. // indexEntryKey returns the key for an index entry.
  406. func (m *TableManager) indexEntryKey(indexName string, colValue interface{}) string {
  407. // Format the value without scientific notation
  408. var valueStr string
  409. switch v := colValue.(type) {
  410. case float64:
  411. // Check if it's actually an integer value
  412. if v == float64(int64(v)) {
  413. valueStr = fmt.Sprintf("%d", int64(v))
  414. } else {
  415. valueStr = fmt.Sprintf("%f", v)
  416. }
  417. case int64:
  418. valueStr = fmt.Sprintf("%d", v)
  419. case int:
  420. valueStr = fmt.Sprintf("%d", v)
  421. default:
  422. valueStr = fmt.Sprintf("%v", v)
  423. }
  424. return fmt.Sprintf("%s:idx:%s:%s", m.database, strings.ToLower(indexName), valueStr)
  425. }
  426. // indexPrefix returns the prefix for all entries of an index.
  427. func (m *TableManager) indexPrefix(indexName string) string {
  428. return fmt.Sprintf("%s:idx:%s:", m.database, strings.ToLower(indexName))
  429. }
  430. // AddIndexEntry adds a rowid to an index entry.
  431. func (m *TableManager) AddIndexEntry(indexName string, colValue interface{}, rowid int64) error {
  432. key := m.indexEntryKey(indexName, colValue)
  433. // Read existing rowids
  434. var rowids []int64
  435. err := m.pool.WithClient(func(c *KVClient) error {
  436. data, err := c.Read(key)
  437. if err == nil && data != "" {
  438. json.Unmarshal([]byte(data), &rowids)
  439. }
  440. return nil // Ignore not found errors
  441. })
  442. if err != nil {
  443. return err
  444. }
  445. // Add new rowid if not already present
  446. for _, r := range rowids {
  447. if r == rowid {
  448. return nil // Already exists
  449. }
  450. }
  451. rowids = append(rowids, rowid)
  452. // Write back
  453. data, _ := json.Marshal(rowids)
  454. return m.pool.WithClient(func(c *KVClient) error {
  455. return c.Write(key, string(data))
  456. })
  457. }
  458. // RemoveIndexEntry removes a rowid from an index entry.
  459. func (m *TableManager) RemoveIndexEntry(indexName string, colValue interface{}, rowid int64) error {
  460. key := m.indexEntryKey(indexName, colValue)
  461. // Read existing rowids
  462. var rowids []int64
  463. err := m.pool.WithClient(func(c *KVClient) error {
  464. data, err := c.Read(key)
  465. if err != nil {
  466. return err
  467. }
  468. json.Unmarshal([]byte(data), &rowids)
  469. return nil
  470. })
  471. if err != nil {
  472. return nil // Entry doesn't exist
  473. }
  474. // Remove rowid
  475. newRowids := make([]int64, 0, len(rowids))
  476. for _, r := range rowids {
  477. if r != rowid {
  478. newRowids = append(newRowids, r)
  479. }
  480. }
  481. if len(newRowids) == 0 {
  482. // Delete the entry entirely
  483. return m.pool.WithClient(func(c *KVClient) error {
  484. return c.Delete(key)
  485. })
  486. }
  487. // Write back
  488. data, _ := json.Marshal(newRowids)
  489. return m.pool.WithClient(func(c *KVClient) error {
  490. return c.Write(key, string(data))
  491. })
  492. }
  493. // LookupIndex returns rowids matching a column value using the index.
  494. func (m *TableManager) LookupIndex(indexName string, colValue interface{}) ([]int64, error) {
  495. key := m.indexEntryKey(indexName, colValue)
  496. var rowids []int64
  497. err := m.pool.WithClient(func(c *KVClient) error {
  498. data, err := c.Read(key)
  499. if err != nil {
  500. return err
  501. }
  502. return json.Unmarshal([]byte(data), &rowids)
  503. })
  504. if err != nil {
  505. return nil, nil // Return empty if not found
  506. }
  507. return rowids, nil
  508. }
  509. // ClearIndex removes all entries for an index by scanning table and removing entries.
  510. func (m *TableManager) ClearIndex(indexName, tableName string, columns []string) error {
  511. rows, err := m.Select(tableName, nil)
  512. if err != nil {
  513. return err
  514. }
  515. for _, row := range rows {
  516. colValue := m.buildIndexValue(row, columns)
  517. key := m.indexEntryKey(indexName, colValue)
  518. m.pool.WithClient(func(c *KVClient) error {
  519. return c.Delete(key)
  520. })
  521. }
  522. return nil
  523. }
  524. // BuildIndex builds index entries for all existing rows in a table.
  525. func (m *TableManager) BuildIndex(indexName, tableName string, columns []string) error {
  526. rows, err := m.Select(tableName, nil)
  527. if err != nil {
  528. return err
  529. }
  530. for _, row := range rows {
  531. rowid, ok := row["_rowid_"].(float64)
  532. if !ok {
  533. continue
  534. }
  535. // Build composite key value for multi-column indexes
  536. colValue := m.buildIndexValue(row, columns)
  537. if err := m.AddIndexEntry(indexName, colValue, int64(rowid)); err != nil {
  538. return err
  539. }
  540. }
  541. return nil
  542. }
  543. // buildIndexValue creates the index key value from row columns.
  544. func (m *TableManager) buildIndexValue(row Row, columns []string) string {
  545. formatValue := func(v interface{}) string {
  546. switch val := v.(type) {
  547. case float64:
  548. // Check if it's actually an integer value
  549. if val == float64(int64(val)) {
  550. return fmt.Sprintf("%d", int64(val))
  551. }
  552. return fmt.Sprintf("%f", val)
  553. case int64:
  554. return fmt.Sprintf("%d", val)
  555. case int:
  556. return fmt.Sprintf("%d", val)
  557. default:
  558. return fmt.Sprintf("%v", val)
  559. }
  560. }
  561. if len(columns) == 1 {
  562. return formatValue(row[columns[0]])
  563. }
  564. // Multi-column index: concatenate values with separator
  565. var parts []string
  566. for _, col := range columns {
  567. parts = append(parts, formatValue(row[col]))
  568. }
  569. return strings.Join(parts, "\x00")
  570. }
  571. // SelectByIndex retrieves rows using an index lookup.
  572. func (m *TableManager) SelectByIndex(table, indexName string, colValue interface{}) ([]Row, error) {
  573. rowids, err := m.LookupIndex(indexName, colValue)
  574. if err != nil {
  575. return nil, err
  576. }
  577. // If no rowids found, return empty result
  578. if len(rowids) == 0 {
  579. return []Row{}, nil
  580. }
  581. schema, err := m.schema.GetSchema(table)
  582. if err != nil {
  583. return nil, err
  584. }
  585. // Check if primary key is INTEGER type (in which case rowid == pk)
  586. pkCol, _ := schema.GetColumn(schema.PrimaryKey)
  587. isPKInteger := pkCol != nil && isIntegerType(pkCol.Type)
  588. rows := make([]Row, 0, len(rowids))
  589. for _, rowid := range rowids {
  590. var row Row
  591. // For INTEGER PRIMARY KEY, the rowid IS the primary key
  592. if isPKInteger {
  593. row, err = m.GetByPK(table, fmt.Sprintf("%d", rowid))
  594. if err == nil {
  595. rows = append(rows, row)
  596. continue
  597. }
  598. }
  599. // For non-INTEGER primary keys or if PK lookup fails, look up by _rowid_
  600. allRows, _ := m.Select(table, func(r Row) bool {
  601. if rid, ok := r["_rowid_"].(float64); ok {
  602. return int64(rid) == rowid
  603. }
  604. if rid, ok := r["_rowid_"].(int64); ok {
  605. return rid == rowid
  606. }
  607. return false
  608. })
  609. if len(allRows) > 0 {
  610. rows = append(rows, allRows[0])
  611. }
  612. }
  613. return rows, nil
  614. }