Files
five/_FiveSql2/test/test_parser2.prg
Charles KWON OhJun 486e466592 feat: FiveSql2 43/43, @byref, mutable closure, RTL 479, DateTime fix
Major changes since last commit:
- FiveSql2 SQL:1999 engine (10,458 LOC) — 43/43 ALL PASS
- 21 compiler/runtime bugs fixed (short-circuit AND/OR, FOR LOOP, etc.)
- @byref pass-by-reference via RefCell pattern
- Mutable closure capture (EnsureLocalRef + RefCell sharing)
- RTL: 400 → 479 functions (+79: file, string, datetime, hash, UTF-8)
- DateTime/Timestamp fully working (hb_DateTime, hb_Hour/Min/Sec, display)
- Reserved word guard (39 keywords blocked from function calls)
- AEval arg order fix (element before index)
- Closure capture redecl fix (unique _cap_ names per block)
- Hash/string indexing in ArrayPush/ArrayPop
- Harbour compat test suite: 51/51
- 4 docs: Porting Report, Implementation Plan, Optimization Plan, Commercialization

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:35:37 +09:00

82 lines
4.1 KiB
Plaintext

#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