This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Mirodin's profile picture

Flat Database Engine

Started by Mirodin, 12 May 2013 - 04:13 PM
Mirodin #1
Posted 12 May 2013 - 06:13 PM
Hello guys,

I made myself a little DB-API for my sorting system with interactive sorter.
My LUA experiences are still very modest so please by patient if some code is quite crappy :)/>

I hope, someone with some more practice can help me clean it up.

Functions:
  • versioncheck(ver) Checks for the API-Version ver – Returns true/false
  • check(db) Checks if db is a Database – Returns true/false
  • erstellen(db, name) Creates name on HD and saves db – Returns true
  • laden(name) Loads name from HD – Returns table
  • speichern(db, name) Saves DB db as name on HD – Returns true
  • suchen(db, item) Searches the DB db for item – Returns false OR true and i, w (i=key, w= value) OR true and i, k, v(db[k], v=value)
  • anzeigen(db, from, to, mitk) Shows content of DB db from Index from to Index to (from/to optional) – Returns true (if mitk=true Index gets also returned)
  • einfuegen(db, item, wo, sub, over) Inserts item at Position wo (and "subindex" sub) in DB db. If over is true existing entry gets overwritten – Returns false OR true and db
  • merge(db1, db2) merges db2 in db1 – Returns db1
  • loeschen(db, item) Deletes entry item form DB db – Same as insert
  • backup(name, number) Backups DB name and keeps given number of Backups (number optional)
  • restore(name) Restores DB name
  • drop(name) Drops DB name
  • dropALL(name) Drops DB name and ALL Backups
Spoiler

–[[
**********************************************************************************
** DB-API by JJJonny V1.1 **
** ———————- **
** **
** This DB-API provides a simple Database engine which was designed **
** for my sorting system. **
**********************************************************************************
]]



pfad = "data"
version = 1.1



–[[
—————————————————————————————————
Checks:
Functions which check some parameters.
—————————————————————————————————]]


– Check for correct DB-API Version

function versioncheck(ver)

local p = math.floor(ver)
local e = math.floor(version)

if p == e then

return true

elseif p > e then

print("This program wants a newer version of the DB-API.")
print("Please use following version!")
print("Version: "..p..".x")

return false

else

print("This program wants a older version of the DB-API.")
print("Please use following version!")
print("Version: "..p..".x")

return false

end

end



– Check for table

function check(db)

if type(db) == "table" then

return true

else

print("ERROR: This is not a Database!")

return false

end

end



–[[
—————————————————————————————————
Basic functions:
Creat, load and save the database on HD.
—————————————————————————————————]]


– Creates a new database if there is no

function erstellen(db, name)

local name = name or "data"

if not fs.exists(pfad) then

fs.makeDir(pfad)
print("Database-Directory created!")

end

if not fs.exists(fs.combine(pfad, name)) then

speichern(db, name)

if name == "data" then

print("Standard-database \""..name.."\" created!")

else

print("Database \""..name.."\" created!")

end

end

return true

end



– Loads database

function laden(name)

local name = name or "data"
local file = fs.open(fs.combine(pfad, name), "r")
local tmp = file.readAll()
local daten = textutils.unserialize(tmp)

file.close()
– print("Database \""..name.."\" loaded!")

return daten

end



– Saves database on HD

function speichern(db, name)

local name = name or "data"

if not fs.exists(pfad) then

erstellen(db, name)

end

local file = fs.open(fs.combine(pfad, name), "w")

file.write(textutils.serialize(db))
file.close()
– print("Database \""..name.."\" saved!")

return true

end



–[[
—————————————————————————————————
Extended functions:
Shows content, inserts/updates and deletes Entries.
—————————————————————————————————]]


– Searches database for given item

function suchen(db, item)

if type(db) == "table" then

for i, w in pairs(db) do

if w == item then

return true, i, w

elseif type(w) == "table" then

for k, v in pairs(w) do

if v == item then

return true, i, k, v

end

end

else

print("An Error occured!")

return false

end

end

print("Could not find entry!")

return false

else

return false

end

end



– Lists given area of the database (WIP)

function anzeigen(db, von, bis, mitk)

local _, tast, x, y, einrueck
local count = 1
local w, h = term.getSize()
local tmp = {}
local inter = {
["TOP"] = "Navigate by pressing arrow right/left, press \"Esc\" for exit.",
["TRENN"] = "-",
}

local function show(tab)

einrueck = einrueck + 1
local einrueck = einrueck

for k, v in pairs(tab) do

x, y = term.getCursorPos()

if type(v) == "table" and mitk then

term.setCursorPos(einrueck, y + 1)
term.write(tostring(k))
show(v)

elseif type(v) == "table" and not mitk then

show(v)

elseif mitk then

term.setCursorPos(einrueck,y + 1)
term.write(tostring(k).." - "..tostring(v))

elseif not mitk then

term.setCursorPos(einrueck,y + 1)
term.write(tostring(v))

end

end

end

– Temporary DB

for k, v in pairs(db) do

tmp[count] = {[k] = v}
count = count + 1

end

if type(von) == "boolean" then

mitk = von
von = 1

elseif type(bis) == "boolean" then

mitk = bis
bis = #tmp

end

von = von or 1
bis = bis or #tmp

if von > bis then

print("Start value has to be lower than final value!")
print("Show database beginning with first value…")

von = 1

elseif von > #tmp then

print("Database ends before start value!")
print("Show database beginning with first value…")

von = 1

end

if bis > #tmp then

print("Database ends before final value!")
print("Show database to the end…")

bis = #tmp

end

– End temporary DB

sauber()
print(inter["TOP"].."\n0/"..#tmp)

while true do

_, tast = os.pullEvent("key")

if tast == 203 then

count = count - 1

elseif tast == 205 then

count = count + 1

elseif tast == 1 then

sauber()

return

end

einrueck = 0

if count > bis then

count = von

elseif count < von then

count = bis

end

sauber()
print(inter["TOP"].."\n"..count.."/"..#tmp.."\n")
show(tmp[count])

end

end



– Inserts new data and updates entrys
– sub and over are optional

function einfuegen(db, item, wo, sub, over)

local ueber – if true existing entry gets overwritten

if item == nil then

return false, db

end

if type(over) == "boolean" then

ueber = over

elseif type(sub) == "boolean" then

ueber = sub

else

ueber = false

end

if wo ~= nil then

if sub ~= nil then

if ueber then

db[wo] = { = item}

return true, db

elseif db[wo] == nil then

db[wo] = { = item}

return true, db

elseif type(db[wo]) == "table" and db[wo] == nil then

db[wo] = item

return true, db

else

return false, db

end

else

if ueber then – Ueberschreiben erlaubt

db[wo] = item

return true, db

elseif db[wo] == nil then

db[wo] = item

return true, db

else

return false, db

end

end

elseif db[item] == nil then

if ueber then

db[item] = item

return true, db

elseif db[item] == nil then

db[item] = item

return true, db

else

return false, db

end

else

return false, db

end

end



– Merges DB t2 into t1

function merge(t1, t2)

for k, v in pairs(t2) do

if (type(v) == "table") and (type(t1[k] or false) == "table") then

merge(t1[k], t2[k])

else

t1[k] = v

end

end

return t1

end


– Deletes entry

function loeschen(db, item)

local bool, i, k, v = suchen(db, item)

if bool == false then

print("Entry not found!")

elseif v == item then

print("Do you want to delete \""..item.."\"?")
print("To confirm type \"YES\", to cancel press \"ENTER\"!")

if io.read() == "YES" then

db[k] = nil

print("Entry "..v.." deleted!")

return true, db

else

print("An Error occured when deleting \""..v.."\" in \""..i.." ,"..k.."\"!")

return false

end

elseif k == item then

print("Do you want to delete \""..item.."\"?")
print("To confirm type \"YES\", to cancel press \"ENTER\"!")

if io.read() == "YES" then

db = nil

print("Entry "..v.." deleted!")

return true, db

else

print("An Error occured when deleting \""..k.."\" in \""..i.."\"!")

return false

end

else

print("An Error occured!")

return false

end

end



–[[
—————————————————————————————————
Filesystem:
These functions provide Backup, Restore and Drop abilities for the database file on HD.
—————————————————————————————————]]


– Backup program which keeps defined number of old Backups

function backup(name, anzahl)

local name = name or "data"
local bpfad = fs.combine(pfad, name.."_Backups")

if not fs.exists(bpfad) then

fs.makeDir(bpfad)

end

local anzahl = anzahl or 10
local unten = anzahl - 1
local bupfad = fs.combine(bpfad, name.."_Backup_"..anzahl)
local bupfadneu = fs.combine(bpfad, name.."_Backup_"..unten)

if fs.exists(bupfad) then

fs.delete(bupfad)
print("Delete old data!")

end

for z = anzahl, 1, -1 do

bupfad = fs.combine(bpfad, name.."_Backup_"..z)

if fs.exists(bupfad) then

fs.delete(bupfad)
fs.move(bupfadneu, bupfad)

elseif fs.exists(bupfadneu) then

fs.move(bupfadneu, bupfad)

end

unten = unten - 1

bupfadneu = fs.combine(bpfad, name.."_Backup_"..unten)

end

fs.copy(fs.combine(pfad, name), fs.combine(bpfad, name.."_Backup_1"))
print("Success")

end



– Restores database from Backup

function restore(name)

local base = fs.combine(pfad, name)
local bpfad = fs.combine(pfad, name.."_Backups")
local list = fs.list(bpfad)
local wahl
local nummer = #list or 0

if not fs.exists(bpfad) or nummer == 0 then

print("There are no Backups of \""..name.."\"!")

return false

else

repeat

print("There are "..nummer.." Backups, which one you want to restore?")

for k, v in ipairs(list) do

print(k.." - "..v)

end

wahl = tonumber(io.read())
local ok

if wahl < nummer and wahl > 1 then

print("Do you want to restore "..wahl.."? Accept with \"YES\", press \"ENTER\" to choose another one!")

ok = io.read()

else

sauber()
print("Please choose one Backup!")

ok = nil

end

until ok == "YES"

end

sauber()
print("Backup number "..wahl.." getting restored…")

if fs.exists(base) then

fs.delete(base)
fs.copy(fs.combine(bpfad, name.."_Backup_"..wahl), base)

else

fs.copy(fs.combine(bpfad, name.."_Backup_"..wahl), base)

end

print("Restore of \""..name.."\" succeded!")

end



– Deletes given database WARNING: Can not be undone!!!

function drop(name)

local name = name or "data"

print("Delete database \""..name.."\"!")
print("Please confirm with \"YES\", press \"ENTER\" to cancle!")

local ok = io.read()

if ok == "YES" then

sauber()
print("Do you really want to delete \""..name.."\"? This CAN NOT be undone!")
print("Please confirm with \"YES\", press \"ENTER\" to cancle!")

local okok = io.read()

if okok == "YES" then

sauber()
fs.delete(fs.combine(pfad, name))
print("Database \""..name.."\" deleted permanently!")

end

end

end



– Deletes a database and ALL its Backups WARNING: Can not be undone!!!

function dropALL(name)

local name = name or "data"

print("Delete database \""..name.."\" including ALL Backups!")
print("Please confirm with \"YES\", press \"ENTER\" to cancle!")

local ok = io.read()

if ok == "JA" then

sauber()
print("Do you really want to delete \""..name.."\" and ALL existing Backups? This CAN NOT be undone!")
print("Please confirm with \"YES\", press \"ENTER\" to cancle!")

local okok = io.read()

if okok == "JA" then

sauber()
fs.delete(fs.combine(pfad, name))

for i = 1, 10 do

local bupfad = fs.combine(pfad, name.."_Backup_"..i)

fs.delete(bupfad)

end – for i = 1, 10 do

fs.delete(fs.combine(pfad, name.."_Backups"))
print("Database \""..name.."\" and all Backups deleted permanently!")

end

end

end



–[[
—————————————————————————————————
Misc:
—————————————————————————————————]]


– Clears Monitor

function sauber()

term.clear()
term.setCursorPos(1, 1)

return true

end



http://pastebin.com/arDF3wBs

Cheers
Mirodin

P.S.: No warranty for any issues this code produces.
Feel free to modify, improve, whatever. I would appreciate a link and/or credits ;)/>
Edited on 21 August 2013 - 07:57 AM
darkrising #2
Posted 14 May 2013 - 05:12 AM
Interesting way of storing data, but wouldn't it be easier working with tables?
TorakTu #3
Posted 14 May 2013 - 07:28 AM
Dude !! This is brilliant. Great work !
H4X0RZ #4
Posted 14 May 2013 - 09:33 AM
Nice work!

[Offtopic]
Some variables are german :)/>
I like it to see good german coder :D/>
I'm german too :P/>
[/Offtopic]
Mirodin #5
Posted 27 May 2013 - 12:23 PM
Sorry for long absence, holidays :D/>

Nice work!

[Offtopic]
Some variables are german :)/>
I like it to see good german coder :D/>
I'm german too :P/>
[/Offtopic]

Thanks man. I know about but was to lazy to replace them all ;)/>

Interesting way of storing data, but wouldn't it be easier working with tables?

What do you mean? This thing works with tables. There is one Table which contains all the other tables.
UMayBleed #6
Posted 27 May 2013 - 04:44 PM
Lol this is quite interesting! I am also working on my own MySQL, Except I don't use functions for each command, I am working on complete parsing like SELECT * FROM users WHERE id=1;
btbenedi #7
Posted 05 August 2013 - 03:43 PM
Awesome DB API!

I get an error when trying to insert a new item though

db:188: attempt to call nil

That's the db.search(db,item) line in the insert function.

If I call the db.search(db,item) with the item I'm trying to input, it returns false, as it should since it's a new item. Any ideas?

All of the other functions work flawlessy, I love the backup function.

EDIT: Seems like it's because it's db.search, trying to call it as if it's loaded within itself. Changed db.search to search and it seems to work now.
Mirodin #8
Posted 05 August 2013 - 04:44 PM
Awesome DB API!

I get an error when trying to insert a new item though

db:188: attempt to call nil

That's the db.search(db,item) line in the insert function.

If I call the db.search(db,item) with the item I'm trying to input, it returns false, as it should since it's a new item. Any ideas?

All of the other functions work flawlessy, I love the backup function.

EDIT: Seems like it's because it's db.search, trying to call it as if it's loaded within itself. Changed db.search to search and it seems to work now.

Thank you for feedback. I fixed this issue quite some time ago but forgot to uploade it again :rolleyes:/>
I did quite a bunch of changes the last time and at the moment I think I will pubish that the next days.

Cheers