sync SVN r18041

This commit is contained in:
2026-08-23 11:08:56 +03:00
parent 79b08470be
commit 0027a28961
19 changed files with 369 additions and 592 deletions

View File

@@ -1,31 +1,24 @@
# Capcană: `ALTER TABLE` pe cursorul întors de `goExecutor.oExecute()`
# Capcana: ALTER TABLE pe cursorul intors de goExecutor.oExecute()
Partajat între proiectele ROA* — `goExecutor` (clasa `oExecutor`, definită în
`COMUN/programe/oproceduri_comune.prg`, metoda `oExecute`) e utilitarul standard pentru
interogări SQL pass-through (`SQLExec`) către Oracle, folosit peste tot în codul ROA*.
Comun tuturor proiectelor ROA*.
## Ce nu funcționează
## Ce nu functioneaza
```foxpro
lnSucces = goExecutor.oExecute(lcSql, lcCursor)
...
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pica
```
Cursorul întors de `oExecute()` poate refuza comenzi DDL ulterioare, cu erori în lanț
(descoperite empiric, în această ordine):
Simptome intalnite, in aceasta ordine: `Function is not supported on remote tables.` (ALTER
TABLE direct pe cursorul original) / `Alias name is already in use.` (rematerializare cu
sursa si tinta acelasi nume) / `Invalid operation for the cursor.` (ALTER TABLE pe alias
scratch diferit ca tinta).
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul original.
2. Chiar și după rematerializare (`SELECT * FROM (cursor) INTO CURSOR (acelasi_nume) READWRITE`)
→ `Alias name is already in use.` (sursa și ținta nu pot avea același nume).
3. Cu alias scratch diferit ca țintă → tot `Invalid operation for the cursor.` pe `ALTER TABLE`,
chiar dacă țintă ar trebui să fie deja un cursor local obișnuit.
## Ce functioneaza
## Ce funcționează
**Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`.** Include coloanele
suplimentare direct în `SELECT`-ul de rematerializare, ca expresii literale alături de `*`
(VFP suportă `SELECT *, expr AS coloana FROM ...`):
Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`. Include coloanele suplimentare
direct in `SELECT`-ul de rematerializare, ca expresii literale alaturi de `*`:
```foxpro
lcCursorRaw = lcCursor + '_raw'
@@ -45,11 +38,6 @@ USE IN (lcCursorRaw)
* de-aici incolo doar REPLACE (date), NICIODATA ALTER TABLE (structura) pe (lcCursor)
```
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
normal pe el DUPĂ ACEEA (ex. într-o altă funcție care primește cursorul deja gata construit),
doar comanda imediat următoare unui `oExecute()` e restricționată.
## Vezi și
Exemplu complet aplicat: ROAAUTO, `Programe/oproceduri_autopass.prg`,
`autopass_cursor_comenzi()`/`autopass_cursor_operatii()`.
Dupa acest pas cursorul (`lcCursor`) e un cursor local obisnuit - `ALTER TABLE` functioneaza
normal pe el DUPA ACEEA (ex. intr-o alta functie care primeste cursorul deja gata construit),
doar comanda imediat urmatoare unui `oExecute()` e restrictionata.