From ec942357932b037f100edf3fef4e46889405067f Mon Sep 17 00:00:00 2001 From: Christian Banse Date: Fri, 27 Dec 2024 01:05:29 +0100 Subject: [PATCH 1/2] Passing SQLite comments to the generated struct This is a partial solution for #3430 for sqlite, which may or may not be adaptable for other engines. It basically looks for single-line comments before the CREATE command and in-between column definitions. --- internal/engine/sqlite/convert.go | 33 +++++++++++++++++++++++++++++++ internal/engine/sqlite/parse.go | 2 ++ 2 files changed, 35 insertions(+) diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index 29c06fb285..0e9bdb05f5 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -107,26 +107,59 @@ func (c *cc) convertAttach_stmtContext(n *parser.Attach_stmtContext) ast.Node { } func (c *cc) convertCreate_table_stmtContext(n *parser.Create_table_stmtContext) ast.Node { + tokenStream := n.GetParser().GetTokenStream().(*antlr.CommonTokenStream) + stmt := &ast.CreateTableStmt{ Name: parseTableName(n), IfNotExists: n.EXISTS_() != nil, + Comment: comment(tokenStream, n, false), } + for _, idef := range n.AllColumn_def() { if def, ok := idef.(*parser.Column_defContext); ok { typeName := "any" if def.Type_name() != nil { typeName = def.Type_name().GetText() } + stmt.Cols = append(stmt.Cols, &ast.ColumnDef{ Colname: identifier(def.Column_name().GetText()), IsNotNull: hasNotNullConstraint(def.AllColumn_constraint()), TypeName: &ast.TypeName{Name: typeName}, + Comment: comment(tokenStream, def, true), }) + } } return stmt } +// comment returns the comment associated with the given context. The parameter right indicates whether the comment is +// to the right or to the left of the context. +func comment(tokenStream *antlr.CommonTokenStream, ctx antlr.ParserRuleContext, right bool) string { + var ( + hiddenTokens []antlr.Token + comment string + ) + + if right { + hiddenTokens = tokenStream.GetHiddenTokensToRight(ctx.GetStop().GetTokenIndex()+1, antlr.TokenHiddenChannel) + } else { + hiddenTokens = tokenStream.GetHiddenTokensToLeft(ctx.GetStart().GetTokenIndex(), antlr.TokenHiddenChannel) + } + + for _, token := range hiddenTokens { + // Filter for single-line comments + if token.GetTokenType() == parser.SQLiteLexerSINGLE_LINE_COMMENT { + // Remove "--" and leading/trailing whitespaces + comment = strings.TrimSpace(strings.TrimPrefix(token.GetText(), "--")) + return comment + } + } + + return "" +} + func (c *cc) convertCreate_virtual_table_stmtContext(n *parser.Create_virtual_table_stmtContext) ast.Node { switch moduleName := n.Module_name().GetText(); moduleName { case "fts5": diff --git a/internal/engine/sqlite/parse.go b/internal/engine/sqlite/parse.go index 13425b156e..55c3b97e29 100644 --- a/internal/engine/sqlite/parse.go +++ b/internal/engine/sqlite/parse.go @@ -50,6 +50,7 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) { pp.AddErrorListener(el) // pp.BuildParseTrees = true tree := pp.Parse() + if el.err != "" { return nil, errors.New(el.err) } @@ -83,6 +84,7 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) { loc = stmt.GetStop().GetStop() + 2 } } + return stmts, nil } From 847fd6cc3c9d024012a9aa9ed2125bbc3e531825 Mon Sep 17 00:00:00 2001 From: Christian Banse Date: Fri, 27 Dec 2024 01:25:53 +0100 Subject: [PATCH 2/2] Take only comment inside CREATE query --- internal/engine/sqlite/convert.go | 15 +++++---------- internal/engine/sqlite/parse.go | 2 -- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index 0e9bdb05f5..b253078b1e 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -112,7 +112,7 @@ func (c *cc) convertCreate_table_stmtContext(n *parser.Create_table_stmtContext) stmt := &ast.CreateTableStmt{ Name: parseTableName(n), IfNotExists: n.EXISTS_() != nil, - Comment: comment(tokenStream, n, false), + Comment: comment(tokenStream, n.OPEN_PAR().GetSymbol()), } for _, idef := range n.AllColumn_def() { @@ -126,7 +126,7 @@ func (c *cc) convertCreate_table_stmtContext(n *parser.Create_table_stmtContext) Colname: identifier(def.Column_name().GetText()), IsNotNull: hasNotNullConstraint(def.AllColumn_constraint()), TypeName: &ast.TypeName{Name: typeName}, - Comment: comment(tokenStream, def, true), + Comment: comment(tokenStream, def.GetStop()), }) } @@ -134,19 +134,14 @@ func (c *cc) convertCreate_table_stmtContext(n *parser.Create_table_stmtContext) return stmt } -// comment returns the comment associated with the given context. The parameter right indicates whether the comment is -// to the right or to the left of the context. -func comment(tokenStream *antlr.CommonTokenStream, ctx antlr.ParserRuleContext, right bool) string { +// comment returns the comment associated with the given context. +func comment(tokenStream *antlr.CommonTokenStream, from antlr.Token) string { var ( hiddenTokens []antlr.Token comment string ) - if right { - hiddenTokens = tokenStream.GetHiddenTokensToRight(ctx.GetStop().GetTokenIndex()+1, antlr.TokenHiddenChannel) - } else { - hiddenTokens = tokenStream.GetHiddenTokensToLeft(ctx.GetStart().GetTokenIndex(), antlr.TokenHiddenChannel) - } + hiddenTokens = tokenStream.GetHiddenTokensToRight(from.GetTokenIndex()+1, antlr.TokenHiddenChannel) for _, token := range hiddenTokens { // Filter for single-line comments diff --git a/internal/engine/sqlite/parse.go b/internal/engine/sqlite/parse.go index 55c3b97e29..13425b156e 100644 --- a/internal/engine/sqlite/parse.go +++ b/internal/engine/sqlite/parse.go @@ -50,7 +50,6 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) { pp.AddErrorListener(el) // pp.BuildParseTrees = true tree := pp.Parse() - if el.err != "" { return nil, errors.New(el.err) } @@ -84,7 +83,6 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) { loc = stmt.GetStop().GetStop() + 2 } } - return stmts, nil }