Updated 2013-09-06 17:15:00 by pooryorick

SnODBC, by Anton Kovalenko is a binding for the ODBC API, mostly compatible with TclODBC. It is distributed as starkit that may be sourced to have a snodbc package available. The starkit may also be run to see the documentation. It supports unicode data types; it is able invoke windows ODBC GUI for selecting data source.

The starkit contains binaries of Ffidl and dict extensions compiled for Windows-x86 and Linux-x86.

Response  edit

snichols: Overall I think the snodbc extension is really good. My only request is it would be nice if it worked with Tcl version 8.31. I know it uses the new Tcl dictionary object. This section would have to be rewritten.

Download  edit

2008-11-18: davidw has recently modified SnODBC to improve performance, with the addition of some C coded files. See github
[URL: ]snodbc.kit

Once downloaded, the starkit may be updated to the latest version with the sdx tool:

The version of the starkit presented here may be used with Tclkit 8.4 (tested on 8.4.9), or with any Tcl 8.4 distribution supporting starkits, such as ActiveTcl, dqkit, TixTclKit.
sdx update -from http://sw4me.com/cgi-bin/starsync snodbc.kit

2008-05-21: These binaries are not supported now and will be removed soon. Please use starkit.

Build and Install  edit

jcw 2005-11-15: Had to add a package require Tk before source $starkit::topdir/help/help.tcl in main.tcl, and noted that the starkit help will generate an error with 8.4, but with tclkit 8.5 the help came up fine (tried on Mac, I have no real ODBC driver for it, so it was just to see the docs).

Releases  edit

2008-05-21 New version is available: 1.2.20080521. Features added:

  • OUTPUT and INPUTOUTPUT parameters
  • NULL and DEFAULT representation for parameters
  • -multisets flag may be set before connecting, thus it's usable now.
  • Supports retrieving non-fatal diagnostic messages (SQL_SUCCESS_WITH_INFO) for connection and statement
  • Fixed memory leaks in statement objects.
  • Numerous other bug fixes.

It is still compatible with TCL 8.4. There are now separate script files for 8.4 and 8.5+ (the former is generated from the latter).

Porting the starkit to other platforms is easy as long as you have working Ffidl for that platform. If you succeeded with SnODBC on some platform other than Linux-x86 and Windows-x86, please send me your Ffidl (and optionally dict) binaries.

2005-09-16: Some changes were made to improve TclODBC compatibility. Now the vast majority of scripts using TclODBC will just work with SnODBC as well.

Description  edit

SnODBC is mostly compatible with TclODBC, but there are some subtle differences. See the documentation for details.

The main good difference is that SnODBC supports Unicode character types. Other advantages of SnODBC include:

  • Support for ODBC GUI: you may bring up datasource selection dialog to establish a connection, and save the connection string for subsequent connections.
  • Additional support for metadata: rowid, primarykeys, procedures and procedurecolumns metadata queries.
  • Support for scrollable cursors: navigate back and forth on the result set when the driver supports it.
  • Setting NULL representation for a statement in order to distinguish NULLs from the empty string value.

The extension is developed for Tcl 8.5; this starkit was created with some help of the sugar macro processor to translate {*} syntax into the compatible replacement for Tcl-8.4. See Using sugar for forward-compatible {*} for a syntax macro that does this job.

snichols 09-16-05 I am curious did you use Ffidl to create the C wrappers for the C based ODBC API?

A/AK 09-17-05 I use Ffidl to create the TCL commands that call ODBC functions in ODBC shared library. There is no C functions in SnODBC, and, consequently, no compilation is required when Ffidl is already available.

snichols That's pretty wild. So Ffidl is what exposes the C-based ODBC functions to Tcl?

A/AK Yes. Ffidl is great at exposing C-based functions to Tcl at runtime.

snichols If I have some time I may try using it to expose some LDAP functions to Tcl using the popular Mozilla LDAP C API.

Fixed Bug: Datasources and Drivers  edit

escargo 2005-10-27: I downloaded the Microsoft Windows binary-only version (not the starkit) and found two problems with its installation on my ActiveState 8.4.11 installation (on Windows XP Pro).

  • The file permissions on ffidl06.dll were not executable, so I had to change the permissions before it would load.
  • The pkgIndex.tcl file uses the odbc namespace, but it does not ensure that it is created.

Once I made those changes, I was able to load snodbc.

Once I loaded it, I tried this code:
database datasources system

I got a response:
can't rename "{EngTestDB {SQL Server}}": command doesn't exist

So there is still something not quite right with the binary-only installation.

Later. I tried the same test using source to source the starkit version, and then package require. I get the same error as before.

A/AK 2005-11-02: Fixed the error with datasources and drivers, and added executable permissions for DLLs.

As of ::odbc namespace, it is used in pkgIndex.tcl at the place where it is surely defined. If you see a message about an undefined namespace when loading the package, I would like to see the message and the stack trace.

I've tested the package with ActiveTcl 8.4.1, dqkit, tclkit etc. No namespace-related errors have been noticed.

Mea culpa: I've forgot to test "datasources" and "drivers" for 8.4 backport, and I've not noticed the DLL permissions issue because my unzipper doesn't set permissions on MS Windows; but it would be very strange if the namespace is OK on my machine and missing on some other one.

Example: Check Connection Status  edit

Arlie L. Codina 2007-03-08:

How do I test in snodbc if database connection is ok or not?

Tried this:
database connect db MYDB sa 1234

# check if connected
if {![info exists db]} {

   tk_messageBox -icon info -message "Cannot connect to database!" -type ok

} else {
   tk_messageBox -icon info -message "Connected!" -type ok

Cannot detect connection even if connected.

set error [ catch { database connect db MYDB sa 1234 } msg]
if {$error} {
    puts "Not connected: $msg"

By the way, [info exists]' tests for variable existence, not command, and variables in your namespace won't ever be created by database command. If you want to test command's existence, you need something like
if {[namespace which db] eq {}} {
    puts "There is no such command: 'db'"

Bug Report: Prepared Statements and NULL  edit

[gth] 2006-06-02: I've got an additional problem with prepared statements. I've downloaded the latest version (snodbc v. 1.1.20060413) and try to update a column with a the null value. With or without specifying the "set null ..." parameter it doesn't work.

Bug Report: Lassign  edit

Arlie L. Codina 2007-02-24:

database connect sqlca IACCS sa arliec

Error in constructor: invalid command name "lassign"

Please help.

A/AK - lassign is a command from TclX, which is also in Tcl 8.5. SnODBC provides a forward-compatible implementation in its lassign.tcl file. This file should be autoloaded when the command is used for the first time.

If autoloading doesn't work, you may get around it by sourcing lassign.tcl before using SnODBC.

I'll fix this problem if I'm able to reproduce it. For now, lassign is autoloaded properly (when needed) on every Tcl version that I have, with all variants of SnODBC distribution.

Fixed Bug: Prepared Statements and Blank Tcl Data  edit

snichols 2006-04-13: I fixed a bug in my copy of snodbc when using it with SQL prepared statements. The bug has to do with using blank Tcl data (like set myvar {}) in SQL prepared statements. I guessed where to fix it in the code but it works. I recommend the snodbc author double-check my new way snippit below. FYI... The original tclodbc package suffers from the same problem, but I don't have the C++ sources it fix it too. Here's what I changed in snodbc's odbc-obj.tcl package script to make prepared statements work with blank varchars passed from Tcl:
# Old Way (find this line in odbc-obj.tcl)
if {!$pprec} { set pprec $charlen}
set bound [SQLBindParameter $hstmt $ip 1 $c_type  $ptype $pprec $pscale [::ffidlx::buffer addr $buf]  [string length $bytes]  [expr {$theIndicator+$pib}]]

# New Way
if {!$pprec} { set pprec [expr {$charlen + 1}]}
set bound [SQLBindParameter $hstmt $ip 1 $c_type  $ptype $pprec $pscale [::ffidlx::buffer addr $buf]  [expr {[string length $bytes] + 1}]  [expr {$theIndicator+$pib}]]

In the latter snipit, I simply increased the allocated SQL buffer by one to handle blank Tcl data. This shouldn't hurt anything that I know of. Another way to code it would be to first check if the length of the Tcl var was zero then add one if it is.

A/AK 2006-04-14: Thanks to snichols. The bug described above is now fixed (snodbc v. 1.1.20060413)