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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * be-dumpdata.c
  4.  *   support for collection of returned tuples from an internal
  5.  *   PQ call into a backend buffer.
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  * $Id: be-dumpdata.c,v 1.25 1999/05/25 22:41:06 momjian Exp $
  10.  *
  11.  *-------------------------------------------------------------------------
  12.  */
  13. /*
  14.  * INTERFACE ROUTINES
  15.  * be_portalinit  - initialize backend portal administration
  16.  * be_portalpush  - add a portal to the top of the portal stack
  17.  * be_portalpop  - remove portal on the top of the stack & return it
  18.  * be_currentportal - return the top portal on the portal stack
  19.  * be_newportal  - return a new portal.
  20.  * be_portalinit  - initialize backend portal expected to hold results.
  21.  * be_printtup  - add a tuple to a backend portal
  22.  *
  23.  * NOTES
  24.  * Since backend user-defined operators can call queries
  25.  * which in turn call user-defined operators can call queries...
  26.  * we have to keep track of portals on a stack.  BeginCommand()
  27.  * puts portals on the stack and the PQ functions remove them.
  28.  *
  29.  */
  30. #include <string.h>
  31. #include <postgres.h>
  32. #include <lib/dllist.h>
  33. #include <libpq/libpq.h>
  34. #include <access/heapam.h>
  35. #include <access/htup.h>
  36. #include <storage/buf.h>
  37. #include <utils/memutils.h>
  38. #include <fmgr.h>
  39. #include <utils/mcxt.h>
  40. #include <utils/exc.h>
  41. #include <utils/syscache.h>
  42. #include <catalog/pg_type.h>
  43. #include <catalog/catalog.h>
  44. #include <access/printtup.h>
  45. /* ----------------
  46.  * backend portal stack for recursive PQexec calls
  47.  * ----------------
  48.  */
  49. static Dllist *be_portalstack;
  50. /* ----------------
  51.  * be_portalinit - initialize backend portal administration
  52.  *
  53.  * This is called once from InitPostgres() to initialize
  54.  * the portal stack.
  55.  * ----------------
  56.  */
  57. void
  58. be_portalinit(void)
  59. {
  60. be_portalstack = DLNewList();
  61. }
  62. /* ----------------
  63.  * be_portalpush - add a portal to the top of the portal stack
  64.  *
  65.  * used by BeginCommand()
  66.  * ----------------
  67.  */
  68. void
  69. be_portalpush(PortalEntry *entry)
  70. {
  71. DLAddTail(be_portalstack, DLNewElem(entry));
  72. }
  73. /* ----------------
  74.  * be_portalpop - remove the portal on the top of the stack & return it
  75.  *
  76.  * used by PQexec()
  77.  * ----------------
  78.  */
  79. PortalEntry *
  80. be_portalpop(void)
  81. {
  82. PortalEntry *p;
  83. Dlelem    *elt;
  84. elt = DLRemTail(be_portalstack);
  85. p = (elt ? (PortalEntry *) DLE_VAL(elt) : NULL);
  86. DLFreeElem(elt);
  87. return p;
  88. }
  89. /* ----------------
  90.  * be_currentportal - return the top portal on the portal stack
  91.  *
  92.  * used by be_printtup()
  93.  * ----------------
  94.  */
  95. PortalEntry *
  96. be_currentportal(void)
  97. {
  98. Dlelem    *elt;
  99. elt = DLGetTail(be_portalstack);
  100. return elt ? (PortalEntry *) DLE_VAL(elt) : NULL;
  101. }
  102. /* ----------------
  103.  * be_newportal - return a new portal.
  104.  *
  105.  * If the user-defined function does not specify a portal name,
  106.  * we generate a unique one.  Names are generated from a combination
  107.  * of a postgres oid and an integer counter which is incremented
  108.  * every time we ask for a local portal.
  109.  *
  110.  * used by BeginCommand()
  111.  * ----------------
  112.  */
  113. static Oid be_portaloid;
  114. static u_int be_portalcnt = 0;
  115. PortalEntry *
  116. be_newportal(void)
  117. {
  118. PortalEntry *entry;
  119. char buf[PortalNameLength];
  120. /* ----------------
  121.  * generate a new name
  122.  * ----------------
  123.  */
  124. if (be_portalcnt == 0)
  125. be_portaloid = newoid();
  126. be_portalcnt++;
  127. snprintf(buf, PortalNameLength, "be_%u_%d", be_portaloid, be_portalcnt);
  128. /* ----------------
  129.  * initialize the new portal entry and keep track
  130.  * of the current memory context for be_printtup().
  131.  * This is important - otherwise whatever we allocate
  132.  * will go away and the contents of the portal after
  133.  * PQexec() returns will be meaningless.
  134.  * ----------------
  135.  */
  136. entry = pbuf_setup(buf);
  137. entry->portalcxt = (Pointer) CurrentMemoryContext;
  138. return entry;
  139. }
  140. /* ----------------
  141.  * be_typeinit - initialize backend portal expected to hold
  142.  * query results.
  143.  *
  144.  * used by BeginCommand()
  145.  * ----------------
  146.  */
  147. void
  148. be_typeinit(PortalEntry *entry,
  149. TupleDesc tupDesc,
  150. int natts)
  151. {
  152. PortalBuffer *portal;
  153. GroupBuffer *group;
  154. int i;
  155. Form_pg_attribute *attrs = tupDesc->attrs;
  156. /* ----------------
  157.  * add a new portal group to the portal
  158.  * ----------------
  159.  */
  160. portal = entry->portal;
  161. portal->no_groups++;
  162. portal->groups = group = pbuf_addGroup(portal);
  163. group->no_fields = natts;
  164. /* ----------------
  165.  * initialize portal group type info
  166.  * ----------------
  167.  */
  168. if (natts > 0)
  169. {
  170. group->types = pbuf_addTypes(natts);
  171. for (i = 0; i < natts; ++i)
  172. {
  173. strncpy(group->types[i].name, attrs[i]->attname.data, NAMEDATALEN);
  174. group->types[i].typid = attrs[i]->atttypid;
  175. group->types[i].typlen = attrs[i]->attlen;
  176. }
  177. }
  178. }
  179. /* ----------------
  180.  * be_printtup - add a tuple to a backend portal
  181.  *
  182.  * used indirectly by ExecRetrieve()
  183.  *
  184.  * This code is pretty much copied from printtup(), dump_type()
  185.  * and dump_data().  -cim 2/12/91
  186.  * ----------------
  187.  */
  188. void
  189. be_printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
  190. {
  191. int i;
  192. Datum attr;
  193. bool isnull;
  194. Oid typoutput,
  195. typelem;
  196. PortalEntry *entry = NULL;
  197. PortalBuffer *portal = NULL;
  198. GroupBuffer *group = NULL;
  199. TupleBlock *tuples = NULL;
  200. char   **values;
  201. int    *lengths;
  202. MemoryContext savecxt;
  203. /* ----------------
  204.  * get the current portal and group
  205.  * ----------------
  206.  */
  207. entry = be_currentportal();
  208. portal = entry->portal;
  209. group = portal->groups;
  210. /* ----------------
  211.  * switch to the portal's memory context so that
  212.  * the tuples we allocate are returned to the user.
  213.  * ----------------
  214.  */
  215. savecxt = MemoryContextSwitchTo((MemoryContext) entry->portalcxt);
  216. /* ----------------
  217.  * If no tuple block yet, allocate one.
  218.  * If the current block is full, allocate another one.
  219.  * ----------------
  220.  */
  221. if (group->tuples == NULL)
  222. {
  223. tuples = group->tuples = pbuf_addTuples();
  224. tuples->tuple_index = 0;
  225. }
  226. else
  227. {
  228. tuples = group->tuples;
  229. /* walk to the end of the linked list of TupleBlocks */
  230. while (tuples->next)
  231. tuples = tuples->next;
  232. /*
  233.  * now, tuples is the last TupleBlock, check to see if it is full.
  234.  * If so, allocate a new TupleBlock and add it to the end of the
  235.  * chain
  236.  */
  237. if (tuples->tuple_index == TupleBlockSize)
  238. {
  239. tuples->next = pbuf_addTuples();
  240. tuples = tuples->next;
  241. tuples->tuple_index = 0;
  242. }
  243. }
  244. /* ----------------
  245.  * Allocate space for a tuple.
  246.  * ----------------
  247.  */
  248. tuples->values[tuples->tuple_index] = pbuf_addTuple(tuple->t_data->t_natts);
  249. tuples->lengths[tuples->tuple_index] = pbuf_addTupleValueLengths(tuple->t_data->t_natts);
  250. /* ----------------
  251.  * copy printable representations of the tuple's attributes
  252.  * to the portal.
  253.  *
  254.  * This seems silly, because the user's function which is calling
  255.  * PQexec() or PQfn() will probably just convert this back into the
  256.  * internal form anyways, but the point here is to provide a uniform
  257.  * libpq interface and this is how the fe libpq interface currently
  258.  * works. Pretty soon we'll have to add code to let the fe or be
  259.  * select the desired data representation and then deal with that.
  260.  * This should not be too hard, as there already exist typrecieve()
  261.  * and typsend() procedures for user-defined types (see pg_type.h)
  262.  * -cim 2/11/91
  263.  * ----------------
  264.  */
  265. values = tuples->values[tuples->tuple_index];
  266. lengths = tuples->lengths[tuples->tuple_index];
  267. for (i = 0; i < tuple->t_data->t_natts; i++)
  268. {
  269. attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
  270. getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
  271.   &typoutput, &typelem);
  272. lengths[i] = typeinfo->attrs[i]->attlen;
  273. if (lengths[i] == -1) /* variable length attribute */
  274. {
  275. if (!isnull)
  276. lengths[i] = VARSIZE(attr) - VARHDRSZ;
  277. else
  278. lengths[i] = 0;
  279. }
  280. if (!isnull && OidIsValid(typoutput))
  281. values[i] = fmgr(typoutput, attr, typelem,
  282.  typeinfo->attrs[i]->atttypmod);
  283. else
  284. values[i] = NULL;
  285. }
  286. /* ----------------
  287.  * increment tuple group counters
  288.  * ----------------
  289.  */
  290. portal->no_tuples++;
  291. group->no_tuples++;
  292. tuples->tuple_index++;
  293. /* ----------------
  294.  * return to the original memory context
  295.  * ----------------
  296.  */
  297. MemoryContextSwitchTo(savecxt);
  298. }