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_sql bool | ||||
| 	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 ( | ||||
|  | @ -1400,7 +1400,7 @@ fn (p mut Parser) bterm() string { | |||
| 			p.gen('$' + p.sql_i.str()) | ||||
| 			p.cgen.start_cut() | ||||
| 			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"')
 | ||||
| 		}  else { | ||||
| 			p.check_types(p.expression(), typ) | ||||
|  |  | |||
|  | @ -6,13 +6,27 @@ module main | |||
| 
 | ||||
| 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` 
 | ||||
| fn (p mut Parser) select_query(fn_ph int) string { | ||||
| 	// NB: qprefix, p.sql_i, p.sql_params SHOULD be reset for each query,
 | ||||
| 	// because we can have many queries in the _same_ scope.
 | ||||
| 	qprefix := p.get_tmp().replace('tmp','sql') + '_' | ||||
| 	p.sql_i = 0 | ||||
| 	p.sql_params = '' | ||||
| 	p.sql_params = []string | ||||
|                                                    | ||||
| 	mut q := 'select '  | ||||
| 	p.check(.key_select)  | ||||
|  | @ -103,11 +117,7 @@ fn (p mut Parser) select_query(fn_ph int) string { | |||
| 		}  | ||||
| 		// One object 
 | ||||
| 		if query_one {  | ||||
| 			mut params_gen := '' | ||||
| 			params := p.sql_params.split(',') | ||||
| 			for i, param in params { | ||||
| 				params_gen += '${qprefix}params[$i] = int_str($param).str;' | ||||
| 			} | ||||
| 			mut params_gen := sql_params2params_gen( p.sql_params, qprefix ) | ||||
| 			p.cgen.insert_before(' | ||||
| 
 | ||||
| char* ${qprefix}params[$p.sql_i]; | ||||
|  | @ -131,12 +141,8 @@ ${obj_gen.str()} | |||
| 		}  | ||||
| 		// Array 
 | ||||
| 		else { | ||||
| 			q += ' order by id'  | ||||
| 			mut params_gen := ''  | ||||
| 			params := p.sql_params.split(',')  | ||||
| 			for i, param in params { | ||||
| 				params_gen += '${qprefix}params[$i] = int_str($param).str;' | ||||
| 			} | ||||
| 			q += ' order by id' | ||||
| 			params_gen := sql_params2params_gen( p.sql_params, qprefix ) | ||||
| 			p.cgen.insert_before('char* ${qprefix}params[$p.sql_i]; | ||||
| $params_gen  | ||||
| 
 | ||||
|  | @ -158,8 +164,11 @@ for (int i = 0; i < ${qprefix}rows.len; i++) { | |||
| 	}  | ||||
| 	if n == 'count' { | ||||
| 		return 'int'  | ||||
| 	}	else if query_one { | ||||
| 		return 'Option_$table_name' | ||||
| 	}	else if query_one {		 | ||||
| 		opt_type := 'Option_$table_name'		 | ||||
| 		p.cgen.typedefs << 'typedef Option $opt_type;' | ||||
| 		p.table.register_type( opt_type ) | ||||
| 		return opt_type | ||||
| 	}  else { | ||||
| 		p.register_array('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