OpenFPGA/libs/EXTERNAL/tcl8.6.12/pkgs/tdbcmysql1.1.3/library/tdbcmysql.tcl

194 lines
6.5 KiB
Tcl
Raw Normal View History

2022-06-07 11:15:20 -05:00
# tdbcmysql.tcl --
#
# Class definitions and Tcl-level methods for the tdbc::mysql bridge.
#
# Copyright (c) 2008 by Kevin B. Kenny
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: tdbcmysql.tcl,v 1.47 2008/02/27 02:08:27 kennykb Exp $
#
#------------------------------------------------------------------------------
package require tdbc
::namespace eval ::tdbc::mysql {
namespace export connection datasources drivers
}
#------------------------------------------------------------------------------
#
# tdbc::mysql::connection --
#
# Class representing a connection to a database through MYSQL.
#
#-------------------------------------------------------------------------------
::oo::class create ::tdbc::mysql::connection {
superclass ::tdbc::connection
# The constructor is written in C. It takes alternating keywords
# and values pairs as its argumenta. (See the manual page for the
# available options.)
variable foreignKeysStatement
# The 'statementCreate' method delegates to the constructor of the
# statement class
forward statementCreate ::tdbc::mysql::statement create
# The 'columns' method returns a dictionary describing the tables
# in the database
method columns {table {pattern %}} {
# To return correct lengths of CHARACTER and BINARY columns,
# we need to know the maximum lengths of characters in each
# collation. We cache this information only once, on the first
# call to 'columns'.
if {[my NeedCollationInfo]} {
my SetCollationInfo {*}[my allrows -as lists {
SELECT coll.id, cs.maxlen
FROM INFORMATION_SCHEMA.COLLATIONS coll,
INFORMATION_SCHEMA.CHARACTER_SETS cs
WHERE cs.CHARACTER_SET_NAME = coll.CHARACTER_SET_NAME
ORDER BY coll.id DESC
}]
}
return [my Columns $table $pattern]
}
# The 'preparecall' method gives a portable interface to prepare
# calls to stored procedures. It delegates to 'prepare' to do the
# actual work.
method preparecall {call} {
regexp {^[[:space:]]*(?:([A-Za-z_][A-Za-z_0-9]*)[[:space:]]*=)?(.*)} \
$call -> varName rest
if {$varName eq {}} {
my prepare "CALL $rest"
} else {
my prepare \\{:$varName=$rest\\}
}
}
# The 'init', 'begintransaction', 'commit, 'rollback', 'tables'
# 'NeedCollationInfo', 'SetCollationInfo', and 'Columns' methods
# are implemented in C.
# The 'BuildForeignKeysStatements' method builds a SQL statement to
# retrieve the foreign keys from a database. (It executes once the
# first time the 'foreignKeys' method is executed, and retains the
# prepared statements for reuse.) It is slightly nonstandard because
# MYSQL doesn't name the PRIMARY constraints uniquely.
method BuildForeignKeysStatement {} {
foreach {exists1 clause1} {
0 {}
1 { AND fkc.REFERENCED_TABLE_NAME = :primary}
} {
foreach {exists2 clause2} {
0 {}
1 { AND fkc.TABLE_NAME = :foreign}
} {
set stmt [my prepare "
SELECT rc.CONSTRAINT_SCHEMA AS \"foreignConstraintSchema\",
rc.CONSTRAINT_NAME AS \"foreignConstraintName\",
rc.UPDATE_RULE AS \"updateAction\",
rc.DELETE_RULE AS \"deleteAction\",
fkc.REFERENCED_TABLE_SCHEMA AS \"primarySchema\",
fkc.REFERENCED_TABLE_NAME AS \"primaryTable\",
fkc.REFERENCED_COLUMN_NAME AS \"primaryColumn\",
fkc.TABLE_SCHEMA AS \"foreignSchema\",
fkc.TABLE_NAME AS \"foreignTable\",
fkc.COLUMN_NAME AS \"foreignColumn\",
fkc.ORDINAL_POSITION AS \"ordinalPosition\"
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE fkc
ON fkc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
AND fkc.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA
WHERE 1=1
$clause1
$clause2
"]
dict set foreignKeysStatement $exists1 $exists2 $stmt
}
}
}
}
#------------------------------------------------------------------------------
#
# tdbc::mysql::statement --
#
# The class 'tdbc::mysql::statement' models one statement against a
# database accessed through an MYSQL connection
#
#------------------------------------------------------------------------------
::oo::class create ::tdbc::mysql::statement {
superclass ::tdbc::statement
# The 'resultSetCreate' method forwards to the constructor of the
# result set.
forward resultSetCreate ::tdbc::mysql::resultset create
# Methods implemented in C:
#
# constructor connection SQLCode
# The constructor accepts the handle to the connection and the SQL code
# for the statement to prepare. It creates a subordinate namespace to
# hold the statement's active result sets, and then delegates to the
# 'init' method, written in C, to do the actual work of preparing the
# statement.
# params
# Returns descriptions of the parameters of a statement.
# paramtype paramname ?direction? type ?precision ?scale??
# Declares the type of a parameter in the statement
}
#------------------------------------------------------------------------------
#
# tdbc::mysql::resultset --
#
# The class 'tdbc::mysql::resultset' models the result set that is
# produced by executing a statement against an MYSQL database.
#
#------------------------------------------------------------------------------
::oo::class create ::tdbc::mysql::resultset {
superclass ::tdbc::resultset
# Methods implemented in C include:
# constructor statement ?dictionary?
# -- Executes the statement against the database, optionally providing
# a dictionary of substituted parameters (default is to get params
# from variables in the caller's scope).
# columns
# -- Returns a list of the names of the columns in the result.
# nextdict
# -- Stores the next row of the result set in the given variable in
# the caller's scope as a dictionary whose keys are
# column names and whose values are column values, or else
# as a list of cells.
# nextlist
# -- Stores the next row of the result set in the given variable in
# the caller's scope as a list of cells.
# rowcount
# -- Returns a count of rows affected by the statement, or -1
# if the count of rows has not been determined.
}