orm: fix empty struct and simplify (#8246)
							parent
							
								
									dbf84520f1
								
							
						
					
					
						commit
						e06e8b10cd
					
				|  | @ -1156,13 +1156,12 @@ pub: | ||||||
| 	kind            SqlStmtKind | 	kind            SqlStmtKind | ||||||
| 	db_expr         Expr   // `db` in `sql db {`
 | 	db_expr         Expr   // `db` in `sql db {`
 | ||||||
| 	object_var_name string // `user`
 | 	object_var_name string // `user`
 | ||||||
| 	table_type      table.Type |  | ||||||
| 	pos             token.Position | 	pos             token.Position | ||||||
| 	where_expr      Expr | 	where_expr      Expr | ||||||
| 	updated_columns []string // for `update set x=y`
 | 	updated_columns []string // for `update set x=y`
 | ||||||
| 	update_exprs    []Expr   // for `update`
 | 	update_exprs    []Expr   // for `update`
 | ||||||
| pub mut: | pub mut: | ||||||
| 	table_name string | 	table_expr Type | ||||||
| 	fields     []table.Field | 	fields     []table.Field | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1179,12 +1178,11 @@ pub: | ||||||
| 	order_expr  Expr | 	order_expr  Expr | ||||||
| 	has_desc    bool | 	has_desc    bool | ||||||
| 	is_array    bool | 	is_array    bool | ||||||
| 	table_type  table.Type |  | ||||||
| 	pos         token.Position | 	pos         token.Position | ||||||
| 	has_limit   bool | 	has_limit   bool | ||||||
| 	limit_expr  Expr | 	limit_expr  Expr | ||||||
| pub mut: | pub mut: | ||||||
| 	table_name string | 	table_expr Type | ||||||
| 	fields     []table.Field | 	fields     []table.Field | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5220,16 +5220,15 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) table.Type { | ||||||
| 	defer { | 	defer { | ||||||
| 		c.inside_sql = false | 		c.inside_sql = false | ||||||
| 	} | 	} | ||||||
| 	sym := c.table.get_type_symbol(node.table_type) | 	sym := c.table.get_type_symbol(node.table_expr.typ) | ||||||
| 	if sym.kind == .placeholder { | 	if sym.kind == .placeholder { | ||||||
| 		c.error('orm: unknown type `$sym.name`', node.pos) | 		c.error('orm: unknown type `$sym.name`', node.pos) | ||||||
| 		return table.void_type | 		return table.void_type | ||||||
| 	} | 	} | ||||||
| 	c.cur_orm_ts = sym | 	c.cur_orm_ts = sym | ||||||
| 	info := sym.info as table.Struct | 	info := sym.info as table.Struct | ||||||
| 	fields := c.fetch_and_verify_orm_fields(info, node.pos, node.table_name) | 	fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name) | ||||||
| 	node.fields = fields | 	node.fields = fields | ||||||
| 	node.table_name = sym.name |  | ||||||
| 	if node.has_where { | 	if node.has_where { | ||||||
| 		c.expr(node.where_expr) | 		c.expr(node.where_expr) | ||||||
| 	} | 	} | ||||||
|  | @ -5251,17 +5250,18 @@ fn (mut c Checker) sql_stmt(mut node ast.SqlStmt) table.Type { | ||||||
| 	defer { | 	defer { | ||||||
| 		c.inside_sql = false | 		c.inside_sql = false | ||||||
| 	} | 	} | ||||||
| 	if node.table_type == 0 { | 	sym := c.table.get_type_symbol(node.table_expr.typ) | ||||||
| 		c.error('orm: unknown type `$node.table_name`', node.pos) | 	if node.table_expr.typ == 0 { | ||||||
|  | 		c.error('orm: unknown type `$sym.name`', node.pos) | ||||||
| 	} | 	} | ||||||
| 	sym := c.table.get_type_symbol(node.table_type) |  | ||||||
| 	if sym.kind == .placeholder { | 	if sym.kind == .placeholder { | ||||||
| 		c.error('orm: unknown type `$sym.name`', node.pos) | 		c.error('orm: unknown type `$sym.name`', node.pos) | ||||||
| 		return table.void_type | 		return table.void_type | ||||||
| 	} | 	} | ||||||
| 	c.cur_orm_ts = sym | 	c.cur_orm_ts = sym | ||||||
| 	info := sym.info as table.Struct | 	info := sym.info as table.Struct | ||||||
| 	fields := c.fetch_and_verify_orm_fields(info, node.pos, node.table_name) | 	table_sym := c.table.get_type_symbol(node.table_expr.typ) | ||||||
|  | 	fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name) | ||||||
| 	node.fields = fields | 	node.fields = fields | ||||||
| 	c.expr(node.db_expr) | 	c.expr(node.db_expr) | ||||||
| 	if node.kind == .update { | 	if node.kind == .update { | ||||||
|  | @ -5278,6 +5278,7 @@ fn (mut c Checker) fetch_and_verify_orm_fields(info table.Struct, pos token.Posi | ||||||
| 		[table.string_type, table.int_type, table.bool_type] && !it.attrs.contains('skip')) | 		[table.string_type, table.int_type, table.bool_type] && !it.attrs.contains('skip')) | ||||||
| 	if fields.len == 0 { | 	if fields.len == 0 { | ||||||
| 		c.error('V orm: select: empty fields in `$table_name`', pos) | 		c.error('V orm: select: empty fields in `$table_name`', pos) | ||||||
|  | 		return []table.Field{} | ||||||
| 	} | 	} | ||||||
| 	if fields[0].name != 'id' { | 	if fields[0].name != 'id' { | ||||||
| 		c.error('V orm: `id int` must be the first field in `$table_name`', pos) | 		c.error('V orm: `id int` must be the first field in `$table_name`', pos) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | vlib/v/checker/tests/orm_empty_struct.vv:9:15: error: V orm: select: empty fields in `Person` | ||||||
|  |     7 |     db := sqlite.connect(':memory:')? | ||||||
|  |     8 |     _ := sql db { | ||||||
|  |     9 |         select from Person | ||||||
|  |       |                     ~~~~~~ | ||||||
|  |    10 |     } | ||||||
|  |    11 | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | import sqlite | ||||||
|  | 
 | ||||||
|  | struct Person { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  | 	db := sqlite.connect(':memory:')? | ||||||
|  | 	_ := sql db { | ||||||
|  | 		select from Person | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -1327,8 +1327,8 @@ pub fn (mut f Fmt) sql_expr(node ast.SqlExpr) { | ||||||
| 	f.writeln(' {') | 	f.writeln(' {') | ||||||
| 	f.write('\t') | 	f.write('\t') | ||||||
| 	f.write('select ') | 	f.write('select ') | ||||||
| 	esym := f.table.get_type_symbol(node.table_type) | 	esym := f.table.get_type_symbol(node.table_expr.typ) | ||||||
| 	table_name := esym.name | 	table_name := util.strip_mod_name(esym.name) | ||||||
| 	if node.is_count { | 	if node.is_count { | ||||||
| 		f.write('count ') | 		f.write('count ') | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -1342,7 +1342,7 @@ pub fn (mut f Fmt) sql_expr(node ast.SqlExpr) { | ||||||
| 			f.write(' ') | 			f.write(' ') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	f.write('from ${util.strip_mod_name(table_name)}') | 	f.write('from $table_name') | ||||||
| 	if node.has_where { | 	if node.has_where { | ||||||
| 		f.write(' where ') | 		f.write(' where ') | ||||||
| 		f.expr(node.where_expr) | 		f.expr(node.where_expr) | ||||||
|  | @ -2366,12 +2366,13 @@ pub fn (mut f Fmt) sql_stmt(node ast.SqlStmt) { | ||||||
| 	f.write('sql ') | 	f.write('sql ') | ||||||
| 	f.expr(node.db_expr) | 	f.expr(node.db_expr) | ||||||
| 	f.writeln(' {') | 	f.writeln(' {') | ||||||
|  | 	table_name := util.strip_mod_name(f.table.get_type_symbol(node.table_expr.typ).name) | ||||||
| 	match node.kind { | 	match node.kind { | ||||||
| 		.insert { | 		.insert { | ||||||
| 			f.writeln('\tinsert $node.object_var_name into ${util.strip_mod_name(node.table_name)}') | 			f.writeln('\tinsert $node.object_var_name into $table_name') | ||||||
| 		} | 		} | ||||||
| 		.update { | 		.update { | ||||||
| 			f.write('\tupdate ${util.strip_mod_name(node.table_name)} set ') | 			f.write('\tupdate $table_name set ') | ||||||
| 			for i, col in node.updated_columns { | 			for i, col in node.updated_columns { | ||||||
| 				f.write('$col = ') | 				f.write('$col = ') | ||||||
| 				f.expr(node.update_exprs[i]) | 				f.expr(node.update_exprs[i]) | ||||||
|  | @ -2387,7 +2388,7 @@ pub fn (mut f Fmt) sql_stmt(node ast.SqlStmt) { | ||||||
| 			f.writeln('') | 			f.writeln('') | ||||||
| 		} | 		} | ||||||
| 		.delete { | 		.delete { | ||||||
| 			f.write('\tdelete from ${util.strip_mod_name(node.table_name)} where ') | 			f.write('\tdelete from $table_name where ') | ||||||
| 			f.expr(node.where_expr) | 			f.expr(node.where_expr) | ||||||
| 			f.writeln('') | 			f.writeln('') | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -26,12 +26,13 @@ fn (mut g Gen) sql_stmt(node ast.SqlStmt) { | ||||||
| 	g.expr(node.db_expr) | 	g.expr(node.db_expr) | ||||||
| 	g.writeln(';') | 	g.writeln(';') | ||||||
| 	g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, _SLIT("') | 	g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, _SLIT("') | ||||||
|  | 	table_name := util.strip_mod_name(g.table.get_type_symbol(node.table_expr.typ).name) | ||||||
| 	if node.kind == .insert { | 	if node.kind == .insert { | ||||||
| 		g.write('INSERT INTO `${util.strip_mod_name(node.table_name)}` (') | 		g.write('INSERT INTO `$table_name` (') | ||||||
| 	} else if node.kind == .update { | 	} else if node.kind == .update { | ||||||
| 		g.write('UPDATE `${util.strip_mod_name(node.table_name)}` SET ') | 		g.write('UPDATE `$table_name` SET ') | ||||||
| 	} else if node.kind == .delete { | 	} else if node.kind == .delete { | ||||||
| 		g.write('DELETE FROM `${util.strip_mod_name(node.table_name)}` ') | 		g.write('DELETE FROM `$table_name` ') | ||||||
| 	} | 	} | ||||||
| 	if node.kind == .insert { | 	if node.kind == .insert { | ||||||
| 		for i, field in node.fields { | 		for i, field in node.fields { | ||||||
|  | @ -108,9 +109,10 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { | ||||||
| 	*/ | 	*/ | ||||||
| 	cur_line := g.go_before_stmt(0) | 	cur_line := g.go_before_stmt(0) | ||||||
| 	mut sql_query := 'SELECT ' | 	mut sql_query := 'SELECT ' | ||||||
|  | 	table_name := util.strip_mod_name(g.table.get_type_symbol(node.table_expr.typ).name) | ||||||
| 	if node.is_count { | 	if node.is_count { | ||||||
| 		// `select count(*) from User`
 | 		// `select count(*) from User`
 | ||||||
| 		sql_query += 'COUNT(*) FROM `${util.strip_mod_name(node.table_name)}` ' | 		sql_query += 'COUNT(*) FROM `$table_name` ' | ||||||
| 	} else { | 	} else { | ||||||
| 		// `select id, name, country from User`
 | 		// `select id, name, country from User`
 | ||||||
| 		for i, field in node.fields { | 		for i, field in node.fields { | ||||||
|  | @ -119,7 +121,7 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { | ||||||
| 				sql_query += ', ' | 				sql_query += ', ' | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		sql_query += ' FROM `${util.strip_mod_name(node.table_name)}`' | 		sql_query += ' FROM `$table_name`' | ||||||
| 	} | 	} | ||||||
| 	if node.has_where { | 	if node.has_where { | ||||||
| 		sql_query += ' WHERE ' | 		sql_query += ' WHERE ' | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ fn (mut p Parser) sql_expr() ast.Expr { | ||||||
| 		p.check_name() // from
 | 		p.check_name() // from
 | ||||||
| 		typ = table.int_type | 		typ = table.int_type | ||||||
| 	} | 	} | ||||||
|  | 	table_pos := p.tok.position() | ||||||
| 	table_type := p.parse_type() // `User`
 | 	table_type := p.parse_type() // `User`
 | ||||||
| 	mut where_expr := ast.Expr{} | 	mut where_expr := ast.Expr{} | ||||||
| 	has_where := p.tok.kind == .name && p.tok.lit == 'where' | 	has_where := p.tok.kind == .name && p.tok.lit == 'where' | ||||||
|  | @ -89,7 +90,6 @@ fn (mut p Parser) sql_expr() ast.Expr { | ||||||
| 		is_count: is_count | 		is_count: is_count | ||||||
| 		typ: typ | 		typ: typ | ||||||
| 		db_expr: db_expr | 		db_expr: db_expr | ||||||
| 		table_type: table_type |  | ||||||
| 		where_expr: where_expr | 		where_expr: where_expr | ||||||
| 		has_where: has_where | 		has_where: has_where | ||||||
| 		has_limit: has_limit | 		has_limit: has_limit | ||||||
|  | @ -101,6 +101,10 @@ fn (mut p Parser) sql_expr() ast.Expr { | ||||||
| 		has_desc: has_desc | 		has_desc: has_desc | ||||||
| 		is_array: !query_one | 		is_array: !query_one | ||||||
| 		pos: pos | 		pos: pos | ||||||
|  | 		table_expr: ast.Type{ | ||||||
|  | 			typ: table_type | ||||||
|  | 			pos: table_pos | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -127,18 +131,15 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { | ||||||
| 		kind = .update | 		kind = .update | ||||||
| 	} | 	} | ||||||
| 	mut inserted_var_name := '' | 	mut inserted_var_name := '' | ||||||
| 	mut table_name := '' | 	mut table_type := table.Type(0) | ||||||
| 	if kind != .delete { | 	if kind != .delete { | ||||||
|  | 		if kind == .update { | ||||||
|  | 			table_type = p.parse_type() | ||||||
|  | 		} else if kind == .insert { | ||||||
| 			expr := p.expr(0) | 			expr := p.expr(0) | ||||||
| 		match expr { | 			if expr is ast.Ident { | ||||||
| 			ast.Ident { |  | ||||||
| 				if kind == .insert { |  | ||||||
| 				inserted_var_name = expr.name | 				inserted_var_name = expr.name | ||||||
| 				} else if kind == .update { | 			} else { | ||||||
| 					table_name = expr.name |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			else { |  | ||||||
| 				p.error('can only insert variables') | 				p.error('can only insert variables') | ||||||
| 				return ast.SqlStmt{} | 				return ast.SqlStmt{} | ||||||
| 			} | 			} | ||||||
|  | @ -170,26 +171,18 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { | ||||||
| 		p.error('expecting `from`') | 		p.error('expecting `from`') | ||||||
| 		return ast.SqlStmt{} | 		return ast.SqlStmt{} | ||||||
| 	} | 	} | ||||||
| 	mut table_type := table.Type(0) | 
 | ||||||
|  | 	mut table_pos := p.tok.position() | ||||||
| 	mut where_expr := ast.Expr{} | 	mut where_expr := ast.Expr{} | ||||||
| 	if kind == .insert { | 	if kind == .insert { | ||||||
| 		table_type = p.parse_type() // `User`
 | 		table_pos = p.tok.position() | ||||||
| 		sym := p.table.get_type_symbol(table_type) | 		table_type = p.parse_type() | ||||||
| 		// info := sym.info as table.Struct
 |  | ||||||
| 		// fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type])
 |  | ||||||
| 		table_name = sym.name |  | ||||||
| 	} else if kind == .update { | 	} else if kind == .update { | ||||||
| 		if !p.pref.is_fmt { |  | ||||||
| 			// NB: in vfmt mode, v parses just a single file and table_name may not have been registered
 |  | ||||||
| 			idx := p.table.find_type_idx(p.prepend_mod(table_name)) |  | ||||||
| 			table_type = table.new_type(idx) |  | ||||||
| 		} |  | ||||||
| 		p.check_sql_keyword('where') or { return ast.SqlStmt{} } | 		p.check_sql_keyword('where') or { return ast.SqlStmt{} } | ||||||
| 		where_expr = p.expr(0) | 		where_expr = p.expr(0) | ||||||
| 	} else if kind == .delete { | 	} else if kind == .delete { | ||||||
|  | 		table_pos = p.tok.position() | ||||||
| 		table_type = p.parse_type() | 		table_type = p.parse_type() | ||||||
| 		sym := p.table.get_type_symbol(table_type) |  | ||||||
| 		table_name = sym.name |  | ||||||
| 		p.check_sql_keyword('where') or { return ast.SqlStmt{} } | 		p.check_sql_keyword('where') or { return ast.SqlStmt{} } | ||||||
| 		where_expr = p.expr(0) | 		where_expr = p.expr(0) | ||||||
| 	} | 	} | ||||||
|  | @ -197,8 +190,10 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { | ||||||
| 	pos.last_line = p.prev_tok.line_nr | 	pos.last_line = p.prev_tok.line_nr | ||||||
| 	return ast.SqlStmt{ | 	return ast.SqlStmt{ | ||||||
| 		db_expr: db_expr | 		db_expr: db_expr | ||||||
| 		table_name: table_name | 		table_expr: ast.Type{ | ||||||
| 		table_type: table_type | 			typ: table_type | ||||||
|  | 			pos: table_pos | ||||||
|  | 		} | ||||||
| 		object_var_name: inserted_var_name | 		object_var_name: inserted_var_name | ||||||
| 		pos: pos | 		pos: pos | ||||||
| 		updated_columns: updated_columns | 		updated_columns: updated_columns | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue