Preload fixes

This commit is contained in:
Hein 2025-11-11 15:34:24 +02:00
parent ce106fa940
commit c52fcff61d
5 changed files with 73 additions and 26 deletions

58
.vscode/tasks.json vendored
View File

@ -24,21 +24,63 @@
"type": "go", "type": "go",
"label": "go: test workspace", "label": "go: test workspace",
"command": "test", "command": "test",
"options": { "options": {
"env": { "cwd": "${workspaceFolder}"
"CGO_ENABLED": "0"
},
"cwd": "${workspaceFolder}/bin",
}, },
"args": [ "args": [
"../..." "-v",
"-race",
"-coverprofile=coverage.out",
"-covermode=atomic",
"./..."
], ],
"problemMatcher": [ "problemMatcher": [
"$go" "$go"
], ],
"group": "build", "group": {
"kind": "test",
"isDefault": true
}, },
"presentation": {
"reveal": "always",
"panel": "new"
}
},
{
"type": "shell",
"label": "go: vet workspace",
"command": "go vet ./...",
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$go"
],
"group": "test"
},
{
"type": "shell",
"label": "go: lint workspace",
"command": "golangci-lint run --timeout=5m",
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [],
"group": "test"
},
{
"type": "shell",
"label": "go: full test suite",
"dependsOrder": "sequence",
"dependsOn": [
"go: vet workspace",
"go: test workspace"
],
"problemMatcher": [],
"group": {
"kind": "test",
"isDefault": false
}
}
] ]
} }

View File

@ -183,7 +183,8 @@ func (v *ColumnValidator) ValidateRequestOptions(options RequestOptions) error {
} }
// Validate Preload columns (if specified) // Validate Preload columns (if specified)
for _, preload := range options.Preload { for idx := range options.Preload {
preload := options.Preload[idx]
// Note: We don't validate the relation name itself, as it's a relationship // Note: We don't validate the relation name itself, as it's a relationship
// Only validate columns if specified for the preload // Only validate columns if specified for the preload
if err := v.ValidateColumns(preload.Columns); err != nil { if err := v.ValidateColumns(preload.Columns); err != nil {
@ -239,7 +240,8 @@ func (v *ColumnValidator) FilterRequestOptions(options RequestOptions) RequestOp
// Filter Preload columns // Filter Preload columns
validPreloads := make([]PreloadOption, 0, len(options.Preload)) validPreloads := make([]PreloadOption, 0, len(options.Preload))
for _, preload := range options.Preload { for idx := range options.Preload {
preload := options.Preload[idx]
filteredPreload := preload filteredPreload := preload
filteredPreload.Columns = v.FilterValidColumns(preload.Columns) filteredPreload.Columns = v.FilterValidColumns(preload.Columns)
filteredPreload.OmitColumns = v.FilterValidColumns(preload.OmitColumns) filteredPreload.OmitColumns = v.FilterValidColumns(preload.OmitColumns)

View File

@ -699,6 +699,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
schema := GetSchema(ctx) schema := GetSchema(ctx)
entity := GetEntity(ctx) entity := GetEntity(ctx)
tableName := GetTableName(ctx) tableName := GetTableName(ctx)
model := GetModel(ctx)
logger.Info("Deleting records from %s.%s", schema, entity) logger.Info("Deleting records from %s.%s", schema, entity)
@ -711,7 +712,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
err := h.db.RunInTransaction(ctx, func(tx common.Database) error { err := h.db.RunInTransaction(ctx, func(tx common.Database) error {
for _, itemID := range v { for _, itemID := range v {
query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), itemID) query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), itemID)
if _, err := query.Exec(ctx); err != nil { if _, err := query.Exec(ctx); err != nil {
return fmt.Errorf("failed to delete record %s: %w", itemID, err) return fmt.Errorf("failed to delete record %s: %w", itemID, err)
} }
@ -750,7 +751,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
continue // Skip items without ID continue // Skip items without ID
} }
query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), itemID) query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), itemID)
result, err := query.Exec(ctx) result, err := query.Exec(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to delete record %v: %w", itemID, err) return fmt.Errorf("failed to delete record %v: %w", itemID, err)
@ -775,7 +776,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
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["id"]; ok && itemID != nil {
query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), itemID) query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), itemID)
result, err := query.Exec(ctx) result, err := query.Exec(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to delete record %v: %w", itemID, err) return fmt.Errorf("failed to delete record %v: %w", itemID, err)
@ -809,7 +810,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
return return
} }
query := h.db.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), id) query := h.db.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), id)
result, err := query.Exec(ctx) result, err := query.Exec(ctx)
if err != nil { if err != nil {
@ -1118,7 +1119,8 @@ func (h *Handler) applyPreloads(model interface{}, query common.SelectQuery, pre
return query return query
} }
for _, preload := range preloads { for idx := range preloads {
preload := preloads[idx]
logger.Debug("Processing preload for relation: %s", preload.Relation) logger.Debug("Processing preload for relation: %s", preload.Relation)
relInfo := h.getRelationshipInfo(modelType, preload.Relation) relInfo := h.getRelationshipInfo(modelType, preload.Relation)
if relInfo == nil { if relInfo == nil {

View File

@ -310,8 +310,8 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
options.Preload = make([]common.PreloadOption, 0) options.Preload = make([]common.PreloadOption, 0)
} }
skip := false skip := false
for _, existing := range options.Preload { for idx := range options.Preload {
if existing.Relation == expand.Relation { if options.Preload[idx].Relation == expand.Relation {
skip = true skip = true
continue continue
} }
@ -327,7 +327,8 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
} }
// Apply preloading // Apply preloading
for _, preload := range options.Preload { for idx := range options.Preload {
preload := options.Preload[idx]
logger.Debug("Applying preload: %s", preload.Relation) logger.Debug("Applying preload: %s", preload.Relation)
query = query.PreloadRelation(preload.Relation, func(sq common.SelectQuery) common.SelectQuery { query = query.PreloadRelation(preload.Relation, func(sq common.SelectQuery) common.SelectQuery {
if len(preload.OmitColumns) > 0 { if len(preload.OmitColumns) > 0 {
@ -972,7 +973,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
continue continue
} }
query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), itemID) query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), itemID)
result, err := query.Exec(ctx) result, err := query.Exec(ctx)
if err != nil { if err != nil {
@ -1039,7 +1040,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
continue continue
} }
query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), itemID) query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), itemID)
result, err := query.Exec(ctx) result, err := query.Exec(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to delete record %v: %w", itemID, err) return fmt.Errorf("failed to delete record %v: %w", itemID, err)
@ -1090,7 +1091,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
continue continue
} }
query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), itemID) query := tx.NewDelete().Table(tableName).Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), itemID)
result, err := query.Exec(ctx) result, err := query.Exec(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to delete record %v: %w", itemID, err) return fmt.Errorf("failed to delete record %v: %w", itemID, err)
@ -1150,7 +1151,7 @@ func (h *Handler) handleDelete(ctx context.Context, w common.ResponseWriter, id
return return
} }
query = query.Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(tableName))), id) query = query.Where(fmt.Sprintf("%s = ?", common.QuoteIdent(reflection.GetPrimaryKeyName(model))), id)
// Execute BeforeScan hooks - pass query chain so hooks can modify it // Execute BeforeScan hooks - pass query chain so hooks can modify it
hookCtx.Query = query hookCtx.Query = query