Table of a VFeld from a VCursor
Ed Kleban
Ed at Kleban.com
Mon Nov 21 16:21:49 CST 2005
On 11/21/05 3:30 PM, "Ruslan Zasukhin" <sunshine at public.kherson.ua> wrote:
> On 11/21/05 10:34 PM, "Ed Kleban" <Ed at Kleban.com> wrote:
>
>> In fact, I'll probably publish, or send you to publish, the FieldCursor
>> class hierarchy to use as a V4RB add-on or to include as an example. It
>> essentially provides the lazy read feature in code until such time as you
>> get around to adding it V4RB. If I didn't have a way to do this I would be
>> willing to move nearly as much code over to V4RB and feel ok about burning
>> bridges behind myself. Or I'd have to restructure my use of the database in
>> a far more painful way to manage.
>
> Can you show small example of usage of V4RB now, and with your classes
> To see difference ?
>
>
Sure.
I'm still coding this, nothing is tested, all subject to change. That said,
here is some code to stare at. (Actually this was quite a useful exercise;
I found 3 bugs in the process of pasting text here).
// 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
// 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 )
#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