package aceboot::orm.tests

import aceboot::orm.common.*
import aceboot::orm.sqlite.*
import aceboot::orm.mysql.*
import aceboot::orm.postgres.*

import std.unittest.*
import std.unittest.testmacro.*

@Test
func test_exception_macro_produces_real_exception() {
    // OrmException 由 @Exception 宏生成,应是真正的 Exception 子类、message 构造器可用。
    var msg = ""
    try {
        throw OrmException("boom")
    } catch (e: Exception) {
        msg = e.message
    }
    @Expect(msg, "boom")
}

@Test
func test_dialect_placeholders() {
    @Expect(SqliteDialect().placeholder(0), "?")
    @Expect(SqliteDialect().placeholder(3), "?")
    @Expect(PostgresDialect().placeholder(0), "$1") // PG 是 $n(1 基)
    @Expect(PostgresDialect().placeholder(2), "$3")
    @Expect(MySqlDialect().placeholder(0), "?")
}

@Test
func test_dialect_returning() {
    @Expect(PostgresDialect().usesReturning(), true)
    @Expect(SqliteDialect().usesReturning(), false)
    @Expect(MySqlDialect().usesReturning(), false)
}

@Test
func test_dialect_create_table_per_db() {
    let cols = [
        ColumnSpec("id", DbType.TInt, true, ""),
        ColumnSpec("name", DbType.TText, false, ""),
        ColumnSpec("uid", DbType.TInt, false, "users")
    ]
    @Expect(
        SqliteDialect().createTable("t", cols),
        "CREATE TABLE IF NOT EXISTS t(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, uid INTEGER, FOREIGN KEY(uid) REFERENCES users(id))"
    )
    let pg = PostgresDialect().createTable("t", cols)
    @Expect(pg.contains("id SERIAL PRIMARY KEY"), true)
    @Expect(pg.contains("FOREIGN KEY(uid) REFERENCES users(id)"), true)
    let my = MySqlDialect().createTable("t", cols)
    @Expect(my.contains("id INT AUTO_INCREMENT PRIMARY KEY"), true)
    @Expect(my.contains("name VARCHAR(255)"), true)
}

@Test
func test_column_comments_postgres() {
    let cols = [
        ColumnSpec("id", DbType.TInt, true, ""),
        ColumnSpec("name", DbType.TText, false, "", comment: "the name"),
        ColumnSpec("age", DbType.TInt, false, "") // 无 comment,不产出条目
    ]
    let stmts = PostgresDialect().columnComments("t", cols)
    @Expect(stmts.size, 1)
    @Expect(stmts[0], "COMMENT ON COLUMN t.name IS 'the name'")
    // CREATE TABLE 本身不含 COMMENT(注释走独立语句)。
    @Expect(PostgresDialect().createTable("t", cols).contains("COMMENT"), false)
}

@Test
func test_column_comments_mysql_inline() {
    let cols = [
        ColumnSpec("id", DbType.TInt, true, ""),
        ColumnSpec("name", DbType.TText, false, "", comment: "the name"),
        ColumnSpec("age", DbType.TInt, false, "")
    ]
    let my = MySqlDialect().createTable("t", cols)
    @Expect(my.contains("COMMENT 'the name'"), true)
    // 无 comment 列不出现 COMMENT。
    @Expect(my.contains("age INT COMMENT"), false)
    // MySQL 不产出独立 COMMENT ON 语句。
    @Expect(MySqlDialect().columnComments("t", cols).size, 0)
}

@Test
func test_column_comments_sqlite_skipped() {
    let cols = [
        ColumnSpec("id", DbType.TInt, true, ""),
        ColumnSpec("name", DbType.TText, false, "", comment: "the name")
    ]
    // SQLite 建表 SQL 完全不含 COMMENT,且不产出独立语句。
    @Expect(SqliteDialect().createTable("t", cols).contains("COMMENT"), false)
    @Expect(SqliteDialect().columnComments("t", cols).size, 0)
}

@Test
func test_column_comment_escaping() {
    let cols = [ColumnSpec("note", DbType.TText, false, "", comment: "it's")]
    // PG 独立语句:单引号加倍。
    @Expect(PostgresDialect().columnComments("t", cols)[0], "COMMENT ON COLUMN t.note IS 'it''s'")
    // MySQL 内联:单引号加倍。
    @Expect(MySqlDialect().createTable("t", cols).contains("COMMENT 'it''s'"), true)
}