package models import ( "context" "database/sql" "fmt" "screenmark/screenmark/.gen/haystack/haystack/model" . "screenmark/screenmark/.gen/haystack/haystack/table" . "github.com/go-jet/jet/v2/postgres" "github.com/google/uuid" ) type ListModel struct { dbPool *sql.DB } type ListWithItems struct { model.Lists Schema struct { model.Schemas SchemaItems []model.SchemaItems } } func (m ListModel) Save(ctx context.Context, userId uuid.UUID, name string, description string, schemaItems []model.SchemaItems) (ListWithItems, error) { tx, err := m.dbPool.BeginTx(ctx, nil) stmt := Lists.INSERT(Lists.UserID, Lists.Name, Lists.Description). VALUES(userId, name, description). RETURNING(Lists.ID, Lists.Name, Lists.Description) newList := model.Lists{} err = stmt.QueryContext(ctx, tx, &newList) if err != nil { tx.Rollback() return ListWithItems{}, fmt.Errorf("Could not save new list. %s", err) } insertSchemaStmt := Schemas.INSERT(Schemas.ListID). VALUES(newList.ID). RETURNING(Schemas.ID) newSchema := model.Schemas{} err = insertSchemaStmt.QueryContext(ctx, tx, &newSchema) if err != nil { tx.Rollback() return ListWithItems{}, fmt.Errorf("Could not save new schema. %s", err) } // This is very interesting... for i := range schemaItems { schemaItems[i].SchemaID = newSchema.ID } insertSchemaItemsStmt := SchemaItems.INSERT(SchemaItems.Item, SchemaItems.Value, SchemaItems.Description, SchemaItems.SchemaID). MODELS(schemaItems) _, err = insertSchemaItemsStmt.ExecContext(ctx, tx) if err != nil { tx.Rollback() return ListWithItems{}, fmt.Errorf("Could not save schema items. %s", err) } err = tx.Commit() if err != nil { return ListWithItems{}, fmt.Errorf("Could not commit transaction. %s", err) } getListAndItems := SELECT(Lists.AllColumns, Schemas.AllColumns, SchemaItems.AllColumns). FROM( Lists. INNER_JOIN(Schemas, Schemas.ListID.EQ(Lists.ID)). INNER_JOIN(SchemaItems, SchemaItems.SchemaID.EQ(Schemas.ID)), ). WHERE(Lists.ID.EQ(UUID(newList.ID))) listWithItems := ListWithItems{} err = getListAndItems.QueryContext(ctx, m.dbPool, &listWithItems) return listWithItems, err } func (m ListModel) List(ctx context.Context, userId uuid.UUID) ([]ListWithItems, error) { getListsWithItems := SELECT( Lists.AllColumns, Schemas.AllColumns, SchemaItems.AllColumns, ). FROM( Lists. INNER_JOIN(Schemas, Schemas.ListID.EQ(Lists.ID)). INNER_JOIN(SchemaItems, SchemaItems.SchemaID.EQ(Schemas.ID)), ). WHERE(Lists.UserID.EQ(UUID(userId))) lists := []ListWithItems{} err := getListsWithItems.QueryContext(ctx, m.dbPool, &lists) return lists, err } type IDValue struct { ID string `json:"id"` Value string `json:"value"` } func (m ListModel) SaveInto(ctx context.Context, listId uuid.UUID, imageId uuid.UUID, schemaValues []IDValue) error { imageSchemaItems := make([]model.ImageSchemaItems, len(schemaValues)) for i, v := range schemaValues { parsedId, err := uuid.Parse(v.ID) if err != nil { return err } imageSchemaItems[i].SchemaItemID = parsedId imageSchemaItems[i].ImageID = imageId imageSchemaItems[i].Value = &v.Value } tx, err := m.dbPool.BeginTx(ctx, nil) if err != nil { return err } stmt := ImageLists.INSERT(ImageLists.ListID, ImageLists.ImageID). VALUES(listId, imageId) _, err = stmt.ExecContext(ctx, tx) if err != nil { tx.Rollback() return fmt.Errorf("Could not insert new list. %s", err) } insertSchemaItemsStmt := ImageSchemaItems. INSERT(ImageSchemaItems.Value, ImageSchemaItems.SchemaItemID, ImageSchemaItems.ImageID). MODELS(imageSchemaItems) _, err = insertSchemaItemsStmt.ExecContext(ctx, tx) if err != nil { tx.Rollback() return fmt.Errorf("Could not insert schema items. %s", err) } err = tx.Commit() return err } func NewListModel(db *sql.DB) ListModel { return ListModel{dbPool: db} }