uptrace/bun

Unexpected Data Truncation in CTE with Type Casting During Bulk Update

Aperta

#1093 aperta il 1 gen 2025

 (7 commenti) (0 reazioni) (1 assegnatario)Go (279 fork)user submission
enhancementhelp wanted

Metriche repository

Star
 (4826 stelle)
Metriche merge PR
 (Merge medio 76g 17h) (1 PR mergiata in 30 g)

Descrizione

Hello,

I have encountered an issue with data truncation caused by type casting for a bulk update with CTEs. Below is a minimal reproducible example and the SQL query generated by the ORM (this code is in internal/dbtest/pg_test.go ):

func TestBulkUpdate(t *testing.T) {
    type Model struct {
        ID   int64
        Name string `bun:",type:varchar(3)"`
    }

    db := pg(t)
    t.Cleanup(func() { db.Close() })

    mustResetModel(t, ctx, db, (*Model)(nil))

    models := []*Model{
        {ID: 1, Name: "foo"},
        {ID: 2, Name: "bar"},
    }

    _, err := db.NewInsert().Model(&models).Exec(ctx)
    require.NoError(t, err)

    models[0].Name = "abcd"

    res, err := db.NewUpdate().
        With("_data", db.NewValues(&models)).
        Model((*Model)(nil)).
        TableExpr("_data").
        Set("name = _data.name").
        Where("model.id = _data.id").
        Exec(ctx)
    require.NoError(t, err) // pass

    require.Equal(t, models[0].Name, updatedModels[0].Name) // failed (expected: abcd, actual: abc)
}

generated sql:

WITH "_data" ("id", "name") AS (
    VALUES (1::BIGINT, 'abcd'::varchar(3)), (2::BIGINT, 'bar'::varchar(3))
) 
UPDATE "models" AS "model" 
SET name = _data.name 
FROM _data 
WHERE (model.id = _data.id)

The issue occurs because of the type casting in the VALUES clause ('abcd'::varchar(3)), which results in data truncation ('abcd' becomes 'abc'). This behavior seems problematic for the following reasons:

  • The ORM silently truncates data without throwing any error or warning.
  • This could lead to unexpected data loss, especially if the developer is unaware of the database type constraints.
  • It does not align with the general expectation of ORMs preventing silent data corruption.

Could the ORM be enhanced to either:

  • Avoid type casting in CTEs when it's not strictly necessary?
  • Add a configuration option to handle this behavior explicitly?

Thank you for your time and consideration. Let me know if you need any further details or clarifications.

Guida contributor