jet icon indicating copy to clipboard operation
jet copied to clipboard

Data corrupted when mapped from UUID array

Open illusionare opened this issue 1 year ago • 4 comments

Describe the bug In database I have 2 tables with relation one-to-many (both has ID columns of type uuid). I am making a select with a join of these two tables. The result object contains id field of parent table and an array of ids of child table. Data in the array of child ids are corrupted. The reason: the array of UUIDS is treated as an array of simple type and elements(e.g. uuid) created from first 16 bytes of the string.

Environment (please complete the following information):

  • OS: linux
  • Database: postgres
  • Database driver: pq
  • Jet version: v2.11.1

Code snippet

Code for database:

CREATE TABLE main (
                      id UUID PRIMARY KEY
);

CREATE TABLE second (
                        main_id UUID,
                        second_id UUID,
                        FOREIGN KEY (main_id) REFERENCES main (id)
);

Generated models:

type Main struct {
    ID uuid.UUID \`sql:"primary_key"\`
}

type Second struct {
    MainID   *uuid.UUID
    SecondID *uuid.UUID
}

Code to run:

func main() {
	db, err := sql.Open("postgres", dbConnStr)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// ARRANGE
	mainID := uuid.UUID{} // with empty UUID it is easier to see error
	secondID := uuid.UUID{}

	//InsertData(db, mainID, secondID)

	// ACT
	queryStmt := postgres.
		SELECT(table.Main.ID, table.Second.SecondID).
		FROM(table.Main.INNER_JOIN(table.Second, table.Second.MainID.EQ(table.Main.ID))).
		WHERE(table.Second.MainID.EQ(postgres.UUID(mainID)))

	var composite []Composite
	err = queryStmt.Query(db, &composite)
	if err != nil {
		log.Fatalf("Error querying second: %v", err)
	}
	// ASSERT
	fmt.Printf("Original: mainID:%v secondID:%v\n", mainID, secondID)
	fmt.Printf("Original: mainID:%v secondID:%v\n", composite[0].Main, composite[0].SecondId[0])
	fmt.Printf("Original: mainID:%v secondID:%v <--\n", composite[0].Main, composite[0].SecondId2[0])
	fmt.Printf("Original: mainID:%v secondID:%v\n", composite[0].Main, composite[0].SecondId3)
	fmt.Printf("Original: mainID:%v secondID:%v\n", composite[0].Main, composite[0].SecondId4[0].SecondId)
}

func InsertData(db *sql.DB, mainID uuid.UUID, secondID uuid.UUID) {
	insertMainStmt := table.Main.
		INSERT(table.Main.ID).
		VALUES(mainID)

	_, err := insertMainStmt.Exec(db)
	if err != nil {
		log.Fatalf("Error inserting into main: %v", err)
	}
	fmt.Printf("Inserted main entity with ID: %s\n", mainID)

	insertSecondStmt := table.Second.
		INSERT(table.Second.MainID, table.Second.SecondID).
		VALUES(mainID, secondID)

	_, err = insertSecondStmt.Exec(db)
	if err != nil {
		log.Fatalf("Error inserting into second: %v", err)
	}
}

Composite class:

type Proxy struct {
	SecondId uuid.UUID `alias:"Second.second_id"`
}

type Composite struct {
	model.Main
	SecondId  []string    `alias:"Second.second_id"`
	SecondId2 []uuid.UUID `alias:"Second.second_id"` // this is an version of errors
	SecondId3 uuid.UUID   `alias:"Second.second_id"`
	SecondId4 []Proxy     `alias:"Second.*"`
}

Expected behavior I am expecting that array of UUID`s will have correct values.

illusionare avatar Oct 21 '24 12:10 illusionare

What do you mean by data corruption? queryStmt.Query(db, &composite) always returns this error: Error querying second: jet: can't append string to []uuid.UUID slice: can't assign string to uuid.UUID.

houtn11 avatar Oct 22 '24 11:10 houtn11

Couldn't reproduce data corruption. Query always returns an error. But I agree scan into slice of Scanner type should work as well.

What UUID type are you using?

go-jet avatar Oct 23 '24 13:10 go-jet

I am using "github.com/google/uuid"

illusionare avatar Oct 23 '24 13:10 illusionare

What do you mean by data corruption? queryStmt.Query(db, &composite) always returns this error: Error querying second: jet: can't append string to []uuid.UUID slice: can't assign string to uuid.UUID.

Well, i am not receiving any errors in this example. My output is:

Original: mainID:00000000-0000-0000-0000-000000000000 secondID:00000000-0000-0000-0000-000000000000
Original: mainID:{00000000-0000-0000-0000-000000000000} secondID:00000000-0000-0000-0000-000000000000
Original: mainID:{00000000-0000-0000-0000-000000000000} secondID:30303030-3030-3030-2d30-3030302d3030 <--
Original: mainID:{00000000-0000-0000-0000-000000000000} secondID:00000000-0000-0000-0000-000000000000
Original: mainID:{00000000-0000-0000-0000-000000000000} secondID:00000000-0000-0000-0000-000000000000

illusionare avatar Oct 23 '24 13:10 illusionare