Datasette内部

2020-12-28 08:07:05

我一直在对Datasette的内部工作进行一些根本性的更改,虽然还没有准备好发布,但是它们正在朝着一个有趣的方向发展。

我对Datasette的目标之一是能够在一个地方处理各种各样的数据。 Datasette Library票证跟踪了这一工作-我希望新闻编辑室(或任何其他基于信息的组织)能够将数百个数据库和可能包含数千个表的数据保存在一个地方。

SQLite数据库只是磁盘上的文件,因此,如果您有成千上万个各种形状和大小的各种数据库,我希望能够在一个Datasette实例中显示它们。

如果您有一百个数据库文件,每个数据库文件包含一百个表,则总共为10,000个表。这意味着需要对主页进行分页,并且需要在Datasette实例可用的表中进行搜索和过滤。

因此,在第1150期中,我已经实现了解决方案的第一部分。在启动时,Datasette现在将创建一个内存中的SQLite数据库,该数据库表示所有已连接的数据库和表,以及这些表的列,索引和外键。

对于演示,请首先以root用户身份登录Latest.datasette.io演示实例,然后访问私有_internal数据库。

这个新的内部数据库目前是私有的,因为我不想公开任何可能由Datasette的权限机制涵盖的有关表的元数据。

新的内存数据库表示基础数据库文件的架构,但是如果添加或修改新表时发生更改,该怎么办?

SQLite有一个巧妙的技巧可以帮助您解决此问题:PRAGMA schema_version返回一个表示模式当前版本的整数,该整数在创建或修改表时会更改。

这意味着我可以缓存表模式,并且仅在发生更改时才重新计算它们。针对与数据库的连接运行PRAGMA schema_version是非常快速的查询。

我首先在datasette-graphql中使用了这个技巧来缓存GraphQL模式自省的结果,因此我相信它也可以在这里工作。

Datasette的权限系统于6月份在Datasette 0.44中添加,适用于插件挂钩。权限插件可以按照以下方式回答问题:是否允许当前经过身份验证的actor对表X执行动作视图表?"。每次询问该问题时,都会通过插件挂钩来查询插件。

在设计权限系统时,我忘记了之前曾学习过的有关权限系统的重要课程:在某个时候,您将需要回答以下问题:“向我显示此角色有权执行操作的所有X的列表” ”。

那个时候到了。如果我要为Datasette渲染一个分页的主页,列出10,000多个表,则需要一种有效的方法来计算允许当前用户查看的10,000个表的子集。

循环调用该插件钩子10,000次并不会减少它。

因此,我开始重新考虑权限了-很高兴我还没有使用Datasette 1.0!

对我有利的是SQLite。以通用的,可定制的方式有效地批量回答权限问题是一个非常困难的问题。有了关系数据库,它变得更加容易。

问题#1152跟踪了我对此的一些思考。我有一种预感,该解决方案将涉及一个新的插件挂钩,可能类似于“返回一个SQL片段,该片段标识该用户可以访问的数据库或表”。然后,我可以针对新的_internal数据库运行该SQL(可能与其他插件使用AND或UNION返回的SQL结合使用同一个钩子来返回该SQL)来构造一组用户可以访问的表。

如果可以这样做,然后对内存中的SQLite数据库运行查询,则应该能够为主页上的10,000多个表提供一个分页的,经过筛选的界面,可以轻松实现我的性能目标。

我想很快在新版本中发布新的_internal数据库,因此我可能最终会为此实现一个较慢的版本。绝对是一个有趣的问题。