db_multirow_helper (private)
db_multirow_helper
Defined in packages/acs-tcl/tcl/01-database-procs.tcl
Helper function for db_multirow, performing the actual DB queries.
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- No testcase defined.
Source code: uplevel 1 { if { !$append_p || ![info exists counter]} { set counter 0 } set local_counter -1 # # Make sure 'next_row' dict doesn't exist. # # The variables 'this_row' and 'next_row' are used to always # execute the code block one result set row behind, so that we # have the opportunity to peek ahead, which allows us to do # group by's inside the multirow generation. # # Also make the 'next_row' dict available as a magic __db_multirow__next_row variable # upvar 1 __db_multirow__next_row next_row unset -nocomplain next_row # # Execute the query in one sweep, similar to 'db_foreach'. # upvar 1 __db_multirow__local_columns local_columns set __selections [uplevel 1 [list db_list_of_lists -dbn $dbn -subst $subst -columns_var __db_multirow__local_columns $full_statement_name $sql]] lappend local_columns {*}$extend if { !$append_p || ![info exists columns] } { # store the list of columns in the var_name:columns variable set columns $local_columns } else { # Check that the columns match, if not throw an error if { [join [lsort -ascii $local_columns]] ne [join [lsort -ascii $columns]] } { error "Appending to a multirow with differing columns. Original columns : [join [lsort -ascii $columns] ", "]. Columns in this query: [join [lsort -ascii $local_columns] ", "]" "" "ACS_MULTIROW_APPEND_COLUMNS_MISMATCH" } } if {[llength $__selections] == 0} { return } set more_rows_p 1 while { 1 } { incr local_counter if { $more_rows_p } { set more_rows_p [expr {$local_counter < [llength $__selections]}] set selection [lindex $__selections $local_counter] } else { break } #ns_log notice "$local_counter: $selection" # # Setup the 'columns' part, now that we know the columns # in the result set in the first iteration (when # $local_counter == 0). # if { $local_counter == 0 } { # In case the '-unclobber' switch is specified, save # variables which we might clobber. # if { $unclobber_p && $code_block ne "" } { foreach col $columns { upvar 1 $col column_value __saved_$col column_save if { [info exists column_value] } { if { [array exists column_value] } { array set column_save [array get column_value] } else { set column_save $column_value } # Clear the variable unset column_value } } } } if { $code_block eq "" } { # # There is no code block - pull values directly into # the var_name array. # # The extra loop after the last row is only for when # there's a code block. # if { !$more_rows_p } { break } incr counter upvar $level_up "$var_name:$counter" array_val set array_val(rownum) $counter array set array_val [join [lmap __column $local_columns __value $selection { list $__column $__value }]] } else { # # There is a code block to execute. # Copy next_row to this_row, if it exists # unset -nocomplain this_row if {[info exists next_row]} { set this_row $next_row } # Pull values from the query into next_row unset -nocomplain next_row if { $more_rows_p } { set next_row $selection } # Process the row if { [info exists this_row] } { # Pull values from this_row into local variables foreach name $local_columns __value $this_row { upvar 1 $name column_value set column_value $__value # ns_log notice "... [list set $name $__value]" } # Initialize the "extend" columns to the empty string foreach column_name $extend { upvar 1 $column_name column_value set column_value "" } # Execute the code block set errno [catch { uplevel 1 $code_block } error] #ns_log notice ".... code block returns errno $errno" # Handle or propagate the error. Can't use the usual # "return -code $errno..." trick due to the db_with_handle # wrapped around this loop, so propagate it explicitly. # switch -- $errno { 0 { # TCL_OK } 1 { # TCL_ERROR error $error $::errorInfo $::errorCode } 2 { # TCL_RETURN error "Cannot return from inside a db_multirow loop" } 3 { # TCL_BREAK #### CHECK? #ns_db flush $db break } 4 { # TCL_CONTINUE continue } default { error "Unknown return code: $errno" } } # Pull the local variables back out and into the array. incr counter upvar $level_up "$var_name:$counter" array_val set array_val(rownum) $counter foreach column_name $columns { upvar 1 $column_name column_value set array_val($column_name) $column_value } } } } # Restore values of columns which we've saved if { $unclobber_p && $code_block ne "" && $local_counter > 0 } { foreach col $columns { upvar 1 $col column_value __saved_$col column_save # Unset it first, so the road's paved to restoring unset -nocomplain column_value # Restore it if { [info exists column_save] } { if { [array exists column_save] } { array set column_value [array get column_save] } else { set column_value $column_save } # And then remove the saved col unset column_save } } } # Unset the next_row variable, just in case unset -nocomplain next_row }XQL Not present: Generic, PostgreSQL, Oracle