BitSet operations

Joakim Schramm joakim at astrocalc.com
Tue May 9 10:00:41 CDT 2006


 

> -----Original Message-----
> From: valentina-bounces at lists.macserve.net 
> [mailto:valentina-bounces at lists.macserve.net] On Behalf Of Ivan Smahin
> Sent: 05 May 2006 13:37
> To: Valentina Developers
> Subject: Re[2]: BitSet operations
> 
> Hello Joakim,
> 
> Friday, May 5, 2006, 1:48:08 PM, you wrote:
> 
> > The following code doesn't work, and I don't know why, it allways 
> > returns a NIL for the object to set. The Vset object passed to the 
> > function has over 5000 records and I know there is values 
> in the range 
> > I look. But maybe you can see why?
> 
> Set oLngPlaces = fLngDeg.FindValue(Lng, oAllPlaces)' always 
> returns nil
> 

Hi,

The problem remains after looking it over again taking comments into
account. I was in a hurry before so will take it all again giving a better
picture and commented code to better understand.

As for above, fLngDeg is declared Private to the module it lives in. All
code is in the same module. The core of the problem is that
fLngDeg.FindValue (or fLngDeg.FindValueAsArraySet) does not return any
records although it should - "somehow" it seem to lose its capability to do
so along the way. So lets take it all from the beginning.

All code is in the same module. The first function is Public (Global) and
add a new record passed in an UDT structure to function. But, one important
part of data is missing, this data sometimes have to be looked up from an
existing record - when there is more then 1 alternative. To find this data I
have to locate a record with some data in common with the new record, or
within a certain range.

So to be really clear, first module declarations.

Option Explicit
Public mAtlasDB As VDatabase
Private tblCountry As String
Const tblTimeZones As String = "TimeZones"
Const tblCountryAlias As String = "CountryAlias"
Const tblPlaces As String = "Places"
Const tblZoneData As String = "ZoneData"
Const ptrCountryAlias As String = "PtrAlias"
Const ptrZonePlaces As String = "PtrZone"
Const lnkCountryHasPlaces As String = "lnkCountryHasPlaces"
Const lnkCountryHasZones As String = "lnkCountryHasZones"
Const lnkZoneHasData As String = "lnkZoneHasData"
Private ItrSearch As VSetIterator
Private ResSearch As VSet
Private ListSet As VArraySet

'Tables
Private tPlaces As VTable
Private tCountry As VTable
Private tZones As VTable
Private tZoneData As VTable
'Country name field
Private fCountry As VField
'Place fields
Private fPlace As VField 'Name
Private fLatDeg As VField
Private fLatMin As VField
Private fLatSec As VField
Private fLatSign As VField
Private fLngDeg As VField
Private fLngMin As VField
Private fLngSec As VField
Private fLngSign As VField
Private fZoneId As VField
Private fZonePtr As VField
Private fZoneDate As VField
Private fZoneDiff As VField

Private mLink As VLink
Private nZoneId As Long

At program start, after Valentina been init, the sepcific database is opened
and referenses to tables and fields are set. Database stays open until
program close, all calls to database is routed through functions in this
module.


Public Function InitAtlasDB() As Boolean
Dim DbPath As String
Dim nResult As Long
Dim tajny As String
Dim uPlace As AtlDataUDT

'************************************
'Open database and init it by setting
'referenses for tables and fields for later use.
Set mAtlasDB = New VDatabase

With mAtlasDB
    .InitLocal
    .DateFormat = EVDateFormat.kYMD
    DbPath = AtlasDir + "Atlas.vdb"

    'If Database not exists we create it.
    If Not FileExists(DbPath) Then
        .Create DbPath
        CreateStructure
    End If

    .Open DbPath

    If .IsOpen Then
        InitAtlasDB = True
        tblCountry = "Country_" & sLang
        Set tCountry = .Table(tblCountry)
        Set fCountry = tCountry.Field("CName")
        'zones
        Set tZones = .Table(tblTimeZones)
        Set fZoneId = tZones.Field("ZID")
        Set tZoneData = .Table(tblZoneData)
        Set fZoneDate = tZoneData.Field("DateChange")
        Set fZoneDiff = tZoneData.Field("TimeDiff")

        Set tPlaces = .Table(tblPlaces)
        With tPlaces
            Set fPlace = .Field("PName")
            Set fLatDeg = .Field("LatDeg")
            Set fLatMin = .Field("LatMin")
            Set fLatSec = .Field("LatSec")
            Set fLatSign = .Field("LatSign")
            Set fLngDeg = .Field("LongDeg")
            Set fLngMin = .Field("LongMin")
            Set fLngSec = .Field("LongSec")
            Set fLngSign = .Field("LongSign")
            Set fZonePtr = .Field(ptrZonePlaces)
        End With

    End If

End With

End Function

In a form data for new record is collected from input and passed to Public
function to add it to database. But value for 1 field we don't know yet is
missing and need to be found from existing record. Sometimes this is easy as
there is only 1 alternative, but sometimes a subfunction is needed to find
and return the correct data before record is added.


Public Function AddPlaceRec(uPlace As AtlDataUDT) As Boolean
Dim NewId As Long, NewPtr As Long
Dim lnk As VLink
Dim Res As VSet
Dim arr As VArraySet

'uPlace is UDT with record data to add. Before adding new record, we need
'to obtain value from ObjectPtr in already existing record.
'We need to find 1 record with some data in common to get the right value.

With uPlace

    If Len(Trim$(.TownName)) Then 'Name of place, check to not be empty.
        'RecID for country place belong to.
        'If not already set, we set default value.
        If .CountryID = 0 Then
            .CountryID = mCountryID
        End If

        'Each contry is linked to 1 or more zones.
        'set link for country and zones
        Set lnk = mAtlasDB.Link(lnkCountryHasZones)
        'find zones linked to this country using RecID (=.CountryID)
        'assign result to local VArraySet object
        Set arr = lnk.FindLinked(.CountryID, tCountry, tZones)
        'We need to find how many records returned
        'so set local VSet object to test if count > 1
        Set Res = arr

        If Res.Count > 1 Then
            'We have > 1 links (zones records) so need to figure out
            'which zone to use RecID from in next step
            '
            'Get all links between Country and Places
            Set lnk = mAtlasDB.Link(lnkCountryHasPlaces)
            'Now get all places for this specific country
            'Put result in VArraySet object to pass subfunction
            'together with search criterias
            Set arr = lnk.FindLinked(.CountryID, tCountry, tPlaces)
            'We now should have a subset of table tPlaces for just one
country
            'Here start error happen. No matter if vSet,vArraySet or vBitSet
passed
            'and function argument is as vSet,VarraySet or vBitSet
            NewPtr = FindZoneDataID(.LatDeg, .LongDeg, .LatSign, .LongSign,
arr)
        Else
            'Only 1 link, task is easy, just get RecID of first item
            NewPtr = arr.GetItemAt(1)
        End If

        'NewPtr as RecID in exsisting record.
        'We want ObjectPtr from this record to use in new item to add.
        tPlaces.SetBlank forAdd
        fZonePtr.Value = NewPtr
        fPlace.Value = Trim$(.TownName)
        fLatDeg.Value = .LatDeg

...
End Funtion


Private Function FindZoneDataID(ByVal Lat As Long, ByVal Lng As Long, ByVal
SgnLat As Long, SgnLng As Long, oAllPlaces As VArraySet) As Long
Dim diffM As Long, diffP As Long, Fact As Long, Pid As Long, ptr As Long
Dim Itr As VSetIterator
Dim oSet As VSet
Dim lnk As VLink
Dim oLatPlaces As VArraySet
Dim oLngPlaces As VArraySet

'oAllPlaces should have a subset of places from tPlaces table.
'we want to search in table for this subset for values of passed val Lng
'and put result in oLngPlaces
'
'oLngPlaces always come out as nil (Nothing in VB),
'no matter if used type is As VSet, VArraySet or VBitSet, in oAllPlaces
'have tried all types and variations off them.
'value of Lng exists in fLngDeg, but no matter if oAllPlaces
'is used to narrow scope or nil is passed to search all records of
'tPlaces
'return nil
Set oLngPlaces = fLngDeg.FindValueAsArraySet(Lng, oAllPlaces)
'return nil
Set oLngPlaces = fLngDeg.FindValueAsArraySet(Lng)
'return nil
Set oLngPlaces = tPlaces.Field("LongDeg").FindValueAsArraySet(Lng,
oAllPlaces)
'return nil
Set oLngPlaces = tPlaces.Field("LongDeg").FindValueAsArraySet(Lng)
'return nil
Set oLngPlaces =
mAtlasDB.Table("Places").Field("LongDeg").FindValueAsArraySet(Lng,
oAllPlaces)
'return nil
Set oLngPlaces =
mAtlasDB.Table("Places").Field("LongDeg").FindValueAsArraySet(Lng)

If oLngPlaces Is Nothing Then

...

End Function

As you can see, even with full referense from Vdatabase object, nil is still
returned.
I even tested with current value of fLngDeg.Value is 85 and Lng is 85, still
nil???

I hope this is more understandable this time.

Joakim



More information about the Valentina mailing list