mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser: breaking change, let V ORM queries return arrays for *all* non-count queries, including limit = 1
(#17719)
This commit is contained in:
parent
93b7cc4888
commit
d0e78b1da6
@ -67,23 +67,23 @@ jobs:
|
|||||||
echo "Build Coreutils"
|
echo "Build Coreutils"
|
||||||
cd /tmp/coreutils; make
|
cd /tmp/coreutils; make
|
||||||
|
|
||||||
- name: Build vlang/gitly
|
# - name: Build vlang/gitly
|
||||||
run: |
|
# run: |
|
||||||
echo "Install markdown"
|
# echo "Install markdown"
|
||||||
v install markdown
|
# v install markdown
|
||||||
echo "Install pcre"
|
# echo "Install pcre"
|
||||||
v install pcre
|
# v install pcre
|
||||||
echo "Clone Gitly"
|
# echo "Clone Gitly"
|
||||||
git clone https://github.com/vlang/gitly /tmp/gitly
|
# git clone https://github.com/vlang/gitly /tmp/gitly
|
||||||
echo "Build Gitly"
|
# echo "Build Gitly"
|
||||||
v /tmp/gitly
|
# v /tmp/gitly
|
||||||
## echo "Build Gitly with -autofree"
|
# ## echo "Build Gitly with -autofree"
|
||||||
## v -autofree /tmp/gitly
|
# ## v -autofree /tmp/gitly
|
||||||
echo "Compile gitly.css from gitly.scss"
|
# echo "Compile gitly.css from gitly.scss"
|
||||||
sassc /tmp/gitly/src/static/css/gitly.scss > /tmp/gitly/src/static/css/gitly.css
|
# sassc /tmp/gitly/src/static/css/gitly.scss > /tmp/gitly/src/static/css/gitly.css
|
||||||
echo "Run first_run.v"
|
# echo "Run first_run.v"
|
||||||
v run /tmp/gitly/tests/first_run.v
|
# v run /tmp/gitly/tests/first_run.v
|
||||||
# /tmp/gitly/gitly -ci_run
|
# # /tmp/gitly/gitly -ci_run
|
||||||
|
|
||||||
- name: Build V Language Server (VLS) vlang/vls
|
- name: Build V Language Server (VLS) vlang/vls
|
||||||
run: |
|
run: |
|
||||||
|
@ -4836,7 +4836,7 @@ struct Customer {
|
|||||||
country string [nonull]
|
country string [nonull]
|
||||||
}
|
}
|
||||||
|
|
||||||
db := sqlite.connect('customers.db')?
|
db := sqlite.connect('customers.db')!
|
||||||
|
|
||||||
// you can create tables:
|
// you can create tables:
|
||||||
// CREATE TABLE IF NOT EXISTS `Customer` (
|
// CREATE TABLE IF NOT EXISTS `Customer` (
|
||||||
@ -4854,6 +4854,7 @@ nr_customers := sql db {
|
|||||||
select count from Customer
|
select count from Customer
|
||||||
}
|
}
|
||||||
println('number of all customers: ${nr_customers}')
|
println('number of all customers: ${nr_customers}')
|
||||||
|
|
||||||
// V syntax can be used to build queries
|
// V syntax can be used to build queries
|
||||||
uk_customers := sql db {
|
uk_customers := sql db {
|
||||||
select from Customer where country == 'uk' && nr_orders > 0
|
select from Customer where country == 'uk' && nr_orders > 0
|
||||||
@ -4862,11 +4863,7 @@ println(uk_customers.len)
|
|||||||
for customer in uk_customers {
|
for customer in uk_customers {
|
||||||
println('${customer.id} - ${customer.name}')
|
println('${customer.id} - ${customer.name}')
|
||||||
}
|
}
|
||||||
// by adding `limit 1` we tell V that there will be only one object
|
|
||||||
customer := sql db {
|
|
||||||
select from Customer where id == 1 limit 1
|
|
||||||
}
|
|
||||||
println('${customer.id} - ${customer.name}')
|
|
||||||
// insert a new customer
|
// insert a new customer
|
||||||
new_customer := Customer{
|
new_customer := Customer{
|
||||||
name: 'Bob'
|
name: 'Bob'
|
||||||
|
@ -34,9 +34,10 @@ fn (mut app App) service_auth(username string, password string) !string {
|
|||||||
db.close() or { panic(err) }
|
db.close() or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
user := sql db {
|
users := sql db {
|
||||||
select from User where username == username limit 1
|
select from User where username == username
|
||||||
}
|
}
|
||||||
|
user := users.first()
|
||||||
if user.username != username {
|
if user.username != username {
|
||||||
return error('user not found')
|
return error('user not found')
|
||||||
}
|
}
|
||||||
|
@ -61,5 +61,5 @@ fn (mut app App) service_get_user(id int) !User {
|
|||||||
select from User where id == id
|
select from User where id == id
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
return results.first()
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,15 @@ fn (mut app App) service_auth(username string, password string) !string {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
user := sql db {
|
users := sql db {
|
||||||
select from User where username == username limit 1
|
select from User where username == username
|
||||||
}
|
}
|
||||||
if user.username != username {
|
|
||||||
|
if users.len == 0 {
|
||||||
return error('user not found')
|
return error('user not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user := users.first()
|
||||||
if !user.active {
|
if !user.active {
|
||||||
return error('user is not active')
|
return error('user is not active')
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,11 @@ fn (mut app App) service_add_user(username string, password string) !User {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := sql db {
|
users := sql db {
|
||||||
select from User where username == username limit 1
|
select from User where username == username limit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return users.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) service_get_user_by_id(user_id int) !User {
|
fn (mut app App) service_get_user_by_id(user_id int) !User {
|
||||||
@ -48,11 +48,11 @@ fn (mut app App) service_get_user_by_id(user_id int) !User {
|
|||||||
db.close() or { panic(err) }
|
db.close() or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
results := sql db {
|
users := sql db {
|
||||||
select from User where id == user_id
|
select from User where id == user_id
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
return users.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) service_get_all_user() ![]User {
|
fn (mut app App) service_get_all_user() ![]User {
|
||||||
|
@ -149,10 +149,11 @@ fn test_sqlite_orm() {
|
|||||||
insert test_default_atribute into TestDefaultAtribute
|
insert test_default_atribute into TestDefaultAtribute
|
||||||
}
|
}
|
||||||
|
|
||||||
result_test_default_atribute := sql db {
|
test_default_atributes := sql db {
|
||||||
select from TestDefaultAtribute limit 1
|
select from TestDefaultAtribute limit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_test_default_atribute := test_default_atributes.first()
|
||||||
assert result_test_default_atribute.name == 'Hitalo'
|
assert result_test_default_atribute.name == 'Hitalo'
|
||||||
assert test_default_atribute.created_at.len == 0
|
assert test_default_atribute.created_at.len == 0
|
||||||
assert test_default_atribute.created_at1.len == 0
|
assert test_default_atribute.created_at1.len == 0
|
||||||
|
@ -106,10 +106,11 @@ fn test_orm_insert_with_multiple_child_elements() {
|
|||||||
insert new_parent into Parent
|
insert new_parent into Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
parent := sql db {
|
parents := sql db {
|
||||||
select from Parent where id == 1
|
select from Parent where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent := parents.first()
|
||||||
assert parent.children.len == new_parent.children.len
|
assert parent.children.len == new_parent.children.len
|
||||||
assert parent.notes.len == new_parent.notes.len
|
assert parent.notes.len == new_parent.notes.len
|
||||||
|
|
||||||
|
@ -60,26 +60,26 @@ fn test_sql_or_block_for_select() {
|
|||||||
mut db := sqlite.connect(db_path)!
|
mut db := sqlite.connect(db_path)!
|
||||||
|
|
||||||
eprintln('> selecting user with id 1...')
|
eprintln('> selecting user with id 1...')
|
||||||
single := sql db {
|
mut users := sql db {
|
||||||
select from User where id == 1
|
select from User where id == 1
|
||||||
} or {
|
} or {
|
||||||
eprintln('could not select user, err: ${err}')
|
eprintln('could not select user, err: ${err}')
|
||||||
User{0, ''}
|
[]User{}
|
||||||
}
|
}
|
||||||
eprintln('LINE: ${@LINE}')
|
eprintln('LINE: ${@LINE}')
|
||||||
|
|
||||||
|
single := users.first()
|
||||||
assert single.id == 1
|
assert single.id == 1
|
||||||
|
|
||||||
failed := sql db {
|
users = sql db {
|
||||||
select from User where id == 0
|
select from User where id == 0
|
||||||
} or {
|
} or {
|
||||||
eprintln('could not select user, err: ${err}')
|
eprintln('could not select user, err: ${err}')
|
||||||
User{0, ''}
|
[]User{}
|
||||||
}
|
}
|
||||||
eprintln('LINE: ${@LINE}')
|
eprintln('LINE: ${@LINE}')
|
||||||
|
|
||||||
assert failed.id == 0
|
assert users.len == 0
|
||||||
assert failed.name == ''
|
|
||||||
eprintln('LINE: ${@LINE}')
|
eprintln('LINE: ${@LINE}')
|
||||||
|
|
||||||
eprintln('> selecting users...')
|
eprintln('> selecting users...')
|
||||||
|
@ -104,19 +104,16 @@ fn test_orm() {
|
|||||||
select count from User
|
select count from User
|
||||||
}
|
}
|
||||||
assert nr_all_users == 3
|
assert nr_all_users == 3
|
||||||
println('nr_all_users=${nr_all_users}')
|
|
||||||
|
|
||||||
nr_users1 := sql db {
|
nr_users1 := sql db {
|
||||||
select count from User where id == 1
|
select count from User where id == 1
|
||||||
}
|
}
|
||||||
assert nr_users1 == 1
|
assert nr_users1 == 1
|
||||||
println('nr_users1=${nr_users1}')
|
|
||||||
|
|
||||||
nr_peters := sql db {
|
nr_peters := sql db {
|
||||||
select count from User where id == 2 && name == 'Peter'
|
select count from User where id == 2 && name == 'Peter'
|
||||||
}
|
}
|
||||||
assert nr_peters == 1
|
assert nr_peters == 1
|
||||||
println('nr_peters=${nr_peters}')
|
|
||||||
|
|
||||||
nr_peters2 := sql db {
|
nr_peters2 := sql db {
|
||||||
select count from User where id == 2 && name == name
|
select count from User where id == 2 && name == name
|
||||||
@ -134,24 +131,26 @@ fn test_orm() {
|
|||||||
assert peters.len == 1
|
assert peters.len == 1
|
||||||
assert peters[0].name == 'Peter'
|
assert peters[0].name == 'Peter'
|
||||||
|
|
||||||
one_peter := sql db {
|
mut users := sql db {
|
||||||
select from User where name == name limit 1
|
select from User where name == name limit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
one_peter := users.first()
|
||||||
assert one_peter.name == 'Peter'
|
assert one_peter.name == 'Peter'
|
||||||
assert one_peter.id == 2
|
assert one_peter.id == 2
|
||||||
|
|
||||||
user := sql db {
|
users = sql db {
|
||||||
select from User where id == 1
|
select from User where id == 1
|
||||||
}
|
}
|
||||||
println(user)
|
|
||||||
|
user := users.first()
|
||||||
assert user.name == 'Sam'
|
assert user.name == 'Sam'
|
||||||
assert user.id == 1
|
assert user.id == 1
|
||||||
assert user.age == 29
|
assert user.age == 29
|
||||||
|
|
||||||
users := sql db {
|
users = sql db {
|
||||||
select from User where id > 0
|
select from User where id > 0
|
||||||
}
|
}
|
||||||
println(users)
|
|
||||||
assert users.len == 3
|
assert users.len == 3
|
||||||
assert users[0].name == 'Sam'
|
assert users[0].name == 'Sam'
|
||||||
assert users[1].name == 'Peter'
|
assert users[1].name == 'Peter'
|
||||||
@ -160,23 +159,16 @@ fn test_orm() {
|
|||||||
users2 := sql db {
|
users2 := sql db {
|
||||||
select from User where id < 0
|
select from User where id < 0
|
||||||
}
|
}
|
||||||
println(users2)
|
|
||||||
assert users2.len == 0
|
assert users2.len == 0
|
||||||
|
|
||||||
users3 := sql db {
|
users3 := sql db {
|
||||||
select from User where age == 29 || age == 31
|
select from User where age == 29 || age == 31
|
||||||
}
|
}
|
||||||
println(users3)
|
|
||||||
assert users3.len == 2
|
assert users3.len == 2
|
||||||
assert users3[0].age == 29
|
assert users3[0].age == 29
|
||||||
assert users3[1].age == 31
|
assert users3[1].age == 31
|
||||||
|
|
||||||
missing_user := sql db {
|
|
||||||
select from User where id == 8777
|
|
||||||
}
|
|
||||||
println('missing_user:')
|
|
||||||
println(missing_user) // zero struct
|
|
||||||
|
|
||||||
new_user := User{
|
new_user := User{
|
||||||
name: 'New user'
|
name: 'New user'
|
||||||
age: 30
|
age: 30
|
||||||
@ -185,22 +177,27 @@ fn test_orm() {
|
|||||||
insert new_user into User
|
insert new_user into User
|
||||||
}
|
}
|
||||||
|
|
||||||
x := sql db {
|
users = sql db {
|
||||||
select from User where id == 4
|
select from User where id == 4
|
||||||
}
|
}
|
||||||
println(x)
|
|
||||||
|
x := users.first()
|
||||||
assert x.age == 30
|
assert x.age == 30
|
||||||
assert x.id == 4
|
assert x.id == 4
|
||||||
assert x.name == 'New user'
|
assert x.name == 'New user'
|
||||||
|
|
||||||
kate := sql db {
|
users = sql db {
|
||||||
select from User where id == 3
|
select from User where id == 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kate := users.first()
|
||||||
assert kate.is_customer == true
|
assert kate.is_customer == true
|
||||||
|
|
||||||
customer := sql db {
|
users = sql db {
|
||||||
select from User where is_customer == true limit 1
|
select from User where is_customer == true limit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
customer := users.first()
|
||||||
assert customer.is_customer == true
|
assert customer.is_customer == true
|
||||||
assert customer.name == 'Kate'
|
assert customer.name == 'Kate'
|
||||||
|
|
||||||
@ -208,9 +205,10 @@ fn test_orm() {
|
|||||||
update User set age = 31 where name == 'Kate'
|
update User set age = 31 where name == 'Kate'
|
||||||
}
|
}
|
||||||
|
|
||||||
kate2 := sql db {
|
users = sql db {
|
||||||
select from User where id == 3
|
select from User where id == 3
|
||||||
}
|
}
|
||||||
|
kate2 := users.first()
|
||||||
assert kate2.age == 31
|
assert kate2.age == 31
|
||||||
assert kate2.name == 'Kate'
|
assert kate2.name == 'Kate'
|
||||||
|
|
||||||
@ -218,9 +216,10 @@ fn test_orm() {
|
|||||||
update User set age = 32, name = 'Kate N' where name == 'Kate'
|
update User set age = 32, name = 'Kate N' where name == 'Kate'
|
||||||
}
|
}
|
||||||
|
|
||||||
mut kate3 := sql db {
|
users = sql db {
|
||||||
select from User where id == 3
|
select from User where id == 3
|
||||||
}
|
}
|
||||||
|
mut kate3 := users.first()
|
||||||
assert kate3.age == 32
|
assert kate3.age == 32
|
||||||
assert kate3.name == 'Kate N'
|
assert kate3.name == 'Kate N'
|
||||||
|
|
||||||
@ -229,9 +228,11 @@ fn test_orm() {
|
|||||||
update User set age = new_age, name = 'Kate N' where id == 3
|
update User set age = new_age, name = 'Kate N' where id == 3
|
||||||
}
|
}
|
||||||
|
|
||||||
kate3 = sql db {
|
users = sql db {
|
||||||
select from User where id == 3
|
select from User where id == 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kate3 = users.first()
|
||||||
assert kate3.age == 33
|
assert kate3.age == 33
|
||||||
assert kate3.name == 'Kate N'
|
assert kate3.name == 'Kate N'
|
||||||
|
|
||||||
@ -240,17 +241,18 @@ fn test_orm() {
|
|||||||
update User set age = foo.age, name = 'Kate N' where id == 3
|
update User set age = foo.age, name = 'Kate N' where id == 3
|
||||||
}
|
}
|
||||||
|
|
||||||
kate3 = sql db {
|
users = sql db {
|
||||||
select from User where id == 3
|
select from User where id == 3
|
||||||
}
|
}
|
||||||
|
kate3 = users.first()
|
||||||
assert kate3.age == 34
|
assert kate3.age == 34
|
||||||
assert kate3.name == 'Kate N'
|
assert kate3.name == 'Kate N'
|
||||||
|
|
||||||
no_user := sql db {
|
no_user := sql db {
|
||||||
select from User where id == 30
|
select from User where id == 30
|
||||||
}
|
}
|
||||||
assert no_user.name == '' // TODO optional
|
|
||||||
assert no_user.age == 0
|
assert no_user.len == 0
|
||||||
|
|
||||||
two_users := sql db {
|
two_users := sql db {
|
||||||
select from User limit 2
|
select from User limit 2
|
||||||
@ -270,35 +272,41 @@ fn test_orm() {
|
|||||||
assert z.len == 2
|
assert z.len == 2
|
||||||
assert z[0].id == 3
|
assert z[0].id == 3
|
||||||
|
|
||||||
oldest := sql db {
|
users = sql db {
|
||||||
select from User order by age desc limit 1
|
select from User order by age desc limit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldest := users.first()
|
||||||
assert oldest.age == 34
|
assert oldest.age == 34
|
||||||
|
|
||||||
offs := 1
|
offs := 1
|
||||||
second_oldest := sql db {
|
users = sql db {
|
||||||
select from User order by age desc limit 1 offset offs
|
select from User order by age desc limit 1 offset offs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
second_oldest := users.first()
|
||||||
assert second_oldest.age == 31
|
assert second_oldest.age == 31
|
||||||
sql db {
|
sql db {
|
||||||
delete from User where age == 34
|
delete from User where age == 34
|
||||||
}
|
}
|
||||||
|
|
||||||
updated_oldest := sql db {
|
users = sql db {
|
||||||
select from User order by age desc limit 1
|
select from User order by age desc limit 1
|
||||||
}
|
}
|
||||||
|
updated_oldest := users.first()
|
||||||
assert updated_oldest.age == 31
|
assert updated_oldest.age == 31
|
||||||
|
|
||||||
// Remove this when pg is used
|
// Remove this when pg is used
|
||||||
// db.exec('insert into User (name, age) values (NULL, 31)')
|
// db.exec('insert into User (name, age) values (NULL, 31)')
|
||||||
null_user := sql db {
|
users = sql db {
|
||||||
select from User where id == 5
|
select from User where id == 5
|
||||||
}
|
}
|
||||||
assert null_user.name == ''
|
assert users.len == 0
|
||||||
|
|
||||||
age_test := sql db {
|
users = sql db {
|
||||||
select from User where id == 1
|
select from User where id == 1
|
||||||
}
|
}
|
||||||
|
age_test := users.first()
|
||||||
|
|
||||||
assert age_test.age == 29
|
assert age_test.age == 29
|
||||||
|
|
||||||
@ -306,20 +314,22 @@ fn test_orm() {
|
|||||||
update User set age = age + 1 where id == 1
|
update User set age = age + 1 where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mut first := sql db {
|
users = sql db {
|
||||||
select from User where id == 1
|
select from User where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut first := users.first()
|
||||||
assert first.age == 30
|
assert first.age == 30
|
||||||
|
|
||||||
sql db {
|
sql db {
|
||||||
update User set age = age * 2 where id == 1
|
update User set age = age * 2 where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
first = sql db {
|
users = sql db {
|
||||||
select from User where id == 1
|
select from User where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
first = users.first()
|
||||||
assert first.age == 60
|
assert first.age == 60
|
||||||
|
|
||||||
sql db {
|
sql db {
|
||||||
@ -353,31 +363,31 @@ fn test_orm() {
|
|||||||
update Module set test_id = 11 where id == 1
|
update Module set test_id = 11 where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
test_id_mod := sql db {
|
mut modules := sql db {
|
||||||
select from Module where id == 1
|
select from Module where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
assert test_id_mod.test_id == 11
|
assert modules.first().test_id == 11
|
||||||
|
|
||||||
t := time.now()
|
t := time.now()
|
||||||
sql db {
|
sql db {
|
||||||
update Module set created = t where id == 1
|
update Module set created = t where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
updated_time_mod := sql db {
|
modules = sql db {
|
||||||
select from Module where id == 1
|
select from Module where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: usually updated_time_mod.created != t, because t has
|
// Note: usually updated_time_mod.created != t, because t has
|
||||||
// its microseconds set, while the value retrieved from the DB
|
// its microseconds set, while the value retrieved from the DB
|
||||||
// has them zeroed, because the db field resolution is seconds.
|
// has them zeroed, because the db field resolution is seconds.
|
||||||
assert updated_time_mod.created.format_ss() == t.format_ss()
|
assert modules.first().created.format_ss() == t.format_ss()
|
||||||
|
|
||||||
para_select := sql db {
|
users = sql db {
|
||||||
select from User where (name == 'Sam' && is_customer == true) || id == 1
|
select from User where (name == 'Sam' && is_customer == true) || id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
assert para_select[0] == first
|
assert users.first() == first
|
||||||
|
|
||||||
sql db {
|
sql db {
|
||||||
drop table Module
|
drop table Module
|
||||||
|
@ -16,18 +16,19 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||||||
}
|
}
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
p.check(.key_select)
|
p.check(.key_select)
|
||||||
n := p.check_name()
|
is_count := p.check_name() == 'count'
|
||||||
is_count := n == 'count'
|
|
||||||
mut typ := ast.void_type
|
mut typ := ast.void_type
|
||||||
|
|
||||||
if is_count {
|
if is_count {
|
||||||
p.check_name() // from
|
p.check_name() // from
|
||||||
typ = ast.int_type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table_pos := p.tok.pos()
|
table_pos := p.tok.pos()
|
||||||
table_type := p.parse_type() // `User`
|
table_type := p.parse_type() // `User`
|
||||||
|
|
||||||
mut where_expr := ast.empty_expr
|
mut where_expr := ast.empty_expr
|
||||||
has_where := p.tok.kind == .name && p.tok.lit == 'where'
|
has_where := p.tok.kind == .name && p.tok.lit == 'where'
|
||||||
mut query_one := false // one object is returned, not an array
|
|
||||||
if has_where {
|
if has_where {
|
||||||
p.next()
|
p.next()
|
||||||
where_expr = p.expr(0)
|
where_expr = p.expr(0)
|
||||||
@ -37,11 +38,8 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||||||
if where_check_result is ast.NodeError {
|
if where_check_result is ast.NodeError {
|
||||||
return where_check_result
|
return where_check_result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !is_count {
|
|
||||||
query_one = p.has_sql_where_expr_with_comparison_with_id(&where_expr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mut has_limit := false
|
mut has_limit := false
|
||||||
mut limit_expr := ast.empty_expr
|
mut limit_expr := ast.empty_expr
|
||||||
mut has_offset := false
|
mut has_offset := false
|
||||||
@ -64,29 +62,25 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||||||
has_desc = true
|
has_desc = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.tok.kind == .name && p.tok.lit == 'limit' {
|
if p.tok.kind == .name && p.tok.lit == 'limit' {
|
||||||
// `limit 1` means that a single object is returned
|
|
||||||
p.check_name() // `limit`
|
p.check_name() // `limit`
|
||||||
if p.tok.kind == .number && p.tok.lit == '1' {
|
|
||||||
query_one = true
|
|
||||||
}
|
|
||||||
has_limit = true
|
has_limit = true
|
||||||
limit_expr = p.expr(0)
|
limit_expr = p.expr(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.tok.kind == .name && p.tok.lit == 'offset' {
|
if p.tok.kind == .name && p.tok.lit == 'offset' {
|
||||||
p.check_name() // `offset`
|
p.check_name() // `offset`
|
||||||
has_offset = true
|
has_offset = true
|
||||||
offset_expr = p.expr(0)
|
offset_expr = p.expr(0)
|
||||||
}
|
}
|
||||||
if !query_one && !is_count {
|
|
||||||
// return an array
|
if is_count {
|
||||||
|
typ = ast.int_type
|
||||||
|
} else {
|
||||||
typ = ast.new_type(p.table.find_or_register_array(table_type))
|
typ = ast.new_type(p.table.find_or_register_array(table_type))
|
||||||
} else if !is_count {
|
|
||||||
// return a single object
|
|
||||||
// TODO optional
|
|
||||||
// typ = table_type.set_flag(.optional)
|
|
||||||
typ = table_type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
p.inside_match = false
|
p.inside_match = false
|
||||||
or_expr := p.parse_sql_or_block()
|
or_expr := p.parse_sql_or_block()
|
||||||
@ -105,7 +99,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||||||
has_order: has_order
|
has_order: has_order
|
||||||
order_expr: order_expr
|
order_expr: order_expr
|
||||||
has_desc: has_desc
|
has_desc: has_desc
|
||||||
is_array: !query_one
|
is_array: if is_count { false } else { true }
|
||||||
pos: pos.extend(p.prev_tok.pos())
|
pos: pos.extend(p.prev_tok.pos())
|
||||||
table_expr: ast.TypeNode{
|
table_expr: ast.TypeNode{
|
||||||
typ: table_type
|
typ: table_type
|
||||||
@ -304,26 +298,6 @@ fn (mut p Parser) check_sql_keyword(name string) ?bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// has_sql_where_expr_with_comparison_with_id tries to search comparison with the `id` field.
|
|
||||||
// If `id` is found it means that a database "should" return one row,
|
|
||||||
// but it is not true and depends on a database scheme.
|
|
||||||
// For example, it will be hard to use V ORM in an existing database scheme which wrote before using V.
|
|
||||||
fn (p &Parser) has_sql_where_expr_with_comparison_with_id(expr &ast.Expr) bool {
|
|
||||||
// This method will be removed in the future when we refuse it.
|
|
||||||
// A more difficult expression with `id` means a user tries to find more than one row or he is wrong.
|
|
||||||
// And there is no point to get one structure instead of an array.
|
|
||||||
// `id == x` means that a single object is returned.
|
|
||||||
if expr is ast.InfixExpr {
|
|
||||||
if expr.left is ast.Ident && expr.op == .eq {
|
|
||||||
return expr.left.name == 'id'
|
|
||||||
}
|
|
||||||
} else if expr is ast.ParExpr {
|
|
||||||
return p.has_sql_where_expr_with_comparison_with_id(expr.expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// check_sql_where_expr_has_no_undefined_variables recursively tries to find undefined variables in the right part of infix expressions.
|
// check_sql_where_expr_has_no_undefined_variables recursively tries to find undefined variables in the right part of infix expressions.
|
||||||
fn (mut p Parser) check_sql_where_expr_has_no_undefined_variables(expr &ast.Expr, unacceptable_variable_names []string) ast.Expr {
|
fn (mut p Parser) check_sql_where_expr_has_no_undefined_variables(expr &ast.Expr, unacceptable_variable_names []string) ast.Expr {
|
||||||
if expr is ast.Ident {
|
if expr is ast.Ident {
|
||||||
|
@ -38,7 +38,7 @@ fn test_orm_array() {
|
|||||||
insert par into Parent
|
insert par into Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
parent := sql db {
|
parents := sql db {
|
||||||
select from Parent where id == 1
|
select from Parent where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +46,7 @@ fn test_orm_array() {
|
|||||||
drop table Parent
|
drop table Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent := parents.first()
|
||||||
assert parent.name == par.name
|
assert parent.name == par.name
|
||||||
assert parent.children.len == par.children.len
|
assert parent.children.len == par.children.len
|
||||||
assert parent.children[0].name == 'abc'
|
assert parent.children[0].name == 'abc'
|
||||||
@ -74,10 +75,11 @@ fn test_orm_relationship() {
|
|||||||
insert par into Parent
|
insert par into Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
mut parent := sql db {
|
mut parents := sql db {
|
||||||
select from Parent where id == 1
|
select from Parent where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut parent := parents.first()
|
||||||
child.parent_id = parent.id
|
child.parent_id = parent.id
|
||||||
child.name = 'atum'
|
child.name = 'atum'
|
||||||
|
|
||||||
@ -94,10 +96,11 @@ fn test_orm_relationship() {
|
|||||||
assert parent.name == par.name
|
assert parent.name == par.name
|
||||||
assert parent.children.len == 0
|
assert parent.children.len == 0
|
||||||
|
|
||||||
parent = sql db {
|
parents = sql db {
|
||||||
select from Parent where id == 1
|
select from Parent where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent = parents.first()
|
||||||
assert parent.name == par.name
|
assert parent.name == par.name
|
||||||
assert parent.children.len == 2
|
assert parent.children.len == 2
|
||||||
assert parent.children[0].name == 'atum'
|
assert parent.children[0].name == 'atum'
|
||||||
|
@ -29,9 +29,9 @@ fn test_orm_sub_structs() {
|
|||||||
insert upper_1 into Upper
|
insert upper_1 into Upper
|
||||||
}
|
}
|
||||||
|
|
||||||
upper_s := sql db {
|
uppers := sql db {
|
||||||
select from Upper where id == 1
|
select from Upper where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
assert upper_s.sub.name == upper_1.sub.name
|
assert uppers.first().sub.name == upper_1.sub.name
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ fn test_sql_statement_inside_fn_call() {
|
|||||||
sql db {
|
sql db {
|
||||||
insert m into Movie
|
insert m into Movie
|
||||||
}
|
}
|
||||||
dump(x(sql db {
|
dump(x((sql db {
|
||||||
select from Movie where id == 1
|
select from Movie where id == 1
|
||||||
}))
|
}).first()))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user