dest.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:9k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * dest.c
  4.  *   support for various communication destinations - see include/tcop/dest.h
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/tcop/dest.c,v 1.31 1999/05/25 22:42:06 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  *  INTERFACE ROUTINES
  16.  * BeginCommand - prepare destination for tuples of the given type
  17.  * DestToFunction - identify per-tuple processing routines
  18.  * EndCommand - tell destination that no more tuples will arrive
  19.  * NullCommand - tell dest that an empty query string was recognized
  20.  * ReadyForQuery - tell dest that we are ready for a new query
  21.  *
  22.  *  NOTES
  23.  * These routines do the appropriate work before and after
  24.  * tuples are returned by a query to keep the backend and the
  25.  * "destination" portals synchronized.
  26.  *
  27.  * There is a second level of initialization/cleanup performed by the
  28.  * setup/cleanup routines identified by DestToFunction.  This could
  29.  * probably be merged with the work done by BeginCommand/EndCommand,
  30.  * but as of right now BeginCommand/EndCommand are used in a rather
  31.  * unstructured way --- some places call Begin without End, some vice
  32.  * versa --- so I think I'll just leave 'em alone for now.  tgl 1/99.
  33.  *
  34.  */
  35. #include <stdio.h> /* for sprintf() */
  36. #include <string.h>
  37. #include "postgres.h"
  38. #include "access/htup.h"
  39. #include "libpq/libpq.h"
  40. #include "libpq/pqformat.h"
  41. #include "access/printtup.h"
  42. #include "utils/portal.h"
  43. #include "utils/palloc.h"
  44. #include "executor/executor.h"
  45. #include "tcop/dest.h"
  46. #include "catalog/pg_type.h"
  47. #include "utils/mcxt.h"
  48. #include "commands/async.h"
  49. static char CommandInfo[32] = {0};
  50. /* ----------------
  51.  * dummy DestReceiver functions
  52.  * ----------------
  53.  */
  54. static void
  55. donothingReceive(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
  56. {
  57. }
  58. static void
  59. donothingSetup(DestReceiver *self, TupleDesc typeinfo)
  60. {
  61. }
  62. static void
  63. donothingCleanup(DestReceiver *self)
  64. {
  65. }
  66. /* ----------------
  67.  * static DestReceiver structs for dest types needing no local state
  68.  * ----------------
  69.  */
  70. static DestReceiver donothingDR = {
  71. donothingReceive, donothingSetup, donothingCleanup
  72. };
  73. static DestReceiver printtup_internalDR = {
  74. printtup_internal, donothingSetup, donothingCleanup
  75. };
  76. static DestReceiver be_printtupDR = {
  77. be_printtup, donothingSetup, donothingCleanup
  78. };
  79. static DestReceiver debugtupDR = {
  80. debugtup, donothingSetup, donothingCleanup
  81. };
  82. static DestReceiver spi_printtupDR = {
  83. spi_printtup, donothingSetup, donothingCleanup
  84. };
  85. /* ----------------
  86.  * BeginCommand - prepare destination for tuples of the given type
  87.  * ----------------
  88.  */
  89. void
  90. BeginCommand(char *pname,
  91.  int operation,
  92.  TupleDesc tupdesc,
  93.  bool isIntoRel,
  94.  bool isIntoPortal,
  95.  char *tag,
  96.  CommandDest dest)
  97. {
  98. PortalEntry *entry;
  99. Form_pg_attribute *attrs = tupdesc->attrs;
  100. int natts = tupdesc->natts;
  101. int i;
  102. char    *p;
  103. switch (dest)
  104. {
  105. case Remote:
  106. case RemoteInternal:
  107. /* ----------------
  108.  * if this is a "retrieve portal" query, done
  109.  * because nothing needs to be sent to the fe.
  110.  * ----------------
  111.  */
  112. CommandInfo[0] = '';
  113. if (isIntoPortal)
  114. break;
  115. /* ----------------
  116.  * if portal name not specified for remote query,
  117.  * use the "blank" portal.
  118.  * ----------------
  119.  */
  120. if (pname == NULL)
  121. pname = "blank";
  122. /* ----------------
  123.  * send fe info on tuples we're about to send
  124.  * ----------------
  125.  */
  126. pq_puttextmessage('P', pname);
  127. /* ----------------
  128.  * if this is a retrieve, then we send back the tuple
  129.  * descriptor of the tuples.  "retrieve into" is an
  130.  * exception because no tuples are returned in that case.
  131.  * ----------------
  132.  */
  133. if (operation == CMD_SELECT && !isIntoRel)
  134. {
  135. StringInfoData buf;
  136. pq_beginmessage(&buf);
  137. pq_sendbyte(&buf, 'T'); /* tuple descriptor message type */
  138. pq_sendint(&buf, natts, 2); /* # of attributes in
  139.  * tuples */
  140. for (i = 0; i < natts; ++i)
  141. {
  142. pq_sendstring(&buf, attrs[i]->attname.data);
  143. pq_sendint(&buf, (int) attrs[i]->atttypid,
  144.    sizeof(attrs[i]->atttypid));
  145. pq_sendint(&buf, attrs[i]->attlen,
  146.    sizeof(attrs[i]->attlen));
  147. if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
  148. pq_sendint(&buf, attrs[i]->atttypmod,
  149.    sizeof(attrs[i]->atttypmod));
  150. }
  151. pq_endmessage(&buf);
  152. }
  153. break;
  154. case Local:
  155. /* ----------------
  156.  * prepare local portal buffer for query results
  157.  * and setup result for PQexec()
  158.  * ----------------
  159.  */
  160. entry = be_currentportal();
  161. if (pname != NULL)
  162. pbuf_setportalinfo(entry, pname);
  163. if (operation == CMD_SELECT && !isIntoRel)
  164. {
  165. be_typeinit(entry, tupdesc, natts);
  166. p = (char *) palloc(strlen(entry->name) + 2);
  167. p[0] = 'P';
  168. strcpy(p + 1, entry->name);
  169. }
  170. else
  171. {
  172. p = (char *) palloc(strlen(tag) + 2);
  173. p[0] = 'C';
  174. strcpy(p + 1, tag);
  175. }
  176. entry->result = p;
  177. break;
  178. case Debug:
  179. /* ----------------
  180.  * show the return type of the tuples
  181.  * ----------------
  182.  */
  183. if (pname == NULL)
  184. pname = "blank";
  185. showatts(pname, tupdesc);
  186. break;
  187. case None:
  188. default:
  189. break;
  190. }
  191. }
  192. /* ----------------
  193.  * DestToFunction - return appropriate receiver function set for dest
  194.  * ----------------
  195.  */
  196. DestReceiver *
  197. DestToFunction(CommandDest dest)
  198. {
  199. switch (dest)
  200. {
  201. case Remote:
  202. /* printtup wants a dynamically allocated DestReceiver */
  203. return printtup_create_DR();
  204. break;
  205. case RemoteInternal:
  206. return &printtup_internalDR;
  207. break;
  208. case Local:
  209. return &be_printtupDR;
  210. break;
  211. case Debug:
  212. return &debugtupDR;
  213. break;
  214. case SPI:
  215. return &spi_printtupDR;
  216. break;
  217. case None:
  218. default:
  219. return &donothingDR;
  220. break;
  221. }
  222. /*
  223.  * never gets here, but DECstation lint appears to be stupid...
  224.  */
  225. return &donothingDR;
  226. }
  227. /* ----------------
  228.  * EndCommand - tell destination that no more tuples will arrive
  229.  * ----------------
  230.  */
  231. void
  232. EndCommand(char *commandTag, CommandDest dest)
  233. {
  234. char buf[64];
  235. switch (dest)
  236. {
  237. case Remote:
  238. case RemoteInternal:
  239. /* ----------------
  240.  * tell the fe that the query is over
  241.  * ----------------
  242.  */
  243. sprintf(buf, "%s%s", commandTag, CommandInfo);
  244. pq_puttextmessage('C', buf);
  245. CommandInfo[0] = '';
  246. break;
  247. case Local:
  248. case Debug:
  249. case None:
  250. default:
  251. break;
  252. }
  253. }
  254. /*
  255.  * These are necessary to sync communications between fe/be processes doing
  256.  * COPY rel TO stdout
  257.  *
  258.  * or
  259.  *
  260.  * COPY rel FROM stdin
  261.  *
  262.  * NOTE: the message code letters are changed at protocol version 2.0
  263.  * to eliminate possible confusion with data tuple messages.
  264.  */
  265. void
  266. SendCopyBegin(void)
  267. {
  268. if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
  269. pq_putbytes("H", 1); /* new way */
  270. else
  271. pq_putbytes("B", 1); /* old way */
  272. }
  273. void
  274. ReceiveCopyBegin(void)
  275. {
  276. if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
  277. pq_putbytes("G", 1); /* new way */
  278. else
  279. pq_putbytes("D", 1); /* old way */
  280. /* We *must* flush here to ensure FE knows it can send. */
  281. pq_flush();
  282. }
  283. /* ----------------
  284.  * NullCommand - tell dest that an empty query string was recognized
  285.  *
  286.  * In FE/BE protocol version 1.0, this hack is necessary to support
  287.  * libpq's crufty way of determining whether a multiple-command
  288.  * query string is done.  In protocol 2.0 it's probably not really
  289.  * necessary to distinguish empty queries anymore, but we still do it
  290.  * for backwards compatibility with 1.0.
  291.  * ----------------
  292.  */
  293. void
  294. NullCommand(CommandDest dest)
  295. {
  296. switch (dest)
  297. {
  298. case RemoteInternal:
  299. case Remote:
  300. /* ----------------
  301.  * tell the fe that we saw an empty query string
  302.  * ----------------
  303.  */
  304. pq_putbytes("I", 2);/* note we send I and  */
  305. break;
  306. case Local:
  307. case Debug:
  308. case None:
  309. default:
  310. break;
  311. }
  312. }
  313. /* ----------------
  314.  * ReadyForQuery - tell dest that we are ready for a new query
  315.  *
  316.  * The ReadyForQuery message is sent in protocol versions 2.0 and up
  317.  * so that the FE can tell when we are done processing a query string.
  318.  *
  319.  * Note that by flushing the stdio buffer here, we can avoid doing it
  320.  * most other places and thus reduce the number of separate packets sent.
  321.  * ----------------
  322.  */
  323. void
  324. ReadyForQuery(CommandDest dest)
  325. {
  326. switch (dest)
  327. {
  328. case RemoteInternal:
  329. case Remote:
  330. if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
  331. pq_putbytes("Z", 1);
  332. /* Flush output at end of cycle in any case. */
  333. pq_flush();
  334. break;
  335. case Local:
  336. case Debug:
  337. case None:
  338. default:
  339. break;
  340. }
  341. }
  342. void
  343. UpdateCommandInfo(int operation, Oid lastoid, uint32 tuples)
  344. {
  345. switch (operation)
  346. {
  347. case CMD_INSERT:
  348. if (tuples > 1)
  349. lastoid = InvalidOid;
  350. sprintf(CommandInfo, " %u %u", lastoid, tuples);
  351. break;
  352. case CMD_DELETE:
  353. case CMD_UPDATE:
  354. sprintf(CommandInfo, " %u", tuples);
  355. break;
  356. default:
  357. CommandInfo[0] = '';
  358. break;
  359. }
  360. }