newcat

ComputerCraft Database v1.01

Jun 2nd, 2014
527
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.91 KB | None | 0 0
  1. --Tests if the database 'dbName' exists.
  2. --Returns true if it does, else it returns false
  3. function dbExists(dbName)
  4.     if (fs.isDir("Databases\\" .. dbName)) then
  5.         return true --Database exists
  6.     else
  7.         return false --Database doesn't exist
  8.     end
  9. end
  10.  
  11. --Tests if the table 'tableName' exists in the database 'db'
  12. --Returns true if it does, else it returns false
  13. function tableExists(db, tableName)
  14.     if dbExists(db) then
  15.         if (fs.isDir("Databases\\" .. db .. "\\" .. tableName)) then
  16.             return true
  17.         else
  18.             return false
  19.         end
  20.     else
  21.         print("Invalid Database")
  22.         return false
  23.     end
  24. end
  25.  
  26. --This function behaves like the CREATE DATABASE operator in MySQL.
  27. --Ex: MySQL: CREATE DATABASE `exampleDB`
  28. --in this API: db.createDatabase("exampleDB")
  29. function createDatabase(dbName)
  30.     if (not(fs.isDir("Databases"))) then
  31.         fs.makeDir("Databases")
  32.     end
  33.     if (not(dbExists(dbName))) then
  34.         fs.makeDir("Databases\\" .. dbName)
  35.     else
  36.         print("Database already existing!")
  37.     end
  38. end
  39.  
  40. --This function behaves like the DROP DATABASE operator in MySQL.
  41. --Ex: MySQL: DROP DATABASE `exampleDB`
  42. --in this API: db.deleteDatabase("exampleDB")
  43. function deleteDatabase(dbName)
  44.     if (dbExists(dbName)) then
  45.         fs.delete("Databases\\" .. dbName)
  46.     end
  47. end
  48.  
  49. --With this function you can create a new table.
  50. --You dont need to specify any columns like in MySQL.
  51. --The keys are set completely flexible, so you can create a key
  52. --named "foo" for one row, and for the other you can create a key
  53. --named "bar".
  54. function createTable(db, tableName)
  55.     if (dbExists(db)) then
  56.         if (tableExists(db, tableName)) then
  57.             print("Table already exists!")
  58.         else
  59.             fs.makeDir("Databases\\" .. db .. "\\" .. tableName)
  60.         end
  61.     else
  62.         print("Invalid Database!")
  63.     end
  64. end
  65.  
  66. --This function behaves like the RENAME TABLE operator in MySQL.
  67. --Ex: MySQL: RENAME TABLE `exampleTable` TO `newName`
  68. --in this API: db.renameTable("DatabaseName", "exampleTable", "newName")
  69. function renameTable(db, oldName, newName)
  70.     if (dbExists(db)) then
  71.         if (tableExists(db, oldName)) then
  72.             basePath = "Databases\\" .. db .. "\\"
  73.             fs.move(basePath .. oldName, basePath .. newName)
  74.         else
  75.             print("Invalid Table")
  76.         end
  77.     else
  78.         print("Invalid Database!")
  79.     end
  80. end
  81.  
  82. --This function behaves like the DROP TABLE operator in MySQL.
  83. --Ex: MySQL: DROP TABLE `exampleTable`
  84. --in this API: db.deleteTable("DatabaseName", "exampleTable")
  85. function deleteTable(db, tableName)
  86.     if (dbExists(db)) then
  87.         if (tableExists(db, oldName)) then
  88.             path = "Databases\\" .. db .. "\\" .. tableName
  89.             fs.delete(path)
  90.         else
  91.             print("Invalid Table")
  92.         end
  93.     else
  94.         print("Invalid Database!")
  95.     end
  96. end
  97.  
  98. --This function is a mix of:
  99. --MYSQL: SELECT * FROM `exampleTable` WHERE 1
  100. --and PHP: mysql_num_rows()
  101. function getTotalEntries(db, tableName)
  102.     if (dbExists(db)) then
  103.         if (tableExists(db, tableName)) then
  104.             path = "Databases\\" .. db .. "\\" .. tableName
  105.             ls = fs.list(path)
  106.             totalEntries = 0
  107.             for _ in pairs(ls) do totalEntries = totalEntries + 1 end
  108.             return totalEntries
  109.         else
  110.             print("Invalid Table!")
  111.             return nil
  112.         end
  113.     else
  114.         print("Invalid Database!")
  115.         return nil
  116.     end
  117. end
  118.  
  119. --This function behaves like the UPDATE/INSERT operator in MySQL.
  120. --Ex: MySQL: INSERT INTO `exampleTable` (`id`, `foo`) VALUES ('1', 'bar')
  121. --in this API: db.set("DatabaseName", "exampleTable", db.getNextFreeID(), "foo", "bar")
  122. --MySQL: UPDATE `exampleTable` SET `foo` = 'updatedValue' WHERE `id` = '1'
  123. --in this API: db.set("DatabaseName", "exampleTable", 1, "foo", "updatedValue")
  124. --NOTE: It doesn't matter if you hand over the ID as number or as string
  125. function set(db, tableName, id, key, value)
  126.     if (dbExists(db)) then
  127.         if (tableExists(db, tableName)) then
  128.             if (not(fs.isDir("Databases\\" .. db .. "\\" .. tableName .. "\\" .. id))) then
  129.                 fs.makeDir("Databases\\" .. db .. "\\" .. tableName .. "\\" .. id)
  130.             end
  131.             path = "Databases\\" .. db .. "\\" .. tableName .. "\\" .. id .. "\\" .. key
  132.             keyFile = fs.open(path, "w")
  133.             keyFile.write(value)
  134.             keyFile.close()
  135.         else
  136.             print("Invalid Table!")
  137.         end
  138.     else
  139.         print("Invalid Database!")
  140.     end
  141. end
  142.  
  143. --This function behaves like the SELECT operator in MySQL.
  144. --Ex: MySQL: SELECT `foo` FROM `exampleTable` WHERE `id` = '1'
  145. --in this API: db.get("DatabaseName", "exampleTable", 1, "foo")
  146. --NOTE: It doesn't matter if you hand over the ID as number or as string
  147. function get(db, tableName, id, key)
  148.     if (dbExists(db)) then
  149.         if (tableExists(db, tableName)) then
  150.             path = "Databases\\" .. db .. "\\" .. tableName .. "\\" .. id .. "\\" .. key
  151.             if (fs.exists(path)) then
  152.                 keyFile = fs.open(path, "r")
  153.                 value = keyFile.readAll()
  154.                 keyFile.close()
  155.                 return value
  156.             else
  157.                 return nil
  158.             end
  159.         else
  160.             print("Invalid Table!")
  161.         end
  162.     else
  163.         print("Invalid Database!")
  164.     end
  165. end
  166.  
  167. --This function behaves like the DELETE operator in MySQL.
  168. --Ex: MySQL: DELETE FROM `exampleTable` WHERE `id` = '1'
  169. --in this API: db.delete("DatabaseName", "exampleTable", 1)
  170. function delete(db, tableName, id)
  171.     if (dbExists(db)) then
  172.         if (tableExists(db, tableName)) then
  173.             path = "Databases\\" .. db .. "\\" .. tableName .. "\\" .. id
  174.             if (fs.exists(path)) then
  175.                 fs.delete(path)
  176.             end
  177.         else
  178.             print("Invalid Table!")
  179.         end
  180.     else
  181.         print("Invalid Database!")
  182.     end
  183. end
  184.  
  185. --This function is similar to the WHERE operator in MySQL.
  186. --It returns all the id's, where the value of the key specified
  187. --is the same as the value you gave as a parameter.
  188. --Ex: MySQL: SELECT `id` FROM `exampleTable` WHERE `foo` = 'bar'
  189. --in this API: db.getIdsByValue("DatabaseName", "exampleTable", "foo", "bar")
  190. function getIdsByValue(db, tableName, key, value)
  191.     if (dbExists(db)) then
  192.         if (tableExists(db, tableName)) then
  193.             path="Databases\\" .. db .. "\\" .. tableName .. "\\"
  194.             ls = fs.list(path)
  195.             index = 0
  196.             ids = {}
  197.             for _, file in ipairs(ls) do
  198.                 origValue = get(db, tableName, file, key)
  199.                 if (origValue == value) then
  200.                     index = index + 1
  201.                     ids[index] = file
  202.                 end
  203.             end
  204.             return ids
  205.         else
  206.             print("Invalid Table!")
  207.         end
  208.     else
  209.         print("Invalid Database!")
  210.     end
  211. end
  212.  
  213. --Gets the next not used ID
  214. --Behaves like manual auto-increment
  215. function getNextFreeID(db, tableName)
  216.     if (dbExists(db)) then
  217.         if (tableExists(db, tableName)) then
  218.             totalEntries = getTotalEntries(db, tableName)
  219.             path = "Databases\\" .. db .. "\\" .. tableName
  220.             ls = fs.list(path)
  221.             nextFreeID = tonumber(ls[totalEntries]) + 1
  222.             return nextFreeID
  223.         else
  224.             print("Invalid Table!")
  225.             return nil
  226.         end
  227.     else
  228.         print("Invalid Database!")
  229.         return nil
  230.     end
  231. end
  232.  
  233. function splitString(aString)
  234.     --Split the string (query) into single words
  235.     --and put them into a table
  236.     local index = 0
  237.     local splitString = {}
  238.     for word in string.gmatch(aString, "[%a%d]+") do
  239.         index = index + 1
  240.         splitString[index] = word
  241.     end
  242.     return splitString
  243. end
  244.  
  245. function query(db, query)
  246.     --Get the first word, so the program knows, what to do
  247.     --Possible: SELECT | UPDATE | INSERT | DELETE | CREATE | RENAME | DROP
  248.     --IMPORTANT NOTE: You cant use parameters with spaces yet.
  249.     --So something like UPDATE exampleTable SET foo = 'Hello World' isn't possible yet.
  250.     --I will try to understand the gmatch-Patterns, so i can improve that.
  251.    
  252.     split = splitString(query)
  253.    
  254.     if (split[1] == "SELECT") then return sqlSELECT(db, query)
  255.     elseif (split[1] == "UPDATE") then sqlUPDATE(db, query)
  256.     elseif (split[1] == "INSERT") then return sqlINSERT(db, query)
  257.     elseif (split[1] == "DELETE") then sqlDELETE(db, query)
  258.     elseif (split[1] == "CREATE") then sqlCREATE(db, query)
  259.     elseif (split[1] == "RENAME") then sqlRENAME(db, query)
  260.     elseif (split[1] == "DROP") then sqlDROP(db, query)
  261.     else
  262.         print("Invalid SQL Query! Possible Operators (need to be the first word):")
  263.         print("SELECT | UPDATE | INSERT | DELETE | CREATE | DROP")
  264.     end
  265. end
  266.  
  267. --db.query("TestDB", "UPDATE TestTable1 SET key = 'Value' WHERE id = '2'")
  268.  
  269. function sqlSELECT(db, query)
  270.     --Standard SELECT query should look like this:
  271.     --SELECT foo FROM exampleTable WHERE id = 1
  272.     --So we need the words 2 (key) | 4 (table) | 6 (id or key) | 8 (searchValue)
  273.    
  274.     split = splitString(query)
  275.    
  276.     key = split[2]
  277.     tableName = split[4]
  278.    
  279.     if (split[6] == "id") then
  280.         --since we have got a single id we can just use the get-function
  281.         return get(db, tableName, split[6], key)
  282.     else
  283.         --get the lists of IDs where key=value
  284.         ids = getIdsByValue(db, tableName, split[6], split[8])
  285.        
  286.         --get the value of the key for every id found
  287.         index = 0
  288.         results = {}
  289.         for _, id in ipairs(ids) do
  290.             index = index + 1
  291.             results[index] = get(db, tableName, id, key)
  292.         end
  293.        
  294.         --results[0] is the total count of results found
  295.         results[0] = index
  296.         return results
  297.     end
  298. end
  299.  
  300. function sqlUPDATE(db, query)
  301.     --Standard UPDATE query should look like this (only accepting a single value to be updated due to Lua
  302.     --string parsing limitations, but this value can be updated in multiple rows):
  303.     --UPDATE exampleTable SET foo = newValue WHERE id = 1
  304.     --So we need the words 2 (table) | 4 (key) | 5 (newValue) | 7 (id or key) | 8 (searchValue)
  305.    
  306.     split = splitString(query)
  307.    
  308.     tableName = split[2]
  309.     key = split[4]
  310.     newValue = split[5]
  311.    
  312.     if (split[7] == "id") then
  313.         --since we have got a single id we can just use the set-function
  314.         set(db, tableName, split[8], key, newValue)
  315.     else
  316.         --get the lists of IDs where key=value
  317.         ids = getIdsByValue(db, tableName, split[7], split[8])
  318.        
  319.         --set the value of the key for every id found
  320.         index = 0
  321.         results = {}
  322.         for _, id in ipairs(ids) do
  323.             index = index + 1
  324.             set(db, tableName, id, key, newValue)
  325.         end
  326.     end
  327. end
  328.  
  329. function sqlINSERT(db, query)
  330.     --This function behaves a bit different as the MySQL model.
  331.     --Instead of giving multiple keys and values you can just use this query:
  332.     --INSERT INTO exampleTable
  333.     --It will return the ID of the row that has just been inserted, so you can use UPDATE after.
  334.     --If you want to create a row with one key and value, you can simply use the UPDATE query with given id after WHERE like this:
  335.     --UPDATE exampleTable SET foo = newValue WHERE id = '5'
  336.     --If a row with the id '5' isn't existing, the program will automatically create it and create the key with the given value.
  337.     --Therefore the function db.getNextFreeID() can be useful, this is the only advantage this function has over the UPDATE function,
  338.     --because this function directly looks for the next free ID, so you dont have to parameterize the ID.
  339.     --This function is limited due to Lua string parsing limitations and will maybe get fixed in future versions
  340.    
  341.     split = splitString(query)
  342.    
  343.     tableName = split[3]   
  344.     nextFreeID = getNextFreeID(db, tableName)
  345.    
  346.     fs.makeDir("Databases\\" .. db .. "\\" .. tableName .. "\\" .. nextFreeID)
  347.    
  348.     return nextFreeID
  349.  
  350. end
  351.    
  352.    
  353.  
  354. function sqlDELETE(db, query)
  355.     --Standard DELETE query should look like this:
  356.     --DELETE FROM exampleTable WHERE id = '1'
  357.     --So we need the words 3 (table) | 5 (id or key) | 6 (searchValue)
  358.    
  359.     split = splitString(query)
  360.    
  361.     tableName = split[3]
  362.    
  363.     if (split[5] == "id") then
  364.         --since we have got a single id we can just use the delete-function
  365.         delete(db, tableName, split[6])
  366.     else
  367.         --get the lists of IDs where key=value
  368.         ids = getIdsByValue(db, tableName, split[5], split[6])
  369.        
  370.         --delete the row for every id found
  371.         index = 0
  372.         results = {}
  373.         for _, id in ipairs(ids) do
  374.             index = index + 1
  375.             delete(db, tableName, id)
  376.         end
  377.     end
  378. end
  379.  
  380. function sqlCREATE(db, query)
  381.     --Standard CREATE query should look like this:
  382.     --CREATE DATABASE dbName
  383.     --or
  384.     --CREATE TABLE tableName
  385.     --So we need the words 2 (operator) | 3 (name)
  386.     --NOTE: If you create a database, its not necessary to parameterize the db, you can just hand over nil
  387.    
  388.     split = splitString(query)
  389.    
  390.     operator = split[2]
  391.     name = split[3]
  392.    
  393.     if (operator == "DATABASE") then createDatabase(name)
  394.     elseif (operator == "TABLE") then createTable(db, name)
  395.     else
  396.         print("Invalid second operator! Possible second operators:")
  397.         print("DATABASE | TABLE")
  398.     end
  399. end
  400.  
  401. function sqlRENAME(db, query)
  402.     --Standard RENAME query should look like this:
  403.     --RENAME TABLE oldName TO newName
  404.     --So we need the words 3 (oldName) | 5 (newName)
  405.     --NOTE: In MySQL it it possible to rename multiple DB's at once, but in this API you
  406.     --can only rename one at the same time due to Lua string parsing limitations
  407.    
  408.     split = splitString(query)
  409.    
  410.     oldName = split[3]
  411.     newName = split[5]
  412.    
  413.     renameTable(db, oldName, newName)
  414. end
  415.  
  416. function sqlDROP(db, query)
  417.     --Standard DROP query should look like this:
  418.     --DROP DATABASE dbName
  419.     --or
  420.     --DROP TABLE tableName
  421.     --So we need the words 2 (operator) | 3 (name)
  422.    
  423.     split = splitString(query)
  424.    
  425.     operator = split[2]
  426.     name = split[3]
  427.    
  428.     if (operator == "DATABASE") then deleteDatabase(name)
  429.     elseif (operator == "TABLE") then deleteTable(db, name)
  430.     else
  431.         print("Invalid second operator! Possible second operators:")
  432.         print("DATABASE | TABLE")
  433.     end
  434. end
Advertisement
Add Comment
Please, Sign In to add comment