用李红艳先生的DuckDB luajit插件批量计算数独

这个插件比名字类似的lua插件功能强大太多,不要装错。

存储库地址:https://github.com/alitrack/duckdb-luajit

1.安装插件

复制代码
memory D force install luajit from community;
memory D load luajit;

2.拉取远程duckdb-luajit现成库(https://github.com/alitrack/duckdb-luajit-libs)

复制代码
--列举可用模块
memory D SELECT * FROM luajit_module(mode := 'list_remote');
┌─────────┬─────────────┬─────────────┬────────────────────┬────────────────────────────────────────────────┬──────────┐
│   ok    │    mode     │    phase    │      message       │                     detail                     │ sql_name │
│ boolean │   varchar   │   varchar   │      varchar       │                    varchar                     │ varchar  │
├─────────┼─────────────┼─────────────┼────────────────────┼────────────────────────────────────────────────┼──────────┤
│ true    │ list_remote │ list_remote │ duckdb-luajit-libs │ available libs:\n  dicom --- libs/datasource/dic │          │
│         │             │             │                    │ om.lua\n  dirscan --- libs/datasource/dirscan.lu │          │
│         │             │             │                    │ a\n  export --- libs/export/export.lua\n  json --- │          │
│         │             │             │                    │  libs/parser/json.lua\n  base64 --- libs/udf/bas │          │
│         │             │             │                    │ e64.lua\n  crc32 --- libs/udf/crc32.lua\n  uuid  │          │
│         │             │             │                    │ --- libs/udf/uuid.lua\n  html_escape --- libs/udf/ │          │
│         │             │             │                    │ html_escape.lua\n  mcp_demo --- libs/mcp/mcp-ser │          │
│         │             │             │                    │ ver.sql\n                                      │          │
└─────────┴─────────────┴─────────────┴────────────────────┴────────────────────────────────────────────────┴──────────┘
--拉取base64 udf
memory D SELECT * FROM luajit_module(mode := 'install', sql_name := 'base64');
┌─────────┬─────────┬─────────┬──────────────────────────────────────┬──────────────────────────────────────┬──────────┐
│   ok    │  mode   │  phase  │               message                │                detail                │ sql_name │
│ boolean │ varchar │ varchar │               varchar                │               varchar                │ varchar  │
├─────────┼─────────┼─────────┼──────────────────────────────────────┼──────────────────────────────────────┼──────────┤
│ true    │ install │ install │ installed 'base64' (UDF) --- cached at │ luajit_table('base64') or luajit_s(' │ base64   │
│         │         │         │  ~/.duckdb/luajit-libs/base64.lua    │ base64', ...)                        │          │
└─────────┴─────────┴─────────┴──────────────────────────────────────┴──────────────────────────────────────┴──────────┘
--使用base64 udf成功
memory D SELECT luajit_s('base64', 'hello');
┌─────────────────────────────┐
│ luajit_s('base64', 'hello') │
│           varchar           │
├─────────────────────────────┤
│ aGVsbG8=                    │
└─────────────────────────────┘

错误的用法尝试

复制代码
--希望安装mcp_demo,报错
memory D SELECT * FROM luajit_module(mode := 'install', sql_name := 'mcp_demo');
┌─────────┬─────────┬─────────┬───────────────────────────────────────────────────────────────────┬─────────┬──────────┐
│   ok    │  mode   │  phase  │                              message                              │ detail  │ sql_name │
│ boolean │ varchar │ varchar │                              varchar                              │ varchar │ varchar  │
├─────────┼─────────┼─────────┼───────────────────────────────────────────────────────────────────┼─────────┼──────────┤
│ false   │ install │         │ install 'mcp_demo': [string "-- @lib: mcp_demo..."]:28: '=' expec │         │ mcp_demo │
│         │         │         │ ted near '*'                                                      │         │          │
└─────────┴─────────┴─────────┴───────────────────────────────────────────────────────────────────┴─────────┴──────────┘
--拉取sudoku失败,第一次是网络问题,第二次网络正常后,说不在索引中
memory D SELECT * FROM luajit_module(mode := 'install', sql_name := 'sudoku');
┌─────────┬─────────┬─────────┬───────────────────────────────────────────────────────────────────┬─────────┬──────────┐
│   ok    │  mode   │  phase  │                              message                              │ detail  │ sql_name │
│ boolean │ varchar │ varchar │                              varchar                              │ varchar │ varchar  │
├─────────┼─────────┼─────────┼───────────────────────────────────────────────────────────────────┼─────────┼──────────┤
│ false   │ install │         │ install 'sudoku' failed: IO Error: Timeout was reached error for  │         │ sudoku   │
│         │         │         │ HTTP HEAD to 'https://raw.githubusercontent.com/alitrack/duckdb-l │         │          │
│         │         │         │ uajit-libs/main/INDEX'                                            │         │          │
└─────────┴─────────┴─────────┴───────────────────────────────────────────────────────────────────┴─────────┴──────────┘
memory D SELECT * FROM luajit_module(mode := 'install', sql_name := 'sudoku');
┌─────────┬─────────┬─────────┬──────────────────────────────────────────────────────────┬─────────┬──────────┐
│   ok    │  mode   │  phase  │                         message                          │ detail  │ sql_name │
│ boolean │ varchar │ varchar │                         varchar                          │ varchar │ varchar  │
├─────────┼─────────┼─────────┼──────────────────────────────────────────────────────────┼─────────┼──────────┤
│ false   │ install │         │ install 'sudoku' failed: lib 'sudoku' not found in INDEX │         │ sudoku   │
└─────────┴─────────┴─────────┴──────────────────────────────────────────────────────────┴─────────┴──────────┘

实地查看索引内容,确实不存在一个sudoku udf

复制代码
ls ~/.duckdb/luajit-libs/
INDEX  base64.lua  mcp_demo.lua
root@DESKTOP-59T6U68:/mnt/c/d# cat ~/.duckdb/luajit-libs/INDEX
dicom|libs/datasource/dicom.lua
dirscan|libs/datasource/dirscan.lua
export|libs/export/export.lua
json|libs/parser/json.lua
base64|libs/udf/base64.lua
crc32|libs/udf/crc32.lua
uuid|libs/udf/uuid.lua
html_escape|libs/udf/html_escape.lua
mcp_demo|libs/mcp/mcp-server.sql

考虑到国内上github.com经常网络出错,趁早把存储库整个下载到本地duckdb-luajit-libs-main目录下。

然后复制mcp-server.sql中的语句

复制代码
-- 2. 注册 Lua UDF: 数独求解 (模块文件 sudoku.lua 需同目录, 或改用 install 协议从本仓库拉)
memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_solve',
           source := 'local s = dofile(''duckdb-luajit-libs-main/libs/mcp/sudoku.lua'') return function(x) return s.solve(x) end');
┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────────┐
│   ok    │  mode   │  phase  │ message │ detail  │   sql_name   │
│ boolean │ varchar │ varchar │ varchar │ varchar │   varchar    │
├─────────┼─────────┼─────────┼─────────┼─────────┼──────────────┤
│ true    │ compile │ compile │ OK      │         │ sudoku_solve │
└─────────┴─────────┴─────────┴─────────┴─────────┴──────────────┘

memory D SELECT luajit_s('sudoku_solve', '000001002000020030004500600007600050080090006100005800001004000070900003400030020') AS r;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                                         r                                         │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 359461782716829534824573619947682351583197246162345897631254978275918463498736125 │
└───────────────────────────────────────────────────────────────────────────────────┘
memory D .timer on
memory D select count(*) from read_csv('sudoku17.txt');
┌──────────────┐
│ count_star() │
│    int64     │
├──────────────┤
│        49150 │
└──────────────┘
Run Time (s): real 0.075 user 0.007009 sys 0.014781


memory D with a(i) as(select * from read_csv('sudoku17.txt') limit 3)select luajit_s('sudoku_solve',i)from a;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                            luajit_s('sudoku_solve', i)                            │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 793684512486512937125973846932751684578246391641398725319465278857129463264837159 │
│ 673894512912735486845612973798261354526473891134589267469128735287356149351947628 │
│ 679835412123694758548217936416723895892561374735489621287956143961342587354178269 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 10.209 user 9.331371 sys 0.000000

计算成功,速度不算太快,可能是算法过于简单原因。

李艳红先生将上述测试文档输入AI,AI自动找到了问题,并且修复了,顺便还升级了数独算法,用新的sudoku.lua重新编译一版sudoku_solve_opt函数,速度是上一版本的100倍。

复制代码
testluaudf D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_solve_opt',
                        source := 'local s = dofile(''./sudoku.lua'') return function(x) return s.solve(x) end');
┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────────────┐
│   ok    │  mode   │  phase  │ message │ detail  │     sql_name     │
│ boolean │ varchar │ varchar │ varchar │ varchar │     varchar      │
├─────────┼─────────┼─────────┼─────────┼─────────┼──────────────────┤
│ true    │ compile │ compile │ OK      │         │ sudoku_solve_opt │
└─────────┴─────────┴─────────┴─────────┴─────────┴──────────────────┘

testluaudf D with a(i) as(select * from read_csv('sudoku17.txt') limit 3)select luajit_s('sudoku_solve_opt',i)from a;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                          luajit_s('sudoku_solve_opt', i)                          │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 793684512486512937125973846932751684578246391641398725319465278857129463264837159 │
│ 673894512912735486845612973798261354526473891134589267469128735287356149351947628 │
│ 679835412123694758548217936416723895892561374735489621287956143961342587354178269 │
└───────────────────────────────────────────────────────────────────────────────────┘
testluaudf D .timer on
testluaudf D with a(i) as(from read_csv('sudoku17.txt') limit 3)select max(luajit_s('sudoku_solve_opt',i))from a;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                       max(luajit_s('sudoku_solve_opt', i))                        │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 793684512486512937125973846932751684578246391641398725319465278857129463264837159 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 0.071 user 0.015625 sys 0.000000
testluaudf D with a(i) as(from read_csv('sudoku17.txt') limit 300)select max(luajit_s('sudoku_solve_opt',i))from a;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                       max(luajit_s('sudoku_solve_opt', i))                        │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 986735124143298576275614893459183762821467359637529481592371648364852917718946235 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 5.289 user 5.234375 sys 0.031250

又及,上个版本还存在lua自定义函数不能持久化的问题,现在也解决了。

https://github.com/alitrack/duckdb-luajit/releases/tag/v0.32 下载离线版插件。强制安装并装载。

将内存数据库保存到物理数据库文件,再次打开此文件,load luajit;后,原来编译的lua自定义函数直接能用。

复制代码
C:\d>duckdb155 -unsigned
DuckDB v1.5.5 (Variegata)
Enter ".help" for usage hints.
memory D force install 'C:\Users\lt\Downloads\luajit.duckdb_extension';
memory D from duckdb_extensions();
┌──────────────────┬─────────┬───────────┬───┬───────────────────┬───────────────────┬─────────────────────────────────┐
│  extension_name  │ loaded  │ installed │ ... │ extension_version │   install_mode    │         installed_from          │
│     varchar      │ boolean │  boolean  │ ... │      varchar      │      varchar      │             varchar             │
├──────────────────┼─────────┼───────────┼───┼───────────────────┼───────────────────┼─────────────────────────────────┤
│ luajit           │ false   │ true      │ ... │ v0.32             │ CUSTOM_PATH       │ C:\Users\lt\Downloads\luajit.d... │

memory D load luajit;
memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_solve',
                                 source := 'local s = dofile(''duckdb-luajit-libs-main/libs/mcp/sudoku.lua'') return function(x) return s.solve(x) end');
┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────────┐
│   ok    │  mode   │  phase  │ message │ detail  │   sql_name   │
│ boolean │ varchar │ varchar │ varchar │ varchar │   varchar    │
├─────────┼─────────┼─────────┼─────────┼─────────┼──────────────┤
│ true    │ compile │ compile │ OK      │         │ sudoku_solve │
└─────────┴─────────┴─────────┴─────────┴─────────┴──────────────┘
memory D SELECT luajit_s('sudoku_solve', '000001002000020030004500600007600050080090006100005800001004000070900003400030020') AS r;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                                         r                                         │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 359461782716829534824573619947682351583197246162345897631254978275918463498736125 │
└───────────────────────────────────────────────────────────────────────────────────┘
memory D ATTACH 'lua032.db';

memory D COPY FROM DATABASE memory to lua032;
memory D .exit

C:\d>duckdb155 lua032.db -unsigned
DuckDB v1.5.5 (Variegata)
Enter ".help" for usage hints.
lua032 D load luajit;
lua032 D SELECT luajit_s('sudoku_solve', '000001002000020030004500600007600050080090006100005800001004000070900003400030020') AS r;
┌───────────────────────────────────────────────────────────────────────────────────┐
│                                         r                                         │
│                                      varchar                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 359461782716829534824573619947682351583197246162345897631254978275918463498736125 │
└───────────────────────────────────────────────────────────────────────────────────┘
相关推荐
聆风吟º2 小时前
【金仓数据库征文】Java 应用接入金仓数据库:从驱动、连接池到存储过程调试的踩坑实录
java·开发语言·数据库
程序员-Benothing4 小时前
MySQL 的覆盖索引是什么?
数据库·mysql
数翊科技4 小时前
权威认可!HexaDB海纳分布式HTAP数据库通过CCRC EAL4增强级认证
数据库
星恒讯工业路由器4 小时前
MIMO与多天线技术:从5G到WiFi的工程解析
数据库·mysql·5g·工业物联网·mimo技术·天线隔离度·5g/wifi多天线
deepdata_cn4 小时前
向量数据库赋能研报智能分析、舆情检索、风险洞察
数据库·向量数据库
涤生大数据5 小时前
Flink Agents 深度剖析:这才是生产级 AI Agent 该有的底座!
数据库·人工智能
海上小飞龙5 小时前
Redis 持久化:RDB 与 AOF
数据库·redis·缓存
hold?fish:palm5 小时前
redis中AOF 重写机制解析
数据库·c++·redis
Minxinbb5 小时前
TDSQL for MySQL修改统计信息参数
数据库·dba
2501_937860945 小时前
MySQL数据库入门|从零搞懂数据库基础、架构与存储引擎
数据库·mysql·架构