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:
Steve Yegge
2025-12-24 13:22:55 -08:00
parent ce2b05356a
commit 1e7c7f5e54
6 changed files with 204 additions and 18 deletions

View File

@@ -2,6 +2,7 @@ package sqlite
import (
"context"
"database/sql"
"fmt"
"strings"
)
@@ -65,4 +66,36 @@ func (s *SQLiteStorage) GetNextChildID(ctx context.Context, parentID string) (st
return childID, nil
}
// ensureChildCounterUpdated ensures the child_counters table has a value for parentID
// that is at least childNum. This prevents ID collisions when children are created
// with explicit IDs (via --id flag or import) rather than GetNextChildID.
// (GH#728 fix)
func (s *SQLiteStorage) ensureChildCounterUpdated(ctx context.Context, parentID string, childNum int) error {
_, err := s.db.ExecContext(ctx, `
INSERT INTO child_counters (parent_id, last_child)
VALUES (?, ?)
ON CONFLICT(parent_id) DO UPDATE SET
last_child = MAX(last_child, excluded.last_child)
`, parentID, childNum)
if err != nil {
return fmt.Errorf("failed to update child counter for parent %s: %w", parentID, err)
}
return nil
}
// ensureChildCounterUpdatedWithConn is like ensureChildCounterUpdated but uses a specific
// connection for transaction consistency. (GH#728 fix)
func ensureChildCounterUpdatedWithConn(ctx context.Context, conn *sql.Conn, parentID string, childNum int) error {
_, err := conn.ExecContext(ctx, `
INSERT INTO child_counters (parent_id, last_child)
VALUES (?, ?)
ON CONFLICT(parent_id) DO UPDATE SET
last_child = MAX(last_child, excluded.last_child)
`, parentID, childNum)
if err != nil {
return fmt.Errorf("failed to update child counter for parent %s: %w", parentID, err)
}
return nil
}
// generateHashID moved to ids.go (bd-0702)