Public
Edited
Oct 25, 2023
1 fork
Insert cell
Insert cell
viewof runbtn = Inputs.toggle({ label: "Run" })
Insert cell
{
runbtn;
let i = 0;
let invalidated = false;
// Stop the cycle when re-executed
invalidation.then(() => {
// Do clean-up before the next re-evaluation of the cell
invalidated = true;
});
while (runbtn && !invalidated) {
let filter = await duckDBFilter();
let client = await filter.initialize(cars);
await filter.clearInstance();
console.log("🚫 Iteration ", ++i);
}
}
Insert cell
// import { DuckDBClient } from "@kasivisu4/duckdb"
Insert cell
// client._db.disconnect()
Insert cell
Select a data source…
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
viewof factedSearch = FacetedSearch(cars, { filter: duckDBFilter })
Insert cell
factedSearch.filters
Insert cell
factedSearch.log
Insert cell
async function duckDBFilter() {
const tableName = "duck_db_table";
let filterName = "duckDB";
let client, log;

// Initialize the data
async function initialize(data, log_) {
log = log_;
let err;
try {
log?.push({
msg: `${filterName}: Initializing Data`,
level: 2
});
client = await DuckDBClient.of({ [tableName]: data });
log?.push({
msg: `${filterName}: Data initialized`,
level: 2
});
return client;
} catch (error) {
console.log(error);
}
}

//Filter the data based on the filters map and log the current selected col value
async function filterData(filters) {
//Generate SQL statement from the filters map
const select_sql = filtersToSQL(filters, { tableName });
let res;
let err;
try {
log?.push({
msg: `${filterName}: Filtering Data based on provided filters ${JSON.stringify(
Object.fromEntries(filters)
)}`,
level: 2
});

log?.push({
msg: `Generated Sql : ${select_sql})}`,
level: 2
});

res = await client.query(select_sql);

log?.push({
msg: `${filterName}: Filtered ${res.length} records`,
level: 2
});
} catch (error) {
console.error(filterName, err);
}
return res;
}

async function getClient() {
return client;
}

async function clearInstance() {
console.log("clearing Instance");

// John: Before killing everything, maybe disconnect and close the db
// https://shell.duckdb.org/docs/classes/index.AsyncDuckDB.html
await client._db.disconnect();
await client._db._worker.terminate();
console.log("cleared Instance");
}

return {
initialize,
filterData,
filterName,
getClient,
clearInstance
};
}
Insert cell
function filtersToSQL(filters, { tableName = "duck_db_table" } = {}) {
// const getAttrExpressionCategorical = (filter) =>
// ` ${filter.selected
// .map((val) => ` "${filter.attr}" = '${val}' `)
// .join(" OR ")} `;
const getAttrExpressionCategorical = (filter) => {
if (filter.selected.length != 0) {
return ` "${filter.attr}" in ('${filter.selected
.map((d) => d?.toString().replaceAll("'", "''"))
.join("', '")}')`;
}
return ` "${filter.attr} = ''"`;
};

const getAttrExpressionRange = (filter) =>
`"${filter.attr}" >= ${filter.selected[0]} AND "${filter.attr}" <= ${filter.selected[1]}`;

const getAttrExpression = (filter) =>
filter.selected && filter.selected.length !== 0 // If none selected return empty
? `( ${
filter.type === "Q"
? getAttrExpressionRange(filter)
: filter.type === "C"
? getAttrExpressionCategorical(filter)
: ""
} )
`
: ` "${filter.attr}" ='' `; // TODO what should we do if no checkbox is selected?

const getWhereClause = (filters) =>
` ${Array.from(filters.values())
.map(getAttrExpression)
.filter((d) => d) // ignore empty filters
.join(" AND ")} `;

let select_sql = `SELECT * FROM ${tableName} WHERE ${getWhereClause(
filters
)} ;`;

console.log("duckdb query", { select_sql });
return select_sql;
}
Insert cell
a = new Blob([cars], { type: "text/csv" })
Insert cell
new FURL.createObjectURL(a)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
DuckDBClient.of({name: data})
Insert cell
stdlib = {
return require(await FileAttachment("stdlib@1.js").url());
// try {
// return await require(`http://localhost:8080/dist/TimeSearcher.js?${Date.now()}`);
// } catch (e) {
// return await require("time-searcher-plus");
// // return require(await FileAttachment("TimeSearcher@1.js").url())
// }
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more