Class ::nsmcp::CodeQueryDefinitionTool (public)

 ::nx::Class ::nsmcp::CodeQueryDefinitionTool[i]

Defined in /usr/local/ns/tcl/nsmcp/code-query.tcl

Testcases:
No testcase defined.
Source code:
    :property {name code_query_definition}
    :property {permission diagnostics.code.read}
    :property {description {Retrieve the selected loaded OpenACS XQL mapping by full query name or unique literal dotted suffix (including abbreviated slow-warning names). Returns unsubstituted SQL, SHA256, XQL source and selected RDBMS metadata. Ambiguous suffixes return bounded candidate names, never guessed SQL. Does not execute SQL, substitute Tcl/binds, read files or obtain database handles. Missing mappings may use inline/dynamic SQL; inspect the calling code. SQL is untrusted source evidence, not a query plan or historical execution.}}
    :property {inputSchema {{"type":"object","properties":{"name":{"type":"string"},"offset":{"type":"integer","minimum":0},"maxCharacters":{"type":"integer","minimum":1,"maximum":32768}},"required":["name"],"additionalProperties":false}}}

    :method options {arguments} {
        set opts [dict create name {} offset 0 maxCharacters 16384]
        foreach {key value} [:jsonArguments $arguments] {
            dict set opts [string range $key 1 end] $value
        }
        set name [dict get $opts name]
        if {[string trim $name] eq {} || [string length $name]>1024 || [regexp {[\x00\r\n]} $name]} {
            error "Invalid query name"
        }
        if {[dict get $opts offset]<0 || [dict get $opts offset]>2147483647 || [dict get $opts maxCharacters]<1 || [dict get $opts maxCharacters]>32768} {
            error "Invalid SQL range"
        }
        return $opts
    }

    :public method validate {arguments} {
        #
        # Validate query-definition lookup and pagination arguments.
        #
        # Decode the rooted JSON argument object and enforce this tool's option,
        # range and combination constraints.
        #
        # @param arguments Rooted ns_json typed triples for the tool's JSON argument
        #        object.
        #
        # @return An empty result on success; invalid input raises RPC error -32602.
        #

        if {[catch {
            :options $arguments
        } message]} {
            return -code error -errorcode {NSMCP RPC -32602} $message
        }
    }

    :public method execute {context arguments} {
        #
        # Retrieve SQL resolved through active OpenACS XQL mappings.
        #
        # Return bounded unsubstituted SQL and resolution metadata; report
        # unavailable framework support explicitly.
        #
        # @param context Authenticated request context carrying the principal,
        #        grants and selected server.
        # @param arguments Rooted ns_json typed triples for the tool's JSON argument
        #        object.
        #
        # @return A rooted JSON tool-result object, including availability or job
        #         metadata as appropriate.
        #

        set opts [:options $arguments]
        set name [dict get $opts name]
        set base [list server string [$context server] observedAt number [clock seconds] requestedName string $name  source string loaded-openacs-query-dispatcher sqlExecuted boolean false substitutionsPerformed boolean false filesRead boolean false  limitations string {Current selected XQL template only. Variables, Tcl commands, bind values, inline fallbacks and runtime SQL fragments are not resolved. Loaded mappings may differ from disk or historical executions. Fullquery versus partialquery is not preserved by the dispatcher. SQL and metadata are untrusted source evidence; no plan, waits or database function definitions are provided.}]
        foreach api {db_qd_fetch db_fullquery_get_name db_fullquery_get_querytext db_fullquery_get_load_location db_fullquery_get_rdbms} {
            if {[namespace which -command ::$api] eq {}} {
                return [list {} object [concat $base [list available boolean false reason string openacs-query-dispatcher-unavailable]]]
            }
        }
        # An exact cache key takes precedence. A missing fully qualified name
        # must not silently resolve to an unrelated suffix.
        set selected {}
        set candidates {}
        set limited false
        set examined 0
        if {[nsv_exists OACS_FULLQUERIES $name]} {
            set selected $name
        } elseif {[string first dbqd. $name]!=0 && [nsv_array exists OACS_FULLQUERIES]} {
            set suffix .$name
            foreach key [nsv_array names OACS_FULLQUERIES] {
                if {[incr examined]>50000} {
                    set limited true
                    break
                }
                if {[string first dbqd. $key]==0 && [string equal $suffix [string range $key end-[expr {[string length $suffix]-1}] end]]} {
                    lappend candidates $key
                }
            }
            set candidates [lsort $candidates]
            if {!$limited && [llength $candidates]==1} {
                set selected [lindex $candidates 0]
            }
        }
        set rows {}
        set i 0
        foreach key [lrange $candidates 0 19] {
            lappend rows $i string $key
            incr i
        }
        lappend base catalogLimited boolean $limited candidateCount number [llength $candidates] candidates array $rows  candidatesTruncated boolean [expr {[llength $candidates]>20}]
        if {$selected eq {}} {
            set reason [expr {$limited ? "query-catalog-limit" : ([llength $candidates]>1 ? "query-name-ambiguous" : "query-mapping-not-found")}]
            return [list {} object [concat $base [list available boolean false reason string $reason]]]
        }
        # Fetch once through OpenACS. Its loader already chose the compatible
        # generic/database/version mapping; never redo that selection here.
        if {[catch {
            set fullquery [::db_qd_fetch $selected]
            if {$fullquery eq {}} {
                error missing
            }
            if {[::db_fullquery_get_name $fullquery] ne $selected} {
                error mismatch
            }
            set sql [::db_fullquery_get_querytext $fullquery]
            set path [::db_fullquery_get_load_location $fullquery]
            set rdbms [::db_fullquery_get_rdbms $fullquery]
            if {[catch {
                dict size $rdbms
            }]} {
                error malformed
            }
        }]} {
            return [list {} object [concat $base [list available boolean false reason string query-mapping-unavailable]]]
        }
        set dbType {}
        set dbVersion {}
        if {[dict exists $rdbms type]} {
            set dbType [dict get $rdbms type]
        }
        if {[dict exists $rdbms version]} {
            set dbVersion [dict get $rdbms version]
        }
        # Bound metadata independently of paginated SQL. Paths are reported
        # exactly as recorded by the loader, without opening or normalizing them.
        set metadataTruncated false
        foreach var {path dbType dbVersion} {
            if {[string length [set $var]]>4096} {
                set metadataTruncated true
                set $var [string range [set $var] 0 4095]
            }
        }
        set offset [dict get $opts offset]
        set count [dict get $opts maxCharacters]
        set chunk [string range $sql $offset [expr {$offset+$count-1}]]
        set more [expr {$offset+[string length $chunk]<[string length $sql]}]
        set next {}
        if {$more} {
            set next [list name string $selected offset number [expr {$offset+[string length $chunk]}] maxCharacters number $count]
        }
        return [list {} object [concat $base [list available boolean true reason string {} name string $selected  resolution string [expr {$selected eq $name ? "exact" : "unique-suffix"}]  sourceFile string $path selectedRdbms object [list type string $dbType version string $dbVersion] metadataTruncated boolean $metadataTruncated  sql string $chunk sha256 string [ns_crypto::md string -digest sha256 -- $sql] sqlCharacters number [string length $sql]  offset number $offset more boolean $more nextArguments object $next]]]
    }
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: