Vserver v4.3

Ivan Smahin ivan_smahin at paradigmasoft.com
Mon Apr 5 05:27:35 CDT 2010


Hello Stan,

Monday, April 5, 2010, 12:52:34 PM, you wrote:

> Hi Ivan,

> The function code is:

> aCursor = inDatabase.SQLSelect( aQuery,
> EVCursorLocation.kServerSide, EVLockType.kNoLocks, EVCursorDirection.kRandom )
> If aCursor <> nil then
>  If aCursor.RecordCount > 0 then
>       Do
>         aCurrency = aCursor.ULongField("Account_CurrencyRecord").Value
>         aBalance  = aCursor.DoubleField("Account_Balance").Value
>         aResult   = aResult + ConvertToDefaultCurrency( inDatabase,
> aBalance, aCurrency )  <----- CRASH HERE AFTER 6 OR 7 ITERATIONS
>       Loop Until not aCursor.NextRecord()
>     end if
>   end if

Ok,  you  extract  aCurrency  and  aBalance values and pass it to some
function in the loop.


> It crashed inside the 'ConvertToDefaultCurrency' function. This is function code is:

I guess inCurrency is a passed aCurrency - yes?

>   If inCurrency > 0 then    
>     aRate      = inDatabase.mCurrency.GetRate( inCurrency )
>     aDirection = inDatabase.mCurrency.GetCurrencyDirection( inCurrency )
>     If aRate = 0 then aRate = 1
>     If aDirection = 0 then
>       Return inNumber / aRate
>     elseif aDirection = 1 then
>       Return inNumber * aRate
>     end if
>   else
>     Return inNumber
>   end if

> inDatabase.mCurrency.GetRate code is:

>   If isValid( inRec ) then
>     Return mRate.Value
>   end if
>

mRate is a field - right?
But who load proper value into this field?


> inDatabase.mCurrency.GetCurrencyDirection is:

>   If isValid( inRec ) then
>     Return mDirection.Value
>   end if

> In both cases isValid code is:

>   If RecordExists( inRec ) then
>     RecID = inRec
>     Return True
>   else
>     Return False
>   end if

> Stan


Ok, let me explain
Firstly  API way is not a best choice in client-server environment due
to the following reasons:

1. It could be a lot of calls which must be passed to the server.
   Finally it might be more time than using SQL-way.
   I mean it would not be so time-efficient as in a local mode.
   So SQL-way is preferred choice here.

2. Your   loop  might  be interrupted by another user in any moment.
   And, say, current record might be changed, moved, even deleted.
   Another user may alter the table or even drop it... and so on.
   In  most  of  cases  you  are able to write some additional code to
   guarantee  than  nothing  "bad"  may  happen  but it would not be
   a "general" solution anyway.
   So it is one more vote for SQL-way.

   Short  note  - you have a guarantee that each particular API-method
   call will NOT be interrupted by another user.

   Example:

   SetBLank
   AddRecord

   It  could  be  interruption between that commands but not inside of
   any of them.

   So  when  you  call SqlExecute( "..." ) it could not be interrupted
   too.  And  most  of people prefer to keep the business-logic inside
   the database using stored procedures. There are many advantages...

   So actually call might be as strong as

   SqlExecute( "call mySp1( param1, param2)" );


Getting back to your code...
Can you send me the app and db for testing?
Just hard to say why it work 6-7 times and then crashed.





-- 
Best regards,
Ivan Smahin 
Senior Software Engineer
Paradigma Software, Inc
Valentina - The Ultra-Fast Database
http://www.valentina-db.com



More information about the Valentina mailing list