annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/tdbcodbc1.1.5/tdbcodbc.tcl @ 68:5028fdace37b

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