Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua表作为数据库的前端_Lua_Redis_Lua Table - Fatal编程技术网

Lua表作为数据库的前端

Lua表作为数据库的前端,lua,redis,lua-table,Lua,Redis,Lua Table,我正在尝试将数据库实现为Lua表。使用元表时,该表将为空,当表中的某个项被请求或修改时,它将返回或修改数据库中的该项。除了请求的部分之外,数据库本身永远不会加载到内存中。它应该作为一个表(因为它是一个表)被程序交互。由于该表只是一个“前端”,因此它会将修改后的数据保存到数据库中(而不是在表中定义该项) 在没有表的表中,这很容易实现。我试图使它与一个不确定深度的多层表一起工作。 (旁白:我考虑的数据库是redis。理想情况下,只要更改基本的操作语法,就可以为任何数据库或类似数据库的服务器实现这一点

我正在尝试将数据库实现为Lua表。使用元表时,该表将为空,当表中的某个项被请求或修改时,它将返回或修改数据库中的该项。除了请求的部分之外,数据库本身永远不会加载到内存中。它应该作为一个表(因为它是一个表)被程序交互。由于该表只是一个“前端”,因此它会将修改后的数据保存到数据库中(而不是在表中定义该项)

在没有表的表中,这很容易实现。我试图使它与一个不确定深度的多层表一起工作。 (旁白:我考虑的数据库是redis。理想情况下,只要更改基本的操作语法,就可以为任何数据库或类似数据库的服务器实现这一点。)

由于Lua元表的行为,只有在顶层修改(或创建,如果使用代理)某些内容时才使用
\uu newindex
方法。当读取某个内容时,将调用
\u index
方法,即使该调用是修改子表中的某个内容。因此,我试图编写一个
\uuu index
方法,当请求一个表时,该方法返回另一个具有相同行为的伪代理(代理数据库的表而不是另一个表),但该代理用于顶级中的表/数组/列表等,深度不确定。我在挣扎

我的问题是:

  • 这项措施以前实施过吗
  • 我应该关注“适当”吗 而不是我现在在做什么

创建表时,只需在fake中添加一个空表并将其设置为metatable:

local fake = {}
do
   local lookup = {} --Will be using this to avoid using lots of metatables

   local real = {}

   local meta
   meta = {
      __index = function(self,i)
         return rawget(lookup[self], i)
      end,
      __newindex = function(self,i,v)
         rawset(lookup[self], i, v)
         if type(v) == "table" then
             rawset(self, i, setmetatable({},meta))
             lookup[self[i]] = v
         end
      end
   }

   setmetatable(fake, meta)
   lookup[fake] = real
end

fake[1] = "hello"
print(fake[1])
print(rawget(fake, 1))
fake.x = {"hi"}
print(fake.x)
print(rawget(fake, 'x')) --This still prints a table because there actually is one, but in reality it's abiding by our rules
print(fake.x[1])
print(rawget(fake.x, 1))
fake.x.y = "aha"
print(fake.x.y)
print(rawget(fake.x, 'y'))
此方法的唯一警告是,他们可以直接修改数据库,如下所示:

fake.myvalue = {}
fake.myvalue = 5
另一种方法可以是边走边包装:

local fake = {}
do
   local lookup = {} --Will be using this to avoid using lots of metatables
   local cache = {} --will be using to avoid usings tons of new objects

   local real = {}

   local meta
   meta = {
      __index = function(self,i)
         local val = rawget(lookup[self], i)
         if type(val) == "table" then
            if cache[val] then
                return cache[val]
            else
                local faker = {}
                lookup[faker] = val
                cache[val] = faker
                return setmetatable(faker, meta)
             end
         else
            return val
         end
       end,
      __newindex = function(self,i,v)
         rawset(lookup[self], i, v)
      end
   }

   setmetatable(fake, meta)
   lookup[fake] = real
end

fake[1] = "hello"
print(fake[1])
print(rawget(fake, 1))

fake.x = {"hi"}
print(fake.x)
print(rawget(fake, 'x')) --This still prints a table because there actually is one, but in reality it's abiding by our rules
print(fake.x[1])
print(rawget(fake.x, 1))
fake.x.y = "aha"
print(fake.x.y)
print(rawget(fake.x, 'y'))
完全避免了直接修改的问题