FreeTDS API
Loading...
Searching...
No Matches
How to add a new type

Introduction

Adding a new type in FreeTDS is a quite complicated task involving different tasks.

To see an example you can look at commit id adb893f1381fd3ea40564c775e30dc8cdc81dcf2 ("Implement big(date)time types") and parent changes in the source repository.

libTDS changes

  • protocol. First thing to do is add the type to the protocol. A type usually have some mnemonic constant and a structure. Declare them in include/freetds/proto.h file. Note that here you should declare the structure the server use not the structure to hold the data in libTDS.
    Cfr commit id a74a06e1f97f3137f6cf1bc7319dd7a2cfb52b1f.

  • base information. Add the type to misc/types.csv file (I use LibreOffice Calc to do it). This table maintain the base information for a type.
    Cfr commit id 680cb3371e042bb372cbc5e6feb4054e50d40c1a.

  • data. There should be some code to handle this type to/from the server. This code is implemented in include/freetds/data.h and src/tds/data.c. You can either add a new set of functions to handle this new type or add the type handling do another set of types depending on how complicated is that type. One thing you have to to at this step is determine how you store that type in libTDS. This is quite important at upper level libraries will have to use these structures or even present these data to client code (like DB-Library usually do). Due to the way FreeTDS works now you would get a linker error in the ODBC part. You can either ignore the error and proceed with libTDS, add the code to ODBC or disable temporarily ODBC.
    Cfr commit id 680cb3371e042bb372cbc5e6feb4054e50d40c1a.

  • enable the type from server. In order to receive the new type from the server you have to tell the server that we support that type. This can be either done changing the protocol (usually Microsoft) or enabling some flags (capabilities for Sybase).
    Cfr commit id a498703ff9e309c656b19dd990f4cad0283a47c7.

  • conversions. Conversions are not hard to write but usually require quite a bit of coding. After extending CONV_RESULT type in include/freetds/convert.h and adding the type to the script that generate the conversion tables in src/tds/tds_willconvert.pl you have to write the big part in src/tds/covnert.c. You have to implement all kind of conversions you declared in the previous file. Reuse the functions that are there (for instance there are some parser functions). Also if there are similar types it could be helpful to convert first your type to a super type then use the conversion for that type. For instance for SMALLINT type (tds_convert_int2) the type is just readed and then tds_convert_int is called which handle any int (actually 32 bit integer). Same for data where the TDS_DATETIMEALL structure is used. Note that conversions to binary (which usually are implemented) are done in another function (tds_convert_to_binary).
    Cfr commit id 9ed52cb78f725607ac109c8c284ca7c4658d87a9.

  • string definition. Add string for your type to src/tds/token.c in tds_prtype.
    Cfr commit id ac0d3b46db7d98436cd76f906b7d455f7651faae.

  • conversion tests. You probably will have done some mistake with conversions but don't mind, there are some tests which will help sorting this out. src/tds/unittests/convert.c try any possible combination of conversion to check if all conversion are implemented (it does not check the conversions themself). src/tds/unittests/t0007.c test that your conversion are working. Just add manually the conversions you want to try.
    Cfr commit id abcc09c9a88acd0e9a45b46dab3ca44309917a02.

  • parameter. Add type/parameter declaration in tds_get_column_declaration in src/tds/query.c. Also do any necessary step to initialize the parameter to send to server.
    Cfr commit id 54fdd3233e430c045cf5524ac385770738d9e92c, commit id 88cfea19d91245372779b8893a2d62b42696cd49.

  • emulated prepared/rpc. If needed handle your type in tds_put_param_as_string in src/tds/query.c.
    Cfr commit id 017b7bf2fee0f09847e64546d27382d2f2b756f4.

ODBC changes

ODBC is the most complicated library to add a type to. Usually its data are different from libTDS so you have to add additional code for conversions which are not required by other libraries.

CT-Library changes

This is quite easy as usual the conversion in libTDS are fine for this library.

  • define type in include/cspublic.h
  • implement conversion in src/ctlib/cs.h
  • set corrent conversion from cs types to server in src/ctlib/ct.c

Cfr commit id c5e71e5ad4a557038ecedcec457e2531ab02a77b.

DB-Library changes

A bit more complicated than CT-Library but not that much.

  • add type and binding type to include/sybdb.h
  • add NULL handling in dbgetnull, dbsetnull and default_null_representation in src/dblib/dblib.c
  • add binding to dbbindtype
  • add support for conversion from/to server
  • add printable size
  • return correct type string

Cfr commit id 99dd126e0eb248dd3079b2a7cf97437fe3bcd163.

Applications changes

datacopy application requires some changes too to support new types so add them to src/apps/datacopy.c.
Cfr commit id e59c48ac39c76abb036651f8ec238090eef321c9.