gitoriaLog in with ident

ident

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit81b15b7b81b15b7bState of 2026-09-27, before the move to gitoriamre81b15b7b/plugins/mpackdb/MPackDB.hl

3.8 KB

  1. \* hl:mpackdb — the MessagePack file database. Construct it and it opens
  2. (the file root IS the constructor):
  3. db = new MPackDB(file = '/tmp/users.db', primaryKey = '*id',
  4. indexes = ['!email', 'age'])
  5. Key prefixes follow the JS API: `*name` auto-increment number pk, `@name`
  6. uuid pk, plain `name` string pk; a LEADING `!` on an index makes it
  7. unique, `*`/`@` on an index select numeric/uuid key parsing. On-disk
  8. format is compatible with the JS mpackdb 1.0.7 — a db written by either
  9. side is readable and mutable by the other. *\
  10. /* Wraps the Zig engine (plugins/mpackdb/{msgpack,engine}.zig, mission 066).
  11. `>` / `<>` hydration does NOT run the run body — construct with args. */
  12. \* The database is open (fired from the constructor's run body). *\
  13. emit opened(
  14. MPackDB db \\ this database
  15. )
  16. \* Opening failed. *\
  17. emit error(
  18. Hybrid e \\ the failure
  19. )
  20. \* close() finished. *\
  21. emit closed(
  22. MPackDB db \\ this database
  23. )
  24. String file = "" \\ the .db path, script-relative
  25. String primaryKey = "" \\ pk declaration: *name | @name | name | '' for none
  26. Hybrid indexes = [] \\ index declarations, '!' prefix = unique
  27. Boolean compact = true \\ compact the file on open
  28. Hybrid #handle
  29. String #pk \\ the primary key FIELD NAME, prefixes stripped (null when none)
  30. open() {
  31. #handle = __native("mpackdb.open", file, primaryKey, indexes, compact)
  32. if (#handle != null) {
  33. #pk = #handle.pk_name()
  34. emit opened(this)
  35. } else {
  36. emit error(new Error("mpackdb: cannot open " + file))
  37. }
  38. }
  39. open()
  40. \* The primary key field name, prefixes stripped (null when none). *\
  41. pkField() {
  42. return #pk
  43. }
  44. \* Insert one record. Answers the primary key it was stored under (a
  45. generated one for `*`/`@` pks), true for a pk-less db, or null on failure
  46. — lastError() has the reason (e.g. a unique-index violation). *\
  47. put(
  48. Hybrid record \\ the record to store
  49. ) {
  50. return #handle.insert(record)
  51. }
  52. \* First record with this primary key, or null. (Named fetch(), not get():
  53. `get` is reserved for getter syntax.) *\
  54. fetch(key) {
  55. let it = #handle.find_pk(key)
  56. if (it == null) {
  57. return null
  58. }
  59. return it.next()
  60. }
  61. \* Raw iterator over matches. field null → every live record; the pk and any
  62. declared index are binary-searched — other fields need an index declared. *\
  63. iterate(field, value) {
  64. if (field == null) {
  65. return #handle.find_all()
  66. }
  67. if (field == #pk) {
  68. return #handle.find_pk(value)
  69. }
  70. return #handle.find_index(field, value)
  71. }
  72. \* All matching records as a Hybrid; find(null) answers everything. *\
  73. find(field, value) {
  74. return drain(iterate(field, value))
  75. }
  76. \* Ascending index range scan, both bounds inclusive; null bound = open end. *\
  77. range(field, low, high) {
  78. return drain(#handle.find_range(field, low, high))
  79. }
  80. \* Lazy Cursor over the same matches — records decode one at a time. *\
  81. cursor(field, value) {
  82. return {
  83. #iter = iterate(field, value);
  84. } > new Cursor()
  85. }
  86. \* Delete every record with this primary key; answers how many went. *\
  87. delete(key) {
  88. return #handle.delete_pk(key)
  89. }
  90. \* Replace the record(s) at this pk. `record` must carry the pk (the JS
  91. update() contract); answers how many were replaced. A record without it
  92. is refused — null, the stored record untouched, lastError() says why. *\
  93. update(key, record) {
  94. return #handle.update_pk(key, record)
  95. }
  96. \* Live record count. *\
  97. count() {
  98. return #handle.count()
  99. }
  100. \* Rewrite the data file without tombstones and rebuild the indexes. *\
  101. compactNow() {
  102. #handle.compact()
  103. }
  104. \* Flush meta/index state to disk now. *\
  105. persist() {
  106. #handle.persist()
  107. }
  108. \* Reason for the last failed put/update ('' when none). *\
  109. lastError() {
  110. return #handle.last_error()
  111. }
  112. \* Close the database; the closed event fires. *\
  113. close() {
  114. #handle.close()
  115. emit closed(this)
  116. }
  117. // Internal: collect an iterator into an array.
  118. drain(it) {
  119. let out = []
  120. if (it == null) {
  121. return out
  122. }
  123. for (rec of it) {
  124. out.push(rec)
  125. }
  126. return out
  127. }

Branches

Latest commits

  • 81b15b7bState of 2026-09-27, before the move to gitoriamre