Fixed hardcoded id

This commit is contained in:
Hein 2025-11-20 09:40:11 +02:00
parent 35089f511f
commit 7d6a9025f5
4 changed files with 31 additions and 11 deletions

View File

@ -388,12 +388,17 @@ func (b *BunUpdateQuery) Set(column string, value interface{}) common.UpdateQuer
} }
func (b *BunUpdateQuery) SetMap(values map[string]interface{}) common.UpdateQuery { func (b *BunUpdateQuery) SetMap(values map[string]interface{}) common.UpdateQuery {
pkName := reflection.GetPrimaryKeyName(b.model)
for column, value := range values { for column, value := range values {
// Validate column is writable if model is set // Validate column is writable if model is set
if b.model != nil && !reflection.IsColumnWritable(b.model, column) { if b.model != nil && !reflection.IsColumnWritable(b.model, column) {
// Skip scan-only columns // Skip scan-only columns
continue continue
} }
if pkName != "" && column == pkName {
// Skip primary key updates
continue
}
b.query = b.query.Set(column+" = ?", value) b.query = b.query.Set(column+" = ?", value)
} }
return b return b

View File

@ -369,13 +369,20 @@ func (g *GormUpdateQuery) Set(column string, value interface{}) common.UpdateQue
} }
func (g *GormUpdateQuery) SetMap(values map[string]interface{}) common.UpdateQuery { func (g *GormUpdateQuery) SetMap(values map[string]interface{}) common.UpdateQuery {
// Filter out read-only columns if model is set // Filter out read-only columns if model is set
if g.model != nil { if g.model != nil {
pkName := reflection.GetPrimaryKeyName(g.model)
filteredValues := make(map[string]interface{}) filteredValues := make(map[string]interface{})
for column, value := range values { for column, value := range values {
if pkName != "" && column == pkName {
// Skip primary key updates
continue
}
if reflection.IsColumnWritable(g.model, column) { if reflection.IsColumnWritable(g.model, column) {
filteredValues[column] = value filteredValues[column] = value
} }
} }
g.updates = filteredValues g.updates = filteredValues
} else { } else {

View File

@ -111,6 +111,9 @@ func (p *NestedCUDProcessor) ProcessNestedCUD(
// Inject parent IDs for foreign key resolution // Inject parent IDs for foreign key resolution
p.injectForeignKeys(regularData, modelType, parentIDs) p.injectForeignKeys(regularData, modelType, parentIDs)
// Get the primary key name for this model
pkName := reflection.GetPrimaryKeyName(model)
// Process based on operation // Process based on operation
switch strings.ToLower(operation) { switch strings.ToLower(operation) {
case "insert", "create": case "insert", "create":
@ -128,30 +131,30 @@ func (p *NestedCUDProcessor) ProcessNestedCUD(
} }
case "update": case "update":
rows, err := p.processUpdate(ctx, regularData, tableName, data["id"]) rows, err := p.processUpdate(ctx, regularData, tableName, data[pkName])
if err != nil { if err != nil {
return nil, fmt.Errorf("update failed: %w", err) return nil, fmt.Errorf("update failed: %w", err)
} }
result.ID = data["id"] result.ID = data[pkName]
result.AffectedRows = rows result.AffectedRows = rows
result.Data = regularData result.Data = regularData
// Process child relations for update // Process child relations for update
if err := p.processChildRelations(ctx, "update", data["id"], relationFields, result.RelationData, modelType); err != nil { if err := p.processChildRelations(ctx, "update", data[pkName], relationFields, result.RelationData, modelType); err != nil {
return nil, fmt.Errorf("failed to process child relations: %w", err) return nil, fmt.Errorf("failed to process child relations: %w", err)
} }
case "delete": case "delete":
// Process child relations first (for referential integrity) // Process child relations first (for referential integrity)
if err := p.processChildRelations(ctx, "delete", data["id"], relationFields, result.RelationData, modelType); err != nil { if err := p.processChildRelations(ctx, "delete", data[pkName], relationFields, result.RelationData, modelType); err != nil {
return nil, fmt.Errorf("failed to process child relations before delete: %w", err) return nil, fmt.Errorf("failed to process child relations before delete: %w", err)
} }
rows, err := p.processDelete(ctx, tableName, data["id"]) rows, err := p.processDelete(ctx, tableName, data[pkName])
if err != nil { if err != nil {
return nil, fmt.Errorf("delete failed: %w", err) return nil, fmt.Errorf("delete failed: %w", err)
} }
result.ID = data["id"] result.ID = data[pkName]
result.AffectedRows = rows result.AffectedRows = rows
result.Data = regularData result.Data = regularData

View File

@ -807,12 +807,14 @@ func (h *Handler) handleUpdate(ctx context.Context, w common.ResponseWriter, id
nestedRelations = relations nestedRelations = relations
} }
// Get the primary key name for the model
pkName := reflection.GetPrimaryKeyName(model)
// Ensure ID is in the data map for the update // Ensure ID is in the data map for the update
dataMap["id"] = targetID dataMap[pkName] = targetID
// Create update query // Create update query
query := tx.NewUpdate().Table(tableName).SetMap(dataMap) query := tx.NewUpdate().Table(tableName).SetMap(dataMap)
pkName := reflection.GetPrimaryKeyName(model)
query = query.Where(fmt.Sprintf("%s = ?", common.QuoteIdent(pkName)), targetID) query = query.Where(fmt.Sprintf("%s = ?", common.QuoteIdent(pkName)), targetID)
// Execute BeforeScan hooks - pass query chain so hooks can modify it // Execute BeforeScan hooks - pass query chain so hooks can modify it
@ -936,6 +938,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
// Array of IDs or objects with ID field // Array of IDs or objects with ID field
logger.Info("Batch delete with %d items ([]interface{})", len(v)) logger.Info("Batch delete with %d items ([]interface{})", len(v))
deletedCount := 0 deletedCount := 0
pkName := reflection.GetPrimaryKeyName(model)
err := h.db.RunInTransaction(ctx, func(tx common.Database) error { err := h.db.RunInTransaction(ctx, func(tx common.Database) error {
for _, item := range v { for _, item := range v {
var itemID interface{} var itemID interface{}
@ -945,7 +948,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
case string: case string:
itemID = v itemID = v
case map[string]interface{}: case map[string]interface{}:
itemID = v["id"] itemID = v[pkName]
default: default:
itemID = item itemID = item
} }
@ -1002,9 +1005,10 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
// Array of objects with id field // Array of objects with id field
logger.Info("Batch delete with %d items ([]map[string]interface{})", len(v)) logger.Info("Batch delete with %d items ([]map[string]interface{})", len(v))
deletedCount := 0 deletedCount := 0
pkName := reflection.GetPrimaryKeyName(model)
err := h.db.RunInTransaction(ctx, func(tx common.Database) error { err := h.db.RunInTransaction(ctx, func(tx common.Database) error {
for _, item := range v { for _, item := range v {
if itemID, ok := item["id"]; ok && itemID != nil { if itemID, ok := item[pkName]; ok && itemID != nil {
itemIDStr := fmt.Sprintf("%v", itemID) itemIDStr := fmt.Sprintf("%v", itemID)
// Execute hooks for each item // Execute hooks for each item
@ -1052,7 +1056,8 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
case map[string]interface{}: case map[string]interface{}:
// Single object with id field // Single object with id field
if itemID, ok := v["id"]; ok && itemID != nil { pkName := reflection.GetPrimaryKeyName(model)
if itemID, ok := v[pkName]; ok && itemID != nil {
id = fmt.Sprintf("%v", itemID) id = fmt.Sprintf("%v", itemID)
} }
} }