"Fossies" - the Fresh Open Source Software Archive

Member "install-tl-20200916/tlpkg/tltcl/lib/tcl8/8.6/tdbc/sqlite3-1.1.1.tm" (17 Mar 2020, 19299 Bytes) of package /windows/misc/install-tl.zip:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # tdbcsqlite3.tcl --
    2 #
    3 #    SQLite3 database driver for TDBC
    4 #
    5 # Copyright (c) 2008 by Kevin B. Kenny.
    6 # See the file "license.terms" for information on usage and redistribution
    7 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    8 #
    9 # RCS: @(#) $Id: tdbcodbc.tcl,v 1.47 2008/02/27 02:08:27 kennykb Exp $
   10 #
   11 #------------------------------------------------------------------------------
   12 
   13 package require tdbc
   14 package require sqlite3
   15 
   16 package provide tdbc::sqlite3 1.1.1
   17 
   18 namespace eval tdbc::sqlite3 {
   19     namespace export connection
   20 }
   21 
   22 #------------------------------------------------------------------------------
   23 #
   24 # tdbc::sqlite3::connection --
   25 #
   26 #	Class representing a SQLite3 database connection
   27 #
   28 #------------------------------------------------------------------------------
   29 
   30 ::oo::class create ::tdbc::sqlite3::connection {
   31 
   32     superclass ::tdbc::connection
   33 
   34     variable timeout
   35 
   36     # The constructor accepts a database name and opens the database.
   37 
   38     constructor {databaseName args} {
   39 	set timeout 0
   40 	if {[llength $args] % 2 != 0} {
   41 	    set cmd [lrange [info level 0] 0 end-[llength $args]]
   42 	    return -code error \
   43 		-errorcode {TDBC GENERAL_ERROR HY000 SQLITE3 WRONGNUMARGS} \
   44 		"wrong # args, should be \"$cmd ?-option value?...\""
   45 	}
   46 	next
   47 	sqlite3 [namespace current]::db $databaseName
   48 	if {[llength $args] > 0} {
   49 	    my configure {*}$args
   50 	}
   51 	db nullvalue \ufffd
   52     }
   53 
   54     # The 'statementCreate' method forwards to the constructor of the
   55     # statement class
   56 
   57     forward statementCreate ::tdbc::sqlite3::statement create
   58 
   59     # The 'configure' method queries and sets options to the database
   60 
   61     method configure args {
   62 	if {[llength $args] == 0} {
   63 
   64 	    # Query all configuration options
   65 
   66 	    set result {-encoding utf-8}
   67 	    lappend result -isolation
   68 	    if {[db onecolumn {PRAGMA read_uncommitted}]} {
   69 		lappend result readuncommitted
   70 	    } else {
   71 		lappend result serializable
   72 	    }
   73 	    lappend result -readonly 0
   74 	    lappend result -timeout $timeout
   75 	    return $result
   76 
   77 	} elseif {[llength $args] == 1} {
   78 
   79 	    # Query a single option
   80 
   81 	    set option [lindex $args 0]
   82 	    switch -exact -- $option {
   83 		-e - -en - -enc - -enco - -encod - -encodi - -encodin -
   84 		-encoding {
   85 		    return utf-8
   86 		}
   87 		-i - -is - -iso - -isol - -isola - -isolat - -isolati -
   88 		-isolatio - -isolation {
   89 		    if {[db onecolumn {PRAGMA read_uncommitted}]} {
   90 			return readuncommitted
   91 		    } else {
   92 			return serializable
   93 		    }
   94 		}
   95 		-r - -re - -rea - -read - -reado - -readon - -readonl -
   96 		-readonly {
   97 		    return 0
   98 		}
   99 		-t - -ti - -tim - -time - -timeo - -timeou - -timeout {
  100 		    return $timeout
  101 		}
  102 		default {
  103 		    return -code error \
  104 			-errorcode [list TDBC GENERAL_ERROR HY000 SQLITE3 \
  105 					BADOPTION $option] \
  106 			"bad option \"$option\": must be\
  107                          -encoding, -isolation, -readonly or -timeout"
  108 
  109 		}
  110 	    }
  111 
  112 	} elseif {[llength $args] % 2 != 0} {
  113 
  114 	    # Syntax error
  115 
  116 	    set cmd [lrange [info level 0] 0 end-[llength $args]]
  117 	    return -code error \
  118 		-errorcode [list TDBC GENERAL_ERROR HY000 \
  119 				SQLITE3 WRONGNUMARGS] \
  120 		"wrong # args, should be \" $cmd ?-option value?...\""
  121 	}
  122 
  123 	# Set one or more options
  124 
  125 	foreach {option value} $args {
  126 	    switch -exact -- $option {
  127 		-e - -en - -enc - -enco - -encod - -encodi - -encodin -
  128 		-encoding {
  129 		    if {$value ne {utf-8}} {
  130 			return -code error \
  131 			    -errorcode [list TDBC FEATURE_NOT_SUPPORTED 0A000 \
  132 					    SQLITE3 ENCODING] \
  133 			    "-encoding not supported. SQLite3 is always \
  134                              Unicode."
  135 		    }
  136 		}
  137 		-i - -is - -iso - -isol - -isola - -isolat - -isolati -
  138 		-isolatio - -isolation {
  139 		    switch -exact -- $value {
  140 			readu - readun - readunc - readunco - readuncom -
  141 			readuncomm - readuncommi - readuncommit -
  142 			readuncommitt - readuncommitte - readuncommitted {
  143 			    db eval {PRAGMA read_uncommitted = 1}
  144 			}
  145 			readc - readco - readcom - readcomm - readcommi -
  146 			readcommit - readcommitt - readcommitte -
  147 			readcommitted -
  148 			rep - repe - repea - repeat - repeata - repeatab -
  149 			repeatabl - repeatable - repeatabler - repeatablere -
  150 			repeatablerea - repeatablread -
  151 			s - se - ser - seri - seria - serial - seriali -
  152 			serializ - serializa - serializab - serializabl -
  153 			serializable -
  154 			reado - readon - readonl - readonly {
  155 			    db eval {PRAGMA read_uncommitted = 0}
  156 			}
  157 			default {
  158 			    return -code error \
  159 				-errorcode [list TDBC GENERAL_ERROR HY000 \
  160 						SQLITE3 BADISOLATION $value] \
  161 				"bad isolation level \"$value\":\
  162                                 should be readuncommitted, readcommitted,\
  163                                 repeatableread, serializable, or readonly"
  164 			}
  165 		    }
  166 		}
  167 		-r - -re - -rea - -read - -reado - -readon - -readonl -
  168 		-readonly {
  169 		    if {$value} {
  170 			return -code error \
  171 			    -errorcode [list TDBC FEATURE_NOT_SUPPORTED 0A000 \
  172 					    SQLITE3 READONLY] \
  173 			    "SQLite3's Tcl API does not support read-only\
  174                              access"
  175 		    }
  176 		}
  177 		-t - -ti - -tim - -time - -timeo - -timeou - -timeout {
  178 		    if {![string is integer $value]} {
  179 			return -code error \
  180 			    -errorcode [list TDBC DATA_EXCEPTION 22018 \
  181 					    SQLITE3 $value] \
  182 			    "expected integer but got \"$value\""
  183 		    }
  184 		    db timeout $value
  185 		    set timeout $value
  186 		}
  187 		default {
  188 		    return -code error \
  189 			-errorcode [list TDBC GENERAL_ERROR HY000 \
  190 					SQLITE3 BADOPTION $value] \
  191 			"bad option \"$option\": must be\
  192                          -encoding, -isolation, -readonly or -timeout"
  193 
  194 		}
  195 	    }
  196 	}
  197 	return
  198     }
  199 
  200     # The 'tables' method introspects on the tables in the database.
  201 
  202     method tables {{pattern %}} {
  203 	set retval {}
  204 	my foreach row {
  205 	    SELECT * from sqlite_master
  206 	    WHERE type IN ('table', 'view')
  207 	    AND name LIKE :pattern
  208 	} {
  209 	    dict set row name [string tolower [dict get $row name]]
  210 	    dict set retval [dict get $row name] $row
  211 	}
  212 	return $retval
  213     }
  214 
  215     # The 'columns' method introspects on columns of a table.
  216 
  217     method columns {table {pattern %}} {
  218 	regsub -all ' $table '' table
  219 	set retval {}
  220 	set pattern [string map [list \
  221 				     * {[*]} \
  222 				     ? {[?]} \
  223 				     \[ \\\[ \
  224 				     \] \\\[ \
  225 				     _ ? \
  226 				     % *] [string tolower $pattern]]
  227 	my foreach origrow "PRAGMA table_info('$table')" {
  228 	    set row {}
  229 	    dict for {key value} $origrow {
  230 		dict set row [string tolower $key] $value
  231 	    }
  232 	    dict set row name [string tolower [dict get $row name]]
  233 	    if {![string match $pattern [dict get $row name]]} {
  234 		continue
  235 	    }
  236 	    switch -regexp -matchvar info [dict get $row type] {
  237 		{^(.+)\(\s*([[:digit:]]+)\s*,\s*([[:digit:]]+)\s*\)\s*$} {
  238 		    dict set row type [string tolower [lindex $info 1]]
  239 		    dict set row precision [lindex $info 2]
  240 		    dict set row scale [lindex $info 3]
  241 		}
  242 		{^(.+)\(\s*([[:digit:]]+)\s*\)\s*$} {
  243 		    dict set row type [string tolower [lindex $info 1]]
  244 		    dict set row precision [lindex $info 2]
  245 		    dict set row scale 0
  246 		}
  247 		default {
  248 		    dict set row type [string tolower [dict get $row type]]
  249 		    dict set row precision 0
  250 		    dict set row scale 0
  251 		}
  252 	    }
  253 	    dict set row nullable [expr {![dict get $row notnull]}]
  254 	    dict set retval [dict get $row name] $row
  255 	}
  256 	return $retval
  257     }
  258 
  259     # The 'primarykeys' method enumerates the primary keys on a table.
  260 
  261     method primarykeys {table} {
  262 	set result {}
  263 	my foreach row "PRAGMA table_info($table)" {
  264 	    if {[dict get $row pk]} {
  265 		lappend result [dict create ordinalPosition \
  266 				    [expr {[dict get $row cid]+1}] \
  267 				    columnName \
  268 				    [dict get $row name]]
  269 	    }
  270 	}
  271 	return $result
  272     }
  273 
  274     # The 'foreignkeys' method enumerates the foreign keys that are
  275     # declared in a table or that refer to a given table.
  276 
  277     method foreignkeys {args} {
  278 
  279 	variable ::tdbc::generalError
  280 
  281 	# Check arguments
  282 
  283 	set argdict {}
  284 	if {[llength $args] % 2 != 0} {
  285 	    set errorcode $generalError
  286 	    lappend errorcode wrongNumArgs
  287 	    return -code error -errorcode $errorcode \
  288 		"wrong # args: should be [lrange [info level 0] 0 1]\
  289                  ?-option value?..."
  290 	}
  291 	foreach {key value} $args {
  292 	    if {$key ni {-primary -foreign}} {
  293 		set errorcode $generalError
  294 		lappend errorcode badOption
  295 		return -code error -errorcode $errorcode \
  296 		    "bad option \"$key\", must be -primary or -foreign"
  297 	    }
  298 	    set key [string range $key 1 end]
  299 	    if {[dict exists $argdict $key]} {
  300 		set errorcode $generalError
  301 		lappend errorcode dupOption
  302 		return -code error -errorcode $errorcode \
  303 		    "duplicate option \"$key\" supplied"
  304 	    }
  305 	    dict set argdict $key $value
  306 	}
  307 
  308 	# If we know the table with the foreign key, search just its
  309 	# foreign keys. Otherwise, iterate over all the tables in the
  310 	# database.
  311 
  312 	if {[dict exists $argdict foreign]} {
  313 	    return [my ForeignKeysForTable [dict get $argdict foreign] \
  314 			$argdict]
  315 	} else {
  316 	    set result {}
  317 	    foreach foreignTable [dict keys [my tables]] {
  318 		lappend result {*}[my ForeignKeysForTable \
  319 				       $foreignTable $argdict]
  320 	    }
  321 	    return $result
  322 	}
  323 
  324     }
  325 
  326     # The private ForeignKeysForTable method enumerates the foreign keys
  327     # in a specific table.
  328     #
  329     # Parameters:
  330     #
  331     #	foreignTable - Name of the table containing foreign keys.
  332     #   argdict - Dictionary that may or may not contain a key,
  333     #             'primary', whose value is the name of a table that
  334     #             must hold the primary key corresponding to the foreign
  335     #             key. If the 'primary' key is absent, all tables are
  336     #             candidates.
  337     # Results:
  338     #
  339     # 	Returns the list of foreign keys that meed the specified
  340     # 	conditions, as a list of dictionaries, each containing the
  341     # 	keys, foreignConstraintName, foreignTable, foreignColumn,
  342     # 	primaryTable, primaryColumn, and ordinalPosition.  Note that the
  343     #   foreign constraint name is constructed arbitrarily, since SQLite3
  344     #   does not report this information.
  345 
  346     method ForeignKeysForTable {foreignTable argdict} {
  347 
  348 	set result {}
  349 	set n 0
  350 
  351 	# Go through the foreign keys in the given table, looking for
  352 	# ones that refer to the primary table (if one is given), or
  353 	# for any primary keys if none is given.
  354 	my foreach row "PRAGMA foreign_key_list($foreignTable)" {
  355 	    if {(![dict exists $argdict primary])
  356 		|| ([string tolower [dict get $row table]]
  357 		    eq [dict get $argdict primary])} {
  358 
  359 		# Construct a dictionary for each key, translating
  360 		# SQLite names to TDBC ones and converting sequence
  361 		# numbers to 1-based indexing.
  362 
  363 		set rrow [dict create foreignTable $foreignTable \
  364 			      foreignConstraintName \
  365 			      ?$foreignTable?[dict get $row id]]
  366 		if {[dict exists $row seq]} {
  367 		    dict set rrow ordinalPosition \
  368 			[expr {1 + [dict get $row seq]}]
  369 		}
  370 		foreach {to from} {
  371 		    foreignColumn from
  372 		    primaryTable table
  373 		    primaryColumn to
  374 		    deleteAction on_delete
  375 		    updateAction on_update
  376 		} {
  377 		    if {[dict exists $row $from]} {
  378 			dict set rrow $to [dict get $row $from]
  379 		    }
  380 		}
  381 
  382 		# Add the newly-constucted dictionary to the result list
  383 
  384 		lappend result $rrow
  385 	    }
  386 	}
  387 
  388 	return $result
  389     }
  390 
  391     # The 'preparecall' method prepares a call to a stored procedure.
  392     # SQLite3 does not have stored procedures, since it's an in-process
  393     # server.
  394 
  395     method preparecall {call} {
  396 	return -code error \
  397 	    -errorcode [list TDBC FEATURE_NOT_SUPPORTED 0A000 \
  398 			    SQLITE3 PREPARECALL] \
  399 	    {SQLite3 does not support stored procedures}
  400     }
  401 
  402     # The 'begintransaction' method launches a database transaction
  403 
  404     method begintransaction {} {
  405 	db eval {BEGIN TRANSACTION}
  406     }
  407 
  408     # The 'commit' method commits a database transaction
  409 
  410     method commit {} {
  411 	db eval {COMMIT}
  412     }
  413 
  414     # The 'rollback' method abandons a database transaction
  415 
  416     method rollback {} {
  417 	db eval {ROLLBACK}
  418     }
  419 
  420     # The 'transaction' method executes a script as a single transaction.
  421     # We override the 'transaction' method of the base class, since SQLite3
  422     # has a faster implementation of the same thing. (The base class's generic
  423     # method should also work.)
  424     # (Don't overload the base class method, because 'break', 'continue'
  425     # and 'return' in the transaction body don't work!)
  426 
  427     #method transaction {script} {
  428     #	uplevel 1 [list {*}[namespace code db] transaction $script]
  429     #}
  430 
  431     method prepare {sqlCode} {
  432 	set result [next $sqlCode]
  433 	return $result
  434     }
  435 
  436     method getDBhandle {} {
  437 	return [namespace which db]
  438     }
  439 }
  440 
  441 #------------------------------------------------------------------------------
  442 #
  443 # tdbc::sqlite3::statement --
  444 #
  445 #	Class representing a statement to execute against a SQLite3 database
  446 #
  447 #------------------------------------------------------------------------------
  448 
  449 ::oo::class create ::tdbc::sqlite3::statement {
  450 
  451     superclass ::tdbc::statement
  452 
  453     variable Params db sql
  454 
  455     # The constructor accepts the handle to the connection and the SQL
  456     # code for the statement to prepare.  All that it does is to parse the
  457     # statement and store it.  The parse is used to support the
  458     # 'params' and 'paramtype' methods.
  459 
  460     constructor {connection sqlcode} {
  461 	next
  462 	set Params {}
  463 	set db [$connection getDBhandle]
  464 	set sql $sqlcode
  465 	foreach token [::tdbc::tokenize $sqlcode] {
  466 	    if {[string index $token 0] in {$ : @}} {
  467 		dict set Params [string range $token 1 end] \
  468 		    {type Tcl_Obj precision 0 scale 0 nullable 1 direction in}
  469 	    }
  470 	}
  471     }
  472 
  473     # The 'resultSetCreate' method relays to the result set constructor
  474 
  475     forward resultSetCreate ::tdbc::sqlite3::resultset create
  476 
  477     # The 'params' method returns descriptions of the parameters accepted
  478     # by the statement
  479 
  480     method params {} {
  481 	return $Params
  482     }
  483 
  484     # The 'paramtype' method need do nothing; Sqlite3 uses manifest typing.
  485 
  486     method paramtype args {;}
  487 
  488     method getDBhandle {} {
  489 	return $db
  490     }
  491 
  492     method getSql {} {
  493 	return $sql
  494     }
  495 
  496 }
  497 
  498 #-------------------------------------------------------------------------------
  499 #
  500 # tdbc::sqlite3::resultset --
  501 #
  502 #	Class that represents a SQLlite result set in Tcl
  503 #
  504 #-------------------------------------------------------------------------------
  505 
  506 ::oo::class create ::tdbc::sqlite3::resultset {
  507 
  508     superclass ::tdbc::resultset
  509 
  510     # The variables of this class all have peculiar names. The reason is
  511     # that the RunQuery method needs to execute with an activation record
  512     # that has no local variables whose names could conflict with names
  513     # in the SQL query. We start the variable names with hyphens because
  514     # they can't be bind variables.
  515 
  516     variable -set {*}{
  517 	-columns -db -needcolumns -resultArray
  518 	-results -sql -Cursor -RowCount -END
  519     }
  520 
  521     constructor {statement args} {
  522 	next
  523 	set -db [$statement getDBhandle]
  524 	set -sql [$statement getSql]
  525 	set -columns {}
  526 	set -results {}
  527 	${-db} trace [namespace code {my RecordStatement}]
  528 	if {[llength $args] == 0} {
  529 
  530 	    # Variable substitutions are evaluated in caller's context
  531 
  532 	    uplevel 1 [list ${-db} eval ${-sql} \
  533 			   [namespace which -variable -resultArray] \
  534 			   [namespace code {my RecordResult}]]
  535 
  536 	} elseif {[llength $args] == 1} {
  537 
  538 	    # Variable substitutions are in the dictionary at [lindex $args 0].
  539 
  540 	    set -paramDict [lindex $args 0]
  541 
  542 	    # At this point, the activation record must contain no variables
  543 	    # that might be bound within the query.  All variables at this point
  544 	    # begin with hyphens so that they are syntactically incorrect
  545 	    # as bound variables in SQL.
  546 
  547 	    unset args
  548 	    unset statement
  549 
  550 	    dict with -paramDict {
  551 		${-db} eval ${-sql} -resultArray {
  552 		    my RecordResult
  553 		}
  554 	    }
  555 
  556 	} else {
  557 
  558 	    ${-db} trace {}
  559 
  560 	    # Too many args
  561 
  562 	    return -code error \
  563 		-errorcode [list TDBC GENERAL_ERROR HY000 \
  564 				SQLITE3 WRONGNUMARGS] \
  565 		"wrong # args: should be\
  566                  [lrange [info level 0] 0 1] statement ?dictionary?"
  567 
  568 	}
  569 	${-db} trace {}
  570 	set -Cursor 0
  571 	if {${-Cursor} < [llength ${-results}]
  572 	    && [lindex ${-results} ${-Cursor}] eq {statement}} {
  573 	    incr -Cursor 2
  574 	}
  575 	if {${-Cursor} < [llength ${-results}]
  576 	    && [lindex ${-results} ${-Cursor}] eq {columns}} {
  577 	    incr -Cursor
  578 	    set -columns [lindex ${-results} ${-Cursor}]
  579 	    incr -Cursor
  580 	}
  581 	set -RowCount [${-db} changes]
  582     }
  583 
  584     # Record the start of a SQL statement
  585 
  586     method RecordStatement {stmt} {
  587 	set -needcolumns 1
  588 	lappend -results statement {}
  589     }
  590 
  591     # Record one row of results from a query by appending it as a dictionary
  592     # to the 'results' list.  As a side effect, set 'columns' to a list
  593     # comprising the names of the columns of the result.
  594 
  595     method RecordResult {} {
  596 	set columns ${-resultArray(*)}
  597 	if {[info exists -needcolumns]} {
  598 	    lappend -results columns $columns
  599 	    unset -needcolumns
  600 	}
  601 	set dict {}
  602 	foreach key $columns {
  603 	    if {[set -resultArray($key)] ne "\ufffd"} {
  604 		dict set dict $key [set -resultArray($key)]
  605 	    }
  606 	}
  607 	lappend -results row $dict
  608     }
  609 
  610     # Advance to the next result set
  611 
  612     method nextresults {} {
  613 	set have 0
  614 	while {${-Cursor} < [llength ${-results}]} {
  615 	    if {[lindex ${-results} ${-Cursor}] eq {statement}} {
  616 		set have 1
  617 		incr -Cursor 2
  618 		break
  619 	    }
  620 	    incr -Cursor 2
  621 	}
  622 	if {!$have} {
  623 	    set -END {}
  624 	}
  625 	if {${-Cursor} >= [llength ${-results}]} {
  626 	    set -columns {}
  627 	} elseif {[lindex ${-results} ${-Cursor}] eq {columns}} {
  628 	    incr -Cursor
  629 	    set -columns [lindex ${-results} ${-Cursor}]
  630 	    incr -Cursor
  631 	} else {
  632 	    set -columns {}
  633 	}
  634 	return $have
  635     }
  636 
  637     method getDBhandle {} {
  638 	return ${-db}
  639     }
  640 
  641     # Return a list of the columns
  642 
  643     method columns {} {
  644 	if {[info exists -END]} {
  645 	    return -code error \
  646 		-errorcode {TDBC GENERAL_ERROR HY010 SQLITE3 FUNCTIONSEQ} \
  647 		"Function sequence error: result set is exhausted."
  648 	}
  649 	return ${-columns}
  650     }
  651 
  652     # Return the next row of the result set as a list
  653 
  654     method nextlist var {
  655 
  656 	upvar 1 $var row
  657 
  658 	if {[info exists -END]} {
  659 	    return -code error \
  660 		-errorcode {TDBC GENERAL_ERROR HY010 SQLITE3 FUNCTIONSEQ} \
  661 		"Function sequence error: result set is exhausted."
  662 	}
  663 	if {${-Cursor} >= [llength ${-results}]
  664 	    || [lindex ${-results} ${-Cursor}] ne {row}} {
  665 	    return 0
  666 	} else {
  667 	    set row {}
  668 	    incr -Cursor
  669 	    set d [lindex ${-results} ${-Cursor}]
  670 	    incr -Cursor
  671 	    foreach key ${-columns} {
  672 		if {[dict exists $d $key]} {
  673 		    lappend row [dict get $d $key]
  674 		} else {
  675 		    lappend row {}
  676 		}
  677 	    }
  678 	}
  679 	return 1
  680     }
  681 
  682     # Return the next row of the result set as a dict
  683 
  684     method nextdict var {
  685 
  686 	upvar 1 $var row
  687 
  688 	if {[info exists -END]} {
  689 	    return -code error \
  690 		-errorcode {TDBC GENERAL_ERROR HY010 SQLITE3 FUNCTIONSEQ} \
  691 		"Function sequence error: result set is exhausted."
  692 	}
  693 	if {${-Cursor} >= [llength ${-results}]
  694 	    || [lindex ${-results} ${-Cursor}] ne {row}} {
  695 	    return 0
  696 	} else {
  697 	    incr -Cursor
  698 	    set row [lindex ${-results} ${-Cursor}]
  699 	    incr -Cursor
  700 	}
  701 	return 1
  702     }
  703 
  704     # Return the number of rows affected by a statement
  705 
  706     method rowcount {} {
  707 	if {[info exists -END]} {
  708 	    return -code error \
  709 		-errorcode {TDBC GENERAL_ERROR HY010 SQLITE3 FUNCTIONSEQ} \
  710 		"Function sequence error: result set is exhausted."
  711 	}
  712 	return ${-RowCount}
  713     }
  714 
  715 }