Forum OpenACS Development: Fundemental problem with oracle bind variables, lobs and upvar
Posted by
Barry Books
on 06/15/04 04:47 PM
I'm having problems with cr_write_content which I'm think are really fundemental problems with the way the Oracle db rountins handle upvar and bind variables. I was having problems with clobs yesterday and I fixed them. Now I'm having similar problems with blobs and I'm not sure I fixed clobs the correct way.
First I've always assumed that the bind variables and the results should happen in the same stack frame. For example
cr_write_content -revision_id $revision_id db_write_blob db_exec_lob passes -ulevel 3 db_exec_lob_oracle passes ns_oraThe bind variable for :revision_id should come from the cr_write_content stack frame, but db_exec_lob_orace does
set start_time [clock clicks -milliseconds] set sql [db_qd_replace_sql $statement_name $pre_sql] # insert tcl variable values (Openacs - Dan) if {![string equal $sql $pre_sql]} { set sql [uplevel $ulevel [list subst -nobackslashes $sql]] } set file_storage_p 0 upvar $ulevel storage_type storage_type if {[info exists storage_type] && [string equal $storage_type file]} { set file_storage_p 1 set original_type $type set qtype 1row ns_log Debug "db_exec_lob: file storage in use" } else { set qtype $type ns_log Debug "db_exec_lob: blob storage in use" } set errno [catch { upvar bind bind # Below, note that 'ns_ora blob_get_file' takes 3 parameters, # while 'ns_ora write_blob' takes only 2. So if file is empty # string (which it always will/should be for $qtype # write_blob), we must not pass any 3rd parameter to the # ns_ora command: --atp@piskorski.com, 2003/04/09 15:10 EDT if { [info exists bind] && [llength $bind] != 0 } { if { [llength $bind] == 1 } { if { [empty_string_p $file] } { set selection [eval [list ns_ora $qtype $db -bind $bind $sql]] } else { set selection [eval [list ns_ora $qtype $db -bind $bind $sql $file]] } } else { set bind_vars [ns_set create] foreach { name value } $bind { ns_set put $bind_vars $name $value } if { [empty_string_p $file] } { set selection [eval [list ns_ora $qtype $db -bind $bind_vars $sql]] } else { set selection [eval [list ns_ora $qtype $db -bind $bind_vars $sql $file]] } } } else { if { [empty_string_p $file] } { set selection [uplevel $ulevel [list ns_ora $qtype $db $sql]] } else { set selection [uplevel $ulevel [list ns_ora $qtype $db $sql $file]] } }Here is a stack trace
nsoracle.c:3206:ora_tcl_command: error in `OCIStmtExecute ()': ORA-01008: not al l variables bound SQL: select content from cr_revisions where revision_id = :revision_id while executing "ns_ora write_blob nsdb0 { select content from cr_revisions where revision_id = :revision_id }" ("uplevel" body line 1) invoked from within "uplevel $ulevel [list ns_ora $qtype $db $sql]" invoked from within "$which_proc -ulevel [expr {$ulevel +1}] $type $db $statement_name $pre_sql $fil e" (procedure "db_exec_lob" line 35) invoked from within "db_exec_lob write_blob $db $full_statement_name $sql " ("uplevel" body line 2) invoked from within "uplevel 1 $code_block " invoked from within "db_with_handle -dbn $dbn db { db_exec_lob write_blob $db $full_statement_name $sql }" (procedure "db_write_blob" line 5) invoked from within "db_write_blob write_lob_content " select content from cr_revisions where revision_id = :revision_id "" ("lob" arm line 12) invoked from withinNow I think the code with the insert tcl var comments should substitue for $revision_id in a query. but upvar bind bind will only go up 1 level. It seems like this should be upvar $ulevel bind bind (maybe, the wrapper rountines do not pass bind variables) but I also seems like the ns_ora command should be always upleveled as well.
The other thing that happens is db_with_handle does an uplevel also. I'm not sure how that interacts with the uplevel that happens latter
So I guess the questions are should the wrapper routines pass down bind variables? and more fundemental what frame should ns_ora run in. And I guess what needs to be done to fix it.