annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/tdbcodbc1.1.5/tdbcodbc.tcl @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 # tdbcodbc.tcl --
jpayne@69 2 #
jpayne@69 3 # Class definitions and Tcl-level methods for the tdbc::odbc bridge.
jpayne@69 4 #
jpayne@69 5 # Copyright (c) 2008 by Kevin B. Kenny
jpayne@69 6 # See the file "license.terms" for information on usage and redistribution
jpayne@69 7 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
jpayne@69 8 #
jpayne@69 9 # RCS: @(#) $Id: tdbcodbc.tcl,v 1.47 2008/02/27 02:08:27 kennykb Exp $
jpayne@69 10 #
jpayne@69 11 #------------------------------------------------------------------------------
jpayne@69 12
jpayne@69 13 package require tdbc
jpayne@69 14
jpayne@69 15 ::namespace eval ::tdbc::odbc {
jpayne@69 16
jpayne@69 17 namespace export connection datasources drivers
jpayne@69 18
jpayne@69 19 # Data types that are predefined in ODBC
jpayne@69 20
jpayne@69 21 variable sqltypes [dict create \
jpayne@69 22 1 char \
jpayne@69 23 2 numeric \
jpayne@69 24 3 decimal \
jpayne@69 25 4 integer \
jpayne@69 26 5 smallint \
jpayne@69 27 6 float \
jpayne@69 28 7 real \
jpayne@69 29 8 double \
jpayne@69 30 9 datetime \
jpayne@69 31 12 varchar \
jpayne@69 32 91 date \
jpayne@69 33 92 time \
jpayne@69 34 93 timestamp \
jpayne@69 35 -1 longvarchar \
jpayne@69 36 -2 binary \
jpayne@69 37 -3 varbinary \
jpayne@69 38 -4 longvarbinary \
jpayne@69 39 -5 bigint \
jpayne@69 40 -6 tinyint \
jpayne@69 41 -7 bit \
jpayne@69 42 -8 wchar \
jpayne@69 43 -9 wvarchar \
jpayne@69 44 -10 wlongvarchar \
jpayne@69 45 -11 guid]
jpayne@69 46 }
jpayne@69 47
jpayne@69 48 #------------------------------------------------------------------------------
jpayne@69 49 #
jpayne@69 50 # tdbc::odbc::connection --
jpayne@69 51 #
jpayne@69 52 # Class representing a connection to a database through ODBC.
jpayne@69 53 #
jpayne@69 54 #-------------------------------------------------------------------------------
jpayne@69 55
jpayne@69 56 ::oo::class create ::tdbc::odbc::connection {
jpayne@69 57
jpayne@69 58 superclass ::tdbc::connection
jpayne@69 59
jpayne@69 60 variable statementSeq typemap
jpayne@69 61
jpayne@69 62 # The constructor is written in C. It takes the connection string
jpayne@69 63 # as its argument It sets up a namespace to hold the statements
jpayne@69 64 # associated with the connection, and then delegates to the 'init'
jpayne@69 65 # method (written in C) to do the actual work of attaching to the
jpayne@69 66 # database. When that comes back, it sets up a statement to query
jpayne@69 67 # the support types, makes a dictionary to enumerate them, and
jpayne@69 68 # calls back to set a flag if WVARCHAR is seen (If WVARCHAR is
jpayne@69 69 # seen, the database supports Unicode.)
jpayne@69 70
jpayne@69 71 # The 'statementCreate' method forwards to the constructor of the
jpayne@69 72 # statement class
jpayne@69 73
jpayne@69 74 forward statementCreate ::tdbc::odbc::statement create
jpayne@69 75
jpayne@69 76 # The 'tables' method returns a dictionary describing the tables
jpayne@69 77 # in the database
jpayne@69 78
jpayne@69 79 method tables {{pattern %}} {
jpayne@69 80 set stmt [::tdbc::odbc::tablesStatement create \
jpayne@69 81 Stmt::[incr statementSeq] [self] $pattern]
jpayne@69 82 set status [catch {
jpayne@69 83 set retval {}
jpayne@69 84 $stmt foreach -as dicts row {
jpayne@69 85 if {[dict exists $row TABLE_NAME]} {
jpayne@69 86 dict set retval [dict get $row TABLE_NAME] $row
jpayne@69 87 }
jpayne@69 88 }
jpayne@69 89 set retval
jpayne@69 90 } result options]
jpayne@69 91 catch {rename $stmt {}}
jpayne@69 92 return -level 0 -options $options $result
jpayne@69 93 }
jpayne@69 94
jpayne@69 95 # The 'columns' method returns a dictionary describing the tables
jpayne@69 96 # in the database
jpayne@69 97
jpayne@69 98 method columns {table {pattern %}} {
jpayne@69 99 # Make sure that the type map is initialized
jpayne@69 100 my typemap
jpayne@69 101
jpayne@69 102 # Query the columns from the database
jpayne@69 103
jpayne@69 104 set stmt [::tdbc::odbc::columnsStatement create \
jpayne@69 105 Stmt::[incr statementSeq] [self] $table $pattern]
jpayne@69 106 set status [catch {
jpayne@69 107 set retval {}
jpayne@69 108 $stmt foreach -as dicts origrow {
jpayne@69 109
jpayne@69 110 # Map the type, precision, scale and nullable indicators
jpayne@69 111 # to tdbc's notation
jpayne@69 112
jpayne@69 113 set row {}
jpayne@69 114 dict for {key value} $origrow {
jpayne@69 115 dict set row [string tolower $key] $value
jpayne@69 116 }
jpayne@69 117 if {[dict exists $row column_name]} {
jpayne@69 118 if {[dict exists $typemap \
jpayne@69 119 [dict get $row data_type]]} {
jpayne@69 120 dict set row type \
jpayne@69 121 [dict get $typemap \
jpayne@69 122 [dict get $row data_type]]
jpayne@69 123 } else {
jpayne@69 124 dict set row type [dict get $row type_name]
jpayne@69 125 }
jpayne@69 126 if {[dict exists $row column_size]} {
jpayne@69 127 dict set row precision \
jpayne@69 128 [dict get $row column_size]
jpayne@69 129 }
jpayne@69 130 if {[dict exists $row decimal_digits]} {
jpayne@69 131 dict set row scale \
jpayne@69 132 [dict get $row decimal_digits]
jpayne@69 133 }
jpayne@69 134 if {![dict exists $row nullable]} {
jpayne@69 135 dict set row nullable \
jpayne@69 136 [expr {!![string trim [dict get $row is_nullable]]}]
jpayne@69 137 }
jpayne@69 138 dict set retval [dict get $row column_name] $row
jpayne@69 139 }
jpayne@69 140 }
jpayne@69 141 set retval
jpayne@69 142 } result options]
jpayne@69 143 catch {rename $stmt {}}
jpayne@69 144 return -level 0 -options $options $result
jpayne@69 145 }
jpayne@69 146
jpayne@69 147 # The 'primarykeys' method returns a dictionary describing the primary
jpayne@69 148 # keys of a table
jpayne@69 149
jpayne@69 150 method primarykeys {tableName} {
jpayne@69 151 set stmt [::tdbc::odbc::primarykeysStatement create \
jpayne@69 152 Stmt::[incr statementSeq] [self] $tableName]
jpayne@69 153 set status [catch {
jpayne@69 154 set retval {}
jpayne@69 155 $stmt foreach -as dicts row {
jpayne@69 156 foreach {odbcKey tdbcKey} {
jpayne@69 157 TABLE_CAT tableCatalog
jpayne@69 158 TABLE_SCHEM tableSchema
jpayne@69 159 TABLE_NAME tableName
jpayne@69 160 COLUMN_NAME columnName
jpayne@69 161 KEY_SEQ ordinalPosition
jpayne@69 162 PK_NAME constraintName
jpayne@69 163 } {
jpayne@69 164 if {[dict exists $row $odbcKey]} {
jpayne@69 165 dict set row $tdbcKey [dict get $row $odbcKey]
jpayne@69 166 dict unset row $odbcKey
jpayne@69 167 }
jpayne@69 168 }
jpayne@69 169 lappend retval $row
jpayne@69 170 }
jpayne@69 171 set retval
jpayne@69 172 } result options]
jpayne@69 173 catch {rename $stmt {}}
jpayne@69 174 return -level 0 -options $options $result
jpayne@69 175 }
jpayne@69 176
jpayne@69 177 # The 'foreignkeys' method returns a dictionary describing the foreign
jpayne@69 178 # keys of a table
jpayne@69 179
jpayne@69 180 method foreignkeys {args} {
jpayne@69 181 set stmt [::tdbc::odbc::foreignkeysStatement create \
jpayne@69 182 Stmt::[incr statementSeq] [self] {*}$args]
jpayne@69 183 set status [catch {
jpayne@69 184 set fkseq 0
jpayne@69 185 set retval {}
jpayne@69 186 $stmt foreach -as dicts row {
jpayne@69 187 foreach {odbcKey tdbcKey} {
jpayne@69 188 PKTABLE_CAT primaryCatalog
jpayne@69 189 PKTABLE_SCHEM primarySchema
jpayne@69 190 PKTABLE_NAME primaryTable
jpayne@69 191 PKCOLUMN_NAME primaryColumn
jpayne@69 192 FKTABLE_CAT foreignCatalog
jpayne@69 193 FKTABLE_SCHEM foreignSchema
jpayne@69 194 FKTABLE_NAME foreignTable
jpayne@69 195 FKCOLUMN_NAME foreignColumn
jpayne@69 196 UPDATE_RULE updateRule
jpayne@69 197 DELETE_RULE deleteRule
jpayne@69 198 DEFERRABILITY deferrable
jpayne@69 199 KEY_SEQ ordinalPosition
jpayne@69 200 FK_NAME foreignConstraintName
jpayne@69 201 } {
jpayne@69 202 if {[dict exists $row $odbcKey]} {
jpayne@69 203 dict set row $tdbcKey [dict get $row $odbcKey]
jpayne@69 204 dict unset row $odbcKey
jpayne@69 205 }
jpayne@69 206 }
jpayne@69 207 # Horrible kludge: If the driver doesn't report FK_NAME,
jpayne@69 208 # make one up.
jpayne@69 209 if {![dict exists $row foreignConstraintName]} {
jpayne@69 210 if {![dict exists $row ordinalPosition]
jpayne@69 211 || [dict get $row ordinalPosition] == 1} {
jpayne@69 212 set fkname ?[dict get $row foreignTable]?[incr fkseq]
jpayne@69 213 }
jpayne@69 214 dict set row foreignConstraintName $fkname
jpayne@69 215 }
jpayne@69 216 lappend retval $row
jpayne@69 217 }
jpayne@69 218 set retval
jpayne@69 219 } result options]
jpayne@69 220 catch {rename $stmt {}}
jpayne@69 221 return -level 0 -options $options $result
jpayne@69 222 }
jpayne@69 223
jpayne@69 224 # The 'evaldirect' evaluates driver-native SQL code without preparing it,
jpayne@69 225 # and returns a list of dicts (similar to '$connection allrows -as dicts').
jpayne@69 226
jpayne@69 227 method evaldirect {sqlStatement} {
jpayne@69 228 set stmt [::tdbc::odbc::evaldirectStatement create \
jpayne@69 229 Stmt::[incr statementSeq] [self] $sqlStatement]
jpayne@69 230 set status [catch {
jpayne@69 231 $stmt allrows -as dicts
jpayne@69 232 } result options]
jpayne@69 233 catch {rename $stmt {}}
jpayne@69 234 return -level 0 -options $options $result
jpayne@69 235 }
jpayne@69 236
jpayne@69 237 # The 'prepareCall' method gives a portable interface to prepare
jpayne@69 238 # calls to stored procedures. It delegates to 'prepare' to do the
jpayne@69 239 # actual work.
jpayne@69 240
jpayne@69 241 method preparecall {call} {
jpayne@69 242
jpayne@69 243 regexp {^[[:space:]]*(?:([A-Za-z_][A-Za-z_0-9]*)[[:space:]]*=)?(.*)} \
jpayne@69 244 $call -> varName rest
jpayne@69 245 if {$varName eq {}} {
jpayne@69 246 my prepare \\{CALL $rest\\}
jpayne@69 247 } else {
jpayne@69 248 my prepare \\{:$varName=CALL $rest\\}
jpayne@69 249 }
jpayne@69 250
jpayne@69 251 if 0 {
jpayne@69 252 # Kevin thinks this is going to be
jpayne@69 253
jpayne@69 254 if {![regexp -expanded {
jpayne@69 255 ^\s* # leading whitespace
jpayne@69 256 (?::([[:alpha:]_][[:alnum:]_]*)\s*=\s*) # possible variable name
jpayne@69 257 (?:(?:([[:alpha:]_][[:alnum:]_]*)\s*[.]\s*)? # catalog
jpayne@69 258 ([[:alpha:]_][[:alnum:]_]*)\s*[.]\s*)? # schema
jpayne@69 259 ([[:alpha:]_][[:alnum:]_]*)\s* # procedure
jpayne@69 260 (.*)$ # argument list
jpayne@69 261 } $call -> varName catalog schema procedure arglist]} {
jpayne@69 262 return -code error \
jpayne@69 263 -errorCode [list TDBC \
jpayne@69 264 SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION \
jpayne@69 265 42000 ODBC -1] \
jpayne@69 266 "Syntax error in stored procedure call"
jpayne@69 267 } else {
jpayne@69 268 my PrepareCall $varName $catalog $schema $procedure $arglist
jpayne@69 269 }
jpayne@69 270
jpayne@69 271 # at least if making all parameters 'inout' doesn't work.
jpayne@69 272
jpayne@69 273 }
jpayne@69 274
jpayne@69 275 }
jpayne@69 276
jpayne@69 277 # The 'typemap' method returns the type map
jpayne@69 278
jpayne@69 279 method typemap {} {
jpayne@69 280 if {![info exists typemap]} {
jpayne@69 281 set typemap $::tdbc::odbc::sqltypes
jpayne@69 282 set typesStmt [tdbc::odbc::typesStatement new [self]]
jpayne@69 283 $typesStmt foreach row {
jpayne@69 284 set typeNum [dict get $row DATA_TYPE]
jpayne@69 285 if {![dict exists $typemap $typeNum]} {
jpayne@69 286 dict set typemap $typeNum [string tolower \
jpayne@69 287 [dict get $row TYPE_NAME]]
jpayne@69 288 }
jpayne@69 289 switch -exact -- $typeNum {
jpayne@69 290 -9 {
jpayne@69 291 [self] HasWvarchar 1
jpayne@69 292 }
jpayne@69 293 -5 {
jpayne@69 294 [self] HasBigint 1
jpayne@69 295 }
jpayne@69 296 }
jpayne@69 297 }
jpayne@69 298 rename $typesStmt {}
jpayne@69 299 }
jpayne@69 300 return $typemap
jpayne@69 301 }
jpayne@69 302
jpayne@69 303 # The 'begintransaction', 'commit' and 'rollback' methods are
jpayne@69 304 # implemented in C.
jpayne@69 305
jpayne@69 306 }
jpayne@69 307
jpayne@69 308 #-------------------------------------------------------------------------------
jpayne@69 309 #
jpayne@69 310 # tdbc::odbc::statement --
jpayne@69 311 #
jpayne@69 312 # The class 'tdbc::odbc::statement' models one statement against a
jpayne@69 313 # database accessed through an ODBC connection
jpayne@69 314 #
jpayne@69 315 #-------------------------------------------------------------------------------
jpayne@69 316
jpayne@69 317 ::oo::class create ::tdbc::odbc::statement {
jpayne@69 318
jpayne@69 319 superclass ::tdbc::statement
jpayne@69 320
jpayne@69 321 # The constructor is implemented in C. It accepts the handle to
jpayne@69 322 # the connection and the SQL code for the statement to prepare.
jpayne@69 323 # It creates a subordinate namespace to hold the statement's
jpayne@69 324 # active result sets, and then delegates to the 'init' method,
jpayne@69 325 # written in C, to do the actual work of preparing the statement.
jpayne@69 326
jpayne@69 327 # The 'resultSetCreate' method forwards to the result set constructor
jpayne@69 328
jpayne@69 329 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 330
jpayne@69 331 # The 'params' method describes the parameters to the statement
jpayne@69 332
jpayne@69 333 method params {} {
jpayne@69 334 set typemap [[my connection] typemap]
jpayne@69 335 set result {}
jpayne@69 336 foreach {name flags typeNum precision scale nullable} [my ParamList] {
jpayne@69 337 set lst [dict create \
jpayne@69 338 name $name \
jpayne@69 339 direction [lindex {unknown in out inout} \
jpayne@69 340 [expr {($flags & 0x06) >> 1}]] \
jpayne@69 341 type [dict get $typemap $typeNum] \
jpayne@69 342 precision $precision \
jpayne@69 343 scale $scale]
jpayne@69 344 if {$nullable in {0 1}} {
jpayne@69 345 dict set list nullable $nullable
jpayne@69 346 }
jpayne@69 347 dict set result $name $lst
jpayne@69 348 }
jpayne@69 349 return $result
jpayne@69 350 }
jpayne@69 351
jpayne@69 352 # Methods implemented in C:
jpayne@69 353 # init statement ?dictionary?
jpayne@69 354 # Does the heavy lifting for the constructor
jpayne@69 355 # connection
jpayne@69 356 # Returns the connection handle to which this statement belongs
jpayne@69 357 # paramtype paramname ?direction? type ?precision ?scale??
jpayne@69 358 # Declares the type of a parameter in the statement
jpayne@69 359
jpayne@69 360 }
jpayne@69 361
jpayne@69 362 #------------------------------------------------------------------------------
jpayne@69 363 #
jpayne@69 364 # tdbc::odbc::tablesStatement --
jpayne@69 365 #
jpayne@69 366 # The class 'tdbc::odbc::tablesStatement' represents the special
jpayne@69 367 # statement that queries the tables in a database through an ODBC
jpayne@69 368 # connection.
jpayne@69 369 #
jpayne@69 370 #------------------------------------------------------------------------------
jpayne@69 371
jpayne@69 372 oo::class create ::tdbc::odbc::tablesStatement {
jpayne@69 373
jpayne@69 374 superclass ::tdbc::statement
jpayne@69 375
jpayne@69 376 # The constructor is written in C. It accepts the handle to the
jpayne@69 377 # connection and a pattern to match table names. It works in all
jpayne@69 378 # ways like the constructor of the 'statement' class except that
jpayne@69 379 # its 'init' method sets up to enumerate tables and not run a SQL
jpayne@69 380 # query.
jpayne@69 381
jpayne@69 382 # The 'resultSetCreate' method forwards to the result set constructor
jpayne@69 383
jpayne@69 384 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 385
jpayne@69 386 }
jpayne@69 387
jpayne@69 388 #------------------------------------------------------------------------------
jpayne@69 389 #
jpayne@69 390 # tdbc::odbc::columnsStatement --
jpayne@69 391 #
jpayne@69 392 # The class 'tdbc::odbc::tablesStatement' represents the special
jpayne@69 393 # statement that queries the columns of a table or view
jpayne@69 394 # in a database through an ODBC connection.
jpayne@69 395 #
jpayne@69 396 #------------------------------------------------------------------------------
jpayne@69 397
jpayne@69 398 oo::class create ::tdbc::odbc::columnsStatement {
jpayne@69 399
jpayne@69 400 superclass ::tdbc::statement
jpayne@69 401
jpayne@69 402 # The constructor is written in C. It accepts the handle to the
jpayne@69 403 # connection, a table name, and a pattern to match column
jpayne@69 404 # names. It works in all ways like the constructor of the
jpayne@69 405 # 'statement' class except that its 'init' method sets up to
jpayne@69 406 # enumerate tables and not run a SQL query.
jpayne@69 407
jpayne@69 408 # The 'resultSetCreate' class forwards to the constructor of the
jpayne@69 409 # result set
jpayne@69 410
jpayne@69 411 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 412
jpayne@69 413 }
jpayne@69 414
jpayne@69 415 #------------------------------------------------------------------------------
jpayne@69 416 #
jpayne@69 417 # tdbc::odbc::primarykeysStatement --
jpayne@69 418 #
jpayne@69 419 # The class 'tdbc::odbc::primarykeysStatement' represents the special
jpayne@69 420 # statement that queries the primary keys on a table through an ODBC
jpayne@69 421 # connection.
jpayne@69 422 #
jpayne@69 423 #------------------------------------------------------------------------------
jpayne@69 424
jpayne@69 425 oo::class create ::tdbc::odbc::primarykeysStatement {
jpayne@69 426
jpayne@69 427 superclass ::tdbc::statement
jpayne@69 428
jpayne@69 429 # The constructor is written in C. It accepts the handle to the
jpayne@69 430 # connection and a table name. It works in all
jpayne@69 431 # ways like the constructor of the 'statement' class except that
jpayne@69 432 # its 'init' method sets up to enumerate primary keys and not run a SQL
jpayne@69 433 # query.
jpayne@69 434
jpayne@69 435 # The 'resultSetCreate' method forwards to the result set constructor
jpayne@69 436
jpayne@69 437 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 438
jpayne@69 439 }
jpayne@69 440
jpayne@69 441 #------------------------------------------------------------------------------
jpayne@69 442 #
jpayne@69 443 # tdbc::odbc::foreignkeysStatement --
jpayne@69 444 #
jpayne@69 445 # The class 'tdbc::odbc::foreignkeysStatement' represents the special
jpayne@69 446 # statement that queries the foreign keys on a table through an ODBC
jpayne@69 447 # connection.
jpayne@69 448 #
jpayne@69 449 #------------------------------------------------------------------------------
jpayne@69 450
jpayne@69 451 oo::class create ::tdbc::odbc::foreignkeysStatement {
jpayne@69 452
jpayne@69 453 superclass ::tdbc::statement
jpayne@69 454
jpayne@69 455 # The constructor is written in C. It accepts the handle to the
jpayne@69 456 # connection and the -primary and -foreign options. It works in all
jpayne@69 457 # ways like the constructor of the 'statement' class except that
jpayne@69 458 # its 'init' method sets up to enumerate foreign keys and not run a SQL
jpayne@69 459 # query.
jpayne@69 460
jpayne@69 461 # The 'resultSetCreate' method forwards to the result set constructor
jpayne@69 462
jpayne@69 463 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 464
jpayne@69 465 }
jpayne@69 466
jpayne@69 467 #------------------------------------------------------------------------------
jpayne@69 468 #
jpayne@69 469 # tdbc::odbc::evaldirectStatement --
jpayne@69 470 #
jpayne@69 471 # The class 'tdbc::odbc::evaldirectStatement' provides a mechanism to
jpayne@69 472 # execute driver-name SQL code through an ODBC connection. The SQL code
jpayne@69 473 # is not prepared and no tokenization or variable substitution is done.
jpayne@69 474 #
jpayne@69 475 #------------------------------------------------------------------------------
jpayne@69 476
jpayne@69 477 oo::class create ::tdbc::odbc::evaldirectStatement {
jpayne@69 478
jpayne@69 479 superclass ::tdbc::statement
jpayne@69 480
jpayne@69 481 # The constructor is written in C. It accepts the handle to the
jpayne@69 482 # connection and a SQL statement. It works in all
jpayne@69 483 # ways like the constructor of the 'statement' class except that
jpayne@69 484 # its 'init' method does not tokenize or prepare the SQL statement, and
jpayne@69 485 # sets up to run the SQL query without performing variable substitution.
jpayne@69 486
jpayne@69 487 # The 'resultSetCreate' method forwards to the result set constructor
jpayne@69 488
jpayne@69 489 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 490
jpayne@69 491 }
jpayne@69 492
jpayne@69 493 #------------------------------------------------------------------------------
jpayne@69 494 #
jpayne@69 495 # tdbc::odbc::typesStatement --
jpayne@69 496 #
jpayne@69 497 # The class 'tdbc::odbc::typesStatement' represents the special
jpayne@69 498 # statement that queries the types available in a database through
jpayne@69 499 # an ODBC connection.
jpayne@69 500 #
jpayne@69 501 #------------------------------------------------------------------------------
jpayne@69 502
jpayne@69 503
jpayne@69 504 oo::class create ::tdbc::odbc::typesStatement {
jpayne@69 505
jpayne@69 506 superclass ::tdbc::statement
jpayne@69 507
jpayne@69 508 # The constructor is written in C. It accepts the handle to the
jpayne@69 509 # connection, and (optionally) a data type number. It works in all
jpayne@69 510 # ways like the constructor of the 'statement' class except that
jpayne@69 511 # its 'init' method sets up to enumerate types and not run a SQL
jpayne@69 512 # query.
jpayne@69 513
jpayne@69 514 # The 'resultSetCreate' method forwards to the constructor of result sets
jpayne@69 515
jpayne@69 516 forward resultSetCreate ::tdbc::odbc::resultset create
jpayne@69 517
jpayne@69 518 # The C code contains a variant implementation of the 'init' method.
jpayne@69 519
jpayne@69 520 }
jpayne@69 521
jpayne@69 522 #------------------------------------------------------------------------------
jpayne@69 523 #
jpayne@69 524 # tdbc::odbc::resultset --
jpayne@69 525 #
jpayne@69 526 # The class 'tdbc::odbc::resultset' models the result set that is
jpayne@69 527 # produced by executing a statement against an ODBC database.
jpayne@69 528 #
jpayne@69 529 #------------------------------------------------------------------------------
jpayne@69 530
jpayne@69 531 ::oo::class create ::tdbc::odbc::resultset {
jpayne@69 532
jpayne@69 533 superclass ::tdbc::resultset
jpayne@69 534
jpayne@69 535 # Methods implemented in C include:
jpayne@69 536
jpayne@69 537 # constructor statement ?dictionary?
jpayne@69 538 # -- Executes the statement against the database, optionally providing
jpayne@69 539 # a dictionary of substituted parameters (default is to get params
jpayne@69 540 # from variables in the caller's scope).
jpayne@69 541 # columns
jpayne@69 542 # -- Returns a list of the names of the columns in the result.
jpayne@69 543 # nextdict
jpayne@69 544 # -- Stores the next row of the result set in the given variable in
jpayne@69 545 # the caller's scope as a dictionary whose keys are
jpayne@69 546 # column names and whose values are column values.
jpayne@69 547 # nextlist
jpayne@69 548 # -- Stores the next row of the result set in the given variable in
jpayne@69 549 # the caller's scope as a list of cells.
jpayne@69 550 # rowcount
jpayne@69 551 # -- Returns a count of rows affected by the statement, or -1
jpayne@69 552 # if the count of rows has not been determined.
jpayne@69 553
jpayne@69 554 }