fix(sqlite): update child_counters when explicit child IDs are created (GH#728)
When creating issues with explicit hierarchical IDs (e.g., bd-test.1, bd-test.2 via --id flag or import), the child_counters table was not being updated. This caused GetNextChildID to return colliding IDs when later called with --parent. Changes: - Add ensureChildCounterUpdatedWithConn() to update counter on explicit child creation - Add ParseHierarchicalID() to extract parent and child number from IDs - Update CreateIssue to call counter update after hierarchical ID validation - Update EnsureIDs to call counter update when parent exists - Add post-insert phase in batch operations to update counters after FK constraint can be satisfied - Update tests to reflect new behavior where counter is properly initialized 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,33 @@ func IsHierarchicalID(id string) (isHierarchical bool, parentID string) {
|
||||
return true, id[:lastDot]
|
||||
}
|
||||
|
||||
// ParseHierarchicalID extracts the parent ID and child number from a hierarchical ID.
|
||||
// Returns (parentID, childNum, true) for hierarchical IDs like "bd-abc.1" -> ("bd-abc", 1, true).
|
||||
// Returns ("", 0, false) for non-hierarchical IDs.
|
||||
// (GH#728 fix)
|
||||
func ParseHierarchicalID(id string) (parentID string, childNum int, ok bool) {
|
||||
lastDot := strings.LastIndex(id, ".")
|
||||
if lastDot == -1 {
|
||||
return "", 0, false
|
||||
}
|
||||
|
||||
suffix := id[lastDot+1:]
|
||||
if len(suffix) == 0 {
|
||||
return "", 0, false
|
||||
}
|
||||
|
||||
// Parse the numeric suffix
|
||||
num := 0
|
||||
for _, c := range suffix {
|
||||
if c < '0' || c > '9' {
|
||||
return "", 0, false
|
||||
}
|
||||
num = num*10 + int(c-'0')
|
||||
}
|
||||
|
||||
return id[:lastDot], num, true
|
||||
}
|
||||
|
||||
// ValidateIssueIDPrefix validates that an issue ID matches the configured prefix
|
||||
// Supports both top-level (bd-a3f8e9) and hierarchical (bd-a3f8e9.1) IDs
|
||||
func ValidateIssueIDPrefix(id, prefix string) error {
|
||||
@@ -235,6 +262,18 @@ func EnsureIDs(ctx context.Context, conn *sql.Conn, prefix string, issues []*typ
|
||||
// Default to allow for backward compatibility
|
||||
}
|
||||
}
|
||||
|
||||
// Update child_counters to prevent future ID collisions (GH#728 fix)
|
||||
// When explicit child IDs are imported, the counter must be at least the child number
|
||||
// Only update if parent exists (parentCount > 0) - for orphan modes, skip this
|
||||
// The counter will be updated when the parent is actually created/exists
|
||||
if parentCount > 0 {
|
||||
if _, childNum, ok := ParseHierarchicalID(issues[i].ID); ok {
|
||||
if err := ensureChildCounterUpdatedWithConn(ctx, conn, parentID, childNum); err != nil {
|
||||
return fmt.Errorf("failed to update child counter: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usedIDs[issues[i].ID] = true
|
||||
|
||||
Reference in New Issue
Block a user