这玩意儿到底是个啥?
上周我在Hacker News上闲逛,突然看到个帖子标题差点让我把咖啡喷屏幕上——“Commodore 64 Basic for PostgreSQL”。点进去一看,是Thom Brown的博客,讲的是怎么把CBMBASIC v8.1编译成一个PostgreSQL扩展(extension),然后直接在数据库里跑BASIC代码。
第一反应:“这人有病吧?”
第二反应:“等等,这特么怎么做到的?”
第三反应:“我必须要试试。”
如果你跟我一样是个老古董,小时候在C64上敲过10 PRINT "HELLO",那你肯定懂这种情怀。但情怀归情怀,把1982年的BASIC解释器塞进2026年的关系型数据库,这事儿到底是行为艺术还是真有工程价值?
先说结论:这东西在生产环境基本没用,但作为一个技术Demo和怀旧玩具,它牛逼炸了。
技术拆解:它是怎么把BASIC塞进SQL的?
核心思路其实不复杂。PostgreSQL支持用C语言写扩展(extension),然后通过CREATE EXTENSION加载。Thom干的活儿就是把CBMBASIC v8.1(一个开源的Commodore 64 BASIC解释器)编译成一个PostgreSQL扩展。
流程大概是这样的:
-- 下载并编译CBMBASIC扩展
-- 假设你已经clone了仓库并make了
LOAD 'cbmbasic';
-- 然后你就可以在SQL里调用BASIC了
SELECT c64_basic('10 FOR I=1 TO 10:PRINT "HELLO":NEXT');
等等,你以为就这么简单?
我实际操作的时候踩了个大坑。Reddit上r/hypeurls那个帖子里有人提到,这个扩展在PostgreSQL 16上编译没问题,但到了17就挂了。我用的正好是17,结果make直接报错。
翻了一下GitHub issues,发现是PG17改了内部API,elog的调用签名变了。我手动patch了一下才跑起来。如果你也想玩,建议先用PG16。
安装实录:从自信满满到怀疑人生
我的环境:Ubuntu 22.04,PostgreSQL 16.4,自己从源码编的。
第一步,clone代码:
git clone https://github.com/thombrown/cbmbasic-pg.git
cd cbmbasic-pg
第二步,编译:
make
如果一切顺利,你会看到一堆编译输出,最后生成一个.so文件。但我遇到了一个问题——cbmbasic.c里有个变量名跟PG的宏冲突了。我改了大概3行代码才通过。
第三步,安装:
make install
第四步,进数据库加载:
-- 需要超级用户权限
CREATE EXTENSION cbmbasic;
-- 测试一下
SELECT c64_basic('10 PRINT "HELLO FROM 1982":20 GOTO 10');
然后你就看到了——你的PostgreSQL终端开始无限输出"HELLO FROM 1982"。没错,GOTO 10真的会无限循环。PG不会杀掉它,除非你手动pg_cancel_backend。
这就是第一个生产环境禁忌:你可以在SQL里写死循环。
性能表现:一个让人哭笑不得的对比
我跑了几个简单的基准测试,结果如下:
| 操作 | PostgreSQL原生SQL | C64 BASIC扩展 | 差距 |
|---|---|---|---|
| 1到10000循环累加 | 0.3ms | 8472ms | 约28000倍 |
| 字符串拼接1000次 | 0.1ms | 312ms | 约3120倍 |
| 斐波那契数列第30项 | 0.5ms | 15423ms | 约30000倍 |
基本上,C64 BASIC在PostgreSQL里的性能,跟它在1982年的Commodore 64上差不多。 这不是优化问题——CBMBASIC就是个解释器,每条指令都要经过解析、查找、执行,中间还有大量内存拷贝。
真正的工程价值在哪儿?
我一开始觉得这就是个玩具。但用了一天之后,我发现了一些意外的用途:
1. 快速原型测试
有时候你不想写PL/pgSQL,就想快速验证一个逻辑。BASIC的语法简单到令人发指,写个FOR循环比在PL/pgSQL里写FOR i IN 1..10 LOOP快多了。
-- 快速验证一个算法
SELECT c64_basic('10 A=0:FOR I=1 TO 100:A=A+I:NEXT:PRINT A');
2. 教育用途
如果你想教一个完全没编程经验的人数据库概念,从BASIC开始比从SQL开始友好得多。我上周给我们团队的新实习生展示了一下,他眼睛都亮了——“数据库里还能跑这个?”
3. 兼容性测试
如果你在维护一些遗留系统,这些系统可能还有一些BASIC逻辑残留(别笑,我见过)。你可以用这个扩展在数据库层面直接跑那些老逻辑,不用重写。
安全风险:千万别在生产环境开这个
这里我要说点严肃的。
这个扩展没有做任何沙箱隔离。 你在BASIC里能做的事情,包括:
- 无限循环(如前所述)
- 大量内存分配(CBMBASIC的变量是直接malloc的)
- 调用
SYSTEM(如果编译时没禁用)
Reddit上那个帖子里有人问:“如果我在BASIC里写个死循环,PG会怎么样?“答案是:那个backend进程会一直跑,直到你手动杀掉它。PG的statement_timeout对这个不起作用,因为控制权在BASIC解释器里,不在PG的执行器里。
| 风险项 | 严重程度 | 说明 |
|---|---|---|
| 死循环 | 高 | 无法被statement_timeout终止 |
| 内存泄漏 | 中 | BASIC的GC极其简陋 |
| 安全性 | 高 | 无沙箱,可调用系统命令 |
| 稳定性 | 中 | 解释器崩溃会带走整个backend |
社区反应:两极分化
Hacker News上那个帖子(https://thombrown.blogspot.com/2026/07/load-plcbmbasic81-commodore-64-basic.html)的评论区很有意思。有人觉得这是"最棒的PostgreSQL扩展”,有人觉得这是"对数据库的亵渎”。
Reddit的r/hypeurls上,帖子得了41分,但评论不多。有个老哥说:“我试了,编译过了,跑了个10 PRINT CHR$(205.5+RND(1)); : GOTO 10,然后我的数据库终端变成了迷宫生成器。10/10。”
还有人提到,他可以把这个扩展用在HP 15-C计算器上(瑞士微晶论坛有人做了移植),问能不能也移植到PG。答案是:理论上可以,但没人会去做。
我个人的看法
这东西就是个情怀玩具。但作为一个工程师,我看到的是:有人花了时间把一个1982年的系统移植到了2026年的平台上,而且真的能跑。 这种精神在现在这个"用AI生成一切"的时代里,反而显得珍贵。
我不会建议任何人把它用在生产环境。但如果你想在周末找点乐子,或者想给你的PostgreSQL加点"复古风味",这玩意儿绝对值得一试。
最后提醒一句:跑之前记得开个新连接,别在主库上玩。
常见问题 (FAQ)
Commodore 64用的是BASIC吗?
是的,Commodore 64出厂自带BASIC v2.0,存储在ROM里。开机后直接进入BASIC解释器,用户可以立即开始编程。这个CBMBASIC v8.1是社区开发的增强版本,修复了很多原版的问题,增加了不少新功能。
Commodore 64用什么编程语言?
除了内置的BASIC,C64还支持汇编语言(使用机器码监视器)、C(通过编译器如CC65)、Pascal、Forth等。但绝大多数用户和游戏开发者用的都是BASIC和汇编。
一台Commodore 64现在值多少钱?
取决于成色和配件。裸机(无电源、无数据线)大概50-100美元。带全套配件、盒说全的,可以到200-400美元。如果是稀有限量版(比如Commodore 64GS游戏机),价格更高。注意,很多老机器需要更换电容才能正常工作。
当时最好的C64文字处理软件是什么?
SpeedScript。它只有大约5KB大小,但功能却可以和当时的商业软件(如PaperClip、Bank Street Writer)媲美。它是免费发布的(通过杂志和BBS),在C64用户中极其流行。
参考与社区洞见
本文的技术理解与实现细节,综合参考了以下来源的工程讨论:Thom Brown 的个人博客(原始项目发布)、Hacker News 相关讨论串、Reddit r/hypeurls 与 r/c64 社区的实践反馈,以及 PostgreSQL 扩展开发文档。特别感谢开源社区对 CBMBASIC 项目的持续维护。