MySQL caps `text` at 65,535 bytes. A single base64 image attachment is allowed up to ~1.34MB by the chat route, so appending such a message fails with ER_DATA_TOO_LONG under the default strict mode. SQLite and PostgreSQL are unaffected because their text types are effectively unbounded. `mediumtext` holds 16MB, comfortably above the 2MB request cap. The migration keeps the parenthesised default expression that every other text default in this folder uses, because MySQL rejects a literal default on TEXT columns.
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
import path from "path";
|
|
import { MySqlContainer } from "@testcontainers/mysql";
|
|
import { eq } from "drizzle-orm";
|
|
import { drizzle } from "drizzle-orm/mysql2";
|
|
import { migrate } from "drizzle-orm/mysql2/migrator";
|
|
import mysql from "mysql2";
|
|
import { describe, expect, test } from "vitest";
|
|
|
|
import { DB_CASING } from "@homarr/core/infrastructure/db/constants";
|
|
|
|
import * as mysqlSchema from "../schema/mysql";
|
|
|
|
describe("Mysql Migration", () => {
|
|
test("should add all tables and keys specified in migration files", async () => {
|
|
const mysqlContainer = await new MySqlContainer("mysql:latest").start();
|
|
|
|
const connection = mysql.createConnection({
|
|
host: mysqlContainer.getHost(),
|
|
database: mysqlContainer.getDatabase(),
|
|
port: mysqlContainer.getPort(),
|
|
user: mysqlContainer.getUsername(),
|
|
password: mysqlContainer.getUserPassword(),
|
|
});
|
|
|
|
const database = drizzle(connection, {
|
|
schema: mysqlSchema,
|
|
mode: "default",
|
|
casing: DB_CASING,
|
|
});
|
|
|
|
// Run migrations and check if it works
|
|
await migrate(database, {
|
|
migrationsFolder: path.join(__dirname, "..", "migrations", "mysql"),
|
|
});
|
|
|
|
// Check if users table exists
|
|
await database.query.users.findMany();
|
|
|
|
// A single base64 image attachment already exceeds the 64KB that `text` holds on MySQL, so
|
|
// `assistant_message.content` has to be `mediumtext`. Everything below 64KB passes either way.
|
|
const largeContent = "x".repeat(200_000);
|
|
await database.insert(mysqlSchema.users).values({ id: "size-check-user", name: "size-check" });
|
|
await database.insert(mysqlSchema.assistantThreads).values({ id: "size-check-thread", userId: "size-check-user" });
|
|
await database.insert(mysqlSchema.assistantMessages).values({
|
|
id: "size-check-message",
|
|
threadId: "size-check-thread",
|
|
parentId: null,
|
|
content: largeContent,
|
|
});
|
|
const [storedMessage] = await database.query.assistantMessages.findMany({
|
|
where: eq(mysqlSchema.assistantMessages.id, "size-check-message"),
|
|
});
|
|
expect(storedMessage?.content).toHaveLength(largeContent.length);
|
|
|
|
connection.end();
|
|
await mysqlContainer.stop();
|
|
}, 120_000);
|
|
});
|