--- name: roa-vfp-go-recno description: Prinde capcana `GO ` in Visual FoxPro 9 cand numarul de inregistrare a fost capturat mai devreme sau primit ca parametru - cursorul s-a schimbat intre timp, iar `GO` fie da "Record is out of range", fie aseaza pointerul pe alt rand, tacit, fara eroare. Foloseste-l OBLIGATORIU cand vezi `GO` pe o variabila de recno (`lnRecno = Recno()`, `GO tnRecNo`, `Recno(alias)` refolosit), cand exista un `SELECT-SQL` sau requery intre captura si pozitionare, sau cand auzi "s-a pozitionat pe alt rand", "dupa requery sare altundeva", "recno capturat", "GO pe Recno()", "nu s-a dus pe inregistrarea ceruta", "record is out of range", "GO-ul nu nimereste". Nu repara cu `IF BETWEEN(...)` si nu te multumi cu "nu a dat eroare" - inlocuieste cu repozitionare pe cheie unica (`LOCATE`/`SEEK`) sau impacheteaza `GO` in `TRY/CATCH`. --- # GO pe Recno() capturat - repozitionare sigura `GO ` e pozitionare absoluta pe numarul curent de ordine al cursorului. Daca `n` a fost capturat inainte de un `SELECT-SQL`, `APPEND`, `DELETE`, `PACK` sau orice requery, `n` nu mai desemneaza acelasi rand. De multe ori nu primesti eroare, doar alt rand. ## Cand se foloseste Opreste-te si aplica regula cand: - vezi `GO ` sau `GO (expresie)` unde expresia e un recno pastrat (`lnRecno = Recno()`, `Recno(alias)`, `RECNO()`); - o rutina primeste un recno ca parametru (`LPARAMETERS tnRecNo`) si face `GO tnRecNo`; - intre capturarea recno-ului si `GO` exista un `SELECT ... FROM` sau orice requery pe acelasi cursor; - auzi "s-a pozitionat pe alt rand", "dupa requery sare altundeva", "recno capturat", "nu s-a dus pe inregistrarea ceruta", "record is out of range". `GO TOP` / `GO BOTTOM` nu poarta recno, dar se re-evalueaza si ele dupa requery. ## Regula Nu folosi `GO` pe un recno capturat anterior sau primit ca parametru. Repozitioneaza prin cheia unica de rand (ex. `doc_key`), care nu depinde de ordinea cursorului. WRONG - recno capturat, apoi requery, apoi `GO`: ```foxpro lnRecno = Recno("facturi") SELECT SUM(valoare) FROM facturi WHERE ... INTO CURSOR tmp GO lnRecno && sursa a ramas pe EOF -> "Record is out of range" sau alt rand ``` RIGHT - cheie unica, refacuta dupa requery: ```foxpro lcKey = facturi.doc_key SELECT SUM(valoare) FROM facturi WHERE ... INTO CURSOR tmp SELECT facturi LOCATE FOR doc_key = lcKey && sau SEEK( lcKey, "facturi", "tag_doc_key" ) IF NOT FOUND() GO TOP && randul a disparut intre timp - decizie explicita ENDIF ``` Daca nu exista cheie si ramai la recno (rar), impacheteaza-l: `TRY` / `GO tnRecNo` / `CATCH` / `GO TOP` / `ENDTRY`. ## Capcane - `SELECT-SQL ... FROM cursor` lasa pointerul sursei pe EOF (`Reccount()+1`); `GO` pe un recno capturat inainte de `SELECT` da "Record is out of range" - pointerul nu revine singur. - `Recno()` fara alias se citeste pe aliasul selectat; un `SELECT` intre timp intoarce alt numar. Captureaza cu alias explicit, inainte de requery. - Randurile pot disparea intre timp (DELETE + PACK, filtru schimbat, `SET ORDER`); un `LOCATE` care intoarce `.F.` e informatie reala - trateaz-o explicit. - `GO` in afara `[1, Reccount()]` da eroare; in interior NU da niciodata. "A mers" nu inseamna "s-a dus corect"; fara assert pe cheie nu ai dovada. - Nu repara cu `IF BETWEEN(tnRecNo, 1, Reccount())` - trece, dar poate cadea pe alt rand. Doar re-`LOCATE` pe cheie rezolva. - `SEEK` cere tag-ul/ordinea potrivita; dupa un `SET ORDER` gresit rateaza tacit. Verifica `ORDER()` sau foloseste `LOCATE`. ## Criterii de acceptare si dovada Fara dovada da/nu nu raporta ca rezolvat; "nu a dat eroare" nu e dovada. 1. Dupa fiecare requery, assert pe cheia randului curent (`ASSERT doc_key == lcKey`, sau log daca difera). Recno-ul nu e dovada, cheia e. 2. Test headless pe scenariul real: captureaza cheia, forteaza un requery pe acelasi cursor, repozitioneaza, apoi verifica `doc_key` si campurile randului asteptat. 3. Caz limita: randul capturat dispare intre timp -> rutina cade pe `GO TOP` sau pe calea decisa, fara eroare, cu log. 4. Regresii: zero `GO ` ramase in modul (`grep -rn "GO " `). ## Referinta (doar la nevoie) - `COMUN\docs\conventie_go_recno.md` - nota de conventie (EOF dupa `SELECT-SQL`, varianta TRY/CATCH).