QB64 Phoenix Edition
Variable length string database, using an index file - Printable Version

+- QB64 Phoenix Edition (https://staging.qb64phoenix.com)
+-- Forum: QB64 Rising (https://staging.qb64phoenix.com/forumdisplay.php?fid=1)
+--- Forum: Prolific Programmers (https://staging.qb64phoenix.com/forumdisplay.php?fid=26)
+---- Forum: SMcNeill (https://staging.qb64phoenix.com/forumdisplay.php?fid=29)
+---- Thread: Variable length string database, using an index file (/showthread.php?tid=142)



Variable length string database, using an index file - SMcNeill - 04-23-2022

Code: (Select All)
'Random length string database creation.
'This demo will utilize two different files to manage our database.
'the first one will be the data, and the second will be our index to the data

TYPE RecordType
    Name AS STRING
    Age AS _BYTE
    Sex AS STRING
    Phone AS STRING
END TYPE

TYPE IndexType
    StartPosition AS LONG
    LengthName AS LONG 'track how long the name is
    LengthSex AS LONG 'track how long the sex is
    LengthPhone AS LONG 'track how long the phone is
END TYPE

DEFLNG A-Z
DIM SHARED Record AS RecordType, Index AS IndexType
DIM SHARED RecordNumber, RecordCount

OPEN "Demo.dba" FOR BINARY AS #1 'the demo database
OPEN "Demo.ndx" FOR BINARY AS #2 'the demo index
RecordCount = LOF(2) \ LEN(Index)


DO
    choice = ShowOptions
    SELECT CASE choice
        CASE 1: AddRecord
        CASE 2:
        CASE 3:
        CASE 4: RecordNumber = RecordNumber - 1: IF RecordNumber < 1 THEN RecordNumber = RecordCount
        CASE 5: RecordNumber = RecordNumber + 1: IF RecordNumber > RecordCount THEN RecordNumber = 1
        CASE 6: SYSTEM
    END SELECT
LOOP

SUB ShowMainInfo
    CLS
    IF RecordNumber > 0 THEN 'Get the current record and display it
        GET #2, (RecordNumber - 1) * LEN(Index) + 1, Index
        Record.Name = SPACE$(Index.LengthName)
        Record.Sex = SPACE$(Index.LengthSex)
        Record.Phone = SPACE$(Index.LengthPhone)
        GET #1, Index.StartPosition, Record.Name
        GET #1, , Record.Age
        GET #1, , Record.Sex
        GET #1, , Record.Phone
    ELSE
        Record.Name = ""
        Record.Age = 0
        Record.Sex = ""
        Record.Phone = ""
    END IF



    PRINT "Steve's Variable Length Database Demo"
    PRINT
    PRINT "Record RECORD "; RecordNumber; " of "; RecordCount
    PRINT "Name : "; Record.Name
    PRINT "Age  : "; Record.Age
    PRINT "Sex  : "; Record.Sex
    PRINT "Phone: "; Record.Phone

    PRINT
    PRINT
END SUB

SUB AddRecord
    RecordNumber = 0 'Display a blank record
    ShowMainInfo
    RecordCount = RecordCount + 1 'increase our total count of records
    RecordNumber = RecordCount 'And set our current record to the new record count value
    PRINT "ENTER Name : "
    PRINT "ENTER Age  : "
    PRINT "ENTER Sex  : "
    PRINT "ENTER Phone: "

    LOCATE 10, 14: INPUT ; ""; Record.Name
    LOCATE 11, 14: INPUT ; ""; Record.Age
    LOCATE 12, 14: INPUT ; ""; Record.Sex
    LOCATE 13, 14: INPUT ; ""; Record.Phone
    filesize = LEN(Record.Name) + LEN(Record.Age) + LEN(Record.Sex) + LEN(Record.Phone)
    Index.StartPosition = LOF(1) + 1
    Index.LengthName = LEN(Record.Name)
    Index.LengthSex = LEN(Record.Sex)
    Index.LengthPhone = LEN(Record.Phone)
    PUT #2, (RecordCount - 1) * LEN(Index) + 1, Index
    t$ = Record.Name: PUT #1, LOF(1) + 1, t$ 'We must use a temp string, as we can't put a variable length string type to a file
    PUT #1, , Record.Age
    t$ = Record.Sex: PUT #1, , t$
    t$ = Record.Phone: PUT #1, , t$
END SUB



FUNCTION ShowOptions
    ShowMainInfo
    PRINT "1) Add Record"
    PRINT "2) Delete Record Record (Not Implemented Yet)"
    PRINT "3) Edit Record Record (Not Implemented Yet)"
    PRINT "4) Previous Record"
    PRINT "5) Next Record"
    PRINT "6) Quit"
    PRINT
    PRINT
    DO
        i$ = INPUT$(1)
        SELECT CASE i$
            CASE "1" TO "6": ShowOptions = VAL(i$): EXIT FUNCTION
        END SELECT
    LOOP
END FUNCTION


Folks have recently been talking about how to make databases with BINARY vs RANDOM access, and somebody brought up how they'd manage variable length strings with a database, using line terminations and parsing...  (I think it might have been bplus who mentioned that method.)

Here's how I generally work with handling variable length strings with a database.

For each variable length database, I usually use two databases -- one for the data, and one for an index to the data, which is what I'm doing with the above.  (Though sometimes, I'll pack both files into one database, with the index being a set positional header, and the data coming after that header -- but I thought I'd show the simplest form of the process first.)

Now, before I let the demo get too complicated that it might turn folks off from looking at it, I'm just going to post the bare bones of the process first.  The code above basically doesn't do anything except allow us to ADD RECORDS, and browse those records sequentially -- but it does show how we'd GET/PUT our information, and track where all that information is while on a disk for us.

RecordNumber is the current record that we're looking at
RecordCount is the total number of records which our database contains.

"Demo.dba" is the demo database
"Demo.ndx" is the demo index

In  AddRecord, you can see where we get the information from the user and how we put the proper information onto the drive for us, so we can access it later, and in ShowMainInfo, you can see the process by which we get that information back for us.




Honestly, I don't think there's anything very complicated about what we're doing here, so I really don't know what I need to comment on, or what questions someone might have about the process.  If anyone has any specific questions, feel free to ask, and I'll happily answer them, but the process is really very simple:

One file is the user's data, the other file tracks each record's position and lengths inside that file, so we only retrieve and work with what we want, when we want it.

A simple database is included below, but you can freely ignore it if you want.  Just run the code above and add your own records and browse them all you want.  Wink