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.
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...