diff --git a/vlib/v/parser/orm.v b/vlib/v/parser/orm.v index 425b4a0a41e94a..e600db979d75c4 100644 --- a/vlib/v/parser/orm.v +++ b/vlib/v/parser/orm.v @@ -133,6 +133,10 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { mut lines := []ast.SqlStmtLine{} for p.tok.kind != .rcbr { + if p.tok.kind == .eof { + p.unexpected_with_pos(pos, got: 'eof, while parsing an SQL statement') + return ast.SqlStmt{} + } lines << p.parse_sql_stmt_line() } diff --git a/vlib/v/parser/testdata/silent/orm_infinite_loop_in_parser_sql_stmt.vv b/vlib/v/parser/testdata/silent/orm_infinite_loop_in_parser_sql_stmt.vv new file mode 100644 index 00000000000000..69f97ead2e3481 --- /dev/null +++ b/vlib/v/parser/testdata/silent/orm_infinite_loop_in_parser_sql_stmt.vv @@ -0,0 +1,68 @@ +module main + +import db.sqlite + +@[table: 'modules'] +struct Module { + id int @[primary; sql: serial] + name string + nr_downloads int @[sql: u64] + creator User +} + +struct User { + id int @[primary; sql: serial] + age u32 @[unique: 'user'] + name string @[sql: 'username'; sql_type: 'VARCHAR(200)'; unique] + is_customer bool @[sql: 'abc'; unique: 'user'] + skipped_string string @[skip] +} + +struct Parent { + id int @[primary; sql: serial] + name string + children []Child @[fkey: 'parent_id'] +} + +struct Child { + id int @[primary; sql: serial] + parent_id int + name string +} + +fn main() { + eprintln('------------ ${@METHOD} -----------------') + mut db := sqlite.connect(':memory:')! + defer { + sql db { + drop table Parent + drop table Child + } or {} + db.close() or {} + } + + sql db { + create table Parent + }! + sql db { + create table Child + }! + par := Parent{ + name: 'test' + children: [ + Child{ + name: 'abc' + }, + Child{ + name: 'def' + }, + ] + } + sql db { + insert par into Parent + }! + sql db { + select from Parent where id == 1 & name == "whatever" + }! + eprintln(parent) +} diff --git a/vlib/v/parser/testdata/stdout/.gitkeep b/vlib/v/parser/testdata/stdout/.gitkeep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/vlib/v/parser/v_parser_test.v b/vlib/v/parser/v_parser_test.v index 5892b08ed8fa97..d35a58702d8949 100644 --- a/vlib/v/parser/v_parser_test.v +++ b/vlib/v/parser/v_parser_test.v @@ -7,6 +7,9 @@ import v.checker import v.pref import term import os +import benchmark + +const vroot = os.dir(os.dir(os.dir(os.dir(@FILE)))) fn test_eval() { /* @@ -60,42 +63,40 @@ fn test_eval() { return } -fn test_parse_file() { - if true { - return - } - s := ' +fn test_parse_text() { + println(@LOCATION) + source_text := ' fn foo() int { f := 23 - return 10+4 + return 10+4+f } +fn ff(x int) {} -12 + 3 -x := 10 -5+7 -8+4 +fn main() { + ff(12 + 3) + x := 10 + bar(5+7) + ff(8+x) +} ' table := ast.new_table() vpref := &pref.Preferences{} - mut prog := parse_file(s, table, .skip_comments, vpref) + mut prog := parse_text(source_text, '', table, .skip_comments, vpref) mut checker_ := checker.new_checker(table, vpref) checker_.check(mut prog) - res, _, _, _ := c.gen([prog], table, vpref) - println(res) } fn test_one() { if true { return } - println('\n\ntest_one()') + println(@LOCATION) input := ['a := 10', 'b := -a', 'c := 20'] expected := 'int a = 10;int b = -a;int c = 20;' table := ast.new_table() vpref := &pref.Preferences{} scope := &ast.Scope{ start_pos: 0 - parent: 0 } mut e := []ast.Stmt{} for line in input { @@ -113,6 +114,7 @@ fn test_one() { println(res) ok := expected == res println(res) + dump(ok) assert ok if !ok { } @@ -120,6 +122,7 @@ fn test_one() { } fn test_parse_expr() { + println(@LOCATION) if true { return } @@ -138,7 +141,6 @@ fn test_parse_expr() { mut chk := checker.new_checker(table, vpref) scope := &ast.Scope{ start_pos: 0 - parent: 0 } for s in input { println('\n\nst="${s}"') @@ -176,6 +178,7 @@ fn test_parse_expr() { } fn test_num_literals() { + println(@LOCATION) inputs := [ 'a := -1', 'b := -12.e17', @@ -185,7 +188,6 @@ fn test_num_literals() { table := ast.new_table() mut scope := &ast.Scope{ start_pos: 0 - parent: 0 } mut rhs_types := []string{} for input in inputs { @@ -220,6 +222,7 @@ for s in text_expr { */ fn test_fn_is_html_open_tag() { + println(@LOCATION) mut s := '