fix🐛: the mysql-only guard never fired

pkg.Assert panics when its condition is false, so pkg.Assert(true,
"目前只支持mysql数据库") is a no-op. On postgres or sqlserver the code
generator did not report that it needs MySQL: DBTables returned an empty
list with a nil error, and DBColumns ran its query on the zero-value
*gorm.DB left over from the branch that never assigned, which is a nil
dereference rather than a message.

Assert the driver up front instead of asserting a constant in an else,
which also removes the placeholder *gorm.DB the fall-through relied on.
DBColumns.GetPage had no guard at all and gets the same one.
This commit is contained in:
zhangwenjian
2026-08-23 13:19:15 +08:00
parent d16f5e7180
commit f201792d8f
3 changed files with 83 additions and 46 deletions
+11 -19
View File
@@ -24,46 +24,38 @@ type DBColumns struct {
}
func (e *DBColumns) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBColumns, int, error) {
pkg.Assert(config.DatabaseConfig.Driver == "mysql", "目前只支持mysql数据库", 500)
var doc []DBColumns
var count int64
table := new(gorm.DB)
if e.TableName == "" {
return nil, 0, errors.New("table name cannot be empty")
}
if config.DatabaseConfig.Driver == "mysql" {
table = tx.Table("information_schema.`COLUMNS`")
table = table.Where("table_schema= ? ", config.GenConfig.DBName)
table = table.Where("TABLE_NAME = ?", e.TableName)
}
table := tx.Table("information_schema.`COLUMNS`")
table = table.Where("table_schema= ? ", config.GenConfig.DBName)
table = table.Where("TABLE_NAME = ?", e.TableName)
if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil {
return nil, 0, err
}
//table.Count(&count)
return doc, int(count), nil
}
func (e *DBColumns) GetList(tx *gorm.DB) ([]DBColumns, error) {
var doc []DBColumns
table := new(gorm.DB)
pkg.Assert(config.DatabaseConfig.Driver == "mysql", "目前只支持mysql数据库", 500)
var doc []DBColumns
if e.TableName == "" {
return nil, errors.New("table name cannot be empty")
}
if config.DatabaseConfig.Driver == "mysql" {
table = tx.Table("information_schema.columns")
table = table.Where("table_schema= ? ", config.GenConfig.DBName)
table = table.Where("TABLE_NAME = ?", e.TableName).Order("ORDINAL_POSITION asc")
} else {
pkg.Assert(true, "目前只支持mysql数据库", 500)
}
table := tx.Table("information_schema.columns")
table = table.Where("table_schema= ? ", config.GenConfig.DBName)
table = table.Where("TABLE_NAME = ?", e.TableName).Order("ORDINAL_POSITION asc")
if err := table.Find(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
}
+20 -27
View File
@@ -20,43 +20,36 @@ type DBTables struct {
}
func (e *DBTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBTables, int, error) {
pkg.Assert(config2.DatabaseConfig.Driver == "mysql", "目前只支持mysql数据库", 500)
var doc []DBTables
table := new(gorm.DB)
var count int64
if config2.DatabaseConfig.Driver == "mysql" {
table = tx.Table("information_schema.tables")
table = table.Where("TABLE_NAME not in (select table_name from `" + config2.GenConfig.DBName + "`.sys_tables) ")
table = table.Where("table_schema= ? ", config2.GenConfig.DBName)
table := tx.Table("information_schema.tables")
table = table.Where("TABLE_NAME not in (select table_name from `" + config2.GenConfig.DBName + "`.sys_tables) ")
table = table.Where("table_schema= ? ", config2.GenConfig.DBName)
if e.TableName != "" {
table = table.Where("TABLE_NAME = ?", e.TableName)
}
if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil {
return nil, 0, err
}
} else {
pkg.Assert(true, "目前只支持mysql数据库", 500)
if e.TableName != "" {
table = table.Where("TABLE_NAME = ?", e.TableName)
}
if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil {
return nil, 0, err
}
//table.Count(&count)
return doc, int(count), nil
}
func (e *DBTables) Get(tx *gorm.DB) (DBTables, error) {
pkg.Assert(config2.DatabaseConfig.Driver == "mysql", "目前只支持mysql数据库", 500)
var doc DBTables
if config2.DatabaseConfig.Driver == "mysql" {
table := tx.Table("information_schema.tables")
table = table.Where("table_schema= ? ", config2.GenConfig.DBName)
if e.TableName == "" {
return doc, errors.New("table name cannot be empty")
}
table = table.Where("TABLE_NAME = ?", e.TableName)
if err := table.First(&doc).Error; err != nil {
return doc, err
}
} else {
pkg.Assert(true, "目前只支持mysql数据库", 500)
if e.TableName == "" {
return doc, errors.New("table name cannot be empty")
}
table := tx.Table("information_schema.tables")
table = table.Where("table_schema= ? ", config2.GenConfig.DBName)
table = table.Where("TABLE_NAME = ?", e.TableName)
if err := table.First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
@@ -0,0 +1,52 @@
package tools
import (
"strings"
"testing"
"github.com/go-admin-team/go-admin-core/sdk/config"
"gorm.io/gorm"
)
// The generator reads MySQL's information_schema and nothing else. Every entry
// point says so, but the guard used to be written pkg.Assert(true, ...), which
// never fires: pkg.Assert panics when its condition is false. A non-mysql
// deployment therefore fell through to a query built on a zero-value *gorm.DB.
//
// tx is nil on purpose - the assertion has to come before anything touches it.
func TestCodegenModelsRefuseNonMySQLDrivers(t *testing.T) {
previous := config.DatabaseConfig.Driver
config.DatabaseConfig.Driver = "postgres"
t.Cleanup(func() { config.DatabaseConfig.Driver = previous })
cases := map[string]func(*gorm.DB){
"DBTables.GetPage": func(tx *gorm.DB) {
_, _, _ = new(DBTables).GetPage(tx, 10, 1)
},
"DBTables.Get": func(tx *gorm.DB) {
_, _ = (&DBTables{TableName: "sys_user"}).Get(tx)
},
"DBColumns.GetPage": func(tx *gorm.DB) {
_, _, _ = (&DBColumns{TableName: "sys_user"}).GetPage(tx, 10, 1)
},
"DBColumns.GetList": func(tx *gorm.DB) {
_, _ = (&DBColumns{TableName: "sys_user"}).GetList(tx)
},
}
for name, call := range cases {
t.Run(name, func(t *testing.T) {
defer func() {
raised := recover()
if raised == nil {
t.Fatal("driver is not mysql and the call went through anyway")
}
msg, ok := raised.(string)
if !ok || !strings.Contains(msg, "目前只支持mysql数据库") {
t.Fatalf("want the mysql-only assertion, got %v", raised)
}
}()
call(nil)
})
}
}