Skip to content

Commit 1ff25e7

Browse files
committed
Apply PQgetRowData()
1 parent 035c88d commit 1ff25e7

File tree

5 files changed

+110
-11
lines changed

5 files changed

+110
-11
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4059,6 +4059,34 @@ int PQsetSingleRowMode(PGconn *conn);
40594059
</listitem>
40604060
</varlistentry>
40614061

4062+
<varlistentry id="libpq-pqgetrowdata">
4063+
<term>
4064+
<function>PQgetRowData</function>
4065+
<indexterm>
4066+
<primary>PQgetRowData</primary>
4067+
</indexterm>
4068+
</term>
4069+
4070+
<listitem>
4071+
<para>
4072+
In single row mode it is possible to get row data directly,
4073+
without constructing <structname>PGresult</structname> for
4074+
each row.
4075+
4076+
<synopsis>
4077+
int PQgetRowData(PGconn *conn, PGresult **hdr, PGdataValue **columns);
4078+
</synopsis>
4079+
</para>
4080+
4081+
<para>
4082+
It can be called everywhere <function>PQgetResult</function> can.
4083+
It returns 1 and fills pointers if there is row data avilable.
4084+
It returns 0 otherwise. Then <function>PQgetResult</function>
4085+
should be called to get final status.
4086+
</para>
4087+
</listitem>
4088+
</varlistentry>
4089+
40624090
</variablelist>
40634091
</para>
40644092

src/interfaces/libpq/exports.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,4 @@ PQping 158
161161
PQpingParams 159
162162
PQlibVersion 160
163163
PQsetSingleRowMode 161
164+
PQgetRowData 162

src/interfaces/libpq/fe-exec.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,6 +1554,75 @@ pqSingleRowResult(PGconn *conn)
15541554
return pqPrepareAsyncResult(conn);
15551555
}
15561556

1557+
/*
1558+
* Get raw row data from network buffer.
1559+
*
1560+
* It duplicates the flush/read logic of PQgetResult() to be able
1561+
* to work on sync connection. It does not return any error state,
1562+
* instead it leaves that to actual PQgetResult().
1563+
*
1564+
* Returns: 1 - have row data, 0 - do not have it
1565+
*/
1566+
int
1567+
PQgetRowData(PGconn *conn, PGresult **hdrp, PGdataValue **cols)
1568+
{
1569+
if (!conn)
1570+
return 0;
1571+
1572+
/* Parse any available data, if our state permits. */
1573+
parseInput(conn);
1574+
1575+
/* If not ready to return something, block until we are. */
1576+
while (conn->asyncStatus == PGASYNC_BUSY)
1577+
{
1578+
int flushResult;
1579+
1580+
/*
1581+
* If data remains unsent, send it. Else we might be waiting for the
1582+
* result of a command the backend hasn't even got yet.
1583+
*/
1584+
while ((flushResult = pqFlush(conn)) > 0)
1585+
{
1586+
if (pqWait(FALSE, TRUE, conn))
1587+
{
1588+
flushResult = -1;
1589+
break;
1590+
}
1591+
}
1592+
1593+
/* Wait for some more data, and load it. */
1594+
if (flushResult ||
1595+
pqWait(TRUE, FALSE, conn) ||
1596+
pqReadData(conn) < 0)
1597+
{
1598+
/*
1599+
* conn->errorMessage has been set by pqWait or pqReadData. We
1600+
* want to append it to any already-received error message.
1601+
*/
1602+
pqSaveErrorResult(conn);
1603+
1604+
/* Make PQgetResult() return the error */
1605+
conn->asyncStatus = PGASYNC_READY;
1606+
break;
1607+
}
1608+
1609+
/* Parse it. */
1610+
parseInput(conn);
1611+
}
1612+
1613+
/* should PQgetResult() be called instead? */
1614+
if (conn->asyncStatus != PGASYNC_ROW_READY)
1615+
return 0;
1616+
1617+
/* allow parsing to proceed */
1618+
conn->asyncStatus = PGASYNC_BUSY;
1619+
1620+
/* return pointers to current row */
1621+
*hdrp = conn->result;
1622+
*cols = conn->rowBuf;
1623+
return 1;
1624+
}
1625+
15571626
/*
15581627
* Consume any available input from the backend
15591628
* 0 return: some kind of trouble

src/interfaces/libpq/libpq-fe.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ typedef struct pg_conn PGconn;
130130
*/
131131
typedef struct pg_result PGresult;
132132

133+
/* PGdataValue represents a data field value being passed to a row processor.
134+
* It could be either text or binary data; text data is not zero-terminated.
135+
* A SQL NULL is represented by len < 0; then value is still valid but there
136+
* are no data bytes there.
137+
*/
138+
typedef struct pgDataValue
139+
{
140+
int len; /* data length in bytes, or <0 if NULL */
141+
const char *value; /* data value, without zero-termination */
142+
} PGdataValue;
143+
133144
/* PGcancel encapsulates the information needed to cancel a running
134145
* query on an existing connection.
135146
* The contents of this struct are not supposed to be known to applications.
@@ -392,6 +403,7 @@ extern int PQsendQueryPrepared(PGconn *conn,
392403
extern PGresult *PQgetResult(PGconn *conn);
393404

394405
extern int PQsetSingleRowMode(PGconn *conn);
406+
extern int PQgetRowData(PGconn *conn, PGresult **hdrp, PGdataValue **columns);
395407

396408
/* Routines for managing an asynchronous query */
397409
extern int PQisBusy(PGconn *conn);

src/interfaces/libpq/libpq-int.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -278,17 +278,6 @@ typedef struct pgLobjfuncs
278278
Oid fn_lo_write; /* OID of backend function LOwrite */
279279
} PGlobjfuncs;
280280

281-
/* PGdataValue represents a data field value being passed to a row processor.
282-
* It could be either text or binary data; text data is not zero-terminated.
283-
* A SQL NULL is represented by len < 0; then value is still valid but there
284-
* are no data bytes there.
285-
*/
286-
typedef struct pgDataValue
287-
{
288-
int len; /* data length in bytes, or <0 if NULL */
289-
const char *value; /* data value, without zero-termination */
290-
} PGdataValue;
291-
292281
/*
293282
* PGconn stores all the state data associated with a single connection
294283
* to a backend.

0 commit comments

Comments
 (0)