xbrowse / ADS failure

Post Reply
User avatar
TimStone
Posts: 2536
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Contact:

xbrowse / ADS failure

Post by TimStone »

In another thread, we identified there is still a continuing problem with xBrowse and ADS.

When we open a browse and the dbf does not have an index opened, when going towards the end of the file, the pointer has an error. We have shown this consistently and it has also been previously reported by at least one other person. If an index is open, the error does not occur.

The previous threads on this topic were specific and the error was noted, but no fix has yet taken place.

The specific build uses FWH 15.09 xBrowse, Harbour, MSVC 2013, and ADS Server mode.

Can we please go back and get this resolved correctly ? Thank you. Although the temporary work around is to set the index before browsing the file, often we want to go to the last records added and natural order ( no index ) is the fastest way.
Tim Stone
http://www.MasterLinkSoftware.com
timstone@masterlinksoftware.com
Using: FWH 19.06 with Harbour 3.2.0 / Microsoft Visual Studio Community 2019
User avatar
Giovany Vecchi
Posts: 129
Joined: Mon Jun 05, 2006 9:39 pm
Location: Brasil

Re: xbrowse / ADS failure

Post by Giovany Vecchi »

All these navigation problems xbrowse already decided to put runs on TADs class, The Linear Sr could study and add in xBrowse class.

In xbrowse.prg method SetRdd() change:

Code: Select all

   If ( "ADS"$( ::cAlias )->( RddName() ) .or. 'ADT' $ ( ::cAlias )->( RddName() ) ) //.and. ;
      //( ::cAlias )->( LastRec() ) > 200

      // Modified in FWH 9.06
      // AdsGetRelKeyPos() returns approximate position as % and when multipilied by 100 and rounded off
      // returns incorrect values occassionally on smaller  tables. OrdKeyNo() mapped to AdsKeyNo() gives reliable
      // result in such cases. For large tables OrdKeyNo() is unacceptably slow. Limit of 200 is chosen because
      // 0.5% is 1/200.

      cAdsKeyNo    := "{| n, Self | iif( n == nil, " +;
                         "nCalcRelPos( " + cAlias + "->( ADSGetRelKeyPos() ) * Self:nLen, Self ), "+;
                         cAlias + "->( ADSSetRelKeyPos( n / Self:nLen ) ) ) }"

      cAdsKeyCount := "{|| " + cAlias + "->( ADSKeyCount(,,1) )}" 

      DEFAULT ::bKeyNo    := &cAdsKeyNo ,;
              ::bKeyCount := &cAdsKeyCount

 
Function nCalcRalPos()

Code: Select all

FUNCTION nCalcRelPos(f_nVal,f_oXBrw)
  Local nLenRegs := f_oXBrw:nLen, nRowPos := f_oXBrw:nRowSel
  Local nRetorno := 0
  
  nRetorno := Round(f_nVal,3)
  
  If nRetorno == 0
    nRetorno := 1
  EndIf

  If nRetorno < nRowPos
    nRetorno := nRowPos
  EndIf  

  nRetorno := Int(nRetorno)

RETURN nRetorno
 
When I use the TADS class I use the tCtrlxBrw class ()
here is the class, most only works with TADS ().

Class tCtrlxbrw:

Code: Select all

#Include "Fivewin.ch"
#Include "xBrowse.ch"

#Define df_BaseMySql    1

Class tCtrlxBrw 

  Data oXBrwCtrl, oDbDs_DataBaseAds
  Data bStrData
  Data oGetDsFilter, nTpCampoFilter, cCampoFilter, lLastRecZero
  Data bChangeBrw
  
  Method New(f_oXBrowse,f_oDbDs_DataBaseAds) Constructor
  Method End()

  Method SetTAds()
  
  Method tCtrlxBrw_Skip(f_nKip)
  
  Method tCtrlxBrw_Seek(f_oBjCol,f_uVar)
  Method tCtrlxBrw_EditFilterRdd()
  Method tCtrlxBrw_EditFilterSql()
  Method tCtrlxBrw_EditChange()
  Method tCtrlxBrw_EditClearChar(f_cTxt, f_nTipo)


Endclass
//-----------------------------------------------------------------------------
Method New(f_oXBrowse,f_oDbDs_DataBaseAds,f_aGetFilter) Class tCtrlxBrw
  Local oSelf

  // f_aGetFilter[1] > oBjeto Get
  // f_aGetFilter[2] > Tipo Filtro 1=SetAof contains / 2=Sql select Contains
  // f_aGetFilter[3] > Nome do campo a pesquisar
   
  ///Override Method Skip In Class Txbrowse With oSelf:tCtrlxBrw_Skip

  ::lLastRecZero := .F.

  ::oDbDs_DataBaseAds     := f_oDbDs_DataBaseAds
  ::oXBrwCtrl             := f_oXBrowse
  
  ::oXBrwCtrl:cAlias      := ::oDbDs_DataBaseAds:cAlias
  
  If !Hb_IsNil(f_aGetFilter)

    ::oGetDsFilter    := f_aGetFilter[1]
    ::nTpCampoFilter  := f_aGetFilter[2]
    ::cCampoFilter    := f_aGetFilter[3]
    
    If f_aGetFilter[2] == 2 // Sql Contains
      ::oGetDsFilter:bChange := {||::tCtrlxBrw_EditFilterSql()}
    
    ElseIf f_aGetFilter[2] == 1 // Rdd set aof

      ::oGetDsFilter:bChange := {||::tCtrlxBrw_EditFilterRdd()}
      
    EndIf

    ::bChangeBrw := ::oXBrwCtrl:bChange
    ::oXBrwCtrl:bChange    := {||::tCtrlxBrw_EditChange()}
    ::oXBrwCtrl:bGotFocus  := {||::tCtrlxBrw_EditChange()}
    
  EndIf  

  ::oXBrwCtrl:bClrSel := {|| { CLR_BLACK, CLR_HGRAY} } // Giovany
  ::SetTAds()
  ::oDbDs_DataBaseAds:Refresh()

Return Self
//-----------------------------------------------------------------------------
Method End() Class tCtrlxBrw

Self := Nil

Return Nil
//-----------------------------------------------------------------------------
Method SetTAds() Class tCtrlxBrw
  Local nTpGetRelPos := 1, cTmpQry := "", nTmp := 0

  ::oDbDs_DataBaseAds:lBufferOnSkip := .T.
  
  If ::oDbDs_DataBaseAds:nOpenType == 3 // Open via Dataset
    cTmpQry := Upper(::oDbDs_DataBaseAds:cQrySql)
    If At("{STATIC}",cTmpQry) == 0 
      nTpGetRelPos := 2
    Else
      nTpGetRelPos := 1 
    EndIf
  Else
    nTpGetRelPos := 1
  EndIf

  If nTpGetRelPos == 2 // Open via Sql Dataset cursor vivo 

    ::oXBrwCtrl:bKeyNo    := {| n, _Self | If( n == nil, ;
                                   nCalcRelPos((::oDbDs_DataBaseAds:GetRelKeyPos() * _Self:nLen) /10,::oXBrwCtrl) , ;
                                   ::oDbDs_DataBaseAds:SetRelKeyPos( Round(n / _Self:nLen,3) ) ) }

  Else // Viao Rdd ou Static Cursor

    ::oXBrwCtrl:bKeyNo    := {| n, _Self | If( n == nil, ;
                                 nCalcRelPos((::oDbDs_DataBaseAds:GetRelKeyPos() * _Self:nLen),::oXBrwCtrl ) , ;
                                 ::oDbDs_DataBaseAds:SetRelKeyPos( Round(n / _Self:nLen,3) ) ) }

  EndIf

  ::oXBrwCtrl:bBookMark := {| n | iif( n == nil,;
                               ::oDbDs_DataBaseAds:Recno() , ;
                               ::oDbDs_DataBaseAds:GoTo( n ) ) }

  ::oXBrwCtrl:bKeyCount := {|| ::oDbDs_DataBaseAds:KeyCount(1)  }
  
  ::oXBrwCtrl:bBof      := { ||  ::oDbDs_DataBaseAds:Bof() }
  ::oXBrwCtrl:bEof      := { ||  ::oDbDs_DataBaseAds:Eof() }
  ::oXBrwCtrl:bSkip     := { |n| Iif( n == Nil, n := 1, ), ::tCtrlxBrw_Skip( n )} 
  ::oXBrwCtrl:bGoTop    := { ||  ::oDbDs_DataBaseAds:GoTop() }
  ::oXBrwCtrl:bGoBottom := { ||  ::oDbDs_DataBaseAds:GoBottom() }

  ::oDbDs_DataBaseAds:OnSkip()

Return Nil
//-----------------------------------------------------------------------------
Method tCtrlxBrw_Skip(f_nSkip) Class tCtrlxBrw
  Local nSkipper := 0
  
  Default f_nSkip := 1 

  nSkipper := (::oDbDs_DataBaseAds:cAlias)->(DbSkipper(f_nSkip))

  ::oDbDs_DataBaseAds:OnSkip()
  
Return nSkipper  
//-----------------------------------------------------------------------------
Method tCtrlxBrw_Seek(f_oBjCol,f_uVar,f_lTpSeek) Class tCtrlxBrw
LOCAL nRecMarca := ::oDbDs_DataBaseAds:Recno(), cTpData := ""

  cTpData := VALTYPE(f_uVar)
  
  IF cTpData == "N"
     f_lTpSeek := .F.
  ELSEIF cTpData == "D"
     f_lTpSeek := .F.
  ELSEIF cTpData == "C"
     f_lTpSeek := .T.
  ENDIF
  
  //If ::oDbDs_DataBaseAds:nOpenType == 1
    f_oBjCol:SetOrder()
    ::oDbDs_DataBaseAds:Seek(f_uVar,f_oBjCol:cSortOrder,f_lTpSeek)
  //EndIf
  
  IF ::oDbDs_DataBaseAds:EOF()
  
     ::oDbDs_DataBaseAds:GoTo(nRecMarca)
     
     MSGSTOP("A ocorrencia solicitada não foi encontrada.",;
             "Procedimento abortado...")
  
  ENDIF
  ::oXBrwCtrl:Refresh(.T.)
  
  IF ::oXBrwCtrl:bChange != nil
     EVAL(::oXBrwCtrl:bChange)
  ENDIF

RETURN NIL
//-----------------------------------------------------------------------------
Method tCtrlxBrw_EditFilterRdd() Class tCtrlxBrw
  Local cTxtDigitacao := "", cAof := ""

  //::oGetDsFilter:Save()
  cTxtDigitacao := Alltrim(::tCtrlxBrw_EditClearChar(::oGetDsFilter:cText))

  If Len(cTxtDigitacao) < 5
    cTxtDigitacao := ""
  Else
    ::lLastRecZero := .F.
  EndIf
  
  If ::lLastRecZero
    Return Nil
  EndIf
  ///? cTxtDigitacao

  cAof := "CONTAINS("+::cCampoFilter+","+cTxtDigitacao+")"

    ::oGetDsFilter:oWnd:cTitle := cAof
    ::oGetDsFilter:oWnd:Refresh()
    ///msginfo(cAof)
    
    ::oDbDs_DataBaseAds:Filter(cAof)
    ::oDbDs_DataBaseAds:GoTop()
  ::oXBrwCtrl:Refresh(.T.)

  If Len(cTxtDigitacao) < 5
    ::lLastRecZero := .T.
  EndIf

Return Nil
//-----------------------------------------------------------------------------
Method tCtrlxBrw_EditFilterSql() Class tCtrlxBrw
  Local cTxtDigitacao := ""

  //::oGetDsFilter:Save()
  cTxtDigitacao := Alltrim(::tCtrlxBrw_EditClearChar(::oGetDsFilter:cText))

  If Len(cTxtDigitacao) < 5
    cTxtDigitacao := ""
  Else
    ::lLastRecZero := .F.
  EndIf
  
  If ::lLastRecZero
    Return Nil
  EndIf
  ///? cTxtDigitacao

  ::oDbDs_DataBaseAds:aVarsSql := {{"_TxtDigitacao_",cTxtDigitacao},;
                                   {"_Campo_",::cCampoFilter}}
  
  ::oDbDs_DataBaseAds:DsExecute()
  ::oXBrwCtrl:Refresh(.T.)

  If Len(cTxtDigitacao) < 5
    ::lLastRecZero := .T.
  EndIf

Return Nil
//-----------------------------------------------------------------------------
Method tCtrlxBrw_EditChange() Class tCtrlxBrw

  If ::oDbDs_DataBaseAds:LastRec() == 0
    Return Nil
  EndIf
  
  ::oGetDsFilter:VarPut(::oDbDs_DataBaseAds:VarGet(::cCampoFilter))
  ::oGetDsFilter:Refresh()
  
  If !Hb_IsNil(::bChangeBrw)
    Eval(::bChangeBrw)
  EndIf
  
Return Nil

//-----------------------------------------------------------------------------
Method tCtrlxBrw_EditClearChar(f_cTxt) Class tCtrlxBrw
  Local cRetTxt := f_cTxt
  Local iFor := 0, cAnd := ""
  Local aCharDeletes := { chr(34),"-",".","+","=","&","'","´"}
  Local aPalavras := {}
  
  cRetTxt := _CHAR_CLEAN(cRetTxt,{ " AND ",;
                                      " NEAR ",;
                                      " ANY "})

  For iFor := 1 To Len(aCharDeletes)
    cRetTxt := StrTran(cRetTxt,aCharDeletes[iFor]," ")
  Next

  aPalavras := Hb_aTokens(cRetTxt)

  cRetTxt := ""
  For iFor := 1 To Len(aPalavras)
    If Len(aPalavras[iFor]) > 3
      cRetTxt += (cAnd + Chr(34)+aPalavras[iFor])+Chr(34) //+ " "
      cAnd := " and "
    Endif
  Next

Return cRetTxt
///////////////////////////////////////////////////////////////////////////////
FUNCTION nCalcRelPos(f_nVal,f_oXBrw)
  Local nLenRegs := f_oXBrw:nLen, nRowPos := f_oXBrw:nRowSel
  Local nRetorno := 0
  
  nRetorno := Round(f_nVal,3)
  
  If nRetorno == 0
    nRetorno := 1
  EndIf

  If nRetorno < nRowPos
    nRetorno := nRowPos
  EndIf  

  nRetorno := Int(nRetorno)

RETURN nRetorno
///////////////////////////////////////////////////////////////////////////////
FUNCTION _CHAR_CLEAN(f_cTxt,f_aCaracteresRetira)
    Local cTxtRetorno := f_cTxt, iFor := 0
    
    For iFor := 1 To Len(f_aCaracteresRetira)
    cTxtRetorno := StrTran(cTxtRetorno,f_aCaracteresRetira[iFor],"")
  Next
   
RETURN cTxtRetorno

 
Exemplo com tAds

Code: Select all

  ::oDb_BoletoNucleo  := DB_BOLNUCL():OpenRdd()

  ::oBrw361_Remessas                     := tXBrowse():New( ::oDlgBoletosGeral )
  ::oBrw361_Remessas:cAlias              := ::oDb_BoletoNucleo:cAlias
  ::oBrw361_Remessas:nMarqueeStyle       := MARQSTYLE_HIGHLROW
  ::oBrw361_Remessas:nRowDividerStyle    := LINESTYLE_BLACK
  ::oBrw361_Remessas:nColDividerStyle    := LINESTYLE_BLACK
  ::oBrw361_Remessas:nColSel             := 1
  ::oBrw361_Remessas:l2007               := .T.
  ::oBrw361_Remessas:nRowHeight          := 24
  ::oBrw361_Remessas:nHeaderHeight       := 24 
  ::oBrw361_Remessas:bClrRowFocus        := {||{ GetSysColor( 9 ), GetSysColor( 16 )}}
  ::oBrw361_Remessas:lFooter             := .F.

  aadd(aColunas,Nil)
  nColTmp := Len(aColunas)
  aColunas[nColTmp] := ::oBrw361_Remessas:AddCol()
    With Object aColunas[nColTmp]
      :bStrData         := {||::oDb_BoletoNucleo:dProcesso}
      :cHeader          := "Dt. Imp. "
      :nWidth           := 90
      :nDataStrAlign    := AL_RIGHT
      :nHeadStrAlign    := AL_RIGHT
      :cSortOrder       := "dProcesso"
      :nEditType        := EDIT_GET
      //:cEditPicture     := "!"
      //:bEditValue       := {||}
      //:bEditWhen        := {||}
      //:bEditValid       := {||}
      //:aEditListTxt     := {}
      :AddResource("B16_BRWSEEK") // Bitmaps
      :AddResource("B16_LED_RED_1") // Bitmaps
      :nHeadBmpNo       := 1 
      //:bBmpData         := {||}
      //:nBtnBmp          := 2
      //:bEditBlock       := {|oSelf|::Fun_Menus(01,oSelf)}
      :bOnPostEdit      := {|ooBj,vVar,nKey|::oCtrl361_Remessas:tCtrlxBrw_Seek(ooBj,vVar)} // Automatic seek on Presskey
      //:cFooter          := "Total"
      //:bFooter          := {||20+20}
      //:nFootStrAlign    := 1
    //:nTotal           := 0
    //:lTotal           := .T.
      //:nFootStrAlign    := 1 
  
    End With 

  aadd(aColunas,Nil)
  nColTmp := Len(aColunas)
  aColunas[nColTmp] := ::oBrw361_Remessas:AddCol()
    With Object aColunas[nColTmp]
      :bStrData         := {||::oDb_BoletoNucleo:nOcorrencias}
      :cHeader          := "Qta "
      :nWidth           := 30
      :nDataStrAlign    := AL_RIGHT
      :nHeadStrAlign    := AL_RIGHT
  
    End With 


  ::oBrw361_Remessas:SetRDD()
  ::oBrw361_Remessas:CreateFromResource(361)
    
  aColunas[1]:SetOrder()
  ::oBrw361_Remessas:GoTop()
  ::oBrw361_Remessas:SetFocus()
  ::oBrw361_Remessas:Refresh()

  ::oCtrl361_Remessas  := tCtrlxBrw():New(::oBrw361_Remessas,::oDb_BoletoNucleo) // Class tCtrlxBrw control xbrowse


 
User avatar
TimStone
Posts: 2536
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Contact:

Re: xbrowse / ADS failure

Post by TimStone »

I appreciate the alternative, but I really think the most appropriate solution is to get a fix for the bug !

Antonio ? Did you receive a response to your inquiries ?

The problem does not exist with xHarbour ( .com ) builds, or DBFCDX, only ADS with Harbour ... so surely we can get the error fixed.
Tim Stone
http://www.MasterLinkSoftware.com
timstone@masterlinksoftware.com
Using: FWH 19.06 with Harbour 3.2.0 / Microsoft Visual Studio Community 2019
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: xbrowse / ADS failure

Post by Antonio Linares »

Tim,

Could you prepare a small and self contained example without using FWH that reproduces the error ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
TimStone
Posts: 2536
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Contact:

Re: xbrowse / ADS failure

Post by TimStone »

Antonio,

This has been discussed in another thread, and Rao identified the exact lines in the xBrowse code that creates the error.

In addition, others had the exact same result.

He indicated he knew what was causing the error, but then the topic was never resolved.
Thanks for testing. From the result of your tests we understand that OrdKeyGoTo() works with dbfcdx RDD even when there is no index and with ADS RDD it fails. When I made this change in 2009 I am sure it was working and at that time most of my applications were using ADSCDX.

If you are using Harbour we need to check with xHarbour version also.
Surprisingly it appears these functions are working:
AdsGetRelKeyPos
AdsSetRelKeyPos
AdsGetKeyCount
Theoretically, these functions also should depend on the index still they work.

Interestingly there is AdsGetKeyPos() function in ACE but no comparable function to OrdKeyGoTo()

I suggest you please continue with the change we proposed earlier.
I study both xHarbour and Harbour versions of the RDD source and also Advantage documentation and implement a dependable solution.
That dependable solution was never provided.

Tim
Tim Stone
http://www.MasterLinkSoftware.com
timstone@masterlinksoftware.com
Using: FWH 19.06 with Harbour 3.2.0 / Microsoft Visual Studio Community 2019
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: xbrowse / ADS failure

Post by Antonio Linares »

We need Rao help on this
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
TimStone
Posts: 2536
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Contact:

Re: xbrowse / ADS failure

Post by TimStone »

Did you get in touch with him ?
Tim Stone
http://www.MasterLinkSoftware.com
timstone@masterlinksoftware.com
Using: FWH 19.06 with Harbour 3.2.0 / Microsoft Visual Studio Community 2019
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: xbrowse / ADS failure

Post by nageswaragunupudi »

Mr Tim

I'll get back on this very soon
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: xbrowse / ADS failure

Post by nageswaragunupudi »

Regards

G. N. Rao.
Hyderabad, India
Post Reply