+Release 3.01
+-- bug in mysql::nextresult fixed
+-- bug in man format doc fixed
+-- new command mysql::encoding
+-- new ssl connection options -sslkey -sslcert -sslca -sslcapath -sslciphers using of mysql_ssl_set
+-- new command option mysq::info state
+-- removed c-header installation section from Makefile.in
Release 3.00
-- all comands are defined in ::mysql namespace
-- commands are renamed after pattern mysqlconnect mysql::connect
doc:
@echo "user manual doc is as nroff (man) file mysqltcl.n"
-install: all install-binaries install-libraries install-doc
+#install: all install-binaries install-libraries install-doc
+install: all install-binaries install-doc
install-binaries: binaries install-lib-binaries install-bin-binaries
if test "x$(SHARED_BUILD)" = "x1"; then \
# This rule installs platform-independent files, such as header files.
#========================================================================
-install-libraries: libraries
- @mkdir -p $(DESTDIR)$(includedir)
- @echo "Installing header files in $(DESTDIR)$(includedir)"
- @for i in $(GENERIC_HDRS) ; do \
- echo "Installing $$i" ; \
- $(INSTALL_DATA) $$i $(DESTDIR)$(includedir) ; \
- done;
+# no headerfiles by mysqltcl
+#install-libraries: libraries
+# @mkdir -p $(DESTDIR)$(includedir)
+# @echo "Installing header files in $(DESTDIR)$(includedir)"
+# @for i in $(GENERIC_HDRS) ; do \
+# echo "Installing $$i" ; \
+# $(INSTALL_DATA) $$i $(DESTDIR)$(includedir) ; \
+# done;
#========================================================================
# Install documentation. Unix manpages should go in the $(mandir)
MAJOR_VERSION=3
MINOR_VERSION=0
-PATCHLEVEL=0
+PATCHLEVEL=1
VERSION=${MAJOR_VERSION}.${MINOR_VERSION}${PATCHLEVEL}
NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION}
echo $ECHO_N "checking for libmysqlclient lib... $ECHO_C" >&6
if test "$tcl_ok" = "yes"; then
if test ! -f ${MYSQL_LIB_DIR}/libmysqlclient.a ; then
- { { echo "$as_me:$LINENO: error: Cannot find libmysqlclient.a in $MYSQL_LIB_DIR use -with-mysql-lib=?" >&5
-echo "$as_me: error: Cannot find libmysqlclient.a in $MYSQL_LIB_DIR use -with-mysql-lib=?" >&2;}
+ { { echo "$as_me:$LINENO: error: Cannot find libmysqlclient.a in $MYSQL_LIB_DIR use --with-mysql-lib=?" >&5
+echo "$as_me: error: Cannot find libmysqlclient.a in $MYSQL_LIB_DIR use --with-mysql-lib=?" >&2;}
{ (exit 1); exit 1; }; }
fi
else
if test ! -f ${MYSQL_LIB_DIR}/libmysqlclient${SHLIB_SUFFIX} ; then
- { { echo "$as_me:$LINENO: error: Cannot find libmysqlclient${SHLIB_SUFFIX} in $MYSQL_LIB_DIR use -with-mysql-lib=?" >&5
-echo "$as_me: error: Cannot find libmysqlclient${SHLIB_SUFFIX} in $MYSQL_LIB_DIR use -with-mysql-lib=?" >&2;}
+ { { echo "$as_me:$LINENO: error: Cannot find libmysqlclient${SHLIB_SUFFIX} in $MYSQL_LIB_DIR use --with-mysql-lib=?" >&5
+echo "$as_me: error: Cannot find libmysqlclient${SHLIB_SUFFIX} in $MYSQL_LIB_DIR use --with-mysql-lib=?" >&2;}
{ (exit 1); exit 1; }; }
fi
fi
MAJOR_VERSION=3
MINOR_VERSION=0
-PATCHLEVEL=0
+PATCHLEVEL=1
VERSION=${MAJOR_VERSION}.${MINOR_VERSION}${PATCHLEVEL}
NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION}
AC_MSG_CHECKING([for libmysqlclient lib])
if test "$tcl_ok" = "yes"; then
if test ! -f ${MYSQL_LIB_DIR}/libmysqlclient.a ; then
- AC_MSG_ERROR(Cannot find libmysqlclient.a in $MYSQL_LIB_DIR use -with-mysql-lib=?)
+ AC_MSG_ERROR(Cannot find libmysqlclient.a in $MYSQL_LIB_DIR use --with-mysql-lib=?)
fi
else
if test ! -f ${MYSQL_LIB_DIR}/libmysqlclient${SHLIB_SUFFIX} ; then
- AC_MSG_ERROR(Cannot find libmysqlclient${SHLIB_SUFFIX} in $MYSQL_LIB_DIR use -with-mysql-lib=?)
+ AC_MSG_ERROR(Cannot find libmysqlclient${SHLIB_SUFFIX} in $MYSQL_LIB_DIR use --with-mysql-lib=?)
fi
fi
AC_MSG_RESULT([yes])
--- /dev/null
+'\" The definitions below are for supplemental macros used in Tcl/Tk
+'\" manual entries.
+'\"
+'\" .AP type name in/out ?indent?
+'\" Start paragraph describing an argument to a library procedure.
+'\" type is type of argument (int, etc.), in/out is either "in", "out",
+'\" or "in/out" to describe whether procedure reads or modifies arg,
+'\" and indent is equivalent to second arg of .IP (shouldn't ever be
+'\" needed; use .AS below instead)
+'\"
+'\" .AS ?type? ?name?
+'\" Give maximum sizes of arguments for setting tab stops. Type and
+'\" name are examples of largest possible arguments that will be passed
+'\" to .AP later. If args are omitted, default tab stops are used.
+'\"
+'\" .BS
+'\" Start box enclosure. From here until next .BE, everything will be
+'\" enclosed in one large box.
+'\"
+'\" .BE
+'\" End of box enclosure.
+'\"
+'\" .CS
+'\" Begin code excerpt.
+'\"
+'\" .CE
+'\" End code excerpt.
+'\"
+'\" .VS ?version? ?br?
+'\" Begin vertical sidebar, for use in marking newly-changed parts
+'\" of man pages. The first argument is ignored and used for recording
+'\" the version when the .VS was added, so that the sidebars can be
+'\" found and removed when they reach a certain age. If another argument
+'\" is present, then a line break is forced before starting the sidebar.
+'\"
+'\" .VE
+'\" End of vertical sidebar.
+'\"
+'\" .DS
+'\" Begin an indented unfilled display.
+'\"
+'\" .DE
+'\" End of indented unfilled display.
+'\"
+'\" .SO
+'\" Start of list of standard options for a Tk widget. The
+'\" options follow on successive lines, in four columns separated
+'\" by tabs.
+'\"
+'\" .SE
+'\" End of list of standard options for a Tk widget.
+'\"
+'\" .OP cmdName dbName dbClass
+'\" Start of description of a specific option. cmdName gives the
+'\" option's name as specified in the class command, dbName gives
+'\" the option's name in the option database, and dbClass gives
+'\" the option's class in the option database.
+'\"
+'\" .UL arg1 arg2
+'\" Print arg1 underlined, then print arg2 normally.
+'\"
+'\" RCS: @(#) $Id$
+'\"
+'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
+.if t .wh -1.3i ^B
+.nr ^l \n(.l
+.ad b
+'\" # Start an argument description
+.de AP
+.ie !"\\$4"" .TP \\$4
+.el \{\
+. ie !"\\$2"" .TP \\n()Cu
+. el .TP 15
+.\}
+.ta \\n()Au \\n()Bu
+.ie !"\\$3"" \{\
+\&\\$1 \\fI\\$2\\fP (\\$3)
+.\".b
+.\}
+.el \{\
+.br
+.ie !"\\$2"" \{\
+\&\\$1 \\fI\\$2\\fP
+.\}
+.el \{\
+\&\\fI\\$1\\fP
+.\}
+.\}
+..
+'\" # define tabbing values for .AP
+.de AS
+.nr )A 10n
+.if !"\\$1"" .nr )A \\w'\\$1'u+3n
+.nr )B \\n()Au+15n
+.\"
+.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
+.nr )C \\n()Bu+\\w'(in/out)'u+2n
+..
+.AS Tcl_Interp Tcl_CreateInterp in/out
+'\" # BS - start boxed text
+'\" # ^y = starting y location
+'\" # ^b = 1
+.de BS
+.br
+.mk ^y
+.nr ^b 1u
+.if n .nf
+.if n .ti 0
+.if n \l'\\n(.lu\(ul'
+.if n .fi
+..
+'\" # BE - end boxed text (draw box now)
+.de BE
+.nf
+.ti 0
+.mk ^t
+.ie n \l'\\n(^lu\(ul'
+.el \{\
+.\" Draw four-sided box normally, but don't draw top of
+.\" box if the box started on an earlier page.
+.ie !\\n(^b-1 \{\
+\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
+.\}
+.el \}\
+\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
+.\}
+.\}
+.fi
+.br
+.nr ^b 0
+..
+'\" # VS - start vertical sidebar
+'\" # ^Y = starting y location
+'\" # ^v = 1 (for troff; for nroff this doesn't matter)
+.de VS
+.if !"\\$2"" .br
+.mk ^Y
+.ie n 'mc \s12\(br\s0
+.el .nr ^v 1u
+..
+'\" # VE - end of vertical sidebar
+.de VE
+.ie n 'mc
+.el \{\
+.ev 2
+.nf
+.ti 0
+.mk ^t
+\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
+.sp -1
+.fi
+.ev
+.\}
+.nr ^v 0
+..
+'\" # Special macro to handle page bottom: finish off current
+'\" # box/sidebar if in box/sidebar mode, then invoked standard
+'\" # page bottom macro.
+.de ^B
+.ev 2
+'ti 0
+'nf
+.mk ^t
+.if \\n(^b \{\
+.\" Draw three-sided box if this is the box's first page,
+.\" draw two sides but no top otherwise.
+.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
+.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
+.\}
+.if \\n(^v \{\
+.nr ^x \\n(^tu+1v-\\n(^Yu
+\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
+.\}
+.bp
+'fi
+.ev
+.if \\n(^b \{\
+.mk ^y
+.nr ^b 2
+.\}
+.if \\n(^v \{\
+.mk ^Y
+.\}
+..
+'\" # DS - begin display
+.de DS
+.RS
+.nf
+.sp
+..
+'\" # DE - end display
+.de DE
+.fi
+.RE
+.sp
+..
+'\" # SO - start of list of standard options
+.de SO
+.SH "STANDARD OPTIONS"
+.LP
+.nf
+.ta 4c 8c 12c
+.ft B
+..
+'\" # SE - end of list of standard options
+.de SE
+.fi
+.ft R
+.LP
+See the \\fBoptions\\fR manual entry for details on the standard options.
+..
+'\" # OP - start of full description for a single option
+.de OP
+.LP
+.nf
+.ta 4c
+Command-Line Name: \\fB\\$1\\fR
+Database Name: \\fB\\$2\\fR
+Database Class: \\fB\\$3\\fR
+.fi
+.IP
+..
+'\" # CS - begin code excerpt
+.de CS
+.RS
+.nf
+.ta .25i .5i .75i 1i
+..
+'\" # CE - end code excerpt
+.de CE
+.fi
+.RE
+..
+.de UL
+\\$1\l'|0\(ul'\\$2
+..
close $filein
close $file
+set file [open man.macros r]
+set manmacros [string trim [read $file]]
+close $file
+
::doctools::new dl2 -file mysqltcl.man -format nroff
set file [open mysqltcl.n w]
set filein [open mysqltcl.man]
-puts $file [dl2 format [read $filein]]
+set data [dl2 format [read $filein]]
+set data [string map [list {.so man.macros} $manmacros] $data]
+puts $file $data
close $filein
close $file
<tr valign=top ><td ><a href="#30"><b class='cmd'>::mysql::newnull</b> </a></td></tr>
<tr valign=top ><td ><a href="#31"><b class='cmd'>::mysql::setserveroption</b> <i class='arg'>handle</i> <i class='arg'>option</i></a></td></tr>
<tr valign=top ><td ><a href="#32"><b class='cmd'>::mysql::shutdown</b> <i class='arg'>handle</i></a></td></tr>
+<tr valign=top ><td ><a href="#33"><b class='cmd'>::mysql::encoding</b> <i class='arg'>handle</i> ?encoding?</a></td></tr>
</table></td></tr></table>
<h2><a name="description">DESCRIPTION</a></h2>
<p>
database and what encoding they expect. It can useful
to use -encoding utf-8. That is standard encoding in some linux distributions and newer systems.
-<br><br>
-<dt><strong>-ssl</strong> <i class='arg'>boolean</i><dd>
-Switch to SSL after handshake. Default is false
-
<br><br>
<dt><strong>-compress</strong> <i class='arg'>boolean</i><dd>
Use compression protocol. Default is false
The client's session wait_timeout variable will be set to the value of the session interactive_timeout variable.
Default is false.
+<br><br>
+<dt><strong>-ssl</strong> <i class='arg'>boolean</i><dd>
+Switch to SSL after handshake. Default is false
+
+<br><br>
+<dt><strong>-sslkey</strong> <i class='arg'>string</i><dd>
+is the pathname to the key file.
+Used if -ssl is true
+
+<br><br>
+<dt><strong>-sslcert</strong> <i class='arg'>string</i><dd>
+is the pathname to the certificate file.
+Used if -ssl is true
+
+<br><br>
+<dt><strong>-sslca</strong> <i class='arg'>string</i><dd>
+is the pathname to the certificate authority file.
+Used if -ssl is true
+
+<br><br>
+<dt><strong>-sslcapath</strong> <i class='arg'>string</i><dd>
+is the pathname to a directory that contains trusted SSL CA certificates in pem format.
+Used if -ssl is true
+
+<br><br>
+<dt><strong>-sslcipher</strong> <i class='arg'>string</i><dd>
+is a list of allowable ciphers to use for SSL encryption.
+Used if -ssl is true
+
</dl>
<dt><a name="2"><b class='cmd'>::mysql::use</b> <i class='arg'>handle</i> <i class='arg'>database</i></a><dd>
{1 Joe 2 Phil 3 John}
</pre></td></tr></table></p>
-Note that both list syntaxes are faster than something like\fB
+Note that both list syntaxes are faster than something like
<p><table><tr><td bgcolor=black> </td><td><pre class='sample'>
% ::mysql::sel $db "SELECT ID, NAME FROM FRIENDS"
<br><br>
Example:
<p><table><tr><td bgcolor=black> </td><td><pre class='sample'>
-set query1 [::mysql::query \$db {SELECT ID, NAME FROM FRIENDS}\]
-while {[set row [::mysql::fetch \$query1]]!=""} {
- set id [lindex \$row 0]
- set query2 [::mysql::query \$db "SELECT ADDRESS FROM ADDRESS WHERE FRIENDID=$ID"]
- ::mysql::map \$query2 address { puts "address = $address" }
- ::mysql::endquery \$query2
+set query1 [::mysql::query $db {SELECT ID, NAME FROM FRIENDS}\]
+while {[set row [::mysql::fetch $query1]]!=""} {
+ set id [lindex $row 0]
+ set query2 [::mysql::query $db "SELECT ADDRESS FROM ADDRESS WHERE FRIENDID=$ID"]
+ ::mysql::map $query2 address { puts "address = $address" }
+ ::mysql::endquery $query2
}
::mysql::endquery $query1
</pre></td></tr></table></p>
has completed.
<br><br>
A simple example follows.
-Assume $db is a handle in use.\fB
+Assume $db is a handle in use.
<p><table><tr><td bgcolor=black> </td><td><pre class='sample'>
-::mysql::sel \$db {
+::mysql::sel $db {
select lname, fname, area, phone from friends order by lname, fname
}
-::mysql::map \$db {ln fn - phone} {
- if {\$phone == {}} continue
- puts [format "%16s %-8s %s" \$ln \$fn \$phone]
+::mysql::map $db {ln fn - phone} {
+ if {$phone == {}} continue
+ puts [format "%16s %-8s %s" $ln $fn $phone]
}
</pre></td></tr></table></p>
-The ::mysql::sel command gets and sorts all rows from table \fIfriends].
+The ::mysql::sel command gets and sorts all rows from table friends.
The ::mysql::map command is used to format and print the result in a way
suitable for a phone list.
For demonstration purposes one of the columns (area) is not used.
The following is a sample interactive session containing all forms of
the ::mysql::col command and their results.
The last command uses the <em>-current</em> option.
-It could alternatively specify the table name explicitly.\fB
+It could alternatively specify the table name explicitly.
<p><table><tr><td bgcolor=black> </td><td><pre class='sample'>
%::mysql::col $db friends name
name lname area phone
Return a list of all table names in the database with which the handle
is associated.
The handle must be in use.
+
+<br><br>
+<dt><strong>serverversion</strong><dd>
+Returns the version number of the server as a string.
+
+<br><br>
+<dt><strong>serverversionid</strong><dd>
+Returns the version number of the server as an integer.
+
+<br><br>
+<dt><strong>sqlstate</strong><dd>
+Returns a string containing the SQLSTATE error code for the last error.
+The error code consists of five characters. '00000' means ``no error.''
+The values are specified by ANSI SQL and ODBC.
+
+Note that not all MySQL errors are yet mapped to SQLSTATE's.
+The value 'HY000' (general error) is used for unmapped errors.
+
+<br><br>
+<dt><strong>state</strong><dd>
+Returns a character string containing information similar to that provided by the mysqladmin status command.
+This includes uptime in seconds and the number of running threads, questions, reloads, and open tables.
+
</dl>
<dt><a name="15"><b class='cmd'>::mysql::baseinfo</b> <i class='arg'>option</i></a><dd>
current position in the pending result; an empty string if no result
is pending.
<br><br>
-[::mysql::result \$db current] + [::mysql::result \$db rows]
+[::mysql::result $db current] + [::mysql::result $db rows]
always equals the total number of rows in the pending result.
</dl>
<br><br>
<dt><a name="29"><b class='cmd'>::mysql::isnull</b> <i class='arg'>value</i></a><dd>
-Null handling is known problem by Tcl to DB interfaces.
-Mysql varchar type known 2 valid values NULL and empty string.
-There is no way to difference it in core Tcl because of it strong string based
-philosophy.
+Null handling is a known problem with Tcl, especially with DB interaction.
+The mysql "varchar" type has two valid blank values, NULL and an empty
+string. This is where the problem arises; Tcl is not able to differentiate
+between the two because of the way it handles strings.
Mysql has new internal Tcl type for null that string representation is stored
in global array mysqltcl(nullvalue) and as default empty string.
mysql::isnull can be used for safe check for null value.
Warning mysql::isnull works only reliable if there are no type conversation on
returned rows.
-Consider row is always Tcl list even when there are only on column in the row.
+Consider row is always Tcl list even when there are only one column in the row.
<p><table><tr><td bgcolor=black> </td><td><pre class='sample'>
-set row [::mysql::next \$handle]
-if {[mysql::isnull [lindex \$row 1]]} {
+set row [::mysql::next $handle]
+if {[mysql::isnull [lindex $row 1]]} {
puts "2. column of $row is null"
}
-if {[mysql::isnull \$row]} {
+if {[mysql::isnull $row]} {
puts "this does not work, because of type conversation list to string"
}
</pre></td></tr></table></p>
Asks the database server to shut down. The connected user must have SHUTDOWN privileges.
+<br><br>
+<dt><a name="33"><b class='cmd'>::mysql::encoding</b> <i class='arg'>handle</i> ?encoding?</a><dd>
+
+Ask or change a encoding of connection.
+There are special encoding "binary" for binary data transfers.
+
</dl>
<h2><a name="status_information">STATUS INFORMATION</a></h2>
<br><br>
<li>
Artur Trzewik (mail@xdobry.de) - active maintainer
+
</ul>
MySQLTcl is derived from a patch of msql by Hakan Soderstrom, Soderstrom Programvaruverkstad,
database and what encoding they expect. It can useful
to use -encoding utf-8. That is standard encoding in some linux distributions and newer systems.
-[opt_def -ssl [arg boolean]]
-Switch to SSL after handshake. Default is false
-
[opt_def -compress [arg boolean]]
Use compression protocol. Default is false
The client's session wait_timeout variable will be set to the value of the session interactive_timeout variable.
Default is false.
+[opt_def -ssl [arg boolean]]
+Switch to SSL after handshake. Default is false
+
+[opt_def -sslkey [arg string]]
+is the pathname to the key file.
+Used if -ssl is true
+
+[opt_def -sslcert [arg string]]
+is the pathname to the certificate file.
+Used if -ssl is true
+
+[opt_def -sslca [arg string]]
+is the pathname to the certificate authority file.
+Used if -ssl is true
+
+[opt_def -sslcapath [arg string]]
+is the pathname to a directory that contains trusted SSL CA certificates in pem format.
+Used if -ssl is true
+
+[opt_def -sslcipher [arg string]]
+is a list of allowable ciphers to use for SSL encryption.
+Used if -ssl is true
+
[list_end]
[call [cmd ::mysql::use] [arg handle] [arg database]]
{1 Joe 2 Phil 3 John}
[example_end]
-Note that both list syntaxes are faster than something like\fB
+Note that both list syntaxes are faster than something like
[example_begin]
% ::mysql::sel $db "SELECT ID, NAME FROM FRIENDS"
[nl]
Example:
[example_begin]
-set query1 [lb]::mysql::query \$db {SELECT ID, NAME FROM FRIENDS}\[rb]
-while {[lb]set row [lb]::mysql::fetch \$query1[rb][rb]!=""} {
- set id [lb]lindex \$row 0[rb]
- set query2 [lb]::mysql::query \$db "SELECT ADDRESS FROM ADDRESS WHERE FRIENDID=$ID"[rb]
- ::mysql::map \$query2 address { puts "address = $address" }
- ::mysql::endquery \$query2
+set query1 [lb]::mysql::query $db {SELECT ID, NAME FROM FRIENDS}\[rb]
+while {[lb]set row [lb]::mysql::fetch $query1[rb][rb]!=""} {
+ set id [lb]lindex $row 0[rb]
+ set query2 [lb]::mysql::query $db "SELECT ADDRESS FROM ADDRESS WHERE FRIENDID=$ID"[rb]
+ ::mysql::map $query2 address { puts "address = $address" }
+ ::mysql::endquery $query2
}
::mysql::endquery $query1
[example_end]
has completed.
[nl]
A simple example follows.
-Assume $db is a handle in use.\fB
+Assume $db is a handle in use.
[example_begin]
-::mysql::sel \$db {
+::mysql::sel $db {
select lname, fname, area, phone from friends order by lname, fname
}
-::mysql::map \$db {ln fn - phone} {
- if {\$phone == {}} continue
- puts [lb]format "%16s %-8s %s" \$ln \$fn \$phone[rb]
+::mysql::map $db {ln fn - phone} {
+ if {$phone == {}} continue
+ puts [lb]format "%16s %-8s %s" $ln $fn $phone[rb]
}
[example_end]
-The ::mysql::sel command gets and sorts all rows from table \fIfriends].
+The ::mysql::sel command gets and sorts all rows from table friends.
The ::mysql::map command is used to format and print the result in a way
suitable for a phone list.
For demonstration purposes one of the columns (area) is not used.
The following is a sample interactive session containing all forms of
the ::mysql::col command and their results.
The last command uses the [emph -current] option.
-It could alternatively specify the table name explicitly.\fB
+It could alternatively specify the table name explicitly.
[example_begin]
%::mysql::col $db friends name
name lname area phone
Return a list of all table names in the database with which the handle
is associated.
The handle must be in use.
+
+[opt_def serverversion]
+Returns the version number of the server as a string.
+
+[opt_def serverversionid]
+Returns the version number of the server as an integer.
+
+[opt_def sqlstate]
+Returns a string containing the SQLSTATE error code for the last error.
+The error code consists of five characters. '00000' means ``no error.''
+The values are specified by ANSI SQL and ODBC.
+
+Note that not all MySQL errors are yet mapped to SQLSTATE's.
+The value 'HY000' (general error) is used for unmapped errors.
+
+[opt_def state]
+Returns a character string containing information similar to that provided by the mysqladmin status command.
+This includes uptime in seconds and the number of running threads, questions, reloads, and open tables.
+
[list_end]
[call [cmd ::mysql::baseinfo] [arg option]]
current position in the pending result; an empty string if no result
is pending.
[nl]
-[lb]::mysql::result \$db current[rb] + [lb]::mysql::result \$db rows[rb]
+[lb]::mysql::result $db current[rb] + [lb]::mysql::result $db rows[rb]
always equals the total number of rows in the pending result.
[list_end]
[call [cmd ::mysql::isnull] [arg value]]
-Null handling is known problem by Tcl to DB interfaces.
-Mysql varchar type known 2 valid values NULL and empty string.
-There is no way to difference it in core Tcl because of it strong string based
-philosophy.
+Null handling is a known problem with Tcl, especially with DB interaction.
+The mysql "varchar" type has two valid blank values, NULL and an empty
+string. This is where the problem arises; Tcl is not able to differentiate
+between the two because of the way it handles strings.
Mysql has new internal Tcl type for null that string representation is stored
in global array mysqltcl(nullvalue) and as default empty string.
mysql::isnull can be used for safe check for null value.
returned rows.
Consider row is always Tcl list even when there are only one column in the row.
[example_begin]
-set row [lb]::mysql::next \$handle[rb]
-if {[lb]mysql::isnull [lb]lindex \$row 1[rb]]} {
+set row [lb]::mysql::next $handle[rb]
+if {[lb]mysql::isnull [lb]lindex $row 1[rb]]} {
puts "2. column of $row is null"
}
-if {[lb]mysql::isnull \$row[rb]} {
+if {[lb]mysql::isnull $row[rb]} {
puts "this does not work, because of type conversation list to string"
}
[example_end]
[call [cmd ::mysql::shutdown] [arg handle]]
Asks the database server to shut down. The connected user must have SHUTDOWN privileges.
+[call [cmd ::mysql::encoding] [arg handle] [opt encoding]]
+Ask or change a encoding of connection.
+There are special encoding "binary" for binary data transfers.
+
[list_end]
[section "STATUS INFORMATION"]
Paolo Brutti
[bullet]
Artur Trzewik (mail@xdobry.de) - active maintainer
+
[list_end]
MySQLTcl is derived from a patch of msql by Hakan Soderstrom, Soderstrom Programvaruverkstad,
'\" Generated from file 'mysqltcl.man' by tcllib/doctools with format 'nroff'
'\"
'\" -*- tcl -*- mysqltcl manpage
-.so man.macros
+'\" The definitions below are for supplemental macros used in Tcl/Tk
+'\" manual entries.
+'\"
+'\" .AP type name in/out ?indent?
+'\" Start paragraph describing an argument to a library procedure.
+'\" type is type of argument (int, etc.), in/out is either "in", "out",
+'\" or "in/out" to describe whether procedure reads or modifies arg,
+'\" and indent is equivalent to second arg of .IP (shouldn't ever be
+'\" needed; use .AS below instead)
+'\"
+'\" .AS ?type? ?name?
+'\" Give maximum sizes of arguments for setting tab stops. Type and
+'\" name are examples of largest possible arguments that will be passed
+'\" to .AP later. If args are omitted, default tab stops are used.
+'\"
+'\" .BS
+'\" Start box enclosure. From here until next .BE, everything will be
+'\" enclosed in one large box.
+'\"
+'\" .BE
+'\" End of box enclosure.
+'\"
+'\" .CS
+'\" Begin code excerpt.
+'\"
+'\" .CE
+'\" End code excerpt.
+'\"
+'\" .VS ?version? ?br?
+'\" Begin vertical sidebar, for use in marking newly-changed parts
+'\" of man pages. The first argument is ignored and used for recording
+'\" the version when the .VS was added, so that the sidebars can be
+'\" found and removed when they reach a certain age. If another argument
+'\" is present, then a line break is forced before starting the sidebar.
+'\"
+'\" .VE
+'\" End of vertical sidebar.
+'\"
+'\" .DS
+'\" Begin an indented unfilled display.
+'\"
+'\" .DE
+'\" End of indented unfilled display.
+'\"
+'\" .SO
+'\" Start of list of standard options for a Tk widget. The
+'\" options follow on successive lines, in four columns separated
+'\" by tabs.
+'\"
+'\" .SE
+'\" End of list of standard options for a Tk widget.
+'\"
+'\" .OP cmdName dbName dbClass
+'\" Start of description of a specific option. cmdName gives the
+'\" option's name as specified in the class command, dbName gives
+'\" the option's name in the option database, and dbClass gives
+'\" the option's class in the option database.
+'\"
+'\" .UL arg1 arg2
+'\" Print arg1 underlined, then print arg2 normally.
+'\"
+'\" RCS: @(#) $Id$
+'\"
+'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
+.if t .wh -1.3i ^B
+.nr ^l \n(.l
+.ad b
+'\" # Start an argument description
+.de AP
+.ie !"\\$4"" .TP \\$4
+.el \{\
+. ie !"\\$2"" .TP \\n()Cu
+. el .TP 15
+.\}
+.ta \\n()Au \\n()Bu
+.ie !"\\$3"" \{\
+\&\\$1 \\fI\\$2\\fP (\\$3)
+.\".b
+.\}
+.el \{\
+.br
+.ie !"\\$2"" \{\
+\&\\$1 \\fI\\$2\\fP
+.\}
+.el \{\
+\&\\fI\\$1\\fP
+.\}
+.\}
+..
+'\" # define tabbing values for .AP
+.de AS
+.nr )A 10n
+.if !"\\$1"" .nr )A \\w'\\$1'u+3n
+.nr )B \\n()Au+15n
+.\"
+.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
+.nr )C \\n()Bu+\\w'(in/out)'u+2n
+..
+.AS Tcl_Interp Tcl_CreateInterp in/out
+'\" # BS - start boxed text
+'\" # ^y = starting y location
+'\" # ^b = 1
+.de BS
+.br
+.mk ^y
+.nr ^b 1u
+.if n .nf
+.if n .ti 0
+.if n \l'\\n(.lu\(ul'
+.if n .fi
+..
+'\" # BE - end boxed text (draw box now)
+.de BE
+.nf
+.ti 0
+.mk ^t
+.ie n \l'\\n(^lu\(ul'
+.el \{\
+.\" Draw four-sided box normally, but don't draw top of
+.\" box if the box started on an earlier page.
+.ie !\\n(^b-1 \{\
+\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
+.\}
+.el \}\
+\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
+.\}
+.\}
+.fi
+.br
+.nr ^b 0
+..
+'\" # VS - start vertical sidebar
+'\" # ^Y = starting y location
+'\" # ^v = 1 (for troff; for nroff this doesn't matter)
+.de VS
+.if !"\\$2"" .br
+.mk ^Y
+.ie n 'mc \s12\(br\s0
+.el .nr ^v 1u
+..
+'\" # VE - end of vertical sidebar
+.de VE
+.ie n 'mc
+.el \{\
+.ev 2
+.nf
+.ti 0
+.mk ^t
+\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
+.sp -1
+.fi
+.ev
+.\}
+.nr ^v 0
+..
+'\" # Special macro to handle page bottom: finish off current
+'\" # box/sidebar if in box/sidebar mode, then invoked standard
+'\" # page bottom macro.
+.de ^B
+.ev 2
+'ti 0
+'nf
+.mk ^t
+.if \\n(^b \{\
+.\" Draw three-sided box if this is the box's first page,
+.\" draw two sides but no top otherwise.
+.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
+.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
+.\}
+.if \\n(^v \{\
+.nr ^x \\n(^tu+1v-\\n(^Yu
+\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
+.\}
+.bp
+'fi
+.ev
+.if \\n(^b \{\
+.mk ^y
+.nr ^b 2
+.\}
+.if \\n(^v \{\
+.mk ^Y
+.\}
+..
+'\" # DS - begin display
+.de DS
+.RS
+.nf
+.sp
+..
+'\" # DE - end display
+.de DE
+.fi
+.RE
+.sp
+..
+'\" # SO - start of list of standard options
+.de SO
+.SH "STANDARD OPTIONS"
+.LP
+.nf
+.ta 4c 8c 12c
+.ft B
+..
+'\" # SE - end of list of standard options
+.de SE
+.fi
+.ft R
+.LP
+See the \\fBoptions\\fR manual entry for details on the standard options.
+..
+'\" # OP - start of full description for a single option
+.de OP
+.LP
+.nf
+.ta 4c
+Command-Line Name: \\fB\\$1\\fR
+Database Name: \\fB\\$2\\fR
+Database Class: \\fB\\$3\\fR
+.fi
+.IP
+..
+'\" # CS - begin code excerpt
+.de CS
+.RS
+.nf
+.ta .25i .5i .75i 1i
+..
+'\" # CE - end code excerpt
+.de CE
+.fi
+.RE
+..
+.de UL
+\\$1\l'|0\(ul'\\$2
+..
.TH "mysqltcl" n 3.0 ""
.BS
.SH "NAME"
.sp
\fB::mysql::shutdown\fR \fIhandle\fR
.sp
+\fB::mysql::encoding\fR \fIhandle\fR ?encoding?
+.sp
.BE
.SH "DESCRIPTION"
MySQLTcl is a collection of Tcl commands and a Tcl global array that
database and what encoding they expect. It can useful
to use -encoding utf-8. That is standard encoding in some linux distributions and newer systems.
.TP
-\fB-ssl\fR \fIboolean\fR
-Switch to SSL after handshake. Default is false
-.TP
\fB-compress\fR \fIboolean\fR
Use compression protocol. Default is false
.TP
Allow interactive_timeout seconds (instead of wait_timeout seconds) of inactivity before closing the connection.
The client's session wait_timeout variable will be set to the value of the session interactive_timeout variable.
Default is false.
+.TP
+\fB-ssl\fR \fIboolean\fR
+Switch to SSL after handshake. Default is false
+.TP
+\fB-sslkey\fR \fIstring\fR
+is the pathname to the key file.
+Used if -ssl is true
+.TP
+\fB-sslcert\fR \fIstring\fR
+is the pathname to the certificate file.
+Used if -ssl is true
+.TP
+\fB-sslca\fR \fIstring\fR
+is the pathname to the certificate authority file.
+Used if -ssl is true
+.TP
+\fB-sslcapath\fR \fIstring\fR
+is the pathname to a directory that contains trusted SSL CA certificates in pem format.
+Used if -ssl is true
+.TP
+\fB-sslcipher\fR \fIstring\fR
+is a list of allowable ciphers to use for SSL encryption.
+Used if -ssl is true
.RE
.TP
\fB::mysql::use\fR \fIhandle\fR \fIdatabase\fR
% ::mysql::sel $db "SELECT ID, NAME FROM FRIENDS" -flatlist
{1 Joe 2 Phil 3 John}
.fi
-Note that both list syntaxes are faster than something like\\fB
+Note that both list syntaxes are faster than something like
.nf
% ::mysql::sel $db "SELECT ID, NAME FROM FRIENDS"
% ::mysql::map $db {id name} {lappend result $id $name}
.sp
Example:
.nf
-set query1 [::mysql::query \\$db {SELECT ID, NAME FROM FRIENDS}\\]
-while {[set row [::mysql::fetch \\$query1]]!=""} {
- set id [lindex \\$row 0]
- set query2 [::mysql::query \\$db "SELECT ADDRESS FROM ADDRESS WHERE FRIENDID=$ID"]
- ::mysql::map \\$query2 address { puts "address = $address" }
- ::mysql::endquery \\$query2
+set query1 [::mysql::query $db {SELECT ID, NAME FROM FRIENDS}\\]
+while {[set row [::mysql::fetch $query1]]!=""} {
+ set id [lindex $row 0]
+ set query2 [::mysql::query $db "SELECT ADDRESS FROM ADDRESS WHERE FRIENDID=$ID"]
+ ::mysql::map $query2 address { puts "address = $address" }
+ ::mysql::endquery $query2
}
::mysql::endquery $query1
.fi
has completed.
.sp
A simple example follows.
-Assume $db is a handle in use.\\fB
+Assume $db is a handle in use.
.nf
-::mysql::sel \\$db {
+::mysql::sel $db {
select lname, fname, area, phone from friends order by lname, fname
}
-::mysql::map \\$db {ln fn - phone} {
- if {\\$phone == {}} continue
- puts [format "%16s %-8s %s" \\$ln \\$fn \\$phone]
+::mysql::map $db {ln fn - phone} {
+ if {$phone == {}} continue
+ puts [format "%16s %-8s %s" $ln $fn $phone]
}
.fi
-The ::mysql::sel command gets and sorts all rows from table \\fIfriends].
+The ::mysql::sel command gets and sorts all rows from table friends.
The ::mysql::map command is used to format and print the result in a way
suitable for a phone list.
For demonstration purposes one of the columns (area) is not used.
The following is a sample interactive session containing all forms of
the ::mysql::col command and their results.
The last command uses the \fI-current\fR option.
-It could alternatively specify the table name explicitly.\\fB
+It could alternatively specify the table name explicitly.
.nf
%::mysql::col $db friends name
name lname area phone
Return a list of all table names in the database with which the handle
is associated.
The handle must be in use.
+.TP
+\fBserverversion\fR
+Returns the version number of the server as a string.
+.TP
+\fBserverversionid\fR
+Returns the version number of the server as an integer.
+.TP
+\fBsqlstate\fR
+Returns a string containing the SQLSTATE error code for the last error.
+The error code consists of five characters. '00000' means ``no error.''
+The values are specified by ANSI SQL and ODBC.
+Note that not all MySQL errors are yet mapped to SQLSTATE's.
+The value 'HY000' (general error) is used for unmapped errors.
+.TP
+\fBstate\fR
+Returns a character string containing information similar to that provided by the mysqladmin status command.
+This includes uptime in seconds and the number of running threads, questions, reloads, and open tables.
.RE
.TP
\fB::mysql::baseinfo\fR \fIoption\fR
current position in the pending result; an empty string if no result
is pending.
.sp
-[::mysql::result \\$db current] + [::mysql::result \\$db rows]
+[::mysql::result $db current] + [::mysql::result $db rows]
always equals the total number of rows in the pending result.
.RE
.TP
Returns the number of warnings generated during execution of the previous SQL statement.
.TP
\fB::mysql::isnull\fR \fIvalue\fR
-Null handling is known problem by Tcl to DB interfaces.
-Mysql varchar type known 2 valid values NULL and empty string.
-There is no way to difference it in core Tcl because of it strong string based
-philosophy.
+Null handling is a known problem with Tcl, especially with DB interaction.
+The mysql "varchar" type has two valid blank values, NULL and an empty
+string. This is where the problem arises; Tcl is not able to differentiate
+between the two because of the way it handles strings.
Mysql has new internal Tcl type for null that string representation is stored
in global array mysqltcl(nullvalue) and as default empty string.
mysql::isnull can be used for safe check for null value.
Warning mysql::isnull works only reliable if there are no type conversation on
returned rows.
-Consider row is always Tcl list even when there are only on column in the row.
+Consider row is always Tcl list even when there are only one column in the row.
.nf
-set row [::mysql::next \\$handle]
-if {[mysql::isnull [lindex \\$row 1]]} {
+set row [::mysql::next $handle]
+if {[mysql::isnull [lindex $row 1]]} {
puts "2. column of $row is null"
}
-if {[mysql::isnull \\$row]} {
+if {[mysql::isnull $row]} {
puts "this does not work, because of type conversation list to string"
}
.fi
.TP
\fB::mysql::shutdown\fR \fIhandle\fR
Asks the database server to shut down. The connected user must have SHUTDOWN privileges.
+.TP
+\fB::mysql::encoding\fR \fIhandle\fR ?encoding?
+Ask or change a encoding of connection.
+There are special encoding "binary" for binary data transfers.
.SH "STATUS INFORMATION"
Mysqltcl creates and maintains a Tcl global array to provide status
information.
#ifdef _WINDOWS\r
#include <windows.h>\r
#define PACKAGE "mysqltcl"\r
- #define VERSION "3.00"\r
+ #define VERSION "3.01"\r
#endif\r
\r
#include <tcl.h>\r
{\r
"-host", "-user", "-password", "-db", "-port", "-socket","-encoding",\r
"-ssl", "-compress", "-noschema","-odbc","-multistatement","-multiresult",\r
- "-localfiles","-ignorespace","-foundrows","-interactive",\r
- NULL\r
+ "-localfiles","-ignorespace","-foundrows","-interactive","-sslkey","-sslcert",\r
+ "-sslca","-sslcapath","-sslciphers",NULL\r
};\r
\r
static int Mysqltcl_Connect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
int port = 0, flags = 0, booleanflag;\r
char *socket = NULL;\r
char *encodingname = NULL;\r
+\r
+ int isSSL = 0;\r
+ char *sslkey = NULL;\r
+ char *sslcert = NULL;\r
+ char *sslca = NULL;\r
+ char *sslcapath = NULL;\r
+ char *sslcipher = NULL;\r
+ \r
MysqlTclHandle *handle;\r
const char *groupname = "mysqltcl";\r
\r
MYSQL_CONNDB_OPT, MYSQL_CONNPORT_OPT, MYSQL_CONNSOCKET_OPT, MYSQL_CONNENCODING_OPT,\r
MYSQL_CONNSSL_OPT, MYSQL_CONNCOMPRESS_OPT, MYSQL_CONNNOSCHEMA_OPT, MYSQL_CONNODBC_OPT,\r
MYSQL_MULTISTATEMENT_OPT,MYSQL_MULTIRESULT_OPT,MYSQL_LOCALFILES_OPT,MYSQL_IGNORESPACE_OPT,\r
- MYSQL_FOUNDROWS_OPT,MYSQL_INTERACTIVE_OPT\r
+ MYSQL_FOUNDROWS_OPT,MYSQL_INTERACTIVE_OPT,MYSQL_SSLKEY_OPT,MYSQL_SSLCERT_OPT,\r
+ MYSQL_SSLCA_OPT,MYSQL_SSLCAPATH_OPT,MYSQL_SSLCIPHERS_OPT\r
};\r
\r
if (!(objc & 1) || \r
encodingname = Tcl_GetStringFromObj(objv[++i],NULL);\r
break;\r
case MYSQL_CONNSSL_OPT:\r
- if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )\r
+ if (Tcl_GetBooleanFromObj(interp,objv[++i],&isSSL) != TCL_OK )\r
return TCL_ERROR;\r
- if (booleanflag)\r
- flags |= CLIENT_SSL;\r
break;\r
case MYSQL_CONNCOMPRESS_OPT:\r
if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )\r
return TCL_ERROR;\r
if (booleanflag)\r
flags |= CLIENT_MULTI_STATEMENTS;\r
+\r
+\r
break;\r
case MYSQL_MULTIRESULT_OPT:\r
if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )\r
if (booleanflag)\r
flags |= CLIENT_INTERACTIVE;\r
break;\r
+ case MYSQL_SSLKEY_OPT:\r
+ sslkey = Tcl_GetStringFromObj(objv[++i],NULL);\r
+ break;\r
+ case MYSQL_SSLCERT_OPT:\r
+ sslcert = Tcl_GetStringFromObj(objv[++i],NULL);\r
+ break;\r
+ case MYSQL_SSLCA_OPT:\r
+ sslca = Tcl_GetStringFromObj(objv[++i],NULL);\r
+ break;\r
+ case MYSQL_SSLCAPATH_OPT:\r
+ sslcapath = Tcl_GetStringFromObj(objv[++i],NULL);\r
+ break;\r
+ case MYSQL_SSLCIPHERS_OPT:\r
+ sslcipher = Tcl_GetStringFromObj(objv[++i],NULL);\r
+ break;\r
default:\r
return mysql_prim_confl(interp,objc,objv,"Weirdness in options"); \r
}\r
#if (MYSQL_VERSION_ID>=32350)\r
mysql_options(handle->connection,MYSQL_READ_DEFAULT_GROUP,groupname);\r
#endif\r
+ if (isSSL) {\r
+ mysql_ssl_set(handle->connection,sslkey,sslcert, sslca, sslcapath, sslcipher);\r
+ }\r
\r
if (!mysql_real_connect(handle->connection, hostname, user,\r
password, db, port, socket, flags)) {\r
return TCL_ERROR;\r
\r
db=Tcl_GetStringFromObj(objv[2], &len);\r
- if (len >= MYSQL_NAME_LEN)\r
- return mysql_prim_confl(interp,objc,objv,"database name too long") ;\r
- if (mysql_select_db(handle->connection, db) < 0)\r
- return mysql_server_confl(interp,objc,objv,handle->connection) ;\r
+ if (len >= MYSQL_NAME_LEN) {\r
+ mysql_prim_confl(interp,objc,objv,"database name too long");\r
+ return TCL_ERROR;\r
+ }\r
\r
- strcpy(handle->database, db) ;\r
+ if (mysql_select_db(handle->connection, db)!=0) {\r
+ return mysql_server_confl(interp,objc,objv,handle->connection);\r
+ }\r
+ strcpy(handle->database, db);\r
return TCL_OK;\r
}\r
\r
MysqlTclHandle *handle;\r
unsigned long *lengths;\r
\r
+\r
static CONST char* selOptions[] = {"-list", "-flatlist", NULL};\r
/* Warning !! no option number */\r
int i,selOption=2,colCount;\r
MysqlTclHandle *handle, *qhandle;\r
\r
if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,\r
+\r
"handle sqlstatement")) == 0)\r
return TCL_ERROR;\r
\r
qhandle->result = result;\r
qhandle->col_count = mysql_num_fields(qhandle->result) ;\r
\r
+\r
qhandle->res_count = mysql_num_rows(qhandle->result);\r
Tcl_SetObjResult(interp, Tcl_NewHandleObj(statePtr,qhandle));\r
return TCL_OK;\r
}\r
\r
\r
+\r
/*\r
*----------------------------------------------------------------------\r
*\r
}\r
Tcl_Free((char *)val);\r
return TCL_OK ;\r
+\r
}\r
\r
/*\r
* usage: mysqlinfo handle option\r
*\r
\r
+\r
*/\r
\r
static int Mysqltcl_Info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
static CONST char* MysqlDbOpt[] =\r
{\r
"dbname", "dbname?", "tables", "host", "host?", "databases",\r
- "info","serverversion","serverversionid","sqlstate",NULL\r
+ "info","serverversion","serverversionid","sqlstate","state",NULL\r
};\r
enum dboption {\r
MYSQL_INFNAME_OPT, MYSQL_INFNAMEQ_OPT, MYSQL_INFTABLES_OPT,\r
MYSQL_INFHOST_OPT, MYSQL_INFHOSTQ_OPT, MYSQL_INFLIST_OPT, MYSQL_INFO,\r
- MYSQL_INF_SERVERVERSION,MYSQL_INFO_SERVERVERSION_ID,MYSQL_INFO_SQLSTATE\r
+ MYSQL_INF_SERVERVERSION,MYSQL_INFO_SERVERVERSION_ID,MYSQL_INFO_SQLSTATE,MYSQL_INFO_STATE\r
};\r
\r
/* We can't fully check the handle at this stage. */\r
case MYSQL_INF_SERVERVERSION:\r
case MYSQL_INFO_SERVERVERSION_ID:\r
case MYSQL_INFO_SQLSTATE:\r
+ case MYSQL_INFO_STATE:\r
break;\r
+\r
case MYSQL_INFHOSTQ_OPT:\r
if (handle->connection == 0)\r
return TCL_OK ; /* Return empty string if not connected. */\r
mysql_free_result(list) ;\r
break ;\r
case MYSQL_INFHOST_OPT:\r
+\r
case MYSQL_INFHOSTQ_OPT:\r
Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_get_host_info(handle->connection), -1));\r
break ;\r
case MYSQL_INFO_SQLSTATE:\r
Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_sqlstate(handle->connection),-1));\r
break;\r
+ case MYSQL_INFO_STATE:\r
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_stat(handle->connection),-1));\r
+ break;\r
default: /* should never happen */\r
return mysql_prim_confl(interp,objc,objv,"weirdness in Mysqltcl_Info") ;\r
}\r
mysql_field_seek(result, 0) ;\r
while ((fld = mysql_fetch_field(result)) != NULL)\r
if ((colinfo = mysql_colinfo(interp,objc,objv,fld, objv[idx])) != NULL) {\r
+\r
Tcl_ListObjAppendElement(interp, resSubList, colinfo);\r
} else {\r
goto conflict; \r
* Mysqltcl_State\r
* Implements the mysqlstate command:\r
* usage: mysqlstate handle ?-numeric?\r
+\r
* \r
*/\r
\r
if (strcmp(Tcl_GetStringFromObj(objv[2],NULL), "-numeric"))\r
return mysql_prim_confl(interp,objc,objv,"last parameter should be -numeric");\r
else\r
+\r
numeric=1;\r
}\r
\r
\r
static int Mysqltcl_InsertId(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
{\r
+\r
MysqlTclHandle *handle;\r
\r
if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,\r
* Returns 0 if connection is OK\r
*/\r
\r
+\r
static int Mysqltcl_Ping(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
{\r
MysqlTclHandle *handle;\r
static int Mysqltcl_ChangeUser(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
{\r
MysqlTclHandle *handle;\r
+ int len;\r
char *user,*password,*database=NULL;\r
\r
if ((handle = mysql_prologue(interp, objc, objv, 4, 5, CL_CONN,\r
user = Tcl_GetStringFromObj(objv[2],NULL);\r
password = Tcl_GetStringFromObj(objv[3],NULL);\r
if (objc==5) {\r
- database = Tcl_GetStringFromObj(objv[4],NULL);\r
-\r
+ database = Tcl_GetStringFromObj(objv[4],&len);\r
+ if (len >= MYSQL_NAME_LEN) {\r
+ mysql_prim_confl(interp,objc,objv,"database name too long");\r
+ return TCL_ERROR;\r
+ }\r
}\r
if (mysql_change_user(handle->connection, user, password, database)!=0) {\r
- return mysql_server_confl(interp,objc,objv,handle->connection);\r
+ mysql_server_confl(interp,objc,objv,handle->connection);\r
+ return TCL_ERROR;\r
}\r
+ if (database!=NULL) \r
+ strcpy(handle->database, database);\r
return TCL_OK;\r
}\r
/*\r
"handle")) == 0)\r
return TCL_ERROR;\r
if (handle->result != NULL) {\r
-\r
mysql_free_result(handle->result) ;\r
handle->result = NULL ;\r
}\r
result = mysql_next_result(handle->connection);\r
- if (result==0) {\r
+ if (result==-1) {\r
Tcl_SetObjResult(interp, Tcl_NewIntObj(0));\r
return TCL_OK;\r
}\r
static int Mysqltcl_ShutDown(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
{\r
MysqlTclHandle *handle;\r
- int idx;\r
- enum enum_mysql_set_option mysqlServerOption;\r
-\r
- enum serveroption {\r
- MYSQL_MSTATMENT_ON_SOPT, MYSQL_MSTATMENT_OFF_SOPT\r
- };\r
\r
if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,\r
"handle")) == 0)\r
return TCL_ERROR;\r
-\r
if (mysql_shutdown(handle->connection,SHUTDOWN_DEFAULT)!=0) {\r
mysql_server_confl(interp,objc,objv,handle->connection);\r
}\r
return TCL_OK;\r
}\r
+/*\r
+ *----------------------------------------------------------------------\r
+ *\r
+ * Mysqltcl_Encoding\r
+ * usage: mysql::encoding handle ?encoding|binary?\r
+ *\r
+ */\r
+static int Mysqltcl_Encoding(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
+{\r
+ MysqltclState *statePtr = (MysqltclState *)clientData;\r
+ Tcl_HashSearch search;\r
+ Tcl_HashEntry *entryPtr;\r
+ MysqlTclHandle *handle,*qhandle;\r
+ char *encodingname;\r
+ Tcl_Encoding encoding;\r
+ \r
+ if ((handle = mysql_prologue(interp, objc, objv, 2, 3, CL_CONN,\r
+ "handle")) == 0)\r
+ return TCL_ERROR;\r
+ if (objc==2) {\r
+ if (handle->encoding == NULL)\r
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("binary",-1));\r
+ else \r
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetEncodingName(handle->encoding),-1));\r
+ } else {\r
+ if (handle->type!=HT_CONNECTION) {\r
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("encoding set can be used only on connection handle",-1));\r
+ return TCL_ERROR;\r
+ }\r
+ encodingname = Tcl_GetStringFromObj(objv[2],NULL);\r
+ if (strcmp(encodingname, "binary") == 0) {\r
+ encoding = NULL; \r
+ } else {\r
+ encoding = Tcl_GetEncoding(interp, encodingname);\r
+ if (encoding == NULL)\r
+ return TCL_ERROR;\r
+ }\r
+ if (handle->encoding!=NULL)\r
+ Tcl_FreeEncoding(handle->encoding);\r
+ handle->encoding = encoding;\r
+\r
+ /* change encoding of all subqueries */\r
+ for (entryPtr=Tcl_FirstHashEntry(&statePtr->hash,&search);\r
+ entryPtr!=NULL;\r
+ entryPtr=Tcl_NextHashEntry(&search)) {\r
+ qhandle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);\r
+ if (qhandle->type==HT_QUERY && handle->connection==qhandle->connection) {\r
+ qhandle->encoding = encoding;\r
+ }\r
+ }\r
+\r
+ }\r
+ return TCL_OK;\r
+}\r
/*\r
*----------------------------------------------------------------------\r
*\r
*/\r
\r
static int Mysqltcl_Close(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
+\r
{\r
MysqltclState *statePtr = (MysqltclState *)clientData; \r
MysqlTclHandle *handle,*thandle;\r
static int Mysqltcl_Prepare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])\r
{\r
MysqltclState *statePtr = (MysqltclState *)clientData;\r
+\r
MysqlTclHandle *handle;\r
MysqlTclHandle *shandle;\r
MYSQL_STMT *statement;\r
}\r
query = (char *)Tcl_GetByteArrayFromObj(objv[2], &queryLen);\r
if (mysql_stmt_prepare(statement,query,queryLen)) {\r
+\r
mysql_stmt_close(statement);\r
return mysql_server_confl(interp,objc,objv,handle->connection);\r
}\r
if (Tcl_PkgProvide(interp, "mysqltcl" , VERSION) != TCL_OK)\r
return TCL_ERROR;\r
/*\r
+\r
* Initialize the new Tcl commands.\r
* Deleting any command will close all connections.\r
*/\r
Tcl_CreateObjCommand(interp,"::mysql::newnull", Mysqltcl_NewNull,(ClientData)statePtr, NULL);\r
Tcl_CreateObjCommand(interp,"::mysql::setserveroption", Mysqltcl_SetServerOption,(ClientData)statePtr, NULL);\r
Tcl_CreateObjCommand(interp,"::mysql::shutdown", Mysqltcl_ShutDown,(ClientData)statePtr, NULL);\r
+ Tcl_CreateObjCommand(interp,"::mysql::encoding", Mysqltcl_Encoding,(ClientData)statePtr, NULL);\r
/* prepared statements */\r
\r
#ifdef PREPARED_STATEMENT\r
Tcl_CreateObjCommand(interp,"::mysql::pexecute", Mysqltcl_PExecute,(ClientData)statePtr, NULL);\r
#endif\r
\r
+\r
\r
/* Initialize mysqlstatus global array. */\r
\r
-set file libmysqltcl3.00
+set file libmysqltcl3.01
if {[file exists ./${file}[info sharedlibextension]]} {
load ./${file}[info sharedlibextension]
mysqlexec $handle "CREATE DATABASE $dbank"
}
mysqluse $handle $dbank
- if {[lsearch [mysqlinfo $handle tables] Student]<0} {
- puts "Test Table Student does not exist. Create it"
- mysqlexec $handle {
- CREATE TABLE Student (
- MatrNr int NOT NULL auto_increment,
- Name varchar(20),
- Semester int,
- PRIMARY KEY (MatrNr)
- )
- }
+
+ catch {mysqlexec $handle {drop table Student}}
+
+ mysqlexec $handle {
+ CREATE TABLE Student (
+ MatrNr int NOT NULL auto_increment,
+ Name varchar(20),
+ Semester int,
+ PRIMARY KEY (MatrNr)
+ )
}
- # clean test table
- mysqlexec $handle "delete from Student"
mysqlexec $handle "INSERT INTO Student VALUES (1,'Sojka',4)"
mysqlexec $handle "INSERT INTO Student VALUES (2,'Preisner',2)"
mysqlexec $handle "INSERT INTO Student VALUES (3,'Killar',2)"
set handle [getConnection]
+tcltest::test {use-1.0} {false use} -body {
+ mysqluse $handle notdb2
+} -returnCodes error -match glob -result "mysqluse/db server: Unknown database 'notdb2'"
+
+
tcltest::test {select-1.1} {Test sel and next functions} -body {
mysqluse $handle uni
set allrows [mysqlsel $handle {select * from Student}]
}
tcltest::test {handle-1.3} {10 queries, close all} -body {
- set handle [mysqlconnect -user root -db uni]
+ set handle [getConnection]
for {set x 0} {$x<10} {incr x} {
lappend queries [mysqlquery $handle {select * from Student}]
}
} -returnCodes error -match glob -result "*handle already closed*"
tcltest::test {handle-1.4} {10 queries, close all} -body {
- set handle [mysqlconnect -user root -db uni]
+ set handle [getConnection]
mysqlquery $handle {select * from Student}
mysqlclose
return
}
# does not work for mysql4.1
-if 0 {
tcltest::test {changeuser-1.1} {no such user} -body {
- mysqlchangeuser $handle nonuser {} uni
+ mysqlchangeuser $handle root {} nodb
} -returnCodes error -match glob -result "*Unknown database*"
-}
tcltest::test {interpreter-1.0} {mysqltcl in slave interpreter} -body {
- set handle [mysqlconnect -user root -db uni]
+ set handle [getConnection]
set i1 [interp create]
- $i1 eval {
+ $i1 eval "
package require mysqltcl
- set hdl [mysqlconnect -user root -db uni]
- }
+ set hdl [mysqlconnect -user $dbuser -db $dbank]
+ "
interp delete $i1
mysqlinfo $handle databases
mysqlclose $handle
source [file join [file dirname [info script]] libload.tcl]
}
+# global connect variables
+set dbuser root
+set dbpassword ""
+set dbank mysqltcltest
+
package require tcltest
variable SETUP {#common setup code}
variable CLEANUP {#common cleanup code}
tcltest::configure -verbose bet
-proc setConnect {} {
- global conn
- set conn [mysqlconnect -user root -db uni -multistatement 1]
+proc getConnection {{addOptions {}} {withDB 1}} {
+ global dbuser dbpassword dbank
+ if {$withDB} {
+ append addOptions " -db $dbank"
+ }
+ if {$dbpassword ne ""} {
+ append addOptions " -password $dbpassword"
+ }
+ return [eval mysqlconnect -user $dbuser $addOptions]
}
-# Create Table suitable for transaction tests
-proc initTestTable {} {
- global conn
- # drop table if exists
- catch {mysql::exec $conn {drop table transtest}}
- mysql::exec $conn {
+proc prepareTestDB {} {
+ global dbank
+ set handle [getConnection {} 0]
+ if {[lsearch [mysqlinfo $handle databases] $dbank]<0} {
+ puts "Testdatabase $dbank does not exist. Create it"
+ mysqlexec $handle "CREATE DATABASE $dbank"
+ }
+ mysqluse $handle $dbank
+
+ catch {mysql::exec $handle {drop table transtest}}
+ mysql::exec $handle {
create table transtest (
id int,
name varchar(20)
) ENGINE=INNODB
- }
+ }
+
+ catch {mysql::exec $handle {drop table Student}}
+ mysql::exec $handle {
+ CREATE TABLE Student (
+ MatrNr int NOT NULL auto_increment,
+ Name varchar(20),
+ Semester int,
+ PRIMARY KEY (MatrNr)
+ )
+ }
+ mysql::exec $handle "INSERT INTO Student VALUES (1,'Sojka',4)"
+ mysql::exec $handle "INSERT INTO Student VALUES (2,'Preisner',2)"
+ mysql::exec $handle "INSERT INTO Student VALUES (3,'Killar',2)"
+ mysql::exec $handle "INSERT INTO Student VALUES (4,'Penderecki',10)"
+ mysql::exec $handle "INSERT INTO Student VALUES (5,'Turnau',2)"
+ mysql::exec $handle "INSERT INTO Student VALUES (6,'Grechuta',3)"
+ mysql::exec $handle "INSERT INTO Student VALUES (7,'Gorniak',1)"
+ mysql::exec $handle "INSERT INTO Student VALUES (8,'Niemen',3)"
+ mysql::exec $handle "INSERT INTO Student VALUES (9,'Bem',5)"
+ mysql::close $handle
}
+prepareTestDB
+set conn [getConnection {-multistatement 1}]
+
+
tcltest::test {null-1.0} {creating of null} {
set null [mysql::newnull]
mysql::isnull $null
mysql::isnull [lindex [list [mysql::newnull]] 0]
} {1}
-# We need connection for folowing tests
-setConnect
-initTestTable
tcltest::test {autocommit} {setting autocommit} -body {
mysql::autocommit $conn 0
return
}
+tcltest::test {info-1.3} {sqlstate} -body {
+ mysql::info $conn state
+ return
+}
+
tcltest::test {state-1.0} {reported bug in 3.51} -body {
mysql::state nothandle -numeric
} -result 0
expr {[mysql::baseinfo clientversionid]>0}
} -result 1
+tcltest::test {encoding-1.0} {read system encoding} -body {
+ mysql::encoding $conn
+} -result [encoding system]
+
+tcltest::test {encoding-1.1} {change to binary} -body {
+ mysql::encoding $conn binary
+ mysql::exec $conn "INSERT INTO Student (Name,Semester) VALUES ('Test',4)"
+ mysql::encoding $conn
+} -result binary
+
+tcltest::test {encoding-1.2} {change to binary} -body {
+ mysql::encoding $conn [encoding system]
+ mysql::exec $conn "INSERT INTO Student (Name,Semester) VALUES ('Test',4)"
+ mysql::encoding $conn
+} -result [encoding system]
+
+tcltest::test {encoding-1.3} {change to binary} -body {
+ mysql::encoding $conn iso8859-1
+ mysql::exec $conn "INSERT INTO Student (Name,Semester) VALUES ('Test',4)"
+ mysql::encoding $conn
+} -result iso8859-1
+
+tcltest::test {encoding-1.4} {unknown encoding} -body {
+ mysql::encoding $conn unknown
+} -returnCodes error -match glob -result "unknown encoding*"
+
+tcltest::test {encoding-1.5} {changing encoding of query handle} -body {
+ set q [mysql::query $conn "select * from Student"]
+ mysql::encoding $q iso8859-1
+} -cleanup {
+ mysql::endquery $q
+} -returnCodes error -result "encoding set can be used only on connection handle"
+
+tcltest::test {encoding-1.6} {changing encoding of handle} -body {
+ mysql::encoding $conn iso8859-1
+ set q [mysql::query $conn "select * from Student"]
+ mysql::encoding $q
+} -cleanup {
+ mysql::endquery $q
+} -result iso8859-1
+
+tcltest::test {encoding-1.7} {changing encoding of handle} -body {
+ set q [mysql::query $conn "select * from Student"]
+ mysql::encoding $conn iso8859-1
+ mysql::encoding $q
+} -cleanup {
+ mysql::endquery $q
+} -result iso8859-1
+
+tcltest::test {encoding-1.8} {changing encoding of handle} -body {
+ mysql::encoding $conn utf-8
+ set q [mysql::query $conn "select * from Student"]
+ mysql::encoding $conn iso8859-1
+ mysql::encoding $q
+} -cleanup {
+ mysql::endquery $q
+} -result iso8859-1
+
+tcltest::test {encoding-1.8} {changing encoding of handle} -body {
+ mysql::encoding $conn iso8859-5
+ set q [mysql::query $conn "select Name from Student"]
+ mysql::encoding $conn utf-8
+ mysql::fetch $q
+ mysql::endquery $q
+ return
+}
# no prepared statements in this version
if 0 {