On Thu, Feb 6, 2014 at 5:17 PM, Wolfgang Winkler <wolfgang.wink...@digital-concepts.com> wrote: > Hello! > > I've added a datatype "dict" to the list of possible DbiResults. "dicts" > returns a list of dicts, whereas "dict" returns a dict. The keys for the first > level is a simple counter. So instead of > > {user_id 1 user_name Max} {user_id 2 user_name Lisa} > > 1 {user_id 1 user_name Max} 2 {user_id 2 user_name Lisa} > > There is a slight performance hit compared to "dicts", but the result is more > useful, as you can do the following: > > dict for {k v} $result { > set user_id [dict get $v user_id] > dict set result $k user_url "user?user_id=$user_id" > }
Hmm, is the above better than the following: set rows [list [list c1 v1 c2 v2] [list c1 vv1 c2 vv2]] foreach row $rows { lappend rowdicts [dict set row c3 "c3=[dict get $row c2]"] } set rowdicts {c1 v1 c2 v2 c3 c3=v2} {c1 vv1 c2 vv2 c3 c3=vv2} I guess the idea is that 'dict set result k1 k2 v1' is efficient, but I would guess that the implementation above is about the same, due to non-obvious dict duplication. dicts are copy-on-write. If the dict is unshared then no one will see the mutation so no copy is needed, but in the case above the row-dict is shared. dbi_rows returns a list and all the elements in the list have their ref count incremented to by it, and they are therefore unshared. The v in 'dict for {k v} ...' refers to the list which holds the keys and values of the row, and as v is a new variable passed to the script block it has it's ref count incremented, which is now 2. 'dict get $v ...' shimmers the list to a dict, ref-count still 2. 'dict set result ...' navigates the outer dict, which was shimmered by 'dict for ...', with refcount hopefully 1, to the inner dict, with refcount 2, copies it because it won't mutate a shared object, adds the new key and value to the copy, puts the copy back in the outer dict. So, the row is created as a list. The the row is created as a dict. It is created again as a dict, and the old dict is discarded. You can see the effect here: set rows [list 1 [list c1 v1 c2 v2] 2 [list c1 vv1 c2 vv2]] dict for {rownum listydict} $rows { puts "(before) rownum: $rownum listydict: $listydict" puts " rows: $rows" set c2 [dict get $listydict c2] dict set rows $rownum c3 "c3=$c2" puts "(after) rownum: $rownum listydict: $listydict" puts " rows: $rows\n" } (before) rownum: 1 listydict: c1 v1 c2 v2 rows: 1 {c1 v1 c2 v2} 2 {c1 vv1 c2 vv2} (after) rownum: 1 listydict: c1 v1 c2 v2 rows: 1 {c1 v1 c2 v2 c3 c3=v2} 2 {c1 vv1 c2 vv2} (before) rownum: 2 listydict: c1 vv1 c2 vv2 rows: 1 {c1 v1 c2 v2 c3 c3=v2} 2 {c1 vv1 c2 vv2} (after) rownum: 2 listydict: c1 vv1 c2 vv2 rows: 1 {c1 v1 c2 v2 c3 c3=v2} 2 {c1 vv1 c2 vv2 c3 c3=vv2} In 'after' the first row of rows has the new column but listydict does not, even though it was a reference to it at the start of the loop. How about something more like this: set rows [dbi_rows -extend {{c3 c4} { set c3 "c3=$c1" set c4 "c4=$c2" }} { select c1, c2 from table limit 2 }] v1 v2 c3=v1 c4=v2 vv1 vv2 c3=vv1 c4=vv2 This is the flat-list version, which has advantages over the array-get format mentioned in the other thread, but for the purposes of -extend it doesn't matter. It could works like this: After the first row of values has been appended to the rows list, if -extend was given then that number of empty objects are appended before starting the next row. Once all rows have been appended the db handle is released. Now skip back to the empty objects and run the extend-script to fill them in (should look closely at how the modern Tcl does this -- looks like they have some new stuff to prevent variable clobbering). I think this is an acceptable trick for something like -extend but not dbi_foreach because there is no expectation you are working on one row at a time: dbi_rows returns the whole result set. Nested queries here are the equivalent of serial queries. Now, you could do the above also with listy-dicts, but how about this: dbi_dicts -enumerate 1 $cols $rows ...which would return a list of 2-element lists, the first being either a 0 or 1 based counter, the second an actual dict composed of the zipped cols 'n row. All the keys 'n values in the dicts are just ref-counted from the cols 'n rows, so the cols values will be well shared. The dicts are created exactly once. ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk _______________________________________________ naviserver-devel mailing list naviserver-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/naviserver-devel