📄 portalbuf.c
字号:
/*------------------------------------------------------------------------- * * portalbuf.c * portal buffer support routines for src/libpq/portal.c * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/libpq/portalbuf.c,v 1.16 1999/06/19 05:00:27 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES * pbuf_alloc - allocate memory for libpq routines * pbuf_free - free memory for libpq routines * pbuf_addPortal - Allocate a new portal buffer * pbuf_addGroup - Add a new tuple group to the portal * pbuf_addTypes - Allocate n type blocks * pbuf_addTuples - Allocate a tuple block * pbuf_addTuple - Allocate a tuple of n fields (attributes) * pbuf_addValues - Allocate n bytes for a value * pbuf_addEntry - Allocate a portal entry * pbuf_freeEntry - Free a portal entry in the portal table * pbuf_freeTypes - Free up the space used by a portal * pbuf_freeTuples - free space used by tuple block * pbuf_freeGroup - free space used by group, types and tuples * pbuf_freePortal - free space used by portal and portal's group * pbuf_getIndex - Return the index of the portal entry * pbuf_setup - Set up a portal for dumping data * pbuf_close - Close a portal, remove it from the portal table * pbuf_findGroup - Return group given the group_index * pbuf_findFnumber - Return field index of a given field within a group * pbuf_findFname - Find the field name given the field index * pbuf_checkFnumber - signal an error if field number is out of bounds * * NOTES * These functions may be used by both frontend routines which * communicate with a backend or by user-defined functions which * are compiled or dynamically loaded into a backend. * * the portals[] array should be organized as a hash table for * quick portal-by-name lookup. * * Do not confuse "PortalEntry" (or "PortalBuffer") with "Portal" * see utils/mmgr/portalmem.c for why. -cim 2/22/91 * */#include <string.h>#include <sys/types.h>#include <postgres.h>#include <libpq/libpq.h> /* where the declarations go */#include <utils/exc.h>PortalEntry **portals = (PortalEntry **) NULL;size_t portals_array_size = 0;/* portals array memory is palloc'd instead of using MemoryContexts *//* since it will be used by both front and backend programs*//* GlobalMemory portals_mmcxt = (GlobalMemory) NULL; *//* ------------------------------- * portals_realloc * grow the size of the portals array by size * * also ensures that elements are initially NULL */static voidportals_realloc(size_t size){ size_t oldsize; int i; PortalEntry **newp; oldsize = portals_array_size; portals_array_size += size; if (portals) newp = (PortalEntry **) realloc(portals, portals_array_size * sizeof(PortalEntry *)); else newp = (PortalEntry **) palloc(portals_array_size * sizeof(PortalEntry *)); if (newp) portals = newp; else libpq_raise(&PortalError, vararg_format("Cannot alloc more memory in portals_realloc")); for (i = oldsize; i < portals_array_size; i++) portals[i] = (PortalEntry *) NULL;}/* -------------------------------- * pbuf_alloc - allocate memory for portal buffers * * remember: palloc() in the backend uses the postgres MemoryContext * library and palloc() in the frontend (fe-pqstubs.c) calls malloc(). * -------------------------------- */caddr_tpbuf_alloc(size_t size){ caddr_t addr; if (size <= 0) libpq_raise(&MemoryError, vararg_format("Invalid argument to pbuf_alloc().")); addr = (caddr_t) palloc(size); if (addr == (caddr_t) NULL) libpq_raise(&MemoryError, vararg_format("Cannot Allocate space.")); return addr;}/* -------------------------------- * pbuf_free - free memory for portal buffers * * remember: pfree() in the backend uses the postgres MemoryContext * library and pfree() in the frontend (fe-pqstubs.c) calls free(). * -------------------------------- */voidpbuf_free(caddr_t pointer){ if (pointer) pfree(pointer); else libpq_raise(&MemoryError, vararg_format("Tried to free NULL memory pointer"));}/* -------------------------------- * pbuf_addPortal - Allocate a new portal buffer * -------------------------------- */PortalBuffer *pbuf_addPortal(){ PortalBuffer *portal; portal = (PortalBuffer *) pbuf_alloc(sizeof(PortalBuffer)); portal->rule_p = 0; portal->no_tuples = 0; portal->no_groups = 0; portal->groups = NULL; return portal;}/* -------------------------------- * pbuf_addGroup - Add a new tuple group to the portal * -------------------------------- */GroupBuffer *pbuf_addGroup(PortalBuffer *portal){ GroupBuffer *group, *group1; group = (GroupBuffer *) pbuf_alloc(sizeof(GroupBuffer)); /* Initialize the new group buffer. */ group->no_tuples = 0; group->no_fields = 0; group->types = NULL; group->tuples = NULL; group->next = NULL; if ((group1 = portal->groups) == NULL) portal->groups = group; else { while (group1->next != NULL) group1 = group1->next; group1->next = group; } return group;}/* -------------------------------- * pbuf_addTypes - Allocate n type blocks * -------------------------------- */TypeBlock *pbuf_addTypes(int n){ TypeBlock *types; types = (TypeBlock *) pbuf_alloc(n * sizeof(TypeBlock)); return types;}/* -------------------------------- * pbuf_addTuples - Allocate a tuple block * -------------------------------- */TupleBlock *pbuf_addTuples(){ TupleBlock *tuples; tuples = (TupleBlock *) pbuf_alloc(sizeof(TupleBlock)); tuples->next = NULL; tuples->tuple_index = 0; return tuples;}/* -------------------------------- * pbuf_addTuple - Allocate a tuple of n fields (attributes) * -------------------------------- */char **pbuf_addTuple(int n){ return (char **) pbuf_alloc(n * sizeof(char *));}/* -------------------------------- * pbuf_addTupleValueLengths - Allocate a tuple of n lengths (attributes) * -------------------------------- */int *pbuf_addTupleValueLengths(int n){ return (int *) pbuf_alloc(n * sizeof(int));}/* -------------------------------- * pbuf_addValues - Allocate n bytes for a value * -------------------------------- */char *pbuf_addValues(int n){ return pbuf_alloc(n);}/* -------------------------------- * pbuf_addEntry - Allocate a portal entry * -------------------------------- */PortalEntry *pbuf_addEntry(){ return (PortalEntry *) pbuf_alloc(sizeof(PortalEntry));}/* -------------------------------- * pbuf_freeEntry - Free a portal entry in the portal table * the portal is freed separately. * -------------------------------- */voidpbuf_freeEntry(int i){ if (portals) { pbuf_free((caddr_t) portals[i]); portals[i] = NULL; }}/* -------------------------------- * pbuf_freeTypes - Free up the space used by a portal * -------------------------------- */voidpbuf_freeTypes(TypeBlock *types){ pbuf_free((caddr_t) types);}/* -------------------------------- * pbuf_freeTuples - free space used by tuple block * -------------------------------- */voidpbuf_freeTuples(TupleBlock *tuples, int no_tuples, int no_fields){ int i, j; if (no_tuples > TupleBlockSize) { pbuf_freeTuples(tuples->next, no_tuples - TupleBlockSize, no_fields); no_tuples = TupleBlockSize; } /* For each tuple, free all its attribute values. */ for (i = 0; i < no_tuples; i++) { for (j = 0; j < no_fields; j++) if (tuples->values[i][j] != NULL) pbuf_free((caddr_t) tuples->values[i][j]); if (tuples->lengths[i]) pbuf_free((caddr_t) tuples->lengths[i]); if (tuples->values[i]) pbuf_free((caddr_t) tuples->values[i]); } pbuf_free((caddr_t) tuples);}/* -------------------------------- * pbuf_freeGroup - free space used by group, types and tuples * -------------------------------- */voidpbuf_freeGroup(GroupBuffer *group){ if (group->next != NULL) pbuf_freeGroup(group->next); if (group->types != NULL) pbuf_freeTypes(group->types); if (group->tuples != NULL) pbuf_freeTuples(group->tuples, group->no_tuples, group->no_fields); pbuf_free((caddr_t) group);}/* -------------------------------- * pbuf_freePortal - free space used by portal and portal's group * -------------------------------- */voidpbuf_freePortal(PortalBuffer *portal){ if (portal->groups != NULL) pbuf_freeGroup(portal->groups); pbuf_free((caddr_t) portal);}/* -------------------------------- * pbuf_getIndex - Return the index of the portal entry * note: portals[] maps portal names to portal buffers. * -------------------------------- */intpbuf_getIndex(char *pname){ int i; if (portals) { for (i = 0; i < portals_array_size; i++) if (portals[i] != NULL && strncmp(portals[i]->name, pname, PortalNameLength) == 0) return i; } return -1;}/* -------------------------------- * pbuf_setportalname - assign a user given name to a portal * -------------------------------- */voidpbuf_setportalinfo(PortalEntry *entry, char *pname){ if (entry) StrNCpy(entry->name, pname, PortalNameLength);}/* -------------------------------- * pbuf_setup - Set up a portal for dumping data * -------------------------------- */PortalEntry *pbuf_setup(char *pname){ int i; if (!portals) /* the portals array has not been * allocated yet */ { /* allocate portals[] array here */ portals_realloc(PORTALS_INITIAL_SIZE); } /* If a portal with the same name already exists, close it. */ /* else look for an empty entry in the portal table. */ if ((i = pbuf_getIndex(pname)) != -1) pbuf_freePortal(portals[i]->portal); else { for (i = 0; i < portals_array_size; i++) if (portals[i] == NULL) break; /* If the portal table is full, enlarge it */ if (i >= portals_array_size) portals_realloc(PORTALS_GROW_BY); portals[i] = pbuf_addEntry(); strncpy(portals[i]->name, pname, PortalNameLength); } portals[i]->portal = pbuf_addPortal(); portals[i]->portalcxt = NULL; portals[i]->result = NULL; return portals[i];}/* -------------------------------- * pbuf_close - Close a portal, remove it from the portal table * and free up the space * -------------------------------- */voidpbuf_close(char *pname){ int i; if ((i = pbuf_getIndex(pname)) == -1) libpq_raise(&PortalError, vararg_format("Portal %s does not exist.", pname)); pbuf_freePortal(portals[i]->portal); pbuf_freeEntry(i);}/* -------------------------------- * pbuf_findGroup - Return the group given the group_index * -------------------------------- */GroupBuffer *pbuf_findGroup(PortalBuffer *portal, int group_index){ GroupBuffer *group; group = portal->groups; while (group_index > 0 && group != NULL) { group = group->next; group_index--; } if (group == NULL) libpq_raise(&PortalError, vararg_format("Group index %d out of bound.", group_index)); return group;}/* -------------------------------- * pbuf_findFnumber - Return the field index of a given field within a group * -------------------------------- */intpbuf_findFnumber(GroupBuffer *group, char *field_name){ TypeBlock *types; int i; types = group->types; for (i = 0; i < group->no_fields; i++) if (strncmp(types[i].name, field_name, NAMEDATALEN) == 0) return i; libpq_raise(&PortalError, vararg_format("Field-name %s does not exist.", field_name)); /* not reached, here to make compiler happy */ return 0;}/* -------------------------------- * pbuf_checkFnumber - signal an error if field number is out of bounds * -------------------------------- */voidpbuf_checkFnumber(GroupBuffer *group, int field_number){ if (field_number < 0 || field_number >= group->no_fields) libpq_raise(&PortalError, vararg_format("Field number %d out of bound.", field_number));}/* -------------------------------- * pbuf_findFname - Find the field name given the field index * -------------------------------- */char *pbuf_findFname(GroupBuffer *group, int field_number){ pbuf_checkFnumber(group, field_number); return (group->types[field_number]).name;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -