import asyncio
import pyngres.asyncio as py
import ctypes
...

# assume a session was started and connHandle is set. Also assume
# a transaction is already in progress and tranHandle has a value, or
# tranHandle is set to None, indicating the start of a new transaction

async def exec_select():
    '''execute a SELECT statement and receive rows'''

    # encode the query so the DBMS can understand it
    sql = (
        "SELECT name, weight "
        "FROM foo " 
        "WHERE ordernr = 71025" )
    queryText = sql.encode()

    qyp = py.IIAPI_QUERYPARM()
    qyp.qy_connHandle = connHandle
    qyp.qy_queryType = py.IIAPI_QT_QUERY
    qyp.qy_queryText = queryText
    await py.IIapi_query(qyp)

    tranHandle = qyp.qy_tranHandle
    stmtHandle = qyp.qy_stmtHandle

    # get result descriptors
    gdp = py.IIAPI_GETDESCRPARM()
    gdp.gd_stmtHandle = stmtHandle
    await py.IIapi_getDescriptor(gdp)

    # note the number of columns being returned
    n_columns = gdp.gd_descriptorCount

    # allocate a sufficiently large list of IIAPI_DATAVALUEs  
    datavalues = (py.IIAPI_DATAVALUE * n_columns)()

    # allocate buffers for name and weight
    name = ctypes.c_buffer(25)
    weight = ctypes.c_double()

    # point to the buffers 
    datavalues[0].dv_value = ctypes.addressof(name)
    datavalues[1].dv_value = ctypes.addressof(weight)

    # get one result row at a time from the server; loop until IIAPI_ST_NO_DATA
    gcp = py.IIAPI_GETCOLPARM()
    gcp.gc_columnCount = n_columns
    gcp.gc_rowCount = 1             # number of rows to return per iteration
    gcp.gc_datavalues = datavalues
    gcp.gc_stmtHandle = stmtHandle
    while True:
        await py.IIapi_getColumns(gcp)
        if gcp.gc_genParm.gp_status == py.IIAPI_ST_NO_DATA:
            break

        # display the result row
        print(f'name: {name.value}, weight: {weight.value}')

    # release the decriptor array allocated by the OpenAPI
    clp = py.IIAPI_CLOSEPARM()
    clp.cl_stmtHandle = stmtHandle
    await py.IIapi_close(clp)

    ...
