Skip to content

Conversation

@Fil
Copy link
Contributor

@Fil Fil commented Oct 30, 2025

This is a suggestion to surface the database's type in the DatabaseClient options.

When we create an instance without options, we return the type derived from databases.json (or the database name, when applicable).

This allows to write SQL statements that depends on the database's dialect.

const db = new DatabaseClient("experiments");
db.options.type; // "duckdb"

TODO

…te an instance without options, return the type derived from databases.json (or the name)
@Fil
Copy link
Contributor Author

Fil commented Nov 20, 2025

Analyzing https://github.com/observablehq/charts/commit/809883a018be17afb982b838152d9d7811bc98a8 + https://github.com/observablehq/charts/commit/2de479e4df0f239c9b2bfde0f257051c30c2d736 by @mbostock:

  • the switch happens on database.dialect, not database.options.type like I am suggesting here
  • the derivation of the dialect is made at the very last moment, when we actually need to run the query 👍
  • only DuckDBClient has a dialect for now (other database clients are undefined and default to defaults).


/**
* Reads partial database configurations from the .observable/databases.json file.
* For security reasons, no identifiers or passwords are returned.
Copy link
Member

@mbostock mbostock Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this redaction accomplishes anything, since any process can read the .observable/databases.json file directly. I guess if we want to call this getDatabaseTypes then we could have a Map<string, string> that tells you the database types… but it’s probably just fine to load the unredacted database configs, too.

Comment on lines +18 to +19
// if options are passed, don't change them
if (node.arguments.length !== 1) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should pass {dialect} as a third argument, and not allow more than two arguments (or fewer than one) argument, and not allow spread arguments.

else if (name === "sqlite") type = "sqlite";
else if (/\.duckdb$/i.test(name)) type = "duckdb";
else if (/\.db$/i.test(name)) type = "sqlite";
else throw new Error(`database not found: ${name}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be a SyntaxError, not an internal Error. Ideally in the .duckdb and .db case we’d also check that the files exist (and SyntaxError if they don’t), but I’m not sure if that’s possible in this context. Or one possibility is that we find the .duckdb and .db files ahead of time when we call getDatabaseConfigs (because these files implicitly represent databases).

Copy link
Member

@mbostock mbostock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking aloud, I wonder if rewriting DatabaseClient calls is correct, or if this should be more like what we’ve done with FileAttachment in the past (which also is yet to be implemented in Notebook Kit), which is that you register the databases separately when initializing the runtime…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants