Page 1 of 1

dc_setscopearray() - dc_dbgoto() bug

Posted: Sat Aug 21, 2010 5:49 am
by skiman
Hi Roger,

dc_setscopearray() is a very powerfull tool to use. I use it quite a lot. Sometimes I encountered a problem with record position. I found that the dc_dbgoto() isn't working.

See the sample below, is can be used with any database and index if there are at least 100 records. Just change dbffile and ntxfile to the correct names.

dc_dbskip(0) is also doing something weird. However, this isn't used in my application.

Code: Select all

use dbffile alias customer new      
set index to ntxfile

for x = 1 to 100 step 3
	aadd(aRecords,x)
next
customer->(dc_setscopearray(aRecords))
customer->(dc_dbgotop())
wtf customer->(recno())   // 1
customer->(dc_dbskip(1))
wtf customer->(recno())   // 4
customer->(dc_dbskip(1)) 
wtf customer->(recno())   // 7
customer->(dc_dbgoto(31))
wtf " goto 31 " , customer->(recno())   // should be 31 but stays on 7
customer->(dc_dbskip(1)) 
wtf customer->(recno())   // 10
customer->(dc_dbskip(1)) 
wtf customer->(recno())   // 13
customer->(dc_dbskip(0)) 
wtf "skip 0 " , customer->(recno())   // last record in file, in my test record 129
customer->(dc_dbgoto(31))
wtf "goto 31 " , customer->(recno())   // should be 31 but stays on 129.
customer->(dc_dbgobottom())
wtf "bottom" , customer->(recno())   // 100 

I hope you can find the solution for this.

Re: dc_setscopearray() - dc_dbgoto() bug

Posted: Mon Aug 23, 2010 10:02 am
by rdonnay
Chris -

Have you tried dbGoto() insted of DC_DbGoTo().

I think I recall that DC_DbGoTo() was designed to disallow selection of a record that is not in scope.

Record 31 would not be in the scope array.

Roger

Re: dc_setscopearray() - dc_dbgoto() bug

Posted: Mon Aug 23, 2010 11:06 am
by skiman
Hi Roger,

Record 31 is in the array, it is on position 11. Since it starts with 1, next are 4,7,10,...,31,34,...

dbgoto() is working, but the next dc_dbskip(1) isn't correct after a dbgoto(). The dc_dbskip(1) skips to the next element in the array.

Code: Select all

dc_dbgotop()  -> element 1, record 1
dbgoto(31) -> record 31
dc_dbskip(1) -> element 2, record 4.
I suppose that dc_dbgoto(31) should position the pointer to the correct array element. This is the only way a dc_dbskip(1) or dc_dbskip(-1) can work correct afterwards?

Re: dc_setscopearray() - dc_dbgoto() bug

Posted: Mon Aug 23, 2010 12:10 pm
by rdonnay
Yes, you are correct.

I should fix that.

I'll send you a fix.

Re: dc_setscopearray() - dc_dbgoto() bug

Posted: Mon Aug 23, 2010 1:27 pm
by rdonnay
Add a line of code to the DC_DbGoTo() function in _DCSCOPE.PRG as shown below.
Rebuild DCLIPX.DLL by running BUILD19_SL1.BAT.

This should fix it.

Code: Select all

FUNCTION DC_DbGoTo( nRecNo, xDataSource )

LOCAL cDataType := Valtype(xDataSource), aScopeArray, nPointer

IF xDataSource == NIL
  aScopeArray := DC_SetScopeArray()
  IF !Empty(aScopeArray)
    nPointer := AScan( aScopeArray, nRecNo )
    IF nPointer > 0
      DC_SetScopeArrayPointer(nPointer)
      _dbGoTo(nRecNo)   // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ENDIF
  ELSE
    _dbGoTo(nRecNo)
  ENDIF
ELSEIF cDataType == 'C'  // It's an alias
  aScopeArray := (xDataSource)->(DC_SetScopeArray())
  IF !Empty(aScopeArray)
    nPointer := AScan( aScopeArray, nRecNo )
    IF nPointer > 0
      (xDataSource)->(DC_SetScopeArrayPointer(nPointer))
    ENDIF
  ENDIF
ELSEIF cDataType == 'N'  // It's an ADS SQL cursor
  RETURN AdsGoToRecord( xDataSource, nRecNo )
ELSEIF cDataType == 'O'  // It's an SQLexpress cursor
  RETURN xDataSource:goTo(nRecNo)
ENDIF

RETURN nil

Re: dc_setscopearray() - dc_dbgoto() bug

Posted: Tue Aug 24, 2010 12:24 am
by skiman
Fixed. :dance: