Index: openacs-4/packages/acs-bootstrap-installer/tcl/40-db-query-dispatcher-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-bootstrap-installer/tcl/40-db-query-dispatcher-procs.tcl,v diff -u -N -r1.49.2.7 -r1.49.2.8 --- openacs-4/packages/acs-bootstrap-installer/tcl/40-db-query-dispatcher-procs.tcl 22 Feb 2021 16:56:53 -0000 1.49.2.7 +++ openacs-4/packages/acs-bootstrap-installer/tcl/40-db-query-dispatcher-procs.tcl 22 Feb 2021 17:13:38 -0000 1.49.2.8 @@ -22,7 +22,7 @@ @author Ben Adida (ben@openforce.net) @author Bart Teeuwisse (bart.teeuwisse@thecodemill.biz) - @cvs-id $Id$ + @cvs-id $Id$ } } @@ -82,31 +82,33 @@ ad_proc -public db_rdbms_compatible_p {rdbms_test rdbms_pattern} { @return 0 if test incompatible with pattern, 1 if miscible } { - # db_qd_log QDDebug "The RDBMS_TEST is [db_rdbms_get_type $rdbms_test] - [db_rdbms_get_version $rdbms_test]" - # db_qd_log QDDebug "The RDBMS_PATTERN is [db_rdbms_get_type $rdbms_pattern] - [db_rdbms_get_version $rdbms_pattern]" + #db_qd_log QDDebug "The RDBMS_TEST is [db_rdbms_get_type $rdbms_test] - " \ + # [db_rdbms_get_version $rdbms_test] + #db_qd_log QDDebug "The RDBMS_PATTERN is [db_rdbms_get_type $rdbms_pattern] - " \ + # [db_rdbms_get_version $rdbms_pattern] # If the pattern is for all RDBMS, then yeah, compatible if {[db_rdbms_get_type $rdbms_test] eq ""} { - return 1 + return 1 } # If the RDBMS types are not the same, we have a problem if {[db_rdbms_get_type $rdbms_test] != [db_rdbms_get_type $rdbms_pattern]} { - # db_qd_log QDDebug "compatibility - RDBMS types are different!" - return 0 + # db_qd_log QDDebug "compatibility - RDBMS types are different!" + return 0 } # If the pattern has no version if {[db_rdbms_get_version $rdbms_pattern] eq ""} { - return 1 + return 1 } # If the query being tested was written for a version that is older than # the current RDBMS then we have compatibility. Otherwise we don't. foreach t [split [db_rdbms_get_version $rdbms_test ] "\."] \ - p [split [db_rdbms_get_version $rdbms_pattern] "\."] { - if {$t != $p} {return [expr {$t < $p}]} - } + p [split [db_rdbms_get_version $rdbms_pattern] "\."] { + if {$t != $p} {return [expr {$t < $p}]} + } # Same version (though not strictly "older") is OK return 1 @@ -195,17 +197,17 @@ # Otherwise this is a stupid exercise if {[db_rdbms_get_version $rdbms_1] eq ""} { - return $query_2 + return $query_2 } if {[db_rdbms_get_version $rdbms_2] eq ""} { - return $query_1 + return $query_1 } if {[db_rdbms_get_version $rdbms_1] > [db_rdbms_get_version $rdbms_2]} { - return $query_1 + return $query_1 } else { - return $query_2 + return $query_2 } } @@ -222,17 +224,17 @@ to load a particular file } { if {$errorVarName ne ""} { - upvar $errorVarName errors + upvar $errorVarName errors } else { - array set errors [list] + array set errors [list] } if { [catch {db_qd_internal_load_cache $file_path} errMsg] } { set backTrace $::errorInfo ns_log Error "Error parsing queryfile $file_path:\n\n$errMsg\n\n$backTrace" - set r_file [ad_make_relative_path $file_path] - set package_key "" - regexp {/packages/([^/]+)/} $file_path -> package_key - lappend errors($package_key) $r_file $backTrace + set r_file [ad_make_relative_path $file_path] + set package_key "" + regexp {/packages/([^/]+)/} $file_path -> package_key + lappend errors($package_key) $r_file $backTrace } } @@ -251,43 +253,49 @@ # Since the DB procs are a bit incestuous, this might get # called more than once. DAMMIT! (ben) if {![db_qd_relative_path_p $local_name]} { - return $local_name + return $local_name } # Get the proc name being executed. # We catch this in case we're being called from the top level # (e.g. from bootstrap.tcl), in which case we return what we # were given if { [catch {string trimleft [info level [expr {-1 - $added_stack_num}]] ::} proc_name] } { - return [::nsf::strip_proc_name $local_name] + return [::nsf::strip_proc_name $local_name] } # If util_memoize, we have to go back up one in the stack if {[lindex $proc_name 0] eq "util_memoize"} { - # db_qd_log QDDebug "util_memoize! going up one level" - set proc_name [info level [expr {-2 - $added_stack_num}]] + # db_qd_log QDDebug "util_memoize! going up one level" + set proc_name [info level [expr {-2 - $added_stack_num}]] } set proc_name [::nsf::strip_proc_name $proc_name] - set list_of_source_procs {ns_sourceproc apm_source template::adp_parse template::frm_page_handler rp_handle_tcl_request} + set list_of_source_procs { + ns_sourceproc + apm_source + template::adp_parse + template::frm_page_handler + rp_handle_tcl_request + } # We check if we're running the special ns_ proc that tells us # whether this is a URL or a Tcl proc. if { [lindex $proc_name 0] in $list_of_source_procs } { - # Means we are running inside a URL + # Means we are running inside a URL - # TEST - # for {set i 0} {$i < 6} {incr i} { + # TEST + # for {set i 0} {$i < 6} {incr i} { # if {[catch {db_qd_log QDDebug "LEVEL=$i= [info level [expr {-1 - $i}]]"} errmsg]} {} # } - # Check the ad_conn stuff - # if {[ns_conn isconnected]} { + # Check the ad_conn stuff + # if {[ns_conn isconnected]} { # if {[catch {db_qd_log QDDebug "the ad_conn file is [ad_conn file]"} errmsg]} {} # } - # Now we do a check to see if this is a directly accessed URL or a + # Now we do a check to see if this is a directly accessed URL or a # sourced URL # added case for handling .vuh files which are sourced from @@ -326,32 +334,32 @@ } } - # Get the URL and remove the .tcl - regsub {^/} $url {} url - regsub {\.tcl$} $url {} url - regsub {\.vuh$} $url {} url + # Get the URL and remove the .tcl + regsub {^/} $url {} url + regsub {\.tcl$} $url {} url + regsub {\.vuh$} $url {} url - # Change all dots to colons, and slashes to dots - regsub -all {\.} $url {:} url - regsub -all {/} $url {.} url + # Change all dots to colons, and slashes to dots + regsub -all {\.} $url {:} url + regsub -all {/} $url {.} url - # We insert the "www" after the package key + # We insert the "www" after the package key set rest {} - regexp {^([^\.]*)(.*)} $url all package_key rest + regexp {^([^\.]*)(.*)} $url all package_key rest - # db_qd_log QDDebug "package key is $package_key and rest is $rest" + # db_qd_log QDDebug "package key is $package_key and rest is $rest" - if {$real_url_p} { - set full_name [db_qd_make_absolute_path "${package_key}.www${rest}." $local_name] - # set full_name "acs.${package_key}.www${rest}.${local_name}" - } else { - set full_name [db_qd_make_absolute_path "${package_key}${rest}." $local_name] - # set full_name "acs.${package_key}${rest}.${local_name}" - } + if {$real_url_p} { + set full_name [db_qd_make_absolute_path "${package_key}.www${rest}." $local_name] + # set full_name "acs.${package_key}.www${rest}.${local_name}" + } else { + set full_name [db_qd_make_absolute_path "${package_key}${rest}." $local_name] + # set full_name "acs.${package_key}${rest}.${local_name}" + } } else { - # Let's find out where this Tcl proc is defined!! - # Get the first word, which is the Tcl proc - regexp {^([^ ]*).*} $proc_name all proc_name + # Let's find out where this Tcl proc is defined!! + # Get the first word, which is the Tcl proc + regexp {^([^ ]*).*} $proc_name all proc_name # check to see if a package proc is being called without # namespace qualification. If so, add the package qualification to the @@ -365,40 +373,43 @@ ![string match "*::*" $proc_name]} { set proc_name ${calling_namespace}::${proc_name} } - # db_qd_log QDDebug "proc_name is -$proc_name-" + # db_qd_log QDDebug "proc_name is -$proc_name-" - # We use the ad_proc construct!! - # (woohoo, can't believe that was actually useful!) + # We use the ad_proc construct!! + # (woohoo, can't believe that was actually useful!) - # First we check if the proc is there. If not, then we're - # probably dealing with one of the bootstrap procs, and so we just - # return a bogus proc name - if {![nsv_exists api_proc_doc $proc_name]} { - ns_log warning "db_qd_get_fullname: there is no documented proc with name $proc_name returning [db_qd_null_path] (declare proc $proc_name with ad_proc to make it work with the query dispatcher" - return [db_qd_null_path] - } + # First we check if the proc is there. If not, then we're + # probably dealing with one of the bootstrap procs, and so we just + # return a bogus proc name + if {![nsv_exists api_proc_doc $proc_name]} { + ns_log warning "db_qd_get_fullname: there is no documented proc " \ + "with name $proc_name returning [db_qd_null_path] " \ + "(declare proc $proc_name with ad_proc to make it " \ + "work with the query dispatcher" + return [db_qd_null_path] + } - array set doc_elements [nsv_get api_proc_doc $proc_name] - set url $doc_elements(script) + array set doc_elements [nsv_get api_proc_doc $proc_name] + set url $doc_elements(script) - # db_qd_log QDDebug "tcl file is $url" + # db_qd_log QDDebug "tcl file is $url" - regsub {.tcl$} $url {} url + regsub {.tcl$} $url {} url - # Change all dots to colons, and slashes to dots - regsub -all {\.} $url {:} url - regsub -all {/} $url {.} url + # Change all dots to colons, and slashes to dots + regsub -all {\.} $url {:} url + regsub -all {/} $url {.} url - # We get something like packages.acs-tcl.tcl.acs-kernel-procs - # We need to remove packages. + # We get something like packages.acs-tcl.tcl.acs-kernel-procs + # We need to remove packages. set rest {} - regexp {^packages\.(.*)} $url all rest + regexp {^packages\.(.*)} $url all rest - # db_qd_log QDDebug "TEMP - QD: proc_name is $proc_name" - # db_qd_log QDDebug "TEMP - QD: local_name is $local_name" + # db_qd_log QDDebug "TEMP - QD: proc_name is $proc_name" + # db_qd_log QDDebug "TEMP - QD: local_name is $local_name" - # set full_name "acs.$rest.${proc_name}.${local_name}" - set full_name [db_qd_make_absolute_path "${rest}.${proc_name}." $local_name] + # set full_name "acs.$rest.${proc_name}.${local_name}" + set full_name [db_qd_make_absolute_path "${rest}.${proc_name}." $local_name] } # db_qd_log QDDebug "generated fullname of $full_name" @@ -438,9 +449,9 @@ set fullquery [db_qd_fetch $statement_name] if {$fullquery ne ""} { - set sql [db_fullquery_get_querytext $fullquery] + set sql [db_fullquery_get_querytext $fullquery] } else { - db_qd_log Debug "NO FULLQUERY FOR $statement_name --> using default SQL" + db_qd_log Debug "NO FULLQUERY FOR $statement_name --> using default SQL" if { $sql eq "" } { # The default SQL is empty, that implies a bug somewhere in the code. error "No fullquery for $statement_name and default SQL empty - query for statement missing" @@ -518,45 +529,48 @@ set acs_file_path [ad_make_relative_path $file_tag] set queryname_root [db_qd_internal_get_queryname_root $acs_file_path] - # db_qd_log QDDebug "db_qd_internal_load_queries: \n file: [lindex $parsing_state 4] \n default_rdbms: [lindex $parsing_state 3] \n queryname_root: $queryname_root" + #db_qd_log QDDebug "db_qd_internal_load_queries: \n" \ + # "file: [lindex $parsing_state 4] \n" \ + # "default_rdbms: [lindex $parsing_state 3] \n" \ + # "queryname_root: $queryname_root" while {1} { - set result [db_qd_internal_parse_one_query $parsing_state] + set result [db_qd_internal_parse_one_query $parsing_state] - # db_qd_log QDDebug "one parse result -$result-" + # db_qd_log QDDebug "one parse result -$result-" - # If we get the empty string, we are done parsing - if {$result eq ""} { - break - } + # If we get the empty string, we are done parsing + if {$result eq ""} { + break + } lassign $result one_query parsing_state - # db_qd_log QDDebug "loaded one query - [db_fullquery_get_name $one_query]" + # db_qd_log QDDebug "loaded one query - [db_fullquery_get_name $one_query]" - # Relative Path for the Query - if {[db_qd_relative_path_p [db_fullquery_get_name $one_query]]} { - set new_name [db_qd_make_absolute_path $queryname_root [db_fullquery_get_name $one_query]] + # Relative Path for the Query + if {[db_qd_relative_path_p [db_fullquery_get_name $one_query]]} { + set new_name [db_qd_make_absolute_path $queryname_root [db_fullquery_get_name $one_query]] - set new_fullquery [db_fullquery_create \ - $new_name \ - [db_fullquery_get_querytext $one_query] \ - [db_fullquery_get_bind_vars $one_query] \ - [db_fullquery_get_query_type $one_query] \ - [db_fullquery_get_rdbms $one_query] \ - [db_fullquery_get_load_location $one_query]] + set new_fullquery [db_fullquery_create \ + $new_name \ + [db_fullquery_get_querytext $one_query] \ + [db_fullquery_get_bind_vars $one_query] \ + [db_fullquery_get_query_type $one_query] \ + [db_fullquery_get_rdbms $one_query] \ + [db_fullquery_get_load_location $one_query]] - set one_query $new_fullquery + set one_query $new_fullquery - # db_qd_log QDDebug "relative path, replaced name with $new_name" - } + # db_qd_log QDDebug "relative path, replaced name with $new_name" + } - # Store the query - db_qd_internal_store_cache $one_query + # Store the query + db_qd_internal_store_cache $one_query } set relative_path [string range $file_tag \ - [expr { [string length $::acs::rootdir] + 1 }] end] + [expr { [string length $::acs::rootdir] + 1 }] end] nsv_set apm_library_mtime $relative_path [file mtime $file_tag] } @@ -567,15 +581,15 @@ } { # If we have no record if {![nsv_exists OACS_FULLQUERIES $fullquery_name]} { - return "" + return "" } set fullquery_array [nsv_get OACS_FULLQUERIES $fullquery_name] # If this isn't cached! if {$fullquery_array eq ""} { - # we need to do something - return "" + # we need to do something + return "" } # See if we have the correct location for this query @@ -596,7 +610,8 @@ set rdbms [db_fullquery_get_rdbms $fullquery] if {![db_rdbms_compatible_p $rdbms [db_current_rdbms]]} { # The query isn't compatible, probably because of a too high version - ns_log Warning "Query [db_fullquery_get_name $fullquery] has rdbms info $rdbms which is not compatible with system rdbms [db_current_rdbms]" + ns_log Warning "Query [db_fullquery_get_name $fullquery] has rdbms info $rdbms" \ + "which is not compatible with system rdbms [db_current_rdbms]" return } @@ -607,9 +622,9 @@ # If we already have a query for that name, we need to # figure out which one is *most* compatible. if {[nsv_exists OACS_FULLQUERIES $name]} { - set old_fullquery [nsv_get OACS_FULLQUERIES $name] + set old_fullquery [nsv_get OACS_FULLQUERIES $name] - set fullquery [db_qd_pick_most_specific_query [db_current_rdbms] $old_fullquery $fullquery] + set fullquery [db_qd_pick_most_specific_query [db_current_rdbms] $old_fullquery $fullquery] } nsv_set OACS_FULLQUERIES $name $fullquery @@ -680,21 +695,22 @@ # Check if the node is a queryset if {[xml_node_get_name $root_node] ne "queryset"} { - # db_qd_log Error "OH OH, error, first node is [xml_node_get_name $root_node] and not 'queryset'" + # db_qd_log Error "OH OH, error, first node is [xml_node_get_name $root_node] and not 'queryset'" return "" } # Extract the default RDBMS if there is one set rdbms_nodes [xml_node_get_children_by_name $root_node rdbms] if {[llength $rdbms_nodes] > 0} { - set default_rdbms [db_rdbms_parse_from_xml_node [lindex $rdbms_nodes 0]] - # db_qd_log QDDebug "Detected DEFAULT RDBMS for whole queryset: $default_rdbms" + set default_rdbms [db_rdbms_parse_from_xml_node [lindex $rdbms_nodes 0]] + # db_qd_log QDDebug "Detected DEFAULT RDBMS for whole queryset: $default_rdbms" } else { - set default_rdbms "" + set default_rdbms "" } set parsed_stuff [xml_node_get_children_by_name $root_node fullquery] - # db_qd_log QDDebug "db_qd_internal_parse_init extra info : index: $index; parsed_stuff: $parsed_stuff; parsed_doc: $parsed_doc;" + #db_qd_log QDDebug "db_qd_internal_parse_init extra info: " \ + # "index: $index; parsed_stuff: $parsed_stuff; parsed_doc: $parsed_doc;" return [list $index $parsed_stuff $parsed_doc $default_rdbms $file_path] } @@ -708,13 +724,13 @@ # BASE CASE if {[llength $node_list] <= $index} { - # Clean up - xml_doc_free $parsed_doc + # Clean up + xml_doc_free $parsed_doc - # db_qd_log QDDebug "Cleaning up, done parsing" + # db_qd_log QDDebug "Cleaning up, done parsing" - # return nothing - return "" + # return nothing + return "" } # Get one query @@ -736,14 +752,18 @@ } -ad_proc -private db_qd_internal_parse_one_query_from_xml_node {one_query_node {default_rdbms {}} {file_path {}}} { +ad_proc -private db_qd_internal_parse_one_query_from_xml_node { + one_query_node + {default_rdbms {}} + {file_path {}} +} { Parse one query from an XML node } { # db_qd_log QDDebug "parsing one query node in XML with name -[xml_node_get_name $one_query_node]-" # Check that this is a fullquery if {[xml_node_get_name $one_query_node] ne "fullquery"} { - return "" + return "" } set queryname [xml_node_get_attribute $one_query_node name] @@ -756,11 +776,11 @@ # If we have no RDBMS specified, use the default if {[llength $rdbms_nodes] == 0} { - # db_qd_log QDDebug "Wow, Nelly, no RDBMS for this query, using default rdbms $default_rdbms" - set rdbms $default_rdbms + # db_qd_log QDDebug "Wow, Nelly, no RDBMS for this query, using default rdbms $default_rdbms" + set rdbms $default_rdbms } else { - set rdbms_node [lindex $rdbms_nodes 0] - set rdbms [db_rdbms_parse_from_xml_node $rdbms_node] + set rdbms_node [lindex $rdbms_nodes 0] + set rdbms [db_rdbms_parse_from_xml_node $rdbms_node] } return [db_fullquery_create $queryname $querytext [list] "" $rdbms $file_path] @@ -773,8 +793,8 @@ # Check if the DOM node refers to a RDBMS. # if {[xml_node_get_name $rdbms_node] ne "rdbms"} { - db_qd_log Debug "db_rdbms_parse_from_xml_node: PARSER = BAD RDBMS NODE!" - return {} + db_qd_log Debug "db_rdbms_parse_from_xml_node: PARSER = BAD RDBMS NODE!" + return {} } # Get the type and version tags @@ -811,9 +831,9 @@ # Check if the path starts with the root if {[string range $path 0 $root_path_length-1] eq $root_path} { - return 0 + return 0 } else { - return 1 + return 1 } } @@ -825,7 +845,7 @@ } -ad_proc -public db_qd_prepare_queryfile_content {file_content} { +ad_proc -public db_qd_prepare_queryfile_content {file_content} { Prepare raw .xql-file content form xml-parsing via quoting. The result is parsable XML, where "partialquery" is replaced by "fullquery". @@ -849,26 +869,32 @@ # We're going to ns_quotehtml the querytext, # because XML parsing might choke otherwise while {1} { - set first_querytext_open [string first $querytext_open $rest_of_file_content] - set first_querytext_close [string first $querytext_close $rest_of_file_content] + set first_querytext_open [string first $querytext_open $rest_of_file_content] + set first_querytext_close [string first $querytext_close $rest_of_file_content] - # We have no more querytext to process - if {$first_querytext_open == -1} { - append new_file_content $rest_of_file_content - break - } + # We have no more querytext to process + if {$first_querytext_open == -1} { + append new_file_content $rest_of_file_content + break + } - # append first chunk before the querytext including "" - append new_file_content [string range $rest_of_file_content 0 [expr {$first_querytext_open + $querytext_open_len - 1}]] + # append first chunk before the querytext including "" + append new_file_content [string range $rest_of_file_content \ + 0 \ + [expr {$first_querytext_open + $querytext_open_len - 1}]] - # append quoted querytext - append new_file_content [ns_quotehtml [string range $rest_of_file_content $first_querytext_open+$querytext_open_len $first_querytext_close-1]] + # append quoted querytext + append new_file_content [ns_quotehtml [string range $rest_of_file_content \ + $first_querytext_open+$querytext_open_len \ + $first_querytext_close-1]] - # append close querytext - append new_file_content $querytext_close + # append close querytext + append new_file_content $querytext_close - # Set up the rest - set rest_of_file_content [string range $rest_of_file_content $first_querytext_close+$querytext_close_len end] + # Set up the rest + set rest_of_file_content [string range $rest_of_file_content \ + $first_querytext_close+$querytext_close_len \ + end] } # db_qd_log QDDebug "new massaged file content: \n $new_file_content \n" @@ -881,12 +907,12 @@ ## Logging ## -ad_proc -private db_qd_log {level msg} { +ad_proc -private db_qd_log {level args} { Centralized DB QD logging If you want to debug the QD, change QDDebug below to Debug } { if {"QDDebug" ne $level } { - ns_log $level "$msg" + ns_log $level [join $args " "] } }