Bug en RECCOUNT de cursor?

230 views
Skip to first unread message

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 6:34:09 PM2/9/15
to publice...@googlegroups.com, mundovis...@googlegroups.com
Hola

Ejecuten el programa adjunto y observen el resultado.

La línea: Index On IdTmp Tag IdTmp

dejarla como comentario: *--Index On IdTmp Tag IdTmp

Ejecuten y comparen el resultado!

Exijo una explicación ;-)

Saludos,
Víctor.
Lambaré - Paraguay.


reccountbug.prg

HernanCano

unread,
Feb 9, 2015, 7:18:52 PM2/9/15
to publice...@googlegroups.com, mundovis...@googlegroups.com
Incluso si no cierro los cursores, y desde la ventana de comandos ejecuto GO 1, GO 2, GO 3, GO 4, GO 5, y GO 6, sólo cuando ejecuto GO 6 aparece el error "Registro fuera de rango".

Claudio Luna

unread,
Feb 9, 2015, 7:37:36 PM2/9/15
to Comunidad de Visual Foxpro en Español
Victor si el bug es por el _tally  no es un bug ya que haces esto >

Select * From Tmp Where IdTmp > 5 Into Cursor curAux y no hay un registro con IdTmp > 5 por eso el _tally te da 0.

Espero haber entendido bien.
Saludos

El 9 de febrero de 2015, 22:18, HernanCano <jherna...@gmail.com> escribió:
Incluso si no cierro los cursores, y desde la ventana de comandos ejecuto GO 1, GO 2, GO 3, GO 4, GO 5, y GO 6, sólo cuando ejecuto GO 6 aparece el error "Registro fuera de rango".



--
Claudio Luna
Monttevideo - Uruguay
SKYPE: clunamarin
Cel. 099 194 770

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 7:44:34 PM2/9/15
to publice...@googlegroups.com
Hola Claudio

La variable _Tally siempre tiene el valor correcto, la función RECCOUNT("curAux") es la que da en un caso 5 y en otro 0 que es lo que se espera puesto que el cursor está vacío!

Saludos,
Víctor.
Lambaré - Paraguay.

Alex Vargas

unread,
Feb 9, 2015, 8:11:41 PM2/9/15
to publice...@googlegroups.com
Lo ejecute mas de 20 veces y siempre _Tally y Reccount me retornaron 0

Saludos 

Alex A. Vargas

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 8:16:42 PM2/9/15
to publice...@googlegroups.com
Hola Alex

Qué versión de VFP usas?

Puedes enviar un archivo de texto con la información creada por LIST STATUS?

Saludos,
Víctor.
Lambaré - Paraguay.

Claudio Luna

unread,
Feb 9, 2015, 8:31:20 PM2/9/15
to Comunidad de Visual Foxpro en Español
Victor en la consulta hay que agregar la clausula nofilter.
Te paso un link donde hablan sobre el tema>
Saludos

Alex Vargas

unread,
Feb 9, 2015, 8:44:11 PM2/9/15
to publice...@googlegroups.com
Claro   09.00.0000.7423
status.txt

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 8:50:53 PM2/9/15
to publice...@googlegroups.com
Hola Alex

Me gustaría ver el STATUS antes del cierre de la tabla y el cursor.

Messagebox([RECCOUNT("curAux"): ] + Transform(Reccount("curAux")) ;
+ [    _Tally: ] + Transform(_Tally))

LIST STATUS TO status.txt

Use In Select("Tmp")
Use In Select("curAux")

Saludos,
Víctor.
Lambaré - Paraguay.

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 8:55:15 PM2/9/15
to publice...@googlegroups.com
Hola Claudio

Es correcto lo que apuntas, me costó un buen tiempo darme cuenta, por eso en represalia prefiero usar _Tally ;-)

Lo que me parece incongruente es que con una tabla con índices se comporte de manera diferente a una tabla sin índices. Cuando la tabla tiene .cdx genera el cursor filtrando la tabla sin crear un archivo temporal.

Saludos,
Víctor.
Lambaré - Paraguay.

Alex Vargas

unread,
Feb 9, 2015, 8:58:43 PM2/9/15
to publice...@googlegroups.com
Con gusto, ajunto.

Saludos

Alex A. Vargas
status.txt

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 9:04:49 PM2/9/15
to publice...@googlegroups.com
Hola Alex

En ese escenario coinciden los valores de RECCOUNT("curAux") y _Tally, pero si generas el índice de la tabla, Index On IdTmp Tag IdTmp,  podrás ver que los resultados son diferentes a pesar de que el cursor está vacío.

Saludos,
Víctor.
Lambaré - Paraguay.


Alex Vargas

unread,
Feb 9, 2015, 9:13:58 PM2/9/15
to publice...@googlegroups.com
No Victor, en ambos casos me retorna el mismo resultado.
Adjunto status.txt con indice y sin el
status.txt

César Pistiner

unread,
Feb 9, 2015, 9:54:58 PM2/9/15
to publice...@googlegroups.com

Hola Víctor

El famoso problema de no usar el nofilter en la sentencia de select. También pasa con los campos que no obtienes en la sentencia, si consultas por ellos te retorna un valor!!!

A veces vfp para optimizar en vez de crear un nuevo cursor lo que hace es filtrar la tabla de origen y mostrarte solos los campos que pediste.

Muchísimos problemas nos trajo esto en su momento.

Saludos,
César

HernanCano

unread,
Feb 9, 2015, 10:16:27 PM2/9/15
to mundovis...@googlegroups.com, publice...@googlegroups.com

Messagebox([RECCOUNT("curAux"): ] + Transform(Reccount("curAux")) ;
+ [    _Tally: ] + Transform(_Tally))

*Use In Select("Tmp")
*Use In Select("curAux")

CLEAR
1
SKIP -1
?RECNO(),EOF(),bOF()  && muestra 6, .t., .t.
5
SKIP 
?RECNO(),EOF(),bOF()  && muestra 6, .t., .f.
--

(( Los comentarios en la "Comunidad de Visual Foxpro en Español" están muy bien.. ))

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 10:48:12 PM2/9/15
to publice...@googlegroups.com
Hola Alex

Estoy sorprendido y confundido :-(

Saludos,
Víctor.
Lambaré - Paraguay.

Alex Vargas

unread,
Feb 9, 2015, 10:52:07 PM2/9/15
to publice...@googlegroups.com
Seguis con los mismos resultados?

Alex A. Vargas

HernanCano

unread,
Feb 9, 2015, 11:08:20 PM2/9/15
to mundovis...@googlegroups.com, publice...@googlegroups.com

close databases 
If File("Tmp.dbf")
Erase Tmp.Dbf
Endif
If File("Tmp.cdx")
Erase Tmp.Cdx
Endif

Create Table Tmp( IdTmp I, AlgunCampo C(30))
For lnReg = 1 To 5
Insert Into Tmp Values (m.lnReg, "Algún valor del Reg.: " + Transform(m.lnReg))
Endfor
Index On IdTmp Tag IdTmp  && es cuando Víctor nos reporta que hay bug...

Browse

Select * From Tmp Where IdTmp > 5 Into Cursor curAux && nofilter
   && un primer  ensayo: con nofilter comentarizado
   && un segundo ensayo: con nofilter des-comentarizado

Browse

Messagebox([Reccount("curAux"): ] + Transform(Reccount("curAux")) ;
+ [    _Tally: ] + Transform(_Tally))

*Use In Select("Tmp")
*Use In Select("curAux")

clear

?'   alias() : ',alias()
?'     dbf() : ',dbf()
?'  filter() : ',filter()   && ---> muestra IdTmp>5 (cuando  nofilter está comentarizado)
?'file(dbf()): ',file(dbf())
?'   _tally  : ',_tally
?'reccount() : ',reccount()
1
skip -1
?recno(),eof(),bof()  && muestra 6, .t., .t.
5
skip 
?recno(),eof(),bof()  && muestra 6, .t., .f.


#if .f.

La solución que se entiende de ese tema (la indica el colega Cetin Basoz), es que se debe usar NOFILTER (o READWRITE, o 'adding a non existant field') en el SELECT (o agregar AND .T. en verisones anteriores), a pesar que MikeLewis no haya estado de acuerdo, pues decía que "primero se debe saber qué es lo que pasa".

Mi conclusión es que sí sabe qué es lo que pasa: el SELECT es optimizable, y VFP lo optimiza no generando un cursor, sino filtrando el DBF original (al mismo estilo de SET FILTER TO).

Esta conclusión la demuestro con el script que adjunto.

Pero también me queda la misma sensación del colega que se hace llamar 'Nro': no uso filtros, pero me han gustado mucho los cursores.

#endif

HernanCano

unread,
Feb 9, 2015, 11:12:51 PM2/9/15
to publice...@googlegroups.com, mundovis...@googlegroups.com

?' version() : ',version() && HCano: 9.00.0000.7423
 

Víctor Hugo Espínola Domínguez

unread,
Feb 9, 2015, 11:26:55 PM2/9/15
to publice...@googlegroups.com
Hola César

Uso bastante la cláusula NOFILTER para poder hacer SELECT de un cursor generado en una consulta, las veces que olvidé incluirla el VFP tenía la gentileza de avisarme, pero en este caso yo estaba seguro que el cursor debía estar vacío y el maldito RECCOUNT me decía otra cosa a pesar de que mis cansados y somnolientos ojos veían mediante el BROWSE que el cursor sí estaba vacío :-(, hasta que mirando la parte inferior de la pantalla vi en la barra de estado "RECORD: EOF/5" y ahí entendí lo que estaba pasando.

Saludos,
Víctor.
Lambaré - Paraguay.

Fernando D. Bozzo

unread,
Feb 10, 2015, 8:34:54 AM2/10/15
to mundovis...@googlegroups.com, publice...@googlegroups.com
Hola Victor Hugo:

Hernán tiene razón y lo argumenta perfecto.

Pero además parte de esto está explicado en la ayuda de Fox, específicamente en la ayuda de SELECT-SQL bajo el apartado "INTO or TO Clause":

CURSOR CursorName [NOFILTER | READWRITE]

Stores query results in a temporary cursor.

Note

If you specify the name of an open table, Visual FoxPro generates an error message. After SELECT is executed, the temporary cursor remains open and is active and read-only unless you specify the READWRITE option. When you close this temporary cursor, it is deleted. Cursors can exist as a temporary file on the drive or volume specified by SORTWORK.

NOFILTER creates a cursor that can be used in subsequent queries.

Note

Including NOFILTER can reduce query performance because it creates a temporary table on disk. When the cursor is closed, the temporary table is deleted from disk.

READWRITE specifies that the temporary cursor is modifiable. If the source table or tables use auto-incrementing, the cursor created with READWRITE does not inherit those settings. You can create more than one structural index on a cursor using the READWRITE argument.


Por otro lado, si en tu programa no cerrás las tablas/cursores al final (comentá los USE) vas a poder comprobar que ambos son la misma tabla:


? DBF("tmp")
C:\DESA\TEST\VARIOS\VISTOR HUGO ESPINOLA\TMP.DBF

? DBF("curaux")
C:\DESA\TEST\VARIOS\VISTOR HUGO ESPINOLA\TMP.DBF


Otra: En la ayuda de RECCOUNT dice esto:

The value RECCOUNT( ) returns isn't affected by SET DELETED and SET FILTER.

O sea, que retorna lo que haya físicamente en la tabla, sin importar qué filtros haya



En resumen, la ayuda de Fox tiene muchas cosas y muy buena información, incluso algunos artículos, que se desconocen porque pocos se atreven a leerla ;-)


Saludos.-

Ricardo Peña

unread,
Feb 10, 2015, 9:53:41 AM2/10/15
to GRUPO-VFP GRUPO-VFP, mundovis...@googlegroups.com
Disculpen la tardanza en mi respuesta.  Recién me puedo sentar
a ver esto.
 
Me parece que todo funciona bien.
 
La sentencia

 
Select * From Tmp Where IdTmp > 5 Into Cursor curAux
 
no deja afuera todos los registros por la cláusula where dado
que IdTmp vale entre 1 y 5 ?

Ricardo Luis Peña
Analista de Sistemas
BA - Argentina
011-15-4440-7378
 

Date: Mon, 9 Feb 2015 20:34:07 -0300
Subject: [vfp] Bug en RECCOUNT de cursor?
From: vich...@gmail.com
To: publice...@googlegroups.com; mundovis...@googlegroups.com

Víctor Hugo Espínola Domínguez

unread,
Feb 10, 2015, 10:10:24 AM2/10/15
to publice...@googlegroups.com
Hola Ricardo

Se genera un cursor vacío, pero RECCOUNT("curAux") ==>> 5 cuando la tabla posee indices, porque es optimizable y no se genera una tabla temporal para el cursor, el VFP hace lo siguiente:

USE Tmp AGAIN ALIAS "curAux" IN 0
SELECT curAux
SET FILTER TO IdTmp > 5

Se debe usar _Tally para saber la cantidad de registros del cursor, o usar una cláusula adicional como NOFILTER o READWRITE o incluir un campo adicional que no pertenezca a la tabla fuente.

Saludos,
Víctor.
Lambaré - Paraguay.

Ricardo Peña

unread,
Feb 10, 2015, 10:23:10 AM2/10/15
to GRUPO-VFP GRUPO-VFP
Sigo sin entender.  Posiblemente deba cambiar la medicación (jajajaja)
 
A mi me da
 
 
 
 
 
La cláusula where del select no selecciona ningún registro y el resultado
es correcto para el reccount() y para el _tally
 
por favor que alguien  me avive en dónde me equivoco !!!!!!!!!!!!!!!



Ricardo Luis Peña
Analista de Sistemas
BA - Argentina
011-15-4440-7378


 

Date: Tue, 10 Feb 2015 12:10:22 -0300
Subject: Re: [vfp] Bug en RECCOUNT de cursor?
0000.jpg

Víctor Hugo Espínola Domínguez

unread,
Feb 10, 2015, 11:11:05 AM2/10/15
to publice...@googlegroups.com
Hola Ricardo

La única explicación que se me ocurre es que no está creando el índice, lanza un DISPLAY STATUS antes del cierre de la tabla y el cursor.

Saludos,
Víctor.
Lambaré - Paraguay.

HernanCano

unread,
Feb 10, 2015, 12:20:38 PM2/10/15
to mundovis...@googlegroups.com, publice...@googlegroups.com
>>>  The value RECCOUNT( ) returns isn't affected by SET DELETED and SET FILTER.

Exacto, Fernando. Lo que pasa es que no sabíamos que crear un cursor se comportara como SET FILTER.... por no leer las ayudas, claro....

Debo predicar con el ejemplo... Por no leer sobre SELECT... NOFILTER me pasa ésto.....

Lo de que se reduzca la performance no me inquieta. Prefiero la seguridad al desempeño: incluiré NOLFILTER y/o READWRITE al generar cursores (VFP9). Cuando necesite desempeño, considero que me daré cuenta.

Jhonny Zambrana

unread,
Feb 10, 2015, 1:58:04 PM2/10/15
to publice...@googlegroups.com, mundovis...@googlegroups.com
Comparto lo dicho  por Fernando D. Bozzo pero sufro del gran mal de la flojera, la yuda es un gran libro peroooooooo....!!!!!!! tenemos que leerlaaa????? y algunas veces suena un poco enrevesado..!!!

buenos dias. compañeritos del kinder..!!!

Víctor Hugo Espínola Domínguez

unread,
Feb 10, 2015, 5:55:45 PM2/10/15
to publice...@googlegroups.com
Hola Hernán

>crear un cursor se comportara como SET FILTER.... 

No siempre, solo si la expresión del WHERE es optimizable. En el ejemplo si reemplazas "IdTmp > 5" por "AlgunCampo = [Cualquier cosa]" se crea la tabla temporal para el cursor y coinciden los valores devueltos por RECCOUNT y _TALLY.

Saludos,
Víctor.
Lambaré - Paraguay.

HernanCano

unread,
Feb 10, 2015, 6:03:46 PM2/10/15
to publice...@googlegroups.com
Sí, Víctor. Lo lemento ya había expresado éso... sólo que no lo volví a repertir.

César Pistiner

unread,
Feb 10, 2015, 7:50:38 PM2/10/15
to publice...@googlegroups.com

Te entiendo perfectamente Víctor!!

Mas de una vez me quitó el sueño esto, y por más que esté aclarado en la ayuda es un detalle que se olvida fácilmente, en mi caso yo no me lo olvidaba al programar pero al supervisar código de otros compañeros del equipo ni me daba cuenta de ese detalle... Y después las consecuencias jaja

Por eso cuando creamos nuestra capa de datos estos problemas se solucionaron de raíz.

Saludos,
César

César Pistiner

unread,
Feb 10, 2015, 7:55:13 PM2/10/15
to publice...@googlegroups.com

Jaja te equivocaste de pastillita Ricardo!

Mira creo que VFP OPTIMIZA en base al entorno donde se ejecuta así que es posible que en tu caso sí genere un cursor temporal.

Saludos,
César

Reply all
Reply to author
Forward
0 new messages