Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Lua ➜ Blackboard Setup with SQLite

Blackboard Setup with SQLite

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Mleo2003   (32 posts)  Bio
Date Wed 31 Aug 2022 02:15 AM (UTC)
Message
I have been playing with the idea of a Blackboard system for my characters on a mud, and wanted some durable way to store data, and possibly share it with other chars. This is my attempt at somewhat simple interface for doing so.


-- BlackBoards for shared/persistant data
require "serialize"

bb = {}
DatabaseOpen("blackboard", GetInfo (66) .. "blackboard.db", 6)
DatabaseExec("blackboard", [[
CREATE TABLE IF NOT EXISTS "board" ("key" TEXT PRIMARY KEY, "character" TEXT, "value" BLOB);
]])
local mt = {
    __index = function (t,k)
        local t = {}
        local value = DatabaseGetField ("blackboard", string.format("SELECT value FROM board WHERE key = '%s' AND character = '%s';", k, GetInfo (3)))
        setfenv (assert (loadstring (value or "")), t) ()
        return t['value']
    end,
    
    __newindex = function (t,k,v)
        if v == nil then
            DatabaseExec ("blackboard", string.format("DELETE FROM board WHERE key = '%s' AND character = '%s';", k, GetInfo (3)))
        else
            local data = 'value = ' .. serialize.save_simple (v)
            local return_value = DatabaseExec ("blackboard", string.format("INSERT INTO board (key, character, value) VALUES ('%s', '%s', '%s');", k, GetInfo (3), data))
            if return_value ~= 0 and return_value ~= 100 and return_value ~= 101 then
                return_value = DatabaseExec ("blackboard", string.format("UPDATE board SET value = '%s' WHERE key = '%s' AND character = '%s';", data, k, GetInfo (3)))
            end
        end
    end
}

setmetatable(bb, mt)


You use it like any other table:

bb['hello'] = 'world'


And since it uses serialize for the saving/loading, it will remember types and do simple nested tables (could be updated to use more complex ones if needed).

The only problem I found with it was nested tables do not work as you expect them too:


bb['test'] = {name = 'Bart'}
print(bb['test']['name']) -- shows 'Bart'
bb['test']['name'] = 'Lisa'
print(bb['test']['name']) -- still shows 'Bart'


It makes sense why this happens, as what I return is a new table every time. I think if I used a hidden table to cache/record the DB results, and update those on some timer, it could work decently, but hackish.

Can anyone else think of any other improvements this could take on?
Top

Posted by Nick Gammon   Australia  (23,098 posts)  Bio   Forum Administrator
Date Reply #1 on Wed 31 Aug 2022 05:36 AM (UTC)
Message
I think that design is fundamentally flawed, if I can say so without giving offence. ;)

You are trying to make a simple database table with one key and one value handle two-dimensional arrays. That's never going to work.

Either set up a proper table, where each row has a major key (eg. an ascending number) and then other columns such as the message, the date, who wrote it, and so on. That gets rid of the need for two dimensions.

OR ...

Just serialize the table to disk and bypass the database altogether. There is a discussion of doing that here:

http://www.gammon.com.au/forum/?id=4960&reply=6#reply6

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Mleo2003   (32 posts)  Bio
Date Reply #2 on Wed 31 Aug 2022 03:07 PM (UTC)
Message
No offence taken. :)

I was mainly inspired by projects like these:


  • https://pypi.org/project/diskcache/0.7.0/
  • https://github.com/RaRe-Technologies/sqlitedict


Which is more what I was wanting: a way to store data that looked like a table (as that is the main feature I wanted) while hiding the implementation of how it was actually stored. But, the issue I pointed out (of nested/2D tables) does lead to some confusion for anyone who may use it.

I could just as easily have those be global function "get and set" calls, and then it would be more obvious what would happen:

bb_get('test')['name'] = 'Lisa'


That would at least be more clear what to expect with the return.

My only other reason for wanting this, was that as a SQLite DB in a file, I could have multiple worlds open the file, and essentially have a shared space for data. I've tried passing data between worlds before, and while doable, this seemed to clean up all the assumptions around that to point externally nice enough, and get some durability of the data I was passing for free (as a lot of what I was sharing between worlds was still true/relevant from one run of Mushclient to the next).

Thanks for the input, for more structured/planned data to share/pass, I do intend on using more columns and all they give. This area was just to be for random things to share that were mainly single value in nature, but serialize gave me the ability to even store/share more complex things for free (but how I chose to make the interface can lead to confusion, I admit).
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


10,900 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.