XBROWSE : Error in method Delrepos

Re: XBROWSE : Error in method Delrepos

Postby Otto » Sat Mar 14, 2009 1:17 pm

Thank you, Antonio.

But if the filter expression contained references to local or static variables you get an error:
Error BASE/1003 Variable does not exist: CRGZIMMERNR

How can you resolve this problem?
Thanks in advance
Otto
********************************************************************
mod harbour - Vamos a la conquista de la Web
modharbour.org
https://www.facebook.com/groups/modharbour.club
********************************************************************
User avatar
Otto
 
Posts: 6131
Joined: Fri Oct 07, 2005 7:07 pm

Re: XBROWSE : Error in method Delrepos

Postby demont frank » Sat Mar 14, 2009 3:34 pm

Otto wrote:Thank you, Antonio.

But if the filter expression contained references to local or static variables you get an error:
Error BASE/1003 Variable does not exist: CRGZIMMERNR

How can you resolve this problem?
Thanks in advance
Otto


Otto,

The problems comes from macro evaluation cFilter ( := Dbfilter() ) , so it must be avoided.

When dbsetfilter is used , we can :

Dbsetfilter({||....})

Without providing the second parameter. Dbfilter will return a empty string , so we can not know that a filter is active

While painting , skip is used and when a filter is active , (x)harbour will skip records not matching the filter condition.

So , only the first record can be falls , when the programmer as set a record with goto .... , or set a filter without a skip

Maybe we could :

Code: Select all  Expand view

LOCAL Gehrec1 := RECNO() , GehRec2
SKIP
Gehrec2 := RECNO()
SKIP -1 // When the first record matches or if no active filter , all is ok
IF RECNO() <> Gehrec1
    GO Gehrec2
END
 

Frank
demont frank
 
Posts: 167
Joined: Thu Mar 22, 2007 11:24 am

Re: XBROWSE : Error in method Delrepos

Postby Antonio Linares » Sat Mar 14, 2009 3:56 pm

Otto,

>
But if the filter expression contained references to local or static variables you get an error:
Error BASE/1003 Variable does not exist: CRGZIMMERNR
>

You can create a temporary private variable to hold such value.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41456
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: XBROWSE : Error in method Delrepos

Postby James Bott » Sun Mar 15, 2009 4:30 pm

Antonio,

>Basically the idea is that we are going to repaint the browse, and if the current record does not match the filter expression, then we skip it, so it is not displayed.

But as Frank said, isn't this redundant since the database RDD is already handling the filter? It seems to me that the xbrowse code will never even see a filtered record since the RDD won't ever return it.

Regards,
James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: XBROWSE : Error in method Delrepos

Postby Antonio Linares » Sun Mar 15, 2009 7:38 pm

James,

Yes, I also thought about that yesterday, when I answered :-)

That enhancement was developed by Nageswararao, as far as I remember. His comments would be welcome.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41456
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: XBROWSE : Error in method Delrepos

Postby nageswaragunupudi » Sun Mar 22, 2009 4:41 am

To start with, let me apologize for not looking at the posts during the last few days. Hence the delay in my response.

Mr Antonio wrote:
Basically the idea is that we are going to repaint the browse, and if the current record does not match the filter expression, then we skip it, so it is not displayed.

Yes, that was the intention.

Mr James Bott wrote:
But as Frank said, isn't this redundant since the database RDD is already handling the filter? It seems to me that the xbrowse code will never even see a filtered record since the RDD won't ever return it.


I wish the RDD handles it well. But unfortunately it does not. Though SET DELETED is ON, after we delete a record, the RDD does not move the record pointer. Similarly, if an edit invalidates a filter condition also, the RDD does not move the pointer. In both cases, it is the responsibility of the programmer to move the record pointer to ( next ) valid record. This can be done in many ways, but the most popular way is "DbSkip(1); if Eof(); DbGogottom(); endif". By the way. DbSkip( 0 ) also does not help.

This is the standard behavior of Clipper since the Summer 87, which faithfully implemented the behavior of Ashontate's DBase III. Naturally, Harbour and xHarbour provide the same behavior.

So, during a browse, if a record is deleted and SET DELETED is ON or a record is edited invalidating the filter condition, we have to manually write the repositioning code. We have to check for these situations every time and write the repositioning code in our application program for all browses. There were even many postings here by programmers, who did not know this behavior, seeking help. In all such cases they were advised to reposition the record pointer in the above manner.

Not only the deleted / invalid record continues to appear in the browse, subsequent navigation messes up the entire browse, without this repositioning logic.

I am a lazy programmer. If I have to repeat the same lines of code more than once, I would push it into a common function or into my libraries. I pushed this logic in to my copies of xbrowse and it was working satisfactorily to me. On this basis I suggested this enhancement and FWH adopted this.

The intention of this enhancement ( or headache ) was to avoid the need to keep repeating the same code by the programmer in all his browses and instead the xbrowse library to handle the situation automatically.

I did not encounter any problems because by habit since years, I do not use local or static variables ( or any variables ) or aliased expressions in my filter and index expressions.

I realized that this modification has become a great irritant to the programmers who use local / static variables in their filter expressions.

I propose revision of DelRePos() method as below:
Code: Select all  Expand view
//----------------------------------------------------------------------------//

METHOD DelRepos() CLASS TXBrowse

   local lRepos := .f.
   local cFilter, bFilter

   if lAnd( ::nDataType, DATATYPE_RDD ) .and. ::nLen > 0

      if ( Set( _SET_DELETED ) .and. ( ::cAlias )->( Deleted() ) ) ;
         .or. ;
         ( ! Empty( cFilter := ( ::cAlias )->( dbFilter() ) ) .and. ;
           Type( cFilter ) == 'L' .and. ;
           ! &cFilter )

            ( ::cAlias )->( dbSkip( 1 ) )
            if ( ::cAlias )->( eof() )
               ( ::cAlias )->( DbGoBottom() )
            endif
            lRepos := .t.
      endif

   endif

return lRepos

//----------------------------------------------------------------------------//
 

Now, XBrowse deals both cases well, if the filter expression does not contain local/static variables. If it contains local/static variables, now the xbrowse does not complain through the irritating runtime error, but it does not help by repositioning the record pointer. The programmer has to himself write the repositioning logic in his program after re validating the filter expression.

Now I hope this method helps those who like to avail its benefit and does not come in the way of those who do not.
Regards

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

Re: XBROWSE : Error in method Delrepos

Postby James Bott » Sun Mar 22, 2009 4:24 pm

NageswaraRao,

Thanks for the detailed explaination. It does seem that it would be less work to change from using a local or static than to write repostioning code.

One other possible solution would be to leave the original code as is (so that it does error out with locals and statics) and add a comment to the method stating that you cannot use locals or statics in the filter. This way after getting an error, the programmer can figure out what the problem is more easily.

Regards,
James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: XBROWSE : Error in method Delrepos

Postby demont frank » Mon Mar 30, 2009 3:33 pm

The described method uses cFilter := Dbfilter()

When the programmer set the filter expression as dbfilter(Code block) , cFilter will be empty.
Next code tries to avoid this
Code: Select all  Expand view
//----------------------------------------------------------------------------//

METHOD DelRepos() CLASS TXBrowse

   local lRepos := .f.
   local rec1 , rec2


   if lAnd( ::nDataType, DATATYPE_RDD ) .and. ::nLen > 0

      if ( Set( _SET_DELETED ) .and. ( ::cAlias )->( Deleted() ) )
          (::cAlias)->(DbSkip(1))   // If a filter is set , it will go to the first record that matches the filter expression
          if ( ::cAlias )->( eof() )
               ( ::cAlias )->( DbGoBottom() )
          endif
           lRepos := .T.
      else // Maybe the record doesn't match filter expression
          rec1 := (::cAlias)->(Recno())
          (::cAlias)->(DbSkip(1))   // If a filter is set , it will go to the first record that matches the filter expression
          rec2 := (::cAlias)->(Recno())
          (::cAlias)->(DbSkip(-1))   // If no filter is set , or if the original position matches the filter expression , it returns to his original position
          if (::cAlias)->(Recno()) <> rec1
                (::cAlias)->(DbGoto(Rec2))
                lRepos := .T.
          endif
      endif

return lRepos

//----------------------------------------------------------------------------//
 [/code fw]
 



nageswaragunupudi wrote:To start with, let me apologize for not looking at the posts during the last few days. Hence the delay in my response.

I wish the RDD handles it well. But unfortunately it does not. Though SET DELETED is ON, after we delete a record, the RDD does not move the record pointer. Similarly, if an edit invalidates a filter condition also, the RDD does not move the pointer. In both cases, it is the responsibility of the programmer to move the record pointer to ( next ) valid record. This can be done in many ways, but the most popular way is "DbSkip(1); if Eof(); DbGogottom(); endif". By the way. DbSkip( 0 ) also does not help.

This is the standard behavior of Clipper since the Summer 87, which faithfully implemented the behavior of Ashontate's DBase III. Naturally, Harbour and xHarbour provide the same behavior.

So, during a browse, if a record is deleted and SET DELETED is ON or a record is edited invalidating the filter condition, we have to manually write the repositioning code. We have to check for these situations every time and write the repositioning code in our application program for all browses. There were even many postings here by programmers, who did not know this behavior, seeking help. In all such cases they were advised to reposition the record pointer in the above manner.

Not only the deleted / invalid record continues to appear in the browse, subsequent navigation messes up the entire browse, without this repositioning logic.

I am a lazy programmer. If I have to repeat the same lines of code more than once, I would push it into a common function or into my libraries. I pushed this logic in to my copies of xbrowse and it was working satisfactorily to me. On this basis I suggested this enhancement and FWH adopted this.

The intention of this enhancement ( or headache ) was to avoid the need to keep repeating the same code by the programmer in all his browses and instead the xbrowse library to handle the situation automatically.

I did not encounter any problems because by habit since years, I do not use local or static variables ( or any variables ) or aliased expressions in my filter and index expressions.

I realized that this modification has become a great irritant to the programmers who use local / static variables in their filter expressions.

I propose revision of DelRePos() method as below:
Code: Select all  Expand view
//----------------------------------------------------------------------------//

METHOD DelRepos() CLASS TXBrowse

   local lRepos := .f.
   local cFilter, bFilter

   if lAnd( ::nDataType, DATATYPE_RDD ) .and. ::nLen > 0

      if ( Set( _SET_DELETED ) .and. ( ::cAlias )->( Deleted() ) ) ;
         .or. ;
         ( ! Empty( cFilter := ( ::cAlias )->( dbFilter() ) ) .and. ;
           Type( cFilter ) == 'L' .and. ;
           ! &cFilter )

            ( ::cAlias )->( dbSkip( 1 ) )
            if ( ::cAlias )->( eof() )
               ( ::cAlias )->( DbGoBottom() )
            endif
            lRepos := .t.
      endif

   endif

return lRepos

//----------------------------------------------------------------------------//
 

Now, XBrowse deals both cases well, if the filter expression does not contain local/static variables. If it contains local/static variables, now the xbrowse does not complain through the irritating runtime error, but it does not help by repositioning the record pointer. The programmer has to himself write the repositioning logic in his program after re validating the filter expression.

Now I hope this method helps those who like to avail its benefit and does not come in the way of those who do not.
demont frank
 
Posts: 167
Joined: Thu Mar 22, 2007 11:24 am

Previous

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 126 guests