sqlx icon indicating copy to clipboard operation
sqlx copied to clipboard

FIX cloning arguments on "join"

Open MishaNiki opened this issue 4 years ago • 3 comments

https://github.com/jmoiron/sqlx/issues/753

The project made the transition from version 1.2.4 to version 1.3.4.

Cases with arguments cloning in the "join" request stopped working

Example:

SELECT t_1.code_1, t_1.code_2 , t_1.name, t_1.age
FROM public.table_name t_1
INNER JOIN (
    VALUES (:code_1, :code_2)
) t_2 (code_1, code_2) ON
    t_2.code_1 = t_1.code_1 AND t_2.code_2 = t_1.code_2
args := struct{
    Code1 string `db:"code_1"`
    Code2 string `db:"code_2"`
}{
    {"v1", "v1"},  {"v2", "v2"},
}

Expected Result:

SELECT t_1.code_1, t_1.code_2 , t_1.name, t_1.age
FROM public.table_name t_1
INNER JOIN (
    VALUES ($1, $2),($3, $4)
) t_2 (code_1, code_2) ON
    t_2.code_1 = t_1.code_1 AND t_2.code_2 = t_1.code_2

Actual Result:

SELECT t_1.code_1, t_1.code_2 , t_1.name, t_1.age
FROM public.table_name t_1
INNER JOIN (
    VALUES ($1, $2)
) t_2 (code_1, code_2) ON
    t_2.code_1 = t_1.code_1 AND t_2.code_2 = t_1.code_2

Solution to the problem

Add one more parenthesis before VALUES

// named.go
var valuesReg = regexp.MustCompile(`[\(\)]\s*(?i)VALUES\s*\(`)

test case

// named_test.go

func TestFixBounds(t *testing.T) {
     table := []struct {
         name, query, expect string
         loop                int
    }{
         {
             name:   `query with "join" generated table`,
             query:  `
                 SELECT 
                     t_1.code_values, t_2.name, t_2.age, t_2.first, t_2.last  
                 FROM public.table_1 t_1 
                 INNER JOIN 
                     (VALUES (:v_code, :v_name, :v_age, :v_first, :v_last)) 
                     t_2 (code, name, age, first, last)
                 ON
                     t_1.code_values = t_2.code
             `,
             expect: `
                 SELECT
                     t_1.code_values, t_2.name, t_2.age, t_2.first, t_2.last  
                 FROM public.table_1 t_1 
                 INNER JOIN 
                     (VALUES (:v_code, :v_name, :v_age, :v_first, :v_last),(:v_code, :v_name, :v_age, :v_first, :v_last)) 
                     t_2 (code, name, age, first, last)
                 ON
                     t_1.code_values = t_2.code
             `,
             loop:   2,
         },
    }
}

MishaNiki avatar Jul 14 '21 11:07 MishaNiki

@jmoiron

sosiska avatar Jul 20 '21 10:07 sosiska

i think that thisI think this pull is very important .

baibikov avatar Jul 20 '21 12:07 baibikov

Or it should be fixed like in this comment: https://github.com/jmoiron/sqlx/pull/734/files/4b6b69ec278c1fbfafba4336f8c84065b0911029 Could make the solution works with more cases.

QuangTung97 avatar Jul 22 '21 05:07 QuangTung97