code wiki / _hdl_build / nx_query_gate.nx

nx_query_gate.nx source

↩ module page · 107 lines · 5694 B

1// nx_query_gate.nx -- GATE for the query executor (nx_query). Known-answer queries over a small hand-built 2// dataset so SELECT-agg/WHERE-filter/GROUP-BY are proven exact. expect_exit: 0 license_tier: ORIGINAL 3import "nx_syscalls.nx" 4import "_hdl_build/nx_query.nx" 5import "nx_gate_verdict.nx" 6 7func qp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 8func qn(v: i64) -> i64 { var m: i64=v; if m<0{qp("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let o:*u8=sys_mmap(24); var i:i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 } 9 10func main() -> i64 { 11 qp("=== nx_query_gate ===\n" as *u8) 12 var pass: i64 = 0 13 var fail: i64 = 0 14 15 // dataset (8 rows): cat (group), size (filter), price (agg) 16 // row: cat size price 17 // 0 1 50 500 18 // 1 1 150 1500 19 // 2 2 80 800 20 // 3 2 200 2000 21 // 4 1 120 1200 22 // 5 3 60 600 23 // 6 2 300 3000 24 // 7 1 90 900 25 let n: i64 = 8 26 let cat: *i64 = sys_mmap(n * 8) as *i64 27 let size: *i64 = sys_mmap(n * 8) as *i64 28 let price: *i64 = sys_mmap(n * 8) as *i64 29 cat[0]=1; size[0]=50; price[0]=500 30 cat[1]=1; size[1]=150; price[1]=1500 31 cat[2]=2; size[2]=80; price[2]=800 32 cat[3]=2; size[3]=200; price[3]=2000 33 cat[4]=1; size[4]=120; price[4]=1200 34 cat[5]=3; size[5]=60; price[5]=600 35 cat[6]=2; size[6]=300; price[6]=3000 36 cat[7]=1; size[7]=90; price[7]=900 37 38 // Q1 SELECT count(*) -> 8 39 if q_scalar(price, size, n, Q_ALL, 0, Q_COUNT) == 8 { pass = pass + 1 } else { fail = fail + 1; qp("Q1 FAIL count all\n" as *u8) } 40 41 // Q2 SELECT sum(price) WHERE size > 100 -> rows 1(1500),3(2000),4(1200),6(3000) = 7700 42 let q2: i64 = q_scalar(price, size, n, 3, 100, Q_SUM) 43 qp("sum(price) WHERE size>100 = " as *u8); qn(q2); qp("\n" as *u8) 44 if q2 == 7700 { pass = pass + 1 } else { fail = fail + 1; qp("Q2 FAIL sum where\n" as *u8) } 45 46 // Q3 SELECT avg(price) WHERE size >= 80 -> rows 1500,800,2000,1200,3000,900 (6 rows) sum=9400 avg=1566 47 let q3: i64 = q_scalar(price, size, n, 4, 80, Q_AVG) 48 qp("avg(price) WHERE size>=80 = " as *u8); qn(q3); qp("\n" as *u8) 49 if q3 == 1566 { pass = pass + 1 } else { fail = fail + 1; qp("Q3 FAIL avg where\n" as *u8) } 50 51 // Q4 SELECT max(price) WHERE cat==2 (filter on cat) -> rows 800,2000,3000 -> 3000 ; min -> 800 52 var t4: i64 = 1 53 if q_scalar(price, cat, n, 0, 2, Q_MAX) != 3000 { t4 = 0 } 54 if q_scalar(price, cat, n, 0, 2, Q_MIN) != 800 { t4 = 0 } 55 if t4 == 1 { pass = pass + 1 } else { fail = fail + 1; qp("Q4 FAIL min/max where\n" as *u8) } 56 57 // Q5 SELECT sum(price) GROUP BY cat (no filter): 58 // cat1: 500+1500+1200+900 = 4100 ; cat2: 800+2000+3000 = 5800 ; cat3: 600 59 let ok: *i64 = sys_mmap(16 * 8) as *i64 60 let oa: *i64 = sys_mmap(16 * 8) as *i64 61 let oc: *i64 = sys_mmap(16 * 8) as *i64 62 let g: i64 = q_grouped(price, size, cat, n, Q_ALL, 0, Q_SUM, ok, oa, oc, 16) 63 qp("GROUP BY cat SUM(price): groups=" as *u8); qn(g); qp("\n" as *u8) 64 var t5: i64 = 1 65 if g != 3 { t5 = 0 } 66 // first-seen order: cat1, cat2, cat3 67 if ok[0] != 1 { t5 = 0 } else { if oa[0] != 4100 { t5 = 0 } } 68 if ok[1] != 2 { t5 = 0 } else { if oa[1] != 5800 { t5 = 0 } } 69 if ok[2] != 3 { t5 = 0 } else { if oa[2] != 600 { t5 = 0 } } 70 if t5 == 1 { pass = pass + 1 } else { fail = fail + 1; qp("Q5 FAIL group by sum\n" as *u8) } 71 72 // Q6 SELECT avg(price) GROUP BY cat WHERE size>=90: 73 // cat1: rows size>=90 -> 150(1500),120(1200),90(900) = 3600/3 = 1200 74 // cat2: 200(2000),300(3000) [80 excluded] = 5000/2 = 2500 ; cat3: 60 excluded -> no group 75 let g2: i64 = q_grouped(price, size, cat, n, 4, 90, Q_AVG, ok, oa, oc, 16) 76 var t6: i64 = 1 77 if g2 != 2 { t6 = 0 } 78 if ok[0] != 1 { t6 = 0 } else { if oa[0] != 1200 { t6 = 0 } } 79 if ok[1] != 2 { t6 = 0 } else { if oa[1] != 2500 { t6 = 0 } } 80 if t6 == 1 { pass = pass + 1 } else { fail = fail + 1; qp("Q6 FAIL group by avg + filter\n" as *u8) } 81 82 // Q7 empty filter result -> count 0, sum 0 83 var t7: i64 = 1 84 if q_scalar(price, size, n, 3, 100000, Q_COUNT) != 0 { t7 = 0 } 85 if q_scalar(price, size, n, 3, 100000, Q_SUM) != 0 { t7 = 0 } 86 if t7 == 1 { pass = pass + 1 } else { fail = fail + 1; qp("Q7 FAIL empty filter\n" as *u8) } 87 88 qp("pass=" as *u8); qn(pass); qp(" fail=" as *u8); qn(fail); qp("\n" as *u8) 89 let log: *u8 = sys_mmap(128) 90 var lo: i64 = 0 91 let pre: *u8 = "QUERY authored=organ verdict=" as *u8 92 var pi: i64 = 0 93 while pre[pi] != (0 as u8) { log[lo] = pre[pi]; lo = lo + 1; pi = pi + 1 } 94 if fail == 0 { let gg: *u8 = "GREEN\n" as *u8; var gi: i64 = 0; while gg[gi] != (0 as u8) { log[lo] = gg[gi]; lo = lo + 1; gi = gi + 1 } } else { let rr: *u8 = "RED\n" as *u8; var ri: i64 = 0; while rr[ri] != (0 as u8) { log[lo] = rr[ri]; lo = lo + 1; ri = ri + 1 } } 95 let fd: i64 = sys_openat_wr("knowledge/status/query.log" as *u8, 0x1A4) 96 if fd >= 0 { sys_write(fd, log, lo); sys_close(fd) } 97 98 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 99 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 100 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 101 let ctr__dry: *i64 = gv_ctr() 102 ctr__dry[0] = pass 103 ctr__dry[1] = pass + fail 104 let rc__dry: i64 = gv_verdict("QUERY-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 105 sys_exit(rc__dry) 106 return rc__dry 107}