From 56e8c439992aead39e920cf88ff47e3d62aa1a48 Mon Sep 17 00:00:00 2001 From: almac2022 Date: Sun, 5 Apr 2026 08:53:05 -0700 Subject: [PATCH] Add id_segment for unique sub-segment identity after breaking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .frs_add_id_segment() initializes id_segment from linear_feature_id. When frs_break_apply(segment_id = "id_segment") splits segments, sub-segments get new unique id_segment values while linear_feature_id is carried from the parent (FWA provenance preserved). Tested: 510 segments → 532 after breaking. All id_segment unique. Sub-segments share parent linear_feature_id correctly (e.g. one parent split into 7 sub-segments). Also adds naming conventions to CLAUDE.md (id_* prefix, col_* params, frs_noun_verb functions, long-format habitat table structure). Fixes #82 Relates to #83 Co-Authored-By: Claude Opus 4.6 (1M context) --- R/frs_break.R | 8 ++++---- R/utils.R | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/R/frs_break.R b/R/frs_break.R index a68d3c9..766d448 100644 --- a/R/frs_break.R +++ b/R/frs_break.R @@ -582,20 +582,20 @@ frs_break_apply <- function(conn, table, breaks, # Get writable columns only (excludes GENERATED ALWAYS columns) cols_writable <- .frs_table_columns(conn, table, exclude_generated = TRUE) - # Split columns: these come from the temp table, not the parent + # Split columns: segment_id, measures, and geom come from the split cols_split_all <- c(sid, "downstream_route_measure", "upstream_route_measure", "geom") - # Only include split columns that are actually writable cols_split <- intersect(cols_split_all, cols_writable) # Carry columns: everything writable that isn't a split column + # This preserves linear_feature_id (FWA provenance) from parent cols_carry <- setdiff(cols_writable, cols_split_all) # Build INSERT column list and SELECT expressions cols_insert_parts <- character(0) select_parts <- character(0) - # segment_id — new ID from max + row_number + # segment_id — new unique ID from max + row_number if (sid %in% cols_split) { cols_insert_parts <- c(cols_insert_parts, sid) select_parts <- c(select_parts, sprintf( @@ -604,7 +604,7 @@ frs_break_apply <- function(conn, table, breaks, )", sid, table)) } - # Carried columns from parent + # Carried columns from parent (includes linear_feature_id for provenance) if (length(cols_carry) > 0) { cols_insert_parts <- c(cols_insert_parts, cols_carry) select_parts <- c(select_parts, paste0("s.", cols_carry)) diff --git a/R/utils.R b/R/utils.R index da2354d..af2734a 100644 --- a/R/utils.R +++ b/R/utils.R @@ -60,6 +60,26 @@ } +#' Add id_segment column to a working table +#' +#' Assigns a unique integer ID to every row. Uses `linear_feature_id` +#' as the starting value (so original FWA segments keep their ID), +#' then generates new IDs for any rows added later by +#' [frs_break_apply()]. +#' +#' @param conn DBI connection. +#' @param table Schema-qualified table name. +#' @noRd +.frs_add_id_segment <- function(conn, table) { + if (!inherits(conn, "DBIConnection")) return(invisible(NULL)) + .frs_db_execute(conn, sprintf( + "ALTER TABLE %s ADD COLUMN IF NOT EXISTS id_segment integer", table)) + .frs_db_execute(conn, sprintf( + "UPDATE %s SET id_segment = linear_feature_id + WHERE id_segment IS NULL", table)) +} + + #' Add indexes to a working table based on available columns #' #' Checks which index-worthy columns exist and creates appropriate indexes.