Hello Pyngres

This application connects to a local Ingres database called sandbox then immediately disconnects. If it runs without error it proves that pyngres is correctly installed and that it can communicate with the database server.

There is a link at the bottom of the page to download a runnable version of this example.

Begin by importing pyngres.

import pyngres as py

Note

The import process automatically discovers and loads the Actian OpenAPI library. On Unix-like systems it uses the II_SYSTEM environment variable to find the root of the Actian installation. On Windows it loads the first OpenAPI DLL it discovers by searching the folders named in PATH.

Before the OpenAPI can be used it must be initialized by calling IIapi_initialize(). All OpenAPI functions take a single argument. The argument must be an instance of a control block appropriate to the function. To initialize the OpenAPI it is first necessary to instantiate an IIAPI_INITPARM control block. In this example it is named inp:

inp = py.IIAPI_INITPARM()

After any control block is allocated it needs to be initialized with the values to be passed to the OpenAPI function. Here the in_timeout attribute of inp is set to -1 (which indicates “no timeout”, wait forever to initialize), and in_version is assigned the local OpenAPI version number (whatever that happens to be, effectively requesting the most recent version):

inp.in_timeout = -1
inp.in_version = py.IIAPI_VERSION

Call IIapi_initialize() passing its control block:

py.IIapi_initialize(inp)

Control blocks are used not only to pass values to OpenAPI functions but also to return information to the caller. In this case the status of the function call is returned as in_status, and if the function was successful, a handle for the OpenAPI environment is returned as in_envHandle.

status = inp.in_status
if status != py.IIAPI_ST_SUCCESS:
    print('could not initialize the OpenAPI')
    quit()

Note the handle returned for the environment. It will be passed to IIapi_connect() later.

envHandle = inp.in_envHandle

Important

Functions to instantiate control blocks are synchronous; they complete and then return. But most other OpenAPI functions are asynchronous, meaning they return before completing the requested action. The application has to determine when the requested action has been completed. (See Working with Asynchronous Functions.)

The function to connect to the database is asynchronous. The simplest way to tell that any asynchronous function has finished is to repeatedly check the completion flag in its control block using a so-called “busy wait loop”. The body of the loop makes a call to IIapi_wait() to give the OpenAPI the opportunity to set the flag.

IIapi_wait() takes an instance of an IIAPI_WAITPARM. In preparation for calling asynchronous functions, instantiate one and set its wt_timeout to 0 (milliseconds), meaning “don’t wait”, return immediately.

Note

A wt_timeout of 0 means the application will spin in a “tight” loop. iIf there is nothing to do in the busy-wait loop it may instead be preferable to either allow a few milliseconds wait or even to wait indefinitely by setting wt_timeout = -1.

wtp = py.IIAPI_WAITPARM()
wtp.wt_timeout = 0

Important

The OpenAPI is implemented in C and expects to be called by applications conforming to C calling conventions using C datatypes. In Python everything is an object. Python does not understand C datatypes and the OpenAPI does not understand Python objects.

In the next piece of code co_target has to be initialized with the name of the database to connect to. But dbname is a Python str. It needs to be converted to the NUL-terminated array of bytes expected by C. That is accomplished using the str.encode() method.

Connect to the database sever by calling IIapi_connect(). It takes an instance of IIAPI_CONNPARM which has been initialized with appropriate values, most of which will not be explained here. If the connection request is successful a connection handle is returned in co_connHandle. The connection handle needs to be noted for use later.

dbname = 'sandbox'
target = dbname.encode()
cop = py.IIAPI_CONNPARM()
cop.co_target = target
cop.co_connHandle = envHandle
cop.co_type = py.IIAPI_CT_SQL
cop.co_timeout = -1

py.IIapi_connect(cop)
while not cop.co_genParm.gp_completed:
    py.IIapi_wait(wtp)

status = cop.co_genParm.gp_status
if status != py.IIAPI_ST_SUCCESS:
    print('could not connect to the database')
    quit()

connHandle = cop.co_connHandle

print('successfully connected')

The application now has a connection to an Actian database so it could start executing SQL. However it is sufficient that it has demonstrated it is possible to negotiate a connection to a database. Disconnect and terminate in an orderly fashion.

Although the following OpenAPI functions may be unfamiliar (refer to the OpenAPI Function Reference for details), the way they are invoked should be entirely clear.

dcp = py.IIAPI_DISCONNPARM()
dcp.dc_connHandle = connHandle

py.IIapi_disconnect(dcp)
while not dcp.dc_genParm.gp_completed:
    py.IIapi_wait(wtp)

rep = py.IIAPI_RELENVPARM()
rep.re_envHandle = envHandle
py.IIapi_releaseEnv(rep)

tmp = py.IIAPI_TERMPARM()
py.IIapi_terminate(tmp)

quit()

Download