问题记录

7 阅读1分钟
import { Input, Card, Table, Spin, Button, Space, Alert } from 'antd'
import { useState } from 'react'
import * as duckdb from '@duckdb/duckdb-wasm';

import duckdb_wasm from '@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm'
import duckdb_wasm_next from '@duckdb/duckdb-wasm/dist/duckdb-eh.wasm'

// const MANUAL_BUNDLES = {
//   mvp: {
//     mainModule: duckdb_wasm,
//     mainWorker: new URL('@duckdb/duckdb-wasm/dist/duckdb-browser-mvp.worker.js', import.meta.url).toString(),
//   },
//   eh: {
//     mainModule: duckdb_wasm_next,
//     mainWorker: new URL('@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js', import.meta.url).toString(),
//   },
// };

// import duckdb_wasm from './package/dist/duckdb-mvp.wasm';
// import duckdb_wasm_next from './package/dist/duckdb-eh.wasm';

const MANUAL_BUNDLES = {
  mvp: {
    mainModule: duckdb_wasm,
    mainWorker: new URL('./package/dist/duckdb-browser-mvp.worker.js', import.meta.url).toString(),
  },
  eh: {
    mainModule: duckdb_wasm_next,
    mainWorker: new URL('./package/dist/duckdb-browser-eh.worker.js', import.meta.url).toString(),
  },
};
const { TextArea } = Input
export function App() {
  const [loading, setLoading] = useState(false)
  const [dataSource, setDataSource] = useState([])
  const [columns, setColumns] = useState([])
  const [inputValue, setInputValue] = useState(
    "SELECT * FROM 'https://shell.duckdb.org/data/tpch/0_01/parquet/orders.parquet' LIMIT 10",
  )
  const [errorText, setErrorText] = useState('')
  async function duckdbSearch() {
    const sql = inputValue
    try {
      // 基于浏览器选择bundle
      // const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles()
      // const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES)
      // const worker_url = URL.createObjectURL(
      //   new Blob([`importScripts("${bundle.mainWorker}");`], {
      //     type: 'text/javascript',
      //   }),
      // )
      // const worker = new Worker(worker_url)

      console.log('import.meta.url',import.meta.url)
      console.log('-------------static', new URL('./package/dist/duckdb-browser-eh.worker.js', import.meta.url).toString())
      // console.log('===========webpack', new URL('@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js', import.meta.url).toString())

      const bundle = await duckdb.selectBundle(MANUAL_BUNDLES)
      const worker = new Worker(bundle.mainWorker)

      console.log('bundle', bundle)
      console.log('worker', worker)
      const logger = new duckdb.ConsoleLogger()
      const db = new duckdb.AsyncDuckDB(logger, worker)
      await db.instantiate(bundle.mainModule, bundle.pthreadWorker)

      // 连接,查询
      const conn = await db.connect()
      let res = await conn.query(sql)
      console.log('res', res)
      // 处理返回数据格式
      if (res.numCols && res.numRows) {
        const items = JSON.parse(JSON.stringify(res.toArray()))
        console.log('items', items)
        const col = Object.keys(items[0]).map((key) => {
          return {
            title: key,
            dataIndex: key,
            key: key,
            width: `${100 / res.numCols}%`,
          }
        })
        const data = items.map((item, index) => {
          return {
            ...item,
            key: index,
          }
        })
        setColumns(col)
        setDataSource(data)
        console.log('---------col', col)
      }

      setLoading(false)

      // 关闭连接
      // URL.revokeObjectURL(worker_url)
      // await conn.close()
      // await db.terminate()
      // await worker.terminate()
    } catch (error) {
      setLoading(false)
      setErrorText(error.toString())
    }
  }
  return (
    <div>
      <Card title="Card" size="small">
        <Space
          direction="vertical"
          size="middle"
          style={{
            display: 'flex',
          }}
        >
          <TextArea
            size='large'
            defaultValue="default"
            placeholder="在此处键入sql语句"
            autoSize
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
          >
          </TextArea>
          {/* <textarea value={inputValue}></textarea> */}
          <Button
            type="primary"
            loading={loading}
            onClick={() => {
              setLoading(true)
              duckdbSearch()
            }}
          >
            {'> '}Execute
          </Button>
          <Spin spinning={loading}>
            {!errorText && (
              <Table
                dataSource={dataSource}
                columns={columns}
                bordered
                pagination={false}
                scroll={{
                  y: 300,
                }}
              />
            )}
            {errorText && (
              <Alert
                message="Error"
                description={errorText}
                type="error"
                showIcon
              />
            )}
          </Spin>
        </Space>
      </Card>
    </div>
  )
}
export default App