测试DuckDB电子表格读取插件rusty_sheet 0.2版

又在超第一时间拿到了张泽鹏先生的rusty_sheet插件0.2版,迫不及待装上测试,却发现DuckDB对插件版本卡得很严,1.4.0都用不了1.4.1版的插件。这难不倒我,一边下载新版本DuckDB,一边让deepseek编了个python程序,把插件中间的1.4.1都替换成了1.4.0,就可以在1.4.0中用了。

代码如下:

python 复制代码
import sys
import os

def replace_string_in_binary(filename, old_str, new_str):
    """
    在二进制文件中替换指定字符串
    """
    # 检查文件是否存在
    if not os.path.exists(filename):
        print(f"错误: 文件 '{filename}' 不存在")
        return False
    
    # 检查新旧字符串长度是否相同
    if len(old_str) != len(new_str):
        print(f"错误: 新旧字符串长度必须相同 ('{old_str}' -> '{new_str}')")
        return False
    
    try:
        # 读取二进制文件
        with open(filename, 'rb') as f:
            content = f.read()
        
        # 将二进制内容转换为字节数组以便修改
        content_bytearray = bytearray(content)
        
        # 将字符串编码为字节
        old_bytes = old_str.encode('utf-8')
        new_bytes = new_str.encode('utf-8')
        
        # 查找并替换所有匹配的字节序列
        replaced_count = 0
        i = 0
        while i <= len(content_bytearray) - len(old_bytes):
            # 检查是否匹配
            if content_bytearray[i:i+len(old_bytes)] == old_bytes:
                # 替换字节
                content_bytearray[i:i+len(old_bytes)] = new_bytes
                replaced_count += 1
                i += len(old_bytes)  # 跳过已替换的部分
            else:
                i += 1
        
        if replaced_count == 0:
            print(f"未找到字符串 '{old_str}'")
            return False
        
        # 写回文件
        with open(filename, 'wb') as f:
            f.write(content_bytearray)
        
        print(f"成功替换 {replaced_count} 处 '{old_str}' -> '{new_str}'")
        return True
        
    except Exception as e:
        print(f"处理文件时出错: {e}")
        return False

def main():
    # 检查命令行参数
    if len(sys.argv) != 4:
        print("用法: python rep.py <文件名> <旧字符串> <新字符串>")
        print("示例: python rep.py file.bin \"1.4.1\" \"1.4.0\"")
        sys.exit(1)
    
    filename = sys.argv[1]
    old_str = sys.argv[2]
    new_str = sys.argv[3]
    
    # 执行替换
    success = replace_string_in_binary(filename, old_str, new_str)
    
    if not success:
        sys.exit(1)

if __name__ == "__main__":
    main()

如果希望在旧版本测试的,可以使用这个程序。

sql 复制代码
python3 rep.py '/par/14/rusty_sheet.duckdb_extension' "1.4.1" "1.4.0"
成功替换 5 处 '1.4.1' -> '1.4.0'
root@66d4e20ec1d7:/par# ./duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/14/rusty_sheet.duckdb_extension';
D from read_sheets('/par/file*xls',header=0);
┌─────────────┐
│      A      │
│   varchar   │
├─────────────┤
│ Hello World │
│ Hello World │
└─────────────┘

这个版本插件最大的变化有两点,第一点:支持通配符处理多个电子表格;第二点:支持更多种类电子表格,包括旧版xls文件,ODS、wps et文件等。

上哪去找那么多种电子表格?我从calamine的源代码包中找到了一些,位于calamine/tests/。

先看这个插件包括的函数

sql 复制代码
select function_name from duckdb_functions() where function_name like '%sheet%';
┌────────────────┐
│ function_name  │
│    varchar     │
├────────────────┤
│ read_sheet     │
│ read_sheets    │
│ analyze_sheet  │
│ analyze_sheets │

函数名一目了然,分析读取单个、多个电子表格文件。

下面举例

1.分析单表单个sheet, 用analyze_sheet,

例如

sql 复制代码
from analyze_sheet('/par/2025work.xlsx',sheet_name='证书',header=1);
┌─────────────┬─────────────┐
│ column_name │ column_type │
│   varchar   │   varchar   │
├─────────────┼─────────────┤
│ 8日         │ varchar     │
│ B           │ varchar     │
│ C           │ varchar     │

如果用通配符,那么只有第一个满足条件的sheet被分析

sql 复制代码
from analyze_sheet('/par/2025work.xlsx',sheet_name='*',header=1);
┌──────────────────────────┬─────────────┐
│       column_name        │ column_type │
│         varchar          │   varchar   │
├──────────────────────────┼─────────────┤
│ 工单创建时间             │ varchar     │
│ 工单办结时间             │ varchar     │

2.分析单表多个sheet, 用analyze_sheets ,

sql 复制代码
from analyze_sheets('/par/2025work.xlsx',sheets=['证书','工单实录'],header=1);
┌────────────────────┬────────────┬──────────────────────────┬─────────────┐
│     file_name      │ sheet_name │       column_name        │ column_type │
│      varchar       │  varchar   │         varchar          │   varchar   │
├────────────────────┼────────────┼──────────────────────────┼─────────────┤
│ /par/2025work.xlsx │ 工单实录   │ 工单创建时间             │ varchar     │
│ /par/2025work.xlsx │ 工单实录   │ 工单办结时间             │ varchar     │
│         ·          │  ·         │ ·                        │    ·        │
│ /par/2025work.xlsx │ 证书       │ J                        │ varchar     │
│ /par/2025work.xlsx │ 证书       │ K                        │ varchar     │

虽然analyze_sheets也可以用来分析单个sheet, 但是有冗余列,不推荐

sql 复制代码
 from analyze_sheets('/par/2025work.xlsx',sheets=['证书'],header=1);
┌────────────────────┬────────────┬─────────────┬─────────────┐
│     file_name      │ sheet_name │ column_name │ column_type │
│      varchar       │  varchar   │   varchar   │   varchar   │
├────────────────────┼────────────┼─────────────┼─────────────┤
│ /par/2025work.xlsx │ 证书       │ 8日         │ varchar     │
│ /par/2025work.xlsx │ 证书       │ B           │ varchar     │
│ /par/2025work.xlsx │ 证书       │ C           │ varchar     │

3.读取单文件多个sheet, 用read_sheets

通配符读取所有满足条件的sheet

sql 复制代码
from read_sheets('/par/400.xls',sheets=['*']);
┌──────────────────────┬─────────┬─────────┬────────────────┬
│  400热线分日工单情况 │    B    │    C    │       D        │ 
│       varchar        │ varchar │ varchar │    varchar     │ 
├──────────────────────┼─────────┼─────────┼────────────────┼
│ 分日工单情况         │ NULL    │ NULL    │ 分类型工单数量 │
│ 日期                 │ 星期    │ 接起量  │ 口令\n问题     │ 
│ 2025-01-01           │ 元旦    │ 11      │ 5              │ 
│     ·                │  ·      │ ·       │ ·              │
│ 2025-12-29           │ 周五    │ 0       │ NULL           │ 
│ 2025-12-30           │ 周六    │ 0       │ NULL           │ 
│ 2025-12-31           │ 周日    │ 0       │ NULL           │ 
│ 合计                 │ NULL    │ 0       │ 0              │ 
├──────────────────────┴─────────┴─────────┴────────────────┴
│ 401 rows (40 shown) 

也可以用明确的sheet名列表

sql 复制代码
from read_sheets('/par/400.xls',sheets=['一月','二月']);
┌──────────────────────┬─────────┬─────────┬────────────────┬
│  400热线分日工单情况 │    B    │    C    │       D        │ 
│       varchar        │ varchar │ varchar │    varchar     │ 
├──────────────────────┼─────────┼─────────┼────────────────┼
│ 分日工单情况         │ NULL    │ NULL    │ 分类型工单数量 │
│ 日期                 │ 星期    │ 接起量  │ 口令\n问题     │ 
│ 2025-01-01           │ 元旦    │ 11      │ 5              │ 
│     ·                │  ·      │ ·       │ ·              │
│ 2025-02-28           │ 周五    │ 198     │ 17             │
│ 合计                 │ NULL    │ 2637    │ 406            │
├──────────────────────┴─────────┴─────────┴────────────────┴
│ 65 rows (40 shown)

4.读取多文件多个sheet, 用read_sheets,列标题按第一个sheet的列标题给出,缺少的列用NULL填充

.system ls ???.xls

conv.xls demo.xls file.xls gbk2.xls

sql 复制代码
from read_sheets('/par/????.xls',sheets=['*'],header=1);
┌──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────────┐
│          id          │        title         │     inserted_at      │      updated_at      │         mapping          │
│       varchar        │       varchar        │       varchar        │       varchar        │         varchar          │
├──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────────┤
│ e6535268-e25a-4620...  │ 把下列句子翻译成英语 │ 2025-01-23T14:10:3...  │ 2025-01-23T14:48:2...  │ Length too long!         │
│ 74c16f63-675c-4bc8...  │ 货车运输成本最小化...  │ 2025-01-27T13:56:2...  │ 2025-01-27T14:06:5...  │ Length too long!         │
│ ·                    │  ·                   │  ·                   │  ·                   │  ·                       │
│ 23                   │ "doubly quoted str...  │ 'singly quoted str...  │ NULL                 │ NULL                     │
│ 24                   │ Formula:             │ The quick brown fox  │ 2                    │ NULL                     │
│ 1                    │ Tom                  │ 12.4                 │ NULL                 │ NULL                     │
│ 2                    │ Jerry                │ 3                    │ NULL                 │ NULL                     │
│ 3                    │ 张一                 │ -12                  │ NULL                 │ NULL                     │
├──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────────┤
│ 281 rows (40 shown)                                                                                        5 columns │
相关推荐
曹牧7 小时前
Oracle数据库中,将JSON字符串转换为多行数据
数据库·oracle·json
被摘下的星星8 小时前
MySQL count()函数的用法
数据库·mysql
末央&8 小时前
【天机论坛】项目环境搭建和数据库设计
java·数据库
徒 花8 小时前
数据库知识复习07
数据库·作业
素玥8 小时前
实训5 python连接mysql数据库
数据库·python·mysql
jnrjian8 小时前
text index 查看index column index定义 index 刷新频率 index视图
数据库·oracle
瀚高PG实验室9 小时前
审计策略修改
网络·数据库·瀚高数据库
言慢行善9 小时前
sqlserver模糊查询问题
java·数据库·sqlserver
韶博雅9 小时前
emcc24ai
开发语言·数据库·python
爱分享的阿Q9 小时前
Rust加WebAssembly前端性能革命实践指南
前端·rust·wasm