package require struct::graph 2 # Resolving reference dependecies for tcldb tables # # Create a dependency graph first, # then walk from leaves to the root # proc createGraph {tableObjs} { set g [::struct::graph ] foreach table $tableObjs { set tablename [$table cget -table] set fields [$table fieldlist 0 1 1] $g set $tablename $table if {![$g node exists $tablename]} { $g node insert $tablename } puts "Table: $tablename" foreach {field type param} $fields { puts "$field" puts "$type" puts $param array unset finfo set finfo(reference) "" $g node set $tablename $field [list $type $param] array set finfo $param if {$finfo(reference) eq ""} {continue} set reftable [lindex $finfo(reference) 0] if {![$g node exists $reftable]} { $g node insert $reftable } $g arc insert $tablename $reftable } } return $g } proc filterIsolated {g n} { if {[llength [$g arcs -out $n]]} { return 0 } else { return 1 } } proc findOrder {graph} { set g [::struct::graph tempGraph = $graph] set order [list] set old [llength [$g nodes]] while {[llength [$g nodes]]} { set isolated [$g nodes -filter [namespace current]::filterIsolated] if {[llength $isolated]} { foreach node $isolated { lappend order [list $node [$g set $node]] $g node delete $node } } else { break } } if {[llength [$g nodes]]} { return -code error "Could not resolve reference conflicts, objects left [$g nodes]" } $g destroy return $order }To use it, put all your tcldb::table objects into a list, then call:
set g [createGraph $tablelist] puts [findOrder $g]This returns the creation order for your table as a list of lists, each sublist is a tablename tableobject pair.
escargo 16 Dec 2005 - In terms of dependencies, would determining the order via a topological sort work as well? Can the dependency graph be relied upon to have no cycles?
schlenk 16 Dec 2005 - I think a topological sort would work as well. If the dependency graph for this use case (sql table relations) would have cycles, this would be a clear indication that some database normalization could be a good idea.