利用SQL脚本批量测试电子表格插件rusty_sheet 0.2.读取各种格式文件
因为要对DuckDB电子表格插件测试各种千奇百怪格式文件的读取功能,逐个输入文件名很麻烦,所以想到用DuckDB的脚本生成。
第1步,用ls命令生成文件名列表
/par/calamine/tests$ ls -1
adhocallbabynames1996to2016.xls
any_sheets.ods
any_sheets.xls
any_sheets.xlsb
any_sheets.xlsx
biff5_write.xls
covered.ods
用复制粘贴或重定向保存到文件xlsx.txt。
第2步,在DuckDB用select语句生成SQL列表
.mode list
.header off
select 'from analyze_sheets(''/par/calamine/tests/'||trim(txt)||''');' from read_csv('/par/xlsx.txt')t(txt);
如果要排除或筛选某种格式文件,可以加where条件
select 'from analyze_sheets(''/par/calamine/tests/'||trim(txt)||''');' from read_csv('/par/xls.txt')t(txt) where txt not like '%xlsx';
输出如下
from read_sheets('/par/calamine/tests/inventory-table.xlsx');
from read_sheets('/par/calamine/tests/issue_391.xlsx');
from read_sheets('/par/calamine/tests/richtext-namespaced.xlsx');
from read_sheets('/par/calamine/tests/date.xlsx');
from read_sheets('/par/calamine/tests/issue127.xlsx');
...
可以用.output文件名,再执行select语句生成脚本文件,也可以将结果复制粘贴到文本编辑器保存。
用.read 脚本文件名执行。
测试记录如下
./duckdb140 -unsigned -cmd "load '/par/14/rusty_sheet.duckdb_extension';"
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D .read ana_xlse.txt
Binder Error:
Sheet 'Hidden' is empty
Binder Error:
Sheet 'Hidden' is empty
Binder Error:
failed to fill whole buffer
┌─────────────────────────────────┬────────────┬─────────────┬─────────────┐
│ file_name │ sheet_name │ column_name │ column_type │
│ varchar │ varchar │ varchar │ varchar │
├─────────────────────────────────┼────────────┼─────────────┼─────────────┤
│ /par/calamine/tests/covered.ods │ sheet1 │ a1 │ varchar │
└─────────────────────────────────┴────────────┴─────────────┴─────────────┘
┌───────────┬────────────┬─────────────┬─────────────┐
│ file_name │ sheet_name │ column_name │ column_type │
│ varchar │ varchar │ varchar │ varchar │
├───────────┴────────────┴─────────────┴─────────────┤
│ 0 rows │
└────────────────────────────────────────────────────┘
有的文件报错,但是不知道哪个文件错了,虽然analyze_sheets正确结果中有file_name字段,但报错的看不到,所以修改查询语句如下,
就能知道错在哪了。read_sheets本来就不输出文件名,如有需要也可以加上。
select 'any_sheets.ods'file_name ; from analyze_sheet('/par/calamine/tests/any_sheets.ods')limit 2;select 'any_sheets.ods'file_name ; from read_sheet('/par/calamine/tests/any_sheets.ods')limit 2;select 'any_sheets.ods'file_name ; from analyze_sheets('/par/calamine/tests/any_sheets.ods')limit 2;select 'any_sheets.ods'file_name ; from read_sheets('/par/calamine/tests/any_sheets.ods')limit 2;
这样就方便定位错误文件,例如:
D select 'any_sheets.ods'file_name ; from read_sheet('/par/calamine/tests/any_sheets.ods')limit 2;
┌────────────────┐
│ file_name │
│ varchar │
├────────────────┤
│ any_sheets.ods │
└────────────────┘
┌─────────┬───────┐
│ 1 │ 2 │
│ varchar │ int64 │
├─────────┼───────┤
│ 3 │ 4 │
│ 5 │ 6 │
└─────────┴───────┘
Run Time (s): real 0.002 user 0.000000 sys 0.000000
D select 'any_sheets.ods'file_name ; from analyze_sheet('/par/calamine/tests/any_sheets.ods')limit 2;
┌────────────────┐
│ file_name │
│ varchar │
├────────────────┤
│ any_sheets.ods │
└────────────────┘
┌─────────────┬─────────────┐
│ column_name │ column_type │
│ varchar │ varchar │
├─────────────┼─────────────┤
│ 1 │ varchar │
│ 2 │ bigint │
└─────────────┴─────────────┘
Run Time (s): real 0.002 user 0.000000 sys 0.004000
D select 'any_sheets.ods'file_name ; from analyze_sheets('/par/calamine/tests/any_sheets.ods')limit 2;
┌────────────────┐
│ file_name │
│ varchar │
├────────────────┤
│ any_sheets.ods │
└────────────────┘
Run Time (s): real 0.001 user 0.000000 sys 0.000000
Binder Error:
Sheet 'Hidden' is empty
D select 'any_sheets.ods'file_name ; from read_sheets('/par/calamine/tests/any_sheets.ods')limit 2;
┌────────────────┐
│ file_name │
│ varchar │
├────────────────┤
│ any_sheets.ods │
└────────────────┘
┌─────────┬───────┐
│ 1 │ 2 │
│ varchar │ int64 │
├─────────┼───────┤
│ 3 │ 4 │
│ 5 │ 6 │
└─────────┴───────┘
为了生成这种带文件名的自动测试脚本,可以将前面的Select语句修改如下:
select 'select '''||trim(txt)||'''file_name ; from analyze_sheets(''/par/calamine/tests/'||trim(txt)||''');' from read_csv('/par/xls.txt')t(txt);
注意同样的表,analyze_sheets报错,但read_sheets不报错,这是因为read_sheets遇到有问题的sheet跳过,而analyze_sheets分析所有的sheet。
上述脚本遇到导致DuckDB崩溃的错误就中止了,这时可以手工在脚本文件出错行前加上--
注释掉该行。多次执行和注释,就能确定全部出错的文件。