head 1.16; access; symbols release_4_2:1.16 aix_ok:1.15 Version_2_1:1.7; locks; strict; comment @ * @; 1.16 date 94.01.13.17.23.48; author jiangwu; state Exp; branches; next 1.15; 1.15 date 93.01.16.03.14.59; author aoki; state Exp; branches; next 1.14; 1.14 date 92.05.06.06.02.28; author mer; state Exp; branches; next 1.13; 1.13 date 92.05.05.18.53.14; author mer; state Exp; branches; next 1.12; 1.12 date 92.03.06.22.18.14; author clarsen; state Exp; branches; next 1.11; 1.11 date 92.02.27.20.38.47; author clarsen; state Exp; branches; next 1.10; 1.10 date 92.02.25.15.31.27; author clarsen; state Exp; branches; next 1.9; 1.9 date 91.11.11.22.59.03; author hong; state Exp; branches; next 1.8; 1.8 date 91.05.23.18.49.01; author kemnitz; state Exp; branches; next 1.7; 1.7 date 91.03.09.03.12.53; author kemnitz; state Exp; branches; next 1.6; 1.6 date 91.03.08.19.48.41; author kemnitz; state Exp; branches; next 1.5; 1.5 date 91.02.23.23.05.48; author cimarron; state Exp; branches; next 1.4; 1.4 date 91.02.20.00.41.19; author cimarron; state Exp; branches; next 1.3; 1.3 date 91.02.11.17.17.33; author cimarron; state Exp; branches; next 1.2; 1.2 date 91.02.11.15.37.53; author cimarron; state Exp; branches; next 1.1; 1.1 date 91.02.10.18.19.46; author cimarron; state Exp; branches; next ; desc @reorganization of libpq routines to provide PQexec and PQfn functionality from both the front end applications and the postgres backend. @ 1.16 log @Minor change to handling of null query -- jw, 1/13/94 @ text @/* ---------------------------------------------------------------- * FILE * dest.c * * DESCRIPTION * support for various communication destinations - see lib/H/tcop/dest.h * * INTERFACE ROUTINES * BeginCommand - prepare destination for tuples of the given type * EndCommand - tell destination that no more tuples will arrive * NullCommand - tell dest that the last of a query sequence was processed * * NOTES * These routines do the appropriate work before and after * tuples are returned by a query to keep the backend and the * "destination" portals synchronized. * * IDENTIFICATION * $Header: /private/src/postgres/src/backend/tcop/RCS/dest.c,v 1.15 1993/01/16 03:14:59 aoki Exp jiangwu $ * ---------------------------------------------------------------- */ #include "tmp/postgres.h" RcsId("$Header: /private/src/postgres/src/backend/tcop/RCS/dest.c,v 1.15 1993/01/16 03:14:59 aoki Exp jiangwu $"); #include "parse.h" #include "access/htup.h" #include "tmp/simplelists.h" #include "tmp/libpq-be.h" #include "access/printtup.h" #include "tmp/portal.h" #include "utils/log.h" #include "nodes/pg_lisp.h" #include "tcop/dest.h" #include "catalog/pg_type.h" #include "utils/mcxt.h" /* ---------------- * output functions * ---------------- */ void donothing(tuple, attrdesc) List tuple; List attrdesc; { } void (*DestToFunction(dest))() CommandDest dest; { switch (dest) { case RemoteInternal: return printtup_internal; break; case Remote: return printtup; break; case Local: return be_printtup; break; case Debug: return debugtup; break; case None: default: return donothing; break; } /* * never gets here, but DECstation lint appears to be stupid... */ return donothing; } #define IS_APPEND_TAG(tag) (*tag == 'A' && *(tag+1) == 'P') /* ---------------- * EndCommand - tell destination that no more tuples will arrive * ---------------- */ void EndCommand(commandTag, dest) String commandTag; CommandDest dest; { char buf[64]; switch (dest) { case RemoteInternal: case Remote: /* ---------------- * tell the fe that the query is over * ---------------- */ pq_putnchar("C", 1); pq_putint(0, 4); if (IS_APPEND_TAG(commandTag)) { sprintf(buf, "%s %d", commandTag, GetAppendOid()); pq_putstr(buf); } else pq_putstr(commandTag); pq_flush(); break; case Local: case Debug: break; case CopyEnd: pq_putnchar("Z", 1); pq_flush(); break; case None: default: break; } } /* * These are necessary to sync communications between fe/be processes doing * COPY rel TO stdout * * or * * COPY rel FROM stdin * */ void SendCopyBegin() { pq_putnchar("B", 1); pq_putint(0, 4); pq_flush(); } void ReceiveCopyBegin() { pq_putnchar("D", 1); pq_putint(0, 4); pq_flush(); } /* ---------------- * NullCommand - tell dest that the last of a query sequence was processed * * Necessary to implement the hacky FE/BE interface to handle * multiple-return queries. * ---------------- */ void NullCommand(dest) CommandDest dest; { switch (dest) { case RemoteInternal: case Remote: { #if 0 /* Do any asynchronous notification. If front end wants to poll, it can send null queries to call this function. */ PQNotifyList *nPtr; extern GlobalMemory notifyContext; MemoryContext orig; if (notifyContext == NULL) { notifyContext = CreateGlobalMemory("notify"); } orig = MemoryContextSwitchTo((MemoryContext)notifyContext); for (nPtr = PQnotifies() ; nPtr != NULL; nPtr = (PQNotifyList *)SLGetSucc(&nPtr->Node)) { pq_putnchar("A",1); pq_putint(0, 4); pq_putstr(nPtr->relname); pq_putint(nPtr->be_pid,4); PQremoveNotify(nPtr); } pq_flush(); PQcleanNotify(); /* garbage collect */ (void) MemoryContextSwitchTo(orig); #endif /* ---------------- * tell the fe that the last of the queries has finished * ---------------- */ pq_putnchar("I", 1); pq_putint(0, 4); pq_flush(); } break; case Local: case Debug: case None: default: break; } } /* ---------------- * BeginCommand - prepare destination for tuples of the given type * ---------------- */ void BeginCommand(pname, operation, attinfo, isIntoRel, isIntoPortal, tag, dest) char *pname; int operation; LispValue attinfo; bool isIntoRel; bool isIntoPortal; char *tag; CommandDest dest; { PortalEntry *entry; struct attribute **attrs; int natts; int i; char *p; natts = CInteger(CAR(attinfo)); attrs = (struct attribute **) CADR(attinfo); switch (dest) { case RemoteInternal: case Remote: /* ---------------- * if this is a "retrieve portal" query, just return * because nothing needs to be sent to the fe. * ---------------- */ ResetAppendOid(); if (isIntoPortal) return; /* ---------------- * if portal name not specified for remote query, * use the "blank" portal. * ---------------- */ if (pname == NULL) pname = "blank"; /* ---------------- * send fe info on tuples we're about to send * ---------------- */ pq_flush(); pq_putnchar("P", 1); /* new portal.. */ pq_putint(0, 4); /* xid */ pq_putstr(pname); /* portal name */ /* ---------------- * if this is a retrieve, then we send back the tuple * descriptor of the tuples. "retrieve into" is an * exception because no tuples are returned in that case. * ---------------- */ if (operation == RETRIEVE && !isIntoRel) { pq_putnchar("T", 1); /* type info to follow.. */ pq_putint(natts, 2); /* number of attributes in tuples */ for (i = 0; i < natts; ++i) { pq_putstr(attrs[i]->attname); /* if 16 char name oops.. */ pq_putint((int) attrs[i]->atttypid, 4); pq_putint(attrs[i]->attlen, 2); } } pq_flush(); break; case Local: /* ---------------- * prepare local portal buffer for query results * and setup result for PQexec() * ---------------- */ entry = be_currentportal(); if (pname != NULL) pbuf_setportalinfo(entry, pname); if (operation == RETRIEVE && !isIntoRel) { be_typeinit(entry, attrs, natts); p = (char *) palloc(strlen(entry->name)+2); p[0] = 'P'; strcpy(p+1,entry->name); } else { p = (char *) palloc(strlen(tag)+2); p[0] = 'C'; strcpy(p+1,tag); } entry->result = p; break; case Debug: /* ---------------- * show the return type of the tuples * ---------------- */ if (pname == NULL) pname = "blank"; showatts(pname, natts, attrs); break; case None: default: break; } } static ObjectId AppendOid; void ResetAppendOid() { AppendOid = InvalidObjectId; } #define MULTI_TUPLE_APPEND -1 void UpdateAppendOid(newoid) ObjectId newoid; { /* * First update after AppendOid was reset (at command beginning). */ if (AppendOid == InvalidObjectId) AppendOid = newoid; /* * Already detected a multiple tuple append, return a void oid ;) */ else if (AppendOid == MULTI_TUPLE_APPEND) return; /* * Oid has been assigned once before, tag this as a multiple tuple * append. */ else AppendOid = MULTI_TUPLE_APPEND; } ObjectId GetAppendOid() { if (AppendOid == MULTI_TUPLE_APPEND) return InvalidObjectId; return AppendOid; } @ 1.15 log @removed references to utils/fmgr.h and parser/parse.h @ text @d19 1 a19 1 * $Header: /home2/aoki/postgres/src/backend/tcop/RCS/dest.c,v 1.14 1992/05/06 06:02:28 mer Exp aoki $ d25 1 a25 1 RcsId("$Header: /home2/aoki/postgres/src/backend/tcop/RCS/dest.c,v 1.14 1992/05/06 06:02:28 mer Exp aoki $"); d171 1 d196 1 a196 1 @ 1.14 log @append oid change - returns valid oid only when exactly 1 tuple appended @ text @d19 1 a19 1 * $Header: /users/mer/pg/src/tcop/RCS/dest.c,v 1.13 1992/05/05 18:53:14 mer Exp mer $ d25 1 a25 1 RcsId("$Header: /users/mer/pg/src/tcop/RCS/dest.c,v 1.13 1992/05/05 18:53:14 mer Exp mer $"); d27 1 a27 1 #include "parser/parse.h" @ 1.13 log @add some trivial functionality to return last oid of newly append tuples @ text @d19 1 a19 1 * $Header: /users/mer/pg/src/tcop/RCS/dest.c,v 1.12 1992/03/06 22:18:14 clarsen Exp mer $ d25 1 a25 1 RcsId("$Header: /users/mer/pg/src/tcop/RCS/dest.c,v 1.12 1992/03/06 22:18:14 clarsen Exp mer $"); d86 1 a86 1 #define IS_APPEND_TAG(tag) (*tag == 'A') d110 1 a110 1 sprintf(buf, "%s %d", commandTag, GetLastOid()); d245 1 a245 1 ResetLastOid(); d325 1 a325 1 static ObjectId LastOid; d328 1 a328 1 ResetLastOid() d330 1 a330 1 LastOid = InvalidObjectId; d333 2 d336 1 a336 1 UpdateLastOid(newoid) d339 16 a354 1 LastOid = newoid; d358 1 a358 1 GetLastOid() d360 3 a362 1 return LastOid; @ 1.12 log @Binary Portals @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.11 92/02/27 20:38:47 clarsen Exp Locker: clarsen $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.11 92/02/27 20:38:47 clarsen Exp Locker: clarsen $"); d86 2 d97 2 d108 7 a114 1 pq_putstr(commandTag); d245 1 d323 21 @ 1.11 log @diff. type @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.10 92/02/25 15:31:27 clarsen Exp Locker: clarsen $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.10 92/02/25 15:31:27 clarsen Exp Locker: clarsen $"); d57 4 d96 1 d159 1 d228 1 @ 1.10 log @async portals. @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.9 91/11/11 22:59:03 hong Exp Locker: clarsen $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.9 91/11/11 22:59:03 hong Exp Locker: clarsen $"); d159 1 a159 1 extern MemoryContext notifyContext; @ 1.9 log @for prototyping @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.8 91/05/23 18:49:01 kemnitz Exp Locker: hong $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.8 91/05/23 18:49:01 kemnitz Exp Locker: hong $"); d29 1 d39 1 d154 26 a179 1 case Remote: d187 1 @ 1.8 log @got rid of lint warning "has return(e); and return;" @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.7 91/03/09 03:12:53 kemnitz Exp Locker: kemnitz $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.7 91/03/09 03:12:53 kemnitz Exp Locker: kemnitz $"); a26 1 #include "tcop/dest.h" d28 1 d30 1 d35 1 a49 8 /* ---------------- * DestToFunction - return the proper "output" function for dest * ---------------- */ extern void debugtup(); extern void printtup(); extern void be_printtup(); a277 1 @ 1.7 log @fixed problem in switch. @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.6 91/03/08 19:48:41 kemnitz Exp Locker: kemnitz $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.6 91/03/08 19:48:41 kemnitz Exp Locker: kemnitz $"); d78 6 @ 1.6 log @New copy command protocols. @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.5 91/02/23 23:05:48 cimarron Exp Locker: kemnitz $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.5 91/02/23 23:05:48 cimarron Exp Locker: kemnitz $"); d103 1 @ 1.5 log @PQexec() now works correctly in the backend @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.4 91/02/20 00:41:19 cimarron Exp Locker: cimarron $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.4 91/02/20 00:41:19 cimarron Exp Locker: cimarron $"); d103 4 d111 26 @ 1.4 log @added support for "Local" tuple destinations via be_printtup @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.3 91/02/11 17:17:33 cimarron Exp Locker: cimarron $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.3 91/02/11 17:17:33 cimarron Exp Locker: cimarron $"); d29 1 a29 1 #include "tmp/libpq.h" d48 4 a55 4 /* ---------------- * DestToFunction - return the proper "output" function for dest * ---------------- */ d81 59 d144 1 a144 1 BeginCommand(pname, attinfo, operation, isInto, dest) d146 1 d148 3 a150 2 int operation; bool isInto; d157 2 a158 1 d165 8 d195 1 a195 1 if (operation == RETRIEVE && !isInto) { d211 1 d214 5 a218 2 entry = (PortalEntry *) be_newportal(pname); if (operation == RETRIEVE && !isInto) d220 9 a228 1 be_portalpush(entry); a247 58 /* ---------------- * EndCommand - tell destination that no more tuples will arrive * ---------------- */ void EndCommand(commandTag, dest) String commandTag; CommandDest dest; { switch (dest) { case Remote: /* ---------------- * tell the fe that the query is over * ---------------- */ pq_putnchar("C", 1); pq_putint(0, 4); pq_putstr(commandTag); pq_flush(); break; case Local: case Debug: case None: default: break; } } /* ---------------- * NullCommand - tell dest that the last of a query sequence was processed * * Necessary to implement the hacky FE/BE interface to handle * multiple-return queries. * ---------------- */ void NullCommand(dest) CommandDest dest; { switch (dest) { case Remote: /* ---------------- * tell the fe that the last of the queries has finished * ---------------- */ pq_putnchar("I", 1); pq_putint(0, 4); pq_flush(); break; case Local: case Debug: case None: default: break; } } @ 1.3 log @changed ExecMain interface to use new "communication destination" code instead of old hacky lisp interface. @ text @d6 1 a6 1 * support for various command destinations - see lib/H/tcop/dest.h d19 1 a19 1 * $Header: RCS/dest.c,v 1.2 91/02/11 15:37:53 cimarron Exp Locker: cimarron $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.2 91/02/11 15:37:53 cimarron Exp Locker: cimarron $"); d29 2 a31 1 #include "tmp/portal.h" d50 1 d66 1 a66 1 return donothing; d92 1 d94 2 a95 2 int natts; int i; d103 8 d139 8 d154 3 d172 1 a172 1 String commandTag; @ 1.2 log @moved some communication processing from pquery.c to BeginCommand() in dest.c and fixed a problem with storing dest in the query descriptor. @ text @d19 1 a19 1 * $Header: RCS/dest.c,v 1.1 91/02/10 18:19:46 cimarron Exp Locker: cimarron $ d25 1 a25 1 RcsId("$Header: RCS/dest.c,v 1.1 91/02/10 18:19:46 cimarron Exp Locker: cimarron $"); d35 42 @ 1.1 log @Initial revision @ text @d19 1 a19 1 * $Header$ d25 1 a25 1 RcsId("$Header: RCS/slaves.c,v 1.6 90/09/10 20:45:02 hong Exp Locker: hong $"); d28 1 a36 35 * initport * * XXX change all these "P"'s and "T"'s to use #define constants * ---------------- */ void initport(name, natts, attinfo) char *name; int natts; struct attribute *attinfo[]; { register int i; /* ---------------- * send fe info on tuples we're about to send * ---------------- */ pq_putnchar("P", 1); /* new portal.. */ pq_putint(0, 4); /* xid */ pq_putstr(name); /* portal name */ pq_putnchar("T", 1); /* type info to follow.. */ pq_putint(natts, 2); /* number of attributes in tuples */ /* ---------------- * send tuple attribute types to fe * ---------------- */ for (i = 0; i < natts; ++i) { pq_putstr(attinfo[i]->attname); /* if 16 char name oops.. */ pq_putint((int) attinfo[i]->atttypid, 4); pq_putint(attinfo[i]->attlen, 2); } } /* ---------------- d41 1 a41 1 BeginCommand(pname, attinfo, dest) d44 2 d49 2 a50 1 int nattrs; d52 1 a52 1 nattrs = CInteger(CAR(attinfo)); d57 4 d62 20 a81 1 initport(pname, nattrs, attrs); d89 5 a93 1 showatts(pname, nattrs, attrs); d113 4 d144 4 @