├── actions ├── image │ └── TAG └── runner │ ├── ufw_before_rules.txt │ ├── multipass.sh │ └── cloud-init.yaml ├── .prettierignore ├── lib ├── src │ ├── wasm_main.cc │ ├── extensions │ │ ├── json_extension.cc │ │ └── parquet_extension.cc │ └── utils │ │ └── thread.cc ├── include │ └── duckdb │ │ └── web │ │ ├── arrow_stream_factory.h │ │ ├── extensions │ │ ├── json_extension.h │ │ └── parquet_extension.h │ │ ├── utils │ │ ├── thread.h │ │ ├── spin_mutex.h │ │ ├── shared_mutex.h │ │ ├── parallel.h │ │ ├── debug.h │ │ └── parking_lot.h │ │ ├── io │ │ ├── file_page_defaults.h │ │ └── glob.h │ │ ├── test │ │ └── config.h │ │ ├── environment.h │ │ ├── insert_options.h │ │ ├── arrow_type_mapping.h │ │ ├── udf.h │ │ ├── arrow_insert_options.h │ │ ├── json_dataview.h │ │ ├── functions │ │ └── table_function_relation.h │ │ └── json_typedef.h ├── .gitignore ├── .clang-format ├── README.md ├── test │ ├── tester.cc │ ├── bugs_test.cc │ └── ifstream_test.cc └── cmake │ ├── gflags.cmake │ ├── rapidjson.cmake │ └── spdlog.cmake ├── tools └── dataprep │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── error.rs ├── data ├── .gitignore ├── test.csv └── test.json ├── examples ├── bare-node │ ├── .gitignore │ ├── package.json │ └── index.cjs ├── esbuild-node │ ├── .gitignore │ ├── bundle.mjs │ ├── tsconfig.json │ ├── package.json │ └── index.mjs ├── bare-browser │ ├── .gitignore │ ├── node_modules │ │ └── .bin │ │ │ └── http-server │ ├── package.json │ └── bundle.mjs └── esbuild-browser │ ├── .gitignore │ ├── index.html │ ├── tsconfig.json │ ├── serve.json │ ├── package.json │ └── index.ts ├── packages ├── duckdb-wasm-app │ ├── src │ │ ├── utils │ │ │ ├── format.ts │ │ │ └── platform.ts │ │ ├── model │ │ │ ├── index.ts │ │ │ └── model_context.ts │ │ ├── pages │ │ │ ├── docs.module.css │ │ │ ├── shell.module.css │ │ │ ├── blog.module.css │ │ │ ├── docs.tsx │ │ │ ├── table.tsx │ │ │ ├── versus.module.css │ │ │ └── table.module.css │ │ └── components │ │ │ ├── minibar_chart.module.css │ │ │ ├── page_structure.tsx │ │ │ ├── page_structure.module.css │ │ │ ├── minibar_chart.tsx │ │ │ └── feature_table.module.css │ ├── .eslintignore │ ├── .gitignore │ ├── test │ │ ├── index.ts │ │ └── shell.test.ts │ ├── types │ │ ├── crate.d.ts │ │ ├── csv.d.ts │ │ ├── html.d.ts │ │ ├── png.d.ts │ │ ├── sql.d.ts │ │ ├── svg.d.ts │ │ ├── tbl.d.ts │ │ ├── wasm.d.ts │ │ ├── parquet.d.ts │ │ ├── worker.d.ts │ │ ├── css-modules.d.ts │ │ └── editor-worker.d.ts │ ├── static │ │ ├── favicons │ │ │ ├── favicon.ico │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── mstile-150x150.png │ │ │ ├── sharingduckdb.jpg │ │ │ ├── apple-touch-icon.png │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-384x384.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── browserconfig.xml │ │ │ ├── site.webmanifest │ │ │ └── safari-pinned-tab.svg │ │ ├── fonts │ │ │ ├── Nunito-Bold.ttf │ │ │ ├── Nunito-Light.ttf │ │ │ ├── Nunito-Regular.ttf │ │ │ ├── Nunito-SemiBold.ttf │ │ │ └── fonts.module.css │ │ └── svg │ │ │ ├── icons │ │ │ ├── minus.svg │ │ │ ├── plus.svg │ │ │ ├── warn.svg │ │ │ ├── check.svg │ │ │ ├── delete.svg │ │ │ ├── view-list.svg │ │ │ ├── close.svg │ │ │ ├── minus-circle.svg │ │ │ ├── tray_full.svg │ │ │ ├── add.svg │ │ │ ├── delete-outline.svg │ │ │ ├── monitor.svg │ │ │ ├── file-document-outline.svg │ │ │ ├── table.svg │ │ │ ├── file-chart.svg │ │ │ ├── cloud.svg │ │ │ ├── shell.svg │ │ │ ├── file-table.svg │ │ │ ├── duckdb_logo.svg │ │ │ ├── file-table-box.svg │ │ │ ├── timer.svg │ │ │ ├── pivot.svg │ │ │ ├── data-matrix.svg │ │ │ ├── server.svg │ │ │ ├── data-matrix-scan.svg │ │ │ ├── clockfast.svg │ │ │ └── book.svg │ │ │ └── logo │ │ │ └── duckdb.svg │ ├── .eslintrc │ ├── webpack.release.js │ ├── webpack.debug.corp.js │ ├── tsconfig.json │ └── webpack.tests.js ├── duckdb-wasm-shell │ ├── crate │ │ ├── src │ │ │ ├── error.rs │ │ │ ├── xterm │ │ │ │ ├── sugar │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── addons │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── ligatures.rs │ │ │ │ │ ├── unicode11.rs │ │ │ │ │ ├── serialize.rs │ │ │ │ │ ├── webgl.rs │ │ │ │ │ ├── web_links.rs │ │ │ │ │ └── attach.rs │ │ │ ├── comfy │ │ │ │ ├── utils │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── style │ │ │ │ │ ├── modifiers.rs │ │ │ │ │ ├── cell.rs │ │ │ │ │ └── column.rs │ │ │ ├── duckdb │ │ │ │ ├── mod.rs │ │ │ │ ├── version.rs │ │ │ │ └── web_file.rs │ │ │ ├── shell_options.rs │ │ │ └── lib.rs │ │ └── Cargo.toml │ ├── .eslintignore │ ├── .gitignore │ ├── src │ │ ├── index.ts │ │ ├── platform.ts │ │ ├── version.ts │ │ └── utils │ │ │ └── format.ts │ ├── .eslintrc │ ├── tsconfig.json │ └── README.md ├── duckdb-wasm │ ├── src │ │ ├── bindings │ │ │ ├── .gitignore │ │ │ ├── duckdb-coi.pthread.d.ts │ │ │ ├── duckdb-coi.d.ts │ │ │ ├── duckdb-eh.d.ts │ │ │ ├── duckdb-mvp.d.ts │ │ │ ├── tokens.ts │ │ │ ├── progress.ts │ │ │ ├── index.ts │ │ │ ├── web_file.ts │ │ │ ├── udf_function.ts │ │ │ ├── duckdb_module.ts │ │ │ ├── bindings_browser_mvp.ts │ │ │ ├── bindings_node_eh.ts │ │ │ ├── bindings_node_mvp.ts │ │ │ ├── bindings_browser_coi.ts │ │ │ ├── bindings_browser_eh.ts │ │ │ └── insert_options.ts │ │ ├── utils │ │ │ ├── index.ts │ │ │ ├── binary_dump.ts │ │ │ └── opfs_util.ts │ │ ├── index.ts │ │ ├── parallel │ │ │ └── index.ts │ │ ├── index_docs.ts │ │ ├── worker.ts │ │ ├── version.ts │ │ ├── status.ts │ │ └── targets │ │ │ ├── duckdb.ts │ │ │ ├── duckdb-browser-blocking.ts │ │ │ ├── duckdb-node-blocking.ts │ │ │ ├── duckdb-node-eh.worker.ts │ │ │ ├── duckdb-browser-coi.worker.ts │ │ │ ├── duckdb-browser-eh.worker.ts │ │ │ ├── duckdb-browser-mvp.worker.ts │ │ │ └── duckdb-node-mvp.worker.ts │ ├── .eslintignore │ ├── jasmine.json │ ├── .prettierrc.js │ ├── types │ │ ├── wasm.d.ts │ │ └── web-worker.d.ts │ ├── .gitignore │ ├── karma │ │ ├── tests-debug.cjs │ │ ├── tests-firefox.cjs │ │ ├── tests-all.cjs │ │ ├── tests-chrome.cjs │ │ ├── tests-chrome-coverage.cjs │ │ └── s3rver │ │ │ └── s3rver.js │ ├── .eslintrc.json │ ├── typedoc.json │ ├── test │ │ ├── json.test.ts │ │ ├── regression │ │ │ ├── index.ts │ │ │ ├── github_1467.test.ts │ │ │ └── github_1833.test.ts │ │ ├── string_test_helper.ts │ │ ├── table_test.ts │ │ ├── long_queries.test.ts │ │ └── tokenizer.test.ts │ ├── tsconfig.json │ └── coverage.mjs ├── benchmarks │ ├── .eslintignore │ ├── .gitignore │ ├── src │ │ ├── utils │ │ │ ├── index.ts │ │ │ ├── shuffle.ts │ │ │ └── format.ts │ │ ├── internal │ │ │ └── index.ts │ │ ├── system │ │ │ └── index.ts │ │ ├── suite_internal.ts │ │ ├── suite_system_tpch_arquero.ts │ │ ├── suite_system_sum_csv.ts │ │ ├── suite_system_tpch_duckdb.ts │ │ ├── suite_system_tpch_lovefield.ts │ │ └── suite_system_tpch_sqljs.ts │ ├── .prettierrc.js │ ├── types │ │ ├── wasm.d.ts │ │ ├── worker.d.ts │ │ └── web-worker.d.ts │ ├── .eslintrc.json │ ├── scripts │ │ └── tpch │ │ │ ├── 6.sql │ │ │ ├── 14.sql │ │ │ ├── 17.sql │ │ │ ├── 4.sql │ │ │ ├── 13.sql │ │ │ ├── 3.sql │ │ │ ├── 5.sql │ │ │ ├── 1.sql │ │ │ ├── 16.sql │ │ │ ├── 18.sql │ │ │ ├── 10.sql │ │ │ ├── 11.sql │ │ │ ├── 20.sql │ │ │ ├── 22-sqlite.sql │ │ │ ├── 21.sql │ │ │ ├── 9-sqlite.sql │ │ │ ├── 12.sql │ │ │ ├── 15.sql │ │ │ ├── 9.sql │ │ │ ├── 22.sql │ │ │ ├── 2.sql │ │ │ ├── 8-sqlite.sql │ │ │ ├── 19.sql │ │ │ ├── 8.sql │ │ │ ├── 7-sqlite.sql │ │ │ └── 7.sql │ └── tsconfig.json └── react-duckdb │ ├── src │ └── index.ts │ └── package.json ├── .gitattributes ├── misc ├── duckdb_wasm.png ├── duckdb_wasm.afdesign ├── duckdb_wasm_circle.png ├── duckdb_wasm_circle.afdesign ├── github_social_preview.png ├── duckdb.svg ├── duckdb_wasm.svg └── duckdb_wasm_light.svg ├── Cargo.toml ├── .prettierrc.js ├── patches ├── rapidjson │ └── cmake_minimum_required.patch ├── duckdb │ ├── preloaded_httpfs.patch │ ├── no_httpfs.patch │ ├── fix_config_size_t.patch │ ├── bind_copy_direct_io.patch │ └── fix_load_database.patch └── arrow │ └── hashing_compile_in_emscripten.patch ├── scripts ├── npm_publish_react.sh ├── npm_publish_shell.sh ├── npm_publish_lib.sh ├── reset_pages_subtree.sh ├── npm_measure_lib.sh ├── generate_uni.sh ├── npm_restore.sh ├── build_duckdb_badge.sh ├── build_loadable.sh ├── npm_version.sh ├── deploy_benchmarks.sh ├── format.sh ├── generate_tpch_duckdb.sh ├── generate_tpch_tbl.sh ├── sync_versions.mjs └── generate_benchmark_data.sh ├── .clang-format ├── docker-compose.yml ├── .github ├── ISSUE_TEMPLATE │ └── config.yml ├── dependabot.yml └── workflows │ └── npm_tags.yml ├── .gitignore ├── tsconfig.json ├── extension_config_wasm.cmake ├── package.json ├── LICENSE └── .gitmodules /actions/image/TAG: -------------------------------------------------------------------------------- 1 | 0.75 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | submodules 2 | dist -------------------------------------------------------------------------------- /lib/src/wasm_main.cc: -------------------------------------------------------------------------------- 1 | int main() {} 2 | -------------------------------------------------------------------------------- /tools/dataprep/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !vega 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /examples/bare-node/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/arrow_stream_factory.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/utils/format.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/error.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/test.csv: -------------------------------------------------------------------------------- 1 | "a","b","c" 2 | 1,2,3 3 | 4,5,6 4 | 7,8,9 5 | -------------------------------------------------------------------------------- /examples/esbuild-node/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /index.cjs 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # bash can't handle crlf line breaks 2 | *.sh text eol=lf 3 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/.gitignore: -------------------------------------------------------------------------------- 1 | /duckdb*.js 2 | /duckdb*.wasm 3 | -------------------------------------------------------------------------------- /examples/bare-browser/.gitignore: -------------------------------------------------------------------------------- 1 | /duckdb-browser* 2 | /*.wasm 3 | /node_modules 4 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | /.cache 2 | /.ccls-cache 3 | /build 4 | /compile_commands.json 5 | -------------------------------------------------------------------------------- /packages/benchmarks/.eslintignore: -------------------------------------------------------------------------------- 1 | *.cjs 2 | *.js 3 | *.mjs 4 | /karma/*.cjs 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/.eslintignore: -------------------------------------------------------------------------------- 1 | *.cjs 2 | *.js 3 | *.mjs 4 | /*.json 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/model/index.ts: -------------------------------------------------------------------------------- 1 | export * from './model_context'; 2 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/.eslintignore: -------------------------------------------------------------------------------- 1 | *.cjs 2 | *.js 3 | *.mjs 4 | /*.json 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/.eslintignore: -------------------------------------------------------------------------------- 1 | *.cjs 2 | *.js 3 | *.mjs 4 | /karma/*.cjs 5 | -------------------------------------------------------------------------------- /examples/esbuild-browser/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /*.wasm 3 | /*.js 4 | /*.js.map 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /crate/pkg 3 | /build 4 | /node_modules 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /crate/pkg 3 | /build 4 | /node_modules 5 | -------------------------------------------------------------------------------- /misc/duckdb_wasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/misc/duckdb_wasm.png -------------------------------------------------------------------------------- /examples/bare-browser/node_modules/.bin/http-server: -------------------------------------------------------------------------------- 1 | ../../../../node_modules/http-server/bin/http-server -------------------------------------------------------------------------------- /packages/benchmarks/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /duckdb_webapi.* 3 | /dist 4 | *.d.ts.map 5 | 6 | -------------------------------------------------------------------------------- /packages/benchmarks/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './format'; 2 | export * from './shuffle'; 3 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/sugar/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod builder; 2 | pub mod constructor; 3 | -------------------------------------------------------------------------------- /data/test.json: -------------------------------------------------------------------------------- 1 | {"a": 1, "b": 2.0, "c": "foo", "d": false} 2 | {"a": 4, "b": -5.5, "c": null, "d": true} 3 | -------------------------------------------------------------------------------- /misc/duckdb_wasm.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/misc/duckdb_wasm.afdesign -------------------------------------------------------------------------------- /misc/duckdb_wasm_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/misc/duckdb_wasm_circle.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/test/index.ts: -------------------------------------------------------------------------------- 1 | import { testShell } from './shell.test'; 2 | 3 | testShell(); 4 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "failFast": true, 3 | "timeoutInterval": 900000 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './binary_dump'; 2 | export * from './s3_helper'; 3 | -------------------------------------------------------------------------------- /packages/benchmarks/.prettierrc.js: -------------------------------------------------------------------------------- 1 | const base = require('../../.prettierrc.js'); 2 | module.exports = base; 3 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/.prettierrc.js: -------------------------------------------------------------------------------- 1 | const base = require('../../.prettierrc.js'); 2 | module.exports = base; 3 | -------------------------------------------------------------------------------- /misc/duckdb_wasm_circle.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/misc/duckdb_wasm_circle.afdesign -------------------------------------------------------------------------------- /misc/github_social_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/misc/github_social_preview.png -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "tools/dataprep", 5 | "packages/duckdb-wasm-shell/crate", 6 | ] 7 | -------------------------------------------------------------------------------- /packages/benchmarks/types/wasm.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.wasm' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/types/wasm.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.wasm' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/crate.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*crate' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/csv.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.csv' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/html.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.html' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/png.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/sql.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.sql' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/svg.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/tbl.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.tbl' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/wasm.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.wasm' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /lib/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | ColumnLimit: 120 3 | IndentWidth: 4 4 | AlwaysBreakTemplateDeclarations: MultiLine 5 | 6 | -------------------------------------------------------------------------------- /packages/benchmarks/types/worker.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.worker.js' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/parquet.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.parquet' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/worker.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.worker.js' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './version'; 2 | export * from './shell'; 3 | export { getJsDelivrModule } from './platform'; 4 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/favicon.ico -------------------------------------------------------------------------------- /packages/benchmarks/src/internal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './format_benchmark'; 2 | export * from './iterator_benchmark'; 3 | export * from './udf_benchmark'; 4 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/fonts/Nunito-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/fonts/Nunito-Bold.ttf -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/fonts/Nunito-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/fonts/Nunito-Light.ttf -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/fonts/Nunito-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/fonts/Nunito-Regular.ttf -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/fonts/Nunito-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/fonts/Nunito-SemiBold.ttf -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/comfy/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod arrangement; 2 | pub mod borders; 3 | mod column_display_info; 4 | pub mod format; 5 | mod split; 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod keys; 2 | pub use keys::*; 3 | pub mod xterm; 4 | pub use xterm::*; 5 | pub mod addons; 6 | pub mod sugar; 7 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/sharingduckdb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/sharingduckdb.jpg -------------------------------------------------------------------------------- /packages/duckdb-wasm/.gitignore: -------------------------------------------------------------------------------- 1 | /*.parquet 2 | /*.csv 3 | /.nyc_output 4 | /coverage 5 | /node_modules 6 | /duckdb_webapi.* 7 | /dist 8 | /docs 9 | *.d.ts.map 10 | -------------------------------------------------------------------------------- /examples/esbuild-browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: { [className: string]: string }; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/types/editor-worker.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'monaco-editor/esm/vs/editor/editor.worker.js' { 2 | const content: any; 3 | export = content; 4 | } 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/android-chrome-384x384.png -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckdb/duckdb-wasm/HEAD/packages/duckdb-wasm-app/static/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /packages/react-duckdb/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './connection_provider'; 2 | export * from './database_provider'; 3 | export * from './platform_provider'; 4 | export * from './resolvable'; 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/docs.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | position: relative; 3 | height: 100%; 4 | width: 100%; 5 | box-sizing: border-box; 6 | overflow: hidden; 7 | } 8 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/duckdb-coi.pthread.d.ts: -------------------------------------------------------------------------------- 1 | export const alert: any; 2 | export const onmessage: any; 3 | export function getModule(): any; 4 | export function setModule(m: any): void; 5 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "trailingComma": "all", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "arrowParens": "avoid", 7 | "printWidth": 120 8 | } 9 | -------------------------------------------------------------------------------- /packages/benchmarks/types/web-worker.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'web-worker' { 2 | type ConstructorOf = { new (...args: any[]): C }; 3 | const _default: ConstructorOf; 4 | export default _default; 5 | } 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/duckdb-coi.d.ts: -------------------------------------------------------------------------------- 1 | import { DuckDBModule } from './duckdb_module'; 2 | export function DuckDB(moduleOverrides?: Partial): Promise; 3 | export default DuckDB; 4 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/duckdb-eh.d.ts: -------------------------------------------------------------------------------- 1 | import { DuckDBModule } from './duckdb_module'; 2 | export function DuckDB(moduleOverrides?: Partial): Promise; 3 | export default DuckDB; 4 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/duckdb-mvp.d.ts: -------------------------------------------------------------------------------- 1 | import { DuckDBModule } from './duckdb_module'; 2 | export function DuckDB(moduleOverrides?: Partial): Promise; 3 | export default DuckDB; 4 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/types/web-worker.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'web-worker' { 2 | type ConstructorOf = { new (...args: any[]): C }; 3 | const _default: ConstructorOf; 4 | export default _default; 5 | } 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod attach; 2 | pub mod fit; 3 | pub mod ligatures; 4 | pub mod search; 5 | pub mod serialize; 6 | pub mod unicode11; 7 | pub mod web_links; 8 | pub mod webgl; 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/karma/tests-debug.cjs: -------------------------------------------------------------------------------- 1 | const base = require('./karma.base.cjs'); 2 | 3 | module.exports = function (config) { 4 | config.set({ ...base(config), singleRun: false, reporters: ['kjhtml'], browsers: [] }); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/karma/tests-firefox.cjs: -------------------------------------------------------------------------------- 1 | const base = require('./karma.base.cjs'); 2 | 3 | module.exports = function (config) { 4 | config.set({ ...base(config), browsers: ['FirefoxHeadless'], reporters: ['spec'] }); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/benchmarks/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.base.json"], 3 | "parserOptions": { 4 | "project": "./tsconfig.json", 5 | "ecmaVersion": 2020, 6 | "sourceType": "module" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.base.json"], 3 | "parserOptions": { 4 | "project": "./tsconfig.json", 5 | "ecmaVersion": 2020, 6 | "sourceType": "module" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.base.json"], 3 | "parserOptions": { 4 | "project": "./tsconfig.json", 5 | "ecmaVersion": 2020, 6 | "sourceType": "module" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.base.json"], 3 | "parserOptions": { 4 | "project": "./tsconfig.json", 5 | "ecmaVersion": 2020, 6 | "sourceType": "module" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './bindings'; 2 | export * from './log'; 3 | export * from './parallel'; 4 | export * from './status'; 5 | export * from './platform'; 6 | export * from './version'; 7 | export * from './worker'; 8 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/parallel/index.ts: -------------------------------------------------------------------------------- 1 | export * from './async_connection'; 2 | export * from './async_bindings_interface'; 3 | export * from './async_bindings'; 4 | export * from './worker_dispatcher'; 5 | export * from './worker_request'; 6 | -------------------------------------------------------------------------------- /lib/src/extensions/json_extension.cc: -------------------------------------------------------------------------------- 1 | #include "duckdb/web/extensions/json_extension.h" 2 | 3 | #include "json_extension.hpp" 4 | 5 | extern "C" void duckdb_web_json_init(duckdb::DuckDB* db) { db->LoadStaticExtension(); } 6 | -------------------------------------------------------------------------------- /packages/benchmarks/src/system/index.ts: -------------------------------------------------------------------------------- 1 | export * from './arquero_benchmarks'; 2 | export * from './lovefield_benchmarks'; 3 | export * from './sqljs_benchmarks'; 4 | export * from './system_benchmark'; 5 | export * from './duckdb_sync_benchmarks'; 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/src/extensions/parquet_extension.cc: -------------------------------------------------------------------------------- 1 | #include "duckdb/web/extensions/parquet_extension.h" 2 | 3 | #include "parquet_extension.hpp" 4 | 5 | extern "C" void duckdb_web_parquet_init(duckdb::DuckDB* db) { db->LoadStaticExtension(); } 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/duckdb/mod.rs: -------------------------------------------------------------------------------- 1 | mod async_duckdb; 2 | 3 | pub mod file_stats; 4 | pub mod tokens; 5 | mod version; 6 | mod web_file; 7 | 8 | pub use async_duckdb::*; 9 | pub use file_stats::*; 10 | pub use version::*; 11 | pub use web_file::*; 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/warn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/extensions/json_extension.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_EXTENSIONS_JSON_EXTENSION_H_ 2 | #define INCLUDE_DUCKDB_WEB_EXTENSIONS_JSON_EXTENSION_H_ 3 | 4 | #include "duckdb/main/database.hpp" 5 | 6 | extern "C" void duckdb_web_json_init(duckdb::DuckDB* db); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/model/model_context.ts: -------------------------------------------------------------------------------- 1 | export type Action = { 2 | readonly type: T; 3 | readonly data: P; 4 | }; 5 | 6 | export type Dispatch = (action: ActionVariant) => void; 7 | 8 | export type ProviderProps = { children: React.ReactElement }; 9 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/6.sql: -------------------------------------------------------------------------------- 1 | select 2 | sum(l_extendedprice * l_discount) as revenue 3 | from 4 | lineitem 5 | where 6 | l_shipdate >= '1994-01-01' 7 | and l_shipdate < '1995-01-01' 8 | and l_discount between 0.05 9 | and 0.07 10 | and l_quantity < 24; 11 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/comfy/mod.rs: -------------------------------------------------------------------------------- 1 | mod cell; 2 | mod column; 3 | mod row; 4 | mod style; 5 | mod table; 6 | mod utils; 7 | 8 | pub use cell::{Cell, Cells}; 9 | pub use column::Column; 10 | pub use row::Row; 11 | pub use style::*; 12 | pub use table::{ColumnCellIter, Table}; 13 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/extensions/parquet_extension.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_EXTENSIONS_PARQUET_EXTENSION_H_ 2 | #define INCLUDE_DUCKDB_WEB_EXTENSIONS_PARQUET_EXTENSION_H_ 3 | 4 | #include "duckdb/main/database.hpp" 5 | 6 | extern "C" void duckdb_web_parquet_init(duckdb::DuckDB* db); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/utils/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_THREAD_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_THREAD_H_ 3 | 4 | #include 5 | 6 | namespace duckdb { 7 | namespace web { 8 | 9 | uint32_t GetThreadID(); 10 | 11 | } 12 | } // namespace duckdb 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/view-list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/karma/tests-all.cjs: -------------------------------------------------------------------------------- 1 | const base = require('./karma.base.cjs'); 2 | 3 | module.exports = function (config) { 4 | config.set({ 5 | ...base(config), 6 | browsers: ['FirefoxHeadless', 'ChromeHeadlessNoSandbox'], 7 | reporters: ['spec'], 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /examples/esbuild-node/bundle.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | 3 | esbuild.build({ 4 | entryPoints: ['./index.ts'], 5 | outfile: 'index.mjs', 6 | platform: 'node', 7 | format: 'esm', 8 | target: 'esnext', 9 | bundle: false, 10 | minify: false, 11 | sourcemap: false, 12 | }); 13 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/test/shell.test.ts: -------------------------------------------------------------------------------- 1 | export function testShell(): void { 2 | beforeAll(async () => {}); 3 | 4 | beforeEach(async () => {}); 5 | 6 | describe('Parser', () => { 7 | it('syntax error', async () => { 8 | expect(1).toEqual(1); 9 | }); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/minus-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/tray_full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/index_docs.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from './targets/duckdb'; 2 | import * as blocking_browser from './targets/duckdb-browser-blocking'; 3 | import * as blocking_node from './targets/duckdb-node-blocking'; 4 | 5 | exports = { 6 | duckdb, 7 | blocking_browser, 8 | blocking_node, 9 | }; 10 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/src/platform.ts: -------------------------------------------------------------------------------- 1 | import { PACKAGE_NAME, PACKAGE_VERSION } from './version'; 2 | 3 | export function getJsDelivrModule(): URL { 4 | const jsdelivr_dist_url = `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@${PACKAGE_VERSION}/dist/`; 5 | return new URL(`${jsdelivr_dist_url}dist/shell_bg.wasm`); 6 | } 7 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/delete-outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/tokens.ts: -------------------------------------------------------------------------------- 1 | export enum TokenType { 2 | IDENTIFIER = 0, 3 | NUMERIC_CONSTANT = 1, 4 | STRING_CONSTANT = 2, 5 | OPERATOR = 3, 6 | KEYWORD = 4, 7 | COMMENT = 5, 8 | } 9 | 10 | export interface ScriptTokens { 11 | offsets: number[]; 12 | types: TokenType[]; 13 | } 14 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/worker.ts: -------------------------------------------------------------------------------- 1 | import Worker from 'web-worker'; 2 | 3 | export async function createWorker(url: string) { 4 | const request = new Request(url); 5 | const workerScript = await fetch(request); 6 | const workerURL = URL.createObjectURL(await workerScript.blob()); 7 | return new Worker(workerURL); 8 | } 9 | -------------------------------------------------------------------------------- /examples/esbuild-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2020", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "skipLibCheck": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #000000 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/esbuild-browser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2020", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "skipLibCheck": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/monitor.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/file-document-outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/table.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/file-chart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/cloud.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/shell.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/progress.ts: -------------------------------------------------------------------------------- 1 | /** An instantiation progress */ 2 | export interface InstantiationProgress { 3 | startedAt: Date; 4 | updatedAt: Date; 5 | bytesTotal: number; 6 | bytesLoaded: number; 7 | } 8 | 9 | /** An instantiation progress handler */ 10 | export type InstantiationProgressHandler = (p: InstantiationProgress) => void; 11 | -------------------------------------------------------------------------------- /misc/duckdb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/bare-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@duckdb/duckdb-wasm-examples-bare-node", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@duckdb/duckdb-wasm": "file:../../packages/duckdb-wasm" 9 | }, 10 | "scripts": { 11 | "test": "node ./index.cjs" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /patches/rapidjson/cmake_minimum_required.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index dd1f173..2351bad 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -1,4 +1,4 @@ 6 | -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) 7 | +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12...3.29) 8 | if(POLICY CMP0025) 9 | # detect Apple's Clang 10 | cmake_policy(SET CMP0025 NEW) 11 | -------------------------------------------------------------------------------- /examples/esbuild-browser/serve.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": [ 3 | { 4 | "source": "*", 5 | "headers": [ 6 | { 7 | "key": "Cross-Origin-Embedder-Policy", 8 | "value": "require-corp" 9 | }, 10 | { 11 | "key": "Cross-Origin-Opener-Policy", 12 | "value": "same-origin" 13 | } 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/utils/binary_dump.ts: -------------------------------------------------------------------------------- 1 | export function dumpBuffer(src: Uint8Array): string { 2 | return [...src] 3 | .map(x => (x >= 32 && x <= 127 ? String.fromCharCode(x) : '.')) 4 | .reduce((acc: string, value: string, index: number) => { 5 | if (index % 20 == 0) acc += '\n'; 6 | acc += value; 7 | return acc; 8 | }, ''); 9 | } 10 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/version.ts: -------------------------------------------------------------------------------- 1 | import config from '../package.json'; 2 | 3 | export const PACKAGE_NAME = config.name; 4 | export const PACKAGE_VERSION = config.version; 5 | 6 | const VERSION_PARTS = config.version.split('.'); 7 | export const PACKAGE_VERSION_MAJOR = VERSION_PARTS[0]; 8 | export const PACKAGE_VERSION_MINOR = VERSION_PARTS[1]; 9 | export const PACKAGE_VERSION_PATCH = VERSION_PARTS[2]; 10 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/file-table.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/utils/opfs_util.ts: -------------------------------------------------------------------------------- 1 | export const REGEX_OPFS_FILE = /'(opfs:\/\/\S*?)'/g; 2 | export const REGEX_OPFS_PROTOCOL = /(opfs:\/\/\S*?)/g; 3 | 4 | export function isOPFSProtocol(path: string): boolean { 5 | return path.search(REGEX_OPFS_PROTOCOL) > -1; 6 | } 7 | 8 | export function searchOPFSFiles(text: string) { 9 | return [...text.matchAll(REGEX_OPFS_FILE)].map(match => match[1]); 10 | } -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/src/version.ts: -------------------------------------------------------------------------------- 1 | import config from '../package.json'; 2 | 3 | export const PACKAGE_NAME = config.name; 4 | export const PACKAGE_VERSION = config.version; 5 | 6 | const VERSION_PARTS = config.version.split('.'); 7 | export const PACKAGE_VERSION_MAJOR = VERSION_PARTS[0]; 8 | export const PACKAGE_VERSION_MINOR = VERSION_PARTS[1]; 9 | export const PACKAGE_VERSION_PATCH = VERSION_PARTS[2]; 10 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/index.ts: -------------------------------------------------------------------------------- 1 | export * from './bindings_interface'; 2 | export * from './bindings_base'; 3 | export * from './config'; 4 | export * from './connection'; 5 | export * from './duckdb_module'; 6 | export * from './file_stats'; 7 | export * from './runtime'; 8 | export * from './insert_options'; 9 | export * from './progress'; 10 | export * from './tokens'; 11 | export * from './web_file'; 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/status.ts: -------------------------------------------------------------------------------- 1 | export enum StatusCode { 2 | SUCCESS = 0, 3 | MAX_ARROW_ERROR = 255, 4 | DUCKDB_WASM_RETRY = 256, 5 | } 6 | 7 | export function IsArrowBuffer(status: StatusCode): boolean { 8 | return status <= StatusCode.MAX_ARROW_ERROR; 9 | } 10 | 11 | export function IsDuckDBWasmRetry(status: StatusCode): boolean { 12 | return status === StatusCode.DUCKDB_WASM_RETRY; 13 | } 14 | -------------------------------------------------------------------------------- /packages/benchmarks/src/utils/shuffle.ts: -------------------------------------------------------------------------------- 1 | export function shuffle(array: T[]): T[] { 2 | let currentIndex = array.length, 3 | randomIndex; 4 | while (currentIndex != 0) { 5 | randomIndex = Math.floor(Math.random() * currentIndex); 6 | currentIndex--; 7 | [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]]; 8 | } 9 | return array; 10 | } 11 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/shell.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | position: relative; 3 | height: 100%; 4 | width: 100%; 5 | box-sizing: border-box; 6 | } 7 | 8 | .resizer { 9 | position: absolute; 10 | top: 0; 11 | left: 0; 12 | right: 0; 13 | bottom: 0; 14 | width: 100%; 15 | height: 100%; 16 | } 17 | 18 | .term_container { 19 | width: 100%; 20 | height: 100%; 21 | } 22 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/duckdb_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/file-table-box.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/comfy/style/modifiers.rs: -------------------------------------------------------------------------------- 1 | /// A modifier, that when applied will convert the outer corners to round corners. 2 | /// ```text 3 | /// ╭───────┬───────╮ 4 | /// │ Hello │ there │ 5 | /// ╞═══════╪═══════╡ 6 | /// │ a ┆ b │ 7 | /// ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤ 8 | /// │ c ┆ d │ 9 | /// ╰───────┴───────╯ 10 | /// ``` 11 | pub const UTF8_ROUND_CORNERS: &str = " ╭╮╰╯"; 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb.ts: -------------------------------------------------------------------------------- 1 | export * from '../bindings/config'; 2 | export * from '../bindings/tokens'; 3 | export * from '../log'; 4 | export * from '../status'; 5 | export * from '../parallel'; 6 | export * from '../platform'; 7 | export * from '../version'; 8 | export * from '../worker'; 9 | 10 | export { InstantiationProgress, InstantiationProgressHandler, DuckDBDataProtocol, WebFile } from '../bindings'; 11 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DuckDB-WASM", 3 | "entryPoints": [ 4 | "src/index.ts", 5 | "src/targets/duckdb.ts", 6 | "src/targets/duckdb-browser-blocking.ts", 7 | "src/targets/duckdb-node-blocking.ts" 8 | ], 9 | "readme": "none", 10 | "out": "docs", 11 | "includeVersion": false, 12 | "excludeProtected": true, 13 | "theme": "default" 14 | } 15 | -------------------------------------------------------------------------------- /tools/dataprep/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dataprep" 3 | version = "0.1.0" 4 | authors = ["Andre Kohn "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | chrono = { version = "0.4.19", features = ["serde"] } 9 | serde = { version = "1.0.130", features = ["derive"] } 10 | serde_json = "1.0" 11 | parquet = "13.0.0" 12 | arrow = { version = "13.0.0", features = ["csv", "ipc"] } 13 | clap = "3.0.0-beta.2" 14 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/karma/tests-chrome.cjs: -------------------------------------------------------------------------------- 1 | const base = require('./karma.base.cjs'); 2 | 3 | if (process.env.CHROME_BIN === 'undefined') { 4 | process.env.CHROME_BIN = require('puppeteer').executablePath(); 5 | } 6 | console.log(`CHROME_BIN=${process.env.CHROME_BIN}`); 7 | 8 | module.exports = function (config) { 9 | config.set({ ...base(config), browsers: ['ChromeHeadlessNoSandbox'], reporters: ['spec'] }); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/web_file.ts: -------------------------------------------------------------------------------- 1 | import { DuckDBDataProtocol } from './runtime'; 2 | 3 | export interface WebFile { 4 | fileName: string; 5 | dataProtocol: DuckDBDataProtocol; 6 | fileId?: number; 7 | fileSize?: number; 8 | dataUrl?: string; 9 | dataNativeFd?: number; 10 | collectStatistics?: boolean; 11 | reliableHeadRequests?: boolean; 12 | allowFullHttpReads?: boolean; 13 | } 14 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/14.sql: -------------------------------------------------------------------------------- 1 | select 2 | 100.00 * sum( 3 | case 4 | when p_type like 'PROMO%' then l_extendedprice * (1 - l_discount) 5 | else 0 6 | end 7 | ) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue 8 | from 9 | lineitem, 10 | part 11 | where 12 | l_partkey = p_partkey 13 | and l_shipdate >= '1995-09-01' 14 | and l_shipdate < '1995-10-01' 15 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/karma/tests-chrome-coverage.cjs: -------------------------------------------------------------------------------- 1 | const base = require('./karma.base.cjs'); 2 | 3 | if (process.env.CHROME_BIN === 'undefined') { 4 | process.env.CHROME_BIN = require('puppeteer').executablePath(); 5 | } 6 | console.log(`CHROME_BIN=${process.env.CHROME_BIN}`); 7 | 8 | module.exports = function (config) { 9 | config.set({ ...base(config), browsers: ['ChromeHeadlessNoSandbox'], reporters: ['coverage'] }); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/17.sql: -------------------------------------------------------------------------------- 1 | select 2 | sum(l_extendedprice) / 7.0 as avg_yearly 3 | from 4 | lineitem, 5 | part 6 | where 7 | p_partkey = l_partkey 8 | and p_brand = 'Brand#23' 9 | and p_container = 'MED BOX' 10 | and l_quantity < ( 11 | select 12 | 0.2 * avg(l_quantity) 13 | from 14 | lineitem 15 | where 16 | l_partkey = p_partkey 17 | ); 18 | -------------------------------------------------------------------------------- /scripts/npm_publish_react.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | 5 | cd ${PROJECT_ROOT}/packages/react-duckdb 6 | mkdir -p ./dist/img 7 | cp ${PROJECT_ROOT}/misc/duckdb_wasm.svg ./dist/img/duckdb_wasm.svg 8 | ${PROJECT_ROOT}/scripts/build_duckdb_badge.sh > ./dist/img/duckdb_version_badge.svg 9 | 10 | npm login 11 | npm publish --ignore-scripts --access public --tag ${TAG} 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/components/minibar_chart.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | 7 | .bar { 8 | flex: 1; 9 | height: 6px; 10 | border-radius: 3px; 11 | background: hsla(56, 100%, 30%, 0.4); 12 | overflow: hidden; 13 | } 14 | 15 | .bar_fill { 16 | height: 100%; 17 | background: hsl(56, 100%, 30%); 18 | border-radius: 3px; 19 | } 20 | -------------------------------------------------------------------------------- /scripts/npm_publish_shell.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | 5 | cd ${PROJECT_ROOT}/packages/duckdb-wasm-shell 6 | mkdir -p ./dist/img 7 | cp ${PROJECT_ROOT}/misc/duckdb_wasm.svg ./dist/img/duckdb_wasm.svg 8 | ${PROJECT_ROOT}/scripts/build_duckdb_badge.sh > ./dist/img/duckdb_version_badge.svg 9 | 10 | npm login 11 | npm publish --ignore-scripts --access public --tag ${TAG} 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/blog.module.css: -------------------------------------------------------------------------------- 1 | .section_container { 2 | width: 100%; 3 | padding: 8px; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | 9 | @media only screen and (min-width: 600px) { 10 | .section { 11 | width: 90%; 12 | max-width: 800px; 13 | } 14 | } 15 | @media only screen and (max-width: 600px) { 16 | .section { 17 | width: 100%; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/logo/duckdb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/io/file_page_defaults.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_IO_FILE_PAGE_DEFAULTS_H 2 | #define INCLUDE_DUCKDB_WEB_IO_FILE_PAGE_DEFAULTS_H 3 | 4 | #include 5 | 6 | namespace duckdb { 7 | namespace web { 8 | namespace io { 9 | 10 | constexpr size_t DEFAULT_FILE_PAGE_CAPACITY = 10000; 11 | constexpr size_t DEFAULT_FILE_PAGE_SHIFT = 14; // 16KB pages 12 | 13 | } // namespace io 14 | } // namespace web 15 | } // namespace duckdb 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/components/page_structure.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './page_structure.module.css'; 3 | 4 | interface PageSectionProps { 5 | children: React.ReactChild | React.ReactChild[]; 6 | } 7 | 8 | export const PageSection: React.FC = (props: PageSectionProps) => ( 9 |
10 |
{props.children}
11 |
12 | ); 13 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/timer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/udf_function.ts: -------------------------------------------------------------------------------- 1 | import { SQLType } from '../json_typedef'; 2 | import * as arrow from 'apache-arrow'; 3 | 4 | export interface UDFFunctionDeclaration { 5 | functionId: number; 6 | name: string; 7 | returnType: SQLType; 8 | } 9 | 10 | export interface UDFFunction { 11 | functionId: number; 12 | connectionId: number; 13 | name: string; 14 | returnType: arrow.DataType; 15 | func: (...args: any[]) => any; 16 | } 17 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 4 3 | ColumnLimit: 200 4 | AllowShortFunctionsOnASingleLine: Empty 5 | IndentCaseLabels: true 6 | NamespaceIndentation: All 7 | IncludeCategories: 8 | - Regex: '<.*>' 9 | Priority: -1 10 | - Regex: '.*' 11 | Priority: 0 12 | DerivePointerAlignment: false 13 | PointerAlignment: Left 14 | AllowAllArgumentsOnNextLine: true 15 | SpaceAfterTemplateKeyword: false 16 | SpaceBeforeCtorInitializerColon: false -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.0" 2 | services: 3 | duckdb-wasm-ci: 4 | image: duckdb/wasm-ci:0.75 5 | build: 6 | context: ./actions/image 7 | args: 8 | - GID=0 9 | - UID=0 10 | volumes: 11 | - .:/wd 12 | - ./.ccache:/mnt/ccache 13 | - ./.emscripten_cache:/mnt/emscripten_cache 14 | environment: 15 | - CCACHE_BASEDIR=/wd/lib 16 | - CCACHE_DIR=/mnt/ccache 17 | - EM_CACHE=/mnt/emscripten_cache/ 18 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/components/page_structure.module.css: -------------------------------------------------------------------------------- 1 | .section_container { 2 | width: 100%; 3 | padding: 16px 8px 8px 8px; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | 9 | @media only screen and (min-width: 600px) { 10 | .section { 11 | width: 90%; 12 | max-width: 800px; 13 | } 14 | } 15 | @media only screen and (max-width: 600px) { 16 | .section { 17 | width: 100%; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /patches/duckdb/preloaded_httpfs.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/include/duckdb/main/database.hpp b/src/include/duckdb/main/database.hpp 2 | index d3c5fb9bd5..adc2ac42e6 100644 3 | --- a/src/include/duckdb/main/database.hpp 4 | +++ b/src/include/duckdb/main/database.hpp 5 | @@ -17,6 +17,9 @@ 6 | #include "duckdb/main/valid_checker.hpp" 7 | 8 | namespace duckdb { 9 | + 10 | +extern bool preloaded_httpfs; 11 | + 12 | class BufferManager; 13 | class DatabaseManager; 14 | class StorageManager; 15 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/pivot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/duckdb_module.ts: -------------------------------------------------------------------------------- 1 | export interface PThread { 2 | unusedWorkers: Worker[]; 3 | runningWorkers: Worker[]; 4 | } 5 | 6 | export interface DuckDBModule extends EmscriptenModule { 7 | stackSave: typeof stackSave; 8 | stackAlloc: typeof stackAlloc; 9 | stackRestore: typeof stackRestore; 10 | lengthBytesUTF8: typeof lengthBytesUTF8; 11 | stringToUTF8: typeof stringToUTF8; 12 | 13 | ccall: typeof ccall; 14 | PThread: PThread; 15 | } 16 | -------------------------------------------------------------------------------- /scripts/npm_publish_lib.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | 5 | cd ${PROJECT_ROOT}/packages/duckdb-wasm 6 | mkdir -p ./dist/img 7 | cp ${PROJECT_ROOT}/misc/duckdb.svg ./dist/img/duckdb.svg 8 | cp ${PROJECT_ROOT}/misc/duckdb_wasm.svg ./dist/img/duckdb_wasm.svg 9 | ${PROJECT_ROOT}/scripts/build_duckdb_badge.sh > ./dist/img/duckdb_version_badge.svg 10 | 11 | npm publish --ignore-scripts --access public --tag ${TAG} 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/docs.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as duckdb from '@duckdb/duckdb-wasm'; 3 | import styles from './docs.module.css'; 4 | 5 | export const Docs = (): React.ReactElement => ( 6 |
`, 10 | }} 11 | /> 12 | ); 13 | 14 | export default Docs; 15 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/data-matrix.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /patches/arrow/hashing_compile_in_emscripten.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cpp/src/arrow/util/hashing.h b/cpp/src/arrow/util/hashing.h 2 | index 2de9f41532..1a7803d2d8 100644 3 | --- a/cpp/src/arrow/util/hashing.h 4 | +++ b/cpp/src/arrow/util/hashing.h 5 | @@ -31,6 +31,10 @@ 6 | #include 7 | #include 8 | 9 | +#ifdef EMSCRIPTEN 10 | +#include 11 | +#endif 12 | + 13 | #include "arrow/array/builder_binary.h" 14 | #include "arrow/buffer_builder.h" 15 | #include "arrow/result.h" 16 | -------------------------------------------------------------------------------- /examples/bare-browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@duckdb/duckdb-wasm-examples-bare-browser", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@duckdb/duckdb-wasm": "file:../../packages/duckdb-wasm" 9 | }, 10 | "devDependencies": { 11 | "http-server": "^14.1.1" 12 | }, 13 | "scripts": { 14 | "build": "node ./bundle.mjs", 15 | "server": "http-server" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/test/config.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_TEST_CONFIG_H_ 2 | #define INCLUDE_DUCKDB_WEB_TEST_CONFIG_H_ 3 | 4 | #include 5 | 6 | #include "duckdb.hpp" 7 | 8 | namespace duckdb { 9 | namespace web { 10 | namespace test { 11 | 12 | extern std::filesystem::path SOURCE_DIR; 13 | 14 | bool CHECK_COLUMN(MaterializedQueryResult &result, uint32_t column, vector values); 15 | 16 | } // namespace test 17 | } // namespace web 18 | } // namespace duckdb 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/4.sql: -------------------------------------------------------------------------------- 1 | select 2 | o_orderpriority, 3 | count(*) as order_count 4 | from 5 | orders 6 | where 7 | o_orderdate >= '1993-07-01' 8 | and o_orderdate < '1993-10-01' 9 | and exists ( 10 | select 11 | * 12 | from 13 | lineitem 14 | where 15 | l_orderkey = o_orderkey 16 | and l_commitdate < l_receiptdate 17 | ) 18 | group by 19 | o_orderpriority 20 | order by 21 | o_orderpriority; 22 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/environment.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_ENVIRONMENT_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_ENVIRONMENT_H_ 3 | 4 | namespace duckdb { 5 | namespace web { 6 | 7 | enum class Environment { WEB, NATIVE }; 8 | 9 | #if EMSCRIPTEN 10 | constexpr auto ENVIRONMENT = Environment::WEB; 11 | #else 12 | constexpr auto ENVIRONMENT = Environment::NATIVE; 13 | #endif 14 | 15 | enum NativeTag { NATIVE }; 16 | enum WebTag { WEB }; 17 | 18 | } // namespace web 19 | } // namespace duckdb 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature Request 4 | # manual template until discussion templates are GA 5 | url: https://github.com/duckdb/duckdb-wasm/discussions/new?category=ideas&title=Feature%20Request:%20...&labels=feature&body=Why%20do%20you%20want%20this%20feature%3F 6 | about: Submit feature requests here 7 | - name: Discussions 8 | url: https://github.com/duckdb/duckdb/discussions 9 | about: Please ask and answer general questions here. 10 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/server.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | /.deploy 3 | /perf.data* 4 | /.cache 5 | /.pages 6 | /worktrees 7 | /.cache 8 | /.ccache 9 | .tmp 10 | /.flatc 11 | /.testfile* 12 | /artifacts 13 | /reports 14 | /packages/reports 15 | /build 16 | /.ccls-cache 17 | /.emscripten_cache 18 | .DS_Store 19 | compile_commands.json 20 | 21 | /target 22 | 23 | # Miscellaneous 24 | .DS_Store 25 | /node_modules 26 | .vscode 27 | !.vscode/settings.json 28 | data/tpch/**/*.parquet 29 | .idea 30 | lib/.idea 31 | 32 | check_duckdb 33 | wasm_setup 34 | loadable_extensions 35 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/13.sql: -------------------------------------------------------------------------------- 1 | select 2 | c_count, 3 | count(*) as custdist 4 | from 5 | ( 6 | select 7 | c_custkey, 8 | count(o_orderkey) as c_count 9 | from 10 | customer 11 | left outer join orders on c_custkey = o_custkey 12 | and o_comment not like '%special%requests%' 13 | group by 14 | c_custkey 15 | ) as c_orders 16 | group by 17 | c_count 18 | order by 19 | custdist desc, 20 | c_count desc; 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "es2020", 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "sourceMap": false, 8 | "noImplicitAny": true, 9 | "esModuleInterop": true, 10 | "downlevelIteration": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "jsx": "react", 14 | 15 | "types": ["emscripten", "node", "jasmine"], 16 | "lib": ["es6", "webworker", "dom"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scripts/reset_pages_subtree.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | 5 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 6 | PAGES_DIR=${PROJECT_ROOT}/worktrees/gh-pages 7 | 8 | mkdir -p ${PROJECT_ROOT}/worktrees 9 | if [ ! -d ${PAGES_DIR} ]; then 10 | echo "[ RUN ] Add worktree origin/gh-pages" 11 | git worktree add ${PAGES_DIR} origin/gh-pages 12 | fi 13 | 14 | DEFAULT_BRANCH="main" 15 | CURRENT_BRANCH=${1:-main} 16 | 17 | cd ${PAGES_DIR} 18 | git fetch origin gh-pages 19 | git reset --hard origin/gh-pages 20 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /extension_config_wasm.cmake: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # DuckDB-Wasm extension base config 3 | ################################################################################ 4 | # 5 | 6 | duckdb_extension_load(json DONT_LINK) 7 | duckdb_extension_load(parquet DONT_LINK) 8 | duckdb_extension_load(autocomplete DONT_LINK) 9 | 10 | duckdb_extension_load(icu DONT_LINK) 11 | duckdb_extension_load(tpcds DONT_LINK) 12 | duckdb_extension_load(tpch DONT_LINK) 13 | 14 | #duckdb_extension_load(httpfs DONT_LINK) 15 | -------------------------------------------------------------------------------- /lib/src/utils/thread.cc: -------------------------------------------------------------------------------- 1 | #include "duckdb/web/utils/thread.h" 2 | 3 | #include 4 | 5 | namespace duckdb { 6 | namespace web { 7 | 8 | #if !EMSCRIPTEN || WEBDB_THREADS 9 | uint32_t GetThreadID() { 10 | static std::atomic NEXT_THREAD_ID = 1; 11 | static thread_local uint32_t THREAD_ID = 0; 12 | if (THREAD_ID == 0) { 13 | THREAD_ID = NEXT_THREAD_ID++; 14 | } 15 | return THREAD_ID - 1; 16 | }; 17 | #else 18 | uint32_t GetThreadID() { return 0; } 19 | #endif 20 | 21 | } // namespace web 22 | } // namespace duckdb 23 | -------------------------------------------------------------------------------- /tools/dataprep/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt; 3 | 4 | #[derive(Debug)] 5 | pub struct Error { 6 | message: String, 7 | } 8 | 9 | impl Error { 10 | pub fn new(msg: String) -> Box { 11 | Box::new(Self { message: msg }) 12 | } 13 | } 14 | 15 | impl fmt::Display for Error { 16 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 17 | write!(f, "{}", self.message) 18 | } 19 | } 20 | 21 | impl error::Error for Error { 22 | fn description(&self) -> &str { 23 | &self.message 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/data-matrix-scan.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /patches/duckdb/no_httpfs.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/main/database.cpp b/src/main/database.cpp 2 | index db6e1ed445..17f845c75e 100644 3 | --- a/src/main/database.cpp 4 | +++ b/src/main/database.cpp 5 | @@ -506,6 +528,7 @@ idx_t DuckDB::NumberOfThreads() { 6 | } 7 | 8 | bool DatabaseInstance::ExtensionIsLoaded(const std::string &name) { 9 | + if (name == "httpfs") return true; 10 | auto extension_name = ExtensionHelper::GetExtensionName(name); 11 | auto it = loaded_extensions_info.find(extension_name); 12 | return it != loaded_extensions_info.end() && it->second.is_loaded; 13 | -------------------------------------------------------------------------------- /examples/esbuild-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@duckdb/duckdb-wasm-examples-esbuild-node", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@duckdb/duckdb-wasm": "file:../../packages/duckdb-wasm" 9 | }, 10 | "devDependencies": { 11 | "esbuild": "^0.20.2", 12 | "typescript": "^5.3.3" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "build": "node ./bundle.mjs && tsc --noEmit", 17 | "test": "node ./index.mjs" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/3.sql: -------------------------------------------------------------------------------- 1 | select 2 | l_orderkey, 3 | sum(l_extendedprice * (1 - l_discount)) as revenue, 4 | o_orderdate, 5 | o_shippriority 6 | from 7 | customer, 8 | orders, 9 | lineitem 10 | where 11 | c_mktsegment = 'BUILDING' 12 | and c_custkey = o_custkey 13 | and l_orderkey = o_orderkey 14 | and o_orderdate < '1995-03-15' 15 | and l_shipdate > '1995-03-15' 16 | group by 17 | l_orderkey, 18 | o_orderdate, 19 | o_shippriority 20 | order by 21 | revenue desc, 22 | o_orderdate 23 | limit 24 | 10; 25 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/shell_options.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | extern "C" { 5 | #[wasm_bindgen(js_name = "ShellOptions")] 6 | pub type ShellOptions; 7 | #[wasm_bindgen(method, getter, js_name = "backgroundColor")] 8 | pub fn get_bg(this: &ShellOptions) -> String; 9 | #[wasm_bindgen(method, getter, js_name = "fontFamily")] 10 | pub fn get_font_family(this: &ShellOptions) -> String; 11 | #[wasm_bindgen(method, getter, js_name = "withWebGL")] 12 | pub fn with_webgl(this: &ShellOptions) -> bool; 13 | } 14 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/clockfast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /scripts/npm_measure_lib.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | 5 | cd ${PROJECT_ROOT}/packages/duckdb-wasm 6 | mkdir -p ./dist/img 7 | cp ${PROJECT_ROOT}/misc/duckdb.svg ./dist/img/duckdb.svg 8 | cp ${PROJECT_ROOT}/misc/duckdb_wasm.svg ./dist/img/duckdb_wasm.svg 9 | ${PROJECT_ROOT}/scripts/build_duckdb_badge.sh > ./dist/img/duckdb_version_badge.svg 10 | 11 | npm install -g pkg-size 12 | pkg-size . --sizes=size > output 13 | cat output 14 | tail -n2 output | grep " MB" | awk '{print ($1 < 150)}' | grep "1" || exit 1 15 | -------------------------------------------------------------------------------- /scripts/generate_uni.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | trap exit SIGINT 6 | 7 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 8 | 9 | UNI_DIR=${PROJECT_ROOT}/data/uni 10 | DATAPREP=${PROJECT_ROOT}/target/release/dataprep 11 | 12 | if [ ! -f ${DATAPREP} ]; then 13 | cargo build --manifest-path=${PROJECT_ROOT}/Cargo.toml --release -p dataprep 14 | fi 15 | echo "DATAPREP=${DATAPREP}" 16 | 17 | if [ ! -f "${UNI_DIR}/studenten.parquet" ]; then 18 | mkdir -p ${UNI_DIR} 19 | ${DATAPREP} uni -o ${UNI_DIR} 20 | fi 21 | echo "UNI_DIR=${UNI_DIR}" 22 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/5.sql: -------------------------------------------------------------------------------- 1 | select 2 | n_name, 3 | sum(l_extendedprice * (1 - l_discount)) as revenue 4 | from 5 | customer, 6 | orders, 7 | lineitem, 8 | supplier, 9 | nation, 10 | region 11 | where 12 | c_custkey = o_custkey 13 | and l_orderkey = o_orderkey 14 | and l_suppkey = s_suppkey 15 | and c_nationkey = s_nationkey 16 | and s_nationkey = n_nationkey 17 | and n_regionkey = r_regionkey 18 | and r_name = 'ASIA' 19 | and o_orderdate >= '1994-01-01' 20 | and o_orderdate < '1995-01-01' 21 | group by 22 | n_name 23 | order by 24 | revenue desc; 25 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/utils/spin_mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_SPIN_MUTEX_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_SPIN_MUTEX_H_ 3 | 4 | #include 5 | 6 | namespace duckdb { 7 | namespace web { 8 | 9 | /// A simple mutex as pure spin-lock that never leaves wasm. 10 | struct SpinMutex { 11 | std::atomic_flag flag{0}; 12 | void lock() { 13 | while (flag.test_and_set(std::memory_order_acq_rel)) 14 | ; 15 | } 16 | void unlock() { flag.clear(); } 17 | bool try_lock() { return flag.test_and_set(); } 18 | }; 19 | 20 | } // namespace web 21 | } // namespace duckdb 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /scripts/npm_restore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | 5 | NPM_VERSION=${1} 6 | echo "NPM_VERSION=${NPM_VERSION}" 7 | 8 | PKG_DIR="${PROJECT_ROOT}/packages/duckdb-wasm" 9 | PKG_TARBALL="duckdb-duckdb-wasm-${NPM_VERSION}.tgz" 10 | TMP_DIR="${PROJECT_ROOT}/.tmp/npm" 11 | echo "${NPM_VERSION}" 12 | 13 | set -x 14 | 15 | rm -rf ${TMP_DIR} 16 | mkdir -p ${TMP_DIR} 17 | cd ${TMP_DIR} 18 | 19 | npm pack "@duckdb/duckdb-wasm@${NPM_VERSION}" 20 | tar -xvzf ./duckdb-duckdb-wasm-*.tgz 21 | 22 | rm -rf "${PKG_DIR}/dist" 23 | cp -r "./package/dist" "${PKG_DIR}/dist" 24 | -------------------------------------------------------------------------------- /scripts/build_duckdb_badge.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | BADGEGEN=${PROJECT_ROOT}/node_modules/.bin/badge 5 | 6 | cd ${PROJECT_ROOT}/submodules/duckdb 7 | VERSION=`git describe --tags --abbrev=0 | tr -d "v"` 8 | DEV=`git describe --tags --long | cut -f2 -d-` 9 | 10 | BADGE_LABEL_COLOR="#555" 11 | BADGE_VALUE_COLOR="#007ec6" 12 | 13 | if [[ "${DEV}" = "0" ]] ; then 14 | ${BADGEGEN} duckdb "v${VERSION}" ${BADGE_VALUE_COLOR} ${BADGE_LABEL_COLOR} 15 | else 16 | ${BADGEGEN} duckdb "v${VERSION}-dev${DEV}" ${BADGE_VALUE_COLOR} ${BADGE_LABEL_COLOR} 17 | fi 18 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/ligatures.rs: -------------------------------------------------------------------------------- 1 | use crate::xterm::{Terminal, TerminalAddon}; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen(module = "xterm-addon-ligatures")] 5 | extern "C" { 6 | 7 | #[wasm_bindgen(extends = TerminalAddon)] 8 | pub type LigaturesAddon; 9 | 10 | #[wasm_bindgen(constructor)] 11 | pub fn new() -> LigaturesAddon; 12 | 13 | #[wasm_bindgen(method, method, js_name = "activate")] 14 | pub fn activate(this: &LigaturesAddon, terminal: &Terminal); 15 | 16 | #[wasm_bindgen(method, method, js_name = "dispose")] 17 | pub fn dispose(this: &LigaturesAddon); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/unicode11.rs: -------------------------------------------------------------------------------- 1 | use crate::xterm::{Terminal, TerminalAddon}; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen(module = "xterm-addon-unicode11")] 5 | extern "C" { 6 | 7 | #[wasm_bindgen(extends = TerminalAddon)] 8 | pub type Unicode11Addon; 9 | 10 | #[wasm_bindgen(constructor)] 11 | pub fn new() -> Unicode11Addon; 12 | 13 | #[wasm_bindgen(method, method, js_name = "activate")] 14 | pub fn activate(this: &Unicode11Addon, terminal: Terminal); 15 | 16 | #[wasm_bindgen(method, method, js_name = "dispose")] 17 | pub fn dispose(this: &Unicode11Addon); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/1.sql: -------------------------------------------------------------------------------- 1 | select 2 | l_returnflag, 3 | l_linestatus, 4 | sum(l_quantity) as sum_qty, 5 | sum(l_extendedprice) as sum_base_price, 6 | sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, 7 | sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, 8 | avg(l_quantity) as avg_qty, 9 | avg(l_extendedprice) as avg_price, 10 | avg(l_discount) as avg_disc, 11 | count(*) as count_order 12 | from 13 | lineitem 14 | where 15 | l_shipdate <= '1998-09-02' 16 | group by 17 | l_returnflag, 18 | l_linestatus 19 | order by 20 | l_returnflag, 21 | l_linestatus; 22 | -------------------------------------------------------------------------------- /patches/duckdb/fix_config_size_t.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/main/config.cpp b/src/main/config.cpp 2 | index d6147d0ac0..7d81469356 100644 3 | --- a/src/main/config.cpp 4 | +++ b/src/main/config.cpp 5 | @@ -301,7 +301,7 @@ LogicalType DBConfig::ParseLogicalType(const string &type) { 6 | if (StringUtil::EndsWith(type, "]")) { 7 | // array - recurse 8 | auto bracket_open_idx = type.rfind('['); 9 | - if (bracket_open_idx == DConstants::INVALID_INDEX || bracket_open_idx == 0) { 10 | + if (bracket_open_idx == string::npos || bracket_open_idx == 0) { 11 | throw InternalException("Ill formatted type: '%s'", type); 12 | } 13 | idx_t array_size = 0; 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: '/' 5 | schedule: 6 | interval: weekly 7 | time: '07:00' 8 | timezone: 'Europe/Berlin' 9 | commit-message: 10 | prefix: fix 11 | prefix-development: chore 12 | include: scope 13 | - package-ecosystem: github-actions 14 | directory: '/' 15 | schedule: 16 | interval: weekly 17 | time: '07:00' 18 | timezone: 'Europe/Berlin' 19 | commit-message: 20 | prefix: fix 21 | prefix-development: chore 22 | include: scope 23 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/16.sql: -------------------------------------------------------------------------------- 1 | select 2 | p_brand, 3 | p_type, 4 | p_size, 5 | count(distinct ps_suppkey) as supplier_cnt 6 | from 7 | partsupp, 8 | part 9 | where 10 | p_partkey = ps_partkey 11 | and p_brand <> 'Brand#45' 12 | and p_type not like 'MEDIUM POLISHED%' 13 | and p_size in (49, 14, 23, 45, 19, 3, 36, 9) 14 | and ps_suppkey not in ( 15 | select 16 | s_suppkey 17 | from 18 | supplier 19 | where 20 | s_comment like '%Customer%Complaints%' 21 | ) 22 | group by 23 | p_brand, 24 | p_type, 25 | p_size 26 | order by 27 | supplier_cnt desc, 28 | p_brand, 29 | p_type, 30 | p_size; 31 | -------------------------------------------------------------------------------- /examples/esbuild-browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@duckdb/duckdb-wasm-examples-esbuild-browser", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@duckdb/duckdb-wasm": "file:../../packages/duckdb-wasm" 9 | }, 10 | "devDependencies": { 11 | "esbuild": "^0.20.2", 12 | "http-server": "^14.1.1", 13 | "serve": "^14.2.1", 14 | "typescript": "^5.3.3" 15 | }, 16 | "scripts": { 17 | "build": "node ./bundle.mjs && tsc --noEmit", 18 | "server": "http-server", 19 | "server-coi": "serve" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/18.sql: -------------------------------------------------------------------------------- 1 | select 2 | c_name, 3 | c_custkey, 4 | o_orderkey, 5 | o_orderdate, 6 | o_totalprice, 7 | sum(l_quantity) 8 | from 9 | customer, 10 | orders, 11 | lineitem 12 | where 13 | o_orderkey in ( 14 | select 15 | l_orderkey 16 | from 17 | lineitem 18 | group by 19 | l_orderkey 20 | having 21 | sum(l_quantity) > 300 22 | ) 23 | and c_custkey = o_custkey 24 | and o_orderkey = l_orderkey 25 | group by 26 | c_name, 27 | c_custkey, 28 | o_orderkey, 29 | o_orderdate, 30 | o_totalprice 31 | order by 32 | o_totalprice desc, 33 | o_orderdate 34 | limit 35 | 100; 36 | -------------------------------------------------------------------------------- /actions/runner/ufw_before_rules.txt: -------------------------------------------------------------------------------- 1 | # Isolate the VMs 2 | # 3 | # We certainly want GitHub actions at some point but this will do for the private repo. 4 | # 5 | # Find the bridge used by multipass `brctl show`. 6 | # If you run multipass with libvirt (see multipass.sh), the default bridge will be virbr0. 7 | # Get you standard gateway (192.168.178.1/32, here) 8 | # 9 | # Adjust /etc/ufw/before.rules after L17 10 | # Accept all packets from the multipass vm that target the standard gateway. 11 | # Drop all packets from the multipass vm that target any other host. 12 | 13 | -I FORWARD 1 -d 192.168.178.1/32 -i virbr0 -j ACCEPT 14 | -I FORWARD 2 -d 192.168.0.0/16 -i virbr0 -j DROP 15 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/webpack.release.js: -------------------------------------------------------------------------------- 1 | import { configure } from './webpack.common.js'; 2 | import { fileURLToPath } from 'url'; 3 | import path from 'path'; 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 6 | 7 | const base = configure({ 8 | buildDir: path.resolve(__dirname, './build/release'), 9 | tsLoaderOptions: { 10 | compilerOptions: { 11 | configFile: './tsconfig.json', 12 | sourceMap: false, 13 | }, 14 | }, 15 | extractCss: true, 16 | cssIdentifier: '[hash:base64]', 17 | }); 18 | 19 | export default { 20 | ...base, 21 | mode: 'production', 22 | devtool: false, 23 | }; 24 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/comfy/style/cell.rs: -------------------------------------------------------------------------------- 1 | /// This can be set on [columns](crate::Column::set_cell_alignment) and [cells](crate::Cell::set_alignment). 2 | /// 3 | /// Determines how content of cells should be aligned. 4 | /// 5 | /// ```text 6 | /// +----------------------+ 7 | /// | Header1 | 8 | /// +======================+ 9 | /// | Left | 10 | /// |----------------------+ 11 | /// | center | 12 | /// |----------------------+ 13 | /// | right | 14 | /// +----------------------+ 15 | /// ``` 16 | #[derive(Copy, Clone, Debug)] 17 | pub enum CellAlignment { 18 | Left, 19 | Right, 20 | Center, 21 | } 22 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/duckdb/version.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen(module = "@duckdb/duckdb-wasm")] 4 | extern "C" { 5 | #[wasm_bindgen(js_name = "PACKAGE_NAME")] 6 | pub static PACKAGE_NAME: String; 7 | 8 | #[wasm_bindgen(js_name = "PACKAGE_VERSION")] 9 | pub static PACKAGE_VERSION: String; 10 | #[wasm_bindgen(js_name = "PACKAGE_VERSION_MAJOR")] 11 | pub static PACKAGE_VERSION_MAJOR: String; 12 | #[wasm_bindgen(js_name = "PACKAGE_VERSION_MINOR")] 13 | pub static PACKAGE_VERSION_MINOR: String; 14 | #[wasm_bindgen(js_name = "PACKAGE_VERSION_PATCH")] 15 | pub static PACKAGE_VERSION_PATCH: String; 16 | } 17 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod arrow_printer; 2 | pub mod arrow_reader; 3 | pub mod comfy; 4 | pub mod console; 5 | pub mod duckdb; 6 | pub mod error; 7 | pub mod key_event; 8 | pub mod platform; 9 | pub mod prompt_buffer; 10 | pub mod shell; 11 | pub mod shell_api; 12 | pub mod shell_options; 13 | pub mod shell_runtime; 14 | pub mod utils; 15 | pub mod vt100; 16 | pub mod xterm; 17 | 18 | use wasm_bindgen::prelude::*; 19 | 20 | use console::DEFAULT_LOGGER; 21 | 22 | #[wasm_bindgen(start)] 23 | pub fn main() { 24 | console_error_panic_hook::set_once(); 25 | log::set_logger(&DEFAULT_LOGGER).unwrap(); 26 | log::set_max_level(log::LevelFilter::Info); 27 | } 28 | -------------------------------------------------------------------------------- /scripts/build_loadable.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | trap exit SIGINT 6 | 7 | MODE=$1 8 | FEATURE=$2 9 | INPUT_PATH=./build/${MODE}/${FEATURE}/ 10 | OUTPUT_PATH=loadable_extensions/${MODE}/${FEATURE}/ 11 | 12 | mkdir -p "${OUTPUT_PATH}" 13 | shopt -s nullglob 14 | 15 | for ext_path in $(find "${INPUT_PATH}" -name '*.duckdb_extension.wasm.lib') 16 | do 17 | ext_name=$(basename "$ext_path" .duckdb_extension.wasm.lib) 18 | echo "Building '$ext_name'..." 19 | emcc "$ext_path" -sSIDE_MODULE=2 -sEXPORTED_FUNCTIONS="_""$ext_name""_init,_""$ext_name""_version" -o "${INPUT_PATH}/$ext_name.duckdb_extension.wasm" -O3 -sSHARED_MEMORY=1 -pthread 20 | done 21 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/insert_options.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "arrow/ipc/reader.h" 4 | #include "arrow/type.h" 5 | #include "arrow/type_fwd.h" 6 | #include "duckdb/web/arrow_stream_buffer.h" 7 | #include "rapidjson/document.h" 8 | 9 | namespace duckdb { 10 | namespace web { 11 | 12 | /// Get a type name 13 | std::string_view GetTypeName(rapidjson::Type type); 14 | /// Require a boolean field 15 | arrow::Status RequireBoolField(const rapidjson::Value& value, std::string_view name); 16 | /// Require a certain field type 17 | arrow::Status RequireFieldType(const rapidjson::Value& value, rapidjson::Type type, std::string_view field); 18 | 19 | } // namespace web 20 | } // namespace duckdb 21 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/svg/icons/book.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/favicons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/components/minibar_chart.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import cn from 'classnames'; 3 | 4 | import styles from './minibar_chart.module.css'; 5 | 6 | interface Props { 7 | className?: string; 8 | value: number; 9 | } 10 | 11 | export const MiniBarChart: React.FC = (props: Props): React.ReactElement => ( 12 |
13 |
14 |
20 |
21 |
22 | ); 23 | -------------------------------------------------------------------------------- /patches/duckdb/bind_copy_direct_io.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/planner/binder/statement/bind_copy.cpp b/src/planner/binder/statement/bind_copy.cpp 2 | index ce2f93ad86..140af5ba36 100644 3 | --- a/src/planner/binder/statement/bind_copy.cpp 4 | +++ b/src/planner/binder/statement/bind_copy.cpp 5 | @@ -152,7 +152,9 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt, CopyToType copy_to_type) 6 | } 7 | } 8 | bool is_remote_file = FileSystem::IsRemoteFile(stmt.info->file_path); 9 | - if (is_remote_file) { 10 | + if ( is_remote_file ) { 11 | + use_tmp_file = false; 12 | + } else if( context.db->config.options.use_direct_io ) { 13 | use_tmp_file = false; 14 | } else { 15 | auto &fs = FileSystem::GetFileSystem(context); 16 | -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | # Building and Testing 2 | 3 | Below is a minimal script for building and running the unit tests of the project. 4 | 5 | ```bash 6 | mkdir -p build 7 | cd build 8 | cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ../lib 9 | cmake --build . 10 | 11 | cd .. 12 | ./scripts/generate_tpch_tbl.sh 0.01 13 | ./scripts/generate_tpch_arrow.sh 0.01 14 | ./scripts/generate_uni.sh 15 | 16 | (cd build && ./tester) 17 | ``` 18 | 19 | A standard C++ debugger can be attached to the `tester` program (e.g. `lldb -- ./tester`). 20 | 21 | # Formatting 22 | The following script can be run to format the code. 23 | 24 | ```bash 25 | python3 ./scripts/run_clang_format.py --exclude ./lib/build --exclude ./lib/third_party -r ./lib/ -i 26 | ``` -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/10.sql: -------------------------------------------------------------------------------- 1 | select 2 | c_custkey, 3 | c_name, 4 | sum(l_extendedprice * (1 - l_discount)) as revenue, 5 | c_acctbal, 6 | n_name, 7 | c_address, 8 | c_phone, 9 | c_comment 10 | from 11 | customer, 12 | orders, 13 | lineitem, 14 | nation 15 | where 16 | c_custkey = o_custkey 17 | and l_orderkey = o_orderkey 18 | and o_orderdate >= '1993-10-01' 19 | and o_orderdate < '1994-01-01' 20 | and l_returnflag = 'R' 21 | and c_nationkey = n_nationkey 22 | group by 23 | c_custkey, 24 | c_name, 25 | c_acctbal, 26 | c_phone, 27 | n_name, 28 | c_address, 29 | c_comment 30 | order by 31 | revenue desc 32 | limit 33 | 20; 34 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/11.sql: -------------------------------------------------------------------------------- 1 | select 2 | ps_partkey, 3 | sum(ps_supplycost * ps_availqty) as value 4 | from 5 | partsupp, 6 | supplier, 7 | nation 8 | where 9 | ps_suppkey = s_suppkey 10 | and s_nationkey = n_nationkey 11 | and n_name = 'GERMANY' 12 | group by 13 | ps_partkey 14 | having 15 | sum(ps_supplycost * ps_availqty) > ( 16 | select 17 | sum(ps_supplycost * ps_availqty) * 0.0001 18 | from 19 | partsupp, 20 | supplier, 21 | nation 22 | where 23 | ps_suppkey = s_suppkey 24 | and s_nationkey = n_nationkey 25 | and n_name = 'GERMANY' 26 | ) 27 | order by 28 | value desc; 29 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/json.test.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '../src/'; 2 | 3 | export function testJSON(db: () => duckdb.DuckDBBindings): void { 4 | let conn: duckdb.DuckDBConnection; 5 | beforeEach(() => { 6 | conn = db().connect(); 7 | }); 8 | 9 | afterEach(() => { 10 | conn.close(); 11 | db().flushFiles(); 12 | db().dropFiles(); 13 | }); 14 | 15 | describe('JSON', () => { 16 | it('sample', async () => { 17 | expect(conn.query('select to_json({n: 42})').getChildAt(0)?.toArray()).toEqual(['{"n":42}']); 18 | expect(conn.query("select json_object('duck', 42)").getChildAt(0)?.toArray()).toEqual(['{"duck":42}']); 19 | }); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/regression/index.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '../../src/'; 2 | import { test332 } from './github_332.test'; 3 | import { test334 } from './github_334.test'; 4 | import { test393 } from './github_393.test'; 5 | import { test448 } from './github_448.test'; 6 | import { test470 } from './github_470.test'; 7 | import { test477 } from './github_477.test'; 8 | import { test1467 } from './github_1467.test'; 9 | import { test1833 } from './github_1833.test'; 10 | 11 | export function testRegressionAsync(adb: () => duckdb.AsyncDuckDB): void { 12 | test332(adb); 13 | test334(adb); 14 | test393(adb); 15 | test448(adb); 16 | test470(adb); 17 | test477(adb); 18 | test1467(adb); 19 | test1833(adb); 20 | } 21 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/utils/platform.ts: -------------------------------------------------------------------------------- 1 | // Platform check taken from here: 2 | // https://github.com/xtermjs/xterm.js/blob/master/src/common/Platform.ts#L21 3 | 4 | interface INavigator { 5 | userAgent: string; 6 | language: string; 7 | platform: string; 8 | } 9 | 10 | // We're declaring a navigator global here as we expect it in all runtimes (node and browser), but 11 | // we want this module to live in common. 12 | declare const navigator: INavigator; 13 | 14 | const isNode = typeof navigator === 'undefined' ? true : false; 15 | const userAgent = isNode ? 'node' : navigator.userAgent; 16 | 17 | export const isFirefox = userAgent.includes('Firefox'); 18 | export const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent); 19 | -------------------------------------------------------------------------------- /packages/react-duckdb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@duckdb/react-duckdb", 3 | "version": "1.11.0", 4 | "description": "React components for DuckDB-Wasm", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/duckdb/duckdb-wasm.git" 9 | }, 10 | "keywords": [ 11 | "sql", 12 | "duckdb", 13 | "relational", 14 | "database", 15 | "data", 16 | "query", 17 | "wasm", 18 | "analytics", 19 | "olap", 20 | "arrow", 21 | "parquet", 22 | "json", 23 | "csv" 24 | ], 25 | "files": [ 26 | "src" 27 | ], 28 | "main": "src/index.ts", 29 | "types": "src/index.ts" 30 | } 31 | -------------------------------------------------------------------------------- /actions/runner/multipass.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Configure multipass to use the libvirt driver: 4 | # 5 | # sudo apt install libvirt-daemon-system 6 | # sudo snap connect multipass:libvirt 7 | # sudo multipass set local.driver=libvirt 8 | # 9 | # Let the cloud-init setup your vm, afterwards do the following steps: 10 | # * Su actions and register the runner in /home/actions/runner 11 | # * Install the action runner as root via /home/actions/runner/svc.sh install actions 12 | # * Providing the user actions to svc.sh install is crucial since the service needs the correct permissions! 13 | 14 | 15 | multipass launch \ 16 | --cpus 8 \ 17 | --disk 100G \ 18 | --mem 6G \ 19 | --name github-duckdb-wasm-ci \ 20 | --cloud-init ./cloud-init.yaml 21 | 22 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/table.tsx: -------------------------------------------------------------------------------- 1 | import * as rd from '@duckdb/react-duckdb'; 2 | import React from 'react'; 3 | 4 | import styles from './table.module.css'; 5 | 6 | interface Props { 7 | className?: string; 8 | } 9 | 10 | export const TableViewer: React.FC = (props: Props) => { 11 | const db = rd.useDuckDB(); 12 | const resolveDB = rd.useDuckDBResolver(); 13 | React.useEffect(() => { 14 | if (!db.resolving()) { 15 | resolveDB(); 16 | } 17 | }, [db]); 18 | 19 | if (db == null) { 20 | return ( 21 |
22 |
23 |
24 | ); 25 | } 26 | return
todo
; 27 | }; 28 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/webpack.debug.corp.js: -------------------------------------------------------------------------------- 1 | import config from './webpack.debug.js'; 2 | 3 | export default { 4 | ...config, 5 | devServer: { 6 | ...config.devServer, 7 | headers: { 8 | 'Access-Control-Allow-Origin': '*', 9 | 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', 10 | 'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization', 11 | 12 | // This will enable SharedArrayBuffers in Firefox but will block most requests to third-party sites. 13 | 'Cross-Origin-Resource-Policy': 'cross-origin', 14 | 'Cross-Origin-Embedder-Policy': 'require-corp', 15 | 'Cross-Origin-Opener-Policy': 'same-origin', 16 | }, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/serialize.rs: -------------------------------------------------------------------------------- 1 | use crate::xterm::{Terminal, TerminalAddon}; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen(module = "xterm-addon-serialize")] 5 | extern "C" { 6 | 7 | #[wasm_bindgen(extends = TerminalAddon)] 8 | pub type SerializeAddon; 9 | 10 | #[wasm_bindgen(constructor)] 11 | pub fn new() -> SerializeAddon; 12 | 13 | #[wasm_bindgen(method, method, js_name = "activate")] 14 | pub fn activate(this: &SerializeAddon, terminal: Terminal); 15 | 16 | #[wasm_bindgen(method, method, js_name = "serialize")] 17 | pub fn serialize(this: &SerializeAddon, rows: Option) -> String; 18 | 19 | #[wasm_bindgen(method, method, js_name = "dispose")] 20 | pub fn dispose(this: &SerializeAddon); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/string_test_helper.ts: -------------------------------------------------------------------------------- 1 | export function generateLongQueryString(): string { 2 | const aaa = repeatCharacter('A', 512); 3 | const ccc = repeatCharacter('C', 256); 4 | const ddd = repeatCharacter('D', 512); 5 | const eee = repeatCharacter('E', 256); 6 | const ggg = repeatCharacter('G', 128); 7 | 8 | return ( 9 | `test=inline` + 10 | `&Test-Security-Token=${aaa}` + 11 | `&Test-Algorithm=${ccc}` + 12 | `&Test-Date=${ddd}` + 13 | `&Test-SignedHeaders=host` + 14 | `&Test-Expires=43200` + 15 | `&Test-Credential=${eee}` + 16 | `&Test-Signature=${ggg}` 17 | ); 18 | } 19 | 20 | export function repeatCharacter(char: string, length: number): string { 21 | return char.repeat(length); 22 | } 23 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/arrow_type_mapping.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_ARROW_TYPE_MAPPING_H_ 2 | #define INCLUDE_DUCKDB_WEB_ARROW_TYPE_MAPPING_H_ 3 | 4 | #include 5 | 6 | #include "arrow/array/array_base.h" 7 | #include "arrow/type_fwd.h" 8 | #include "duckdb/common/types.hpp" 9 | 10 | namespace duckdb { 11 | namespace web { 12 | 13 | /// Map arrow type 14 | arrow::Result mapArrowTypeToDuckDB(const arrow::DataType& type); 15 | /// Map duckdb type to arrow 16 | arrow::Result> mapDuckDBTypeToArrow(const duckdb::LogicalType& type); 17 | /// Convert an arrow array to a DuckDB vector 18 | arrow::Status convertArrowArrayToDuckDBVector(arrow::Array& in, duckdb::Vector& out); 19 | 20 | } // namespace web 21 | } // namespace duckdb 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /scripts/npm_version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 4 | 5 | # Prerelease everything else 6 | git describe --tags --long 7 | export VERSION=`git describe --tags --abbrev=0 | tr -d "v"` 8 | export DEV=`git describe --tags --long | cut -f2 -d-` 9 | echo "VERSION=${VERSION}" 10 | echo "DEV=${DEV}" 11 | 12 | # Is release? 13 | if [[ "${DEV}" = "0" ]] ; then 14 | for PKG in ${PROJECT_ROOT}/packages/* ; do 15 | cd ${PKG} 16 | npm version ${VERSION} 17 | done 18 | else 19 | for PKG in ${PROJECT_ROOT}/packages/* ; do 20 | cd ${PKG} 21 | npm version ${VERSION} 22 | npm version prerelease --preid="dev"${DEV} 23 | done 24 | fi 25 | echo "TAG=${TAG}" 26 | 27 | cd ${PROJECT_ROOT} 28 | node ${PROJECT_ROOT}/scripts/sync_versions.mjs 29 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/udf.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UDF_H_ 2 | #define INCLUDE_DUCKDB_WEB_UDF_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "arrow/type_fwd.h" 10 | #include "rapidjson/document.h" 11 | 12 | namespace duckdb { 13 | namespace web { 14 | 15 | struct UDFFunctionDeclaration { 16 | /// The name 17 | std::string name = ""; 18 | /// The function id 19 | size_t function_id = 0; 20 | /// The argument count 21 | size_t argument_count = 0; 22 | /// The return type 23 | std::shared_ptr return_type = {}; 24 | 25 | /// Read from a document 26 | arrow::Status ReadFrom(const rapidjson::Document& doc); 27 | }; 28 | 29 | } // namespace web 30 | } // namespace duckdb 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/arrow_insert_options.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_ARROW_INSERT_OPTIONS_H_ 2 | #define INCLUDE_DUCKDB_WEB_ARROW_INSERT_OPTIONS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "arrow/type_fwd.h" 10 | #include "rapidjson/document.h" 11 | 12 | namespace duckdb { 13 | namespace web { 14 | 15 | /// Get the CSV reader options 16 | struct ArrowInsertOptions { 17 | /// The schema name 18 | std::string schema_name = ""; 19 | /// The table name 20 | std::string table_name = ""; 21 | /// Create a new table? 22 | bool create_new = true; 23 | 24 | /// Read from input stream 25 | arrow::Status ReadFrom(const rapidjson::Document& doc); 26 | }; 27 | 28 | } // namespace web 29 | } // namespace duckdb 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /scripts/deploy_benchmarks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | 5 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 6 | PAGES=${PROJECT_ROOT}/worktrees/gh-pages 7 | 8 | mkdir -p ${PROJECT_ROOT}/worktrees 9 | if [ ! -d ${PAGES} ]; then 10 | echo "[ RUN ] Add worktree origin/gh-pages" 11 | git worktree add ${PAGES} origin/gh-pages 12 | fi 13 | 14 | cd ${PAGES} 15 | git fetch origin gh-pages 16 | git reset --hard origin/gh-pages 17 | 18 | mkdir -p data 19 | cp -r ${PROJECT_ROOT}/reports/benchmarks.arrow ./data/benchmarks.arrow 20 | cp -r ${PROJECT_ROOT}/duckdb/benchmarks.json ./data/benchmarks.json 21 | cp -r ${PROJECT_ROOT}/duckdb/benchmarks.csv ./data/benchmarks.csv 22 | 23 | git add ./data/* 24 | git commit --amend -m "Update benchmarks" 25 | git push origin HEAD:gh-pages --force 26 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/20.sql: -------------------------------------------------------------------------------- 1 | select 2 | s_name, 3 | s_address 4 | from 5 | supplier, 6 | nation 7 | where 8 | s_suppkey in ( 9 | select 10 | ps_suppkey 11 | from 12 | partsupp 13 | where 14 | ps_partkey in ( 15 | select 16 | p_partkey 17 | from 18 | part 19 | where 20 | p_name like 'forest%' 21 | ) 22 | and ps_availqty > ( 23 | select 24 | 0.5 * sum(l_quantity) 25 | from 26 | lineitem 27 | where 28 | l_partkey = ps_partkey 29 | and l_suppkey = ps_suppkey 30 | and l_shipdate >= '1994-01-01' 31 | and l_shipdate < '1995-01-01' 32 | ) 33 | ) 34 | and s_nationkey = n_nationkey 35 | and n_name = 'CANADA' 36 | order by 37 | s_name; 38 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/webgl.rs: -------------------------------------------------------------------------------- 1 | use crate::xterm::{Terminal, TerminalAddon}; 2 | use wasm_bindgen::prelude::*; 3 | use web_sys::HtmlCanvasElement; 4 | 5 | #[wasm_bindgen(module = "xterm-addon-webgl")] 6 | extern "C" { 7 | 8 | #[wasm_bindgen(extends = TerminalAddon)] 9 | pub type WebglAddon; 10 | 11 | #[wasm_bindgen(method, setter, js_name = "textureAtlas")] 12 | pub fn set_texture_atlas(this: &WebglAddon, val: &HtmlCanvasElement); 13 | 14 | #[wasm_bindgen(constructor)] 15 | pub fn new(preserve_drawing_buffer: Option) -> WebglAddon; 16 | 17 | #[wasm_bindgen(method, method, js_name = "activate")] 18 | pub fn activate(this: &WebglAddon, terminal: Terminal); 19 | 20 | #[wasm_bindgen(method, method, js_name = "dispose")] 21 | pub fn dispose(this: &WebglAddon); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "repository": { 3 | "type": "git", 4 | "url": "https://github.com/duckdb/duckdb-wasm.git" 5 | }, 6 | "private": true, 7 | "workspaces": [ 8 | "packages/*", 9 | "examples/*" 10 | ], 11 | "scripts": { 12 | "lint:fix": "yarn workspace @duckdb/duckdb-wasm lint --fix && yarn workspace @duckdb/benchmarks lint --fix && yarn workspace @duckdb/duckdb-wasm-shell lint --fix", 13 | "docs": "yarn workspace @duckdb/duckdb-wasm docs", 14 | "benchmarks:build:browser": "yarn workspace @duckdb/benchmarks build:browser", 15 | "benchmarks:build:node": "yarn workspace @duckdb/benchmarks build:node", 16 | "benchmarks:build": "yarn workspace @duckdb/benchmarks build" 17 | }, 18 | "devDependencies": { 19 | "badge-maker": "^3.3.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/bare-browser/bundle.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { createRequire } from 'module'; 4 | 5 | const require = createRequire(import.meta.url); 6 | const DUCKDB_DIST = path.dirname(require.resolve('@duckdb/duckdb-wasm')); 7 | 8 | function printErr(err) { 9 | if (err) return console.log(err); 10 | } 11 | 12 | fs.copyFile(path.resolve(DUCKDB_DIST, 'duckdb-browser.mjs'), './duckdb-browser.mjs', printErr); 13 | fs.copyFile(path.resolve(DUCKDB_DIST, 'duckdb-mvp.wasm'), './duckdb-mvp.wasm', printErr); 14 | fs.copyFile(path.resolve(DUCKDB_DIST, 'duckdb-eh.wasm'), './duckdb-eh.wasm', printErr); 15 | fs.copyFile(path.resolve(DUCKDB_DIST, 'duckdb-browser-mvp.worker.js'), './duckdb-browser-mvp.worker.js', printErr); 16 | fs.copyFile(path.resolve(DUCKDB_DIST, 'duckdb-browser-eh.worker.js'), './duckdb-browser-eh.worker.js', printErr); 17 | -------------------------------------------------------------------------------- /packages/benchmarks/src/utils/format.ts: -------------------------------------------------------------------------------- 1 | export enum ByteFormat { 2 | SI = 0, 3 | IEC = 1, 4 | } 5 | 6 | export function formatBytes(value: number, format: ByteFormat = ByteFormat.SI): string { 7 | const [multiple, k, suffix] = format === ByteFormat.SI ? [1000, 'k', 'B'] : [1024, 'K', 'iB']; 8 | const exp = (Math.log(value) / Math.log(multiple)) | 0; 9 | const size = Number((value / Math.pow(multiple, exp)).toFixed(2)); 10 | return `${size} ${exp ? `${k}MGTPEZY`[exp - 1] + suffix : `byte${size !== 1 ? 's' : ''}`}`; 11 | } 12 | 13 | export function formatThousands(value: number): string { 14 | const [multiple, k] = [1000, 'k']; 15 | const exp = (Math.log(value) / Math.log(multiple)) | 0; 16 | const size = Number((value / Math.pow(multiple, exp)).toFixed(2)); 17 | return size + (exp ? ` ${`${k}MGTPEZY`[exp - 1]}` : ''); 18 | } 19 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/web_links.rs: -------------------------------------------------------------------------------- 1 | use crate::xterm::{LinkMatcherOptions, Terminal, TerminalAddon}; 2 | use js_sys::Function; 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen(module = "xterm-addon-web-links")] 6 | extern "C" { 7 | 8 | #[wasm_bindgen(extends = TerminalAddon)] 9 | pub type WebLinksAddon; 10 | 11 | #[wasm_bindgen(constructor)] 12 | pub fn new( 13 | handler: Option<&Function>, // (event: MouseEvent, uri: &str) => void 14 | options: Option<&LinkMatcherOptions>, 15 | useLinkProvider: Option, 16 | ) -> WebLinksAddon; 17 | 18 | #[wasm_bindgen(method, method, js_name = "activate")] 19 | pub fn activate(this: &WebLinksAddon, terminal: &Terminal); 20 | 21 | #[wasm_bindgen(method, method, js_name = "dispose")] 22 | pub fn dispose(this: &WebLinksAddon); 23 | } 24 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/22-sqlite.sql: -------------------------------------------------------------------------------- 1 | select 2 | cntrycode, 3 | count(*) as numcust, 4 | sum(c_acctbal) as totacctbal 5 | from 6 | ( 7 | select 8 | substring(c_phone, 1, 2) as cntrycode, 9 | c_acctbal 10 | from 11 | customer 12 | where 13 | substring(c_phone, 1, 2) in ('13', '31', '23', '29', '30', '18', '17') 14 | and c_acctbal > ( 15 | select 16 | avg(c_acctbal) 17 | from 18 | customer 19 | where 20 | c_acctbal > 0.00 21 | and substring(c_phone, 1, 2) in ('13', '31', '23', '29', '30', '18', '17') 22 | ) 23 | and not exists ( 24 | select 25 | * 26 | from 27 | orders 28 | where 29 | o_custkey = c_custkey 30 | ) 31 | ) as custsale 32 | group by 33 | cntrycode 34 | order by 35 | cntrycode; 36 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "target": "es2020", 5 | "module": "es2020", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "sourceMap": false, 9 | "declaration": true, 10 | "declarationMap": false, 11 | "declarationDir": "./dist/types/", 12 | "noImplicitAny": true, 13 | "esModuleInterop": true, 14 | "downlevelIteration": true, 15 | "resolveJsonModule": true, 16 | "skipLibCheck": true, 17 | 18 | "types": ["emscripten", "node", "jasmine"], 19 | "typeRoots": ["./types", "./node_modules/@types", "../../node_modules/@types"], 20 | "lib": ["es6", "webworker", "dom"] 21 | }, 22 | "exclude": ["./node_modules"], 23 | "include": ["./src/**/*", "./test/**/*", "./types/*.d.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/static/fonts/fonts.module.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------- */ 2 | 3 | @font-face { 4 | font-family: 'Nunito'; 5 | font-style: normal; 6 | font-weight: 300; 7 | src: url(./Nunito-Light.ttf) format('truetype'); 8 | } 9 | 10 | @font-face { 11 | font-family: 'Nunito'; 12 | font-style: normal; 13 | font-weight: 400; 14 | src: url(./Nunito-Regular.ttf) format('truetype'); 15 | } 16 | 17 | @font-face { 18 | font-family: 'Nunito'; 19 | font-style: normal; 20 | font-weight: 500; 21 | src: url(./Nunito-SemiBold.ttf) format('truetype'); 22 | } 23 | 24 | @font-face { 25 | font-family: 'Nunito'; 26 | font-style: normal; 27 | font-weight: 700; 28 | src: url(./Nunito-Bold.ttf) format('truetype'); 29 | } 30 | 31 | /* -------------------------------------------------------------------- */ 32 | -------------------------------------------------------------------------------- /lib/test/tester.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "duckdb/web/test/config.h" 5 | #include "gflags/gflags.h" 6 | #include "gtest/gtest.h" 7 | 8 | using namespace duckdb::web::test; 9 | 10 | DEFINE_string(source_dir, "", "Source directory"); 11 | 12 | namespace duckdb { 13 | namespace web { 14 | namespace test { 15 | 16 | std::filesystem::path SOURCE_DIR; 17 | 18 | } 19 | } // namespace web 20 | } // namespace duckdb 21 | 22 | int main(int argc, char* argv[]) { 23 | gflags::AllowCommandLineReparsing(); 24 | gflags::SetUsageMessage("Usage: ./tester --source_dir "); 25 | gflags::ParseCommandLineFlags(&argc, &argv, false); 26 | 27 | if (std::filesystem::exists(FLAGS_source_dir)) { 28 | SOURCE_DIR = std::filesystem::path{FLAGS_source_dir}; 29 | } 30 | 31 | testing::InitGoogleTest(&argc, argv); 32 | return RUN_ALL_TESTS(); 33 | } 34 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./src", 4 | "outDir": "./build/ts/", 5 | "target": "es5", 6 | "module": "es2020", 7 | // TODO(ankoh): Upgrade node resolution to node12 for exports once typescript 4.6.0 is out 8 | // https://www.typescriptlang.org/docs/handbook/esm-node.html 9 | "moduleResolution": "node", 10 | "sourceMap": true, 11 | "noImplicitAny": true, 12 | "esModuleInterop": true, 13 | "downlevelIteration": true, 14 | "strict": true, 15 | "jsx": "react", 16 | "types": ["emscripten", "node", "jasmine"], 17 | "plugins": [{ "name": "typescript-plugin-css-modules" }], 18 | "lib": ["es6", "es2020", "dom"] 19 | }, 20 | "exclude": ["./node_modules"], 21 | "include": ["./src/**/*", "./test/**/*", "./types/*.d.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "target": "es2020", 5 | "module": "es2020", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "sourceMap": false, 9 | "declaration": true, 10 | "declarationMap": false, 11 | "declarationDir": "./dist/types/", 12 | "noImplicitAny": true, 13 | "esModuleInterop": true, 14 | "downlevelIteration": true, 15 | "resolveJsonModule": true, 16 | "skipLibCheck": true, 17 | 18 | "types": ["emscripten", "node", "jasmine"], 19 | "typeRoots": ["./types", "./node_modules/@types", "../../node_modules/@types"], 20 | "lib": ["es6", "webworker", "dom"] 21 | }, 22 | "include": [".eslintrc.js", "./src/**/*", "./types/*.d.ts", "./test/**/*"], 23 | "exclude": ["./test/node/**/*"] 24 | } 25 | -------------------------------------------------------------------------------- /scripts/format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 5 | 6 | PRETTIER_WRITE_MODE="--check" 7 | CLANG_FORMAT_WRITE_MODE="--dry-run -Werror" 8 | 9 | if [ -z "${1:-}" ] || [ ! "$1" = "check" ]; then 10 | PRETTIER_WRITE_MODE="--write" 11 | CLANG_FORMAT_WRITE_MODE="-i" 12 | fi 13 | 14 | npx prettier \ 15 | $PRETTIER_WRITE_MODE \ 16 | "$PROJECT_ROOT/**/*.{js,json,ts,tsx,d.ts,css}" \ 17 | --config "$PROJECT_ROOT/.prettierrc" \ 18 | --ignore-path "$PROJECT_ROOT/.prettierignore" 19 | 20 | find -E $PROJECT_ROOT \ 21 | -regex '.*/(\..*|submodules|node_modules|install|build)/.*' -prune -o \ 22 | -regex "$PROJECT_ROOT/proto/.*" -prune -o \ 23 | -regex '.*\.(cc|h)' \ 24 | -exec echo clang-format $CLANG_FORMAT_WRITE_MODE {} \; \ 25 | -exec clang-format $CLANG_FORMAT_WRITE_MODE {} \; 26 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/21.sql: -------------------------------------------------------------------------------- 1 | select 2 | s_name, 3 | count(*) as numwait 4 | from 5 | supplier, 6 | lineitem l1, 7 | orders, 8 | nation 9 | where 10 | s_suppkey = l1.l_suppkey 11 | and o_orderkey = l1.l_orderkey 12 | and o_orderstatus = 'F' 13 | and l1.l_receiptdate > l1.l_commitdate 14 | and exists ( 15 | select 16 | * 17 | from 18 | lineitem l2 19 | where 20 | l2.l_orderkey = l1.l_orderkey 21 | and l2.l_suppkey <> l1.l_suppkey 22 | ) 23 | and not exists ( 24 | select 25 | * 26 | from 27 | lineitem l3 28 | where 29 | l3.l_orderkey = l1.l_orderkey 30 | and l3.l_suppkey <> l1.l_suppkey 31 | and l3.l_receiptdate > l3.l_commitdate 32 | ) 33 | and s_nationkey = n_nationkey 34 | and n_name = 'SAUDI ARABIA' 35 | group by 36 | s_name 37 | order by 38 | numwait desc, 39 | s_name 40 | limit 41 | 100; 42 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/webpack.tests.js: -------------------------------------------------------------------------------- 1 | import { configure } from './webpack.common.js'; 2 | import { fileURLToPath } from 'url'; 3 | import path from 'path'; 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 6 | const buildDir = path.resolve(__dirname, './build/tests'); 7 | 8 | const base = configure({ 9 | buildDir: buildDir, 10 | extractCss: false, 11 | cssIdentifier: '[hash:base64]', 12 | }); 13 | 14 | export default { 15 | ...base, 16 | entry: { 17 | tests: ['./test/index.ts'], 18 | }, 19 | output: { 20 | path: buildDir, 21 | filename: '[name].js', 22 | chunkFilename: 'static/js/[name].[contenthash].js', 23 | assetModuleFilename: 'static/assets/[name].[contenthash].[ext]', 24 | webassemblyModuleFilename: 'static/wasm/[hash].wasm', 25 | clean: true, 26 | }, 27 | mode: 'development', 28 | devtool: false, 29 | }; 30 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/9-sqlite.sql: -------------------------------------------------------------------------------- 1 | select 2 | nation, 3 | o_year, 4 | sum(amount) as sum_profit 5 | from 6 | ( 7 | select 8 | n_name as nation, 9 | strftime('%Y', o_orderdate) as o_year, 10 | l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount 11 | from 12 | part, 13 | supplier, 14 | lineitem, 15 | partsupp, 16 | orders, 17 | nation 18 | where 19 | s_suppkey = l_suppkey 20 | and ps_suppkey = l_suppkey 21 | and ps_partkey = l_partkey 22 | and p_partkey = l_partkey 23 | and o_orderkey = l_orderkey 24 | and s_nationkey = n_nationkey 25 | and p_name like '%green%' 26 | ) as profit 27 | group by 28 | nation, 29 | o_year 30 | order by 31 | nation, 32 | o_year desc; 33 | -------------------------------------------------------------------------------- /lib/test/bugs_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "duckdb/common/types/date.hpp" 5 | #include "duckdb/common/types/timestamp.hpp" 6 | #include "duckdb/web/environment.h" 7 | #include "duckdb/web/io/ifstream.h" 8 | #include "duckdb/web/io/memory_filesystem.h" 9 | #include "duckdb/web/test/config.h" 10 | #include "duckdb/web/webdb.h" 11 | #include "gtest/gtest.h" 12 | 13 | using namespace duckdb::web; 14 | using namespace std; 15 | 16 | namespace { 17 | 18 | // https://github.com/duckdb/duckdb-wasm/issues/234 19 | TEST(Bugs, DISABLED_Decimals) { 20 | auto db = make_shared(NATIVE); 21 | WebDB::Connection conn{*db}; 22 | auto buffer = conn.RunQuery("SELECT 1::DECIMAL(2,1);"); 23 | ASSERT_TRUE(buffer.ok()) << buffer.status().message(); 24 | buffer = conn.RunQuery("SELECT 1::DECIMAL(2,0);"); 25 | ASSERT_TRUE(buffer.ok()) << buffer.status().message(); 26 | } 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /misc/duckdb_wasm.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/12.sql: -------------------------------------------------------------------------------- 1 | select 2 | l_shipmode, 3 | cast( 4 | sum( 5 | case 6 | when o_orderpriority = '1-URGENT' 7 | or o_orderpriority = '2-HIGH' then 1 8 | else 0 9 | end 10 | ) as integer 11 | ) as high_line_count, 12 | cast( 13 | sum( 14 | case 15 | when o_orderpriority <> '1-URGENT' 16 | and o_orderpriority <> '2-HIGH' then 1 17 | else 0 18 | end 19 | ) as integer 20 | ) as low_line_count 21 | from 22 | orders, 23 | lineitem 24 | where 25 | o_orderkey = l_orderkey 26 | and l_shipmode in ('MAIL', 'SHIP') 27 | and l_commitdate < l_receiptdate 28 | and l_shipdate < l_commitdate 29 | and l_receiptdate >= '1994-01-01' 30 | and l_receiptdate < '1995-01-01' 31 | group by 32 | l_shipmode 33 | order by 34 | l_shipmode; 35 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/json_dataview.h: -------------------------------------------------------------------------------- 1 | #define RAPIDJSON_HAS_STDSTRING 1 2 | 3 | #ifndef INCLUDE_DUCKDB_WEB_JSON_DATAVIEW_H_ 4 | #define INCLUDE_DUCKDB_WEB_JSON_DATAVIEW_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "arrow/type.h" 11 | #include "arrow/type_fwd.h" 12 | #include "duckdb/web/json_analyzer.h" 13 | #include "duckdb/web/json_parser.h" 14 | #include "rapidjson/document.h" 15 | 16 | namespace duckdb { 17 | namespace web { 18 | namespace json { 19 | 20 | typedef vector> additional_buffers_t; 21 | 22 | /// Serialize a DuckDB Vector as JSON data view 23 | arrow::Result CreateDataView(rapidjson::Document& doc, duckdb::DataChunk& chunk, 24 | std::vector& data_ptrs, additional_buffers_t& buffers); 25 | 26 | } // namespace json 27 | } // namespace web 28 | } // namespace duckdb 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /misc/duckdb_wasm_light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/15.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | s_suppkey, 3 | s_name, 4 | s_address, 5 | s_phone, 6 | total_revenue 7 | FROM 8 | supplier, 9 | ( 10 | SELECT 11 | l_suppkey AS supplier_no, 12 | sum(l_extendedprice * (1 - l_discount)) AS total_revenue 13 | FROM 14 | lineitem 15 | WHERE 16 | l_shipdate >= '1996-01-01' 17 | AND l_shipdate < '1996-04-01' 18 | GROUP BY 19 | supplier_no 20 | ) revenue0 21 | WHERE 22 | s_suppkey = supplier_no 23 | AND total_revenue = ( 24 | SELECT 25 | max(total_revenue) 26 | FROM 27 | ( 28 | SELECT 29 | l_suppkey AS supplier_no, 30 | sum(l_extendedprice * (1 - l_discount)) AS total_revenue 31 | FROM 32 | lineitem 33 | WHERE 34 | l_shipdate >= '1996-01-01' 35 | AND l_shipdate < '1996-04-01' 36 | GROUP BY 37 | supplier_no 38 | ) revenue1 39 | ) 40 | ORDER BY 41 | s_suppkey; 42 | -------------------------------------------------------------------------------- /packages/benchmarks/src/suite_internal.ts: -------------------------------------------------------------------------------- 1 | import { benchmarkUDF, benchmarkFormat, benchmarkIterator, benchmarkIteratorAsync } from './internal'; 2 | import { runBenchmarks } from './suite'; 3 | import { Benchmark } from 'buffalo-bench'; 4 | import { setupDuckDBAsync, setupDuckDBSync, writeReport } from './setup'; 5 | 6 | async function main() { 7 | const duckdbSync = await setupDuckDBSync(); 8 | const duckdbAsync = await setupDuckDBAsync(); 9 | 10 | let suite: Benchmark[] = []; 11 | suite = suite.concat(benchmarkUDF(() => duckdbSync!)); 12 | suite = suite.concat(benchmarkFormat(() => duckdbSync!)); 13 | suite = suite.concat(benchmarkFormat(() => duckdbSync!)); 14 | suite = suite.concat(benchmarkIterator(() => duckdbSync!)); 15 | suite = suite.concat(benchmarkIteratorAsync(() => duckdbAsync!)); 16 | const results = await runBenchmarks(suite); 17 | console.log(results); 18 | await writeReport(results, './benchmark_internal.json'); 19 | } 20 | 21 | main(); 22 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/9.sql: -------------------------------------------------------------------------------- 1 | select 2 | nation, 3 | o_year, 4 | sum(amount) as sum_profit 5 | from 6 | ( 7 | select 8 | n_name as nation, 9 | extract( 10 | year 11 | from 12 | o_orderdate 13 | ) as o_year, 14 | l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount 15 | from 16 | part, 17 | supplier, 18 | lineitem, 19 | partsupp, 20 | orders, 21 | nation 22 | where 23 | s_suppkey = l_suppkey 24 | and ps_suppkey = l_suppkey 25 | and ps_partkey = l_partkey 26 | and p_partkey = l_partkey 27 | and o_orderkey = l_orderkey 28 | and s_nationkey = n_nationkey 29 | and p_name like '%green%' 30 | ) as profit 31 | group by 32 | nation, 33 | o_year 34 | order by 35 | nation, 36 | o_year desc; 37 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/utils/shared_mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_SHARED_MUTEX_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_SHARED_MUTEX_H_ 3 | 4 | #include 5 | 6 | namespace duckdb { 7 | namespace web { 8 | 9 | class SharedMutex { 10 | protected: 11 | /// The lock data 12 | std::atomic data; 13 | /// Tries to mark the lock as waiting either as reader or writer 14 | bool tryMarkAsWaiting(bool writer); 15 | 16 | public: 17 | /// Constructor 18 | SharedMutex() : data{0} {} 19 | /// Deleted copy constructor 20 | SharedMutex(const SharedMutex&) = delete; 21 | 22 | /// Try to lock shared 23 | bool try_lock_shared(); 24 | /// Try to lock exclusively 25 | bool try_lock(); 26 | /// Lock 27 | void lock(); 28 | /// Lock shared 29 | void lock_shared(); 30 | /// Unlock 31 | void unlock(); 32 | /// Unlock shared 33 | void unlock_shared(); 34 | }; 35 | 36 | } // namespace web 37 | } // namespace duckdb 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/versus.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | width: 100%; 3 | height: 100%; 4 | background-color: rgb(230, 230, 230); 5 | 6 | overflow-y: auto; 7 | } 8 | 9 | .root_spinner { 10 | width: 100%; 11 | height: 100%; 12 | background-color: rgb(230, 230, 230); 13 | 14 | display: grid; 15 | align-items: center; 16 | justify-content: center; 17 | } 18 | 19 | .content { 20 | padding: 8px 0px; 21 | } 22 | 23 | .tldr { 24 | font-style: italic; 25 | text-align: justify; 26 | padding: 4px 4px; 27 | } 28 | 29 | .header2 { 30 | margin-bottom: 16px; 31 | } 32 | 33 | .link { 34 | margin-left: 4px; 35 | margin-right: 4px; 36 | } 37 | 38 | .section_text { 39 | padding: 0px 4px; 40 | text-align: justify; 41 | margin-bottom: 8px !important; 42 | } 43 | 44 | .feature_table { 45 | margin: 24px 0px 32px 0px; 46 | } 47 | 48 | .tpch_table { 49 | margin: 16px 0px; 50 | } 51 | 52 | .micro_table { 53 | margin: 24px 0px 24px 0px; 54 | } 55 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/io/glob.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_GLOB_H_ 2 | #define INCLUDE_DUCKDB_WEB_GLOB_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace duckdb { 9 | namespace web { 10 | namespace io { 11 | 12 | struct GlobToRegexOptions { 13 | /// Enables "extended" globs (like bash) which 14 | /// supports single character matching, matching ranges of characters, 15 | /// group matching, etc. 16 | bool extended = false; 17 | /// glob_star determines whether a star should match trailing paths 18 | /// '/foo/*' => '^\/foo\/.*$' vs. '^\/foo\/[^/]*$' 19 | /// true false 20 | bool glob_star = false; 21 | /// Case insensitive matching 22 | bool case_insensitive = false; 23 | /// Match anywhere in the string? 24 | bool global = false; 25 | }; 26 | 27 | std::regex glob_to_regex(std::string_view glob, GlobToRegexOptions options = {}); 28 | 29 | } // namespace io 30 | } // namespace web 31 | } // namespace duckdb 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /lib/test/ifstream_test.cc: -------------------------------------------------------------------------------- 1 | #include "duckdb/web/io/ifstream.h" 2 | 3 | #include 4 | 5 | #include "duckdb/web/test/config.h" 6 | #include "gtest/gtest.h" 7 | 8 | using namespace duckdb::web; 9 | using namespace std; 10 | 11 | namespace { 12 | 13 | TEST(InputStreamBuffer, istreambuf_iterator) { 14 | auto fs = duckdb::FileSystem::CreateLocal(); 15 | auto file_page_buffer = std::make_shared(std::move(fs)); 16 | auto path = duckdb::web::test::SOURCE_DIR / ".." / "data" / "test.json"; 17 | std::string expected; 18 | std::string have; 19 | { 20 | std::ifstream ifs{path}; 21 | expected = {std::istreambuf_iterator{ifs}, std::istreambuf_iterator{}}; 22 | } 23 | auto input = std::make_shared(file_page_buffer, path.c_str()); 24 | { 25 | std::istream ifs{input.get()}; 26 | have = {std::istreambuf_iterator{ifs}, std::istreambuf_iterator{}}; 27 | } 28 | ASSERT_EQ(expected, have); 29 | } 30 | 31 | } // namespace 32 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/utils/parallel.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_MUTEX_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_MUTEX_H_ 3 | 4 | #ifdef DUCKDB_NO_THREADS 5 | 6 | namespace duckdb { 7 | namespace web { 8 | 9 | // A pseudo mutex that does nothing. 10 | // We use this for single-threaded versions of duckdb-wasm. 11 | struct PseudoMutex { 12 | void lock() {} 13 | void lock_shared() {} 14 | void unlock() {} 15 | void unlock_shared() {} 16 | bool try_lock() { return true; } 17 | bool try_lock_shared() { return true; } 18 | }; 19 | using SharedMutex = PseudoMutex; 20 | using LightMutex = PseudoMutex; 21 | 22 | } // namespace web 23 | } // namespace duckdb 24 | 25 | #else 26 | 27 | // #include "duckdb/web/utils/shared_mutex.h" 28 | #include 29 | 30 | #include "duckdb/web/utils/spin_mutex.h" 31 | 32 | namespace duckdb { 33 | namespace web { 34 | 35 | using SharedMutex = std::shared_mutex; 36 | using LightMutex = SpinMutex; 37 | 38 | } // namespace web 39 | } // namespace duckdb 40 | 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/22.sql: -------------------------------------------------------------------------------- 1 | select 2 | cntrycode, 3 | count(*) as numcust, 4 | sum(c_acctbal) as totacctbal 5 | from 6 | ( 7 | select 8 | substring( 9 | c_phone 10 | from 11 | 1 for 2 12 | ) as cntrycode, 13 | c_acctbal 14 | from 15 | customer 16 | where 17 | substring( 18 | c_phone 19 | from 20 | 1 for 2 21 | ) in ('13', '31', '23', '29', '30', '18', '17') 22 | and c_acctbal > ( 23 | select 24 | avg(c_acctbal) 25 | from 26 | customer 27 | where 28 | c_acctbal > 0.00 29 | and substring( 30 | c_phone 31 | from 32 | 1 for 2 33 | ) in ('13', '31', '23', '29', '30', '18', '17') 34 | ) 35 | and not exists ( 36 | select 37 | * 38 | from 39 | orders 40 | where 41 | o_custkey = c_custkey 42 | ) 43 | ) as custsale 44 | group by 45 | cntrycode 46 | order by 47 | cntrycode; 48 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/bindings_browser_mvp.ts: -------------------------------------------------------------------------------- 1 | import DuckDBWasm from './duckdb-mvp.js'; 2 | import { DuckDBBrowserBindings } from './bindings_browser_base'; 3 | import { DuckDBModule } from './duckdb_module'; 4 | import { DuckDBRuntime } from './runtime'; 5 | import { Logger } from '../log'; 6 | 7 | /** DuckDB bindings for the browser */ 8 | export class DuckDB extends DuckDBBrowserBindings { 9 | /** Constructor */ 10 | public constructor( 11 | logger: Logger, 12 | runtime: DuckDBRuntime, 13 | mainModuleURL: string, 14 | pthreadWorkerURL: string | null = null, 15 | ) { 16 | super(logger, runtime, mainModuleURL, pthreadWorkerURL); 17 | } 18 | 19 | /** Instantiate the bindings */ 20 | protected instantiateImpl(moduleOverrides: Partial): Promise { 21 | return DuckDBWasm({ 22 | ...moduleOverrides, 23 | instantiateWasm: this.instantiateWasm.bind(this), 24 | locateFile: this.locateFile.bind(this), 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018-2025 Stichting DuckDB Foundation 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/2.sql: -------------------------------------------------------------------------------- 1 | select 2 | s_acctbal, 3 | s_name, 4 | n_name, 5 | p_partkey, 6 | p_mfgr, 7 | s_address, 8 | s_phone, 9 | s_comment 10 | from 11 | part, 12 | supplier, 13 | partsupp, 14 | nation, 15 | region 16 | where 17 | p_partkey = ps_partkey 18 | and s_suppkey = ps_suppkey 19 | and p_size = 15 20 | and p_type like '%BRASS' 21 | and s_nationkey = n_nationkey 22 | and n_regionkey = r_regionkey 23 | and r_name = 'EUROPE' 24 | and ps_supplycost = ( 25 | select 26 | min(ps_supplycost) 27 | from 28 | partsupp, 29 | supplier, 30 | nation, 31 | region 32 | where 33 | p_partkey = ps_partkey 34 | and s_suppkey = ps_suppkey 35 | and s_nationkey = n_nationkey 36 | and n_regionkey = r_regionkey 37 | and r_name = 'EUROPE' 38 | ) 39 | order by 40 | s_acctbal desc, 41 | n_name, 42 | s_name, 43 | p_partkey 44 | limit 45 | 100; 46 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/duckdb/web_file.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Serialize, Deserialize, Debug)] 4 | #[repr(u8)] 5 | pub enum DataProtocol { 6 | Buffer = 0, 7 | Native = 1, 8 | Http = 2, 9 | } 10 | 11 | #[derive(Serialize, Deserialize, Debug, Default)] 12 | pub struct WebFile { 13 | #[serde(rename = "fileName")] 14 | pub file_name: String, 15 | #[serde(rename = "fileId")] 16 | pub file_id: Option, 17 | #[serde(rename = "fileSize")] 18 | pub file_size: Option, 19 | #[serde(rename = "dataProtocol")] 20 | pub data_protocol: Option, 21 | #[serde(rename = "dataUrl")] 22 | pub data_url: Option, 23 | #[serde(rename = "dataNativeFd")] 24 | pub data_native_fd: Option, 25 | #[serde(rename = "reliableHeadRequests")] 26 | pub reliable_head_requests: Option, 27 | #[serde(rename = "allowFullHttpReads")] 28 | pub allow_full_http_reads: Option, 29 | #[serde(rename = "collectStatistics")] 30 | pub collect_statistics: Option, 31 | } 32 | -------------------------------------------------------------------------------- /scripts/generate_tpch_duckdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | trap exit SIGINT 6 | 7 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 8 | DUCKDB_DIR="${PROJECT_ROOT}/submodules/duckdb/" 9 | DUCKDB_BUILD_DIR="${DUCKDB_DIR}/build/Release" 10 | DUCKDB_SHELL="duckdb" 11 | SCALE_FACTOR=${1:-0.01} 12 | SCALE_FACTOR_DIR=${SCALE_FACTOR/./_} 13 | TPCH_DIR=${PROJECT_ROOT}/data/tpch 14 | TPCH_SF_OUT=${TPCH_DIR}/${SCALE_FACTOR_DIR} 15 | TPCH_SF_OUT_DUCKDB=${TPCH_SF_OUT}/duckdb 16 | TPCH_SF_OUT_DUCKDB_DB=${TPCH_SF_OUT_DUCKDB}/db 17 | DUCKDB_SCRIPT_FILE=${TPCH_SF_OUT_DUCKDB}/script.sql 18 | 19 | chmod +x ${DUCKDB_SHELL} 20 | mkdir -p ${TPCH_SF_OUT_DUCKDB} 21 | rm -r ${TPCH_SF_OUT_DUCKDB} 22 | mkdir -p ${TPCH_SF_OUT_DUCKDB} 23 | 24 | cat << END >${DUCKDB_SCRIPT_FILE} 25 | .open ${TPCH_SF_OUT_DUCKDB_DB} 26 | install tpch; 27 | load tpch; 28 | call dbgen(sf = ${SCALE_FACTOR}); 29 | checkpoint; 30 | .databases 31 | .tables 32 | END 33 | ${DUCKDB_BUILD_DIR}/duckdb --echo < ${DUCKDB_SCRIPT_FILE} 34 | echo "TPCH_SF_OUT_DUCKDB=${TPCH_SF_OUT_DUCKDB}/db" 35 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Main](https://github.com/duckdb/duckdb-wasm/actions/workflows/main.yml/badge.svg)](https://github.com/duckdb/duckdb-wasm/actions/workflows/main.yml) 4 | [![Benchmarks](https://github.com/duckdb/duckdb-wasm/actions/workflows/benchmarks.yml/badge.svg)](https://github.com/duckdb/duckdb-wasm/actions/workflows/benchmarks.yml) 5 | [![duckdb](https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm@latest/dist/img/duckdb_version_badge.svg)](https://github.com/duckdb/duckdb) 6 | [![npm](https://img.shields.io/npm/v/@duckdb/duckdb-wasm?logo=npm)](https://www.npmjs.com/package/@duckdb/duckdb-wasm-shell/v/latest) 7 | [![JSDevlivr](https://data.jsdelivr.com/v1/package/npm/@duckdb/duckdb-wasm-shell/badge?style=rounded)](https://www.jsdelivr.com/package/npm/@duckdb/duckdb-wasm-shell) 8 | 9 | **DuckDB-Wasm Shell** 10 | 11 | This library contains an embeddable standalone web shell for **@duckdb/duckdb-wasm**. Try it out at [shell.duckdb.org](https://shell.duckdb.org). 12 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/bindings_node_eh.ts: -------------------------------------------------------------------------------- 1 | import DuckDBWasm from './duckdb-eh.js'; 2 | import { DuckDBModule } from './duckdb_module'; 3 | import { DuckDBNodeBindings } from './bindings_node_base.js'; 4 | import { DuckDBRuntime } from './runtime'; 5 | import { Logger } from '../log'; 6 | 7 | /** DuckDB bindings for node.js */ 8 | export class DuckDB extends DuckDBNodeBindings { 9 | /** Constructor */ 10 | public constructor( 11 | logger: Logger, 12 | runtime: DuckDBRuntime, 13 | mainModulePath: string, 14 | pthreadWorkerPath: string | null = null, 15 | ) { 16 | super(logger, runtime, mainModulePath, pthreadWorkerPath); 17 | } 18 | 19 | /** Instantiate the bindings */ 20 | protected instantiateImpl(moduleOverrides: Partial): Promise { 21 | return DuckDBWasm({ 22 | ...moduleOverrides, 23 | instantiateWasm: this.instantiateWasm.bind(this), 24 | locateFile: this.locateFile.bind(this), 25 | }); 26 | } 27 | } 28 | 29 | export default DuckDB; 30 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/bindings_node_mvp.ts: -------------------------------------------------------------------------------- 1 | import DuckDBWasm from './duckdb-mvp.js'; 2 | import { DuckDBNodeBindings } from './bindings_node_base.js'; 3 | import { Logger } from '../log.js'; 4 | import { DuckDBModule } from './duckdb_module'; 5 | import { DuckDBRuntime } from './runtime'; 6 | 7 | /** DuckDB bindings for node.js */ 8 | export class DuckDB extends DuckDBNodeBindings { 9 | /** Constructor */ 10 | public constructor( 11 | logger: Logger, 12 | runtime: DuckDBRuntime, 13 | mainModulePath: string, 14 | pthreadWorkerPath: string | null = null, 15 | ) { 16 | super(logger, runtime, mainModulePath, pthreadWorkerPath); 17 | } 18 | 19 | /** Instantiate the bindings */ 20 | protected instantiateImpl(moduleOverrides: Partial): Promise { 21 | return DuckDBWasm({ 22 | ...moduleOverrides, 23 | instantiateWasm: this.instantiateWasm.bind(this), 24 | locateFile: this.locateFile.bind(this), 25 | }); 26 | } 27 | } 28 | 29 | export default DuckDB; 30 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/bindings_browser_coi.ts: -------------------------------------------------------------------------------- 1 | import DuckDBWasm from './duckdb-coi.js'; 2 | import { DuckDBBrowserBindings } from './bindings_browser_base'; 3 | import { DuckDBModule } from './duckdb_module'; 4 | import { DuckDBRuntime } from './runtime'; 5 | import { Logger } from '../log'; 6 | 7 | /** DuckDB bindings for the browser */ 8 | export class DuckDB extends DuckDBBrowserBindings { 9 | /** Constructor */ 10 | public constructor( 11 | logger: Logger, 12 | runtime: DuckDBRuntime, 13 | mainModuleURL: string, 14 | pthreadWorkerURL: string | null = null, 15 | ) { 16 | super(logger, runtime, mainModuleURL, pthreadWorkerURL); 17 | } 18 | 19 | /** Instantiate the bindings */ 20 | protected instantiateImpl(moduleOverrides: Partial): Promise { 21 | return DuckDBWasm({ 22 | ...moduleOverrides, 23 | instantiateWasm: this.instantiateWasm.bind(this), 24 | locateFile: this.locateFile.bind(this), 25 | }); 26 | } 27 | } 28 | 29 | export default DuckDB; 30 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/bindings_browser_eh.ts: -------------------------------------------------------------------------------- 1 | import DuckDBWasm from './duckdb-eh.js'; 2 | import { DuckDBBrowserBindings } from './bindings_browser_base'; 3 | import { DuckDBModule } from './duckdb_module'; 4 | import { DuckDBRuntime } from './runtime'; 5 | import { Logger } from '../log'; 6 | 7 | /** DuckDB bindings for the browser */ 8 | export class DuckDB extends DuckDBBrowserBindings { 9 | /** Constructor */ 10 | public constructor( 11 | logger: Logger, 12 | runtime: DuckDBRuntime, 13 | mainModuleURL: string, 14 | pthreadWorkerURL: string | null = null, 15 | ) { 16 | super(logger, runtime, mainModuleURL, pthreadWorkerURL); 17 | } 18 | 19 | /** Instantiate the bindings */ 20 | protected instantiateImpl(moduleOverrides: Partial): Promise { 21 | return DuckDBWasm({ 22 | ...moduleOverrides, 23 | instantiateWasm: this.instantiateWasm.bind(this), 24 | locateFile: this.locateFile.bind(this), 25 | }); 26 | } 27 | } 28 | 29 | export default DuckDB; 30 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/table_test.ts: -------------------------------------------------------------------------------- 1 | import * as arrow from 'apache-arrow'; 2 | 3 | export interface Column { 4 | name: string; 5 | values: any[]; 6 | } 7 | 8 | export function compareTable(table: arrow.Table, expected: Column[]): void { 9 | // Check column count 10 | const colCount = expected.length; 11 | expect(table.numCols).toEqual(colCount); 12 | if (colCount == 0) return; 13 | 14 | // Check columns 15 | const rowCount = expected[0].values.length; 16 | for (let i = 0; i < colCount; ++i) { 17 | expect(expected[i].values.length).toEqual(rowCount); 18 | expect(table.getChildAt(i)?.length).toEqual(rowCount); 19 | expect(table.schema.fields[i]?.name).toEqual(expected[i].name); 20 | } 21 | 22 | // Compare the actual values 23 | for (let i = 0; i < colCount; ++i) { 24 | const col = table.getChildAt(i)!; 25 | const have = []; 26 | for (let j = 0; j < rowCount; ++j) { 27 | have.push(col.get(j)); 28 | } 29 | expect(Number(have)).toEqual(Number(expected[i].values)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/benchmarks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/build/", 4 | "target": "ES2020", 5 | "module": "ES2020", 6 | // TODO(ankoh): Upgrade node resolution to node12 for exports once typescript 4.6.0 is out 7 | // https://www.typescriptlang.org/docs/handbook/esm-node.html 8 | "moduleResolution": "node", 9 | "strict": true, 10 | "sourceMap": true, 11 | "noImplicitAny": true, 12 | "esModuleInterop": true, 13 | "downlevelIteration": true, 14 | "allowJs": true, 15 | "allowSyntheticDefaultImports": true, 16 | "resolveJsonModule": true, 17 | 18 | // Insanity mode due to: 19 | // https://issues.apache.org/jira/browse/ARROW-10794 20 | "skipLibCheck": true, 21 | 22 | "lib": ["ESNext.Array", "DOM", "DOM.Iterable", "es6", "webworker"], 23 | "types": ["emscripten", "node"], 24 | "baseUrl": "." 25 | }, 26 | "include": ["./src/**/*.ts", "./types/**/*.ts"], 27 | "exclude": ["./node_modules/*", "../../node_modules/*"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/bindings/insert_options.ts: -------------------------------------------------------------------------------- 1 | import * as arrow from 'apache-arrow'; 2 | import { SQLField } from '../json_typedef'; 3 | 4 | export enum JSONTableShape { 5 | ROW_ARRAY = 'row-array', 6 | COLUMN_OBJECT = 'column-object', 7 | } 8 | 9 | export interface JSONInsertOptions { 10 | name: string; 11 | schema?: string; 12 | create?: boolean; 13 | shape?: JSONTableShape; 14 | columns?: { 15 | [key: string]: arrow.DataType; 16 | }; 17 | columnsFlat?: SQLField[]; 18 | } 19 | 20 | export interface CSVInsertOptions { 21 | name: string; 22 | schema?: string; 23 | create?: boolean; 24 | header?: boolean; 25 | delimiter?: string; 26 | quote?: string; 27 | escape?: string; 28 | skip?: number; 29 | detect?: boolean; 30 | dateFormat?: string; 31 | timestampFormat?: string; 32 | columns?: { 33 | [key: string]: arrow.DataType; 34 | }; 35 | columnsFlat?: SQLField[]; 36 | } 37 | 38 | export interface ArrowInsertOptions { 39 | name: string; 40 | schema?: string; 41 | create?: boolean; 42 | } 43 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/functions/table_function_relation.h: -------------------------------------------------------------------------------- 1 | #include "duckdb/common/unordered_map.hpp" 2 | #include "duckdb/main/relation.hpp" 3 | #include "unordered_map" 4 | 5 | namespace duckdb { 6 | namespace web { 7 | 8 | class TableFunctionRelation : public Relation { 9 | public: 10 | TableFunctionRelation(const duckdb::shared_ptr &context, string name, 11 | vector unnamed_parameters, unordered_map named_parameters, 12 | shared_ptr input_relation_p = nullptr); 13 | 14 | string name; 15 | vector unnamed_parameters; 16 | unordered_map named_parameters; 17 | vector columns; 18 | shared_ptr input_relation; 19 | 20 | public: 21 | unique_ptr GetQueryNode() override; 22 | unique_ptr GetTableRef() override; 23 | 24 | const vector &Columns() override; 25 | string ToString(idx_t depth) override; 26 | string GetAlias() override; 27 | }; 28 | 29 | } // namespace web 30 | } // namespace duckdb 31 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/utils/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_DEBUG_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_DEBUG_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "duckdb/web/utils/scope_guard.h" 8 | 9 | namespace duckdb { 10 | namespace web { 11 | 12 | #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) 13 | 14 | #define MANUAL_DEBUG_TRACE() \ 15 | auto FILE_NAME_ = __FILENAME__; \ 16 | auto FUNC_NAME_ = __FUNCTION__; \ 17 | std::cout << "[ ENTER ] " << FILE_NAME_ << " " << FUNC_NAME_ << std::endl; \ 18 | auto leave_func = sg::make_scope_guard( \ 19 | [FILE_NAME_, FUNC_NAME_]() { std::cout << "[ EXIT ] " << FILE_NAME_ << " " << FUNC_NAME_ << std::endl; }); 20 | 21 | #ifdef WITH_DEBUG_TRACE 22 | #define DEBUG_TRACE() MANUAL_DEBUG_TRACE(); 23 | #else 24 | #define DEBUG_TRACE() 25 | #endif 26 | 27 | } // namespace web 28 | } // namespace duckdb 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/pages/table.module.css: -------------------------------------------------------------------------------- 1 | .table_page { 2 | background-color: #333; 3 | width: 100%; 4 | height: 100%; 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | } 9 | 10 | .selector_container { 11 | width: 90%; 12 | max-width: 800px; 13 | background-color: rgb(200, 200, 200); 14 | min-height: 300px; 15 | border-radius: var(--border_radius); 16 | 17 | display: grid; 18 | grid-template-rows: max-content auto; 19 | grid-template-columns: auto; 20 | } 21 | 22 | .selector_header { 23 | background-color: black; 24 | border-radius: var(--border_radius) var(--border_radius) 0 0; 25 | color: white; 26 | width: 100%; 27 | padding: 8px 12px; 28 | } 29 | 30 | .grid_container { 31 | background-color: red; 32 | min-height: 300px; 33 | } 34 | 35 | @media only screen and (min-width: 600px) { 36 | .grid_container { 37 | width: 90%; 38 | max-width: 800px; 39 | } 40 | } 41 | @media only screen and (max-width: 600px) { 42 | .grid_container { 43 | width: 100%; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/karma/s3rver/s3rver.js: -------------------------------------------------------------------------------- 1 | const S3rver = require('s3rver'); 2 | 3 | const CORS_CONFIG = 4 | '\n' + 5 | ' \n' + 6 | ' *\n' + 7 | ' PUT\n' + 8 | ' GET\n' + 9 | ' HEAD\n' + 10 | ' *\n' + 11 | ' Content-Range\n' + 12 | ' \n' + 13 | ''; 14 | 15 | var createS3rver = function (args, config, logger) { 16 | const log = logger.create('S3-test-server'); 17 | log.info('Starting S3 test server on port ' + config.s3rver.port); 18 | let instance = new S3rver({ 19 | port: config.s3rver.port, 20 | address: 'localhost', 21 | silent: config.s3rver.silent, 22 | directory: './../../.tmp/s3rver', 23 | configureBuckets: [{ name: 'test-bucket', configs: [CORS_CONFIG] }], 24 | }).run(); 25 | }; 26 | 27 | module.exports = { 28 | 'framework:s3rver': ['factory', createS3rver], 29 | }; 30 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/utils/parking_lot.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_UTILS_PARKING_LOT_H_ 2 | #define INCLUDE_DUCKDB_WEB_UTILS_PARKING_LOT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace duckdb { 9 | namespace web { 10 | 11 | /// A parking lot. 12 | /// https://github.com/WebKit/webkit/blob/main/Source/WTF/wtf/ParkingLot.h 13 | class ParkingLot { 14 | public: 15 | /// Park a thread 16 | static void Park(const void* addr, std::function check, 17 | std::chrono::nanoseconds timeout = std::chrono::nanoseconds{0}); 18 | /// Park a thread with spinning 19 | static void ParkWithSpinning(const void* addr, std::function check); 20 | /// Unpark threads 21 | static void UnparkThreads(const void* addr, bool unpark_all); 22 | /// Unpark one thread 23 | static void UnparkOne(const void* addr) { return UnparkThreads(addr, false); } 24 | /// Unpark all threads 25 | static void UnparkAll(const void* addr) { return UnparkThreads(addr, true); } 26 | }; 27 | 28 | } // namespace web 29 | } // namespace duckdb 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /patches/duckdb/fix_load_database.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/storage/storage_manager.cpp b/src/storage/storage_manager.cpp 2 | index 45d42174f1..10b3ce47b1 100644 3 | --- a/src/storage/storage_manager.cpp 4 | +++ b/src/storage/storage_manager.cpp 5 | @@ -162,9 +162,15 @@ void SingleFileStorageManager::LoadDatabase(StorageOptions storage_options) { 6 | row_group_size, STANDARD_VECTOR_SIZE); 7 | } 8 | } 9 | - // Check if the database file already exists. 10 | - // Note: a file can also exist if there was a ROLLBACK on a previous transaction creating that file. 11 | - if (!read_only && !fs.FileExists(path)) { 12 | + bool is_empty_file = true; 13 | + auto db_file_handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ | FileFlags::FILE_FLAGS_NULL_IF_NOT_EXISTS); 14 | + if (db_file_handle && db_file_handle->GetFileSize() != 0) { 15 | + is_empty_file = false; 16 | + db_file_handle.reset(); 17 | + } 18 | + 19 | + // first check if the database exists 20 | + if (!read_only && (!fs.FileExists(path) || (options.use_direct_io && is_empty_file))) { 21 | // file does not exist and we are in read-write mode 22 | // create a new file 23 | 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/duckdb"] 2 | path = submodules/duckdb 3 | url = https://github.com/duckdb/duckdb 4 | update = rebase 5 | [submodule "submodules/arrow"] 6 | path = submodules/arrow 7 | url = https://github.com/apache/arrow 8 | shallow = true 9 | ignore = dirty 10 | [submodule "submodules/gflags"] 11 | path = submodules/gflags 12 | url = https://github.com/gflags/gflags.git 13 | shallow = true 14 | [submodule "submodules/benchmark"] 15 | path = submodules/benchmark 16 | url = https://github.com/google/benchmark 17 | shallow = true 18 | [submodule "submodules/googletest"] 19 | path = submodules/googletest 20 | url = https://github.com/google/googletest 21 | shallow = true 22 | [submodule "submodules/spdlog"] 23 | path = submodules/spdlog 24 | url = https://github.com/gabime/spdlog 25 | shallow = true 26 | [submodule "submodules/rapidjson"] 27 | path = submodules/rapidjson 28 | url = https://github.com/Tencent/rapidjson 29 | shallow = true 30 | [submodule "submodules/tpch-dbgen"] 31 | path = submodules/tpch-dbgen 32 | url = https://github.com/gregrahn/tpch-kit.git 33 | ignore = dirty 34 | shallow = true 35 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/8-sqlite.sql: -------------------------------------------------------------------------------- 1 | select 2 | o_year, 3 | sum( 4 | case 5 | when nation = 'BRAZIL' then volume 6 | else 0 7 | end 8 | ) / sum(volume) as mkt_share 9 | from 10 | ( 11 | select 12 | strftime('%Y', o_orderdate) as o_year, 13 | l_extendedprice * (1 - l_discount) as volume, 14 | n2.n_name as nation 15 | from 16 | part, 17 | supplier, 18 | lineitem, 19 | orders, 20 | customer, 21 | nation n1, 22 | nation n2, 23 | region 24 | where 25 | p_partkey = l_partkey 26 | and s_suppkey = l_suppkey 27 | and l_orderkey = o_orderkey 28 | and o_custkey = c_custkey 29 | and c_nationkey = n1.n_nationkey 30 | and n1.n_regionkey = r_regionkey 31 | and r_name = 'AMERICA' 32 | and s_nationkey = n2.n_nationkey 33 | and o_orderdate between '1995-01-01' 34 | and '1996-12-31' 35 | ) as all_nations 36 | group by 37 | o_year 38 | order by 39 | o_year; 40 | -------------------------------------------------------------------------------- /.github/workflows/npm_tags.yml: -------------------------------------------------------------------------------- 1 | name: 'NPM tag' 2 | on: 3 | workflow_call: 4 | inputs: 5 | version: 6 | type: string 7 | tag: 8 | type: string 9 | workflow_dispatch: 10 | inputs: 11 | version: 12 | type: string 13 | tag: 14 | type: string 15 | 16 | jobs: 17 | change_tags: 18 | name: Change tags 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | submodules: 'recursive' 24 | fetch-depth: 0 25 | 26 | - uses: actions/setup-node@v4 27 | with: 28 | node-version: '18.x' 29 | registry-url: 'https://registry.npmjs.org' 30 | 31 | - name: Change tags 32 | env: 33 | TAG: ${{ inputs.tag }} 34 | VERSION: ${{ inputs.version }} 35 | run: | 36 | npm dist-tag ls @duckdb/duckdb-wasm@"${VERSION}" 37 | npm dist-tag add @duckdb/duckdb-wasm@"${VERSION}" "${TAG}" 38 | npm dist-tag ls @duckdb/duckdb-wasm@"${VERSION}" 39 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-browser-blocking.ts: -------------------------------------------------------------------------------- 1 | export * from '../bindings'; 2 | export * from '../log'; 3 | export * from '../platform'; 4 | export * from '../status'; 5 | export * from '../version'; 6 | export { DuckDBDataProtocol } from '../bindings/runtime'; 7 | export { DEFAULT_RUNTIME } from '../bindings/runtime'; 8 | export { BROWSER_RUNTIME } from '../bindings/runtime_browser'; 9 | 10 | import { Logger } from '../log'; 11 | import { DuckDBRuntime, DuckDBBindings } from '../bindings'; 12 | import { DuckDBBundles, getPlatformFeatures } from '../platform'; 13 | import { DuckDB as DuckDBMVP } from '../bindings/bindings_browser_mvp'; 14 | import { DuckDB as DuckDBNext } from '../bindings/bindings_browser_eh'; 15 | 16 | export async function createDuckDB( 17 | bundles: DuckDBBundles, 18 | logger: Logger, 19 | runtime: DuckDBRuntime, 20 | ): Promise { 21 | const platform = await getPlatformFeatures(); 22 | if (platform.wasmExceptions) { 23 | if (bundles.eh) { 24 | return new DuckDBNext(logger, runtime, bundles.eh!.mainModule); 25 | } 26 | } 27 | return new DuckDBMVP(logger, runtime, bundles.mvp.mainModule); 28 | } 29 | -------------------------------------------------------------------------------- /scripts/generate_tpch_tbl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | trap exit SIGINT 6 | 7 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 8 | TPCH_DBGEN_DIR="${PROJECT_ROOT}/submodules/tpch-dbgen/dbgen" 9 | TPCH_DBGEN=${TPCH_DBGEN_DIR}/dbgen 10 | SCALE_FACTOR=${1:-0.01} 11 | SCALE_FACTOR_DIR=${SCALE_FACTOR/./_} 12 | TPCH_DIR=${PROJECT_ROOT}/data/tpch 13 | TPCH_SF_OUT=${TPCH_DIR}/${SCALE_FACTOR_DIR} 14 | TPCH_SF_OUT_TBL=${TPCH_SF_OUT}/tbl 15 | 16 | echo "SCALE_FACTOR=${SCALE_FACTOR}" 17 | 18 | if [ ! -f ${TPCH_DBGEN} ]; then 19 | cd ${TPCH_DBGEN_DIR} 20 | case "$(uname)" in 21 | 'Linux');; 22 | 'Darwin') 23 | echo "Patch Makefile" 24 | sed -i '.bak' -e "s/LINUX/MACOS/g" ./Makefile 25 | ;; 26 | esac 27 | make -C ${TPCH_DBGEN_DIR} dbgen 28 | fi 29 | chmod +x ${TPCH_DBGEN} 30 | echo "TPCH_DBGEN=${TPCH_DBGEN}" 31 | 32 | mkdir -p ${TPCH_SF_OUT_TBL} 33 | TBL_COUNT=$(find ${TPCH_SF_OUT_TBL} -name "*.tbl" | wc -l) 34 | if [[ ${TBL_COUNT} -ne 8 ]]; then 35 | cd ${TPCH_DBGEN_DIR} 36 | DSS_PATH=${TPCH_SF_OUT_TBL} ./dbgen -vf -s ${SCALE_FACTOR} 37 | fi 38 | echo "TPCH_SF_OUT_TBL=${TPCH_SF_OUT_TBL}" 39 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/19.sql: -------------------------------------------------------------------------------- 1 | select 2 | sum(l_extendedprice * (1 - l_discount)) as revenue 3 | from 4 | lineitem, 5 | part 6 | where 7 | ( 8 | p_partkey = l_partkey 9 | and p_brand = 'Brand#12' 10 | and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') 11 | and l_quantity >= 1 12 | and l_quantity <= 1 + 10 13 | and p_size between 1 14 | and 5 15 | and l_shipmode in ('AIR', 'AIR REG') 16 | and l_shipinstruct = 'DELIVER IN PERSON' 17 | ) 18 | or ( 19 | p_partkey = l_partkey 20 | and p_brand = 'Brand#23' 21 | and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') 22 | and l_quantity >= 10 23 | and l_quantity <= 10 + 10 24 | and p_size between 1 25 | and 10 26 | and l_shipmode in ('AIR', 'AIR REG') 27 | and l_shipinstruct = 'DELIVER IN PERSON' 28 | ) 29 | or ( 30 | p_partkey = l_partkey 31 | and p_brand = 'Brand#34' 32 | and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') 33 | and l_quantity >= 20 34 | and l_quantity <= 20 + 10 35 | and p_size between 1 36 | and 15 37 | and l_shipmode in ('AIR', 'AIR REG') 38 | and l_shipinstruct = 'DELIVER IN PERSON' 39 | ); 40 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-node-blocking.ts: -------------------------------------------------------------------------------- 1 | export * from '../bindings'; 2 | export * from '../log'; 3 | export * from '../platform'; 4 | export * from '../status'; 5 | export * from '../version'; 6 | export { DuckDBDataProtocol } from '../bindings/runtime'; 7 | export { DEFAULT_RUNTIME } from '../bindings/runtime'; 8 | export { NODE_RUNTIME } from '../bindings/runtime_node'; 9 | 10 | import { Logger } from '../log'; 11 | import { DuckDBRuntime } from '../bindings'; 12 | import { DuckDBNodeBindings } from '../bindings/bindings_node_base'; 13 | import { DuckDBBundles, getPlatformFeatures } from '../platform'; 14 | import { DuckDB as DuckDBMVP } from '../bindings/bindings_node_mvp'; 15 | import { DuckDB as DuckDBNext } from '../bindings/bindings_node_eh'; 16 | 17 | export async function createDuckDB( 18 | bundles: DuckDBBundles, 19 | logger: Logger, 20 | runtime: DuckDBRuntime, 21 | ): Promise { 22 | const platform = await getPlatformFeatures(); 23 | if (platform.wasmExceptions) { 24 | if (bundles.eh) { 25 | return new DuckDBNext(logger, runtime, bundles.eh!.mainModule); 26 | } 27 | } 28 | return new DuckDBMVP(logger, runtime, bundles.mvp.mainModule); 29 | } 30 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/8.sql: -------------------------------------------------------------------------------- 1 | select 2 | o_year, 3 | sum( 4 | case 5 | when nation = 'BRAZIL' then volume 6 | else 0 7 | end 8 | ) / sum(volume) as mkt_share 9 | from 10 | ( 11 | select 12 | extract( 13 | year 14 | from 15 | o_orderdate 16 | ) as o_year, 17 | l_extendedprice * (1 - l_discount) as volume, 18 | n2.n_name as nation 19 | from 20 | part, 21 | supplier, 22 | lineitem, 23 | orders, 24 | customer, 25 | nation n1, 26 | nation n2, 27 | region 28 | where 29 | p_partkey = l_partkey 30 | and s_suppkey = l_suppkey 31 | and l_orderkey = o_orderkey 32 | and o_custkey = c_custkey 33 | and c_nationkey = n1.n_nationkey 34 | and n1.n_regionkey = r_regionkey 35 | and r_name = 'AMERICA' 36 | and s_nationkey = n2.n_nationkey 37 | and o_orderdate between '1995-01-01' 38 | and '1996-12-31' 39 | ) as all_nations 40 | group by 41 | o_year 42 | order by 43 | o_year; 44 | -------------------------------------------------------------------------------- /packages/benchmarks/src/suite_system_tpch_arquero.ts: -------------------------------------------------------------------------------- 1 | import { writeReport } from './setup'; 2 | import { SystemBenchmarkContext, SystemBenchmark, ArqueroTPCHBenchmark } from './system'; 3 | import { runSystemBenchmarks } from './suite'; 4 | import * as path from 'path'; 5 | 6 | async function main() { 7 | const args = process.argv.slice(2); 8 | if (args.length < 1) { 9 | console.error('usage: node suite-system-tpch.js '); 10 | process.exit(-1); 11 | } 12 | const sf = parseFloat(args[0]); 13 | console.log(`Scale Factor ${sf}`); 14 | 15 | const baseDir = path.resolve(__dirname, '../../../'); 16 | const benchmarks: SystemBenchmark[] = []; 17 | for (let i = 1; i <= 22; ++i) { 18 | if (sf >= 0.1 && (i == 9 || i == 21)) { 19 | continue; 20 | } 21 | benchmarks.push(new ArqueroTPCHBenchmark(sf, i)); 22 | } 23 | const ctx: SystemBenchmarkContext = { 24 | projectRootPath: baseDir, 25 | seed: Math.random(), 26 | }; 27 | const results = await runSystemBenchmarks(ctx, benchmarks); 28 | console.log(results); 29 | await writeReport(results, `./benchmark_system_tpch_${sf.toString().replace('.', '')}_arquero.json`); 30 | } 31 | 32 | main(); 33 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/long_queries.test.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '../src'; 2 | 3 | // https://github.com/duckdb/duckdb-wasm/issues/393 4 | export function longQueries(db: () => duckdb.AsyncDuckDB): void { 5 | let conn: duckdb.AsyncDuckDBConnection | null = null; 6 | beforeEach(async () => { 7 | await db().flushFiles(); 8 | }); 9 | afterEach(async () => { 10 | if (conn) { 11 | await conn.close(); 12 | conn = null; 13 | } 14 | await db().flushFiles(); 15 | await db().dropFiles(); 16 | }); 17 | describe('Very long queries', () => { 18 | it('1e6', async () => { 19 | await db().open({ 20 | path: ':memory:', 21 | query: { 22 | castTimestampToDate: false, 23 | }, 24 | }); 25 | conn = await db().connect(); 26 | 27 | let str = `with big_expr as ( select `; 28 | let i = 1; 29 | while (str.length < 1e6) { 30 | str += ` ` + i + ` as col_` + i + `,`; 31 | i++; 32 | } 33 | str += ` NULL as col_NULL) select 99;`; 34 | 35 | await conn.query(str); 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/regression/github_1467.test.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '../../src'; 2 | 3 | // https://github.com/duckdb/duckdb-wasm/issues/477 4 | // Note that when ArrowJS supports negative decimals, castDecimalToDouble should probably be deprecated. 5 | export function test1467(db: () => duckdb.AsyncDuckDB): void { 6 | let conn: duckdb.AsyncDuckDBConnection | null = null; 7 | beforeEach(async () => { 8 | await db().flushFiles(); 9 | }); 10 | afterEach(async () => { 11 | if (conn) { 12 | await conn.close(); 13 | conn = null; 14 | } 15 | await db().flushFiles(); 16 | await db().dropFiles(); 17 | }); 18 | describe('GitHub issues', () => { 19 | it('1467', async () => { 20 | // Baseline without cast: we expect decimal values to not handle fractional parts correctly 21 | await db().open({ 22 | path: ':memory:', 23 | query: {}, 24 | }); 25 | conn = await db().connect(); 26 | const resultWithoutCast = await conn.query(`select substring('🦆🦆🦆' from 3) AS result;`); 27 | expect(resultWithoutCast.toArray()[0]?.result).toEqual('🦆'); 28 | }); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/coverage.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import mkdir from 'make-dir'; 4 | import rimraf from 'rimraf'; 5 | import { spawnSync } from 'child_process'; 6 | import { fileURLToPath } from 'url'; 7 | 8 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 9 | 10 | const cov = path.resolve(__dirname, 'coverage'); 11 | const cov_chrome = path.resolve(cov, 'chrome', 'coverage-final.json'); 12 | //const cov_firefox = path.resolve(cov, 'firefox', 'coverage-final.json'); 13 | const cov_node = path.resolve(cov, 'node', 'coverage-final.json'); 14 | const cov_all = path.resolve(cov, 'all'); 15 | const cov_out = path.resolve(cov, 'coverage.json'); 16 | const nyc = '../../node_modules/nyc/bin/nyc.js'; 17 | 18 | rimraf.sync(cov_all); 19 | mkdir.sync(cov_all); 20 | fs.copyFileSync(cov_chrome, path.resolve(cov_all, 'chrome.json')); 21 | //fs.copyFileSync(cov_firefox, path.resolve(cov_all, 'firefox.json')); 22 | fs.copyFileSync(cov_node, path.resolve(cov_all, 'node.json')); 23 | 24 | const out = spawnSync(nyc, ['merge', cov_all, cov_out], { 25 | encoding: 'utf8', 26 | shell: true, 27 | cov, 28 | }); 29 | console.log(out.stdout); 30 | if (out.status !== 0) { 31 | console.error(out.stderr); 32 | process.exit(out.status); 33 | } 34 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/tokenizer.test.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '../src/'; 2 | 3 | export function testTokenization(db: () => duckdb.DuckDBBindings): void { 4 | describe('Tokenizer', () => { 5 | it('SELECT 1', async () => { 6 | expect(db().tokenize('SELECT 1')).toEqual({ 7 | offsets: [0, 7], 8 | types: [4, 1], 9 | }); 10 | }); 11 | it('SELECT * FROM region', async () => { 12 | expect(db().tokenize('SELECT * FROM region')).toEqual({ 13 | offsets: [0, 7, 9, 14], 14 | types: [4, 3, 4, 0], 15 | }); 16 | }); 17 | }); 18 | } 19 | 20 | export function testTokenizationAsync(db: () => duckdb.AsyncDuckDB): void { 21 | describe('Tokenizer', () => { 22 | it('SELECT 1', async () => { 23 | expect(await db().tokenize('SELECT 1')).toEqual({ 24 | offsets: [0, 7], 25 | types: [4, 1], 26 | }); 27 | }); 28 | it('SELECT * FROM region', async () => { 29 | expect(await db().tokenize('SELECT * FROM region')).toEqual({ 30 | offsets: [0, 7, 9, 14], 31 | types: [4, 3, 4, 0], 32 | }); 33 | }); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /packages/benchmarks/src/suite_system_sum_csv.ts: -------------------------------------------------------------------------------- 1 | import { setupDuckDBSync, writeReport } from './setup'; 2 | import { ArqueroCSVSumBenchmark, DuckDBSyncCSVSumBenchmark, SystemBenchmark, SystemBenchmarkContext } from './system'; 3 | import { runSystemBenchmarks } from './suite'; 4 | import * as path from 'path'; 5 | 6 | async function main() { 7 | const baseDir = path.resolve(__dirname, '../../../'); 8 | const duckdbSync = await setupDuckDBSync(); 9 | const suite: SystemBenchmark[] = [ 10 | new ArqueroCSVSumBenchmark(1000, 10), 11 | new ArqueroCSVSumBenchmark(10000, 100), 12 | new ArqueroCSVSumBenchmark(100000, 1000), 13 | new ArqueroCSVSumBenchmark(1000000, 10000), 14 | new DuckDBSyncCSVSumBenchmark(duckdbSync, 1000, 10), 15 | new DuckDBSyncCSVSumBenchmark(duckdbSync, 10000, 100), 16 | new DuckDBSyncCSVSumBenchmark(duckdbSync, 100000, 1000), 17 | new DuckDBSyncCSVSumBenchmark(duckdbSync, 1000000, 10000), 18 | ]; 19 | const ctx: SystemBenchmarkContext = { 20 | projectRootPath: baseDir, 21 | seed: Math.random(), 22 | }; 23 | const results = await runSystemBenchmarks(ctx, suite); 24 | console.log(results); 25 | await writeReport(results, './benchmark_system_sum_csv.json'); 26 | } 27 | 28 | main(); 29 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/xterm/addons/attach.rs: -------------------------------------------------------------------------------- 1 | use crate::xterm::{Terminal, TerminalAddon}; 2 | use wasm_bindgen::prelude::*; 3 | use wasm_bindgen::JsCast; 4 | use web_sys::WebSocket; 5 | 6 | #[wasm_bindgen(module = "xterm-addon-attach")] 7 | extern "C" { 8 | 9 | #[wasm_bindgen(js_name = "IAttachOptions")] 10 | pub type AttachOptions; 11 | 12 | #[wasm_bindgen(method, setter, js_name = "bidirectional")] 13 | fn set_bidirectional(this: &AttachOptions, val: bool); 14 | 15 | // ======================================================================== 16 | 17 | #[wasm_bindgen(extends = TerminalAddon)] 18 | pub type AttachAddon; 19 | 20 | #[wasm_bindgen(constructor)] 21 | pub fn new(socket: WebSocket, options: Option) -> AttachAddon; 22 | 23 | #[wasm_bindgen(method, method, js_name = "activate")] 24 | pub fn activate(this: &AttachOptions, terminal: Terminal); 25 | 26 | #[wasm_bindgen(method, method, js_name = "dispose")] 27 | pub fn dispose(this: &AttachOptions); 28 | } 29 | 30 | impl AttachOptions { 31 | pub fn new() -> Self { 32 | js_sys::Object::new().unchecked_into() 33 | } 34 | 35 | pub fn with_bidirectional(&self, val: bool) -> &Self { 36 | self.set_bidirectional(val); 37 | self 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/esbuild-node/index.mjs: -------------------------------------------------------------------------------- 1 | import * as duckdb from "@duckdb/duckdb-wasm"; 2 | import path from "path"; 3 | import Worker from "web-worker"; 4 | import { createRequire } from "module"; 5 | const require2 = createRequire(import.meta.url); 6 | const DUCKDB_DIST = path.dirname(require2.resolve("@duckdb/duckdb-wasm")); 7 | (async () => { 8 | try { 9 | const DUCKDB_CONFIG = await duckdb.selectBundle({ 10 | mvp: { 11 | mainModule: path.resolve(DUCKDB_DIST, "./duckdb-mvp.wasm"), 12 | mainWorker: path.resolve(DUCKDB_DIST, "./duckdb-node-mvp.worker.cjs") 13 | }, 14 | eh: { 15 | mainModule: path.resolve(DUCKDB_DIST, "./duckdb-eh.wasm"), 16 | mainWorker: path.resolve(DUCKDB_DIST, "./duckdb-node-eh.worker.cjs") 17 | } 18 | }); 19 | const logger = new duckdb.ConsoleLogger(); 20 | const worker = new Worker(DUCKDB_CONFIG.mainWorker); 21 | const db = new duckdb.AsyncDuckDB(logger, worker); 22 | await db.instantiate(DUCKDB_CONFIG.mainModule, DUCKDB_CONFIG.pthreadWorker); 23 | const conn = await db.connect(); 24 | await conn.query(`SELECT count(*)::INTEGER as v FROM generate_series(0, 100) t(v)`); 25 | await conn.close(); 26 | await db.terminate(); 27 | await worker.terminate(); 28 | } catch (e) { 29 | console.error(e); 30 | } 31 | })(); 32 | -------------------------------------------------------------------------------- /lib/include/duckdb/web/json_typedef.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_DUCKDB_WEB_JSON_TYPEDEF_H_ 2 | #define INCLUDE_DUCKDB_WEB_JSON_TYPEDEF_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "arrow/type.h" 8 | #include "arrow/type_fwd.h" 9 | #include "duckdb/web/json_analyzer.h" 10 | #include "duckdb/web/json_parser.h" 11 | #include "rapidjson/document.h" 12 | 13 | namespace duckdb { 14 | namespace web { 15 | namespace json { 16 | 17 | /// Read a type 18 | arrow::Result> SQLToArrowType(const rapidjson::Value::ConstObject& obj); 19 | /// Read field from a json object 20 | arrow::Result> SQLToArrowField(const rapidjson::Value& obj); 21 | /// Read fields from a json array 22 | arrow::Result>> SQLToArrowFields(const rapidjson::Value::ConstArray& fields); 23 | /// Serialize a SQL type as string 24 | arrow::Result WriteSQLType(rapidjson::Document& doc, const duckdb::LogicalType& type); 25 | /// Serialize a SQL type as string 26 | arrow::Result WriteSQLField(rapidjson::Document& doc, std::string_view name, 27 | const duckdb::LogicalType& type, bool nullable); 28 | 29 | } // namespace json 30 | } // namespace web 31 | } // namespace duckdb 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /scripts/sync_versions.mjs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 The DashQL Authors 2 | 3 | import fs from 'fs'; 4 | 5 | const pkgPaths = [ 6 | './packages/duckdb-wasm-app/package.json', 7 | './packages/duckdb-wasm-shell/package.json', 8 | './packages/duckdb-wasm/package.json', 9 | './packages/react-duckdb/package.json', 10 | './packages/benchmarks/package.json', 11 | './examples/esbuild-browser/package.json', 12 | './examples/esbuild-node/package.json', 13 | './examples/bare-node/package.json', 14 | './examples/bare-browser/package.json', 15 | ]; 16 | const pkgs = []; 17 | 18 | // Read all packages 19 | for (const pkgPath of pkgPaths) { 20 | const j = JSON.parse(fs.readFileSync(pkgPath)); 21 | console.log(`${j.name}:${j.version}`); 22 | pkgs.push({ 23 | path: pkgPath, 24 | name: j.name, 25 | version: j.version, 26 | config: j, 27 | }); 28 | } 29 | 30 | // Do a naive n*n sync 31 | for (const pkg of pkgs) { 32 | for (const otherPkg of pkgs) { 33 | if (pkg.name == otherPkg.name) continue; 34 | if (pkg.config.dependencies && pkg.config.dependencies[otherPkg.name] !== undefined) { 35 | pkg.config.dependencies[otherPkg.name] = `^${otherPkg.config.version}`; 36 | } 37 | } 38 | fs.writeFileSync(pkg.path, JSON.stringify(pkg.config, null, 4) + '\n'); 39 | } 40 | -------------------------------------------------------------------------------- /examples/bare-node/index.cjs: -------------------------------------------------------------------------------- 1 | const duckdb = require('@duckdb/duckdb-wasm'); 2 | const path = require('path'); 3 | const Worker = require('web-worker'); 4 | const DUCKDB_DIST = path.dirname(require.resolve('@duckdb/duckdb-wasm')); 5 | 6 | (async () => { 7 | try { 8 | const DUCKDB_CONFIG = await duckdb.selectBundle({ 9 | mvp: { 10 | mainModule: path.resolve(DUCKDB_DIST, './duckdb-mvp.wasm'), 11 | mainWorker: path.resolve(DUCKDB_DIST, './duckdb-node-mvp.worker.cjs'), 12 | }, 13 | eh: { 14 | mainModule: path.resolve(DUCKDB_DIST, './duckdb-eh.wasm'), 15 | mainWorker: path.resolve(DUCKDB_DIST, './duckdb-node-eh.worker.cjs'), 16 | }, 17 | }); 18 | 19 | const logger = new duckdb.ConsoleLogger(); 20 | const worker = new Worker(DUCKDB_CONFIG.mainWorker); 21 | const db = new duckdb.AsyncDuckDB(logger, worker); 22 | await db.instantiate(DUCKDB_CONFIG.mainModule, DUCKDB_CONFIG.pthreadWorker); 23 | 24 | const conn = await db.connect(); 25 | await conn.query(`SELECT count(*)::INTEGER as v FROM generate_series(0, 100) t(v)`); 26 | 27 | await conn.close(); 28 | await db.terminate(); 29 | await worker.terminate(); 30 | } catch (e) { 31 | console.error(e); 32 | } 33 | })(); 34 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/7-sqlite.sql: -------------------------------------------------------------------------------- 1 | select 2 | supp_nation, 3 | cust_nation, 4 | l_year, 5 | sum(volume) as revenue 6 | from 7 | ( 8 | select 9 | n1.n_name as supp_nation, 10 | n2.n_name as cust_nation, 11 | strftime('%Y', l_shipdate) as l_year, 12 | l_extendedprice * (1 - l_discount) as volume 13 | from 14 | supplier, 15 | lineitem, 16 | orders, 17 | customer, 18 | nation n1, 19 | nation n2 20 | where 21 | s_suppkey = l_suppkey 22 | and o_orderkey = l_orderkey 23 | and c_custkey = o_custkey 24 | and s_nationkey = n1.n_nationkey 25 | and c_nationkey = n2.n_nationkey 26 | and ( 27 | ( 28 | n1.n_name = 'FRANCE' 29 | and n2.n_name = 'GERMANY' 30 | ) 31 | or ( 32 | n1.n_name = 'GERMANY' 33 | and n2.n_name = 'FRANCE' 34 | ) 35 | ) 36 | and l_shipdate between '1995-01-01' 37 | and '1996-12-31' 38 | ) as shipping 39 | group by 40 | supp_nation, 41 | cust_nation, 42 | l_year 43 | order by 44 | supp_nation, 45 | cust_nation, 46 | l_year; 47 | -------------------------------------------------------------------------------- /lib/cmake/gflags.cmake: -------------------------------------------------------------------------------- 1 | include(ExternalProject) 2 | find_package(Git REQUIRED) 3 | 4 | # Get gflags 5 | ExternalProject_Add( 6 | gflags_src 7 | SOURCE_DIR "${CMAKE_SOURCE_DIR}/../submodules/gflags" 8 | PREFIX "${CMAKE_BINARY_DIR}/third_party/gflags" 9 | INSTALL_DIR "${CMAKE_BINARY_DIR}/third_party/gflags/install" 10 | CMAKE_ARGS 11 | -G${CMAKE_GENERATOR} 12 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/third_party/gflags/install 13 | -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} 14 | -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} 15 | -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} 16 | -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} 17 | -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} 18 | DOWNLOAD_COMMAND "" 19 | UPDATE_COMMAND "" 20 | BUILD_BYPRODUCTS /lib/libgflags.a) 21 | 22 | # Prepare gflags 23 | ExternalProject_Get_Property(gflags_src install_dir) 24 | set(GFLAGS_INCLUDE_DIR ${install_dir}/include) 25 | set(GFLAGS_LIBRARY_PATH ${install_dir}/lib/libgflags.a) 26 | file(MAKE_DIRECTORY ${GFLAGS_INCLUDE_DIR}) 27 | add_library(gflags STATIC IMPORTED) 28 | set_property(TARGET gflags PROPERTY IMPORTED_LOCATION ${GFLAGS_LIBRARY_PATH}) 29 | set_property( 30 | TARGET gflags 31 | APPEND 32 | PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GFLAGS_INCLUDE_DIR}) 33 | 34 | # Dependencies 35 | add_dependencies(gflags gflags_src) 36 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/src/comfy/style/column.rs: -------------------------------------------------------------------------------- 1 | /// Constraints can be added to [columns](crate::Column). 2 | /// 3 | /// They allow some control over the dynamic content arrangement process. 4 | #[derive(Copy, Clone, Debug, PartialEq)] 5 | pub enum ColumnConstraint { 6 | /// This will completely hide a column. 7 | Hidden, 8 | /// Force the column to be as long as it's content. 9 | /// Use with caution! This can easily break your table, if the column's content is overly long. 10 | ContentWidth, 11 | /// Enforce a fix width for a column. 12 | Width(u16), 13 | /// Specify a min amount of characters per line for a column. 14 | MinWidth(u16), 15 | /// Specify a max amount of allowed characters per line for a column. 16 | MaxWidth(u16), 17 | /// Set a fixed percentage in respect to table_width for this column. 18 | /// **Warning:** This option will be ignored, if the width cannot be determined! 19 | Percentage(u16), 20 | /// Set a a minimum percentage in respect to table_width for this column. 21 | /// **Warning:** This option will be ignored, if the width cannot be determined! 22 | MinPercentage(u16), 23 | /// Set a a maximum percentage in respect to table_width for this column. 24 | /// **Warning:** This option will be ignored, if the width cannot be determined! 25 | MaxPercentage(u16), 26 | } 27 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/src/utils/format.ts: -------------------------------------------------------------------------------- 1 | export enum ByteFormat { 2 | SI = 0, 3 | IEC = 1, 4 | } 5 | 6 | export function formatBytes(value: number, format: ByteFormat = ByteFormat.SI): string { 7 | const [multiple, k, suffix] = format === ByteFormat.SI ? [1000, 'k', 'B'] : [1024, 'K', 'iB']; 8 | const exp = (Math.log(value) / Math.log(multiple)) | 0; 9 | const size = Number((value / Math.pow(multiple, exp)).toFixed(2)); 10 | return `${size} ${exp ? `${k}MGTPEZY`[exp - 1] + suffix : `byte${size !== 1 ? 's' : ''}`}`; 11 | } 12 | 13 | export function formatThousands(value: number): string { 14 | const [multiple, k] = [1000, 'k']; 15 | const exp = (Math.log(value) / Math.log(multiple)) | 0; 16 | const size = Number((value / Math.pow(multiple, exp)).toFixed(2)); 17 | return size + (exp ? ` ${`${k}MGTPEZY`[exp - 1]}` : ''); 18 | } 19 | 20 | export function formatMs(value: number): string { 21 | const MS_SECONDS = 1000; 22 | const MS_MINUTES = MS_SECONDS * 60; 23 | if (value >= MS_MINUTES) { 24 | return `${Math.floor(value / MS_MINUTES)}:${Math.floor((value % MS_MINUTES) / MS_SECONDS)}.${( 25 | value % MS_SECONDS 26 | ) 27 | .toString() 28 | .padStart(4, '0')}`; 29 | } 30 | return `${Math.floor(value / MS_SECONDS)}.${(value % MS_SECONDS).toFixed(0).padStart(3, '0')}`; 31 | } 32 | -------------------------------------------------------------------------------- /actions/runner/cloud-init.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | package_upgrade: true 4 | 5 | packages: 6 | - apt-transport-https 7 | - ca-certificates 8 | - gnupg-agent 9 | - software-properties-common 10 | - git 11 | - curl 12 | - jq 13 | 14 | groups: 15 | - docker 16 | 17 | users: 18 | - name: actions 19 | groups: docker 20 | homedir: /home/actions 21 | lock_passwd: true 22 | sudo: False 23 | 24 | runcmd: 25 | # Install docker 26 | - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - 27 | - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" 28 | - apt-get update -y 29 | - apt-get install -y docker-ce docker-ce-cli containerd.io 30 | - systemctl start docker 31 | - systemctl enable docker 32 | 33 | # Install actions 34 | - cd /home/actions 35 | - mkdir runner 36 | - cd ./runner 37 | - curl -o runner.tgz -L https://github.com/actions/runner/releases/download/v2.278.0/actions-runner-linux-x64-2.278.0.tar.gz 38 | - tar -xzf ./runner.tgz 39 | - chown -R actions:actions . 40 | - ./installdependencies.sh 41 | - rm ./runner.tgz 42 | 43 | # Cache directories 44 | - mkdir -p /home/actions/.emscripten_cache /home/actions/.yarn_cache /home/actions/.ccache 45 | - chown -R actions:actions /home/actions/.emscripten_cache /home/actions/.yarn_cache /home/actions/.ccache 46 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/test/regression/github_1833.test.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '../../src'; 2 | 3 | // https://github.com/duckdb/duckdb-wasm/issues/1833 4 | export function test1833(db: () => duckdb.AsyncDuckDB): void { 5 | let conn: duckdb.AsyncDuckDBConnection; 6 | beforeEach(async () => { 7 | await db().flushFiles(); 8 | conn = await db().connect(); 9 | }); 10 | afterEach(async () => { 11 | await conn.close(); 12 | await db().flushFiles(); 13 | await db().dropFiles(); 14 | }); 15 | describe('GitHub issues', () => { 16 | it('1833', async () => { 17 | await conn.query(` 18 | CREATE TABLE "Test" (value VARCHAR) 19 | `); 20 | const stmt = await conn.prepare(` 21 | INSERT INTO "Test" (value) 22 | VALUES (?) 23 | `); 24 | await stmt.query('🦆🦆🦆🦆🦆'); 25 | await stmt.query('goo␀se'); 26 | await stmt.query('goo\u0000se'); 27 | const result = await conn.query(` 28 | SELECT * FROM "Test" 29 | `); 30 | expect(result.schema.fields.length).toBe(1); 31 | expect(result.schema.fields[0].name).toBe('value'); 32 | expect(result.toArray().length).toEqual(3); 33 | expect(result.toArray()[2].value.length).toEqual(6); 34 | }); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /scripts/generate_benchmark_data.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | PROJECT_ROOT="$(cd $(dirname "$BASH_SOURCE[0]") && cd .. && pwd)" &> /dev/null 6 | cd ${PROJECT_ROOT} 7 | 8 | # Raw CSVs 9 | ${PROJECT_ROOT}/scripts/generate_tpch_tbl.sh 0.01 10 | ${PROJECT_ROOT}/scripts/generate_tpch_tbl.sh 0.1 11 | ${PROJECT_ROOT}/scripts/generate_tpch_tbl.sh 0.25 12 | ${PROJECT_ROOT}/scripts/generate_tpch_tbl.sh 0.5 13 | ${PROJECT_ROOT}/scripts/generate_tpch_tbl.sh 1 14 | 15 | # Arrow & Parquet 16 | ${PROJECT_ROOT}/scripts/generate_tpch_arrow.sh 0.01 17 | ${PROJECT_ROOT}/scripts/generate_tpch_arrow.sh 0.1 18 | ${PROJECT_ROOT}/scripts/generate_tpch_arrow.sh 0.25 19 | ${PROJECT_ROOT}/scripts/generate_tpch_arrow.sh 0.5 20 | ${PROJECT_ROOT}/scripts/generate_tpch_arrow.sh 1 21 | 22 | # SQLite databases 23 | ${PROJECT_ROOT}/scripts/generate_tpch_sqlite.sh 0.01 24 | ${PROJECT_ROOT}/scripts/generate_tpch_sqlite.sh 0.1 25 | ${PROJECT_ROOT}/scripts/generate_tpch_sqlite.sh 0.25 26 | ${PROJECT_ROOT}/scripts/generate_tpch_sqlite.sh 0.5 27 | ${PROJECT_ROOT}/scripts/generate_tpch_sqlite.sh 1 28 | 29 | # DuckDB databases 30 | ${PROJECT_ROOT}/scripts/generate_tpch_duckdb.sh 0.01 31 | ${PROJECT_ROOT}/scripts/generate_tpch_duckdb.sh 0.1 32 | ${PROJECT_ROOT}/scripts/generate_tpch_duckdb.sh 0.25 33 | ${PROJECT_ROOT}/scripts/generate_tpch_duckdb.sh 0.5 34 | ${PROJECT_ROOT}/scripts/generate_tpch_duckdb.sh 1 35 | -------------------------------------------------------------------------------- /packages/benchmarks/src/suite_system_tpch_duckdb.ts: -------------------------------------------------------------------------------- 1 | import { writeReport, setupDuckDBSync } from './setup'; 2 | import { SystemBenchmarkContext, SystemBenchmark, DuckDBSyncLoadedTPCHBenchmark } from './system'; 3 | import { runSystemBenchmarks } from './suite'; 4 | import * as path from 'path'; 5 | 6 | async function main() { 7 | const args = process.argv.slice(2); 8 | if (args.length < 1) { 9 | console.error('usage: node suite-system-tpch.js '); 10 | process.exit(-1); 11 | } 12 | const sf = parseFloat(args[0]); 13 | console.log(`Scale Factor ${sf}`); 14 | 15 | const baseDir = path.resolve(__dirname, '../../../'); 16 | const duckdbSync = await setupDuckDBSync(); 17 | const benchmarks: SystemBenchmark[] = []; 18 | for (let i = 1; i <= 22; ++i) { 19 | benchmarks.push(new DuckDBSyncLoadedTPCHBenchmark(duckdbSync, sf, i)); 20 | } 21 | const ctx: SystemBenchmarkContext = { 22 | projectRootPath: baseDir, 23 | seed: Math.random(), 24 | }; 25 | await DuckDBSyncLoadedTPCHBenchmark.beforeGroup(duckdbSync, ctx, sf); 26 | const results = await runSystemBenchmarks(ctx, benchmarks); 27 | await DuckDBSyncLoadedTPCHBenchmark.afterGroup(duckdbSync); 28 | 29 | console.log(results); 30 | await writeReport(results, `./benchmark_system_tpch_${sf.toString().replace('.', '')}_duckdb.json`); 31 | } 32 | 33 | main(); 34 | -------------------------------------------------------------------------------- /packages/benchmarks/src/suite_system_tpch_lovefield.ts: -------------------------------------------------------------------------------- 1 | import { writeReport } from './setup'; 2 | import { SystemBenchmarkContext, SystemBenchmark, LovefieldTPCHBenchmark } from './system'; 3 | import { runSystemBenchmarks } from './suite'; 4 | import * as path from 'path'; 5 | 6 | async function main() { 7 | const args = process.argv.slice(2); 8 | if (args.length < 1) { 9 | console.error('usage: node suite-system-tpch.js '); 10 | process.exit(-1); 11 | } 12 | const sf = parseFloat(args[0]); 13 | console.log(`Scale Factor ${sf}`); 14 | 15 | const baseDir = path.resolve(__dirname, '../../../'); 16 | const benchmarks: SystemBenchmark[] = []; 17 | for (const q of [1, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 16, 19]) { 18 | if (sf >= 0.25 && q == 9) { 19 | continue; 20 | } 21 | benchmarks.push(new LovefieldTPCHBenchmark(sf, q)); 22 | } 23 | const ctx: SystemBenchmarkContext = { 24 | projectRootPath: baseDir, 25 | seed: Math.random(), 26 | }; 27 | 28 | await LovefieldTPCHBenchmark.beforeGroup(ctx, sf); 29 | const results = await runSystemBenchmarks(ctx, benchmarks); 30 | await LovefieldTPCHBenchmark.afterGroup(ctx); 31 | 32 | console.log(results); 33 | await writeReport(results, `./benchmark_system_tpch_${sf.toString().replace('.', '')}_lovefield.json`); 34 | } 35 | 36 | main(); 37 | -------------------------------------------------------------------------------- /examples/esbuild-browser/index.ts: -------------------------------------------------------------------------------- 1 | import * as duckdb from '@duckdb/duckdb-wasm'; 2 | import * as arrow from 'apache-arrow'; 3 | 4 | (async () => { 5 | try { 6 | const DUCKDB_CONFIG = await duckdb.selectBundle({ 7 | mvp: { 8 | mainModule: './duckdb-mvp.wasm', 9 | mainWorker: './duckdb-browser-mvp.worker.js', 10 | }, 11 | eh: { 12 | mainModule: './duckdb-eh.wasm', 13 | mainWorker: './duckdb-browser-eh.worker.js', 14 | }, 15 | coi: { 16 | mainModule: './duckdb-coi.wasm', 17 | mainWorker: './duckdb-browser-coi.worker.js', 18 | pthreadWorker: './duckdb-browser-coi.pthread.worker.js', 19 | }, 20 | }); 21 | 22 | const logger = new duckdb.ConsoleLogger(); 23 | const worker = new Worker(DUCKDB_CONFIG.mainWorker!); 24 | const db = new duckdb.AsyncDuckDB(logger, worker); 25 | await db.instantiate(DUCKDB_CONFIG.mainModule, DUCKDB_CONFIG.pthreadWorker); 26 | 27 | const conn = await db.connect(); 28 | await conn.query<{ v: arrow.Int }>(`SELECT count(*)::INTEGER as v FROM generate_series(0, 100) t(v)`); 29 | 30 | await conn.close(); 31 | await db.terminate(); 32 | await worker.terminate(); 33 | } catch (e) { 34 | console.error(e); 35 | } 36 | })(); 37 | -------------------------------------------------------------------------------- /packages/benchmarks/src/suite_system_tpch_sqljs.ts: -------------------------------------------------------------------------------- 1 | import { writeReport, setupSqljs } from './setup'; 2 | import { SystemBenchmarkContext, SystemBenchmark, SqljsTPCHBenchmark } from './system'; 3 | import { runSystemBenchmarks } from './suite'; 4 | import * as path from 'path'; 5 | 6 | async function main() { 7 | const args = process.argv.slice(2); 8 | if (args.length < 1) { 9 | console.error('usage: node suite-system-tpch.js '); 10 | process.exit(-1); 11 | } 12 | const sf = parseFloat(args[0]); 13 | console.log(`Scale Factor ${sf}`); 14 | 15 | const baseDir = path.resolve(__dirname, '../../../'); 16 | const sqljsDB = await setupSqljs(); 17 | const benchmarks: SystemBenchmark[] = []; 18 | for (let i = 1; i <= 22; ++i) { 19 | if (sf >= 0.25 && (i == 17 || i == 20 || i == 22)) { 20 | continue; 21 | } 22 | benchmarks.push(new SqljsTPCHBenchmark(sf, i)); 23 | } 24 | const ctx: SystemBenchmarkContext = { 25 | projectRootPath: baseDir, 26 | seed: Math.random(), 27 | }; 28 | await SqljsTPCHBenchmark.beforeGroup(sqljsDB, ctx, sf); 29 | const results = await runSystemBenchmarks(ctx, benchmarks); 30 | await SqljsTPCHBenchmark.afterGroup(); 31 | 32 | console.log(results); 33 | await writeReport(results, `./benchmark_system_tpch_${sf.toString().replace('.', '')}_sqljs.json`); 34 | } 35 | 36 | main(); 37 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-node-eh.worker.ts: -------------------------------------------------------------------------------- 1 | import { AsyncDuckDBDispatcher, WorkerResponseVariant, WorkerRequestVariant } from '../parallel/'; 2 | import { DuckDBBindings } from '../bindings'; 3 | import { DuckDB } from '../bindings/bindings_node_eh'; 4 | import { NODE_RUNTIME } from '../bindings/runtime_node'; 5 | import { InstantiationProgress } from '../bindings/progress'; 6 | 7 | /** The duckdb worker API for node.js workers */ 8 | class NodeWorker extends AsyncDuckDBDispatcher { 9 | /** Post a response back to the main thread */ 10 | protected postMessage(response: WorkerResponseVariant, transfer: ArrayBuffer[]) { 11 | globalThis.postMessage(response, transfer); 12 | } 13 | 14 | /** Instantiate the wasm module */ 15 | protected async instantiate( 16 | mainModulePath: string, 17 | pthreadWorkerPath: string | null, 18 | progress: (p: InstantiationProgress) => void, 19 | ): Promise { 20 | const bindings = new DuckDB(this, NODE_RUNTIME, mainModulePath, pthreadWorkerPath); 21 | return await bindings.instantiate(progress); 22 | } 23 | } 24 | 25 | /** Register the worker */ 26 | export function registerWorker(): void { 27 | const api = new NodeWorker(); 28 | globalThis.onmessage = async (event: MessageEvent) => { 29 | await api.onMessage(event.data); 30 | }; 31 | } 32 | 33 | registerWorker(); 34 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-browser-coi.worker.ts: -------------------------------------------------------------------------------- 1 | import { AsyncDuckDBDispatcher, WorkerResponseVariant, WorkerRequestVariant } from '../parallel'; 2 | import { DuckDB } from '../bindings/bindings_browser_coi'; 3 | import { DuckDBBindings } from '../bindings'; 4 | import { BROWSER_RUNTIME } from '../bindings/runtime_browser'; 5 | import { InstantiationProgress } from '../bindings/progress'; 6 | 7 | /** The duckdb worker API for web workers */ 8 | class WebWorker extends AsyncDuckDBDispatcher { 9 | /** Post a response back to the main thread */ 10 | protected postMessage(response: WorkerResponseVariant, transfer: ArrayBuffer[]) { 11 | globalThis.postMessage(response, transfer); 12 | } 13 | 14 | /** Instantiate the wasm module */ 15 | protected async instantiate( 16 | mainModuleURL: string, 17 | pthreadWorkerURL: string | null, 18 | progress: (p: InstantiationProgress) => void, 19 | ): Promise { 20 | const bindings = new DuckDB(this, BROWSER_RUNTIME, mainModuleURL, pthreadWorkerURL); 21 | return await bindings.instantiate(progress); 22 | } 23 | } 24 | 25 | /** Register the worker */ 26 | export function registerWorker(): void { 27 | const api = new WebWorker(); 28 | globalThis.onmessage = async (event: MessageEvent) => { 29 | await api.onMessage(event.data); 30 | }; 31 | } 32 | 33 | registerWorker(); 34 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-browser-eh.worker.ts: -------------------------------------------------------------------------------- 1 | import { AsyncDuckDBDispatcher, WorkerResponseVariant, WorkerRequestVariant } from '../parallel'; 2 | import { DuckDB } from '../bindings/bindings_browser_eh'; 3 | import { DuckDBBindings } from '../bindings'; 4 | import { BROWSER_RUNTIME } from '../bindings/runtime_browser'; 5 | import { InstantiationProgress } from '../bindings/progress'; 6 | 7 | /** The duckdb worker API for web workers */ 8 | class WebWorker extends AsyncDuckDBDispatcher { 9 | /** Post a response back to the main thread */ 10 | protected postMessage(response: WorkerResponseVariant, transfer: ArrayBuffer[]) { 11 | globalThis.postMessage(response, transfer); 12 | } 13 | 14 | /** Instantiate the wasm module */ 15 | protected async instantiate( 16 | mainModuleURL: string, 17 | pthreadWorkerURL: string | null, 18 | progress: (p: InstantiationProgress) => void, 19 | ): Promise { 20 | const bindings = new DuckDB(this, BROWSER_RUNTIME, mainModuleURL, pthreadWorkerURL); 21 | return await bindings.instantiate(progress); 22 | } 23 | } 24 | 25 | /** Register the worker */ 26 | export function registerWorker(): void { 27 | const api = new WebWorker(); 28 | globalThis.onmessage = async (event: MessageEvent) => { 29 | await api.onMessage(event.data); 30 | }; 31 | } 32 | 33 | registerWorker(); 34 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-browser-mvp.worker.ts: -------------------------------------------------------------------------------- 1 | import { AsyncDuckDBDispatcher, WorkerResponseVariant, WorkerRequestVariant } from '../parallel'; 2 | import { DuckDB } from '../bindings/bindings_browser_mvp'; 3 | import { DuckDBBindings } from '../bindings'; 4 | import { BROWSER_RUNTIME } from '../bindings/runtime_browser'; 5 | import { InstantiationProgress } from '../bindings/progress'; 6 | 7 | /** The duckdb worker API for web workers */ 8 | class WebWorker extends AsyncDuckDBDispatcher { 9 | /** Post a response back to the main thread */ 10 | protected postMessage(response: WorkerResponseVariant, transfer: ArrayBuffer[]) { 11 | globalThis.postMessage(response, transfer); 12 | } 13 | 14 | /** Instantiate the wasm module */ 15 | protected async instantiate( 16 | mainModuleURL: string, 17 | pthreadWorkerURL: string | null, 18 | progress: (p: InstantiationProgress) => void, 19 | ): Promise { 20 | const bindings = new DuckDB(this, BROWSER_RUNTIME, mainModuleURL, pthreadWorkerURL); 21 | return await bindings.instantiate(progress); 22 | } 23 | } 24 | 25 | /** Register the worker */ 26 | export function registerWorker(): void { 27 | const api = new WebWorker(); 28 | globalThis.onmessage = async (event: MessageEvent) => { 29 | await api.onMessage(event.data); 30 | }; 31 | } 32 | 33 | registerWorker(); 34 | -------------------------------------------------------------------------------- /packages/duckdb-wasm/src/targets/duckdb-node-mvp.worker.ts: -------------------------------------------------------------------------------- 1 | import { AsyncDuckDBDispatcher, WorkerResponseVariant, WorkerRequestVariant } from '../parallel/'; 2 | import { DuckDBBindings } from '../bindings'; 3 | import { DuckDB } from '../bindings/bindings_node_mvp'; 4 | import { NODE_RUNTIME } from '../bindings/runtime_node'; 5 | import { InstantiationProgress } from '../bindings/progress'; 6 | 7 | /** The duckdb worker API for node.js workers */ 8 | class NodeWorker extends AsyncDuckDBDispatcher { 9 | /** Post a response back to the main thread */ 10 | protected postMessage(response: WorkerResponseVariant, transfer: ArrayBuffer[]) { 11 | globalThis.postMessage(response, transfer); 12 | } 13 | 14 | /** Instantiate the wasm module */ 15 | protected async instantiate( 16 | mainModulePath: string, 17 | pthreadWorkerPath: string | null, 18 | progress: (p: InstantiationProgress) => void, 19 | ): Promise { 20 | const bindings = new DuckDB(this, NODE_RUNTIME, mainModulePath, pthreadWorkerPath); 21 | return await bindings.instantiate(progress); 22 | } 23 | } 24 | 25 | /** Register the worker */ 26 | export function registerWorker(): void { 27 | const api = new NodeWorker(); 28 | globalThis.onmessage = async (event: MessageEvent) => { 29 | await api.onMessage(event.data); 30 | }; 31 | } 32 | 33 | registerWorker(); 34 | -------------------------------------------------------------------------------- /packages/benchmarks/scripts/tpch/7.sql: -------------------------------------------------------------------------------- 1 | select 2 | supp_nation, 3 | cust_nation, 4 | l_year, 5 | sum(volume) as revenue 6 | from 7 | ( 8 | select 9 | n1.n_name as supp_nation, 10 | n2.n_name as cust_nation, 11 | extract( 12 | year 13 | from 14 | l_shipdate 15 | ) as l_year, 16 | l_extendedprice * (1 - l_discount) as volume 17 | from 18 | supplier, 19 | lineitem, 20 | orders, 21 | customer, 22 | nation n1, 23 | nation n2 24 | where 25 | s_suppkey = l_suppkey 26 | and o_orderkey = l_orderkey 27 | and c_custkey = o_custkey 28 | and s_nationkey = n1.n_nationkey 29 | and c_nationkey = n2.n_nationkey 30 | and ( 31 | ( 32 | n1.n_name = 'FRANCE' 33 | and n2.n_name = 'GERMANY' 34 | ) 35 | or ( 36 | n1.n_name = 'GERMANY' 37 | and n2.n_name = 'FRANCE' 38 | ) 39 | ) 40 | and l_shipdate between '1995-01-01' 41 | and '1996-12-31' 42 | ) as shipping 43 | group by 44 | supp_nation, 45 | cust_nation, 46 | l_year 47 | order by 48 | supp_nation, 49 | cust_nation, 50 | l_year; 51 | -------------------------------------------------------------------------------- /lib/cmake/rapidjson.cmake: -------------------------------------------------------------------------------- 1 | include(ExternalProject) 2 | 3 | # Get rapidjson 4 | ExternalProject_Add( 5 | rapidjson_ep 6 | SOURCE_DIR "${CMAKE_SOURCE_DIR}/../submodules/rapidjson" 7 | PREFIX "third_party/rapidjson" 8 | INSTALL_DIR "${CMAKE_BINARY_DIR}/third_party/rapidjson/install" 9 | CMAKE_ARGS 10 | -G${CMAKE_GENERATOR} 11 | -DCMAKE_CXX_STANDARD=17 12 | -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} 13 | -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} 14 | -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} 15 | -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} 16 | -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} 17 | -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} 18 | -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} 19 | -DCMAKE_BUILD_TYPE=Release 20 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/third_party/rapidjson/install 21 | -DRAPIDJSON_BUILD_DOC=FALSE 22 | -DRAPIDJSON_BUILD_EXAMPLES=FALSE 23 | -DRAPIDJSON_BUILD_TESTS=FALSE 24 | -DRAPIDJSON_BUILD_THIRDPARTY_GTEST=FALSE 25 | DOWNLOAD_COMMAND "" 26 | UPDATE_COMMAND "") 27 | 28 | # Prepare json 29 | ExternalProject_Get_Property(rapidjson_ep install_dir) 30 | set(RAPIDJSON_INCLUDE_DIR ${install_dir}/include) 31 | file(MAKE_DIRECTORY ${RAPIDJSON_INCLUDE_DIR}) 32 | add_library(rapidjson INTERFACE) 33 | target_include_directories(rapidjson SYSTEM INTERFACE ${RAPIDJSON_INCLUDE_DIR}) 34 | 35 | # Dependencies 36 | add_dependencies(rapidjson rapidjson_ep) 37 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-app/src/components/feature_table.module.css: -------------------------------------------------------------------------------- 1 | .table { 2 | width: 100%; 3 | display: grid; 4 | grid-template-columns: max-content 1fr 1fr 1fr 1fr; 5 | border: 1px solid rgb(180, 180, 180); 6 | overflow-x: auto; 7 | background-color: rgb(255, 255, 255); 8 | font-size: 0.8rem; 9 | margin-top: 20px; 10 | } 11 | 12 | .table_title { 13 | grid-column: 1 / span 5; 14 | padding: 0px 8px; 15 | background-color: rgb(30, 30, 30); 16 | color: white; 17 | font-size: 1rem; 18 | } 19 | 20 | .table_anchor { 21 | grid-column: 1; 22 | background-color: rgb(30, 30, 30); 23 | color: white; 24 | text-align: center; 25 | } 26 | 27 | .table_column_header { 28 | padding: 0px 8px; 29 | background-color: rgb(220, 220, 220); 30 | text-align: center; 31 | background-color: rgb(30, 30, 30); 32 | color: white; 33 | font-size: 1rem; 34 | } 35 | 36 | .table_row_header { 37 | grid-column: 1; 38 | text-align: left; 39 | font-weight: 500; 40 | padding: 0px 16px 0px 8px; 41 | background-color: rgb(90, 90, 90); 42 | color: white; 43 | } 44 | 45 | .table_entry { 46 | display: flex; 47 | flex-direction: row; 48 | justify-content: center; 49 | align-items: center; 50 | border-left: 1px solid rgb(220, 220, 220); 51 | border-top: 1px solid rgb(220, 220, 220); 52 | padding: 2px 4px 2px 4px; 53 | min-width: 160px; 54 | font-weight: 500; 55 | } 56 | -------------------------------------------------------------------------------- /packages/duckdb-wasm-shell/crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "duckdb-wasm-shell" 3 | version = "0.1.0" 4 | authors = ["Andre Kohn "] 5 | edition = "2018" 6 | publish = false 7 | 8 | workspace = "../../../" 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [dependencies.web-sys] 14 | version = "0.3.51" 15 | features = [ 16 | 'console', 17 | 'Crypto', 18 | 'Document', 19 | 'Element', 20 | 'Node', 21 | 'NodeList', 22 | 'Window', 23 | 'MouseEvent', 24 | 'KeyboardEvent', 25 | 'HtmlTextAreaElement', 26 | 'HtmlCanvasElement', 27 | 'WebSocket', 28 | 'Performance', 29 | ] 30 | 31 | [dependencies] 32 | serde = { version = "1.0.126", features = ["derive"] } 33 | serde_json = "1.0.64" 34 | log = "0.4.14" 35 | scopeguard = "1.1.0" 36 | anyhow = "1.0.41" 37 | console_error_panic_hook = "0.1.6" 38 | wasm-bindgen = { version = "0.2.88", features = ["serde-serialize"] } 39 | wasm-bindgen-futures = "0.4.50" 40 | chrono = "0.4.19" 41 | js-sys = "0.3.51" 42 | arrow = { version = "52.0.0", features = ["csv", "ipc"] } 43 | lazy_static = "1.4.0" 44 | encode_unicode = "0.3.6" 45 | unicode-width = "0.1.8" 46 | ropey = "1.2.0" 47 | strum = "^0.20" 48 | strum_macros = "^0.20" 49 | getrandom = { version = "0.2", features = ["js"] } 50 | 51 | [dev-dependencies] 52 | wasm-bindgen-test = "0.3.12" 53 | 54 | [profile.release] 55 | lto = true 56 | opt-level = "s" 57 | 58 | [package.metadata.wasm-pack.profile.release] 59 | wasm-opt = false 60 | -------------------------------------------------------------------------------- /lib/cmake/spdlog.cmake: -------------------------------------------------------------------------------- 1 | include(ExternalProject) 2 | 3 | ExternalProject_Add( 4 | spdlog_ep 5 | SOURCE_DIR "${CMAKE_SOURCE_DIR}/../submodules/spdlog" 6 | INSTALL_DIR "${CMAKE_BINARY_DIR}/third_party/spdlog/install" 7 | PREFIX "${CMAKE_BINARY_DIR}/third_party/spdlog" 8 | CMAKE_ARGS 9 | -G${CMAKE_GENERATOR} 10 | -DCMAKE_CXX_STANDARD=17 11 | -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} 12 | -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} 13 | -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} 14 | -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} 15 | -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} 16 | -DCMAKE_BUILD_TYPE=Release 17 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/third_party/spdlog/install 18 | -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} 19 | -DSPDLOG_INSTALL=ON 20 | -DSPDLOG_BUILD_SHARED=OFF 21 | DOWNLOAD_COMMAND "" 22 | UPDATE_COMMAND "" 23 | BUILD_BYPRODUCTS /lib/libspdlog.a) 24 | 25 | ExternalProject_Get_Property(spdlog_ep install_dir) 26 | set(SPDLOG_INCLUDE_DIR ${install_dir}/include) 27 | set(SPDLOG_LIBRARY_PATH ${install_dir}/lib/libspdlog.a) 28 | file(MAKE_DIRECTORY ${SPDLOG_INCLUDE_DIR}) 29 | 30 | add_library(spdlog STATIC IMPORTED) 31 | set_property(TARGET spdlog PROPERTY IMPORTED_LOCATION ${SPDLOG_LIBRARY_PATH}) 32 | set_property( 33 | TARGET spdlog 34 | APPEND 35 | PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SPDLOG_INCLUDE_DIR}) 36 | 37 | add_dependencies(spdlog spdlog_ep) 38 | --------------------------------------------------------------------------------