Handling VARCHAR and VARBYTE Data

Everything in Python is an object, but everything in an Actian SQL DBMS is a hardware datatype or a C structure. ctypes automatically takes care of marshalling the hardware datatypes and C strings to and from Python, but the other SQL datatypes need to be accommodated as ctypes structures, which have to be defined. (See Data Marshalling for more information.)

VARCHAR() is a straightforward example of an SQL type that requires additional handling. The DBMS treats it a structure consisting of an unsigned 16-bit length indicator, followed by up to 32kb of data. VARBYTE() is handled exactly the same way.

A simple solution would be to define a function to allocate instances of a 32kb structure, large enough to contain the largest possible VARCHAR() value. That would be extremely wasteful if lots of VARCHAR() were needed.

A more economical solution allocates structures just large enough for the values that will actually be exchanged, but at the cost of a more complex method of allocation. The solution shown here consists of a function that dynamically defines a class for instances of the required size, then instantiates one.

Download

 1import ctypes
 2
 3...
 4
 5def varchar(n):
 6    '''allocate a structure for a VARCHAR(n)'''
 7
 8    class Varchar(ctypes.Structure):
 9        '''a structure to accommodate a VARCHAR(n)'''
10
11        _fields_ = [
12            ('length',ctypes.c_ushort),
13            ('value',ctypes.c_char * n) ]
14
15    return Varchar()
16
17...
18
19firstname = varchar(25)
20surname = varchar(25)
21description = varchar(2000)
22
23# use the Varchar() instances as data buffers
24import pyngres as py
25datavalues = (py.IIAPI_DATAVALUE * 3)()
26datavalues[0].dv_value = ctypes.addressof(firstname)
27datavalues[1].dv_value = ctypes.addressof(surname)
28datavalues[2].dv_value = ctypes.addressof(description)
29
30...

Download