From 78ab3296c9345961c7565e65e1eb9d41393dcb2c Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 17 May 2022 11:39:53 +0300 Subject: [PATCH] checker: fix orm bug, when a joined table field context replaced the original table field context --- vlib/v/checker/orm.v | 8 +++++ vlib/v/tests/orm_joined_tables_select_test.v | 37 ++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 vlib/v/tests/orm_joined_tables_select_test.v diff --git a/vlib/v/checker/orm.v b/vlib/v/checker/orm.v index 053bc12d57..4ece161779 100644 --- a/vlib/v/checker/orm.v +++ b/vlib/v/checker/orm.v @@ -12,7 +12,11 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type { } sym := c.table.sym(node.table_expr.typ) c.ensure_type_exists(node.table_expr.typ, node.pos) or { return ast.void_type } + old_ts := c.cur_orm_ts c.cur_orm_ts = *sym + defer { + c.cur_orm_ts = old_ts + } if sym.info !is ast.Struct { c.error('The table symbol `$sym.name` has to be a struct', node.table_expr.pos) return ast.void_type @@ -114,7 +118,11 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type { } c.ensure_type_exists(node.table_expr.typ, node.pos) or { return ast.void_type } table_sym := c.table.sym(node.table_expr.typ) + old_ts := c.cur_orm_ts c.cur_orm_ts = *table_sym + defer { + c.cur_orm_ts = old_ts + } if table_sym.info !is ast.Struct { c.error('unknown type `$table_sym.name`', node.pos) return ast.void_type diff --git a/vlib/v/tests/orm_joined_tables_select_test.v b/vlib/v/tests/orm_joined_tables_select_test.v new file mode 100644 index 0000000000..aa4bbdf6f8 --- /dev/null +++ b/vlib/v/tests/orm_joined_tables_select_test.v @@ -0,0 +1,37 @@ +import sqlite + +struct VieterDb { + conn sqlite.DB +} + +pub struct GitRepoArch { +pub: + id int [primary; sql: serial] + repo_id int [nonull] + // repo string + value string [nonull] +} + +pub struct GitRepo { +pub mut: + id int [optional; primary; sql: serial] + repo string [nonull] + arch []GitRepoArch [fkey: 'repo_id'] +} + +pub fn (db &VieterDb) get_git_repos() []GitRepo { + // NB: the query here, uses the `repo` field on GitRepo, + // while GitRepo is joined to GitRepoArch, + // which does *not* have a `repo` field. + // When this test was added, the checker used `GitRepoArch` + // to check for `repo`'s presence (which is wrong), because of + // a lingering c.cur_orm_ts state. The fix was to save/restore c.cur_orm_ts . + res := sql db.conn { + select from GitRepo where repo == 'something' order by id + } + return res +} + +fn test_compiles() { + assert true +}