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