- leaga_skills.ps1: expune skill-urile in ~/.claude/skills prin symlink (citit si de Claude Code, si de opencode), fara copiere - rutare zona->skill in reguli_lucru pct. 7, README, AGENTS.md; skill-ul devine proprietarul procedurii, docurile raman referinta conditionata - rec_skills.md: decizia, inventarul si cum se adauga un skill nou
67 lines
4.3 KiB
Markdown
67 lines
4.3 KiB
Markdown
---
|
|
name: roa-vfp-go-recno
|
|
description: Prinde capcana `GO <recno>` 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 <n>` 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 <variabila>` 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 <variabila_recno>` ramase in modul (`grep -rn "GO " <module>`).
|
|
|
|
## Referinta (doar la nevoie)
|
|
|
|
- `COMUN\docs\conventie_go_recno.md` - nota de conventie (EOF dupa `SELECT-SQL`, varianta TRY/CATCH).
|