replaced indirect expand field.Unique with unique index constraint check
This commit is contained in:
		
							parent
							
								
									2a682a10b2
								
							
						
					
					
						commit
						226352f884
					
				|  | @ -9,6 +9,7 @@ import ( | |||
| 	"github.com/pocketbase/dbx" | ||||
| 	"github.com/pocketbase/pocketbase/models" | ||||
| 	"github.com/pocketbase/pocketbase/models/schema" | ||||
| 	"github.com/pocketbase/pocketbase/tools/dbutils" | ||||
| 	"github.com/pocketbase/pocketbase/tools/inflector" | ||||
| 	"github.com/pocketbase/pocketbase/tools/list" | ||||
| 	"github.com/pocketbase/pocketbase/tools/security" | ||||
|  | @ -86,7 +87,7 @@ func (dao *Dao) expandRecords(records []*models.Record, expandPath string, fetch | |||
| 		if indirectRelFieldOptions == nil || indirectRelFieldOptions.CollectionId != mainCollection.Id { | ||||
| 			return fmt.Errorf("Invalid indirect relation field path %q.", parts[0]) | ||||
| 		} | ||||
| 		if indirectRelFieldOptions.MaxSelect != nil && *indirectRelFieldOptions.MaxSelect != 1 { | ||||
| 		if indirectRelFieldOptions.IsMultiple() { | ||||
| 			// for now don't allow multi-relation indirect fields expand
 | ||||
| 			// due to eventual poor query performance with large data sets.
 | ||||
| 			return fmt.Errorf("Multi-relation fields cannot be indirectly expanded in %q.", parts[0]) | ||||
|  | @ -126,7 +127,7 @@ func (dao *Dao) expandRecords(records []*models.Record, expandPath string, fetch | |||
| 			MaxSelect:    nil, | ||||
| 			CollectionId: indirectRel.Id, | ||||
| 		} | ||||
| 		if indirectRelField.Unique { | ||||
| 		if isRelFieldUnique(indirectRel, indirectRelField.Name) { | ||||
| 			relFieldOptions.MaxSelect = types.Pointer(1) | ||||
| 		} | ||||
| 		// indirect relation
 | ||||
|  | @ -269,3 +270,14 @@ func normalizeExpands(paths []string) []string { | |||
| 
 | ||||
| 	return list.ToUniqueStringSlice(result) | ||||
| } | ||||
| 
 | ||||
| func isRelFieldUnique(collection *models.Collection, fieldName string) bool { | ||||
| 	for _, idx := range collection.Indexes { | ||||
| 		parsed := dbutils.ParseIndex(idx.(string)) | ||||
| 		if parsed.Unique && len(parsed.Columns) == 1 && strings.EqualFold(parsed.Columns[0].Name, fieldName) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
|  |  | |||
|  | @ -362,3 +362,57 @@ func TestExpandRecord(t *testing.T) { | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIndirectExpandSingeVsArrayResult(t *testing.T) { | ||||
| 	app, _ := tests.NewTestApp() | ||||
| 	defer app.Cleanup() | ||||
| 
 | ||||
| 	record, err := app.Dao().FindRecordById("demo3", "7nwo8tuiatetxdm") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	// non-unique indirect expand
 | ||||
| 	{ | ||||
| 		errs := app.Dao().ExpandRecord(record, []string{"demo4(rel_one_cascade)"}, func(c *models.Collection, ids []string) ([]*models.Record, error) { | ||||
| 			return app.Dao().FindRecordsByIds(c.Id, ids, nil) | ||||
| 		}) | ||||
| 		if len(errs) > 0 { | ||||
| 			t.Fatal(errs) | ||||
| 		} | ||||
| 
 | ||||
| 		result, ok := record.Expand()["demo4(rel_one_cascade)"].([]*models.Record) | ||||
| 		if !ok { | ||||
| 			t.Fatalf("Expected the expanded result to be a slice, got %v", result) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// mock a unique constraint for the rel_one_cascade field
 | ||||
| 	{ | ||||
| 		demo4, err := app.Dao().FindCollectionByNameOrId("demo4") | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 
 | ||||
| 		demo4.Indexes = append(demo4.Indexes, "create unique index idx_unique_expand on demo4 (rel_one_cascade)") | ||||
| 
 | ||||
| 		if err := app.Dao().SaveCollection(demo4); err != nil { | ||||
| 			t.Fatalf("Failed to mock unique constraint: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// non-unique indirect expand
 | ||||
| 	{ | ||||
| 		errs := app.Dao().ExpandRecord(record, []string{"demo4(rel_one_cascade)"}, func(c *models.Collection, ids []string) ([]*models.Record, error) { | ||||
| 			return app.Dao().FindRecordsByIds(c.Id, ids, nil) | ||||
| 		}) | ||||
| 		if len(errs) > 0 { | ||||
| 			t.Fatal(errs) | ||||
| 		} | ||||
| 
 | ||||
| 		result, ok := record.Expand()["demo4(rel_one_cascade)"].(*models.Record) | ||||
| 		if !ok { | ||||
| 			t.Fatalf("Expected the expanded result to be a single model, got %v", result) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue