orm: allow both integer and string arguments in db.select and db.select limit 1
							parent
							
								
									900df8ecf9
								
							
						
					
					
						commit
						cf06faf09b
					
				|  | @ -84,7 +84,7 @@ mut: | ||||||
| 	is_vweb bool | 	is_vweb bool | ||||||
| 	is_sql bool | 	is_sql bool | ||||||
| 	sql_i int  // $1 $2 $3
 | 	sql_i int  // $1 $2 $3
 | ||||||
| 	sql_params string // ("select * from users where id = $1", ***"100"***)
 | 	sql_params []string // ("select * from users where id = $1", ***"100"***)
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
|  | @ -1400,7 +1400,7 @@ fn (p mut Parser) bterm() string { | ||||||
| 			p.gen('$' + p.sql_i.str()) | 			p.gen('$' + p.sql_i.str()) | ||||||
| 			p.cgen.start_cut() | 			p.cgen.start_cut() | ||||||
| 			p.check_types(p.expression(), typ) | 			p.check_types(p.expression(), typ) | ||||||
| 			p.sql_params = p.sql_params + p.cgen.cut() + ',' | 			p.sql_params << p.cgen.cut() | ||||||
| 			//println('sql params = "$p.sql_params"')
 | 			//println('sql params = "$p.sql_params"')
 | ||||||
| 		}  else { | 		}  else { | ||||||
| 			p.check_types(p.expression(), typ) | 			p.check_types(p.expression(), typ) | ||||||
|  |  | ||||||
|  | @ -6,13 +6,27 @@ module main | ||||||
| 
 | 
 | ||||||
| import strings  | import strings  | ||||||
| 
 | 
 | ||||||
|  | fn sql_params2params_gen(sql_params []string, qprefix string) string { | ||||||
|  | 	mut params_gen := '' | ||||||
|  | 	for i, mparam in sql_params { | ||||||
|  | 		param := mparam.trim(` `) | ||||||
|  | 		if param[0].is_digit() { | ||||||
|  | 			params_gen += '${qprefix}params[$i] = int_str($param).str;\n' | ||||||
|  | 		}else{ | ||||||
|  | 			sparam := param.trim(`\'`) | ||||||
|  | 			params_gen += '${qprefix}params[$i] = "$sparam";\n' | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return params_gen | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // `db.select from User where id == 1 && nr_bookings > 0` 
 | // `db.select from User where id == 1 && nr_bookings > 0` 
 | ||||||
| fn (p mut Parser) select_query(fn_ph int) string { | fn (p mut Parser) select_query(fn_ph int) string { | ||||||
| 	// NB: qprefix, p.sql_i, p.sql_params SHOULD be reset for each query,
 | 	// NB: qprefix, p.sql_i, p.sql_params SHOULD be reset for each query,
 | ||||||
| 	// because we can have many queries in the _same_ scope.
 | 	// because we can have many queries in the _same_ scope.
 | ||||||
| 	qprefix := p.get_tmp().replace('tmp','sql') + '_' | 	qprefix := p.get_tmp().replace('tmp','sql') + '_' | ||||||
| 	p.sql_i = 0 | 	p.sql_i = 0 | ||||||
| 	p.sql_params = '' | 	p.sql_params = []string | ||||||
|                                                    |                                                    | ||||||
| 	mut q := 'select '  | 	mut q := 'select '  | ||||||
| 	p.check(.key_select)  | 	p.check(.key_select)  | ||||||
|  | @ -103,11 +117,7 @@ fn (p mut Parser) select_query(fn_ph int) string { | ||||||
| 		}  | 		}  | ||||||
| 		// One object 
 | 		// One object 
 | ||||||
| 		if query_one {  | 		if query_one {  | ||||||
| 			mut params_gen := '' | 			mut params_gen := sql_params2params_gen( p.sql_params, qprefix ) | ||||||
| 			params := p.sql_params.split(',') |  | ||||||
| 			for i, param in params { |  | ||||||
| 				params_gen += '${qprefix}params[$i] = int_str($param).str;' |  | ||||||
| 			} |  | ||||||
| 			p.cgen.insert_before(' | 			p.cgen.insert_before(' | ||||||
| 
 | 
 | ||||||
| char* ${qprefix}params[$p.sql_i]; | char* ${qprefix}params[$p.sql_i]; | ||||||
|  | @ -132,11 +142,7 @@ ${obj_gen.str()} | ||||||
| 		// Array 
 | 		// Array 
 | ||||||
| 		else { | 		else { | ||||||
| 			q += ' order by id' | 			q += ' order by id' | ||||||
| 			mut params_gen := ''  | 			params_gen := sql_params2params_gen( p.sql_params, qprefix ) | ||||||
| 			params := p.sql_params.split(',')  |  | ||||||
| 			for i, param in params { |  | ||||||
| 				params_gen += '${qprefix}params[$i] = int_str($param).str;' |  | ||||||
| 			} |  | ||||||
| 			p.cgen.insert_before('char* ${qprefix}params[$p.sql_i]; | 			p.cgen.insert_before('char* ${qprefix}params[$p.sql_i]; | ||||||
| $params_gen  | $params_gen  | ||||||
| 
 | 
 | ||||||
|  | @ -159,7 +165,10 @@ for (int i = 0; i < ${qprefix}rows.len; i++) { | ||||||
| 	if n == 'count' { | 	if n == 'count' { | ||||||
| 		return 'int'  | 		return 'int'  | ||||||
| 	}	else if query_one {		 | 	}	else if query_one {		 | ||||||
| 		return 'Option_$table_name' | 		opt_type := 'Option_$table_name'		 | ||||||
|  | 		p.cgen.typedefs << 'typedef Option $opt_type;' | ||||||
|  | 		p.table.register_type( opt_type ) | ||||||
|  | 		return opt_type | ||||||
| 	}  else { | 	}  else { | ||||||
| 		p.register_array('array_$table_name')  | 		p.register_array('array_$table_name')  | ||||||
| 		return 'array_$table_name'  | 		return 'array_$table_name'  | ||||||
|  |  | ||||||
|  | @ -0,0 +1,55 @@ | ||||||
|  | module main | ||||||
|  | 
 | ||||||
|  | import pg | ||||||
|  | 
 | ||||||
|  | struct Customer { | ||||||
|  | 	id int | ||||||
|  | 	name string | ||||||
|  | 	nr_orders int | ||||||
|  | 	country string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  | 	db := pg.connect(pg.Config{host: '127.0.0.1' user: 'myuser' dbname: 'mydb'}) | ||||||
|  | 	 | ||||||
|  | 	nr_customers := db.select count from Customer | ||||||
|  | 	println('Total customers: $nr_customers') | ||||||
|  | 	 | ||||||
|  | 	// V syntax can be used to build queries
 | ||||||
|  | 	println('------------------------------------------------------------------------') | ||||||
|  | 	bg_customers := db.select from Customer where country = 'Bulgaria' && id != 2 | ||||||
|  | 	for customer in bg_customers { | ||||||
|  | 		println('$customer.country | $customer.id - $customer.name') | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	println('------------------------------------------------------------------------') | ||||||
|  | 	ru_customers := db.select from Customer where country = 'Russia' | ||||||
|  | 	for customer in ru_customers { | ||||||
|  | 		println('$customer.country | $customer.id - $customer.name') | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	// by adding `limit 1` we tell V that there will be only one object
 | ||||||
|  | 	println('------------------------------------------------------------------------')	 | ||||||
|  | 	existing := db.select from Customer where id = 1 limit 1 or { panic(err) }	 | ||||||
|  | 	println('Existing customer name: $existing.name') | ||||||
|  | 	println('Existing customer full information:') | ||||||
|  | 	println(existing) | ||||||
|  | 	 | ||||||
|  | 	println('------------------------------------------------------------------------') | ||||||
|  |   q := Customer{} | ||||||
|  | 	for { | ||||||
|  | 		anon := db.select from Customer where id = 12345 && nr_orders > q.nr_orders limit 1 or { eprintln('No such customer. Error: $err') break } | ||||||
|  | 		println('Non existing customer name: $anon.name') | ||||||
|  | 		break | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	// TODO: insert a new customer
 | ||||||
|  | 	/* | ||||||
|  | 	nc := Customer{ | ||||||
|  | 		name: 'John Doe' | ||||||
|  | 		nr_orders: 10 | ||||||
|  | 	} | ||||||
|  | 	db.insert(nc) | ||||||
|  |   */ | ||||||
|  |    | ||||||
|  | } | ||||||
|  | @ -0,0 +1,122 @@ | ||||||
|  | -- | ||||||
|  | -- PostgreSQL database dump | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | -- Dumped from database version 9.5.19 | ||||||
|  | -- Dumped by pg_dump version 9.5.19 | ||||||
|  | 
 | ||||||
|  | SET statement_timeout = 0; | ||||||
|  | SET lock_timeout = 0; | ||||||
|  | SET client_encoding = 'UTF8'; | ||||||
|  | SET standard_conforming_strings = on; | ||||||
|  | SELECT pg_catalog.set_config('search_path', '', false); | ||||||
|  | SET check_function_bodies = false; | ||||||
|  | SET xmloption = content; | ||||||
|  | SET client_min_messages = warning; | ||||||
|  | SET row_security = off; | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:  | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:  | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | SET default_tablespace = ''; | ||||||
|  | 
 | ||||||
|  | SET default_with_oids = false; | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: customer; Type: TABLE; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | CREATE TABLE public.customer ( | ||||||
|  |     id integer NOT NULL, | ||||||
|  |     name text DEFAULT ''::text, | ||||||
|  |     nr_orders integer DEFAULT 0, | ||||||
|  |     country text DEFAULT 'England'::text, | ||||||
|  |     created_at timestamp without time zone DEFAULT now() | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ALTER TABLE public.customer OWNER TO myuser; | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: customer_id_seq; Type: SEQUENCE; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | CREATE SEQUENCE public.customer_id_seq | ||||||
|  |     START WITH 1 | ||||||
|  |     INCREMENT BY 1 | ||||||
|  |     NO MINVALUE | ||||||
|  |     NO MAXVALUE | ||||||
|  |     CACHE 1; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ALTER TABLE public.customer_id_seq OWNER TO myuser; | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: customer_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | ALTER SEQUENCE public.customer_id_seq OWNED BY public.customer.id; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: id; Type: DEFAULT; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | ALTER TABLE ONLY public.customer ALTER COLUMN id SET DEFAULT nextval('public.customer_id_seq'::regclass); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Data for Name: customer; Type: TABLE DATA; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | COPY public.customer (id, name, nr_orders, country, created_at) FROM stdin; | ||||||
|  | 2	Pippi Långstrump	3	Bulgaria	2019-08-19 09:41:30.78888 | ||||||
|  | 1	Bilbo Begins	11	Bulgaria	2019-08-19 09:40:31.396807 | ||||||
|  | 3	Viktualia Rullgardina	0	Bulgaria	2019-08-19 09:42:52.723223 | ||||||
|  | 4	Krusmynta Efraimsdotter	5	Bulgaria	2019-08-19 09:43:04.083209 | ||||||
|  | 5	Ana Karenina	0	Russia	2019-08-20 15:41:50.244971 | ||||||
|  | 7	Jiji Lolobridgida	0	Italy	2019-08-20 15:42:26.020113 | ||||||
|  | 6	Viktor Savashkin	8	Russia	2019-08-20 15:42:07.213557 | ||||||
|  | \. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: customer_id_seq; Type: SEQUENCE SET; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | SELECT pg_catalog.setval('public.customer_id_seq', 1, true); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: customer_pkey; Type: CONSTRAINT; Schema: public; Owner: myuser | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | ALTER TABLE ONLY public.customer | ||||||
|  |     ADD CONSTRAINT customer_pkey PRIMARY KEY (id); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- Name: SCHEMA public; Type: ACL; Schema: -; Owner: postgres | ||||||
|  | -- | ||||||
|  | 
 | ||||||
|  | REVOKE ALL ON SCHEMA public FROM PUBLIC; | ||||||
|  | REVOKE ALL ON SCHEMA public FROM postgres; | ||||||
|  | GRANT ALL ON SCHEMA public TO postgres; | ||||||
|  | GRANT ALL ON SCHEMA public TO PUBLIC; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | ||||||
|  | -- PostgreSQL database dump complete | ||||||
|  | -- | ||||||
|  | 
 | ||||||
		Loading…
	
		Reference in New Issue