package db import ( "fmt" "strings" "testing" ) // TestDialectQuoteIdentifier 测试方言的 QuoteIdentifier 方法 func TestDialectQuoteIdentifier(t *testing.T) { tests := []struct { name string dialect Dialect input string expected string }{ // MySQL 方言测试 {"MySQL simple", &MySQLDialect{}, "name", "`name`"}, {"MySQL with backticks", &MySQLDialect{}, "`name`", "`name`"}, {"MySQL with quotes", &MySQLDialect{}, "\"name\"", "`name`"}, // PostgreSQL 方言测试 {"PostgreSQL simple", &PostgreSQLDialect{}, "name", "\"name\""}, {"PostgreSQL with backticks", &PostgreSQLDialect{}, "`name`", "\"name\""}, {"PostgreSQL with quotes", &PostgreSQLDialect{}, "\"name\"", "\"name\""}, // SQLite 方言测试 {"SQLite simple", &SQLiteDialect{}, "name", "\"name\""}, {"SQLite with backticks", &SQLiteDialect{}, "`name`", "\"name\""}, {"SQLite with quotes", &SQLiteDialect{}, "\"name\"", "\"name\""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.dialect.QuoteIdentifier(tt.input) if result != tt.expected { t.Errorf("QuoteIdentifier(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } // TestDialectQuoteChar 测试方言的 QuoteChar 方法 func TestDialectQuoteChar(t *testing.T) { tests := []struct { name string dialect Dialect expected string }{ {"MySQL", &MySQLDialect{}, "`"}, {"PostgreSQL", &PostgreSQLDialect{}, "\""}, {"SQLite", &SQLiteDialect{}, "\""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.dialect.QuoteChar() if result != tt.expected { t.Errorf("QuoteChar() = %q, want %q", result, tt.expected) } }) } } // TestIdentifierProcessorTableName 测试表名处理 func TestIdentifierProcessorTableName(t *testing.T) { tests := []struct { name string dialect Dialect prefix string input string expected string }{ // MySQL 无前缀 {"MySQL no prefix", &MySQLDialect{}, "", "order", "`order`"}, {"MySQL no prefix with backticks", &MySQLDialect{}, "", "`order`", "`order`"}, // MySQL 有前缀 {"MySQL with prefix", &MySQLDialect{}, "app_", "order", "`app_order`"}, {"MySQL with prefix and backticks", &MySQLDialect{}, "app_", "`order`", "`app_order`"}, // PostgreSQL 无前缀 {"PostgreSQL no prefix", &PostgreSQLDialect{}, "", "order", "\"order\""}, // PostgreSQL 有前缀 {"PostgreSQL with prefix", &PostgreSQLDialect{}, "app_", "order", "\"app_order\""}, {"PostgreSQL with prefix and quotes", &PostgreSQLDialect{}, "app_", "\"order\"", "\"app_order\""}, // SQLite 有前缀 {"SQLite with prefix", &SQLiteDialect{}, "app_", "user", "\"app_user\""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { processor := NewIdentifierProcessor(tt.dialect, tt.prefix) result := processor.ProcessTableName(tt.input) if result != tt.expected { t.Errorf("ProcessTableName(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } // TestIdentifierProcessorColumn 测试列名处理(包括 table.column 格式) func TestIdentifierProcessorColumn(t *testing.T) { tests := []struct { name string dialect Dialect prefix string input string expected string }{ // 单独列名 {"MySQL simple column", &MySQLDialect{}, "", "name", "`name`"}, {"MySQL simple column with prefix", &MySQLDialect{}, "app_", "name", "`name`"}, // table.column 格式 {"MySQL table.column no prefix", &MySQLDialect{}, "", "order.name", "`order`.`name`"}, {"MySQL table.column with prefix", &MySQLDialect{}, "app_", "order.name", "`app_order`.`name`"}, {"MySQL table.column with backticks", &MySQLDialect{}, "app_", "`order`.name", "`app_order`.`name`"}, // PostgreSQL {"PostgreSQL table.column with prefix", &PostgreSQLDialect{}, "app_", "order.name", "\"app_order\".\"name\""}, {"PostgreSQL table.column with quotes", &PostgreSQLDialect{}, "app_", "\"order\".name", "\"app_order\".\"name\""}, // SQLite {"SQLite table.column with prefix", &SQLiteDialect{}, "app_", "user.email", "\"app_user\".\"email\""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { processor := NewIdentifierProcessor(tt.dialect, tt.prefix) result := processor.ProcessColumn(tt.input) if result != tt.expected { t.Errorf("ProcessColumn(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } // TestIdentifierProcessorConditionString 测试条件字符串处理 func TestIdentifierProcessorConditionString(t *testing.T) { tests := []struct { name string dialect Dialect prefix string input string contains []string // 结果应该包含这些字符串 }{ // MySQL 简单条件 { "MySQL simple condition", &MySQLDialect{}, "app_", "user.id = order.user_id", []string{"`app_user`", "`app_order`"}, }, // MySQL 复杂条件 { "MySQL complex condition", &MySQLDialect{}, "app_", "user.id = order.user_id AND order.status = 1", []string{"`app_user`", "`app_order`"}, }, // PostgreSQL { "PostgreSQL condition", &PostgreSQLDialect{}, "app_", "user.id = order.user_id", []string{"\"app_user\"", "\"app_order\""}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { processor := NewIdentifierProcessor(tt.dialect, tt.prefix) result := processor.ProcessConditionString(tt.input) for _, expected := range tt.contains { if !strings.Contains(result, expected) { t.Errorf("ProcessConditionString(%q) = %q, should contain %q", tt.input, result, expected) } } }) } } // TestHoTimeDBHelperMethods 测试 HoTimeDB 的辅助方法 T() 和 C() func TestHoTimeDBHelperMethods(t *testing.T) { // 创建 MySQL 数据库实例 mysqlDB := &HoTimeDB{ Type: "mysql", Prefix: "app_", } mysqlDB.initDialect() // 测试 T() 方法 t.Run("MySQL T() method", func(t *testing.T) { result := mysqlDB.T("order") expected := "`app_order`" if result != expected { t.Errorf("T(\"order\") = %q, want %q", result, expected) } }) // 测试 C() 方法(两个参数) t.Run("MySQL C() method with two args", func(t *testing.T) { result := mysqlDB.C("order", "name") expected := "`app_order`.`name`" if result != expected { t.Errorf("C(\"order\", \"name\") = %q, want %q", result, expected) } }) // 测试 C() 方法(一个参数,点号格式) t.Run("MySQL C() method with dot notation", func(t *testing.T) { result := mysqlDB.C("order.name") expected := "`app_order`.`name`" if result != expected { t.Errorf("C(\"order.name\") = %q, want %q", result, expected) } }) // 创建 PostgreSQL 数据库实例 pgDB := &HoTimeDB{ Type: "postgres", Prefix: "app_", } pgDB.initDialect() // 测试 PostgreSQL 的 T() 方法 t.Run("PostgreSQL T() method", func(t *testing.T) { result := pgDB.T("order") expected := "\"app_order\"" if result != expected { t.Errorf("T(\"order\") = %q, want %q", result, expected) } }) // 测试 PostgreSQL 的 C() 方法 t.Run("PostgreSQL C() method", func(t *testing.T) { result := pgDB.C("order", "name") expected := "\"app_order\".\"name\"" if result != expected { t.Errorf("C(\"order\", \"name\") = %q, want %q", result, expected) } }) } // 打印测试结果(用于调试) func ExampleIdentifierProcessor() { // MySQL 示例 mysqlProcessor := NewIdentifierProcessor(&MySQLDialect{}, "app_") fmt.Println("MySQL:") fmt.Println(" Table:", mysqlProcessor.ProcessTableName("order")) fmt.Println(" Column:", mysqlProcessor.ProcessColumn("order.name")) fmt.Println(" Condition:", mysqlProcessor.ProcessConditionString("user.id = order.user_id")) // PostgreSQL 示例 pgProcessor := NewIdentifierProcessor(&PostgreSQLDialect{}, "app_") fmt.Println("PostgreSQL:") fmt.Println(" Table:", pgProcessor.ProcessTableName("order")) fmt.Println(" Column:", pgProcessor.ProcessColumn("order.name")) fmt.Println(" Condition:", pgProcessor.ProcessConditionString("user.id = order.user_id")) // Output: // MySQL: // Table: `app_order` // Column: `app_order`.`name` // Condition: `app_user`.`id` = `app_order`.`user_id` // PostgreSQL: // Table: "app_order" // Column: "app_order"."name" // Condition: "app_user"."id" = "app_order"."user_id" }