vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.5k stars 2.15k forks source link

[ORM] RUNTIME ERROR: invalid memory access #19327

Open Ddiidev opened 9 months ago

Ddiidev commented 9 months ago

Describe the bug

ORM cannot handle nested foreign keys, example:

Reproduction Steps

pub struct Address {
    id int [primary; sql: serial; nonull]
    create_at string [default: 'now()'; nonull; sql_type: 'TIMESTAMP']
    update_at string [default: 'now()'; nonull; sql_type: 'TIMESTAMP']
    street string [nonull]
    city string [nonull]
    state string [nonull]
    zip_code string [nonull]
    proximity string [nonull]
}
[table: 'RealStates']
pub struct RealState {
    id string [primary; sql_type: 'uuid'; default: "uuid_generate_v4()"; nonull]
    parent_id int
    name string [sql_type: 'varchar(80)'; nonull]
    cnpj string [sql_type: 'varchar(14)'; nonull]
    address []Address [fkey: 'id']
}
[table: 'Realtors']
pub struct Realtor {
    id string [primary; sql_type: 'uuid'; default: "uuid_generate_v4()"; nonull]
    first_name string [sql_type: "VARCHAR(30)"; nonull]
    last_name string [sql_type: "VARCHAR(30)"; nonull]
    creci string [sql_type: "VARCHAR(8)"; nonull]
    cnpj string [sql_type: "VARCHAR(15)"]
    cpf string [sql_type: "VARCHAR(12)"]
    phone string [sql_type: "VARCHAR(15)"; nonull]
    real_state []RealState [fkey: 'id']
}
mut db := pg.connect(host: pg_host, user: pg_user, password: pg_pass, dbname: pg_db)!
defer {
    db.close()
}

dump(sql db {
    select from Realtor
}!)

Expected Behavior

something like...

[./src/main.v:37] ast.SqlExpr: [Realtor{
    id: 'ffce0e60-084d-49c0-9e19-a272f257b1a4',
    first_name: 'asdsd',
    last_name: 'qweqwe',
    creci: '4312',
    cnpj: '',
    cpf: '',
    phone: '1241233',
    real_state: '1'
}]

Current Behavior

V panic: as cast: cannot cast `unknown` to `v.ast.InfixExpr`
v hash: 12dd6e8
/tmp/v_1000/v2.2271908984048564447.tmp.c:20702: at _v_panic: Backtrace
/tmp/v_1000/v2.2271908984048564447.tmp.c:21209: by __as_cast
/tmp/v_1000/v2.2271908984048564447.tmp.c:11102: by v__gen__c__Gen_write_orm_select
/tmp/v_1000/v2.2271908984048564447.tmp.c:11145: by v__gen__c__Gen_write_orm_select
/tmp/v_1000/v2.2271908984048564447.tmp.c:10133: by v__gen__c__Gen_sql_select_expr
/tmp/v_1000/v2.2271908984048564447.tmp.c:63183: by v__gen__c__Gen_expr
/tmp/v_1000/v2.2271908984048564447.tmp.c:3111: by v__gen__c__Gen_dump_expr
/tmp/v_1000/v2.2271908984048564447.tmp.c:62978: by v__gen__c__Gen_expr
/tmp/v_1000/v2.2271908984048564447.tmp.c:61844: by v__gen__c__Gen_stmt
/tmp/v_1000/v2.2271908984048564447.tmp.c:61676: by v__gen__c__Gen_stmts_with_tmp_var
/tmp/v_1000/v2.2271908984048564447.tmp.c:61564: by v__gen__c__Gen_stmts
/tmp/v_1000/v2.2271908984048564447.tmp.c:3822: by v__gen__c__Gen_gen_fn_decl
/tmp/v_1000/v2.2271908984048564447.tmp.c:3509: by v__gen__c__Gen_fn_decl
/tmp/v_1000/v2.2271908984048564447.tmp.c:61856: by v__gen__c__Gen_stmt
/tmp/v_1000/v2.2271908984048564447.tmp.c:61676: by v__gen__c__Gen_stmts_with_tmp_var
/tmp/v_1000/v2.2271908984048564447.tmp.c:61564: by v__gen__c__Gen_stmts
/tmp/v_1000/v2.2271908984048564447.tmp.c:60494: by v__gen__c__Gen_gen_file
/tmp/v_1000/v2.2271908984048564447.tmp.c:60437: by v__gen__c__cgen_process_one_file_cb
/tmp/v_1000/v2.2271908984048564447.tmp.c:43543: by sync__pool__process_in_thread
/tmp/v_1000/v2.2271908984048564447.tmp.c:10971: by sync__pool__process_in_thread_thread_wrapper
7f8040bd7b43 : by ???

Possible Solution

???

Additional Information/Context

I already tried to do address Address [fkey: 'id'] because I thought it was like this and I also tried: address []Address [fkey: 'id'] which one is correct?

V version

V 0.4.1 12dd6e8

Environment details (OS name and version, etc.)

V full version: V 0.4.1 45e6e7d.12dd6e8 OS: linux, Ubuntu 22.04.3 LTS (WSL 2) Processor: 8 cpus, 64bit, little endian, 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz

getwd: /mnt/c/Users/AndreLuiz/Documents/SourceApps/QRImovel/QRIMovel-backend vexe: /home/andre_luiz/system/v/v vexe mtime: 2023-09-09 23:52:49

vroot: OK, value: /home/andre_luiz/system/v VMODULES: OK, value: /home/andre_luiz/.vmodules VTMP: OK, value: /tmp/v_1000

Git version: git version 2.34.1 Git vroot status: weekly.2023.33-138-g12dd6e8b (4 commit(s) behind V master) .git/config present: true

CC version: cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 thirdparty/tcc status: Error: fatal: detected dubious ownership in repository at '/home/andre_luiz/system/v/thirdparty/tcc' To add an exception for this directory, call:

    git config --global --add safe.directory /home/andre_luiz/system/v/thirdparty/tcc

Error: fatal: detected dubious ownership in repository at '/home/andre_luiz/system/v/thirdparty/tcc' To add an exception for this directory, call:

    git config --global --add safe.directory /home/andre_luiz/system/v/thirdparty/tcc
Ddiidev commented 1 week ago

After fix #21598, this #19326 issue was fixed, but this one works strangely. If address is an array of Address, it reports an error.

Running code...
Can't run code. The server returned an error:
/tmp/v_60000/../../../../../../box/code.v:754: error: cannot convert 'struct main__RealState' to 'struct array'
builder error: 
==================
C error found. It should never happen, when compiling pure V code.
This is a V compiler bug, please report it using `v bug file.v`,
or goto https://github.com/vlang/v/issues/new/choose .
You can also use #help on Discord: https://discord.gg/vlang .
Exited with error status 1
Please try again.

This is the code used, is it preferable to open a new issue and close this one?

import db.sqlite

pub struct Address {
    id        int    @[primary; sql: serial]
    parent_id int
    create_at string
    update_at string
    street    string
    city      string
    state     string
    zip_code  string
    proximity string
}

@[table: 'RealStates']
pub struct RealState {
    id        string  @[primary; sql_type: 'uuid']
    parent_id int
    name      string  @[sql_type: 'varchar(80)']
    cnpj      string  @[sql_type: 'varchar(14)']
    address   []Address @[fkey: 'parent_id']
}

@[table: 'Realtors']
pub struct Realtor {
    id         ?string    @[ primary; sql_type: 'uuid']
    first_name string    @[sql_type: 'VARCHAR(30)']
    last_name  string    @[sql_type: 'VARCHAR(30)']
    creci      string    @[sql_type: 'VARCHAR(8)']
    cnpj       ?string   @[sql_type: 'VARCHAR(15)']
    cpf        ?string   @[sql_type: 'VARCHAR(12)']
    phone      string    @[sql_type: 'VARCHAR(15)']
    real_state RealState @[fkey: 'id']
}

fn main() {
    mut db := sqlite.connect(":memory:")!

    data := Realtor{
        first_name: 'John',
        last_name:  'Doe',
        creci:      '12345678',
        cnpj:       '12345678901234',
        cpf:        '12345678901',
        phone:      '1234567890',
        real_state: RealState{
            name: 'Teste',
            cnpj: '12345678901234',
            address: [Address{
                street:    'Teste',
                city:      'Teste',
                state:     'Teste',
                zip_code:  'Teste',
                proximity: 'Teste',
            }],
        }
    }

    sql db {
        create table Address
        create table RealState
        create table Realtor
    }!

    sql db {
        insert data into Realtor
    }!

    dump(sql db {
        select from Realtor
    }!)

    db.close()!
}