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>
82 lines
4.1 KiB
Plaintext
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
|