orm: allow both integer and string arguments in db.select and db.select limit 1

pull/1686/head
Delyan Angelov 2019-08-20 17:32:39 +03:00 committed by Alexander Medvednikov
parent 900df8ecf9
commit cf06faf09b
4 changed files with 202 additions and 16 deletions

View File

@ -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)

View File

@ -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'

View File

@ -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)
*/
}

View File

@ -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
--