Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ----------------------------------------------------
- -- Система управления базами данных от Zer0Galaxy --
- ----------------------------------------------------
- local DBpath,port,password
- do
- local cfgFileName="/etc/dbms.cfg"
- local env = {}
- local config = loadfile(cfgFileName, nil, env)
- if config then
- pcall(config)
- DBpath=env.DBpath
- port=env.port
- password=env.password
- else
- print("Ошибка открытия файла конфигурации '"..cfgFileName.."'") return
- end
- end
- if not DBpath then print("В файле конфигурации не задан путь к базам данных") return end
- local fs=require("filesystem")
- if not fs.isDirectory(DBpath) then
- local ok,err=fs.makeDirectory(DBpath)
- if not ok then print("Ошибка создания дирректории '"..DBpath.."' ",err) return end
- end
- local event=require("event")
- local pushSignal = require("computer").pushSignal
- local ser=require("serialization").serialize
- local uns=require("serialization").unserialize
- local sig_request="mysql_request"
- local sig_ansver ="mysql_ansver"
- local sessions={}
- local currentID
- -------------------------------------------------------------
- local errors={
- [0]="Query OK, ",
- [1]="Ошибка в синтаксисе SQL-запроса; ",
- }
- local types={ --Разрешенные типы данных
- tinyint="number", smallint="number", mediumint="number", int="number", --числовые
- char="string", varchar="string", text="string", --строковые
- bool="boolean", boolean="boolean" --булевые
- }
- local DBs={} --Открытые базы данных
- function saveDB(name, row_num)
- local file,err=io.open(DBpath..name,"w")
- if not file then return false, "Ошибка создания базы данных "..name.."; "..err end
- file:write("db="..ser(DBs[name]))
- file:close()
- return true,errors[0]..(row_num and "строк затронуто "..row_num or "")
- end
- function loadDB(name)
- DBs[name]=nil
- local env = {}
- local db = loadfile(DBpath..name, nil, env)
- if db then
- pcall(db)
- DBs[name]=env.db
- else
- return false, "База данных "..name.." не существует"
- end
- if type(DBs[name])=="table" then return true end
- return false, "Ошибка чтения базы данных "..name
- end
- -------------------------------------------------------------
- funcs={
- version=function() return "1.0 OpenSQL" end,
- }
- -------------------------------------------------------------
- --http://www.site-do.ru/db/db.php
- local query={}
- local function currentDB()
- if not sessions[currentID].DBname then return false, "База данных не выбрана" end
- local DB=DBs[sessions[currentID].DBname]
- if not DB then
- local ok,err=loadDB(sessions[currentID].DBname)
- if not ok then return false,err end
- DB=DBs[sessions[currentID].DBname]
- end
- return DB
- end
- function query.create(data)
- local item,name,filds=tostring(data):match("(%S+)%s*(%S+)%s*(.*)")
- if item=="database" then
- if fs.exists(DBpath..name) then return false, "База данных "..name.." уже существует;" end
- DBs[name]={}
- return saveDB(name)
- elseif item=="table" then
- if not sessions[currentID].DBname then return false, "База данных не выбрана" end
- local DB=DBs[sessions[currentID].DBname]
- if not DB then
- local ok,err=loadDB(sessions[currentID].DBname)
- if not ok then return false,err end
- DB=DBs[sessions[currentID].DBname]
- end
- if DB[name] then return false, "Таблица '"..name.."' уже существует" end
- filds=filds:match("%((.+)%)")
- if not filds then return false, errors[1] end
- filds=filds..","
- -- print(filds)
- local tab={name={}, type={}, default={}, extra={}}
- for f_name, f_type, f_params in filds:gmatch("([_%w]+)%s+([_%w]+)%s*(.-),") do
- -- print(f_name,f_type,f_params)
- --[[
- name - название колонки
- -- table - название таблицы, которой принадлежит колонка
- -- max_length - максимальная длинна содержания
- not_null - 1, если колонка не может быть равна NULL
- primary_key - 1, если колонка -- первичный индекс
- unique_key - 1, если колона -- уникальный индекс
- multiple_key - 1, если колонка -- не уникальный индекс
- -- numeric - 1, если колонка численная
- -- blob - 1, если колонка -- BLOB
- type - тип колонки
- -- unsigned - 1, если колонка строго положительная (unsigned)
- -- zerofill - 1, если колонка заполняется нулями (zero-filled)]]
- table.insert(tab.name,f_name)
- if types[f_type] then table.insert(tab.type,types[f_type])
- else return false, errors[1]..","..f_type.."'"
- end
- table.insert(tab.extra,f_params)
- end
- DB[name]=tab
- return saveDB(sessions[currentID].DBname)
- else
- return false, errors[1]..(item or "")
- end
- end
- function query.select(data)
- data=tostring(data) or ""
- local result={}
- local fields,tab,cond,order_by,desc
- -- сортировка по убыванию ORDER BY field DESC
- fields,order_by=data:match("^%s*(.+)%s+order%s+by%s+(.+)%s+desc%s*$")
- if fields then
- data=fields
- desc=true
- else -- сортировка по возрастанию ORDER BY field
- fields,order_by=data:match("^%s*(.+)%s+order%s+by%s+(.+)%s*$")
- if fields then data=fields end
- end
- -- выбор по условию WHERE condition
- fields,cond=data:match("^%s*(.-)%s+where%s+(.-)%s*$")
- if fields then data=fields end
- -- выбор из таблицы FROM table
- fields,tab=data:match("^%s*(.-)%s+from%s+(.-)%s*$")
- -- SELECT fields
- if not fields then fields=data end
- fields=fields..","
- local env=setmetatable({},{__index=funcs})
- local col=""
- result.name={}
- for field in fields:gmatch("%s*(.-)%s*,") do
- local expr,name=field:match("(.-)%s+as%s+([_%w]+)")
- if expr then
- table.insert(result.name,name)
- col=col..expr..","
- else
- table.insert(result.name,field)
- col=col..field..","
- end
- end
- if tab then
- local DB,err=currentDB()
- if not DB then return false,err end
- if not DB[tab] then return false, "Таблица '"..sessions[currentID].DBname.."."..tab.."' не существует" end
- tab=DB[tab]
- if col=="*," then
- result.name=tab.name
- col=table.concat(tab.name,",")
- end
- local Fcol=load("return {"..col.."}",_,_,env)
- if not Fcol then return false, errors[1]..col end
- local Fcond
- if cond then
- Fcond=load("return "..cond,_,_,env)
- if not Fcond then return false, errors[1]..cond end
- end
- for i=1,#tab do
- for j=1,#tab.name do env[tab.name[j]]=tab[i][j] end
- if Fcond then
- local ok,output=pcall(Fcond)
- if not ok or not output then goto continue end
- end
- local ok,output=pcall(Fcol)
- if not ok then return false, errors[1]..col.." в строке "..i end
- table.insert(result,output)
- ::continue::
- end
- if order_by then
- local Fnum
- for i=1,#result.name do
- if result.name[i]==order_by then Fnum=i break end
- end
- if Fnum then
- table.sort(result,
- function(row1,row2)
- row1,row2=row1[Fnum],row2[Fnum]
- if not row1 then return false end
- if not row2 then return true end
- if desc then return row1>row2 end
- return row1<row2
- end
- )
- else
- return false, errors[1]..order_by
- end
- end
- else
- local Fcol=load("return {"..col.."}",_,_,env)
- if not Fcol then return false, errors[1]..col end
- local ok,output=pcall(Fcol)
- if not ok then return false, errors[1]..col end
- result[1]=output
- end
- return ser(result)
- end
- function query.use(data)
- local name=tostring(data):match("(.*)%s*$")
- if not name then return false,"USE: укажите имя базы данных" end
- if not DBs[name] then
- local ok,err=loadDB(name)
- if not ok then return false,err end
- end
- sessions[currentID].DBname=name
- return true, "Произведена смена базы данных"
- end
- function query.show(item)
- item=tostring(item):match("(.*)%s*$")
- local result={}
- if item=="databases" then
- result.name="Databases"
- for db in fs.list(DBpath) do
- table.insert(result,db)
- end
- elseif item=="tables" then
- local DB,err=currentDB()
- if not DB then return false,err end
- result.name="Tables_in_"..sessions[currentID].DBname
- for tab in pairs(DB) do
- table.insert(result,tab)
- end
- else
- return false, errors[1]..(item or "")
- end
- table.sort(result)
- return ser(result)
- end
- function query.describe(tab)
- tab=tostring(tab):match("(.*)%s*$")
- local DB,err=currentDB()
- if not DB then return false,err end
- if not DB[tab] then return false, "Таблица '"..sessions[currentID].DBname.."."..tab.."' не существует" end
- tab=DB[tab]
- local result={name={"Field","Type","Default","Extra"}}
- for i=1,#tab.name do
- result[i]={tab.name[i],tab.type[i],(tab.default or {})[i],(tab.extra or {})[i]}
- end
- return ser(result)
- end
- function query.drop(data)
- local item,name=tostring(data):match("(%S+)%s*(%S+)")
- if item=="database" then
- if not fs.exists(DBpath..name) then return false, "База данных "..name.." не существует;" end
- DBs[name]=nil
- local ok,err=fs.remove(DBpath..name)
- if not ok then return false, "Ошибка удаления базы '"..name.."'; "..err end
- return true, errors[0]
- elseif item=="table" then
- local DB,err=currentDB()
- if not DB then return false,err end
- if not DB[name] then return false, "Таблица '"..sessions[currentID].DBname.."."..name.."' не существует" end
- DB[name]=nil
- return saveDB(sessions[currentID].DBname)
- else
- return false, errors[1]..(item or "")
- end
- end;
- function query.insert(data)
- local tab, fields,values = data:match("^%s*into%s+([_%w]+)%s*%((.*)%)%s*values%s*%((.*)%)%s*$")
- if not tab then tab, values = data:match("^%s*into%s+([_%w]+)%s+values%s*%((.*)%)%s*$") end
- if not tab then return false, errors[1] end
- local DB,err=currentDB()
- if not DB then return false,err end
- if not DB[tab] then return false, "Таблица '"..sessions[currentID].DBname.."."..tab.."' не существует" end
- tab=DB[tab]
- local result = uns("{"..values.."}")
- if not result then return false, errors[1]..values end
- local row={}
- if fields then
- for i=1,#tab.name do
- if tab.default then row[i]=tab.default[i] end
- if tab.type[i]=="number" and tab.extra[i]:find("auto_increment") then
- local Max=0
- for j=1,#tab do
- if type(tab[j][i])=="number" and tab[j][i]>Max then Max=tab[j][i] end
- end
- row[i]=math.floor(Max)+1
- end
- end
- fields=fields..","
- local field_num={}
- for i=1,#tab.name do field_num[tab.name[i]]=i end
- local n=1
- for field in fields:gmatch("([_%w]+)%s*,") do
- if not field_num[field] then return false, "Поле "..field.." отсутствует в таблице" end
- row[field_num[field]]=result[n]
- n=n+1
- end
- else
- if #tab.name~=#result then return false, "Количество колонок таблицы не соответствует количеству данных" end
- for i=1,#tab.type do
- if type(result[i])==tab.type[i] then
- table.insert(row,result[i])
- else
- return false, "Несоответствие типа данных "..result[i]
- end
- end
- end
- table.insert(tab,row)
- return saveDB(sessions[currentID].DBname,1)
- end
- -------------------------------------------------------------
- local commands={}
- function commands.close()
- sessions[currentID]=nil
- return true
- end
- function commands.connect()
- local id=#sessions+1
- sessions[id]={}
- return id
- end
- function commands.query(que)
- local command,data=tostring(que):match("(%S+)%s*(.*)")
- if not command then return false, "Ошибка в строке запроса" end
- if query[command] then return query[command](data)
- else return false, errors[1]..command end
- end
- -------------------------------------------------------------
- function request(ev_name, id, command, ...)
- if not command then pushSignal(sig_ansver, id, false, "Команда не определена") return end
- currentID=id
- if commands[command] then pushSignal(sig_ansver, id, commands[command](...))
- else pushSignal(sig_ansver, id, false, errors[1]..command) end
- end
- if not event.listen(sig_request,request) then
- print("Невозможно запустить обработчик события "..sig_request) return
- end
- print("MySQL-сервер успешно запущен")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement