Keywords: sybase

## 3.10 DataBuf Objects

`DataBuf` objects manage buffers which are used to hold data to be sent to and received from the server.

`DataBuf` objects contain an embedded Sybase `CS_DATAFMT` structure and allocated buffers suitable for binding the contained data to Sybase-CT API functions.

When constructed from native Python or Sybase data types a buffer is created for a single value. When created using a `CS_DATAFMT` object the `count` attribute is used to allocate buffers suitable for array binding. A `count` of zero is treated the same as `1`.

The `DataBuf` objects have the same attributes as a `CS_DATAFMT` object but the attributes which describe the memory are read only and cannot be modified.

attribute | type | read only?
`name` | `string` | no
`datatype` | `int` | yes
`format` | `int` | no
`maxlength` | `int` | yes
`scale` | `int` | yes
`precision` | `int` | yes
`status` | `int` | no
`count` | `int` | yes
`usertype` | `int` | yes
`strip` | `int` | no

In addition the `DataBuf` object behaves like a fixed length mutable sequence.

Adapted from `Sybase.py`, this is how you create a set of buffers suitable for retrieving a number of rows from the server:

      def row_bind(cmd, count = 1):
          status, num_cols = cmd.ct_res_info(CS_NUMDATA)
          if status != CS_SUCCEED:
              raise 'ct_res_info'
          bufs = []
          for i in range(num_cols):
              status, fmt = cmd.ct_describe(i + 1)
              if status != CS_SUCCEED:
                  raise 'ct_describe'
              fmt.count = count
              status, buf = cmd.ct_bind(i + 1, fmt)
              if status != CS_SUCCEED:
                  raise 'ct_bind'
              bufs.append(buf)
          return bufs

Then once the rows have been fetched, this is how you extract the data from the buffers:

      def fetch_rows(cmd, bufs):
          rows = []
          status, rows_read = cmd.ct_fetch()
          if status == CS_SUCCEED:
              for i in range(rows_read):
                  row = []
                  for buf in bufs:
                      row.append(buf[i])
                  rows.append(tuple(row))
          return rows

To send a parameter to a dynamic SQL command or a stored procedure you are likely to create a `DataBuf` object directly from the value you wish to send. For example:

      if cmd.ct_command(CS_RPC_CMD, 'sp_help', CS_NO_RECOMPILE) != CS_SUCCEED:
          raise 'ct_command'
      buf = DataBuf('sysobjects')
      buf.status = CS_INPUTVALUE
      if cmd.ct_param(buf)  != CS_SUCCEED:
          raise 'ct_param'
      if cmd.ct_send() != CS_SUCCEED:
          raise 'ct_send'

Note that it is your responsibility to make sure that the buffers are not deallocated before you have finished using them. If you are not careful you will get a segmentation fault.