sql(mysql): the default database is mysql again

As before this branch and as the docs say. `mariadb://` without a database still selects none: its old
default, a database named `mariadb`, exists on no server unless somebody creates it, so the connection
failed with 1049.
This commit is contained in:
Jarred Sumner committed 2026-10-17 06:03:23 +00:00
1 parent d5a5ba6222
commit 78e0830cdd
5 files changed
+25 -19

No files matched your search

+9 -9
View File
@@ -422,7 +422,7 @@ Call `.raw()` before the query starts, that is before `await`, `.then()` or `.ex
### Result metadata
The array that a query resolves to has six more properties. They are not enumerable, so `console.log`, `Object.keys`, `JSON.stringify` and spreading only see the rows.
The array that a query resolves to has six more properties. `console.log`, `Object.keys` and spreading list `count`, `command`, `lastInsertRowid` and `affectedRows` next to the rows. `columns` and `statement` are not enumerable, and `JSON.stringify` only sees the rows.
| Property | Meaning | PostgreSQL | MySQL / MariaDB | SQLite |
| ----------------- | -------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------ |
@@ -819,13 +819,13 @@ An `sslmode` in the URL takes priority over both, and a mode in the `tls` or `ss
### MySQL and MariaDB Environment Variables
| MySQL | MariaDB | Default Value | Description |
| ---------------- | ------------------ | ------------- | ---------------------------------------------------------- |
| `MYSQL_HOST` | `MARIADB_HOST` | `localhost` | Database host |
| `MYSQL_PORT` | `MARIADB_PORT` | `3306` | Database port |
| `MYSQL_USER` | `MARIADB_USER` | `root` | Database user. Bun reads `USER`, then `USERNAME`, after it |
| `MYSQL_PASSWORD` | `MARIADB_PASSWORD` | (empty) | Database password |
| `MYSQL_DATABASE` | `MARIADB_DATABASE` | (none) | Database name |
| MySQL | MariaDB | Default Value | Description |
| ---------------- | ------------------ | --------------- | ---------------------------------------------------------- |
| `MYSQL_HOST` | `MARIADB_HOST` | `localhost` | Database host |
| `MYSQL_PORT` | `MARIADB_PORT` | `3306` | Database port |
| `MYSQL_USER` | `MARIADB_USER` | `root` | Database user. Bun reads `USER`, then `USERNAME`, after it |
| `MYSQL_PASSWORD` | `MARIADB_PASSWORD` | (empty) | Database password |
| `MYSQL_DATABASE` | `MARIADB_DATABASE` | `mysql`, (none) | Database name |
These variables do not select the adapter. Bun reads them for a client that is already MySQL or MariaDB, through its URL or the `adapter` option.
@@ -896,7 +896,7 @@ You can configure the connection manually by passing options to the `SQL` constr
| `port` | `5432` or `3306` | Database port |
| `username` | `postgres` or `root` | Database user |
| `password` | (empty) | A string, or a [function](#dynamic-passwords) that returns one |
| `database` | PostgreSQL: the user name | Database name. MySQL and MariaDB select none by default |
| `database` | PostgreSQL: the user name | Database name. MySQL: `mysql`. MariaDB selects none by default |
| `path` | | Unix socket to use instead of TCP. `socket` is an alias. On PostgreSQL, a directory gets `/.s.PGSQL.<port>` added |
| `tls` | `false` | `true`, an [SSL mode](#ssl-modes-overview), TLS options, or a `BunFile` with the CA certificate |
| `max` | `10` | Maximum number of connections in the [pool](#connection-pooling) |
+1 -1
View File
@@ -498,7 +498,7 @@ declare module "bun" {
/**
* Name of the database to connect to. `PGDATABASE`, `MYSQL_DATABASE` and
* `MARIADB_DATABASE` take priority over the database in a URL.
* @default The username value for PostgreSQL. MySQL and MariaDB select no database
* @default The username value for PostgreSQL, `"mysql"` for MySQL. MariaDB selects no database
*/
database?: string | undefined;
+1 -1
View File
@@ -684,7 +684,7 @@ function parseOptions(
envOf(prefix, "DATABASE") ||
query.database ||
(!isUnixUrl && decodeIfValid(urlPathname.slice(1))) ||
(isPostgres ? username : "");
(isPostgres ? username : adapter === "mysql" ? "mysql" : "");
let path =
options.path ||
@@ -255,9 +255,12 @@ describe("SQL adapter environment variable precedence", () => {
expect(options.options.username).toBe("mysql-user");
});
test.each(["mysql", "mariadb"] as const)("%s selects no database by default", adapter => {
expect(new SQL({ adapter, hostname: "localhost" }).options.database).toBe("");
expect(new SQL(`${adapter}://root@localhost/`).options.database).toBe("");
test.each([
["mysql", "mysql"],
["mariadb", ""],
] as const)("%s: the default database is %p", (adapter, database) => {
expect(new SQL({ adapter, hostname: "localhost" }).options.database).toBe(database);
expect(new SQL(`${adapter}://root@localhost/`).options.database).toBe(database);
});
test("should default to username as database name for PostgreSQL adapter", () => {
@@ -1241,7 +1244,7 @@ describe("SQL adapter environment variable precedence", () => {
"{ adapter: 'mysql' }: a PostgreSQL DATABASE_URL counts as not set",
{ DATABASE_URL: pg },
[{ adapter: "mysql" }],
{ adapter: "mysql", hostname: "localhost", port: 3306, username: "root", password: "", database: "" },
{ adapter: "mysql", hostname: "localhost", port: 3306, username: "root", password: "", database: "mysql" },
],
[
"{ adapter: 'postgres' }: a MySQL TLS_DATABASE_URL counts as not set, except for the TLS in its name",
@@ -1284,7 +1287,7 @@ describe("SQL adapter environment variable precedence", () => {
// `adapter` passes over the URL of another adapter's server. The server is not dialed and gets no credentials,
// but the connection is as well protected as that URL asks for.
const localPostgres = { adapter: "postgres", hostname: "localhost", port: 5432, password: "" };
const localMySQL = { adapter: "mysql", hostname: "localhost", port: 3306, password: "", database: "" };
const localMySQL = { adapter: "mysql", hostname: "localhost", port: 3306, password: "", database: "mysql" };
const postgres = [{ adapter: "postgres" }] as Row[2];
const mysql = [{ adapter: "mysql" }] as Row[2];
test.each<Row>([
@@ -1409,7 +1412,7 @@ describe("SQL adapter environment variable precedence", () => {
defaultPort,
defaultUser,
"",
adapter === "postgres" ? defaultUser : "",
adapter === "postgres" ? defaultUser : adapter === "mysql" ? "mysql" : "",
]);
setEnv(prefix, "e");
+5 -2
View File
@@ -612,11 +612,14 @@ console.log(JSON.stringify({ outcome, closed }));`,
Bun.inspect(result);
});
test.each(["mysql", "mariadb"])("%s:// without a database name selects no database", async scheme => {
test.each([
["mysql", "mysql"],
["mariadb", null],
])("%s:// without a database name selects %p", async (scheme, selected) => {
const url = `${scheme}://root:${password}@${container.host}:${container.port}`;
for (const suffix of ["", "/"]) {
await using db = new SQL({ ...getOptions(), url: url + suffix });
expect(await db`select database() as db`).toEqual([{ db: null }]);
expect(await db`select database() as db`).toEqual([{ db: selected }]);
}
});