Months ago Arnulf Widemann released to rivet some patches
and add-ons that enabled 'dio' and 'session' to work properly
with Mysql and included a brand new dio class for Oracle
I tested during the summer the dio Mysql class using the 0.5
and 1.0 modules and made some minor changes. (I had
also added a file with a suggestion in order to address a problem
with 'session' that arises if the package is used with
mysql 4.x and 5.0)
I'm attaching to this message these things as a diff file
generated by copying the new code into the 1_0 tree and
running a 'svn diff'. regards
--
-- Massimo Manghi
-- Dipartimento di Biologia Evolutiva e Funzionale
-- Universit? degli Studi di Parma
-- Parco Area delle Scienze 11A - 43100 Parma
Index: session/session-class.tcl
===================================================================
--- session/session-class.tcl (revision 449978)
+++ session/session-class.tcl (working copy)
@@ -102,6 +102,8 @@
constructor {args} {
eval configure $args
+ $dioObject registerSpecialField rivet_session session_update_time NOW
+ $dioObject registerSpecialField rivet_session session_start_time NOW
}
method status {args} {
@@ -149,7 +151,7 @@
set sessionIdKey "$uniqueID[clock clicks][pid]$args[clock
seconds]$scrambleCode[get_entropy_bytes]"
debug "gen_session_id - feeding this to md5: '$sessionIdKey'"
- return [::md5::md5 $sessionIdKey]
+ return [::md5::md5 -hex -- $sessionIdKey]
}
#
@@ -159,7 +161,13 @@
#
method do_garbage_collection {} {
debug "do_garbage_collection: performing garbage collection"
- set result [$dioObject exec "delete from $sessionTable where timestamp
'now' - session_update_time > interval '$gcMaxLifetime seconds';"]
+# set result [$dioObject exec "delete from $sessionTable where timestamp
'now' - session_update_time > interval '$gcMaxLifetime seconds';"]
+ set del_cmd "delete from $sessionTable where "
+ append del_cmd [$dioObject makeDBFieldValue $sessionTable
session_update_time now SECS]
+ append del_cmd " - [$dioObject makeDBFieldValue $sessionTable
session_update_time {} SECS]"
+ append del_cmd " > $gcMaxLifetime"
+ debug "do_garbage_collection: > $del_cmd <"
+ set result [$dioObject exec $del_cmd]
$result destroy
}
@@ -294,14 +302,14 @@
#
method store {packageName key data} {
set a(session_id) [id]
- set a(package) $packageName
- set a(key) $key
+ set a(package_) $packageName
+ set a(key_) $key
regsub -all {\\} $data {\\\\} data
set a(data) $data
- debug "store session data, package '$packageName', key '$key', data
'$data'"
- set kf [list session_id package key]
+ debug "store session data, package_ '$packageName', key_ '$key', data
'$data'"
+ set kf [list session_id package_ key_]
if {![$dioObject store a -table $sessionCacheTable -keyfield $kf]} {
puts "Failed to store $sessionCacheTable '$kf'"
@@ -315,21 +323,21 @@
# for this session
#
method fetch {packageName key} {
- set kf [list session_id package key]
+ set kf [list session_id package_ key_]
set a(session_id) [id]
- set a(package) $packageName
- set a(key) $key
+ set a(package_) $packageName
+ set a(key_) $key
set key [$dioObject makekey a $kf]
if {![$dioObject fetch $key a -table $sessionCacheTable -keyfield $kf]}
{
status [$dioObject errorinfo]
- puts "error: [$dioObject errorinfo]"
- debug "fetch session data failed, package '$packageName', key
'$key', error '[$dioObject errorinfo]'"
+ debug "error: [$dioObject errorinfo]"
+ debug "fetch session data failed, package_ '$packageName', key_
'$key', error '[$dioObject errorinfo]'"
return ""
}
- debug "fetch session data succeeded, package '$packageName', key
'$key', result '$a(data)'"
+ debug "fetch session data succeeded, package_ '$packageName', key_
'$key', result '$a(data)'"
return $a(data)
}
@@ -443,6 +451,7 @@
method debug {message} {
if {$debugMode} {
puts $debugFile "$this (debug) $message<br>"
+ flush $debugFile
}
}
}
Index: dio/dio_Postgresql.tcl
===================================================================
--- dio/dio_Postgresql.tcl (revision 449978)
+++ dio/dio_Postgresql.tcl (working copy)
@@ -134,6 +134,16 @@
set errorcode [pg_result $resultid -status]
set errorinfo [pg_result $resultid -error]
+ # if numrows is zero, see if cmdrows returned anything and if it
+ # did, put that in in place of numrows, hiding a postgresql
+ # idiosyncracy from DIO
+ if {$numrows == 0} {
+ set cmdrows [pg_result $resultId -cmdTuples]
+ if {$cmdrows != ""} {
+ set numrows $cmdrows
+ }
+ }
+
if {$errorcode != "PGRES_COMMAND_OK" \
&& $errorcode != "PGRES_TUPLES_OK"} { set error 1 }
Index: dio/dio_Mysql.tcl
===================================================================
--- dio/dio_Mysql.tcl (revision 449978)
+++ dio/dio_Mysql.tcl (working copy)
@@ -16,15 +16,16 @@
# $Id$
-package provide dio_Mysql 0.1
+package provide dio_Mysql 0.2
namespace eval DIO {
::itcl::class Mysql {
inherit Database
constructor {args} {eval configure $args} {
- if {[catch {package require Mysqltcl}] \
- && [catch {package require mysql}]} {
+ if { [catch {package require Mysqltcl}] \
+ && [catch {package require mysqltcl}] \
+ && [catch {package require mysql} ] } {
return -code error "No MySQL Tcl package available"
}
@@ -48,8 +49,9 @@
if {![lempty $user]} { lappend command -user $user }
if {![lempty $pass]} { lappend command -password $pass }
if {![lempty $port]} { lappend command -port $port }
- if {![lempty $host]} { lappend command $host }
-
+ if {![lempty $host]} { lappend command -host $host }
+
+# puts "i'm going to connect mysql: >$command< ($this) <br/>"
if {[catch $command error]} { return -code error $error }
set conn $error
@@ -105,6 +107,51 @@
return $conn
}
+ method makeDBFieldValue {table_name field_name val {convert_to {}}} {
+ if {[info exists specialFields([EMAIL PROTECTED])]} {
+ switch $specialFields([EMAIL PROTECTED]) {
+ DATE {
+ set secs [clock scan $val]
+ set my_val [clock format $secs -format
{%Y-%m-%d}]
+ return "DATE_FORMAT('$my_val', '%Y-%m-%d')"
+ }
+ DATETIME {
+ set secs [clock scan $val]
+ set my_val [clock format $secs -format
{%Y-%m-%d %T}]
+ return "DATE_FORMAT('$my_val', '%Y-%m-%d %T')"
+ }
+ NOW {
+ switch $convert_to {
+ SECS {
+ if {[::string compare $val "now"] == 0} {
+ set secs [clock seconds]
+ set my_val [clock format $secs
-format {%Y%m%d%H%M%S}]
+ return $my_val
+ } else {
+ return
"DATE_FORMAT(session_update_time,'%Y%m%d%H%i%S')"
+ }
+ }
+ default {
+ if {[::string compare $val, "now"] == 0} {
+ set secs [clock seconds]
+ } else {
+ set secs [clock scan $val]
+ }
+ set my_val [clock format $secs -format
{%Y-%m-%d %T}]
+ return "DATE_FORMAT('$my_val', '%Y-%m-%d
%T')"
+ }
+ }
+ }
+ default {
+ # no special code for that type!!
+ return "'[quote $val]'"
+ }
+ }
+ } else {
+ return "'[quote $val]'"
+ }
+ }
+
public variable db "" {
if {[info exists conn]} {
mysqluse $conn $db
@@ -130,7 +177,7 @@
method nextrow {} {
return [mysqlnext $resultid]
}
-
+
} ; ## ::itcl::class MysqlResult
}
Index: dio/pkgIndex.tcl
===================================================================
--- dio/pkgIndex.tcl (revision 449978)
+++ dio/pkgIndex.tcl (working copy)
@@ -1,5 +1,6 @@
package ifneeded DIO 1.0 [list source [file join $dir dio.tcl]]
package ifneeded DIODisplay 1.0 [list source [file join $dir diodisplay.tcl]]
-package ifneeded dio_Mysql 0.1 [list source [file join $dir dio_Mysql.tcl]]
+package ifneeded dio_Mysql 0.2 [list source [file join $dir dio_Mysql.tcl]]
package ifneeded dio_Postgresql 0.1 [list source [file join $dir
dio_Postgresql.tcl]]
package ifneeded dio_Sqlite 0.1 [list source [file join $dir dio_Sqlite.tcl]]
+package ifneeded dio_Oracle 0.2 [list source [file join $dir dio_Oracle.tcl]]
Index: dio/dio.tcl
===================================================================
--- dio/dio.tcl (revision 449978)
+++ dio/dio.tcl (working copy)
@@ -138,7 +138,7 @@
# is appended with a "field LIKE value"
if {[::string first {%} $elem] != -1} {
- append req " $field LIKE '[quote $elem]'"
+ append req " $field LIKE [makeDBFieldValue $myTable
$field $elem]"
} elseif {[regexp {^([<>]) *([0-9.]*)$} $elem _ fn
val]} {
# value starts with <, or >, then space,
# and a something
@@ -148,7 +148,7 @@
append req " $field$fn$val"
} else {
# otherwise it's a straight key=value comparison
- append req " $field='[quote $elem]'"
+ append req " $field=[makeDBFieldValue $myTable
$field $elem]"
}
continue
@@ -171,14 +171,14 @@
upvar 1 $arrayName array
if {[lempty $myTable]} { set myTable $table }
+ set vals [::list]
+ set vars [::list]
foreach field $fields {
if {![info exists array($field)]} { continue }
- append vars "$field,"
- append vals "'[quote $array($field)]',"
+ lappend vars "$field"
+ lappend vals "[makeDBFieldValue $myTable $field $array($field)]"
}
- set vals [::string range $vals 0 end-1]
- set vars [::string range $vars 0 end-1]
- return "insert into $myTable ($vars) VALUES ($vals)"
+ return "insert into $myTable ([join $vars {,}]) VALUES ([join $vals
{,}])"
}
#
@@ -194,12 +194,12 @@
protected method build_update_query {arrayName fields {myTable ""}} {
upvar 1 $arrayName array
if {[lempty $myTable]} { set myTable $table }
+ set string [::list]
foreach field $fields {
if {![info exists array($field)]} { continue }
- append string "$field='[quote $array($field)]',"
+ lappend string "$field=[makeDBFieldValue $myTable $field
$array($field)]"
}
- set string [::string range $string 0 end-1]
- return "update $myTable SET $string"
+ return "update $myTable SET [join $string {,}]"
}
#
@@ -235,19 +235,13 @@
## If we're not using multiple keyfields, just return a simple
## where clause.
if {[llength $myKeyfield] < 2} {
- return " WHERE $myKeyfield = '[quote $myKey]'"
+ return " WHERE $myKeyfield = [makeDBFieldValue $table $myKeyfield
$myKey]"
}
# multiple fields, construct it as a where-and
- set first 1
- set req ""
+ set req " WHERE 1 = 1"
foreach field $myKeyfield key $myKey {
- if {$first} {
- append req " WHERE $field='[quote $key]'"
- set first 0
- } else {
- append req " AND $field='[quote $key]'"
- }
+ append req " AND $field=[makeDBFieldValue $table $field $key]"
}
return $req
}
@@ -499,9 +493,40 @@
}
#
+ # update_with_explicit_key - an update where the key is specified
+ # as an argument to the proc rather than being dug out of the array
+ #
+ # this is a kludge until we come up with a better way to
+ # solve the problem of updating a row where we actually
+ # want to change the value of a key field
+ #
+ method update_with_explicit_key {key arrayName args} {
+ table_check $args
+ key_check $myKeyfield $key
+ upvar 1 $arrayName $arrayName $arrayName array
+
+ set fields [::array names array]
+ set req [build_update_query array $fields $myTable]
+ append req [build_key_where_clause $myKeyfield $key]
+
+ set res [exec $req]
+ if {[$res error]} {
+ set errinf [$res errorinfo]
+ $res destroy
+ return -code error "Got '$errinf' executing '$req'"
+ }
+
+ # this doesn't work on postgres, you've got to use cmdRows,
+ # we need to figure out what to do with this
+ set numrows [$res numrows]
+ $res destroy
+ return $numrows
+ }
+
+ #
# insert - a pure insert, without store's somewhat clumsy
# efforts to see if it needs to be an update rather than
- # an insert
+ # an insert -- this shouldn't require fields, it's broken
#
method insert {table arrayName} {
upvar 1 $arrayName $arrayName $arrayName array
@@ -571,6 +596,14 @@
return [string "select count(*) from $myTable"]
}
+ method makeDBFieldValue {table_name field_name val} {
+ return "'[quote $val]'"
+ }
+
+ method registerSpecialField {table_name field_name type} {
+ set specialFields([EMAIL PROTECTED]) $type
+ }
+
##
## These are methods which should be defined by each individual database
## interface class.
@@ -580,6 +613,7 @@
method exec {args} {}
method nextkey {args} {}
method lastkey {args} {}
+ method now {} {}
##
## Functions to get and set public variables.
@@ -596,6 +630,8 @@
method host {{string ""}} { configure_variable host $string }
method port {{string ""}} { configure_variable port $string }
+ protected variable specialFields
+
public variable interface ""
public variable errorinfo ""
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]