Sybase module for Python

News

7 April 2005 - Sybase module 0.37 released
No problems were reported with the 0.37pre3 release. This is a re-release of 0.37pre3 as 0.37.
21 March 2005 - Sybase module 0.37pre3 released
This release fixes a FreeTDS compilation problem and removes some warnings
21 March 2005 - Sybase module 0.37pre2 released
This release adds the following patches to the 0.37pre1 release :
  • Callback declaration fix on Windows from Vadim Beloborodov.
  • Cursor state fix from Skip Montanaro.
19 March 2005 - Sybase module 0.37pre1 released
This release is purely bugfix focussed. Changes include:
  • Bugs fixes to output parameter handling.
  • The return value of Cursor.callproc() is now longer returned in the result sets. It is available in the .return_status Cursor member once all results have been consumed.
  • Output hook patch from Ty Sarna.
  • Improved error handle patch from Andre Sedinin.
27 April 2003 - Sybase module 0.36 released
This release contains the result of running the Python DB API 2.0 Anal Compliance Unit Test on the module. A number of changes had to be made to the test suite in order to get a clean run. They changes were all related to the Sybase limitation of not being able to execute a 'CREATE TABLE' statement in a multi-statement transaction.
  • Output parameters from stored procedures are supported via the OUTPUT() function. The parameter to OUTPUT() determines the type and size of the buffer which will be allocated to receive the output value.
    c.callproc('test_proc', {'@type': 'business',
                             '@tot_sales': 5,
                             '@num_books': Sybase.OUTPUT(1)})
    
  • Added Time() and TimeFromTicks() DB API functions.
  • Fixed fmx.maxlength typo.
  • Reorganised result fetching to use "fetcher" classes; _FetchNow, _FetchNowParams, and _FetchLazy. This was in response to testing against the Python DB API 2.0 Anal Compliance Unit Test.
23 February 2003 - Sybase module 0.36pre5 released
This release is purely bugfix focussed. Changes include:
  • Fixed bug in ctx.c:ct_con_drop() which caused SEGFAULT with FreeTDS.
  • Export version of FreeTDS used in sybasect.__have_freetds__.
  • Set Sybase._ctx as the global context soon as in Sybase.py to avoid problems with undefined global ctx.
  • Look for SYBASE_OCS on all platforms during setup.py.
  • Fixed spelling error in ctx.c:global_ctx().
24 February 2003 - Sybase module 0.36pre6 released
This release is purely to fix compilation for non-FreeTDS users.
18 February 2003 - Sybase module 0.36pre4 released
This release includes some bugfixes and provides FreeTDS 0.61 support. Changes include:
  • Fixed cursor locking bug with .nextset() method.
  • Added .debug_msg() method to context type which writes to the debug log when debugging is enabled for the context object.
  • Merged AIX build changes from Dietmar Rothkamp.
  • Limit size of TEXT fields to 65536.
23 January 2003 - Sybase module 0.36pre3 released
This release includes some bugfixes and improves the FreeTDS support. Changes include:
  • Bugfix: Bind VARBINARY columns as BINARY
  • Bugxfix: Work around FreeTDS incorrect reporting of NUMERIC/DECIMAL column maxlength.
  • FreeTDS workaround: Removed references to CS_PENDING and CS_BUSY in Sybase.py.
20 November 2002 - Sybase module 0.35 released
No problems were reported with the 0.35pre3 release so the changes are minimal.
  • The sybasect extension module now includes a __version__ string.
29 October 2002 - Sybase module 0.35pre3 released
This release is identical to the 0.35pre2 release except that the freetds.h and sybasect.h files have been packaged. Oops.
28 October 2002 - Sybase module 0.35pre2 released
This release builds on the 0.35pre1 release. Changes in this release include:
  • Changed ignored server messages to (5701, 5703). Thanks to Kevin Jacobs.
  • Allocate a new CS_COMMAND for each command executed on a cursor. This behaves like an explicit close() on the cursor in between commands. This makes it possible to perform multiple .execute() commands on a cursor with FreeTDS.
  • Added array binding to cursor to gain extra performance. Set the arraysize cursor attribute before executing a command.
  • Made connection locking optional.
    Sybase.connect(..., locking = 0)
  • Native DateTime types now has separate str() and repr(). print used to display "'11/01/63'".
22 April 2002 - Sybase module 0.35pre1 released

In this release the module uses callback instead of inline error handling from the Sybase CT library. This has caused quite extensive changes to the threading support inside the low level extension module.

One of the nice side effects of using callback error handling is that server errors while executing stored procedures will now be reported correctly.

FreeTDS support is much improved in this version. You will still experience segfaults while using FreeTDS though. These issues are still being worked on.

For the adventurous, you can build for FreeTDS like this:

python setup.py build_ext -D HAVE_FREETDS -U WANT_BULKCOPY
python setup.py install
25 March 2002 - Sybase module 0.34 released

This is mostly a bug fix release.

  1. Cursor state machine fix from Phillip J. Eby.
  2. Fix for MS compiler reported by Roberto M Esguerra.
  3. Added CS_IFILE option to ct_config() for Erik A. Dahl.
11 March 2002 - Sybase module 0.33 released

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 this:
    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:

    WARNING: NEVER NEST CALLS TO Py_BEGIN_ALLOW_THREADS AND Py_END_ALLOW_THREADS!!!

    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>.
17 September 2001 - Sybase module 0.32 released

There are no functional changes in this release.

Extra conditional compilation logic has been added to allow the module to compile with more releases of Sybase. In particular, the module will compile with Sybase 11.0.3 again.

3 August 2001 - Sybase module 0.31 released

Timothy Docker reported and fixed two bugs one of which was quite nasty.

Derek Harland supplied a patch to allow mxDateTime.DateTime objects to be supplied as parameters to cursor.execute().

Changes for this release:

  1. The Connection.execute() method was incorrectly returning DATETIME column values. This was due to a bug in the internal DataBuf implementation which always returned the DATETIME value at index 0 in the buffer regardless of the fact that the buffer contained 16 column values.

    Note that the Cursor.execute() method was not affected since it only allocates buffers for one row.

    Thanks to Timothy Docker for fixing this.

  2. The internal Sybase.py context initialisation was being performed before the DB-API exceptions were defined. If the initialisation failed the module tried to raise an exception which had not been defined. Ooops.

    Thanks to Timothy Docker for fixing this.

  3. The internal DateTime object no longer allows you to modify the cracked datetime attributes. Previously you may have been fooled into thinking that modifying these attributes would change the internal value...

    Thanks to Derek Harland for pointing this out.

  4. You can now pass an mxDateTime.DateTime object as a parameter to Cursor.execute().

    Thanks to Derek Harland for implementing this feature.

18 July 2001 - Sybase module 0.30 (Graham Ashton release) released

Changes for this release:

Bugfixes:

  1. Dynamic SQL constructed for cursor is now deallocated. After around 9000 different queries over the same cursor the server was running out of procedure space.
  2. ct_con_props() CS_TDS_VERSION is an integer no a string.
  3. ct_con_props(), ct_options(), ct_config() were returning string values with trailing nul character.
  4. ct_config() CS_VERSION is an integer no a string.
  5. Fixed refcount leak in ct_res_info(CS_ORDERBY_COLS)

DB-API compliance:

  1. Implemented DB-API STRING, BINARY, NUMBER, DATETIME, and ROWID type objects.
  2. Implemented DB-API Date(), Timestamp(), DateFromTicks(), TimestampFromTicks(), and Binary() functions.

Documentation:

  1. Complete DB-API documentation for Sybase.py
  2. Low level sybasect extension module now explains how the Sybase API is wrapped - it does not attempt to explain how to use the API. Sybase have excellent documentation which covers that.

    Documentation for bulkcopy descriptors includes a small program to bulkcopy a table from one server to another using a single set of buffers.

  3. Miscellaneous docstring fixups.

Improvements and enhancements:

  1. All binary dependence on mxDateTime has been removed - it is now integrated at Python level.

    If mxDateTime is available then datetime columns will be returned as mxDateTime.DateTime objects - otherwise they are returned as internal DateTime objects.

    You can disable the use of mxDateTime by doing this:

    import Sybase
    Sybase.use_datetime = 0
  2. Renamed con object in Sybase.py to conn to be consistent with sybasect wrapper module.
  3. Reorganised and simplified cursor DB-API state machine in Sybase.py.
  4. Wrap all Sybase API functions with checks for exceptions raised by Python callback functions.
  5. Added debug, conn, and direction attributes to CS_BLKDESC object.
  6. When CS_DATAFMT structures are cleared when initialised - eliminates possibility of unexpected values.
  7. Added native Sybase datetime/smalldatetime object. Construct and use these objects like this:
    >>> import Sybase
    >>> a = Sybase.money(25.99)
    >>> type(a) <type 'MoneyType'>
    >>> b = a + 5
    >>> b 30.99
    >>> type(b) <type 'MoneyType'>
    >>> b - a 5.00
    >>> dt = Sybase.datetime('2001-07-17', Sybase.CS_DATETIME4_TYPE)
    >>> dt Jul 17 2001 12:00AM
    >>> type(dt)
    <type 'DateTimeType'>
  8. Added native Sybase money/smallmoney object.
  9. DataBuf objects can autoconvert values to money and numeric values during assignment.
27 June 2001 - Sybase module 0.28 (Brown Paper Bag) released

After shooting my mouth off about the cool things that you can do with bulkcopy I went back and tested my claims. I found that I had not implemented support for the bulkcopy optional argument to Sybase.connect()...

Changes for this release:

26 June 2001 - Sybase module 0.27 released

Changes for this release:

  • Sybase.py module no longer imports exceptions module.
  • Optional auto_commit argument has been added to Sybase.connect(). The default value is 0.
  • Optional delay_connect argument has been added to Sybase.connect(). The default value is 0. This allows you to manipulate the Sybase connection before connecting to the server.

    >>> import Sybase
    >>> db = Sybase.connect(server, user, passwd, delay_connect = 1)
    >>> db.set_property(Sybase.CS_HOSTNAME, 'secret')
    >>> db.connect()
  • Removed redundant argument from sybasect.ct_data_info()
  • Added pickle capability to NumericType - I somehow forgot to copy this over from the old 0.13 module.
  • Re-arranged sybasect.h to make it easier to follow - I hope.
  • Documentation updates.
18 June 2001 - Sybase module 0.26 released

Changes for this release:

  • A collection of Sybase example programs was found and converted to use the sybasect module. This highlighted some bugs and many omissions. For the curious the example programs have been included in the release.

          array_bind.py  diag_example.py  mult_text.py
          bulkcopy.py    dynamic_cur.py   params.py
          cursor_sel.py  dynamic_ins.py   rpc.py
          cursor_upd.py  example.py       timeout.py

    On the whole I have avoided relying on using Sybase CT library callback functions. The timeout.py example program requires the use of a callback.

    Since callbacks cause the Python interpreter to be reentered, you cannot compile the module with multi-thread support. This is controlled via the WANT_THREADS #define in sybasect.h

  • The ntsetup.py distutils program was merged into the setup.py
  • The Buffer type was renamed to DataBuf to avoid type name clashes with the Python BufferType.
  • Bug was fixed in blk_bind() which was passing Python type object by value instead of by reference - oops.
  • All of the extension types in the sybasect module are now exported.
  • More work has been done on the documentation.
7 May 2001 - Sybase module 0.24 (Timothy Docker release) released

The 0.20 and later releases are a reimplementation of the module using a thin C wrapper on the Sybase-CT API, and a Python module to provide the DB-API functionality. It is still a work in progress, but should be good enough for most purposes.

Timothy Docker sent a patch with the following changes:

  • con.c renamed to conn.c because NT still has the CON: device!!!
  • warnings from gcc -Wall fixed.
  • bug fix in CS_BLKDESC_blk_init() - missing & operator.
  • bug fix in CS_CONNECTION_ct_diag, CS_CONTEXT_cs_diag() - missing return NULL.
  • bug fixes to raise exception for unhandled properties in sybasect module.
  • ARRAY_INSERT now controlled by HAS_ARRAY_INSERT in sybasect.h
  • Initialisation via PyObject_HEAD_INIT() now conforms to example module in Python distribution. It should be possible to compile and install on NT.
  • rename max() macro to maxv() in numeric.c
  • created initial setup.py and ntsetup.py for use with distutils.

    Now you can just run the following command to install:

    bash$ python setup.py install

    Or on NT:

    > python ntsetup.py install
21 April 2001 - Sybase module 0.13 (Chad Lester release) released

Changes:

  • A refcount leak in the exception code was found and fixed by Chad Lester
20 November 2000 - Sybase module 0.09 released

Changes:

  • A Numeric object exposes the Sybase numeric / decimal data type to Python. Columns of type numeric / decimal will be returned as Numeric objects.

    Numeric objects can be used in almost all places as other Python number objects. The following operations have been implemented; +, -, *, /, int(), float(), long(), str(), cmp(), repr(), hash(), abs().

    A Numeric object has two readonly attributes; precision, and scale.

    You can create a new Numeric object by using the Sybase.numeric(value) function. This will convert the int / long / float / string object passed as value to Numeric.

    At the moment, money and money4 types are still transformed into float objects because I have not worked out how to tell the Sybase library to generate the right number of decimal places in arithmetic results. For example:

    You can pickle the new numeric data type.

    >>> import Sybase
    >>> n = Sybase.numeric(100200300400500L)
    >>> n.precision, n.scale (77, 0)
    >>> m = Sybase.numeric(n, 30, 2)
    >>> m 100200300400500.00
    >>> m.precision, m.scale
    (30, 2)

    If you want to increase the scale without modifying the precision, pass -1 as the precision.

    >>> m = Sybase.numeric(n, -1, 4)
    >>> m 100200300400500.0000
    >>> m.precision, m.scale
    (77, 4)
12 January 2000 - Sybase module - release 0.4
This is the "first" release of my Sybase module for Python