#include "FiveSqlDef.ch" #include "hbclass.ch" PROCEDURE Main() LOCAL aR, i, nPass := 0, nFail := 0 FErase("employees.dbf"); FErase("orders.dbf") dbCreate("employees.dbf",{{"ID","N",10,0},{"NAME","C",30,0},{"DEPT","C",20,0},{"SALARY","N",12,2},{"MGR_ID","N",10,0}}) USE employees.dbf NEW EXCLUSIVE dbAppend(); FieldPut(1,1); FieldPut(2,"Alice"); FieldPut(3,"Engineering"); FieldPut(4,8000); FieldPut(5,0) dbAppend(); FieldPut(1,2); FieldPut(2,"Bob"); FieldPut(3,"Engineering"); FieldPut(4,7000); FieldPut(5,1) dbAppend(); FieldPut(1,3); FieldPut(2,"Charlie"); FieldPut(3,"Engineering"); FieldPut(4,6000); FieldPut(5,1) dbAppend(); FieldPut(1,4); FieldPut(2,"Diana"); FieldPut(3,"Sales"); FieldPut(4,7500); FieldPut(5,0) dbAppend(); FieldPut(1,5); FieldPut(2,"Eve"); FieldPut(3,"Sales"); FieldPut(4,5000); FieldPut(5,4) dbCommit(); CLOSE ALL dbCreate("orders.dbf",{{"ID","N",10,0},{"EMP_ID","N",10,0},{"PRODUCT","C",30,0},{"AMOUNT","N",12,2}}) USE orders.dbf NEW EXCLUSIVE dbAppend(); FieldPut(1,1); FieldPut(2,1); FieldPut(3,"Laptop"); FieldPut(4,2500) dbAppend(); FieldPut(1,2); FieldPut(2,1); FieldPut(3,"Monitor");FieldPut(4,800) dbAppend(); FieldPut(1,3); FieldPut(2,4); FieldPut(3,"Printer");FieldPut(4,1200) dbCommit(); CLOSE ALL ? "=== TSqlParser2 Test ===" ? /* 1. Simple SELECT */ aR := five_SQL("SELECT name, salary FROM employees WHERE salary > 6000") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])>=3; nPass++; ? " PASS: 1 Simple SELECT"; ELSE; nFail++; ? " FAIL: 1"; ENDIF dbCloseAll() /* 2. JOIN */ aR := five_SQL("SELECT e.name, o.product FROM employees e JOIN orders o ON e.id = o.emp_id") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])>=2; nPass++; ? " PASS: 2 JOIN"; ELSE; nFail++; ? " FAIL: 2"; ENDIF dbCloseAll() /* 3. GROUP BY + HAVING */ aR := five_SQL("SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])>=2; nPass++; ? " PASS: 3 GROUP BY"; ELSE; nFail++; ? " FAIL: 3"; ENDIF dbCloseAll() /* 4. Subquery */ aR := five_SQL("SELECT name FROM employees WHERE id IN (SELECT emp_id FROM orders)") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])>=1; nPass++; ? " PASS: 4 Subquery"; ELSE; nFail++; ? " FAIL: 4"; ENDIF dbCloseAll() /* 5. CTE */ aR := five_SQL("WITH top_e AS (SELECT name, salary FROM employees WHERE salary > 6000) SELECT * FROM top_e") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])>=3; nPass++; ? " PASS: 5 CTE"; ELSE; nFail++; ? " FAIL: 5"; ENDIF dbCloseAll() /* 6. Recursive CTE */ aR := five_SQL("WITH RECURSIVE nums AS (SELECT 1 AS n UNION ALL SELECT n+1 FROM nums WHERE n<5) SELECT * FROM nums") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])==5; nPass++; ? " PASS: 6 Recursive CTE"; ELSE; nFail++; ? " FAIL: 6"; ENDIF dbCloseAll() /* 7. Window function */ aR := five_SQL("SELECT name, salary, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn FROM employees") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])==5; nPass++; ? " PASS: 7 Window ROW_NUMBER"; ELSE; nFail++; ? " FAIL: 7"; ENDIF dbCloseAll() /* 8. INSERT */ aR := five_SQL("INSERT INTO employees (id, name, dept, salary, mgr_id) VALUES (99, 'Test', 'QA', 5000, 0)") nPass++; ? " PASS: 8 INSERT" dbCloseAll() /* 9. UPDATE */ aR := five_SQL("UPDATE employees SET salary = 9999 WHERE id = 1") nPass++; ? " PASS: 9 UPDATE" dbCloseAll() /* 10. Recursive CTE + JOIN */ aR := five_SQL("WITH RECURSIVE org AS (SELECT id, name, 1 AS lvl FROM employees WHERE mgr_id = 0 UNION ALL SELECT e.id, e.name, o.lvl+1 FROM employees e JOIN org o ON e.mgr_id = o.id) SELECT name, lvl FROM org ORDER BY lvl") IF ValType(aR)=="A" .AND. Len(aR)>=2 .AND. Len(aR[2])>=5; nPass++; ? " PASS: 10 Recursive+JOIN"; ELSE; nFail++; ? " FAIL: 10 (rows=" + hb_ntos(IIF(ValType(aR)=="A".AND.Len(aR)>=2,Len(aR[2]),0)) + ")"; ENDIF dbCloseAll() ? ? " Pass: " + hb_ntos(nPass) + "/" + hb_ntos(nPass+nFail) FErase("employees.dbf"); FErase("orders.dbf") FErase("__cte_top_e.dbf"); FErase("__cte_nums.dbf"); FErase("__cte_org.dbf") RETURN