|
8 | 8 | * Darko Prenosil <Darko.Prenosil@finteh.hr>
|
9 | 9 | * Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
|
10 | 10 | *
|
11 |
| - * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.82 2009/06/11 14:48:50 momjian Exp $ |
| 11 | + * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.83 2009/08/05 16:11:07 joe Exp $ |
12 | 12 | * Copyright (c) 2001-2009, PostgreSQL Global Development Group
|
13 | 13 | * ALL RIGHTS RESERVED;
|
14 | 14 | *
|
@@ -1635,6 +1635,89 @@ dblink_current_query(PG_FUNCTION_ARGS)
|
1635 | 1635 | PG_RETURN_DATUM(current_query(fcinfo));
|
1636 | 1636 | }
|
1637 | 1637 |
|
| 1638 | +/* |
| 1639 | + * Retrieve async notifications for a connection. |
| 1640 | + * |
| 1641 | + * Returns an setof record of notifications, or an empty set if none recieved. |
| 1642 | + * Can optionally take a named connection as parameter, but uses the unnamed connection per default. |
| 1643 | + * |
| 1644 | + */ |
| 1645 | +#define DBLINK_NOTIFY_COLS 3 |
| 1646 | + |
| 1647 | +PG_FUNCTION_INFO_V1(dblink_get_notify); |
| 1648 | +Datum |
| 1649 | +dblink_get_notify(PG_FUNCTION_ARGS) |
| 1650 | +{ |
| 1651 | + PGconn *conn = NULL; |
| 1652 | + remoteConn *rconn = NULL; |
| 1653 | + PGnotify *notify; |
| 1654 | + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; |
| 1655 | + TupleDesc tupdesc; |
| 1656 | + Tuplestorestate *tupstore; |
| 1657 | + MemoryContext per_query_ctx; |
| 1658 | + MemoryContext oldcontext; |
| 1659 | + |
| 1660 | + DBLINK_INIT; |
| 1661 | + if (PG_NARGS() == 1) |
| 1662 | + DBLINK_GET_NAMED_CONN; |
| 1663 | + else |
| 1664 | + conn = pconn->conn; |
| 1665 | + |
| 1666 | + /* create the tuplestore */ |
| 1667 | + per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; |
| 1668 | + oldcontext = MemoryContextSwitchTo(per_query_ctx); |
| 1669 | + |
| 1670 | + tupdesc = CreateTemplateTupleDesc(DBLINK_NOTIFY_COLS, false); |
| 1671 | + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "notify_name", |
| 1672 | + TEXTOID, -1, 0); |
| 1673 | + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "be_pid", |
| 1674 | + INT4OID, -1, 0); |
| 1675 | + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "extra", |
| 1676 | + TEXTOID, -1, 0); |
| 1677 | + |
| 1678 | + tupstore = tuplestore_begin_heap(true, false, work_mem); |
| 1679 | + rsinfo->returnMode = SFRM_Materialize; |
| 1680 | + rsinfo->setResult = tupstore; |
| 1681 | + rsinfo->setDesc = tupdesc; |
| 1682 | + |
| 1683 | + MemoryContextSwitchTo(oldcontext); |
| 1684 | + |
| 1685 | + PQconsumeInput(conn); |
| 1686 | + while ((notify = PQnotifies(conn)) != NULL) |
| 1687 | + { |
| 1688 | + Datum values[DBLINK_NOTIFY_COLS]; |
| 1689 | + bool nulls[DBLINK_NOTIFY_COLS]; |
| 1690 | + |
| 1691 | + memset(values, 0, sizeof(values)); |
| 1692 | + memset(nulls, 0, sizeof(nulls)); |
| 1693 | + |
| 1694 | + if (notify->relname != NULL) |
| 1695 | + values[0] = CStringGetTextDatum(notify->relname); |
| 1696 | + else |
| 1697 | + nulls[0] = true; |
| 1698 | + |
| 1699 | + values[1] = Int32GetDatum(notify->be_pid); |
| 1700 | + |
| 1701 | + if (notify->extra != NULL) |
| 1702 | + values[2] = CStringGetTextDatum(notify->extra); |
| 1703 | + else |
| 1704 | + nulls[2] = true; |
| 1705 | + |
| 1706 | + /* switch to appropriate context while storing the tuple */ |
| 1707 | + MemoryContextSwitchTo(per_query_ctx); |
| 1708 | + tuplestore_putvalues(tupstore, tupdesc, values, nulls); |
| 1709 | + MemoryContextSwitchTo(oldcontext); |
| 1710 | + |
| 1711 | + PQfreemem(notify); |
| 1712 | + PQconsumeInput(conn); |
| 1713 | + } |
| 1714 | + |
| 1715 | + /* clean up and return the tuplestore */ |
| 1716 | + tuplestore_donestoring(tupstore); |
| 1717 | + |
| 1718 | + return (Datum) 0; |
| 1719 | +} |
| 1720 | + |
1638 | 1721 | /*************************************************************
|
1639 | 1722 | * internal functions
|
1640 | 1723 | */
|
|
0 commit comments