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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * portalbuf.c
  4.  *   portal buffer support routines for src/libpq/portal.c
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/libpq/portalbuf.c,v 1.16 1999/06/19 05:00:27 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  * INTERFACE ROUTINES
  16.  * pbuf_alloc   - allocate memory for libpq routines
  17.  * pbuf_free   - free memory for libpq routines
  18.  * pbuf_addPortal   - Allocate a new portal buffer
  19.  * pbuf_addGroup   - Add a new tuple group to the portal
  20.  * pbuf_addTypes   - Allocate n type blocks
  21.  * pbuf_addTuples   - Allocate a tuple block
  22.  * pbuf_addTuple   - Allocate a tuple of n fields (attributes)
  23.  * pbuf_addValues   - Allocate n bytes for a value
  24.  * pbuf_addEntry   - Allocate a portal entry
  25.  * pbuf_freeEntry   - Free a portal entry in the portal table
  26.  * pbuf_freeTypes   - Free up the space used by a portal
  27.  * pbuf_freeTuples   - free space used by tuple block
  28.  * pbuf_freeGroup   - free space used by group, types and tuples
  29.  * pbuf_freePortal   - free space used by portal and portal's group
  30.  * pbuf_getIndex   - Return the index of the portal entry
  31.  * pbuf_setup   - Set up a portal for dumping data
  32.  * pbuf_close   - Close a portal, remove it from the portal table
  33.  * pbuf_findGroup   - Return group given the group_index
  34.  * pbuf_findFnumber  - Return field index of a given field within a group
  35.  * pbuf_findFname   - Find the field name given the field index
  36.  * pbuf_checkFnumber - signal an error if field number is out of bounds
  37.  *
  38.  * NOTES
  39.  * These functions may be used by both frontend routines which
  40.  * communicate with a backend or by user-defined functions which
  41.  * are compiled or dynamically loaded into a backend.
  42.  *
  43.  * the portals[] array should be organized as a hash table for
  44.  * quick portal-by-name lookup.
  45.  *
  46.  * Do not confuse "PortalEntry" (or "PortalBuffer") with "Portal"
  47.  * see utils/mmgr/portalmem.c for why. -cim 2/22/91
  48.  *
  49.  */
  50. #include <string.h>
  51. #include <sys/types.h>
  52. #include <postgres.h>
  53. #include <libpq/libpq.h> /* where the declarations go */
  54. #include <utils/exc.h>
  55. PortalEntry **portals = (PortalEntry **) NULL;
  56. size_t portals_array_size = 0;
  57. /* portals array memory is palloc'd instead of using MemoryContexts */
  58. /* since it will be used by both front and backend programs*/
  59. /* GlobalMemory portals_mmcxt = (GlobalMemory) NULL;  */
  60. /* -------------------------------
  61.  * portals_realloc
  62.  *   grow the size of the portals array by size
  63.  *
  64.  *   also ensures that elements are initially NULL
  65.  */
  66. static void
  67. portals_realloc(size_t size)
  68. {
  69. size_t oldsize;
  70. int i;
  71. PortalEntry **newp;
  72. oldsize = portals_array_size;
  73. portals_array_size += size;
  74. if (portals)
  75. newp = (PortalEntry **) realloc(portals,
  76.  portals_array_size * sizeof(PortalEntry *));
  77. else
  78. newp = (PortalEntry **) palloc(portals_array_size * sizeof(PortalEntry *));
  79. if (newp)
  80. portals = newp;
  81. else
  82. libpq_raise(&PortalError,
  83. vararg_format("Cannot alloc more memory in portals_realloc"));
  84. for (i = oldsize; i < portals_array_size; i++)
  85. portals[i] = (PortalEntry *) NULL;
  86. }
  87. /* --------------------------------
  88.  * pbuf_alloc - allocate memory for portal buffers
  89.  *
  90.  * remember: palloc() in the backend uses the postgres MemoryContext
  91.  * library and palloc() in the frontend (fe-pqstubs.c) calls malloc().
  92.  * --------------------------------
  93.  */
  94. caddr_t
  95. pbuf_alloc(size_t size)
  96. {
  97. caddr_t addr;
  98. if (size <= 0)
  99. libpq_raise(&MemoryError, vararg_format("Invalid argument to pbuf_alloc()."));
  100. addr = (caddr_t) palloc(size);
  101. if (addr == (caddr_t) NULL)
  102. libpq_raise(&MemoryError, vararg_format("Cannot Allocate space."));
  103. return addr;
  104. }
  105. /* --------------------------------
  106.  * pbuf_free - free memory for portal buffers
  107.  *
  108.  * remember: pfree() in the backend uses the postgres MemoryContext
  109.  * library and pfree() in the frontend (fe-pqstubs.c) calls free().
  110.  * --------------------------------
  111.  */
  112. void
  113. pbuf_free(caddr_t pointer)
  114. {
  115. if (pointer)
  116. pfree(pointer);
  117. else
  118. libpq_raise(&MemoryError, vararg_format("Tried to free NULL memory pointer"));
  119. }
  120. /* --------------------------------
  121.  * pbuf_addPortal - Allocate a new portal buffer
  122.  * --------------------------------
  123.  */
  124. PortalBuffer *
  125. pbuf_addPortal()
  126. {
  127. PortalBuffer *portal;
  128. portal = (PortalBuffer *)
  129. pbuf_alloc(sizeof(PortalBuffer));
  130. portal->rule_p = 0;
  131. portal->no_tuples = 0;
  132. portal->no_groups = 0;
  133. portal->groups = NULL;
  134. return portal;
  135. }
  136. /* --------------------------------
  137.  * pbuf_addGroup - Add a new tuple group to the portal
  138.  * --------------------------------
  139.  */
  140. GroupBuffer *
  141. pbuf_addGroup(PortalBuffer *portal)
  142. {
  143. GroupBuffer *group,
  144.    *group1;
  145. group = (GroupBuffer *)
  146. pbuf_alloc(sizeof(GroupBuffer));
  147. /* Initialize the new group buffer. */
  148. group->no_tuples = 0;
  149. group->no_fields = 0;
  150. group->types = NULL;
  151. group->tuples = NULL;
  152. group->next = NULL;
  153. if ((group1 = portal->groups) == NULL)
  154. portal->groups = group;
  155. else
  156. {
  157. while (group1->next != NULL)
  158. group1 = group1->next;
  159. group1->next = group;
  160. }
  161. return group;
  162. }
  163. /* --------------------------------
  164.  * pbuf_addTypes - Allocate n type blocks
  165.  * --------------------------------
  166.  */
  167. TypeBlock  *
  168. pbuf_addTypes(int n)
  169. {
  170. TypeBlock  *types;
  171. types = (TypeBlock *)
  172. pbuf_alloc(n * sizeof(TypeBlock));
  173. return types;
  174. }
  175. /* --------------------------------
  176.  * pbuf_addTuples - Allocate a tuple block
  177.  * --------------------------------
  178.  */
  179. TupleBlock *
  180. pbuf_addTuples()
  181. {
  182. TupleBlock *tuples;
  183. tuples = (TupleBlock *)
  184. pbuf_alloc(sizeof(TupleBlock));
  185. tuples->next = NULL;
  186. tuples->tuple_index = 0;
  187. return tuples;
  188. }
  189. /* --------------------------------
  190.  * pbuf_addTuple - Allocate a tuple of n fields (attributes)
  191.  * --------------------------------
  192.  */
  193. char   **
  194. pbuf_addTuple(int n)
  195. {
  196. return (char **)
  197. pbuf_alloc(n * sizeof(char *));
  198. }
  199. /* --------------------------------
  200.  * pbuf_addTupleValueLengths - Allocate a tuple of n lengths (attributes)
  201.  * --------------------------------
  202.  */
  203. int *
  204. pbuf_addTupleValueLengths(int n)
  205. {
  206. return (int *)
  207. pbuf_alloc(n * sizeof(int));
  208. }
  209. /* --------------------------------
  210.  * pbuf_addValues - Allocate n bytes for a value
  211.  * --------------------------------
  212.  */
  213. char *
  214. pbuf_addValues(int n)
  215. {
  216. return pbuf_alloc(n);
  217. }
  218. /* --------------------------------
  219.  * pbuf_addEntry - Allocate a portal entry
  220.  * --------------------------------
  221.  */
  222. PortalEntry *
  223. pbuf_addEntry()
  224. {
  225. return (PortalEntry *)
  226. pbuf_alloc(sizeof(PortalEntry));
  227. }
  228. /* --------------------------------
  229.  * pbuf_freeEntry - Free a portal entry in the portal table
  230.  * the portal is freed separately.
  231.  * --------------------------------
  232.  */
  233. void
  234. pbuf_freeEntry(int i)
  235. {
  236. if (portals)
  237. {
  238. pbuf_free((caddr_t) portals[i]);
  239. portals[i] = NULL;
  240. }
  241. }
  242. /* --------------------------------
  243.  * pbuf_freeTypes - Free up the space used by a portal
  244.  * --------------------------------
  245.  */
  246. void
  247. pbuf_freeTypes(TypeBlock *types)
  248. {
  249. pbuf_free((caddr_t) types);
  250. }
  251. /* --------------------------------
  252.  * pbuf_freeTuples - free space used by tuple block
  253.  * --------------------------------
  254.  */
  255. void
  256. pbuf_freeTuples(TupleBlock *tuples,
  257. int no_tuples,
  258. int no_fields)
  259. {
  260. int i,
  261. j;
  262. if (no_tuples > TupleBlockSize)
  263. {
  264. pbuf_freeTuples(tuples->next, no_tuples - TupleBlockSize, no_fields);
  265. no_tuples = TupleBlockSize;
  266. }
  267. /* For each tuple, free all its attribute values. */
  268. for (i = 0; i < no_tuples; i++)
  269. {
  270. for (j = 0; j < no_fields; j++)
  271. if (tuples->values[i][j] != NULL)
  272. pbuf_free((caddr_t) tuples->values[i][j]);
  273. if (tuples->lengths[i])
  274. pbuf_free((caddr_t) tuples->lengths[i]);
  275. if (tuples->values[i])
  276. pbuf_free((caddr_t) tuples->values[i]);
  277. }
  278. pbuf_free((caddr_t) tuples);
  279. }
  280. /* --------------------------------
  281.  * pbuf_freeGroup - free space used by group, types and tuples
  282.  * --------------------------------
  283.  */
  284. void
  285. pbuf_freeGroup(GroupBuffer *group)
  286. {
  287. if (group->next != NULL)
  288. pbuf_freeGroup(group->next);
  289. if (group->types != NULL)
  290. pbuf_freeTypes(group->types);
  291. if (group->tuples != NULL)
  292. pbuf_freeTuples(group->tuples, group->no_tuples, group->no_fields);
  293. pbuf_free((caddr_t) group);
  294. }
  295. /* --------------------------------
  296.  * pbuf_freePortal - free space used by portal and portal's group
  297.  * --------------------------------
  298.  */
  299. void
  300. pbuf_freePortal(PortalBuffer *portal)
  301. {
  302. if (portal->groups != NULL)
  303. pbuf_freeGroup(portal->groups);
  304. pbuf_free((caddr_t) portal);
  305. }
  306. /* --------------------------------
  307.  * pbuf_getIndex - Return the index of the portal entry
  308.  * note: portals[] maps portal names to portal buffers.
  309.  * --------------------------------
  310.  */
  311. int
  312. pbuf_getIndex(char *pname)
  313. {
  314. int i;
  315. if (portals)
  316. {
  317. for (i = 0; i < portals_array_size; i++)
  318. if (portals[i] != NULL &&
  319. strncmp(portals[i]->name, pname, PortalNameLength) == 0)
  320. return i;
  321. }
  322. return -1;
  323. }
  324. /* --------------------------------
  325.  * pbuf_setportalname - assign a user given name to a portal
  326.  * --------------------------------
  327.  */
  328. void
  329. pbuf_setportalinfo(PortalEntry *entry, char *pname)
  330. {
  331. if (entry)
  332. StrNCpy(entry->name, pname, PortalNameLength);
  333. }
  334. /* --------------------------------
  335.  * pbuf_setup - Set up a portal for dumping data
  336.  * --------------------------------
  337.  */
  338. PortalEntry *
  339. pbuf_setup(char *pname)
  340. {
  341. int i;
  342. if (!portals) /* the portals array has not been
  343.  * allocated yet */
  344. {
  345. /* allocate portals[] array here */
  346. portals_realloc(PORTALS_INITIAL_SIZE);
  347. }
  348. /* If a portal with the same name already exists, close it. */
  349. /* else look for an empty entry in the portal table. */
  350. if ((i = pbuf_getIndex(pname)) != -1)
  351. pbuf_freePortal(portals[i]->portal);
  352. else
  353. {
  354. for (i = 0; i < portals_array_size; i++)
  355. if (portals[i] == NULL)
  356. break;
  357. /* If the portal table is full, enlarge it */
  358. if (i >= portals_array_size)
  359. portals_realloc(PORTALS_GROW_BY);
  360. portals[i] = pbuf_addEntry();
  361. strncpy(portals[i]->name, pname, PortalNameLength);
  362. }
  363. portals[i]->portal = pbuf_addPortal();
  364. portals[i]->portalcxt = NULL;
  365. portals[i]->result = NULL;
  366. return portals[i];
  367. }
  368. /* --------------------------------
  369.  * pbuf_close - Close a portal, remove it from the portal table
  370.  * and free up the space
  371.  * --------------------------------
  372.  */
  373. void
  374. pbuf_close(char *pname)
  375. {
  376. int i;
  377. if ((i = pbuf_getIndex(pname)) == -1)
  378. libpq_raise(&PortalError, vararg_format("Portal %s does not exist.", pname));
  379. pbuf_freePortal(portals[i]->portal);
  380. pbuf_freeEntry(i);
  381. }
  382. /* --------------------------------
  383.  * pbuf_findGroup - Return the group given the group_index
  384.  * --------------------------------
  385.  */
  386. GroupBuffer *
  387. pbuf_findGroup(PortalBuffer *portal,
  388.    int group_index)
  389. {
  390. GroupBuffer *group;
  391. group = portal->groups;
  392. while (group_index > 0 && group != NULL)
  393. {
  394. group = group->next;
  395. group_index--;
  396. }
  397. if (group == NULL)
  398. libpq_raise(&PortalError,
  399. vararg_format("Group index %d out of bound.", group_index));
  400. return group;
  401. }
  402. /* --------------------------------
  403.  * pbuf_findFnumber - Return the field index of a given field within a group
  404.  * --------------------------------
  405.  */
  406. int
  407. pbuf_findFnumber(GroupBuffer *group,
  408.  char *field_name)
  409. {
  410. TypeBlock  *types;
  411. int i;
  412. types = group->types;
  413. for (i = 0; i < group->no_fields; i++)
  414. if (strncmp(types[i].name, field_name, NAMEDATALEN) == 0)
  415. return i;
  416. libpq_raise(&PortalError,
  417. vararg_format("Field-name %s does not exist.", field_name));
  418. /* not reached, here to make compiler happy */
  419. return 0;
  420. }
  421. /* --------------------------------
  422.  * pbuf_checkFnumber - signal an error if field number is out of bounds
  423.  * --------------------------------
  424.  */
  425. void
  426. pbuf_checkFnumber(GroupBuffer *group,
  427.   int field_number)
  428. {
  429. if (field_number < 0 || field_number >= group->no_fields)
  430. libpq_raise(&PortalError,
  431. vararg_format("Field number %d out of bound.", field_number));
  432. }
  433. /* --------------------------------
  434.  * pbuf_findFname - Find the field name given the field index
  435.  * --------------------------------
  436.  */
  437. char *
  438. pbuf_findFname(GroupBuffer *group,
  439.    int field_number)
  440. {
  441. pbuf_checkFnumber(group, field_number);
  442. return (group->types[field_number]).name;
  443. }