Table of a VFeld from a VCursor

Ed Kleban Ed at Kleban.com
Tue Nov 29 08:44:15 CST 2005




On 11/22/05 3:36 PM, "Ruslan Zasukhin" <sunshine at public.kherson.ua> wrote:

> On 11/22/05 12:21 AM, "Ed Kleban" <Ed at Kleban.com> wrote:
> 
>> // When you define your VTable subclasses you define the FieldCursors
>> // you want to be able to use in addition to table fields:
>> 
>> Sub CTblForms(db as CRbProjectDB, tableName as String)
>>   // Initialize the receiver and its fields.
>>   
>>   self.name = tableName
>>    
>>   // Define the Table Fields
>>   fFrmFlags = new VByte( "FFrmFlags" )
>>   fFrmLabel = new VVarChar( "FFrmLabel", 504 )
>>   fFrmTagTyp = new VVarChar( "FFrmTagTyp", 504)
>>   fFrmXmlTag = new VVarChar( "FFrmXmlTag", 504)
>>   
>>   // Define the FieldCursors
>>   cursorOnFFrmXmlTag = new CFCVarChar( fFrmXmlTag )
>>   cursorOnFFrmFlags  = new CFCByte( fFrmFlags )
>> End Sub
>> 
>> 
>> // Subsequently, in your code you can use the FieldCursors
>> // to randomly access a single field of a given record without
>> // reading in every single table field when all you need is
>> // a single field's value:
>> 
>>     flagByteFromRecord32 = MyTblForms.cursorOnFFrmFlags.integerValue( 32 )
>>     MyTblForms.cursorOnFFrmFlags.integerValue( 21 ) = kFlagValForRec21
> 
> Okay, I see idea of hacking :-)
> 
> Only problem you can meet is record locks.
> May be you will prefer use kNoLocks.

Yes, if you look in the updateFieldCursor method below, I do indeed use
kNoLocks.
 
> 
> 
>> // To make this possible...
>> 
>> // You need to define a subclass of CFCField for each different
>> // kind of Vfield subclass that you want to be able create a
>> // FieldCursor for.  This gets done once and reused in all the
>> // applications where you want to use FieldCursors.  It is essentially
>> // the common FieldCursor add-in code.  Here are some example guts
>> // out of CFCByte:
>> 
>> Function integerValue(recId as Integer, doUpdateCheck = true) As Integer
>>   // Return an Integer with the value of the reciever's fcCursorField at
>>   // recId from the updated fcCursor on fcTable in fcDatabase.
>>   // If doUpdateCheck is false then assume that no rows have been
>>   // added to fcTable and that the fcCursor is valid.
>>   
>>   if doUpdateCheck and updateFieldCursor then  // fcCursorChanged
>>     fcFCByte = fcCursor.ByteField( 1 )
>>   end
>>   
>>   fcCursor.position = recId
>>   return fcFCByte.Value
>> End Function
>> 
>> 
>> Function integerValue(recId as Integer, newIntVal as Integer, _
>>     doUpdateCheck = true, assigns newValStr as string) As String
>>  
>>   // Change the value of the reciever's fcCursorField at recId
>>   // from the updated fcCursor on fcTable in fcDatabase to newIntVal.
>>   // If doUpdateCheck is false then assume that no rows have been
>>   // added to fcTable and that the fcCursor is valid.
>>   
>>   if doUpdateCheck and updateFieldCursor then  // fcCursorChanged
>>     fcFCByte = fcCursor.ByteField( 1 )
>>   end
>>   
>>   fcCursor.position = recId
>>   fcFCByte.Value = newIntVal
>>   fcCursor.UpdateRecord
>> End Function
>> 
>> 
>> // The central magic that makes all this work transparently so you
>> // don't have worry about the state of the FieldCursor is the
>> // updateFieldCursor method, and the common code called from the
>> // constructors for all CFCField subclasses:
>> 
>> Protected Function updateFieldCursor() As Boolean
>>   // Update the receiver's cursor from it's field if necessary.
>>   // Return true if the Cursor was updated or false if the
>>   // former fcCursor is fine to use.
>>   
>>   const here = "updateFieldCursor"
>>   
>>   if fcCursor is nil or fcCursor.RecordCount <> fcTable.RecordCount then
>>     fcCursor = fcDatabase.SqlSelect( _
>>         fcSqlString, EVCursorLocation.kClientSide, _
>>         EVLockType.kNoLocks, EVCursorDirection.kRandom )
> 
> KClientSide -- give you READ ONLY cursor. Better use ServerSide
> 
>      
>>     #if DebugBuild then
>>       if fcCursor.RecordCount <> fcTable.RecordCount then
>>         fail( here, "Update error" )
>>       end if
>>     #endif 
>>  
>>     return true // Cursor was modified
>>   else
>>     return false // Cursor is fine as-is.
>>   end  
>> End Function
>> 
>> 
>> Sub CFCField(aVField as VField)
>>   // Initialize the receiver to be a cursor on aVField
>>   
>>   const here = "CFCField"
>>   
>>   #if DebugBuild then
>>     if aVField is nil or aVField.Table is nil _
>>         or aVField.Table.Database is nil then
>>       fail( here, "Implementation Error" )
>>     end
>>   #endif
>>   
>>   if not self.checkFieldType( aVField ) then
>>     fail( here, "Invalid VField subclass" )
>>   end
>>   
>>   // Cache useful values in properties
>>   fcTable = aVField.Table
>>   fcSqlString = glue( "Select ", aVField.Name, " from ", fcTable.Name )
>>   fcDatabase = aVField.Table.Database
>>   // There is no need or reason to cache the argument aVField.
>> End Sub




More information about the Valentina mailing list