From 99d22249efae4955ecf676cace631d6c7aee70ee Mon Sep 17 00:00:00 2001 From: zhangwenjian Date: Fri, 25 Sep 2026 20:00:30 +0800 Subject: [PATCH] =?UTF-8?q?fix=F0=9F=90=9B:=20refuse=20to=20generate=20a?= =?UTF-8?q?=20table=20whose=20key=20is=20not=20one=20column?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The templates address a row by a single key: one field on the model, one path parameter, one value per row in a delete. A table with no primary key rendered a model whose GetId returned an empty field name, and a composite key was silently narrowed to whichever of its columns the importer read last. Both wrote files that break the build of the whole module. Preview and NOActionsGen now check first and return an error naming the table and, for a composite key, its columns. Nothing is written. --- app/other/apis/tools/gen.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/app/other/apis/tools/gen.go b/app/other/apis/tools/gen.go index 02701620..cc673b78 100644 --- a/app/other/apis/tools/gen.go +++ b/app/other/apis/tools/gen.go @@ -131,6 +131,10 @@ func (e Gen) Preview(c *gin.Context) { // are not interchangeable stand-ins for each other and should not be // assumed to be. tab.MLTBName = strings.Replace(tab.TBName, "_", "-", -1) + if err := requireSinglePrimaryKey(tab); err != nil { + e.Error(500, err, err.Error()) + return + } // R2: infer a width for any column the config page left at colWidth's 0 // sentinel, before vue.go.template reads .ColWidth - see column_width.go. applyInferredColumnWidths(tab.Columns) @@ -221,6 +225,10 @@ func (e Gen) NOActionsGen(c *gin.Context, tab tools.SysTables) { e.Context = c log := e.GetLogger() tab.MLTBName = strings.Replace(tab.TBName, "_", "-", -1) + if err := requireSinglePrimaryKey(tab); err != nil { + e.Error(500, err, err.Error()) + return + } // R2: see the matching call and comment in Preview above. applyInferredColumnWidths(tab.Columns) @@ -502,3 +510,26 @@ func (e Gen) GenMenuAndApi(c *gin.Context) { e.OK("", "数据生成成功!") } + +// requireSinglePrimaryKey refuses a table whose primary key is not exactly one +// column. The templates address a row by a single key - one field on the +// model, one path parameter, one value per row in a delete - so a table with +// no primary key, or a composite one, has no shape they can render: generating +// it anyway writes a model whose GetId names nothing, or silently keys the +// whole table on whichever key column happened to be imported last. +func requireSinglePrimaryKey(tab tools.SysTables) error { + var keys []string + for _, c := range tab.Columns { + if c.Pk { + keys = append(keys, c.ColumnName) + } + } + switch len(keys) { + case 1: + return nil + case 0: + return fmt.Errorf("表 %s 没有主键,代码生成需要恰好一个主键列", tab.TBName) + default: + return fmt.Errorf("表 %s 是联合主键(%s),代码生成需要恰好一个主键列", tab.TBName, strings.Join(keys, ", ")) + } +}