Posted to tcl by colin at Tue Jan 31 01:52:47 GMT 2012view pretty
oo::class create ::tdbc::skeleton::resultset { # columns - a list of the names of the columns in the result. method columns {} { } # nextdict variableName - store the next row of the result set in the given variable # in caller's scope, in the form of a dictionary that maps column names to values. method nextdict {variableName} { } # nextlist variableName - store the next row of the result set in the given variable # in caller's scope, in the form of a list of cells. method nextlist {variableName} { } # rowcount - count of rows affected by the statement, # or -1 if the count of rows has not been determined. method rowcount {} { } superclass tdbc::resultset constructor {statement args} { # Constructor accepts a statement and an optional dictionary of substituted parameters # execute the statement against the database. # If the dictionary is not supplied, then the default is to get params # from variables in the caller's scope). next if {[llength $args] == 1} { set args [lindex $args 0] } uplevel 1 [list {*}[namespace code {my init}] $statement {*}$args] } } oo::class create tdbc::skeleton::statement { method params {} { # return a description of the names and expected data types of the parameters of [self] # MUST be a dictionary whose keys are the names of the parameters, values dictionaries. # The keys of the subdictionaries MUST include: # name: # type: # precision: # scale: # nullable: # direction: {in out inout} variable params set result $params foreach {n v} $result { if {![llength $v]} { # there is no value for this parameter - calculate it } } return $result } method paramtype {name args} { set args [lassign $args type] if {$type in {in out inout}} { set direction $type set args [lassign [$args type]] } else { set direction inout } if {$type ni {bigint binary bit char date decimal double float integer longvarbinary longvarchar numeric real time timestamp smallint tinyint varbinary varchar}} { error "$type invalid" } set precision 0; set scale 0 lassign $args precision scale # now do something with name, type, direction, precision and scale # Implementors of database APIs SHOULD make every effort to do appropriate type introspection # so that programmers can avoid needing to include explicit type information in their SQL statements. } superclass tdbc::statement constructor {connection sqlcode args} { next if {[llength $args] == 1} { set args [lindex $args 0] } variable params {} variable sql $sqlcode foreach token [::tdbc::tokenize $sqlcode] { if {[string index $token 0] in {$ : @}} { dict set params [string range $token 1 end] {} } } } } oo::class create tdbc::skeleton { # Transactions method starttransaction {} { # Begins an atomic transaction on the database. # If the underlying database does not implement atomic transactions or rollback, # the starttransaction subcommand MUST throw an error reporting the fact. # If the underlying database does not implement nested transactions, # a starttransaction command that is executed when there is a transaction already in progress # (started, but neither committed nor rolled back) MUST result in an error. error "[info object class [self]] does not support transactions" } method commit {} { # Commits a transaction to the database, making the changes durable. } method rollback {} { # Rolls back a transaction against the database, cancelling any changes made during the transaction. } # Statements method preparecall {call} { # Some database interfaces have a different API to stored procedures than to ordinary SQL statements. # These databases may need a separate type of statement object from the one that implements ordinary # statements. # This object can be managed as a statement owned by the connection by using the preparecall method } method statementCreate {name self sqlcode} { tdbc::skeleton::statement create $name [self] $sqlcode } # Structure and Configuration method configure {args} { # args are of the form -option value .... # -encoding name # -isolation {readuncommitted readcommitted repeatableread serializable readonly} # -timeout ms # -readonly boolean } destructor { # dismiss the connection to the database and clean up associated system resources # If there is an uncommitted transaction, it SHOULD be rolled back. # Any handles to other objects associated with the database SHOULD become invalid. } superclass tdbc::connection constructor {args} { next # perform connection and configuration } }