code wiki / _hdl_build / nx_store_query.nx

nx_store_query.nx source

↩ module page · 212 lines · 6888 B

1// nx_store_query.nx -- the FRONT DOOR to the sovereign information store 2// (knowledge/store/im-*). Pure NishiLang, NO SQL -- the operator's queryable 3// interface to the team's own substrate: 4// get <key> latest record state (FOUND + printable dump / GONE / ABSENT) 5// term <word> full-text term search, current-state semantics 6// and <w1> <w2>..multi-term AND search (up to 8 terms, postings-driven 7// intersection, same current-state semantics) 8// hist <key> every stored version, oldest -> newest (the time-travel surface) 9// histall <key> FULL history incl. compaction-archived segments (labeled) 10// compact fold live segments (also the FORMAT-UPGRADE path: old 11// segments without .terms become searchable after compaction) 12// license_tier: ORIGINAL 13 14import "nx_syscalls.nx" 15import "nx_seg_store.nx" 16 17func sq_p(s: *u8) -> i64 { 18 var n: i64 = 0 19 while s[n] != (0 as u8) { n = n + 1 } 20 sys_write(1, s, n) 21 return 0 22} 23 24func sq_pn(v: i64) -> i64 { 25 let bb: *u8 = sys_mmap(28) 26 var m: i64 = v 27 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 28 let t: *u8 = sys_mmap(28) 29 var k: i64 = 0 30 if m == 0 { t[0] = 48 as u8; k = 1 } 31 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 32 var i: i64 = 0 33 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 34 sys_write(1, bb, k) 35 return 0 36} 37 38func sq_streq(a: *u8, b: *u8) -> i64 { 39 var i: i64 = 0 40 while 1 == 1 { 41 if a[i] != b[i] { return 0 } 42 if a[i] == (0 as u8) { return 1 } 43 i = i + 1 44 } 45 return 0 46} 47 48// print bytes with non-printables as '.' (canonical records hold binary lengths) 49func sq_dump(p: *u8, n: i64) -> i64 { 50 let ob: *u8 = sys_mmap(n + 8) 51 var i: i64 = 0 52 while i < n { 53 var c: i64 = p[i] 54 if c < 32 { c = 46 } 55 if c > 126 { c = 46 } 56 ob[i] = c as u8 57 i = i + 1 58 } 59 sys_write(1, ob, n) 60 return 0 61} 62 63func main(argc: i64, argv: *i64) -> i64 { 64 let prefix: *u8 = "knowledge/store/im-" as *u8 65 if argc < 2 { 66 sq_p("usage: nx_store_query <get <key>|term <word>|and <w1> <w2>..|hist <key>|histall <key>|compact>\n" as *u8) 67 return 2 68 } 69 let cmd: *u8 = argv[1] as *u8 70 71 if sq_streq(cmd, "compact" as *u8) == 1 { 72 let rid: i64 = ss_compact(prefix, sys_now_us()) 73 if rid > 0 { 74 sq_p("COMPACTED -> seg-" as *u8) 75 sq_pn(rid) 76 sq_p(" (history archived in manifest-archive.txt)\n" as *u8) 77 return 0 78 } 79 sq_p("COMPACT FAILED rc=" as *u8) 80 sq_pn(rid) 81 sq_p("\n" as *u8) 82 return 1 83 } 84 85 if argc < 3 { 86 sq_p("usage: nx_store_query <get <key>|term <word>|and <w1> <w2>..|hist <key>|histall <key>|compact>\n" as *u8) 87 return 2 88 } 89 let arg: *u8 = argv[2] as *u8 90 91 if sq_streq(cmd, "get" as *u8) == 1 { 92 let h: *i64 = ss_open(prefix) 93 let pp: *i64 = sys_mmap(16) as *i64 94 let ll: *i64 = sys_mmap(16) as *i64 95 let g: i64 = ss_hget(h, arg, pp, ll) 96 if g == 1 { 97 sq_p("FOUND len=" as *u8) 98 sq_pn(ll[0]) 99 sq_p(" :: " as *u8) 100 sq_dump(pp[0] as *u8, ll[0]) 101 sq_p("\n" as *u8) 102 return 0 103 } 104 if g == 0 { sq_p("GONE (tombstoned; history retains prior versions)\n" as *u8); return 0 } 105 sq_p("ABSENT\n" as *u8) 106 return 1 107 } 108 109 if sq_streq(cmd, "term" as *u8) == 1 { 110 let h: *i64 = ss_open(prefix) 111 let kp: *i64 = sys_mmap(8 * 256) as *i64 112 let kl: *i64 = sys_mmap(8 * 256) as *i64 113 let n: i64 = ss_term(h, arg, kp, kl, 256) 114 if n == (0 - 2) { 115 sq_p("OLD-FORMAT segment(s) lack a term index -- run: nx_store_query compact\n" as *u8) 116 return 1 117 } 118 sq_p("MATCHES " as *u8) 119 sq_pn(n) 120 sq_p("\n" as *u8) 121 var i: i64 = 0 122 while i < n { 123 sq_p(" " as *u8) 124 sys_write(1, kp[i] as *u8, kl[i]) 125 sq_p("\n" as *u8) 126 i = i + 1 127 } 128 return 0 129 } 130 131 if sq_streq(cmd, "and" as *u8) == 1 { 132 var nt: i64 = argc - 2 133 if nt > 8 { nt = 8 } 134 let terms: *i64 = sys_mmap(8 * 8) as *i64 135 var ti: i64 = 0 136 while ti < nt { terms[ti] = argv[2 + ti]; ti = ti + 1 } 137 let h: *i64 = ss_open(prefix) 138 let kp: *i64 = sys_mmap(8 * 256) as *i64 139 let kl: *i64 = sys_mmap(8 * 256) as *i64 140 let n: i64 = ss_term_and(h, terms, nt, kp, kl, 256) 141 if n == (0 - 2) { 142 sq_p("OLD-FORMAT segment(s) lack a term index -- run: nx_store_query compact\n" as *u8) 143 return 1 144 } 145 sq_p("MATCHES " as *u8) 146 sq_pn(n) 147 sq_p(" (current records containing ALL " as *u8) 148 sq_pn(nt) 149 sq_p(" terms)\n" as *u8) 150 var i: i64 = 0 151 while i < n { 152 sq_p(" " as *u8) 153 sys_write(1, kp[i] as *u8, kl[i]) 154 sq_p("\n" as *u8) 155 i = i + 1 156 } 157 return 0 158 } 159 160 if sq_streq(cmd, "histall" as *u8) == 1 { 161 let kinds: *i64 = sys_mmap(8 * 260) as *i64 162 let ptrs: *i64 = sys_mmap(8 * 260) as *i64 163 let lens: *i64 = sys_mmap(8 * 260) as *i64 164 let srcs: *i64 = sys_mmap(8 * 260) as *i64 165 let n: i64 = ss_scan_all(prefix, arg, kinds, ptrs, lens, srcs) 166 sq_p("VERSIONS " as *u8) 167 sq_pn(n) 168 sq_p(" (FULL history: compaction-archived segments + live)\n" as *u8) 169 var i: i64 = 0 170 while i < n { 171 sq_p(" v" as *u8) 172 sq_pn(i) 173 if srcs[i] == 0 { sq_p(" ARCHIVED" as *u8) } else { sq_p(" LIVE" as *u8) } 174 if kinds[i] == 2 { sq_p(" TOMBSTONE\n" as *u8) } else { 175 sq_p(" len=" as *u8) 176 sq_pn(lens[i]) 177 sq_p(" :: " as *u8) 178 sq_dump(ptrs[i] as *u8, lens[i]) 179 sq_p("\n" as *u8) 180 } 181 i = i + 1 182 } 183 return 0 184 } 185 186 if sq_streq(cmd, "hist" as *u8) == 1 { 187 let kinds: *i64 = sys_mmap(8 * 260) as *i64 188 let ptrs: *i64 = sys_mmap(8 * 260) as *i64 189 let lens: *i64 = sys_mmap(8 * 260) as *i64 190 let n: i64 = ss_scan(prefix, arg, kinds, ptrs, lens) 191 sq_p("VERSIONS " as *u8) 192 sq_pn(n) 193 sq_p(" (live segments only; compacted history in archive)\n" as *u8) 194 var i: i64 = 0 195 while i < n { 196 sq_p(" v" as *u8) 197 sq_pn(i) 198 if kinds[i] == 2 { sq_p(" TOMBSTONE\n" as *u8) } else { 199 sq_p(" len=" as *u8) 200 sq_pn(lens[i]) 201 sq_p(" :: " as *u8) 202 sq_dump(ptrs[i] as *u8, lens[i]) 203 sq_p("\n" as *u8) 204 } 205 i = i + 1 206 } 207 return 0 208 } 209 210 sq_p("unknown command\n" as *u8) 211 return 2 212}