[DB-SIG] Sybase module 0.33 released

Dave Cole djc@object-craft.com.au
10 Mar 2002 16:58:25 +1100

What is it:
The Sybase module provides a Python interface to the Sybase relational
database system.  It supports all of the Python Database API, version
2.0 with extensions.


Since the 0.32 release I have come to the realisation that the Sybase
dynamic SQL functionality is not nearly general enough to use for
correct DB-API functionality.  I have thrown up my hands and gone back
to the drawing board with the high level Sybase.py module.

There were four pre-releases of the module.  The following is a
summary of what has changed since 0.32:

1) Bulkcopy support has been temporarily removed from Sybase.py.  The
   low level support is still present in the sybasect extension module.

2) Cursors are no longer using dynamic SQL so there will no
   longer be an extra result set which reported the status of the
   temporary stored procedure.  This should remove some of the
   confusion behaviour of cursors.

   There should be fewer restrictions on the use of cursors.

3) The paramstyle is now 'named'.  This means that you can now do

     c.execute("select * from titles where title like @arg",
               {'@arg': 'The %'})

4) You can send arguments to Cursor.callproc() the old way:

     c.callproc('sp_help', ['titles'])

   or the new way:

     c.callproc('sp_help', {'@objname': 'titles'})

5) Some internal cursor state constants were privatised (via leading
   '_').  Sadly no money was raised in the process and the conditions
   of the privatisation contract are commercial-in-confidence.

6) You can now compile the extension module without bulkcopy support
   by doing this:

     python setup.py build_ext -U WANT_BULKCOPY
     python setup.py install

7) The default build does not do threading any more so if you want
   threading enabled you will have to do this:

     python setup.py build_ext -D WANT_THREADS
     python setup.py install

8) There is some initial work to support FreeTDS.  One of the problems
   with FreeTDS is that it does not support inline error handling.
   The callback error handling works well if you do not compile for
   threads support, but causes problems when compiled for threading.

   The problem occurs when the extension module releases the global
   interpreter lock when calling the Sybase CT library.  A Python
   callback causes the interpreter to be reentered by the callback
   which leads to bad things when the following warning from the
   Python include file ceval.h is violated:


   At the moment the module will compile for FreeTDS (at least it does
   on my machine) and some things do work.  All you have to do is
   compile like this:

     python setup.py build_ext -D HAVE_FREETDS -U WANT_BULKCOPY
     python setup.py install

   There is no error handling and reporting for FreeTDS yet.

9) There is now some basic locale support in the sybasect extension
   module.  I do not have a need for this so am really depending upon
   someone to try it and report problems:

      >>> from sybasect import *
      >>> status, ctx = cs_ctx_alloc()
      >>> status, loc = ctx.cs_loc_alloc()
      >>> loc.cs_locale(CS_GET, CS_SYB_LANG)
      (1, 'us_english')
      >>> loc.cs_dt_info(CS_GET, CS_DT_CONVFMT)
      (1, 3)
      >>> loc.cs_dt_info(CS_GET, CS_MONTH, 1)
      (1, 'February')
      >>> loc.cs_dt_info(CS_GET, CS_DATEORDER)
      (1, 'dmy')

   In theory you could do something like this:

      >>> import Sybase
      >>> from Sybase import _ctx, CS_SUCCEED, CS_SET, CS_SYB_LANG, CS_LOC_PROP
      >>> status, locale = _ctx.cs_loc_alloc()
      >>> if status != CS_SUCCEED:
      ...     raise 'cs_loc_alloc'
      >>> if locale.cs_locale(CS_SET, CS_SYB_LANG, 'french') != CS_SUCCEED:
      ...     raise 'cs_locale CS_SYB_LANG'
      >>> db = Sybase.connect('SYBASE', 'sa', '', delay_connect = 1)
      >>> db.set_property(CS_LOC_PROP,  locale)
      >>> db.connect()

10) There is some extra debugging detail for CS_DATAFMT which means you
    now get messages like this:

      >>> import Sybase
      >>> db = Sybase.connect('SYBASE', 'sa', '', 'pubs2')
      >>> db._conn.debug = 1
      >>> c = db.cursor()
      ct_cmd_alloc(conn0, &cmd) -> CS_SUCCEED, cmd1
      >>> c.callproc('sp_help', {'@objname': 'titles'})
      ct_command(cmd1, CS_RPC_CMD, "sp_help", CS_NULLTERM, CS_UNUSED) -> CS_SUCCEED
      ct_param(cmd1, &databuf0->fmt=[name:"@objname" type:CS_CHAR_TYPE status:CS_INPUTVALUE format:CS_FMT_NULLTERM count:1 maxlength:7], databuf0->buff, 6, 0) -> CS_SUCCEED
      ct_send(cmd1) -> CS_SUCCEED
      ct_results(cmd1, &result) -> CS_SUCCEED, CS_ROW_RESULT
      ct_res_info(cmd1, CS_NUMDATA, &value, CS_UNUSED, NULL) -> CS_SUCCEED, 3
      ct_describe(cmd1, 1, &fmt) -> CS_SUCCEED, datafmt0=[name:"Name" type:CS_CHAR_TYPE status:CS_UPDATABLE format:CS_FMT_UNUSED count:0 maxlength:30]
      ct_bind(cmd1, 1, &datafmt0->fmt=[name:"Name" type:CS_CHAR_TYPE status:CS_UPDATABLE format:CS_FMT_UNUSED count:1 maxlength:30], databuf1->buff, databuf1->copied, databuf1->indicator) -> CS_SUCCEED, databuf1
      ct_describe(cmd1, 2, &fmt) -> CS_SUCCEED, datafmt1=[name:"Owner" type:CS_CHAR_TYPE status:48 format:CS_FMT_UNUSED count:0 maxlength:30]
      ct_bind(cmd1, 2, &datafmt1->fmt=[name:"Owner" type:CS_CHAR_TYPE status:48 format:CS_FMT_UNUSED count:1 maxlength:30], databuf2->buff, databuf2->copied, databuf2->indicator) -> CS_SUCCEED, databuf2
      ct_describe(cmd1, 3, &fmt) -> CS_SUCCEED, datafmt2=[name:"Type" type:CS_CHAR_TYPE status:48 format:CS_FMT_UNUSED count:0 maxlength:22]
      ct_bind(cmd1, 3, &datafmt2->fmt=[name:"Type" type:CS_CHAR_TYPE status:48 format:CS_FMT_UNUSED count:1 maxlength:22], databuf3->buff, databuf3->copied, databuf3->indicator) -> CS_SUCCEED, databuf3
11) The was a minor change to setup.py for Linux.  No longer looks for
    both libsybtcl and libtcl.  Now just looks for libinsck.

12) The tar file now unpacks to a directory called sybase-<release>.

The module is available here:


The module home page is here:


- Dave