|
Post by mystikshadows on Dec 27, 2023 0:26:23 GMT
I see it all time. Superbase for example can extend a record to 1024 bytes if not more. however in basic or all seems limited to 256 bytes. does anyone have an example on how to do this in basic?
I've done some testing too. it seems i can't redefine fields on the go to change my structure or anything similar to that.
Thanks in advance for any replies.
|
|
|
Post by c128old on Dec 27, 2023 14:47:27 GMT
Try this: 10 DOPEN #2, "database", L255 run
?illegal quantity error in 10
You cannot make records bigger than 254 bytes this way. This value of 254 is linked to a limit on the side of the DOS in the 1541, 1571. Basic 7 checks this before causing a drive error. If you use basic 2 style open# commands, you can send a 255 value but now you need to keep track of the final carriage return in a record yourself.
At any rate, you cannot create records of size 256 because the commodore DOS "open/create relative file" uses 1 byte (0-255) to define record size. Also, once this has been done, the DOS in the drive is going to manage your file in records of that predefined size. You might ask, could not the DOS in the drive manage a bigger record? No, and I think I can shed some light onto this. The drive will 'build' a record in its internal buffer memory given what you asked, for this it likely will access multiple disk blocks to piece together your request. Each time the 1541 reads 1 physical GCR encoded block from disk, it need to decode the block and this is done in buffer memory of the drive. This buffer is bigger than 256 bytes since the block is bigger due to its encoding. So I need: 1 x 255 bytes for your relative-file record + 1 x 256 bytes to hold decoded physical block and more than 1 x 256 bytes to hold the raw physical block. You see there is no room left for an additional relative file being open on the 1541 (it has 4 buffers of 256 byte to play with).
Now, suppose you redefine the shape of your database record file (that is, the total size of 1 record regardless of its content) This means the starting points of your earlier records would not match anymore. And, to be fair, modern databases do not allow you to redefine their layouts either.
In the case of 1541, the relative file on disk holds a series of records and the drive 'knows' how to get to the information in there in a random access manner. while you still need to make sure records are first created before you can access them, basic7 makes this really easy: dopen#2,"testing",L200 record#2,2 record#2,2 : rem 2nd time according to manual print#2,"record 2 values at start" dclose#2
This works, Basic 7 takes care of all the communication to the drive (which is rather a lot! read the 1541 manual what you're supposed to send to the drive to just access records...) If you (instead) try to reach a non-created record that is not sequentially past the final one you still need to do work. In basic7, the content of a record are otherwise "entirely up to you", meaning nothing is stopping you from using record1 with all kinds of database setup info, where record 2 is suddenly the address card layout you wished to manage.
The statement "I can't redefine fields on the go to change my structure" is not supported by the evidence: dopen#2,"test",L50 record#2,2 record#2,2 print#2,"some string" record#2,3,1 record#2,3,1 print#2,42 record#2,3,5 record#2,3,5 print#2,"hello" dclose#2
If you read this back, you find that the content of the records is (simply) strings. In other words, you can read record3 using input#2,a$ and a$ will be '42 hello' With this knowledge, your program is fully master of the content of a record. For instance, byte 1 of your record might determine the 'type' of the record, which you use in a on n gosub table to read your record content.
The above talks about the drive DOS on the system causing limits to the size of records. I'm relating this loosely to 256 byte buffers and drive memory. What if your drive has tons of memory, like a 1581? Well, if you consider that the 'content' of a record is yours to manage, you can decide to make a distinction in the "logical" level of your database and the "physical" level. In this case, a logical record number 5, with sizes of 1200 each, would have to do IO on 6 records-in-a-row of 200 each. The file would have been opened with L200 and record 5 would be 5*6=30 into that file. Mind you, you still cannot have more than 64k records with commodore DOS, though extensions exist for large storage. Consider a CMD HD (or a DNP file, mounted in ultimate II or sd2iec) allow 16Mb native file systems with matching relative file sizes, the ultimate-ii supports relative files directly on the storage medium... If you do not use the file system at all, you can control the disk layout entirely. This is what the initial super-base for c64 would do. Only later rewrites squeezed this into relative files. Take the 1581: here the "fast IEC command set" has U0-commands to read or write a sector from the disk. On that MFM formatted disk we find sectors of 512 bytes, not 256 bytes! So, the attempt to do IO on a single 'record' of a full native 1581 disk would give you 512 bytes to write or 512 bytes to read. You would have to manage this 512 bytes somewhere in your program, in a buffer, even if you wanted to access offset 8 in a record. Also, if your record is less than 512 bytes, or more, you have to manage the empty space (waste) on your disk between the records. A relative does that for you, in the drive.
Could the 1581, or 1571, have supported bigger records? Sure, they could've but that would have meant an incompatible REL-file handling. I suppose they didn't see the need since the largest file you can handle on a commodore disk would be: 64k * 254 bytes = 256*256*254 = close to 16Meg In other words, regular exchangeable media to manage more than 16 megabyte happened past the time of the 8 bitters. Even the infamous 9090 HD drive commodore made, with its 9 MB, was no match for this.
So, using a single byte to determine record size means: good enough. Having a 16bit record index solves any more complex things on top of that. If your Basic7 program wants to determine a (virtual) 1024 record size then you end up splitting your record in a (matched, of course) number of sub-records. Also, I would (in that case) make sure records have some sort of header to identify them wholly.
Additional tricks include things like 'memo' fields, (see DBase IV) where you have a sort-of-continuation signal as to where you may find additional records with the variable-text-field. If you decided to write the full relative file at creation, then you may put memo-fields from the back to the start and regular records from start.
TLDR; - 255 bytes is max size per record on a REL file. Commodore DOS limit. 256 bytes not possible. 254 practical limit. - Fields have no 'definition' or shape. Use a 1 record-sized-string to always put (all) data to/from a record for updating them - Doing relative files on a 1541 without acceleration is ... not such a good idea
Records of 400 bytes in basic: dopen#3,"400b",L200 for nr=1to2 record#3,nr*2 record#3,nr*2 print#3,"Record "+str$(nr)+", top" record#3,nr*2+1 record#3,nr*2+1 print#3,"Record "+str$(nr)+", bottom" ; rem end of rec 1 next dclose#3 rem access using recordnr * 2 nr=1 dopen#3,"400b",L200 record#3,nr*2 record#3,nr*2 input#3,a$; printa$ : rem record1 a$ max 200 chars record#3,nr*2+1 record#3,nr*2+1 input#3,b$; printb$ : rem record1 b$ max 200 chars, 2nd part dclose#3
|
|
|
Post by mystikshadows on Dec 27, 2023 15:08:07 GMT
Thank you c128old this is exactly what I was looking for. Much Obliged.
|
|