You are viewing a plain text version of this content. The canonical link for it is here.
Posted to rivet-dev@tcl.apache.org by Michael Schlenker <sc...@uni-oldenburg.de> on 2005/11/02 14:44:45 UTC

Comparing nstcl-database with DIO and XOSql (long)

Hi all,

while looking for a database abstraction layer i had a look at
nstcl-database (http://nstcl.sourceforge.net), basically a compatibility
package to aolservers database api, and also looked at the rivet DIO
package. I also took a cursory look at XOSql
(http://www.xdobry.de/xosql/index.html)

So i started with a simple features checklist:

Supported Databases:
--------------------------------------------
MySQL 				nstcl, DIO, XOSql
PostgreSQL			nstcl, DIO, XOSql
Sybase (equiv to MS SQL)	nstcl
SQLite				nstcl, DIO, XOSql
Oracle				nstcl, XOSql
Solid				nstcl
ODBC				nstcl, XOSql
use Perl DBI			XOSQL
--------------------------------------------

Not much of a concern, as adding new databases to DIO looks as easy as
it is for nstcl, just adding some small wrapper procs.

License:
--------------------------------------------
DIO	Apache License
nstcl	MIT/X11 License
XOSql	GNU General Public License
--------------------------------------------

OO Style:
--------------------------------------------
DIO	incrTcl
nstcl	none
XOSql	XOTcl
--------------------------------------------

Basic Functionalities:

executing a SQL query
--------------------------------------------
DIO	$db exec $query
nstcl   db_dml statement1 $query  (*)
XOSql	$db execute $query
--------------------------------------------
(* This is for a query modifing a value)

getting a single value from an SQL query
--------------------------------------------
DIO	set string [$db string $query]
nstcl	set string [database_to_tcl_string $dbhandle $query]
XOSql	set string [lindex [[$db query $query] fetch] 0]
--------------------------------------------

getting one row of a SQL query into an array
--------------------------------------------
DIO	$db array $query $arrayVar
nstcl*  db_1row statement2 $query -columnVar $arrayVar
XOSql	set rObj [$db query $query]
	set keys [$rObj columNames]
	set values [$rObj fetch]
	foreach key $keys value $values {
		set $arrayVar($key) $value
	}
--------------------------------------------
(* 	nstcl errors out if 0 or more than one row is returned)


loop over the rows of a SQL query
(Example: set query "SELECT id,name FROM person")
--------------------------------------------
DIO	set rObj [$db exec $query]
	$rObj forall -array result {
		puts "$result(id) -> $result(name)"
	}

nstcl	db_foreach statement3 $query {
		puts "$id -> $name"
	}
XOSql	set rObj [$db query $query]
	while {[llength [set row [$rObj fetch]]]} {
		puts "[lindex $row 0] -> [lindex $row 1]"
	}
--------------------------------------------
nstcl's style risks accidental overwriting of variables,
which could lead to security problems.


getting the first column of a SQL query as list
-----------------------------------------------
DIO	set list [$db list $query]
nstcl	set list [db_list statement4 $query]
XOSql	set rObj [$db query $query]
	set list [list]
	while {[llength [set row [$rObj fetch]]]} {
		lappend list [lindex $row 0]
	}
-----------------------------------------------

Getting the whole result as nested list of lists
------------------------------------------------
DIO	set llist [list]
	set rObj [$db exec $query]
	$rObj forall -list row {lappend llist $row}

nstcl	set llist [db_list_of_lists statement5 $query]
XOSql	set llist [$db queryList $query]
------------------------------------------------

Get the number of affected rows for a query
------------------------------------------------
DIO	set rObj [$db exec $query]
	set numRows [$rObj numrows]

nstcl*	?
XOSql	set rObj [$db execute $query]
	set numRows [$rObj rows]
------------------------------------------------
(* no idea after just looking at the docs)

Inserting a new row into the database
------------------------------------------------
DIO 	$db insert $arrayVar -table demo
nstcl*	set id $arrayVar(id)
	set name $arrayVar(id)
	db_dml statement {
	    insert into demo (id , name) values (:id, :name)
	}

XOSql 	set keys [array names $arrayVar]
	set values [list]
	foreach key $keys {lappend values $arrayVar($key)}
	$db inserRow demo $keys $values
--------------------------------------------------------
(* not sure if the bind variable feature supports arrays,
   the first two lines may be superfluous.)

Inserting a new row with automatic id
--------------------------------------------------------
DIO	$db insert $arrayVar -table demo \
		-keyfield id -autokey 1 -sequence demo_seq

nstcl*	set name $arrayVar(name)
	db_dml statement {
	    insert into demo (id, name)
		values (
		  (select * FROM nextval(demo_seq)
		), :name)
	}

XOSql   set keys [array names $arrayVar]
	set values [list]
	foreach key $keys {lappend values $arrayVar($key)}
	$db rowInsertAutoId demo $keys $values id $sequencer **
		
--------------------------------------------------------
(* basically no support for automatic ids, use what the
   underlying database provides)
(** I couldn't figure out from the docs what exactly has to be provided
by sequencer)

Delete a record from the database by primary key
--------------------------------------------------------
DIO	$db delete $key -table demo -keyfield id
nstcl	db_dml statement {
		delete from demo where id = :id	
	}
XOSql*	$db execute "delete from demo where id = $id"
--------------------------------------------------------
(* not sure if any quoting is done, may be a security problem)


Transaction support
--------------------------------------------------------
DIO	$db exec {BEGIN TRANSACTION}
	...
	# do some operations
	...
	$db exec {COMMIT TRANSACTION}
nstcl*	db_transaction {
		...
		# do some operations
		...
	}
XOSql	$db execute {BEGIN TRANSACTION}
	...
	# do some operations
	...
	$db execute {COMMIT TRANSACTION}
---------------------------------------------------------
Basically neither DIO nor XOSql seem to have any real
transaction support.nstcl supports optional code to eval in case
of errors during a transaction to decide on commit or rollback.

Quoting support, for dynamic queries
---------------------------------------------------------
DIO*	attempts autoquoting of values in queries,
XOSql	provides escape method for simple value quoting
nstcl	binding variables for queries with autoquoting
	functions to quote identifiers and values
---------------------------------------------------------
* The current practice in DIO is insecure and is an SQL injection attack
vector. Only values are quoted. Identifiers (table and field names) are
passed to the database without any quoting.
Value quoting seems broken and incomplete. It does not take SQL quoting
rules into account, which may lead to data inconsistencies.

Example of SQL Injection:
set table users
set match {'\' OR 1==1; --}
$obj exec "SELECT * FROM $table WHERE id = $match AND password = $passwd;"

Similar issues may be present in XOSql and nstcl but i did not take a
closer look.

Conclusions:
-------------------------------------------------------------
All three interfaces behave quite similar for simple queries,
only differing in style of commands (OO vs. procedural) and
arguments/results available (objs, lists, nested lists, arrays).
Mostly a matter of taste.

XOSql offers the interesting option to use the Perl DBI drivers with
the help of an extension of the same author. Similar things could
probably easily be done with TclBlend and JDBC drivers.

For complexer scenarios both XOSql and DIO are missing support for
handling transactions.

nstcl's database support adds support for bind variables for all
databases, based on some simple tcl procs, which could be adopted by DIO
and XOSql. Even better would be to use the binding functions and support
for prepared statements of the underlying database. At least SQLlite and
newer Pgtcl versions support some form of binding variables.

To provide appropriate quoting support, all layers should look at the db
interfaces and use the database specific quoting functions (available at
least for mysql, postgres) and provide a compatibility function based on
the SQL standard + variations for each db driver for all others.

I have not yet looked at the DIODisplay and the nstcl multirow
datasource features, which look interesting.

Hope this is interesting or informative for some of you
Michael Schlenker




  	


---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Comparing nstcl-database with DIO and XOSql (long)

Posted by Wojciech Kocjan <wo...@kocjan.org>.
Dnia 02-11-2005 o 14:44:45 Michael Schlenker <sc...@uni-oldenburg.de>  
napisaƂ:

> Hi all,
>
> while looking for a database abstraction layer i had a look at
> nstcl-database (http://nstcl.sourceforge.net), basically a compatibility
> package to aolservers database api, and also looked at the rivet DIO
> package. I also took a cursory look at XOSql
> (http://www.xdobry.de/xosql/index.html)

Could you also take a look at tcldb?

It's located in http://sourceforge.net/projects/dqsoftware/

Some of my comments:

1/ it's really impossible to provide SQL-injection proof toolkit. Well,  
almost impossible. But making $db exec "INSERT INTO table  
VALUES('$x','$y')" sounds a bit impossible to me.

Tcldb does that by doing:
$db exec "INSERT INTO table VALUES('@X@','@Y@')" x $x y $y (it quotes  
according to current database's quoting rules)

2/ You should insert some speed tests - ie 1000 inserts, large selects etc.

3/ Could you also include sqlite in the databases? I find it a great db.

4/ Otherwise a very interesting text.

-- 
WK

---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org