Forum OpenACS Q&A: how to pass a multirow data source

Request notifications

Posted by Ignacio Laguna on
Hi, I need to pass a "multirow data source" between two procedures or
scripts. What is the best way to do it?. I've seen that I can send
params to a tcl script like "template::forward file?param...",
however I don't know how to send a multirow. I'm using ACS 4.

Thanks in advance.

Posted by Dan Wickstrom on
A multirow datasource exists as a rowcount variable and tcl array for each row. I could be wrong, but I don't think there is built-in support for passing these data structures around. You could get around this by converting the multirow datasource to a tcl list of lists. The list could then be passed around by using export_url_vars. Something like the following:

Originating script:

template::multirow create mr col0 col1 col2 col3

for {set i 0} {$i < 10} {incr i} {

    template::multirow append mr col0:$i col1:$i col2:$i col3:$i

set exp_lst [export_url_vars [multirow_to_list mr]]

Then in your associated template file, you would just do the following:

<a href=test-multirow-2?@exp_lst@>Pass a multirow datasource as a list</a>

Then on the receiving script, you would need to convert the list back to a multirow datasource:

ad_page_contract {

    test passing multirows between pages.

} {
} -properties {

list_to_multirow mr $mr_lst

Be advised that the utility routines list_to_multirow and multirow_to_list that exist in template::util won't work correctly with the multirow datasources created by template::multirow create, as they don't access the correct stack level when trying to convert to and from a list. You should be able to look at template::multirow proc and create a couple of utility routines for the conversion. If I get some time, I'll try and fix the template::util routines.

If the multirow datasource is not too large, the approach outlined above should work okay, but if the multirow datasource is large, you might want to consider another approach, as passing around a large multirow datasource like this could be pretty inefficient.

Posted by Don Baccus on
"array get" and "array set" seem to work.  However, you need to use a dummy name in "array set" because the template code does a "upvar 0 name:n name" for each row in a "multiple" tag.  db_multirow doesn't set the base array name to anything, but "array set" does, causing the name clash.