[AOLSERVER] Feature request: ns_querygetarray function

11 views
Skip to first unread message

Alexey Pechnikov

unread,
May 8, 2011, 11:02:50 AM5/8/11
to AOLS...@listserv.aol.com
I think we need function for getting HTTP forms arrays. As example,
this is a set of records from rich internet applications.
Results of popular js function serializeArray() from jQuery or analogs
can't be readed simple in AOL now. The function
ns_querygetall is very usefull, but this is not enough!


See code here:
http://pastebin.com/FsvA7ZDs
or below:


# jQuery example
# $.post("/json/answer/set/question/",$("#form_answers").serializeArray())
proc ns_querygetarray {} {
# name {name1 name2 ...} id {id1 id2 ...} ...
set info [dict create]
set form [ns_getform]
set size [ns_set size $form]
# empty form
if { $size == 0 } return
for {set i 0} {$i < $size} {incr i} {
set k [ns_set key $form $i]
set v [ns_set value $form $i]
# empty-named element is not exists
if { $k eq "" } continue
# check for valid names
if { [regexp -- {^\w+$} $k] == 0 } {
error "Field name is dangerous (\"$k\")"
}
dict lappend info [string tolower $k] [string trim $v]
}
# empty form (as form with only empty elements)
if { [llength $info] == 0 } return
# all fields must have equal elements count
set counter ""
dict for {k v} $info {
lappend counter [llength $v]
}
set counter [lsort -unique $counter]
if { [llength $counter] > 1 } {
error "Form arrays have non-equal length"
}
# transpose
set infoT ""
for {set i 0} {$i<$counter} {incr i} {
set row ""
foreach k [dict keys $info] {
lappend row $k [lindex [dict get $info $k] $i]
}
lappend infoT $row
}
# {name name1 id id1 ...} {name name2 id id2 ...} ....
return $infoT
}


--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to <list...@listserv.aol.com> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: field of your email blank.

Dave Bauer

unread,
May 9, 2011, 2:52:48 PM5/9/11
to AOLS...@listserv.aol.com
Are you trying to interpret JSON data sent to form processing script?

There is a JSON library in Tcllib. http://tcllib.sourceforge.net/doc/json.html

Alexey Pechnikov

unread,
May 9, 2011, 5:53:43 PM5/9/11
to AOLS...@listserv.aol.com
2011/5/9 Dave Bauer <da...@thedesignexperience.org>:

> Are you trying to interpret JSON data sent to form processing script?

No. The function parse standart HTTP forms like to ns_querygetall function.
You can sent these by SUBMIT button too.
But modern web applications use AJAX and I did write AJAX example.

> There is a JSON library in
> Tcllib.�http://tcllib.sourceforge.net/doc/json.html

It's very, very slow. Other libraries are faster by 100x factor and
more! As example, see
http://mobigroup.ru/debian/pool-squeeze/main/y/yajl-tcl/
You can check performance of the json2dict function from yajl-tcl
package and tcllib json package...

--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/

Dave Bauer

unread,
May 10, 2011, 10:42:50 AM5/10/11
to AOLS...@listserv.aol.com
On Mon, May 9, 2011 at 5:53 PM, Alexey Pechnikov <pech...@mobigroup.ru> wrote:
2011/5/9 Dave Bauer <da...@thedesignexperience.org>:
> Are you trying to interpret JSON data sent to form processing script?

No. The function parse standart HTTP forms like to ns_querygetall function.
You can sent these by SUBMIT button too.
But modern web applications use AJAX and I did write AJAX example.

> There is a JSON library in
> Tcllib. http://tcllib.sourceforge.net/doc/json.html

It's very, very slow. Other libraries are faster by 100x factor and
more! As example, see
http://mobigroup.ru/debian/pool-squeeze/main/y/yajl-tcl/
You can check performance of the json2dict function from yajl-tcl
package and tcllib json package...


I am not sure I understand hat you are trying to accomplish. What is an HTTP Form Array? I am not aware of such a thing. It looks like you are passing some application specific formatted data and need to process it.

I am not familiar with the performance characteristics of different implementation of JSON parsing so I can't comment on that.

Dave
 
--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to <list...@listserv.aol.com> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: field of your email blank.

Alexey Pechnikov

unread,
May 10, 2011, 11:59:47 AM5/10/11
to AOLS...@listserv.aol.com
2011/5/10 Dave Bauer <da...@thedesignexperience.org>:

> I am not sure I understand hat you are trying to accomplish. What is an HTTP
> Form Array? I am not aware of such a thing. It looks like you are passing
> some application specific formatted data and need to process it.

This is very popular situation! The HTML example with checkboxes array:

<form method=post action=''>";
<input type=checkbox name=box value='John'>
<input type=checkbox name=box value='Mike'>
<input type=checkbox name=box value='Rone'>

Param "box" is array.

As example, a simple HTTP GET request:
/?a=first&a=second&b=1&b=2

In this request we can see 2 two-elements arrays:
a=first, a=second
b=1, b=2

or 2 rows:
a=first, b=1
a=second, b=2

Problems:

1. When names and number of the array elements are not known we can't
use ns_querygetall

2. When some items can be not defined is needed the additional check
of arrays elements count. As example
/?a=first&a=second&b=1&a=third&b=3
But
[ns_querygetall a] {first second third}
[ns_querygetall b] {1 3}

Of course, these are _not_ the 3 rows becouse value [lindex
[ns_querygetall b] 2] = "" is invalid!

Dave Bauer

unread,
May 10, 2011, 12:09:01 PM5/10/11
to AOLS...@listserv.aol.com
 In general since you want to do additional input checking, and the input checking may be application specific AOLserver doesn't support this. I doubt anyone is going to implement this at the AOLserver level.

OpenACS supports parsing the input in this way as well as input validation and error checking, as one example that I am familiar with. I am sure there is other Tcl code that exists to do this.

Dave

Best regards, Alexey Pechnikov.
http://pechnikov.tel/


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to <list...@listserv.aol.com> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: field of your email blank.

Gustaf Neumann

unread,
May 11, 2011, 2:37:39 AM5/11/11
to AOLS...@listserv.aol.com
Am 10.05.11 17:59, schrieb Alexey Pechnikov:

> Problems:
>
> 1. When names and number of the array elements are not known we can't
> use ns_querygetall
why not using ns_getform? like e.g.:

===============================================================form-action.tcl
foreach {att value} [ns_set array [ns_getform]] {
lappend a($att) $value
}
ns_return 200 text/plain "keys: [array names a]\nkeys+values: [array get a]"
==============================================================================

-gustaf neumann

--
Univ.Prof. Dr. Gustaf Neumann
Institute of Information Systems and New Media
WU Vienna
Augasse 2-6, A-1090 Vienna, AUSTRIA

Alexey Pechnikov

unread,
May 11, 2011, 3:09:28 AM5/11/11
to AOLS...@listserv.aol.com
2011/5/11 Gustaf Neumann <neu...@wu.ac.at>:

> why not using ns_getform? like e.g.:
>
> ===============================================================form-action.tcl
> foreach {att value} [ns_set array [ns_getform]] {
> � �lappend a($att) $value
> }
> ns_return 200 text/plain "keys: [array names a]\nkeys+values: [array get a]"

With additional check for counters and transpose this code will be not
so trivial.
But I think that getting set of records from form may be simple
operation in AOL.
How about editing and saving a set of database records?... And how about
parsing CSV format on client (javascript) and packet import?... All
these operations
can be realised easy with ns_querygetarray function.

--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/

Torben Brosten

unread,
May 11, 2011, 4:14:15 AM5/11/11
to AOLS...@listserv.aol.com
Here's a proc that uses ns_getform, and returns the form values to a
supplied array name:

qf_get_inputs_as_array

See:
http://fisheye.openacs.org/browse/OpenACS/openacs-4/packages/spreadsheet/tcl/form-procs.tcl?r=1.27

It uses ad_quotehtml from OpenACS and includes some basic protections.

cheers,

Torben


Alexey Pechnikov wrote:
> 2011/5/11 Gustaf Neumann <neu...@wu.ac.at>:
>> why not using ns_getform? like e.g.:
>>
>> ===============================================================form-action.tcl
>> foreach {att value} [ns_set array [ns_getform]] {
>> lappend a($att) $value
>> }
>> ns_return 200 text/plain "keys: [array names a]\nkeys+values: [array get a]"
>
> With additional check for counters and transpose this code will be not
> so trivial.
> But I think that getting set of records from form may be simple
> operation in AOL.
> How about editing and saving a set of database records?... And how about
> parsing CSV format on client (javascript) and packet import?... All
> these operations
> can be realised easy with ns_querygetarray function.
>


--

Alexey Pechnikov

unread,
May 11, 2011, 6:33:02 AM5/11/11
to AOLS...@listserv.aol.com
2011/5/11 Torben Brosten <tor...@dekka.com>:

> Here's a proc that uses ns_getform, and returns the form values to a
> supplied array name:
>
> qf_get_inputs_as_array
>
> See:
> http://fisheye.openacs.org/browse/OpenACS/openacs-4/packages/spreadsheet/tcl/form-procs.tcl?r=1.27
>
> It uses ad_quotehtml from OpenACS and includes some basic protections.

ACS is very complex solution. Custom AOL-based ORM
(http://en.wikipedia.org/wiki/Object-relational_mapping)
for AJAX applications may be extremly smaller than ACS.

--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/

Torben Brosten

unread,
May 11, 2011, 11:16:07 AM5/11/11
to AOLS...@listserv.aol.com
Alexey Pechnikov wrote:
> 2011/5/11 Torben Brosten <tor...@dekka.com>:
>> Here's a proc that uses ns_getform, and returns the form values to a
>> supplied array name:
>>
>> qf_get_inputs_as_array
>>
>> See:
>> http://fisheye.openacs.org/browse/OpenACS/openacs-4/packages/spreadsheet/tcl/form-procs.tcl?r=1.27
>>
>> It uses ad_quotehtml from OpenACS and includes some basic protections.
>
> ACS is very complex solution. Custom AOL-based ORM
> (http://en.wikipedia.org/wiki/Object-relational_mapping)
> for AJAX applications may be extremly smaller than ACS.
>

qf_get_inputs_as_array is available to use ns_getform with some common
security constraints.

To use qf_get_inputs_as_array outside of the ACS dependency, remove the
first case of ad_quotehtml, it's redundant.

For the second case of ad_quotehtml, substitute a proc defined as:

return [string map {& &amp; \" &quot; < &lt; > &gt;} $arg]


There are no other dependencies on ACS.

cheers,

Torben

Alexey Pechnikov

unread,
May 11, 2011, 11:40:55 AM5/11/11
to AOLS...@listserv.aol.com
2011/5/11 Torben Brosten <tor...@dekka.com>:

> To use qf_get_inputs_as_array outside of the ACS dependency

Thx, but I can read the code. But there is no some useful functions in AOL.
May be adding a few helper procs will make AOL more developer friendly.
ACS has useful database layer but other functionality is not compact
and is not universal.

> For the second case of ad_quotehtml, substitute a proc defined as:
>
> �return [string map {& &amp; \" &quot; < &lt; > &gt;} $arg]

I think these are strange substitutions. HTML entities escaping is
needed for output but not for input.
The full-text search tokenization after additional conversation will
be not easy. And so on.

--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/

Jeff Rogers

unread,
May 11, 2011, 4:05:19 PM5/11/11
to AOLS...@listserv.aol.com
Alexey Pechnikov wrote:
> 2011/5/10 Dave Bauer<da...@thedesignexperience.org>:
>> I am not sure I understand hat you are trying to accomplish. What is an HTTP
>> Form Array? I am not aware of such a thing. It looks like you are passing
>> some application specific formatted data and need to process it.
>
> This is very popular situation! The HTML example with checkboxes array:

It may be a common situation, but that doesn't mean it is well-defined.
In your example below, what would "querygetarray" do when the counts
of the keys are not the same? Would it generate blank entries for
those, drop the keys without enough values, or refuse to process it
(possibly by raising an error)?

A fuller specification of what the function does would be helpful. Does
this function exist for other frameworks? Maybe seeing the docs of
those would help explain things.

Otherwise, this seems like a function specific to using jquery; perhaps
it would go better in a jquery support library.

-J


--

Alexey Pechnikov

unread,
May 11, 2011, 6:29:58 PM5/11/11
to AOLS...@listserv.aol.com
2011/5/12 Jeff Rogers <dv...@diphi.com>:

> It may be a common situation, but that doesn't mean it is well-defined. �In
> your example below, what would "querygetarray" do when the counts of the
> keys are not the same? �Would it generate blank entries for those, drop the
> keys without enough values, or refuse to process it (possibly by raising an
> error)?

I'm sure that raising error for invalid data is the only true way.

> A fuller specification of what the function does would be helpful. �Does
> this function exist for other frameworks? �Maybe seeing the docs of those
> would help explain things.

For OpenACS there is some similar functionality but I don't know
about other frameworks.

> Otherwise, this seems like a function specific to using jquery; perhaps it
> would go better in a jquery support library.

AOL has enough functions for HTTP support and I use only this single
additional proc for forms
(as standalone HTTP forms as jQuery AJAX queries) data parsing. For
javascript applications
is needed server-side JSON generator, but input data can be handled as
common HTTP forms.

P.S. With Tcl 8.5 is easy to build AJAX server on AOL platform, as example:

proc returnjson {args} {
ns_return 200 "text/plain; charset=utf-8" [::json::object_escape {*}$args]
}

proc ad_add {table} {
if {[catch {
json_add $table
} msg]} {
ns_log Error $::errorInfo
returnjsonerror $msg
}
}

# insert a set of new records into database
# and return after the added records from database
# "db" is SQLite3 handler for this connection
proc json_add {table} {
ns_setexpires 0

set newid ""
# use nested catch for errors in SQLite db transaction method
db transaction {
if {[catch {
foreach row [ns_querygetarray] {
lappend newid [table_insert_row $table $row]
}
} msg]} {
ns_log Error $::errorInfo
returnjsonerror $msg
error
}
}
set rid [table_record $table $newid]
set out [table_json $table $rid]
returnjsonobject code {"ok"} counter [llength $out] $table \[[join $out ,]\]
}

# add handlers for some tables
foreach table ... {
ns_register_proc -noinherit POST /json/$table/add/ ad_add $table
}

P.P.S. I use SQLite becouse I need fast full-text realtime search for
all data in database
and SQLite FTS4 extension with snowball stemmers is fine for me.

Single SQLite3 connection handler for each thread is good and fast
solution. As example:
ns_ictl trace create {
package require sqlite3
...
sqlite3 db /tmp/test.db
db timeout 10000
...
}

--
Best regards, Alexey Pechnikov.
http://pechnikov.tel/

Reply all
Reply to author
Forward
0 new messages