diff options
Diffstat (limited to 'src/backend/utils')
66 files changed, 25849 insertions, 22683 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 33580a95125..d4b8f1ca0b6 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * acl.c-- - * Basic access control list data structures manipulation routines. + * Basic access control list data structures manipulation routines. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.13 1997/08/19 21:34:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.14 1997/09/07 04:49:53 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,561 +21,629 @@ #include "utils/syscache.h" #include "miscadmin.h" -static char *getid(char *s, char *n); -static int32 aclitemeq(AclItem *a1, AclItem *a2); -static int32 aclitemgt(AclItem *a1, AclItem *a2); -static char *aclparse(char *s, AclItem *aip, unsigned *modechg); +static char *getid(char *s, char *n); +static int32 aclitemeq(AclItem * a1, AclItem * a2); +static int32 aclitemgt(AclItem * a1, AclItem * a2); +static char *aclparse(char *s, AclItem * aip, unsigned *modechg); -#define ACL_IDTYPE_GID_KEYWORD "group" -#define ACL_IDTYPE_UID_KEYWORD "user" +#define ACL_IDTYPE_GID_KEYWORD "group" +#define ACL_IDTYPE_UID_KEYWORD "user" /* * getid - * Consumes the first alphanumeric string (identifier) found in string - * 's', ignoring any leading white space. + * Consumes the first alphanumeric string (identifier) found in string + * 's', ignoring any leading white space. * * RETURNS: - * the string position in 's' that points to the next non-space character - * in 's'. Also: - * - loads the identifier into 'name'. (If no identifier is found, 'name' - * contains an empty string). + * the string position in 's' that points to the next non-space character + * in 's'. Also: + * - loads the identifier into 'name'. (If no identifier is found, 'name' + * contains an empty string). */ -static char * +static char * getid(char *s, char *n) { - unsigned len; - char *id; - - Assert(s && n); - - while (isspace(*s)) - ++s; - for (id = s, len = 0; isalnum(*s) || *s == '_'; ++len, ++s) - ; - if (len > sizeof(NameData)) - elog(WARN, "getid: identifier cannot be >%d characters", - sizeof(NameData)); - if (len > 0) - memmove(n, id, len); - n[len] = '\0'; - while (isspace(*s)) - ++s; - return(s); + unsigned len; + char *id; + + Assert(s && n); + + while (isspace(*s)) + ++s; + for (id = s, len = 0; isalnum(*s) || *s == '_'; ++len, ++s) + ; + if (len > sizeof(NameData)) + elog(WARN, "getid: identifier cannot be >%d characters", + sizeof(NameData)); + if (len > 0) + memmove(n, id, len); + n[len] = '\0'; + while (isspace(*s)) + ++s; + return (s); } /* * aclparse - * Consumes and parses an ACL specification of the form: - * [group|user] [A-Za-z0-9]*[+-=][rwaR]* - * from string 's', ignoring any leading white space or white space - * between the optional id type keyword (group|user) and the actual - * ACL specification. + * Consumes and parses an ACL specification of the form: + * [group|user] [A-Za-z0-9]*[+-=][rwaR]* + * from string 's', ignoring any leading white space or white space + * between the optional id type keyword (group|user) and the actual + * ACL specification. * - * This routine is called by the parser as well as aclitemin(), hence - * the added generality. + * This routine is called by the parser as well as aclitemin(), hence + * the added generality. * * RETURNS: - * the string position in 's' immediately following the ACL - * specification. Also: - * - loads the structure pointed to by 'aip' with the appropriate - * UID/GID, id type identifier and mode type values. - * - loads 'modechg' with the mode change flag. + * the string position in 's' immediately following the ACL + * specification. Also: + * - loads the structure pointed to by 'aip' with the appropriate + * UID/GID, id type identifier and mode type values. + * - loads 'modechg' with the mode change flag. */ -static char * -aclparse(char *s, AclItem *aip, unsigned *modechg) +static char * +aclparse(char *s, AclItem * aip, unsigned *modechg) { - HeapTuple htp; - char name[NAMEDATALEN]; - - Assert(s && aip && modechg); - - aip->ai_idtype = ACL_IDTYPE_UID; - s = getid(s, name); - if (*s != ACL_MODECHG_ADD_CHR && - *s != ACL_MODECHG_DEL_CHR && - *s != ACL_MODECHG_EQL_CHR) - { /* we just read a keyword, not a name */ - if (!strcmp(name, ACL_IDTYPE_GID_KEYWORD)) { - aip->ai_idtype = ACL_IDTYPE_GID; - } else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD)) { - elog(WARN, "aclparse: bad keyword, must be [group|user]"); + HeapTuple htp; + char name[NAMEDATALEN]; + + Assert(s && aip && modechg); + + aip->ai_idtype = ACL_IDTYPE_UID; + s = getid(s, name); + if (*s != ACL_MODECHG_ADD_CHR && + *s != ACL_MODECHG_DEL_CHR && + *s != ACL_MODECHG_EQL_CHR) + { /* we just read a keyword, not a name */ + if (!strcmp(name, ACL_IDTYPE_GID_KEYWORD)) + { + aip->ai_idtype = ACL_IDTYPE_GID; + } + else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD)) + { + elog(WARN, "aclparse: bad keyword, must be [group|user]"); + } + s = getid(s, name); /* move s to the name beyond the keyword */ + if (name[0] == '\0') + elog(WARN, "aclparse: a name must follow the [group|user] keyword"); } - s = getid(s, name); /* move s to the name beyond the keyword */ if (name[0] == '\0') - elog(WARN, "aclparse: a name must follow the [group|user] keyword"); - } - if (name[0] == '\0') - aip->ai_idtype = ACL_IDTYPE_WORLD; - - switch (*s) { - case ACL_MODECHG_ADD_CHR: *modechg = ACL_MODECHG_ADD; break; - case ACL_MODECHG_DEL_CHR: *modechg = ACL_MODECHG_DEL; break; - case ACL_MODECHG_EQL_CHR: *modechg = ACL_MODECHG_EQL; break; - default: elog(WARN, "aclparse: mode change flag must use \"%s\"", - ACL_MODECHG_STR); - } - - aip->ai_mode = ACL_NO; - while (isalpha(*++s)) { - switch (*s) { - case ACL_MODE_AP_CHR: aip->ai_mode |= ACL_AP; break; - case ACL_MODE_RD_CHR: aip->ai_mode |= ACL_RD; break; - case ACL_MODE_WR_CHR: aip->ai_mode |= ACL_WR; break; - case ACL_MODE_RU_CHR: aip->ai_mode |= ACL_RU; break; - default: elog(WARN, "aclparse: mode flags must use \"%s\"", - ACL_MODE_STR); + aip->ai_idtype = ACL_IDTYPE_WORLD; + + switch (*s) + { + case ACL_MODECHG_ADD_CHR: + *modechg = ACL_MODECHG_ADD; + break; + case ACL_MODECHG_DEL_CHR: + *modechg = ACL_MODECHG_DEL; + break; + case ACL_MODECHG_EQL_CHR: + *modechg = ACL_MODECHG_EQL; + break; + default: + elog(WARN, "aclparse: mode change flag must use \"%s\"", + ACL_MODECHG_STR); } - } - - switch (aip->ai_idtype) { - case ACL_IDTYPE_UID: - htp = SearchSysCacheTuple(USENAME, PointerGetDatum(name), - 0,0,0); - if (!HeapTupleIsValid(htp)) - elog(WARN, "aclparse: non-existent user \"%s\"", name); - aip->ai_id = ((Form_pg_user) GETSTRUCT(htp))->usesysid; - break; - case ACL_IDTYPE_GID: - aip->ai_id = get_grosysid(name); - break; - case ACL_IDTYPE_WORLD: - aip->ai_id = ACL_ID_WORLD; - break; - } - + + aip->ai_mode = ACL_NO; + while (isalpha(*++s)) + { + switch (*s) + { + case ACL_MODE_AP_CHR: + aip->ai_mode |= ACL_AP; + break; + case ACL_MODE_RD_CHR: + aip->ai_mode |= ACL_RD; + break; + case ACL_MODE_WR_CHR: + aip->ai_mode |= ACL_WR; + break; + case ACL_MODE_RU_CHR: + aip->ai_mode |= ACL_RU; + break; + default: + elog(WARN, "aclparse: mode flags must use \"%s\"", + ACL_MODE_STR); + } + } + + switch (aip->ai_idtype) + { + case ACL_IDTYPE_UID: + htp = SearchSysCacheTuple(USENAME, PointerGetDatum(name), + 0, 0, 0); + if (!HeapTupleIsValid(htp)) + elog(WARN, "aclparse: non-existent user \"%s\"", name); + aip->ai_id = ((Form_pg_user) GETSTRUCT(htp))->usesysid; + break; + case ACL_IDTYPE_GID: + aip->ai_id = get_grosysid(name); + break; + case ACL_IDTYPE_WORLD: + aip->ai_id = ACL_ID_WORLD; + break; + } + #ifdef ACLDEBUG_TRACE - elog(DEBUG, "aclparse: correctly read [%x %d %x], modechg=%x", - aip->ai_idtype, aip->ai_id, aip->ai_mode, *modechg); + elog(DEBUG, "aclparse: correctly read [%x %d %x], modechg=%x", + aip->ai_idtype, aip->ai_id, aip->ai_mode, *modechg); #endif - return(s); + return (s); } /* * makeacl - * Allocates storage for a new Acl with 'n' entries. + * Allocates storage for a new Acl with 'n' entries. * * RETURNS: - * the new Acl + * the new Acl */ -Acl * +Acl * makeacl(int n) { - Acl *new_acl; - Size size; - - if (n < 0) - elog(WARN, "makeacl: invalid size: %d\n", n); - size = ACL_N_SIZE(n); - if (!(new_acl = (Acl *) palloc(size))) - elog(WARN, "makeacl: palloc failed on %d\n", size); - memset((char *) new_acl, 0, size); - new_acl->size = size; - new_acl->ndim = 1; - new_acl->flags = 0; - ARR_LBOUND(new_acl)[0] = 0; - ARR_DIMS(new_acl)[0] = n; - return(new_acl); + Acl *new_acl; + Size size; + + if (n < 0) + elog(WARN, "makeacl: invalid size: %d\n", n); + size = ACL_N_SIZE(n); + if (!(new_acl = (Acl *) palloc(size))) + elog(WARN, "makeacl: palloc failed on %d\n", size); + memset((char *) new_acl, 0, size); + new_acl->size = size; + new_acl->ndim = 1; + new_acl->flags = 0; + ARR_LBOUND(new_acl)[0] = 0; + ARR_DIMS(new_acl)[0] = n; + return (new_acl); } /* * aclitemin - * Allocates storage for, and fills in, a new AclItem given a string - * 's' that contains an ACL specification. See aclparse for details. + * Allocates storage for, and fills in, a new AclItem given a string + * 's' that contains an ACL specification. See aclparse for details. * * RETURNS: - * the new AclItem + * the new AclItem */ -AclItem * +AclItem * aclitemin(char *s) { - unsigned modechg; - AclItem *aip; - - if (!s) - elog(WARN, "aclitemin: null string"); - - aip = (AclItem *) palloc(sizeof(AclItem)); - if (!aip) - elog(WARN, "aclitemin: palloc failed"); - s = aclparse(s, aip, &modechg); - if (modechg != ACL_MODECHG_EQL) - elog(WARN, "aclitemin: cannot accept anything but = ACLs"); - while (isspace(*s)) - ++s; - if (*s) - elog(WARN, "aclitemin: extra garbage at end of specification"); - return(aip); + unsigned modechg; + AclItem *aip; + + if (!s) + elog(WARN, "aclitemin: null string"); + + aip = (AclItem *) palloc(sizeof(AclItem)); + if (!aip) + elog(WARN, "aclitemin: palloc failed"); + s = aclparse(s, aip, &modechg); + if (modechg != ACL_MODECHG_EQL) + elog(WARN, "aclitemin: cannot accept anything but = ACLs"); + while (isspace(*s)) + ++s; + if (*s) + elog(WARN, "aclitemin: extra garbage at end of specification"); + return (aip); } /* * aclitemout - * Allocates storage for, and fills in, a new null-delimited string - * containing a formatted ACL specification. See aclparse for details. + * Allocates storage for, and fills in, a new null-delimited string + * containing a formatted ACL specification. See aclparse for details. * * RETURNS: - * the new string + * the new string */ -char * -aclitemout(AclItem *aip) +char * +aclitemout(AclItem * aip) { - register char *p; - char *out; - HeapTuple htp; - unsigned i; - static AclItem default_aclitem = { ACL_ID_WORLD, - ACL_IDTYPE_WORLD, - ACL_WORLD_DEFAULT }; - extern char *int2out(); - char *tmpname; - - if (!aip) - aip = &default_aclitem; - - p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN); - if (!out) - elog(WARN, "aclitemout: palloc failed"); - *p = '\0'; - - switch (aip->ai_idtype) { - case ACL_IDTYPE_UID: - htp = SearchSysCacheTuple(USESYSID, ObjectIdGetDatum(aip->ai_id), - 0,0,0); - if (!HeapTupleIsValid(htp)) { - char *tmp = int2out(aip->ai_id); - - elog(NOTICE, "aclitemout: usesysid %d not found", - aip->ai_id); - strcat(p, tmp); - pfree(tmp); - } else - strncat(p, (char *) &((Form_pg_user) - GETSTRUCT(htp))->usename, - sizeof(NameData)); - break; - case ACL_IDTYPE_GID: - strcat(p, "group "); - tmpname = get_groname(aip->ai_id); - strncat(p, tmpname, NAMEDATALEN); - break; - case ACL_IDTYPE_WORLD: - break; - default: - elog(WARN, "aclitemout: bad ai_idtype: %d", aip->ai_idtype); - break; - } - while (*p) - ++p; - *p++ = '='; - for (i = 0; i < N_ACL_MODES; ++i) - if ((aip->ai_mode >> i) & 01) - *p++ = ACL_MODE_STR[i]; - *p = '\0'; - - return(out); + register char *p; + char *out; + HeapTuple htp; + unsigned i; + static AclItem default_aclitem = {ACL_ID_WORLD, + ACL_IDTYPE_WORLD, + ACL_WORLD_DEFAULT}; + extern char *int2out(); + char *tmpname; + + if (!aip) + aip = &default_aclitem; + + p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN); + if (!out) + elog(WARN, "aclitemout: palloc failed"); + *p = '\0'; + + switch (aip->ai_idtype) + { + case ACL_IDTYPE_UID: + htp = SearchSysCacheTuple(USESYSID, ObjectIdGetDatum(aip->ai_id), + 0, 0, 0); + if (!HeapTupleIsValid(htp)) + { + char *tmp = int2out(aip->ai_id); + + elog(NOTICE, "aclitemout: usesysid %d not found", + aip->ai_id); + strcat(p, tmp); + pfree(tmp); + } + else + strncat(p, (char *) &((Form_pg_user) + GETSTRUCT(htp))->usename, + sizeof(NameData)); + break; + case ACL_IDTYPE_GID: + strcat(p, "group "); + tmpname = get_groname(aip->ai_id); + strncat(p, tmpname, NAMEDATALEN); + break; + case ACL_IDTYPE_WORLD: + break; + default: + elog(WARN, "aclitemout: bad ai_idtype: %d", aip->ai_idtype); + break; + } + while (*p) + ++p; + *p++ = '='; + for (i = 0; i < N_ACL_MODES; ++i) + if ((aip->ai_mode >> i) & 01) + *p++ = ACL_MODE_STR[i]; + *p = '\0'; + + return (out); } /* * aclitemeq * aclitemgt - * AclItem equality and greater-than comparison routines. - * Two AclItems are equal iff they are both NULL or they have the - * same identifier (and identifier type). + * AclItem equality and greater-than comparison routines. + * Two AclItems are equal iff they are both NULL or they have the + * same identifier (and identifier type). * * RETURNS: - * a boolean value indicating = or > + * a boolean value indicating = or > */ -static int32 -aclitemeq(AclItem *a1, AclItem *a2) +static int32 +aclitemeq(AclItem * a1, AclItem * a2) { - if (!a1 && !a2) - return(1); - if (!a1 || !a2) - return(0); - return(a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id); + if (!a1 && !a2) + return (1); + if (!a1 || !a2) + return (0); + return (a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id); } -static int32 -aclitemgt(AclItem *a1, AclItem *a2) +static int32 +aclitemgt(AclItem * a1, AclItem * a2) { - if (a1 && !a2) - return(1); - if (!a1 || !a2) - return(0); - return((a1->ai_idtype > a2->ai_idtype) || - (a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id)); + if (a1 && !a2) + return (1); + if (!a1 || !a2) + return (0); + return ((a1->ai_idtype > a2->ai_idtype) || + (a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id)); } -Acl * +Acl * aclownerdefault(AclId ownerid) { - Acl *acl; - AclItem *aip; - - acl = makeacl(2); - aip = ACL_DAT(acl); - aip[0].ai_idtype = ACL_IDTYPE_WORLD; - aip[0].ai_id = ACL_ID_WORLD; - aip[0].ai_mode = ACL_WORLD_DEFAULT; - aip[1].ai_idtype = ACL_IDTYPE_UID; - aip[1].ai_id = ownerid; - aip[1].ai_mode = ACL_OWNER_DEFAULT; - return(acl); + Acl *acl; + AclItem *aip; + + acl = makeacl(2); + aip = ACL_DAT(acl); + aip[0].ai_idtype = ACL_IDTYPE_WORLD; + aip[0].ai_id = ACL_ID_WORLD; + aip[0].ai_mode = ACL_WORLD_DEFAULT; + aip[1].ai_idtype = ACL_IDTYPE_UID; + aip[1].ai_id = ownerid; + aip[1].ai_mode = ACL_OWNER_DEFAULT; + return (acl); } -Acl * +Acl * acldefault(void) { - Acl *acl; - AclItem *aip; - - acl = makeacl(1); - aip = ACL_DAT(acl); - aip[0].ai_idtype = ACL_IDTYPE_WORLD; - aip[0].ai_id = ACL_ID_WORLD; - aip[0].ai_mode = ACL_WORLD_DEFAULT; - return(acl); + Acl *acl; + AclItem *aip; + + acl = makeacl(1); + aip = ACL_DAT(acl); + aip[0].ai_idtype = ACL_IDTYPE_WORLD; + aip[0].ai_id = ACL_ID_WORLD; + aip[0].ai_mode = ACL_WORLD_DEFAULT; + return (acl); } -Acl * -aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) +Acl * +aclinsert3(Acl * old_acl, AclItem * mod_aip, unsigned modechg) { - Acl *new_acl; - AclItem *old_aip, *new_aip; - unsigned src, dst, num; - - if (!old_acl || ACL_NUM(old_acl) < 1) { - new_acl = makeacl(0); - return(new_acl); - } - if (!mod_aip) { - new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); - return(new_acl); - } - - num = ACL_NUM(old_acl); - old_aip = ACL_DAT(old_acl); - - /* - * Search the ACL for an existing entry for 'id'. If one exists, - * just modify the entry in-place (well, in the same position, since - * we actually return a copy); otherwise, insert the new entry in - * sort-order. - */ - /* find the first element not less than the element to be inserted */ - for (dst = 0; dst < num && aclitemgt(mod_aip, old_aip+dst); ++dst) - ; - if (dst < num && aclitemeq(mod_aip, old_aip+dst)) { - /* modify in-place */ - new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); - new_aip = ACL_DAT(new_acl); - src = dst; - } else { - new_acl = makeacl(num + 1); - new_aip = ACL_DAT(new_acl); - if (dst == 0) { /* start */ - elog(WARN, "aclinsert3: insertion before world ACL??"); - } else if (dst >= num) { /* end */ - memmove((char *) new_aip, - (char *) old_aip, - num * sizeof(AclItem)); - } else { /* middle */ - memmove((char *) new_aip, - (char *) old_aip, - dst * sizeof(AclItem)); - memmove((char *) (new_aip+dst+1), - (char *) (old_aip+dst), - (num - dst) * sizeof(AclItem)); + Acl *new_acl; + AclItem *old_aip, + *new_aip; + unsigned src, + dst, + num; + + if (!old_acl || ACL_NUM(old_acl) < 1) + { + new_acl = makeacl(0); + return (new_acl); } - new_aip[dst].ai_id = mod_aip->ai_id; - new_aip[dst].ai_idtype = mod_aip->ai_idtype; - num++; /* set num to the size of new_acl */ - src = 0; /* world entry */ - } - switch (modechg) { - case ACL_MODECHG_ADD: new_aip[dst].ai_mode = - old_aip[src].ai_mode | mod_aip->ai_mode; - break; - case ACL_MODECHG_DEL: new_aip[dst].ai_mode = - old_aip[src].ai_mode & ~mod_aip->ai_mode; - break; - case ACL_MODECHG_EQL: new_aip[dst].ai_mode = - mod_aip->ai_mode; - break; - } - /* if the newly added entry has no permissions, delete it from - the list. For example, this helps in removing entries for users who - no longer exists...*/ - for (dst = 1; dst < num; dst++) { - if (new_aip[dst].ai_mode == 0) { - int i; - for (i=dst+1; i<num; i++) { - new_aip[i-1].ai_id = new_aip[i].ai_id; - new_aip[i-1].ai_idtype = new_aip[i].ai_idtype; - new_aip[i-1].ai_mode = new_aip[i].ai_mode; - } - ARR_DIMS(new_acl)[0] = num -1 ; - /* Adjust also the array size because it is used for memmove */ - ARR_SIZE(new_acl) -= sizeof(AclItem); - break; + if (!mod_aip) + { + new_acl = makeacl(ACL_NUM(old_acl)); + memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + return (new_acl); } - } - return(new_acl); + num = ACL_NUM(old_acl); + old_aip = ACL_DAT(old_acl); + + /* + * Search the ACL for an existing entry for 'id'. If one exists, just + * modify the entry in-place (well, in the same position, since we + * actually return a copy); otherwise, insert the new entry in + * sort-order. + */ + /* find the first element not less than the element to be inserted */ + for (dst = 0; dst < num && aclitemgt(mod_aip, old_aip + dst); ++dst) + ; + if (dst < num && aclitemeq(mod_aip, old_aip + dst)) + { + /* modify in-place */ + new_acl = makeacl(ACL_NUM(old_acl)); + memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + new_aip = ACL_DAT(new_acl); + src = dst; + } + else + { + new_acl = makeacl(num + 1); + new_aip = ACL_DAT(new_acl); + if (dst == 0) + { /* start */ + elog(WARN, "aclinsert3: insertion before world ACL??"); + } + else if (dst >= num) + { /* end */ + memmove((char *) new_aip, + (char *) old_aip, + num * sizeof(AclItem)); + } + else + { /* middle */ + memmove((char *) new_aip, + (char *) old_aip, + dst * sizeof(AclItem)); + memmove((char *) (new_aip + dst + 1), + (char *) (old_aip + dst), + (num - dst) * sizeof(AclItem)); + } + new_aip[dst].ai_id = mod_aip->ai_id; + new_aip[dst].ai_idtype = mod_aip->ai_idtype; + num++; /* set num to the size of new_acl */ + src = 0; /* world entry */ + } + switch (modechg) + { + case ACL_MODECHG_ADD: + new_aip[dst].ai_mode = + old_aip[src].ai_mode | mod_aip->ai_mode; + break; + case ACL_MODECHG_DEL: + new_aip[dst].ai_mode = + old_aip[src].ai_mode & ~mod_aip->ai_mode; + break; + case ACL_MODECHG_EQL: + new_aip[dst].ai_mode = + mod_aip->ai_mode; + break; + } + + /* + * if the newly added entry has no permissions, delete it from the + * list. For example, this helps in removing entries for users who no + * longer exists... + */ + for (dst = 1; dst < num; dst++) + { + if (new_aip[dst].ai_mode == 0) + { + int i; + + for (i = dst + 1; i < num; i++) + { + new_aip[i - 1].ai_id = new_aip[i].ai_id; + new_aip[i - 1].ai_idtype = new_aip[i].ai_idtype; + new_aip[i - 1].ai_mode = new_aip[i].ai_mode; + } + ARR_DIMS(new_acl)[0] = num - 1; + /* Adjust also the array size because it is used for memmove */ + ARR_SIZE(new_acl) -= sizeof(AclItem); + break; + } + } + + return (new_acl); } /* * aclinsert * */ -Acl * -aclinsert(Acl *old_acl, AclItem *mod_aip) +Acl * +aclinsert(Acl * old_acl, AclItem * mod_aip) { - return(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL)); + return (aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL)); } -Acl * -aclremove(Acl *old_acl, AclItem *mod_aip) +Acl * +aclremove(Acl * old_acl, AclItem * mod_aip) { - Acl *new_acl; - AclItem *old_aip, *new_aip; - unsigned dst, old_num, new_num; - - if (!old_acl || ACL_NUM(old_acl) < 1) { - new_acl = makeacl(0); - return(new_acl); - } - if (!mod_aip) { - new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); - return(new_acl); - } - - old_num = ACL_NUM(old_acl); - old_aip = ACL_DAT(old_acl); - - for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip+dst); ++dst) - ; - if (dst >= old_num) { /* not found or empty */ - new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); - } else { - new_num = old_num - 1; - new_acl = makeacl(ACL_NUM(old_acl) - 1); - new_aip = ACL_DAT(new_acl); - if (dst == 0) { /* start */ - elog(WARN, "aclremove: removal of the world ACL??"); - } else if (dst == old_num - 1) {/* end */ - memmove((char *) new_aip, - (char *) old_aip, - new_num * sizeof(AclItem)); - } else { /* middle */ - memmove((char *) new_aip, - (char *) old_aip, - dst * sizeof(AclItem)); - memmove((char *) (new_aip+dst), - (char *) (old_aip+dst+1), - (new_num - dst) * sizeof(AclItem)); + Acl *new_acl; + AclItem *old_aip, + *new_aip; + unsigned dst, + old_num, + new_num; + + if (!old_acl || ACL_NUM(old_acl) < 1) + { + new_acl = makeacl(0); + return (new_acl); } - } - return(new_acl); + if (!mod_aip) + { + new_acl = makeacl(ACL_NUM(old_acl)); + memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + return (new_acl); + } + + old_num = ACL_NUM(old_acl); + old_aip = ACL_DAT(old_acl); + + for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip + dst); ++dst) + ; + if (dst >= old_num) + { /* not found or empty */ + new_acl = makeacl(ACL_NUM(old_acl)); + memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + } + else + { + new_num = old_num - 1; + new_acl = makeacl(ACL_NUM(old_acl) - 1); + new_aip = ACL_DAT(new_acl); + if (dst == 0) + { /* start */ + elog(WARN, "aclremove: removal of the world ACL??"); + } + else if (dst == old_num - 1) + { /* end */ + memmove((char *) new_aip, + (char *) old_aip, + new_num * sizeof(AclItem)); + } + else + { /* middle */ + memmove((char *) new_aip, + (char *) old_aip, + dst * sizeof(AclItem)); + memmove((char *) (new_aip + dst), + (char *) (old_aip + dst + 1), + (new_num - dst) * sizeof(AclItem)); + } + } + return (new_acl); } int32 -aclcontains(Acl *acl, AclItem *aip) +aclcontains(Acl * acl, AclItem * aip) { - unsigned i, num; - AclItem *aidat; - - if (!acl || !aip || ((num = ACL_NUM(acl)) < 1)) - return(0); - aidat = ACL_DAT(acl); - for (i = 0; i < num; ++i) - if (aclitemeq(aip, aidat+i)) - return(1); - return(0); + unsigned i, + num; + AclItem *aidat; + + if (!acl || !aip || ((num = ACL_NUM(acl)) < 1)) + return (0); + aidat = ACL_DAT(acl); + for (i = 0; i < num; ++i) + if (aclitemeq(aip, aidat + i)) + return (1); + return (0); } /* parser support routines */ /* * aclmakepriv - * make a acl privilege string out of an existing privilege string + * make a acl privilege string out of an existing privilege string * and a new privilege * * does not add duplicate privileges - * + * * the CALLER is reponsible for free'ing the string returned */ -char* -aclmakepriv(char* old_privlist, char new_priv) +char * +aclmakepriv(char *old_privlist, char new_priv) { - char* priv; - int i; - int l; + char *priv; + int i; + int l; - Assert(strlen(old_privlist)<5); - priv = malloc(5); /* at most "rwaR" */; + Assert(strlen(old_privlist) < 5); + priv = malloc(5); /* at most "rwaR" */ ; - if (old_privlist == NULL || old_privlist[0] == '\0') { - priv[0] = new_priv; - priv[1] = '\0'; - return priv; - } + if (old_privlist == NULL || old_privlist[0] == '\0') + { + priv[0] = new_priv; + priv[1] = '\0'; + return priv; + } + + strcpy(priv, old_privlist); + + l = strlen(old_privlist); - strcpy(priv,old_privlist); - - l = strlen(old_privlist); + if (l == 4) + { /* can't add any more privileges */ + return priv; + } + + /* check to see if the new privilege is already in the old string */ + for (i = 0; i < l; i++) + { + if (priv[i] == new_priv) + break; + } + if (i == l) + { /* we really have a new privilege */ + priv[l] = new_priv; + priv[l + 1] = '\0'; + } - if (l == 4) { /* can't add any more privileges */ return priv; - } - - /* check to see if the new privilege is already in the old string */ - for (i=0;i<l;i++) { - if (priv[i] == new_priv) - break; - } - if (i == l) { /* we really have a new privilege*/ - priv[l] = new_priv; - priv[l+1] = '\0'; - } - - return priv; } /* * aclmakeuser - * user_type must be "A" - all users - * "G" - group - * "U" - user + * user_type must be "A" - all users + * "G" - group + * "U" - user * * concatentates the two strings together with a space in between - * + * * this routine is used in the parser - * + * * the CALLER is responsible for freeing the memory allocated */ -char* -aclmakeuser(char* user_type, char* user) +char * +aclmakeuser(char *user_type, char *user) { - char* user_list; - - user_list = malloc(strlen(user) + 3); - sprintf(user_list, "%s %s", user_type, user); - return user_list; + char *user_list; + + user_list = malloc(strlen(user) + 3); + sprintf(user_list, "%s %s", user_type, user); + return user_list; } /* * makeAclStmt: - * this is a helper routine called by the parser + * this is a helper routine called by the parser * create a ChangeAclStmt - * we take in the privilegs, relation_name_list, and grantee + * we take in the privilegs, relation_name_list, and grantee * as well as a single character '+' or '-' to indicate grant or revoke * * returns a new ChangeACLStmt* @@ -584,35 +652,34 @@ aclmakeuser(char* user_type, char* user) * then calling aclparse; */ -ChangeACLStmt* -makeAclStmt(char* privileges, List* rel_list, char* grantee, - char grant_or_revoke) +ChangeACLStmt * +makeAclStmt(char *privileges, List * rel_list, char *grantee, + char grant_or_revoke) { - ChangeACLStmt *n = makeNode(ChangeACLStmt); - char str[MAX_PARSE_BUFFER]; - - n->aclitem = (AclItem*)palloc(sizeof(AclItem)); - /* the grantee string is "G <group_name>", "U <user_name>", or "ALL" */ - if (grantee[0] == 'G') /* group permissions */ + ChangeACLStmt *n = makeNode(ChangeACLStmt); + char str[MAX_PARSE_BUFFER]; + + n->aclitem = (AclItem *) palloc(sizeof(AclItem)); + /* the grantee string is "G <group_name>", "U <user_name>", or "ALL" */ + if (grantee[0] == 'G') /* group permissions */ { - sprintf(str,"%s %s%c%s", - ACL_IDTYPE_GID_KEYWORD, - grantee+2, grant_or_revoke,privileges); - } - else if (grantee[0] == 'U') /* user permission */ + sprintf(str, "%s %s%c%s", + ACL_IDTYPE_GID_KEYWORD, + grantee + 2, grant_or_revoke, privileges); + } + else if (grantee[0] == 'U') /* user permission */ { - sprintf(str,"%s %s%c%s", - ACL_IDTYPE_UID_KEYWORD, - grantee+2, grant_or_revoke,privileges); + sprintf(str, "%s %s%c%s", + ACL_IDTYPE_UID_KEYWORD, + grantee + 2, grant_or_revoke, privileges); } - else /* all permission */ + else +/* all permission */ { - sprintf(str,"%c%s", - grant_or_revoke,privileges); + sprintf(str, "%c%s", + grant_or_revoke, privileges); } - n->relNames = rel_list; - aclparse(str, n->aclitem, (unsigned*)&n->modechg); - return n; + n->relNames = rel_list; + aclparse(str, n->aclitem, (unsigned *) &n->modechg); + return n; } - - diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 48a78366b01..073b0a1fd01 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * arrayfuncs.c-- - * Special functions for arrays. + * Special functions for arrays. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.15 1997/08/19 21:34:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.16 1997/09/07 04:49:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -30,1411 +30,1707 @@ #include "libpq/libpq-fs.h" #include "libpq/be-fsstubs.h" -#define ASSGN "=" +#define ASSGN "=" /* An array has the following internal structure: - * <nbytes> - total number of bytes - * <ndim> - number of dimensions of the array - * <flags> - bit mask of flags - * <dim> - size of each array axis - * <dim_lower> - lower boundary of each dimension - * <actual data> - whatever is the stored data + * <nbytes> - total number of bytes + * <ndim> - number of dimensions of the array + * <flags> - bit mask of flags + * <dim> - size of each array axis + * <dim_lower> - lower boundary of each dimension + * <actual data> - whatever is the stored data */ /*-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-*/ -static int _ArrayCount(char *str, int dim[], int typdelim); -static char *_ReadArrayStr(char *arrayStr, int nitems, int ndim, int dim[], - func_ptr inputproc, Oid typelem, char typdelim, - int typlen, bool typbyval, char typalign, - int *nbytes); +static int _ArrayCount(char *str, int dim[], int typdelim); +static char * +_ReadArrayStr(char *arrayStr, int nitems, int ndim, int dim[], + func_ptr inputproc, Oid typelem, char typdelim, + int typlen, bool typbyval, char typalign, + int *nbytes); + #ifdef LOARRAY -static char *_ReadLOArray(char *str, int *nbytes, int *fd, bool *chunkFlag, - int ndim, int dim[], int baseSize); +static char * +_ReadLOArray(char *str, int *nbytes, int *fd, bool * chunkFlag, + int ndim, int dim[], int baseSize); + #endif -static void _CopyArrayEls(char **values, char *p, int nitems, int typlen, +static void +_CopyArrayEls(char **values, char *p, int nitems, int typlen, char typalign, bool typbyval); -static void system_cache_lookup(Oid element_type, bool input, int *typlen, - bool *typbyval, char *typdelim, Oid *typelem, Oid *proc, - char *typalign); -static Datum _ArrayCast(char *value, bool byval, int len); +static void +system_cache_lookup(Oid element_type, bool input, int *typlen, + bool * typbyval, char *typdelim, Oid * typelem, Oid * proc, + char *typalign); +static Datum _ArrayCast(char *value, bool byval, int len); + #ifdef LOARRAY -static char *_AdvanceBy1word(char *str, char **word); +static char *_AdvanceBy1word(char *str, char **word); + #endif -static void _ArrayRange(int st[], int endp[], int bsize, char *destPtr, - ArrayType *array, int from); -static int _ArrayClipCount(int stI[], int endpI[], ArrayType *array); -static void _LOArrayRange(int st[], int endp[], int bsize, int srcfd, - int destfd, ArrayType *array, int isSrcLO, bool *isNull); -static void _ReadArray (int st[], int endp[], int bsize, int srcfd, int destfd, - ArrayType *array, int isDestLO, bool *isNull); -static ArrayCastAndSet(char *src, bool typbyval, int typlen, char *dest); -static SanityCheckInput(int ndim, int n, int dim[], int lb[], int indx[]); -static int array_read(char *destptr, int eltsize, int nitems, char *srcptr); -static char *array_seek(char *ptr, int eltsize, int nitems); +static void +_ArrayRange(int st[], int endp[], int bsize, char *destPtr, + ArrayType * array, int from); +static int _ArrayClipCount(int stI[], int endpI[], ArrayType * array); +static void +_LOArrayRange(int st[], int endp[], int bsize, int srcfd, + int destfd, ArrayType * array, int isSrcLO, bool * isNull); +static void +_ReadArray(int st[], int endp[], int bsize, int srcfd, int destfd, + ArrayType * array, int isDestLO, bool * isNull); +static ArrayCastAndSet(char *src, bool typbyval, int typlen, char *dest); +static SanityCheckInput(int ndim, int n, int dim[], int lb[], int indx[]); +static int array_read(char *destptr, int eltsize, int nitems, char *srcptr); +static char *array_seek(char *ptr, int eltsize, int nitems); /*--------------------------------------------------------------------- - * array_in : - * converts an array from the external format in "string" to - * it internal format. + * array_in : + * converts an array from the external format in "string" to + * it internal format. * return value : - * the internal representation of the input array + * the internal representation of the input array *-------------------------------------------------------------------- */ -char * -array_in(char *string, /* input array in external form */ - Oid element_type) /* type OID of an array element */ +char * +array_in(char *string, /* input array in external form */ + Oid element_type) /* type OID of an array element */ { - int typlen; - bool typbyval, done; - char typdelim; - Oid typinput; - Oid typelem; - char *string_save, *p, *q, *r; - func_ptr inputproc; - int i, nitems, dummy; - int32 nbytes; - char *dataPtr; - ArrayType *retval = NULL; - int ndim, dim[MAXDIM], lBound[MAXDIM]; - char typalign; - - system_cache_lookup(element_type, true, &typlen, &typbyval, &typdelim, - &typelem, &typinput, &typalign); - - fmgr_info(typinput, &inputproc, &dummy); - - string_save = (char *) palloc(strlen(string) + 3); - strcpy(string_save, string); - - /* --- read array dimensions ---------- */ - p = q = string_save; done = false; - for ( ndim = 0; !done; ) { - while (isspace(*p)) p++; - if (*p == '[' ) { - p++; - if ((r = (char *)strchr(p, ':')) == (char *)NULL) - lBound[ndim] = 1; - else { - *r = '\0'; - lBound[ndim] = atoi(p); - p = r + 1; - } - for (q = p; isdigit(*q); q++); - if (*q != ']') - elog(WARN, "array_in: missing ']' in array declaration"); - *q = '\0'; - dim[ndim] = atoi(p); - if ((dim[ndim] < 0) || (lBound[ndim] < 0)) - elog(WARN,"array_in: array dimensions need to be positive"); - dim[ndim] = dim[ndim] - lBound[ndim] + 1; - if (dim[ndim] < 0) - elog(WARN, "array_in: upper_bound cannot be < lower_bound"); - p = q + 1; ndim++; - } else { - done = true; - } - } - - if (ndim == 0) { - if (*p == '{') { - ndim = _ArrayCount(p, dim, typdelim); - for (i = 0; i < ndim; lBound[i++] = 1); - } else { - elog(WARN,"array_in: Need to specify dimension"); - } - } else { - while (isspace(*p)) p++; - if (strncmp(p, ASSGN, strlen(ASSGN))) - elog(WARN, "array_in: missing assignment operator"); - p+= strlen(ASSGN); - while (isspace(*p)) p++; - } - + int typlen; + bool typbyval, + done; + char typdelim; + Oid typinput; + Oid typelem; + char *string_save, + *p, + *q, + *r; + func_ptr inputproc; + int i, + nitems, + dummy; + int32 nbytes; + char *dataPtr; + ArrayType *retval = NULL; + int ndim, + dim[MAXDIM], + lBound[MAXDIM]; + char typalign; + + system_cache_lookup(element_type, true, &typlen, &typbyval, &typdelim, + &typelem, &typinput, &typalign); + + fmgr_info(typinput, &inputproc, &dummy); + + string_save = (char *) palloc(strlen(string) + 3); + strcpy(string_save, string); + + /* --- read array dimensions ---------- */ + p = q = string_save; + done = false; + for (ndim = 0; !done;) + { + while (isspace(*p)) + p++; + if (*p == '[') + { + p++; + if ((r = (char *) strchr(p, ':')) == (char *) NULL) + lBound[ndim] = 1; + else + { + *r = '\0'; + lBound[ndim] = atoi(p); + p = r + 1; + } + for (q = p; isdigit(*q); q++); + if (*q != ']') + elog(WARN, "array_in: missing ']' in array declaration"); + *q = '\0'; + dim[ndim] = atoi(p); + if ((dim[ndim] < 0) || (lBound[ndim] < 0)) + elog(WARN, "array_in: array dimensions need to be positive"); + dim[ndim] = dim[ndim] - lBound[ndim] + 1; + if (dim[ndim] < 0) + elog(WARN, "array_in: upper_bound cannot be < lower_bound"); + p = q + 1; + ndim++; + } + else + { + done = true; + } + } + + if (ndim == 0) + { + if (*p == '{') + { + ndim = _ArrayCount(p, dim, typdelim); + for (i = 0; i < ndim; lBound[i++] = 1); + } + else + { + elog(WARN, "array_in: Need to specify dimension"); + } + } + else + { + while (isspace(*p)) + p++; + if (strncmp(p, ASSGN, strlen(ASSGN))) + elog(WARN, "array_in: missing assignment operator"); + p += strlen(ASSGN); + while (isspace(*p)) + p++; + } + #ifdef ARRAYDEBUG -printf( "array_in- ndim %d (", ndim); -for (i = 0; i < ndim; i++) { - printf(" %d", dim[i]); -}; -printf( ") for %s\n", string); + printf("array_in- ndim %d (", ndim); + for (i = 0; i < ndim; i++) + { + printf(" %d", dim[i]); + }; + printf(") for %s\n", string); #endif - nitems = getNitems( ndim, dim); - if (nitems == 0) { - char *emptyArray = palloc(sizeof(ArrayType)); - memset(emptyArray, 0, sizeof(ArrayType)); - * (int32 *) emptyArray = sizeof(ArrayType); - return emptyArray; - } - - if (*p == '{') { - /* array not a large object */ - dataPtr = - (char *) _ReadArrayStr(p, nitems, ndim, dim, inputproc, typelem, - typdelim, typlen, typbyval, typalign, - &nbytes ); - nbytes += ARR_OVERHEAD(ndim); - retval = (ArrayType *) palloc(nbytes); - memset(retval,0, nbytes); - memmove(retval, (char *)&nbytes, sizeof(int)); - memmove((char*)ARR_NDIM_PTR(retval), (char *)&ndim, sizeof(int)); - SET_LO_FLAG (false, retval); - memmove((char *)ARR_DIMS(retval), (char *)dim, ndim*sizeof(int)); - memmove((char *)ARR_LBOUND(retval), (char *)lBound, - ndim*sizeof(int)); - /* dataPtr is an array of arbitraystuff even though its type is char* - cast to char** to pass to _CopyArrayEls for now - jolly */ - _CopyArrayEls((char**)dataPtr, - ARR_DATA_PTR(retval), nitems, - typlen, typalign, typbyval); - } else { + nitems = getNitems(ndim, dim); + if (nitems == 0) + { + char *emptyArray = palloc(sizeof(ArrayType)); + + memset(emptyArray, 0, sizeof(ArrayType)); + *(int32 *) emptyArray = sizeof(ArrayType); + return emptyArray; + } + + if (*p == '{') + { + /* array not a large object */ + dataPtr = + (char *) _ReadArrayStr(p, nitems, ndim, dim, inputproc, typelem, + typdelim, typlen, typbyval, typalign, + &nbytes); + nbytes += ARR_OVERHEAD(ndim); + retval = (ArrayType *) palloc(nbytes); + memset(retval, 0, nbytes); + memmove(retval, (char *) &nbytes, sizeof(int)); + memmove((char *) ARR_NDIM_PTR(retval), (char *) &ndim, sizeof(int)); + SET_LO_FLAG(false, retval); + memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int)); + memmove((char *) ARR_LBOUND(retval), (char *) lBound, + ndim * sizeof(int)); + + /* + * dataPtr is an array of arbitraystuff even though its type is + * char* cast to char** to pass to _CopyArrayEls for now - jolly + */ + _CopyArrayEls((char **) dataPtr, + ARR_DATA_PTR(retval), nitems, + typlen, typalign, typbyval); + } + else + { #ifdef LOARRAY - int dummy, bytes; - bool chunked = false; - - dataPtr = _ReadLOArray(p, &bytes, &dummy, &chunked, ndim, - dim, typlen ); - nbytes = bytes + ARR_OVERHEAD(ndim); - retval = (ArrayType *) palloc(nbytes); - memset(retval, 0,nbytes); - memmove(retval, (char *)&nbytes, sizeof(int)); - memmove((char *)ARR_NDIM_PTR(retval), (char *)&ndim, sizeof(int)); - SET_LO_FLAG (true, retval); - SET_CHUNK_FLAG (chunked, retval); - memmove((char *)ARR_DIMS(retval), (char *)dim, ndim*sizeof(int)); - memmove((char *)ARR_LBOUND(retval),(char *)lBound, ndim*sizeof(int)); - memmove(ARR_DATA_PTR(retval), dataPtr, bytes); + int dummy, + bytes; + bool chunked = false; + + dataPtr = _ReadLOArray(p, &bytes, &dummy, &chunked, ndim, + dim, typlen); + nbytes = bytes + ARR_OVERHEAD(ndim); + retval = (ArrayType *) palloc(nbytes); + memset(retval, 0, nbytes); + memmove(retval, (char *) &nbytes, sizeof(int)); + memmove((char *) ARR_NDIM_PTR(retval), (char *) &ndim, sizeof(int)); + SET_LO_FLAG(true, retval); + SET_CHUNK_FLAG(chunked, retval); + memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int)); + memmove((char *) ARR_LBOUND(retval), (char *) lBound, ndim * sizeof(int)); + memmove(ARR_DATA_PTR(retval), dataPtr, bytes); #endif - elog(WARN, "large object arrays not supported"); - } - pfree(string_save); - return((char *)retval); + elog(WARN, "large object arrays not supported"); + } + pfree(string_save); + return ((char *) retval); } /*----------------------------------------------------------------------------- * _ArrayCount -- - * Counts the number of dimensions and the dim[] array for an array string. - * The syntax for array input is C-like nested curly braces + * Counts the number of dimensions and the dim[] array for an array string. + * The syntax for array input is C-like nested curly braces *----------------------------------------------------------------------------- */ static int _ArrayCount(char *str, int dim[], int typdelim) { - int nest_level = 0, i; - int ndim = 0, temp[MAXDIM]; - bool scanning_string = false; - bool eoArray = false; - char *q; - - for (i = 0; i < MAXDIM; ++i) { - temp[i] = dim[i] = 0; - } - - if (strncmp (str, "{}", 2) == 0) return(0); - - q = str; - while (eoArray != true) { - bool done = false; - while (!done) { - switch (*q) { - case '\\': - /* skip escaped characters (\ and ") inside strings */ - if (scanning_string && *(q+1)) { - q++; - } - break; - case '\0': - /* Signal a premature end of the string. DZ - 2-9-1996 */ - elog(WARN, "malformed array constant: %s", str); - break; - case '\"': - scanning_string = ! scanning_string; - break; - case '{': - if (!scanning_string) { - temp[nest_level] = 0; - nest_level++; - } - break; - case '}': - if (!scanning_string) { - if (!ndim) ndim = nest_level; - nest_level--; - if (nest_level) temp[nest_level-1]++; - if (nest_level == 0) eoArray = done = true; + int nest_level = 0, + i; + int ndim = 0, + temp[MAXDIM]; + bool scanning_string = false; + bool eoArray = false; + char *q; + + for (i = 0; i < MAXDIM; ++i) + { + temp[i] = dim[i] = 0; + } + + if (strncmp(str, "{}", 2) == 0) + return (0); + + q = str; + while (eoArray != true) + { + bool done = false; + + while (!done) + { + switch (*q) + { + case '\\': + /* skip escaped characters (\ and ") inside strings */ + if (scanning_string && *(q + 1)) + { + q++; + } + break; + case '\0': + /* Signal a premature end of the string. DZ - 2-9-1996 */ + elog(WARN, "malformed array constant: %s", str); + break; + case '\"': + scanning_string = !scanning_string; + break; + case '{': + if (!scanning_string) + { + temp[nest_level] = 0; + nest_level++; + } + break; + case '}': + if (!scanning_string) + { + if (!ndim) + ndim = nest_level; + nest_level--; + if (nest_level) + temp[nest_level - 1]++; + if (nest_level == 0) + eoArray = done = true; + } + break; + default: + if (!ndim) + ndim = nest_level; + if (*q == typdelim && !scanning_string) + done = true; + break; + } + if (!done) + q++; } - break; - default: - if (!ndim) ndim = nest_level; - if (*q == typdelim && !scanning_string ) - done = true; - break; - } - if (!done) q++; - } - temp[ndim-1]++; - q++; - if (!eoArray) - while (isspace(*q)) q++; - } - for (i = 0; i < ndim; ++i) { - dim[i] = temp[i]; - } - - return(ndim); + temp[ndim - 1]++; + q++; + if (!eoArray) + while (isspace(*q)) + q++; + } + for (i = 0; i < ndim; ++i) + { + dim[i] = temp[i]; + } + + return (ndim); } /*--------------------------------------------------------------------------- * _ReadArrayStr : - * parses the array string pointed by "arrayStr" and converts it in the - * internal format. The external format expected is like C array - * declaration. Unspecified elements are initialized to zero for fixed length - * base types and to empty varlena structures for variable length base - * types. + * parses the array string pointed by "arrayStr" and converts it in the + * internal format. The external format expected is like C array + * declaration. Unspecified elements are initialized to zero for fixed length + * base types and to empty varlena structures for variable length base + * types. * result : - * returns the internal representation of the array elements - * nbytes is set to the size of the array in its internal representation. + * returns the internal representation of the array elements + * nbytes is set to the size of the array in its internal representation. *--------------------------------------------------------------------------- */ -static char * +static char * _ReadArrayStr(char *arrayStr, - int nitems, - int ndim, - int dim[], - func_ptr inputproc, /* function used for the conversion */ - Oid typelem, - char typdelim, - int typlen, - bool typbyval, - char typalign, - int *nbytes) + int nitems, + int ndim, + int dim[], + func_ptr inputproc, /* function used for the + * conversion */ + Oid typelem, + char typdelim, + int typlen, + bool typbyval, + char typalign, + int *nbytes) { - int i, nest_level = 0; - char *p, *q, *r, **values; - bool scanning_string = false; - int indx[MAXDIM], prod[MAXDIM]; - bool eoArray = false; - - mda_get_prod(ndim, dim, prod); - for (i = 0; i < ndim; indx[i++] = 0); - /* read array enclosed within {} */ - values = (char **) palloc(nitems * sizeof(char *)); - memset(values, 0, nitems * sizeof(char *)); - q = p = arrayStr; - - while ( ! eoArray ) { - bool done = false; - int i = -1; - - while (!done) { - switch (*q) { - case '\\': - /* Crunch the string on top of the backslash. */ - for (r = q; *r != '\0'; r++) *r = *(r+1); - break; - case '\"': - if (!scanning_string ) { - while (p != q) p++; - p++; /* get p past first doublequote */ - } else - *q = '\0'; - scanning_string = ! scanning_string; - break; - case '{': - if (!scanning_string) { - p++; - nest_level++; - if (nest_level > ndim) - elog(WARN, "array_in: illformed array constant"); - indx[nest_level - 1] = 0; - indx[ndim - 1] = 0; - } - break; - case '}': - if (!scanning_string) { - if (i == -1) - i = tuple2linear(ndim, indx, prod); - nest_level--; - if (nest_level == 0) - eoArray = done = true; - else { - *q = '\0'; - indx[nest_level - 1]++; - } - } - break; - default: - if (*q == typdelim && !scanning_string ) { - if (i == -1) - i = tuple2linear(ndim, indx, prod); - done = true; - indx[ndim - 1]++; + int i, + nest_level = 0; + char *p, + *q, + *r, + **values; + bool scanning_string = false; + int indx[MAXDIM], + prod[MAXDIM]; + bool eoArray = false; + + mda_get_prod(ndim, dim, prod); + for (i = 0; i < ndim; indx[i++] = 0); + /* read array enclosed within {} */ + values = (char **) palloc(nitems * sizeof(char *)); + memset(values, 0, nitems * sizeof(char *)); + q = p = arrayStr; + + while (!eoArray) + { + bool done = false; + int i = -1; + + while (!done) + { + switch (*q) + { + case '\\': + /* Crunch the string on top of the backslash. */ + for (r = q; *r != '\0'; r++) + *r = *(r + 1); + break; + case '\"': + if (!scanning_string) + { + while (p != q) + p++; + p++; /* get p past first doublequote */ + } + else + *q = '\0'; + scanning_string = !scanning_string; + break; + case '{': + if (!scanning_string) + { + p++; + nest_level++; + if (nest_level > ndim) + elog(WARN, "array_in: illformed array constant"); + indx[nest_level - 1] = 0; + indx[ndim - 1] = 0; + } + break; + case '}': + if (!scanning_string) + { + if (i == -1) + i = tuple2linear(ndim, indx, prod); + nest_level--; + if (nest_level == 0) + eoArray = done = true; + else + { + *q = '\0'; + indx[nest_level - 1]++; + } + } + break; + default: + if (*q == typdelim && !scanning_string) + { + if (i == -1) + i = tuple2linear(ndim, indx, prod); + done = true; + indx[ndim - 1]++; + } + break; + } + if (!done) + q++; } - break; - } - if (!done) - q++; - } - *q = '\0'; - if (i >= nitems) - elog(WARN, "array_in: illformed array constant"); - values[i] = (*inputproc) (p, typelem); - p = ++q; - if (!eoArray) - /* - * if not at the end of the array skip white space - */ - while (isspace(*q)) { - p++; - q++; - } - } - if (typlen > 0) { - *nbytes = nitems * typlen; - if (!typbyval) - for (i = 0; i < nitems; i++) - if (!values[i]) { - values[i] = palloc(typlen); - memset(values[i], 0, typlen); - } - } else { - for (i = 0, *nbytes = 0; i < nitems; i++) { - if (values[i]) { - if (typalign=='d') { - *nbytes += DOUBLEALIGN(* (int32 *) values[i]); - } else { - *nbytes += INTALIGN(* (int32 *) values[i]); + *q = '\0'; + if (i >= nitems) + elog(WARN, "array_in: illformed array constant"); + values[i] = (*inputproc) (p, typelem); + p = ++q; + if (!eoArray) + + /* + * if not at the end of the array skip white space + */ + while (isspace(*q)) + { + p++; + q++; + } + } + if (typlen > 0) + { + *nbytes = nitems * typlen; + if (!typbyval) + for (i = 0; i < nitems; i++) + if (!values[i]) + { + values[i] = palloc(typlen); + memset(values[i], 0, typlen); + } + } + else + { + for (i = 0, *nbytes = 0; i < nitems; i++) + { + if (values[i]) + { + if (typalign == 'd') + { + *nbytes += DOUBLEALIGN(*(int32 *) values[i]); + } + else + { + *nbytes += INTALIGN(*(int32 *) values[i]); + } + } + else + { + *nbytes += sizeof(int32); + values[i] = palloc(sizeof(int32)); + *(int32 *) values[i] = sizeof(int32); + } } - } else { - *nbytes += sizeof(int32); - values[i] = palloc(sizeof(int32)); - *(int32 *)values[i] = sizeof(int32); - } - } - } - return((char *)values); + } + return ((char *) values); } /*---------------------------------------------------------------------------- - * Read data about an array to be stored as a large object + * Read data about an array to be stored as a large object *---------------------------------------------------------------------------- */ #ifdef LOARRAY -static char * +static char * _ReadLOArray(char *str, - int *nbytes, - int *fd, - bool *chunkFlag, - int ndim, - int dim[], - int baseSize) + int *nbytes, + int *fd, + bool * chunkFlag, + int ndim, + int dim[], + int baseSize) { - char *inputfile, *accessfile = NULL, *chunkfile = NULL; - char *retStr, *_AdvanceBy1word(); - Oid lobjId; - - str = _AdvanceBy1word(str, &inputfile); - - while (str != NULL) { - char *word; - - str = _AdvanceBy1word(str, &word); - - if (!strcmp (word, "-chunk")) { - if (str == NULL) - elog(WARN, "array_in: access pattern file required"); - str = _AdvanceBy1word(str, &accessfile); - } - else if (!strcmp (word, "-noreorg")) { - if (str == NULL) - elog(WARN, "array_in: chunk file required"); - str = _AdvanceBy1word(str, &chunkfile); - } else { - elog(WARN, "usage: <input file> -chunk DEFAULT/<access pattern file> -invert/-native [-noreorg <chunk file>]"); + char *inputfile, + *accessfile = NULL, + *chunkfile = NULL; + char *retStr, + *_AdvanceBy1word(); + Oid lobjId; + + str = _AdvanceBy1word(str, &inputfile); + + while (str != NULL) + { + char *word; + + str = _AdvanceBy1word(str, &word); + + if (!strcmp(word, "-chunk")) + { + if (str == NULL) + elog(WARN, "array_in: access pattern file required"); + str = _AdvanceBy1word(str, &accessfile); + } + else if (!strcmp(word, "-noreorg")) + { + if (str == NULL) + elog(WARN, "array_in: chunk file required"); + str = _AdvanceBy1word(str, &chunkfile); + } + else + { + elog(WARN, "usage: <input file> -chunk DEFAULT/<access pattern file> -invert/-native [-noreorg <chunk file>]"); + } + } + + if (inputfile == NULL) + elog(WARN, "array_in: missing file name"); + lobjId = lo_creat(0); + *fd = lo_open(lobjId, INV_READ); + if (*fd < 0) + elog(WARN, "Large object create failed"); + retStr = inputfile; + *nbytes = strlen(retStr) + 2; + + if (accessfile) + { + FILE *afd; + + if ((afd = AllocateFile(accessfile, "r")) == NULL) + elog(WARN, "unable to open access pattern file"); + *chunkFlag = true; + retStr = _ChunkArray(*fd, afd, ndim, dim, baseSize, nbytes, + chunkfile); + FreeFile(afd); } - } - - if (inputfile == NULL) - elog(WARN, "array_in: missing file name"); - lobjId = lo_creat(0); - *fd = lo_open(lobjId, INV_READ); - if ( *fd < 0 ) - elog(WARN, "Large object create failed"); - retStr = inputfile; - *nbytes = strlen(retStr) + 2; - - if ( accessfile ) { - FILE *afd; - if ((afd = AllocateFile(accessfile, "r")) == NULL) - elog(WARN, "unable to open access pattern file"); - *chunkFlag = true; - retStr = _ChunkArray(*fd, afd, ndim, dim, baseSize, nbytes, - chunkfile); - FreeFile(afd); - } - return(retStr); + return (retStr); } + #endif static void -_CopyArrayEls(char **values, - char *p, - int nitems, - int typlen, - char typalign, - bool typbyval) +_CopyArrayEls(char **values, + char *p, + int nitems, + int typlen, + char typalign, + bool typbyval) { - int i; - - for (i = 0; i < nitems; i++) { - int inc; - inc = ArrayCastAndSet(values[i], typbyval, typlen, p); - p += inc; - if (!typbyval) - pfree(values[i]); - } - pfree(values); + int i; + + for (i = 0; i < nitems; i++) + { + int inc; + + inc = ArrayCastAndSet(values[i], typbyval, typlen, p); + p += inc; + if (!typbyval) + pfree(values[i]); + } + pfree(values); } /*------------------------------------------------------------------------- - * array_out : - * takes the internal representation of an array and returns a string - * containing the array in its external format. + * array_out : + * takes the internal representation of an array and returns a string + * containing the array in its external format. *------------------------------------------------------------------------- */ -char * -array_out(ArrayType *v, Oid element_type) +char * +array_out(ArrayType * v, Oid element_type) { - int typlen; - bool typbyval; - char typdelim; - Oid typoutput, typelem; - func_ptr outputproc; - char typalign; - - char *p, *retval, **values, delim[2]; - int nitems, overall_length, i, j, k, indx[MAXDIM]; - bool dummy_bool; - int dummy_int; - int ndim, *dim; - - if (v == (ArrayType *) NULL) - return ((char *) NULL); - - if (ARR_IS_LO(v) == true) { - char *p, *save_p; - int nbytes; - - /* get a wide string to print to */ - p = array_dims(v, &dummy_bool); - nbytes = strlen(ARR_DATA_PTR(v)) + 4 + *(int *)p; - - save_p = (char *) palloc(nbytes); - - strcpy(save_p, p + sizeof(int)); - strcat(save_p, ASSGN); - strcat(save_p, ARR_DATA_PTR(v)); - pfree(p); - return (save_p); - } - - system_cache_lookup(element_type, false, &typlen, &typbyval, - &typdelim, &typelem, &typoutput, &typalign); - fmgr_info(typoutput, & outputproc, &dummy_int); - sprintf(delim, "%c", typdelim); - ndim = ARR_NDIM(v); - dim = ARR_DIMS(v); - nitems = getNitems(ndim, dim); - - if (nitems == 0) { - char *emptyArray = palloc(3); - emptyArray[0] = '{'; - emptyArray[1] = '}'; - emptyArray[2] = '\0'; - return emptyArray; - } - - p = ARR_DATA_PTR(v); - overall_length = 1; /* [TRH] don't forget to count \0 at end. */ - values = (char **) palloc(nitems * sizeof (char *)); - for (i = 0; i < nitems; i++) { - if (typbyval) { - switch(typlen) { - case 1: - values[i] = (*outputproc) (*p, typelem); - break; - case 2: - values[i] = (*outputproc) (* (int16 *) p, typelem); - break; - case 3: - case 4: - values[i] = (*outputproc) (* (int32 *) p, typelem); - break; - } - p += typlen; - } else { - values[i] = (*outputproc) (p, typelem); - if (typlen > 0) - p += typlen; - else - p += INTALIGN(* (int32 *) p); - /* - * For the pair of double quotes - */ - overall_length += 2; - } - overall_length += (strlen(values[i]) + 1); - } - - /* - * count total number of curly braces in output string - */ - for (i = j = 0, k = 1; i < ndim; k *= dim[i++], j += k); - - p = (char *) palloc(overall_length + 2*j); - retval = p; - - strcpy(p, "{"); - for (i = 0; i < ndim; indx[i++] = 0); - j = 0; k = 0; - do { - for (i = j; i < ndim - 1; i++) - strcat(p, "{"); - /* - * Surround anything that is not passed by value in double quotes. - * See above for more details. + int typlen; + bool typbyval; + char typdelim; + Oid typoutput, + typelem; + func_ptr outputproc; + char typalign; + + char *p, + *retval, + **values, + delim[2]; + int nitems, + overall_length, + i, + j, + k, + indx[MAXDIM]; + bool dummy_bool; + int dummy_int; + int ndim, + *dim; + + if (v == (ArrayType *) NULL) + return ((char *) NULL); + + if (ARR_IS_LO(v) == true) + { + char *p, + *save_p; + int nbytes; + + /* get a wide string to print to */ + p = array_dims(v, &dummy_bool); + nbytes = strlen(ARR_DATA_PTR(v)) + 4 + *(int *) p; + + save_p = (char *) palloc(nbytes); + + strcpy(save_p, p + sizeof(int)); + strcat(save_p, ASSGN); + strcat(save_p, ARR_DATA_PTR(v)); + pfree(p); + return (save_p); + } + + system_cache_lookup(element_type, false, &typlen, &typbyval, + &typdelim, &typelem, &typoutput, &typalign); + fmgr_info(typoutput, &outputproc, &dummy_int); + sprintf(delim, "%c", typdelim); + ndim = ARR_NDIM(v); + dim = ARR_DIMS(v); + nitems = getNitems(ndim, dim); + + if (nitems == 0) + { + char *emptyArray = palloc(3); + + emptyArray[0] = '{'; + emptyArray[1] = '}'; + emptyArray[2] = '\0'; + return emptyArray; + } + + p = ARR_DATA_PTR(v); + overall_length = 1; /* [TRH] don't forget to count \0 at end. */ + values = (char **) palloc(nitems * sizeof(char *)); + for (i = 0; i < nitems; i++) + { + if (typbyval) + { + switch (typlen) + { + case 1: + values[i] = (*outputproc) (*p, typelem); + break; + case 2: + values[i] = (*outputproc) (*(int16 *) p, typelem); + break; + case 3: + case 4: + values[i] = (*outputproc) (*(int32 *) p, typelem); + break; + } + p += typlen; + } + else + { + values[i] = (*outputproc) (p, typelem); + if (typlen > 0) + p += typlen; + else + p += INTALIGN(*(int32 *) p); + + /* + * For the pair of double quotes + */ + overall_length += 2; + } + overall_length += (strlen(values[i]) + 1); + } + + /* + * count total number of curly braces in output string */ - if (!typbyval) { - strcat(p, "\""); - strcat(p, values[k]); - strcat(p, "\""); - } else - strcat(p, values[k]); - pfree(values[k++]); - - for (i = ndim - 1; i >= 0; i--) { - indx[i] = (indx[i] + 1)%dim[i]; - if (indx[i]) { - strcat (p, delim); - break; - } else - strcat (p, "}"); - } - j = i; - } while (j != -1); - - pfree(values); - return(retval); + for (i = j = 0, k = 1; i < ndim; k *= dim[i++], j += k); + + p = (char *) palloc(overall_length + 2 * j); + retval = p; + + strcpy(p, "{"); + for (i = 0; i < ndim; indx[i++] = 0); + j = 0; + k = 0; + do + { + for (i = j; i < ndim - 1; i++) + strcat(p, "{"); + + /* + * Surround anything that is not passed by value in double quotes. + * See above for more details. + */ + if (!typbyval) + { + strcat(p, "\""); + strcat(p, values[k]); + strcat(p, "\""); + } + else + strcat(p, values[k]); + pfree(values[k++]); + + for (i = ndim - 1; i >= 0; i--) + { + indx[i] = (indx[i] + 1) % dim[i]; + if (indx[i]) + { + strcat(p, delim); + break; + } + else + strcat(p, "}"); + } + j = i; + } while (j != -1); + + pfree(values); + return (retval); } /*----------------------------------------------------------------------------- * array_dims : - * returns the dimension of the array pointed to by "v" - *---------------------------------------------------------------------------- + * returns the dimension of the array pointed to by "v" + *---------------------------------------------------------------------------- */ -char * -array_dims(ArrayType *v, bool *isNull) +char * +array_dims(ArrayType * v, bool * isNull) { - char *p, *save_p; - int nbytes, i; - int *dimv, *lb; - - if (v == (ArrayType *) NULL) RETURN_NULL; - nbytes = ARR_NDIM(v)*33; - /* - * 33 since we assume 15 digits per number + ':' +'[]' - */ - save_p = p = (char *) palloc(nbytes + 4); - memset(save_p, 0, nbytes + 4); - dimv = ARR_DIMS(v); lb = ARR_LBOUND(v); - p += 4; - for (i = 0; i < ARR_NDIM(v); i++) { - sprintf(p, "[%d:%d]", lb[i], dimv[i]+lb[i]-1); - p += strlen(p); - } - nbytes = strlen(save_p + 4) + 4; - memmove(save_p, &nbytes,4); - return (save_p); -} + char *p, + *save_p; + int nbytes, + i; + int *dimv, + *lb; + + if (v == (ArrayType *) NULL) + RETURN_NULL; + nbytes = ARR_NDIM(v) * 33; + + /* + * 33 since we assume 15 digits per number + ':' +'[]' + */ + save_p = p = (char *) palloc(nbytes + 4); + memset(save_p, 0, nbytes + 4); + dimv = ARR_DIMS(v); + lb = ARR_LBOUND(v); + p += 4; + for (i = 0; i < ARR_NDIM(v); i++) + { + sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1); + p += strlen(p); + } + nbytes = strlen(save_p + 4) + 4; + memmove(save_p, &nbytes, 4); + return (save_p); +} /*--------------------------------------------------------------------------- * array_ref : - * This routing takes an array pointer and an index array and returns - * a pointer to the referred element if element is passed by - * reference otherwise returns the value of the referred element. + * This routing takes an array pointer and an index array and returns + * a pointer to the referred element if element is passed by + * reference otherwise returns the value of the referred element. *--------------------------------------------------------------------------- */ Datum -array_ref(ArrayType *array, - int n, - int indx[], - int reftype, - int elmlen, - int arraylen, - bool *isNull) +array_ref(ArrayType * array, + int n, + int indx[], + int reftype, + int elmlen, + int arraylen, + bool * isNull) { - int i, ndim, *dim, *lb, offset, nbytes; - struct varlena *v = NULL; - char *retval = NULL; - - if (array == (ArrayType *) NULL) RETURN_NULL; - if (arraylen > 0) { - /* - * fixed length arrays -- these are assumed to be 1-d - */ - if (indx[0]*elmlen > arraylen) - elog(WARN, "array_ref: array bound exceeded"); - retval = (char *)array + indx[0]*elmlen; - return _ArrayCast(retval, reftype, elmlen); - } - dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - ndim = ARR_NDIM(array); - nbytes = (* (int32 *) array) - ARR_OVERHEAD(ndim); - - if (!SanityCheckInput(ndim, n, dim, lb, indx)) - RETURN_NULL; - - offset = GetOffset(n, dim, lb, indx); - - if (ARR_IS_LO(array)) { - char * lo_name; - int fd = 0; - - /* We are assuming fixed element lengths here */ - offset *= elmlen; - lo_name = (char *)ARR_DATA_PTR(array); + int i, + ndim, + *dim, + *lb, + offset, + nbytes; + struct varlena *v = NULL; + char *retval = NULL; + + if (array == (ArrayType *) NULL) + RETURN_NULL; + if (arraylen > 0) + { + + /* + * fixed length arrays -- these are assumed to be 1-d + */ + if (indx[0] * elmlen > arraylen) + elog(WARN, "array_ref: array bound exceeded"); + retval = (char *) array + indx[0] * elmlen; + return _ArrayCast(retval, reftype, elmlen); + } + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + ndim = ARR_NDIM(array); + nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim); + + if (!SanityCheckInput(ndim, n, dim, lb, indx)) + RETURN_NULL; + + offset = GetOffset(n, dim, lb, indx); + + if (ARR_IS_LO(array)) + { + char *lo_name; + int fd = 0; + + /* We are assuming fixed element lengths here */ + offset *= elmlen; + lo_name = (char *) ARR_DATA_PTR(array); #ifdef LOARRAY - if ((fd = LOopen(lo_name, ARR_IS_INV(array)?INV_READ:O_RDONLY)) < 0) - RETURN_NULL; -#endif - if (ARR_IS_CHUNKED(array)) - v = _ReadChunkArray1El(indx, elmlen, fd, array, isNull); - else { - if (lo_lseek(fd, offset, SEEK_SET) < 0) - RETURN_NULL; + if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0) + RETURN_NULL; +#endif + if (ARR_IS_CHUNKED(array)) + v = _ReadChunkArray1El(indx, elmlen, fd, array, isNull); + else + { + if (lo_lseek(fd, offset, SEEK_SET) < 0) + RETURN_NULL; #ifdef LOARRAY - v = (struct varlena *) LOread(fd, elmlen); + v = (struct varlena *) LOread(fd, elmlen); #endif - } - if (*isNull) RETURN_NULL; - if (VARSIZE(v) - 4 < elmlen) - RETURN_NULL; - lo_close(fd); - retval = (char *)_ArrayCast((char *)VARDATA(v), reftype, elmlen); - if ( reftype == 0) { /* not by value */ - char * tempdata = palloc (elmlen); - memmove(tempdata, retval, elmlen); - retval = tempdata; + } + if (*isNull) + RETURN_NULL; + if (VARSIZE(v) - 4 < elmlen) + RETURN_NULL; + lo_close(fd); + retval = (char *) _ArrayCast((char *) VARDATA(v), reftype, elmlen); + if (reftype == 0) + { /* not by value */ + char *tempdata = palloc(elmlen); + + memmove(tempdata, retval, elmlen); + retval = tempdata; + } + pfree(v); + return (Datum) retval; + } + + if (elmlen > 0) + { + offset = offset * elmlen; + /* off the end of the array */ + if (nbytes - offset < 1) + RETURN_NULL; + retval = ARR_DATA_PTR(array) + offset; + return _ArrayCast(retval, reftype, elmlen); + } + else + { + bool done = false; + char *temp; + int bytes = nbytes; + + temp = ARR_DATA_PTR(array); + i = 0; + while (bytes > 0 && !done) + { + if (i == offset) + { + retval = temp; + done = true; + } + bytes -= INTALIGN(*(int32 *) temp); + temp += INTALIGN(*(int32 *) temp); + i++; + } + if (!done) + RETURN_NULL; + return (Datum) retval; } - pfree(v); - return (Datum) retval; - } - - if (elmlen > 0) { - offset = offset * elmlen; - /* off the end of the array */ - if (nbytes - offset < 1) RETURN_NULL; - retval = ARR_DATA_PTR (array) + offset; - return _ArrayCast(retval, reftype, elmlen); - } else { - bool done = false; - char *temp; - int bytes = nbytes; - temp = ARR_DATA_PTR (array); - i = 0; - while (bytes > 0 && !done) { - if (i == offset) { - retval = temp; - done = true; - } - bytes -= INTALIGN(* (int32 *) temp); - temp += INTALIGN(* (int32 *) temp); - i++; - } - if (! done) - RETURN_NULL; - return (Datum) retval; - } } /*----------------------------------------------------------------------------- * array_clip : - * This routine takes an array and a range of indices (upperIndex and - * lowerIndx), creates a new array structure for the referred elements - * and returns a pointer to it. + * This routine takes an array and a range of indices (upperIndex and + * lowerIndx), creates a new array structure for the referred elements + * and returns a pointer to it. *----------------------------------------------------------------------------- */ Datum -array_clip(ArrayType *array, - int n, - int upperIndx[], - int lowerIndx[], - int reftype, - int len, - bool *isNull) +array_clip(ArrayType * array, + int n, + int upperIndx[], + int lowerIndx[], + int reftype, + int len, + bool * isNull) { - int i, ndim, *dim, *lb, nbytes; - ArrayType *newArr; - int bytes, span[MAXDIM]; - - /* timer_start(); */ - if (array == (ArrayType *) NULL) - RETURN_NULL; - dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - ndim = ARR_NDIM(array); - nbytes = (* (int32 *) array) - ARR_OVERHEAD(ndim); - - if (!SanityCheckInput(ndim, n, dim, lb, upperIndx)) - RETURN_NULL; - - if (!SanityCheckInput(ndim, n, dim, lb, lowerIndx)) - RETURN_NULL; - - for (i = 0; i < n; i++) - if (lowerIndx[i] > upperIndx[i]) - elog(WARN, "lowerIndex cannot be larger than upperIndx"); - mda_get_range(n, span, lowerIndx, upperIndx); - - if (ARR_IS_LO(array)) { + int i, + ndim, + *dim, + *lb, + nbytes; + ArrayType *newArr; + int bytes, + span[MAXDIM]; + + /* timer_start(); */ + if (array == (ArrayType *) NULL) + RETURN_NULL; + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + ndim = ARR_NDIM(array); + nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim); + + if (!SanityCheckInput(ndim, n, dim, lb, upperIndx)) + RETURN_NULL; + + if (!SanityCheckInput(ndim, n, dim, lb, lowerIndx)) + RETURN_NULL; + + for (i = 0; i < n; i++) + if (lowerIndx[i] > upperIndx[i]) + elog(WARN, "lowerIndex cannot be larger than upperIndx"); + mda_get_range(n, span, lowerIndx, upperIndx); + + if (ARR_IS_LO(array)) + { #ifdef LOARRAY - char * lo_name; + char *lo_name; + #endif - char *newname = NULL; - int fd = 0, newfd = 0, isDestLO = true, rsize; - - if (len < 0) - elog(WARN, "array_clip: array of variable length objects not supported"); + char *newname = NULL; + int fd = 0, + newfd = 0, + isDestLO = true, + rsize; + + if (len < 0) + elog(WARN, "array_clip: array of variable length objects not supported"); #ifdef LOARRAY - lo_name = (char *)ARR_DATA_PTR(array); - if ((fd = LOopen(lo_name, ARR_IS_INV(array)?INV_READ:O_RDONLY)) < 0) - RETURN_NULL; - newname = _array_newLO( &newfd, Unix ); + lo_name = (char *) ARR_DATA_PTR(array); + if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0) + RETURN_NULL; + newname = _array_newLO(&newfd, Unix); #endif - bytes = strlen(newname) + 1 + ARR_OVERHEAD(n); - newArr = (ArrayType *) palloc(bytes); - memmove(newArr, array, sizeof(ArrayType)); - memmove(newArr, &bytes, sizeof(int)); - memmove(ARR_DIMS(newArr), span, n*sizeof(int)); - memmove(ARR_LBOUND(newArr), lowerIndx, n*sizeof(int)); - strcpy(ARR_DATA_PTR(newArr), newname); - - rsize = compute_size (lowerIndx, upperIndx, n, len); - if (rsize < MAX_BUFF_SIZE) { - char *buff; - rsize += 4; - buff = palloc(rsize); - if ( buff ) - isDestLO = false; - if (ARR_IS_CHUNKED(array)) { - _ReadChunkArray(lowerIndx, upperIndx, len, fd, &(buff[4]), - array,0,isNull); - } else { - _ReadArray(lowerIndx, upperIndx, len, fd, (int)&(buff[4]), - array, - 0,isNull); - } - memmove(buff, &rsize, 4); + bytes = strlen(newname) + 1 + ARR_OVERHEAD(n); + newArr = (ArrayType *) palloc(bytes); + memmove(newArr, array, sizeof(ArrayType)); + memmove(newArr, &bytes, sizeof(int)); + memmove(ARR_DIMS(newArr), span, n * sizeof(int)); + memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int)); + strcpy(ARR_DATA_PTR(newArr), newname); + + rsize = compute_size(lowerIndx, upperIndx, n, len); + if (rsize < MAX_BUFF_SIZE) + { + char *buff; + + rsize += 4; + buff = palloc(rsize); + if (buff) + isDestLO = false; + if (ARR_IS_CHUNKED(array)) + { + _ReadChunkArray(lowerIndx, upperIndx, len, fd, &(buff[4]), + array, 0, isNull); + } + else + { + _ReadArray(lowerIndx, upperIndx, len, fd, (int) &(buff[4]), + array, + 0, isNull); + } + memmove(buff, &rsize, 4); #ifdef LOARRAY - if (! *isNull) - bytes = LOwrite(newfd, (struct varlena *)buff); + if (!*isNull) + bytes = LOwrite(newfd, (struct varlena *) buff); #endif - pfree (buff); - } - if (isDestLO) - if (ARR_IS_CHUNKED(array)) { - _ReadChunkArray(lowerIndx, upperIndx, len, fd, (char*)newfd, array, - 1,isNull); - } else { - _ReadArray(lowerIndx, upperIndx, len, fd, newfd, array, 1,isNull); - } + pfree(buff); + } + if (isDestLO) + if (ARR_IS_CHUNKED(array)) + { + _ReadChunkArray(lowerIndx, upperIndx, len, fd, (char *) newfd, array, + 1, isNull); + } + else + { + _ReadArray(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull); + } #ifdef LOARRAY - LOclose(fd); - LOclose(newfd); + LOclose(fd); + LOclose(newfd); #endif - if (*isNull) { - pfree(newArr); - newArr = NULL; - } - /* timer_end(); */ - return ((Datum) newArr); - } - - if (len > 0) { - bytes = getNitems(n, span); - bytes = bytes*len + ARR_OVERHEAD(n); - } else { - bytes = _ArrayClipCount(lowerIndx, upperIndx, array); - bytes += ARR_OVERHEAD(n); - } - newArr = (ArrayType *) palloc(bytes); - memmove(newArr, array, sizeof(ArrayType)); - memmove(newArr, &bytes, sizeof(int)); - memmove(ARR_DIMS(newArr), span, n*sizeof(int)); - memmove(ARR_LBOUND(newArr), lowerIndx, n*sizeof(int)); - _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 1); - return (Datum) newArr; + if (*isNull) + { + pfree(newArr); + newArr = NULL; + } + /* timer_end(); */ + return ((Datum) newArr); + } + + if (len > 0) + { + bytes = getNitems(n, span); + bytes = bytes * len + ARR_OVERHEAD(n); + } + else + { + bytes = _ArrayClipCount(lowerIndx, upperIndx, array); + bytes += ARR_OVERHEAD(n); + } + newArr = (ArrayType *) palloc(bytes); + memmove(newArr, array, sizeof(ArrayType)); + memmove(newArr, &bytes, sizeof(int)); + memmove(ARR_DIMS(newArr), span, n * sizeof(int)); + memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int)); + _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 1); + return (Datum) newArr; } /*----------------------------------------------------------------------------- * array_set : - * This routine sets the value of an array location (specified by an index array) - * to a new value specified by "dataPtr". + * This routine sets the value of an array location (specified by an index array) + * to a new value specified by "dataPtr". * result : - * returns a pointer to the modified array. + * returns a pointer to the modified array. *----------------------------------------------------------------------------- */ -char * -array_set(ArrayType *array, - int n, - int indx[], - char *dataPtr, - int reftype, - int elmlen, - int arraylen, - bool *isNull) +char * +array_set(ArrayType * array, + int n, + int indx[], + char *dataPtr, + int reftype, + int elmlen, + int arraylen, + bool * isNull) { - int ndim, *dim, *lb, offset, nbytes; - char *pos; - - if (array == (ArrayType *) NULL) - RETURN_NULL; - if (arraylen > 0) { - /* - * fixed length arrays -- these are assumed to be 1-d - */ - if (indx[0]*elmlen > arraylen) - elog(WARN, "array_ref: array bound exceeded"); - pos = (char *)array + indx[0]*elmlen; - ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos); - return((char *)array); - } - dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - ndim = ARR_NDIM(array); - nbytes = (* (int32 *) array) - ARR_OVERHEAD(ndim); - - if (!SanityCheckInput(ndim, n, dim, lb, indx)) - { - elog(WARN, "array_set: array bound exceeded"); - return((char *)array); - } - offset = GetOffset( n, dim, lb, indx); - - if (ARR_IS_LO(array)) { - int fd = 0; - struct varlena *v; - - /* We are assuming fixed element lengths here */ - offset *= elmlen; + int ndim, + *dim, + *lb, + offset, + nbytes; + char *pos; + + if (array == (ArrayType *) NULL) + RETURN_NULL; + if (arraylen > 0) + { + + /* + * fixed length arrays -- these are assumed to be 1-d + */ + if (indx[0] * elmlen > arraylen) + elog(WARN, "array_ref: array bound exceeded"); + pos = (char *) array + indx[0] * elmlen; + ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos); + return ((char *) array); + } + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + ndim = ARR_NDIM(array); + nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim); + + if (!SanityCheckInput(ndim, n, dim, lb, indx)) + { + elog(WARN, "array_set: array bound exceeded"); + return ((char *) array); + } + offset = GetOffset(n, dim, lb, indx); + + if (ARR_IS_LO(array)) + { + int fd = 0; + struct varlena *v; + + /* We are assuming fixed element lengths here */ + offset *= elmlen; #ifdef LOARRAY - char * lo_name; - - lo_name = ARR_DATA_PTR(array); - if ((fd = LOopen(lo_name, ARR_IS_INV(array)?INV_WRITE:O_WRONLY)) < 0) - return((char *)array); -#endif - if (lo_lseek(fd, offset, SEEK_SET) < 0) - return((char *)array); - v = (struct varlena *) palloc(elmlen + 4); - VARSIZE (v) = elmlen + 4; - ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, VARDATA(v)); + char *lo_name; + + lo_name = ARR_DATA_PTR(array); + if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0) + return ((char *) array); +#endif + if (lo_lseek(fd, offset, SEEK_SET) < 0) + return ((char *) array); + v = (struct varlena *) palloc(elmlen + 4); + VARSIZE(v) = elmlen + 4; + ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, VARDATA(v)); #ifdef LOARRAY - n = LOwrite(fd, v); + n = LOwrite(fd, v); #endif - /* if (n < VARSIZE(v) - 4) - RETURN_NULL; - */ - pfree(v); - lo_close(fd); - return((char *)array); - } - if (elmlen > 0) { - offset = offset * elmlen; - /* off the end of the array */ - if (nbytes - offset < 1) return((char *)array); - pos = ARR_DATA_PTR (array) + offset; - } else { - ArrayType *newarray; - char *elt_ptr; - int oldsize, newsize, oldlen, newlen, lth0, lth1, lth2; - - elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset); - oldlen = INTALIGN(*(int32 *)elt_ptr); - newlen = INTALIGN(*(int32 *)dataPtr); - - if (oldlen == newlen) { - /* new element with same size, overwrite old data */ - ArrayCastAndSet(dataPtr, (bool)reftype, elmlen, elt_ptr); - return((char *)array); + + /* + * if (n < VARSIZE(v) - 4) RETURN_NULL; + */ + pfree(v); + lo_close(fd); + return ((char *) array); } + if (elmlen > 0) + { + offset = offset * elmlen; + /* off the end of the array */ + if (nbytes - offset < 1) + return ((char *) array); + pos = ARR_DATA_PTR(array) + offset; + } + else + { + ArrayType *newarray; + char *elt_ptr; + int oldsize, + newsize, + oldlen, + newlen, + lth0, + lth1, + lth2; + + elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset); + oldlen = INTALIGN(*(int32 *) elt_ptr); + newlen = INTALIGN(*(int32 *) dataPtr); + + if (oldlen == newlen) + { + /* new element with same size, overwrite old data */ + ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, elt_ptr); + return ((char *) array); + } + + /* new element with different size, reallocate the array */ + oldsize = array->size; + lth0 = ARR_OVERHEAD(n); + lth1 = (int) (elt_ptr - ARR_DATA_PTR(array)); + lth2 = (int) (oldsize - lth0 - lth1 - oldlen); + newsize = lth0 + lth1 + newlen + lth2; + + newarray = (ArrayType *) palloc(newsize); + memmove((char *) newarray, (char *) array, lth0 + lth1); + newarray->size = newsize; + newlen = ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, + (char *) newarray + lth0 + lth1); + memmove((char *) newarray + lth0 + lth1 + newlen, + (char *) array + lth0 + lth1 + oldlen, lth2); - /* new element with different size, reallocate the array */ - oldsize = array->size; - lth0 = ARR_OVERHEAD(n); - lth1 = (int)(elt_ptr - ARR_DATA_PTR(array)); - lth2 = (int)(oldsize - lth0 - lth1 - oldlen); - newsize = lth0 + lth1 + newlen + lth2; - - newarray = (ArrayType *)palloc(newsize); - memmove((char *)newarray, (char *)array, lth0+lth1); - newarray->size = newsize; - newlen = ArrayCastAndSet(dataPtr, (bool)reftype, elmlen, - (char *)newarray+lth0+lth1); - memmove((char *)newarray+lth0+lth1+newlen, - (char *)array+lth0+lth1+oldlen, lth2); - - /* ??? who should free this storage ??? */ - return((char *)newarray); - } - ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos); - return((char *)array); + /* ??? who should free this storage ??? */ + return ((char *) newarray); + } + ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos); + return ((char *) array); } /*---------------------------------------------------------------------------- * array_assgn : - * This routine sets the value of a range of array locations (specified - * by upper and lower index values ) to new values passed as - * another array + * This routine sets the value of a range of array locations (specified + * by upper and lower index values ) to new values passed as + * another array * result : - * returns a pointer to the modified array. + * returns a pointer to the modified array. *---------------------------------------------------------------------------- */ -char * -array_assgn(ArrayType *array, - int n, - int upperIndx[], - int lowerIndx[], - ArrayType *newArr, - int reftype, - int len, - bool *isNull) +char * +array_assgn(ArrayType * array, + int n, + int upperIndx[], + int lowerIndx[], + ArrayType * newArr, + int reftype, + int len, + bool * isNull) { - int i, ndim, *dim, *lb; - - if (array == (ArrayType *) NULL) - RETURN_NULL; - if (len < 0) - elog(WARN,"array_assgn:updates on arrays of variable length elements not allowed"); - - dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - ndim = ARR_NDIM(array); - - if (!SanityCheckInput(ndim, n, dim, lb, upperIndx) || - !SanityCheckInput(ndim, n, dim, lb, lowerIndx)) { - return((char *)array); - } - - for (i = 0; i < n; i++) - if (lowerIndx[i] > upperIndx[i]) - elog(WARN, "lowerIndex larger than upperIndx"); - - if (ARR_IS_LO(array)) { - int fd = 0, newfd = 0; - + int i, + ndim, + *dim, + *lb; + + if (array == (ArrayType *) NULL) + RETURN_NULL; + if (len < 0) + elog(WARN, "array_assgn:updates on arrays of variable length elements not allowed"); + + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + ndim = ARR_NDIM(array); + + if (!SanityCheckInput(ndim, n, dim, lb, upperIndx) || + !SanityCheckInput(ndim, n, dim, lb, lowerIndx)) + { + return ((char *) array); + } + + for (i = 0; i < n; i++) + if (lowerIndx[i] > upperIndx[i]) + elog(WARN, "lowerIndex larger than upperIndx"); + + if (ARR_IS_LO(array)) + { + int fd = 0, + newfd = 0; + #ifdef LOARRAY - char * lo_name; + char *lo_name; - lo_name = (char *)ARR_DATA_PTR(array); - if ((fd = LOopen(lo_name, ARR_IS_INV(array)?INV_WRITE:O_WRONLY)) < 0) - return((char *)array); + lo_name = (char *) ARR_DATA_PTR(array); + if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0) + return ((char *) array); #endif - if (ARR_IS_LO(newArr)) { + if (ARR_IS_LO(newArr)) + { #ifdef LOARRAY - lo_name = (char *)ARR_DATA_PTR(newArr); - if ((newfd = LOopen(lo_name, ARR_IS_INV(newArr)?INV_READ:O_RDONLY)) < 0) - return((char *)array); + lo_name = (char *) ARR_DATA_PTR(newArr); + if ((newfd = LOopen(lo_name, ARR_IS_INV(newArr) ? INV_READ : O_RDONLY)) < 0) + return ((char *) array); #endif - _LOArrayRange(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull); - lo_close(newfd); - } else { - _LOArrayRange(lowerIndx, upperIndx, len, fd, (int)ARR_DATA_PTR(newArr), - array, 0, isNull); - } - lo_close(fd); - return ((char *) array); - } - _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 0); - return (char *) array; + _LOArrayRange(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull); + lo_close(newfd); + } + else + { + _LOArrayRange(lowerIndx, upperIndx, len, fd, (int) ARR_DATA_PTR(newArr), + array, 0, isNull); + } + lo_close(fd); + return ((char *) array); + } + _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 0); + return (char *) array; } /*----------------------------------------------------------------------------- * array_eq : - * compares two arrays for equality + * compares two arrays for equality * result : - * returns 1 if the arrays are equal, 0 otherwise. + * returns 1 if the arrays are equal, 0 otherwise. *----------------------------------------------------------------------------- */ int -array_eq (ArrayType *array1, ArrayType *array2) +array_eq(ArrayType * array1, ArrayType * array2) { - if ((array1 == NULL) || (array2 == NULL)) - return(0); - if (*(int *)array1 != *(int *)array2) - return (0); - if (memcmp(array1, array2, *(int *)array1)) - return(0); - return(1); + if ((array1 == NULL) || (array2 == NULL)) + return (0); + if (*(int *) array1 != *(int *) array2) + return (0); + if (memcmp(array1, array2, *(int *) array1)) + return (0); + return (1); } /***************************************************************************/ -/******************| Support Routines |*****************/ +/******************| Support Routines |*****************/ /***************************************************************************/ static void system_cache_lookup(Oid element_type, - bool input, - int *typlen, - bool *typbyval, - char *typdelim, - Oid *typelem, - Oid *proc, - char *typalign) + bool input, + int *typlen, + bool * typbyval, + char *typdelim, + Oid * typelem, + Oid * proc, + char *typalign) { - HeapTuple typeTuple; - TypeTupleForm typeStruct; - - typeTuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(element_type), - 0,0,0); - - if (!HeapTupleIsValid(typeTuple)) { - elog(WARN, "array_out: Cache lookup failed for type %d\n", - element_type); - return; - } - typeStruct = (TypeTupleForm) GETSTRUCT(typeTuple); - *typlen = typeStruct->typlen; - *typbyval = typeStruct->typbyval; - *typdelim = typeStruct->typdelim; - *typelem = typeStruct->typelem; - *typalign = typeStruct->typalign; - if (input) { - *proc = typeStruct->typinput; - } else { - *proc = typeStruct->typoutput; - } + HeapTuple typeTuple; + TypeTupleForm typeStruct; + + typeTuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(element_type), + 0, 0, 0); + + if (!HeapTupleIsValid(typeTuple)) + { + elog(WARN, "array_out: Cache lookup failed for type %d\n", + element_type); + return; + } + typeStruct = (TypeTupleForm) GETSTRUCT(typeTuple); + *typlen = typeStruct->typlen; + *typbyval = typeStruct->typbyval; + *typdelim = typeStruct->typdelim; + *typelem = typeStruct->typelem; + *typalign = typeStruct->typalign; + if (input) + { + *proc = typeStruct->typinput; + } + else + { + *proc = typeStruct->typoutput; + } } -static Datum +static Datum _ArrayCast(char *value, bool byval, int len) { - if (byval) { - switch (len) { - case 1: - return((Datum) * value); - case 2: - return((Datum) * (int16 *) value); - case 3: - case 4: - return((Datum) * (int32 *) value); - default: - elog(WARN, "array_ref: byval and elt len > 4!"); - break; - } - } else { - return (Datum) value; - } - return 0; + if (byval) + { + switch (len) + { + case 1: + return ((Datum) * value); + case 2: + return ((Datum) * (int16 *) value); + case 3: + case 4: + return ((Datum) * (int32 *) value); + default: + elog(WARN, "array_ref: byval and elt len > 4!"); + break; + } + } + else + { + return (Datum) value; + } + return 0; } static int ArrayCastAndSet(char *src, - bool typbyval, - int typlen, - char *dest) + bool typbyval, + int typlen, + char *dest) { - int inc; - - if (typlen > 0) { - if (typbyval) { - switch(typlen) { - case 1: - *dest = DatumGetChar(src); - break; - case 2: - * (int16 *) dest = DatumGetInt16(src); - break; - case 4: - * (int32 *) dest = (int32)src; - break; - } - } else { - memmove(dest, src, typlen); - } - inc = typlen; - } else { - memmove(dest, src, *(int32 *)src); - inc = (INTALIGN(* (int32 *) src)); - } - return(inc); -} + int inc; + + if (typlen > 0) + { + if (typbyval) + { + switch (typlen) + { + case 1: + *dest = DatumGetChar(src); + break; + case 2: + *(int16 *) dest = DatumGetInt16(src); + break; + case 4: + *(int32 *) dest = (int32) src; + break; + } + } + else + { + memmove(dest, src, typlen); + } + inc = typlen; + } + else + { + memmove(dest, src, *(int32 *) src); + inc = (INTALIGN(*(int32 *) src)); + } + return (inc); +} #ifdef LOARRAY -static char * +static char * _AdvanceBy1word(char *str, char **word) { - char *retstr, *space; - - *word = NULL; - if (str == NULL) return str; - while (isspace(*str)) str++; - *word = str; - if ((space = (char *)strchr(str, ' ')) != (char *) NULL) { - retstr = space + 1; - *space = '\0'; - } - else - retstr = NULL; - return retstr; + char *retstr, + *space; + + *word = NULL; + if (str == NULL) + return str; + while (isspace(*str)) + str++; + *word = str; + if ((space = (char *) strchr(str, ' ')) != (char *) NULL) + { + retstr = space + 1; + *space = '\0'; + } + else + retstr = NULL; + return retstr; } + #endif static int SanityCheckInput(int ndim, int n, int dim[], int lb[], int indx[]) { - int i; - /* Do Sanity check on input */ - if (n != ndim) return 0; - for (i = 0; i < ndim; i++) - if ((lb[i] > indx[i]) || (indx[i] >= (dim[i] + lb[i]))) - return 0; - return 1; + int i; + + /* Do Sanity check on input */ + if (n != ndim) + return 0; + for (i = 0; i < ndim; i++) + if ((lb[i] > indx[i]) || (indx[i] >= (dim[i] + lb[i]))) + return 0; + return 1; } static void _ArrayRange(int st[], - int endp[], - int bsize, - char *destPtr, - ArrayType *array, - int from) + int endp[], + int bsize, + char *destPtr, + ArrayType * array, + int from) { - int n, *dim, *lb, st_pos, prod[MAXDIM]; - int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; - int i, j, inc; - char *srcPtr; - - n = ARR_NDIM(array); dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); srcPtr = ARR_DATA_PTR(array); - for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); - mda_get_prod(n, dim, prod); - st_pos = tuple2linear(n, st, prod); - srcPtr = array_seek(srcPtr, bsize, st_pos); - mda_get_range(n, span, st, endp); - mda_get_offset_values(n, dist, prod, span); - for (i=0; i < n; indx[i++]=0); - i = j = n-1; inc = bsize; - do { - srcPtr = array_seek(srcPtr, bsize, dist[j]); - if (from) - inc = array_read(destPtr, bsize, 1, srcPtr); - else - inc = array_read(srcPtr, bsize, 1, destPtr); - destPtr += inc; srcPtr += inc; - } while ((j = next_tuple(i+1, indx, span)) != -1); + int n, + *dim, + *lb, + st_pos, + prod[MAXDIM]; + int span[MAXDIM], + dist[MAXDIM], + indx[MAXDIM]; + int i, + j, + inc; + char *srcPtr; + + n = ARR_NDIM(array); + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + srcPtr = ARR_DATA_PTR(array); + for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); + mda_get_prod(n, dim, prod); + st_pos = tuple2linear(n, st, prod); + srcPtr = array_seek(srcPtr, bsize, st_pos); + mda_get_range(n, span, st, endp); + mda_get_offset_values(n, dist, prod, span); + for (i = 0; i < n; indx[i++] = 0); + i = j = n - 1; + inc = bsize; + do + { + srcPtr = array_seek(srcPtr, bsize, dist[j]); + if (from) + inc = array_read(destPtr, bsize, 1, srcPtr); + else + inc = array_read(srcPtr, bsize, 1, destPtr); + destPtr += inc; + srcPtr += inc; + } while ((j = next_tuple(i + 1, indx, span)) != -1); } static int -_ArrayClipCount(int stI[], int endpI[], ArrayType *array) +_ArrayClipCount(int stI[], int endpI[], ArrayType * array) { - int n, *dim, *lb, st_pos, prod[MAXDIM]; - int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; - int i, j, inc, st[MAXDIM], endp[MAXDIM]; - int count = 0; - char *ptr; - - n = ARR_NDIM(array); dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); ptr = ARR_DATA_PTR(array); - for (i = 0; i < n; st[i] = stI[i]-lb[i], endp[i]=endpI[i]-lb[i], i++); - mda_get_prod(n, dim, prod); - st_pos = tuple2linear(n, st, prod); - ptr = array_seek(ptr, -1, st_pos); - mda_get_range(n, span, st, endp); - mda_get_offset_values(n, dist, prod, span); - for (i=0; i < n; indx[i++]=0); - i = j = n-1; - do { - ptr = array_seek(ptr, -1, dist[j]); - inc = INTALIGN(* (int32 *) ptr); - ptr += inc; count += inc; - } while ((j = next_tuple(i+1, indx, span)) != -1); - return count; + int n, + *dim, + *lb, + st_pos, + prod[MAXDIM]; + int span[MAXDIM], + dist[MAXDIM], + indx[MAXDIM]; + int i, + j, + inc, + st[MAXDIM], + endp[MAXDIM]; + int count = 0; + char *ptr; + + n = ARR_NDIM(array); + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + ptr = ARR_DATA_PTR(array); + for (i = 0; i < n; st[i] = stI[i] - lb[i], endp[i] = endpI[i] - lb[i], i++); + mda_get_prod(n, dim, prod); + st_pos = tuple2linear(n, st, prod); + ptr = array_seek(ptr, -1, st_pos); + mda_get_range(n, span, st, endp); + mda_get_offset_values(n, dist, prod, span); + for (i = 0; i < n; indx[i++] = 0); + i = j = n - 1; + do + { + ptr = array_seek(ptr, -1, dist[j]); + inc = INTALIGN(*(int32 *) ptr); + ptr += inc; + count += inc; + } while ((j = next_tuple(i + 1, indx, span)) != -1); + return count; } -static char * +static char * array_seek(char *ptr, int eltsize, int nitems) { - int i; - - if (eltsize > 0) - return(ptr + eltsize*nitems); - for (i = 0; i < nitems; i++) - ptr += INTALIGN(* (int32 *) ptr); - return(ptr); + int i; + + if (eltsize > 0) + return (ptr + eltsize * nitems); + for (i = 0; i < nitems; i++) + ptr += INTALIGN(*(int32 *) ptr); + return (ptr); } static int array_read(char *destptr, int eltsize, int nitems, char *srcptr) { - int i, inc, tmp; - - if (eltsize > 0) { - memmove(destptr, srcptr, eltsize*nitems); - return(eltsize*nitems); - } - for (i = inc = 0; i < nitems; i++) { - tmp = (INTALIGN(* (int32 *) srcptr)); - memmove(destptr, srcptr, tmp); - srcptr += tmp; - destptr += tmp; - inc += tmp; - } - return(inc); + int i, + inc, + tmp; + + if (eltsize > 0) + { + memmove(destptr, srcptr, eltsize * nitems); + return (eltsize * nitems); + } + for (i = inc = 0; i < nitems; i++) + { + tmp = (INTALIGN(*(int32 *) srcptr)); + memmove(destptr, srcptr, tmp); + srcptr += tmp; + destptr += tmp; + inc += tmp; + } + return (inc); } static void _LOArrayRange(int st[], - int endp[], - int bsize, - int srcfd, - int destfd, - ArrayType *array, - int isSrcLO, - bool *isNull) + int endp[], + int bsize, + int srcfd, + int destfd, + ArrayType * array, + int isSrcLO, + bool * isNull) { - int n, *dim, st_pos, prod[MAXDIM]; - int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; - int i, j, inc, tmp, *lb, offset; - - n = ARR_NDIM(array); dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); - - mda_get_prod(n, dim, prod); - st_pos = tuple2linear(n, st, prod); - offset = st_pos*bsize; - if (lo_lseek(srcfd, offset, SEEK_SET) < 0) - return; - mda_get_range(n, span, st, endp); - mda_get_offset_values(n, dist, prod, span); - for (i=0; i < n; indx[i++]=0); - for (i = n-1, inc = bsize; i >= 0; inc *= span[i--]) - if (dist[i]) - break; - j = n-1; - do { - offset += (dist[j]*bsize); - if (lo_lseek(srcfd, offset, SEEK_SET) < 0) - return; - tmp = _LOtransfer((char**)&srcfd, inc, 1, (char**)&destfd, isSrcLO, 1); - if ( tmp < inc ) - return; - offset += inc; - } while ((j = next_tuple(i+1, indx, span)) != -1); + int n, + *dim, + st_pos, + prod[MAXDIM]; + int span[MAXDIM], + dist[MAXDIM], + indx[MAXDIM]; + int i, + j, + inc, + tmp, + *lb, + offset; + + n = ARR_NDIM(array); + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); + + mda_get_prod(n, dim, prod); + st_pos = tuple2linear(n, st, prod); + offset = st_pos * bsize; + if (lo_lseek(srcfd, offset, SEEK_SET) < 0) + return; + mda_get_range(n, span, st, endp); + mda_get_offset_values(n, dist, prod, span); + for (i = 0; i < n; indx[i++] = 0); + for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--]) + if (dist[i]) + break; + j = n - 1; + do + { + offset += (dist[j] * bsize); + if (lo_lseek(srcfd, offset, SEEK_SET) < 0) + return; + tmp = _LOtransfer((char **) &srcfd, inc, 1, (char **) &destfd, isSrcLO, 1); + if (tmp < inc) + return; + offset += inc; + } while ((j = next_tuple(i + 1, indx, span)) != -1); } static void -_ReadArray (int st[], - int endp[], - int bsize, - int srcfd, - int destfd, - ArrayType *array, - int isDestLO, - bool *isNull) +_ReadArray(int st[], + int endp[], + int bsize, + int srcfd, + int destfd, + ArrayType * array, + int isDestLO, + bool * isNull) { - int n, *dim, st_pos, prod[MAXDIM]; - int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; - int i, j, inc, tmp, *lb, offset; - - n = ARR_NDIM(array); dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); - - mda_get_prod(n, dim, prod); - st_pos = tuple2linear(n, st, prod); - offset = st_pos*bsize; - if (lo_lseek(srcfd, offset, SEEK_SET) < 0) - return; - mda_get_range(n, span, st, endp); - mda_get_offset_values(n, dist, prod, span); - for (i=0; i < n; indx[i++]=0); - for (i = n-1, inc = bsize; i >= 0; inc *= span[i--]) - if (dist[i]) - break; - j = n-1; - do { - offset += (dist[j]*bsize); - if (lo_lseek(srcfd, offset, SEEK_SET) < 0) - return; - tmp = _LOtransfer((char**)&destfd, inc, 1, (char**)&srcfd, 1, isDestLO); - if ( tmp < inc ) - return; - offset += inc; - } while ((j = next_tuple(i+1, indx, span)) != -1); + int n, + *dim, + st_pos, + prod[MAXDIM]; + int span[MAXDIM], + dist[MAXDIM], + indx[MAXDIM]; + int i, + j, + inc, + tmp, + *lb, + offset; + + n = ARR_NDIM(array); + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); + + mda_get_prod(n, dim, prod); + st_pos = tuple2linear(n, st, prod); + offset = st_pos * bsize; + if (lo_lseek(srcfd, offset, SEEK_SET) < 0) + return; + mda_get_range(n, span, st, endp); + mda_get_offset_values(n, dist, prod, span); + for (i = 0; i < n; indx[i++] = 0); + for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--]) + if (dist[i]) + break; + j = n - 1; + do + { + offset += (dist[j] * bsize); + if (lo_lseek(srcfd, offset, SEEK_SET) < 0) + return; + tmp = _LOtransfer((char **) &destfd, inc, 1, (char **) &srcfd, 1, isDestLO); + if (tmp < inc) + return; + offset += inc; + } while ((j = next_tuple(i + 1, indx, span)) != -1); } int _LOtransfer(char **destfd, - int size, - int nitems, - char **srcfd, - int isSrcLO, - int isDestLO) + int size, + int nitems, + char **srcfd, + int isSrcLO, + int isDestLO) { #define MAX_READ (512 * 1024) #define min(a, b) (a < b ? a : b) - struct varlena *v = NULL; - int tmp, inc, resid; - - inc = nitems*size; - if (isSrcLO && isDestLO && inc > 0) - for (tmp = 0, resid = inc; - resid > 0 && (inc = min(resid, MAX_READ)) > 0; resid -= inc) { + struct varlena *v = NULL; + int tmp, + inc, + resid; + + inc = nitems * size; + if (isSrcLO && isDestLO && inc > 0) + for (tmp = 0, resid = inc; + resid > 0 && (inc = min(resid, MAX_READ)) > 0; resid -= inc) + { #ifdef LOARRAY - v = (struct varlena *) LOread((int) *srcfd, inc); - if (VARSIZE(v) - 4 < inc) - {pfree(v); return(-1);} - tmp += LOwrite((int) *destfd, v); + v = (struct varlena *) LOread((int) *srcfd, inc); + if (VARSIZE(v) - 4 < inc) + { + pfree(v); + return (-1); + } + tmp += LOwrite((int) *destfd, v); #endif - pfree(v); - - } - else if (!isSrcLO && isDestLO) { - tmp = lo_write((int) *destfd, *srcfd, inc); - *srcfd = *srcfd + tmp; - } - else if (isSrcLO && !isDestLO) { - tmp = lo_read((int) *srcfd, *destfd, inc); - *destfd = *destfd + tmp; - } - else { - memmove(*destfd, *srcfd, inc); - tmp = inc; - *srcfd += inc; - *destfd += inc; - } - return(tmp); + pfree(v); + + } + else if (!isSrcLO && isDestLO) + { + tmp = lo_write((int) *destfd, *srcfd, inc); + *srcfd = *srcfd + tmp; + } + else if (isSrcLO && !isDestLO) + { + tmp = lo_read((int) *srcfd, *destfd, inc); + *destfd = *destfd + tmp; + } + else + { + memmove(*destfd, *srcfd, inc); + tmp = inc; + *srcfd += inc; + *destfd += inc; + } + return (tmp); #undef MAX_READ } -char * +char * _array_newLO(int *fd, int flag) { - char *p; - char saveName[NAME_LEN]; - - p = (char *) palloc(NAME_LEN); - sprintf(p, "/Arry.%d", newoid()); - strcpy (saveName, p); + char *p; + char saveName[NAME_LEN]; + + p = (char *) palloc(NAME_LEN); + sprintf(p, "/Arry.%d", newoid()); + strcpy(saveName, p); #ifdef LOARRAY - if ( (*fd = LOcreat (saveName, 0600, flag)) < 0) - elog(WARN, "Large object create failed"); + if ((*fd = LOcreat(saveName, 0600, flag)) < 0) + elog(WARN, "Large object create failed"); #endif - return (p); + return (p); } - diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c index fce0b0ddd57..09a58d46e2c 100644 --- a/src/backend/utils/adt/arrayutils.c +++ b/src/backend/utils/adt/arrayutils.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * arrayutils.c-- - * This file contains some support routines required for array functions. + * This file contains some support routines required for array functions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayutils.c,v 1.3 1996/11/10 03:03:03 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayutils.c,v 1.4 1997/09/07 04:49:57 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,94 +20,109 @@ int GetOffset(int n, int dim[], int lb[], int indx[]) -{ - int i, scale, offset; - for (i = n-1, scale = 1, offset = 0; i >= 0; scale*=dim[i--]) - offset += (indx[i] - lb[i])*scale; - return offset ; +{ + int i, + scale, + offset; + + for (i = n - 1, scale = 1, offset = 0; i >= 0; scale *= dim[i--]) + offset += (indx[i] - lb[i]) * scale; + return offset; } int getNitems(int n, int a[]) -{ - int i, ret; - for (i = 0, ret = 1; i < n; ret *= a[i++]); - if (n == 0) ret = 0; - return ret; +{ + int i, + ret; + + for (i = 0, ret = 1; i < n; ret *= a[i++]); + if (n == 0) + ret = 0; + return ret; } int compute_size(int st[], int endp[], int n, int base) { - int i, ret; - for (i = 0, ret = base; i < n; i++) - ret *= (endp[i] - st[i] + 1); - return ret; + int i, + ret; + + for (i = 0, ret = base; i < n; i++) + ret *= (endp[i] - st[i] + 1); + return ret; } void mda_get_offset_values(int n, int dist[], int PC[], int span[]) -{ - int i, j; - for (j = n-2, dist[n-1]=0; j >= 0; j--) - for (i = j+1, dist[j] = PC[j]-1; i < n; - dist[j] -= (span[i] - 1)*PC[i], i++); -} +{ + int i, + j; + + for (j = n - 2, dist[n - 1] = 0; j >= 0; j--) + for (i = j + 1, dist[j] = PC[j] - 1; i < n; + dist[j] -= (span[i] - 1) * PC[i], i++); +} void mda_get_range(int n, int span[], int st[], int endp[]) -{ - int i; - for (i= 0; i < n; i++) - span[i] = endp[i] - st[i] + 1; -} +{ + int i; + + for (i = 0; i < n; i++) + span[i] = endp[i] - st[i] + 1; +} void mda_get_prod(int n, int range[], int P[]) -{ - int i; - for (i= n-2, P[n-1] = 1; i >= 0; i--) - P[i] = P[i+1] * range[i + 1]; -} +{ + int i; + + for (i = n - 2, P[n - 1] = 1; i >= 0; i--) + P[i] = P[i + 1] * range[i + 1]; +} int tuple2linear(int n, int tup[], int scale[]) { - int i, lin; - for (i= lin = 0; i < n; i++) - lin += tup[i]*scale[i]; - return lin; -} + int i, + lin; + + for (i = lin = 0; i < n; i++) + lin += tup[i] * scale[i]; + return lin; +} void array2chunk_coord(int n, int C[], int a_coord[], int c_coord[]) { - int i; - for (i= 0; i < n; i++) - c_coord[i] = a_coord[i]/C[i]; + int i; + + for (i = 0; i < n; i++) + c_coord[i] = a_coord[i] / C[i]; } /*----------------------------------------------------------------------------- generates the tuple that is lexicographically one greater than the current n-tuple in "curr", with the restriction that the i-th element of "curr" is less than the i-th element of "span". - RETURNS 0 if no next tuple exists + RETURNS 0 if no next tuple exists 1 otherwise -----------------------------------------------------------------------------*/ int next_tuple(int n, int curr[], int span[]) { - int i; - - if (!n) return(-1); - curr[n-1] = (curr[n-1]+1)%span[n-1]; - for (i = n-1; i*(!curr[i]); i--) - curr[i-1] = (curr[i-1]+1)%span[i-1]; - - if (i) - return(i); - if (curr[0]) - return(0); - return(-1); -} + int i; + if (!n) + return (-1); + curr[n - 1] = (curr[n - 1] + 1) % span[n - 1]; + for (i = n - 1; i * (!curr[i]); i--) + curr[i - 1] = (curr[i - 1] + 1) % span[i - 1]; + + if (i) + return (i); + if (curr[0]) + return (0); + return (-1); +} diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c index cb9163f020f..d02661efa67 100644 --- a/src/backend/utils/adt/bool.c +++ b/src/backend/utils/adt/bool.c @@ -1,74 +1,74 @@ /*------------------------------------------------------------------------- * * bool.c-- - * Functions for the built-in type "bool". + * Functions for the built-in type "bool". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/bool.c,v 1.4 1997/04/27 19:20:07 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/bool.c,v 1.5 1997/09/07 04:49:58 momjian Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "utils/builtins.h" /* where the declarations go */ +#include "utils/builtins.h" /* where the declarations go */ #include "utils/palloc.h" -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* - * boolin - converts "t" or "f" to 1 or 0 + * boolin - converts "t" or "f" to 1 or 0 */ bool boolin(char *b) { - if (b == NULL) - elog(WARN, "Bad input string for type bool"); - return((bool) (*b == 't') || (*b == 'T')); + if (b == NULL) + elog(WARN, "Bad input string for type bool"); + return ((bool) (*b == 't') || (*b == 'T')); } /* - * boolout - converts 1 or 0 to "t" or "f" + * boolout - converts 1 or 0 to "t" or "f" */ -char * +char * boolout(long b) { - char *result = (char *) palloc(2); - - *result = (b) ? 't' : 'f'; - result[1] = '\0'; - return(result); + char *result = (char *) palloc(2); + + *result = (b) ? 't' : 'f'; + result[1] = '\0'; + return (result); } -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ bool -booleq(int8 arg1, int8 arg2) -{ - return(arg1 == arg2); +booleq(int8 arg1, int8 arg2) +{ + return (arg1 == arg2); } bool -boolne(int8 arg1, int8 arg2) +boolne(int8 arg1, int8 arg2) { - return(arg1 != arg2); + return (arg1 != arg2); } bool -boollt(int8 arg1, int8 arg2) -{ - return(arg1 < arg2); +boollt(int8 arg1, int8 arg2) +{ + return (arg1 < arg2); } bool -boolgt(int8 arg1, int8 arg2) -{ - return(arg1 > arg2); +boolgt(int8 arg1, int8 arg2) +{ + return (arg1 > arg2); } diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index 1cadb742e62..763ac5856ce 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -8,8 +8,8 @@ * A slightly modified version of this file and a discussion of the * workings can be found in the book "Software Solutions in C" by * Dale Schumacher, Academic Press, ISBN: 0-12-632360-7. - * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.9 1997/08/22 07:12:52 momjian Exp $ + * + * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.10 1997/09/07 04:49:59 momjian Exp $ */ #include <stdio.h> @@ -26,332 +26,363 @@ static const char *num_word(Cash value); /* when we go to 64 bit values we will have to modify this */ -#define CASH_BUFSZ 24 +#define CASH_BUFSZ 24 -#define TERMINATOR (CASH_BUFSZ - 1) -#define LAST_PAREN (TERMINATOR - 1) -#define LAST_DIGIT (LAST_PAREN - 1) +#define TERMINATOR (CASH_BUFSZ - 1) +#define LAST_PAREN (TERMINATOR - 1) +#define LAST_DIGIT (LAST_PAREN - 1) #ifdef USE_LOCALE static struct lconv *lconv = NULL; + #endif /* cash_in() * Convert a string to a cash data type. * Format is [$]###[,]###[.##] * Examples: 123.45 $123.45 $123,456.78 - * + * * This is currently implemented as a 32-bit integer. * XXX HACK It looks as though some of the symbols for - * monetary values returned by localeconv() can be multiple - * bytes/characters. This code assumes one byte only. - tgl 97/04/14 + * monetary values returned by localeconv() can be multiple + * bytes/characters. This code assumes one byte only. - tgl 97/04/14 */ -Cash * +Cash * cash_in(const char *str) { - Cash *result; - - Cash value = 0; - Cash dec = 0; - Cash sgn = 1; - int seen_dot = 0; - const char *s = str; - int fpoint; - char dsymbol, ssymbol, psymbol, nsymbol, csymbol; + Cash *result; + + Cash value = 0; + Cash dec = 0; + Cash sgn = 1; + int seen_dot = 0; + const char *s = str; + int fpoint; + char dsymbol, + ssymbol, + psymbol, + nsymbol, + csymbol; #ifdef USE_LOCALE - if (lconv == NULL) lconv = localeconv(); - - /* frac_digits in the C locale seems to return CHAR_MAX */ - /* best guess is 2 in this case I think */ - fpoint = ((lconv->frac_digits != CHAR_MAX)? lconv->frac_digits: 2); /* int_frac_digits? */ - - dsymbol = *lconv->mon_decimal_point; - ssymbol = *lconv->mon_thousands_sep; - csymbol = *lconv->currency_symbol; - psymbol = *lconv->positive_sign; - nsymbol = *lconv->negative_sign; + if (lconv == NULL) + lconv = localeconv(); + + /* frac_digits in the C locale seems to return CHAR_MAX */ + /* best guess is 2 in this case I think */ + fpoint = ((lconv->frac_digits != CHAR_MAX) ? lconv->frac_digits : 2); /* int_frac_digits? */ + + dsymbol = *lconv->mon_decimal_point; + ssymbol = *lconv->mon_thousands_sep; + csymbol = *lconv->currency_symbol; + psymbol = *lconv->positive_sign; + nsymbol = *lconv->negative_sign; #else - fpoint = 2; - dsymbol = '.'; - ssymbol = ','; - csymbol = '$'; - psymbol = '+'; - nsymbol = '-'; + fpoint = 2; + dsymbol = '.'; + ssymbol = ','; + csymbol = '$'; + psymbol = '+'; + nsymbol = '-'; #endif - /* we need to add all sorts of checking here. For now just */ - /* strip all leading whitespace and any leading dollar sign */ - while (isspace(*s) || *s == csymbol) s++; - - /* a leading minus or paren signifies a negative number */ - /* again, better heuristics needed */ - if (*s == nsymbol || *s == '(') { - sgn = -1; - s++; - - } else if (*s == psymbol) { - s++; - } - - while (isspace(*s) || *s == csymbol) s++; - - for (; ; s++) { - /* we look for digits as int4 as we have less */ - /* than the required number of decimal places */ - if (isdigit(*s) && dec < fpoint) { - value = (value * 10) + *s - '0'; - - if (seen_dot) - dec++; - - /* decimal point? then start counting fractions... */ - } else if (*s == dsymbol && !seen_dot) { - seen_dot = 1; + /* we need to add all sorts of checking here. For now just */ + /* strip all leading whitespace and any leading dollar sign */ + while (isspace(*s) || *s == csymbol) + s++; - /* "thousands" separator? then skip... */ - } else if (*s == ssymbol) { + /* a leading minus or paren signifies a negative number */ + /* again, better heuristics needed */ + if (*s == nsymbol || *s == '(') + { + sgn = -1; + s++; - } else { - /* round off */ - if (isdigit(*s) && *s >= '5') - value++; - - /* adjust for less than required decimal places */ - for (; dec < fpoint; dec++) - value *= 10; + } + else if (*s == psymbol) + { + s++; + } - break; + while (isspace(*s) || *s == csymbol) + s++; + + for (;; s++) + { + /* we look for digits as int4 as we have less */ + /* than the required number of decimal places */ + if (isdigit(*s) && dec < fpoint) + { + value = (value * 10) + *s - '0'; + + if (seen_dot) + dec++; + + /* decimal point? then start counting fractions... */ + } + else if (*s == dsymbol && !seen_dot) + { + seen_dot = 1; + + /* "thousands" separator? then skip... */ + } + else if (*s == ssymbol) + { + + } + else + { + /* round off */ + if (isdigit(*s) && *s >= '5') + value++; + + /* adjust for less than required decimal places */ + for (; dec < fpoint; dec++) + value *= 10; + + break; + } } - } - while (isspace(*s) || *s == '0' || *s == ')') s++; + while (isspace(*s) || *s == '0' || *s == ')') + s++; - if (*s != '\0') - elog(WARN,"Bad money external representation %s",str); + if (*s != '\0') + elog(WARN, "Bad money external representation %s", str); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't input cash '%s'",str); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't input cash '%s'", str); - *result = (value * sgn); + *result = (value * sgn); - return(result); -} /* cash_in() */ + return (result); +} /* cash_in() */ /* cash_out() * Function to convert cash to a dollars and cents representation. * XXX HACK This code appears to assume US conventions for - * positive-valued amounts. - tgl 97/04/14 + * positive-valued amounts. - tgl 97/04/14 */ -const char * -cash_out(Cash *value) +const char * +cash_out(Cash * value) { - char *result; - char buf[CASH_BUFSZ]; - int minus = 0; - int count = LAST_DIGIT; - int point_pos; - int comma_position = 0; - char mon_group, comma, points; - char csymbol, dsymbol, *nsymbol; - char convention; + char *result; + char buf[CASH_BUFSZ]; + int minus = 0; + int count = LAST_DIGIT; + int point_pos; + int comma_position = 0; + char mon_group, + comma, + points; + char csymbol, + dsymbol, + *nsymbol; + char convention; #ifdef USE_LOCALE - if (lconv == NULL) lconv = localeconv(); - - mon_group = *lconv->mon_grouping; - comma = *lconv->mon_thousands_sep; - csymbol = *lconv->currency_symbol; - dsymbol = *lconv->mon_decimal_point; - nsymbol = lconv->negative_sign; - /* frac_digits in the C locale seems to return CHAR_MAX */ - /* best guess is 2 in this case I think */ - points = ((lconv->frac_digits != CHAR_MAX)? lconv->frac_digits: 2); /* int_frac_digits? */ - convention = lconv->n_sign_posn; + if (lconv == NULL) + lconv = localeconv(); + + mon_group = *lconv->mon_grouping; + comma = *lconv->mon_thousands_sep; + csymbol = *lconv->currency_symbol; + dsymbol = *lconv->mon_decimal_point; + nsymbol = lconv->negative_sign; + /* frac_digits in the C locale seems to return CHAR_MAX */ + /* best guess is 2 in this case I think */ + points = ((lconv->frac_digits != CHAR_MAX) ? lconv->frac_digits : 2); /* int_frac_digits? */ + convention = lconv->n_sign_posn; #else - mon_group = 3; - comma = ','; - csymbol = '$'; - dsymbol = '.'; - nsymbol = "-"; - points = 2; - convention = 0; + mon_group = 3; + comma = ','; + csymbol = '$'; + dsymbol = '.'; + nsymbol = "-"; + points = 2; + convention = 0; #endif - point_pos = LAST_DIGIT - points; + point_pos = LAST_DIGIT - points; - /* We're playing a little fast and loose with this. Shoot me. */ - if (!mon_group || mon_group == CHAR_MAX) - mon_group = 3; + /* We're playing a little fast and loose with this. Shoot me. */ + if (!mon_group || mon_group == CHAR_MAX) + mon_group = 3; + + /* allow more than three decimal points and separate them */ + if (comma) + { + point_pos -= (points - 1) / mon_group; + comma_position = point_pos % (mon_group + 1); + } + + /* we work with positive amounts and add the minus sign at the end */ + if (*value < 0) + { + minus = 1; + *value *= -1; + } - /* allow more than three decimal points and separate them */ - if (comma) { - point_pos -= (points - 1)/mon_group; - comma_position = point_pos % (mon_group + 1); - } - - /* we work with positive amounts and add the minus sign at the end */ - if (*value < 0) { - minus = 1; - *value *= -1; - } - - /* allow for trailing negative strings */ - memset(buf, ' ', CASH_BUFSZ); - buf[TERMINATOR] = buf[LAST_PAREN] = '\0'; - - while (*value || count > (point_pos - 2)) { - if (points && count == point_pos) - buf[count--] = dsymbol; - else if (comma && count % (mon_group + 1) == comma_position) - buf[count--] = comma; - - buf[count--] = (*value % 10) + '0'; - *value /= 10; - } - - buf[count] = csymbol; - - if (buf[LAST_DIGIT] == ',') - buf[LAST_DIGIT] = buf[LAST_PAREN]; - - /* see if we need to signify negative amount */ - if (minus) { - if (!PointerIsValid(result = PALLOC(CASH_BUFSZ + 2 - count + strlen(nsymbol)))) - elog(WARN,"Memory allocation failed, can't output cash",NULL); - - /* Position code of 0 means use parens */ - if (convention == 0) - sprintf(result, "(%s)", buf + count); - else if (convention == 2) - sprintf(result, "%s%s", buf + count, nsymbol); + /* allow for trailing negative strings */ + memset(buf, ' ', CASH_BUFSZ); + buf[TERMINATOR] = buf[LAST_PAREN] = '\0'; + + while (*value || count > (point_pos - 2)) + { + if (points && count == point_pos) + buf[count--] = dsymbol; + else if (comma && count % (mon_group + 1) == comma_position) + buf[count--] = comma; + + buf[count--] = (*value % 10) + '0'; + *value /= 10; + } + + buf[count] = csymbol; + + if (buf[LAST_DIGIT] == ',') + buf[LAST_DIGIT] = buf[LAST_PAREN]; + + /* see if we need to signify negative amount */ + if (minus) + { + if (!PointerIsValid(result = PALLOC(CASH_BUFSZ + 2 - count + strlen(nsymbol)))) + elog(WARN, "Memory allocation failed, can't output cash", NULL); + + /* Position code of 0 means use parens */ + if (convention == 0) + sprintf(result, "(%s)", buf + count); + else if (convention == 2) + sprintf(result, "%s%s", buf + count, nsymbol); + else + sprintf(result, "%s%s", nsymbol, buf + count); + } else - sprintf(result, "%s%s", nsymbol, buf + count); - } else { - if (!PointerIsValid(result = PALLOC(CASH_BUFSZ + 2 - count))) - elog(WARN,"Memory allocation failed, can't output cash",NULL); + { + if (!PointerIsValid(result = PALLOC(CASH_BUFSZ + 2 - count))) + elog(WARN, "Memory allocation failed, can't output cash", NULL); - strcpy(result, buf + count); - } + strcpy(result, buf + count); + } - return(result); -} /* cash_out() */ + return (result); +} /* cash_out() */ bool -cash_eq(Cash *c1, Cash *c2) +cash_eq(Cash * c1, Cash * c2) { - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(FALSE); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (FALSE); - return(*c1 == *c2); -} /* cash_eq() */ + return (*c1 == *c2); +} /* cash_eq() */ bool -cash_ne(Cash *c1, Cash *c2) +cash_ne(Cash * c1, Cash * c2) { - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(FALSE); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (FALSE); - return(*c1 != *c2); -} /* cash_ne() */ + return (*c1 != *c2); +} /* cash_ne() */ bool -cash_lt(Cash *c1, Cash *c2) +cash_lt(Cash * c1, Cash * c2) { - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(FALSE); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (FALSE); - return(*c1 < *c2); -} /* cash_lt() */ + return (*c1 < *c2); +} /* cash_lt() */ bool -cash_le(Cash *c1, Cash *c2) +cash_le(Cash * c1, Cash * c2) { - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(FALSE); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (FALSE); - return(*c1 <= *c2); -} /* cash_le() */ + return (*c1 <= *c2); +} /* cash_le() */ bool -cash_gt(Cash *c1, Cash *c2) +cash_gt(Cash * c1, Cash * c2) { - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(FALSE); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (FALSE); - return(*c1 > *c2); -} /* cash_gt() */ + return (*c1 > *c2); +} /* cash_gt() */ bool -cash_ge(Cash *c1, Cash *c2) +cash_ge(Cash * c1, Cash * c2) { - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(FALSE); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (FALSE); - return(*c1 >= *c2); -} /* cash_ge() */ + return (*c1 >= *c2); +} /* cash_ge() */ /* cash_pl() * Add two cash values. */ -Cash * -cash_pl(Cash *c1, Cash *c2) +Cash * +cash_pl(Cash * c1, Cash * c2) { - Cash *result; + Cash *result; - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(NULL); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (NULL); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't add cash",NULL); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't add cash", NULL); - *result = (*c1 + *c2); + *result = (*c1 + *c2); - return(result); -} /* cash_pl() */ + return (result); +} /* cash_pl() */ /* cash_mi() * Subtract two cash values. */ -Cash * -cash_mi(Cash *c1, Cash *c2) +Cash * +cash_mi(Cash * c1, Cash * c2) { - Cash *result; + Cash *result; - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(NULL); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (NULL); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't subtract cash",NULL); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't subtract cash", NULL); - *result = (*c1 - *c2); + *result = (*c1 - *c2); - return(result); -} /* cash_mi() */ + return (result); +} /* cash_mi() */ /* cash_mul() * Multiply cash by floating point number. */ -Cash * -cash_mul(Cash *c, float8 *f) +Cash * +cash_mul(Cash * c, float8 * f) { - Cash *result; + Cash *result; - if (!PointerIsValid(f) || !PointerIsValid(c)) - return(NULL); + if (!PointerIsValid(f) || !PointerIsValid(c)) + return (NULL); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't multiply cash",NULL); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't multiply cash", NULL); - *result = ((*f) * (*c)); + *result = ((*f) * (*c)); - return(result); -} /* cash_mul() */ + return (result); +} /* cash_mul() */ /* cash_div() @@ -360,116 +391,121 @@ cash_mul(Cash *c, float8 *f) * XXX Don't know if rounding or truncating is correct behavior. * Round for now. - tgl 97/04/15 */ -Cash * -cash_div(Cash *c, float8 *f) +Cash * +cash_div(Cash * c, float8 * f) { - Cash *result; + Cash *result; - if (!PointerIsValid(f) || !PointerIsValid(c)) - return(NULL); + if (!PointerIsValid(f) || !PointerIsValid(c)) + return (NULL); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't divide cash",NULL); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't divide cash", NULL); - if (*f == 0.0) - elog(WARN,"cash_div: divide by 0.0 error"); + if (*f == 0.0) + elog(WARN, "cash_div: divide by 0.0 error"); - *result = rint(*c / *f); + *result = rint(*c / *f); - return(result); -} /* cash_div() */ + return (result); +} /* cash_div() */ /* cashlarger() * Return larger of two cash values. */ -Cash * -cashlarger(Cash *c1, Cash *c2) +Cash * +cashlarger(Cash * c1, Cash * c2) { - Cash *result; + Cash *result; - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(NULL); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (NULL); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't return larger cash",NULL); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't return larger cash", NULL); - *result = ((*c1 > *c2)? *c1: *c2); + *result = ((*c1 > *c2) ? *c1 : *c2); - return(result); -} /* cashlarger() */ + return (result); +} /* cashlarger() */ /* cashsmaller() * Return smaller of two cash values. */ -Cash * -cashsmaller(Cash *c1, Cash *c2) +Cash * +cashsmaller(Cash * c1, Cash * c2) { - Cash *result; + Cash *result; - if (!PointerIsValid(c1) || !PointerIsValid(c2)) - return(NULL); + if (!PointerIsValid(c1) || !PointerIsValid(c2)) + return (NULL); - if (!PointerIsValid(result = PALLOCTYPE(Cash))) - elog(WARN,"Memory allocation failed, can't return smaller cash",NULL); + if (!PointerIsValid(result = PALLOCTYPE(Cash))) + elog(WARN, "Memory allocation failed, can't return smaller cash", NULL); - *result = ((*c1 < *c2)? *c1: *c2); + *result = ((*c1 < *c2) ? *c1 : *c2); - return(result); -} /* cashsmaller() */ + return (result); +} /* cashsmaller() */ /* cash_words_out() * This converts a int4 as well but to a representation using words * Obviously way North American centric - sorry */ -const char * -cash_words_out(Cash *value) +const char * +cash_words_out(Cash * value) { - static char buf[128]; - char *p = buf; - Cash m0; - Cash m1; - Cash m2; - Cash m3; - - /* work with positive numbers */ - if (*value < 0) { - *value *= -1; - strcpy(buf, "minus "); - p += 6; - } else { - *buf = 0; - } - - m0 = *value % 100; /* cents */ - m1 = (*value/100) % 1000; /* hundreds */ - m2 = (*value/100000) % 1000; /* thousands */ - m3 = *value/100000000 % 1000; /* millions */ - - if (m3) { - strcat(buf, num_word(m3)); - strcat(buf, " million "); - } - - if (m2) { - strcat(buf, num_word(m2)); - strcat(buf, " thousand "); - } - - if (m1) - strcat(buf, num_word(m1)); - - if (!*p) - strcat(buf, "zero"); - - strcat(buf, (int)(*value/100) == 1 ? " dollar and " : " dollars and "); - strcat(buf, num_word(m0)); - strcat(buf, m0 == 1 ? " cent" : " cents"); - *buf = toupper(*buf); - return(buf); -} /* cash_words_out() */ + static char buf[128]; + char *p = buf; + Cash m0; + Cash m1; + Cash m2; + Cash m3; + + /* work with positive numbers */ + if (*value < 0) + { + *value *= -1; + strcpy(buf, "minus "); + p += 6; + } + else + { + *buf = 0; + } + + m0 = *value % 100; /* cents */ + m1 = (*value / 100) % 1000; /* hundreds */ + m2 = (*value / 100000) % 1000; /* thousands */ + m3 = *value / 100000000 % 1000; /* millions */ + + if (m3) + { + strcat(buf, num_word(m3)); + strcat(buf, " million "); + } + + if (m2) + { + strcat(buf, num_word(m2)); + strcat(buf, " thousand "); + } + + if (m1) + strcat(buf, num_word(m1)); + + if (!*p) + strcat(buf, "zero"); + + strcat(buf, (int) (*value / 100) == 1 ? " dollar and " : " dollars and "); + strcat(buf, num_word(m0)); + strcat(buf, m0 == 1 ? " cent" : " cents"); + *buf = toupper(*buf); + return (buf); +} /* cash_words_out() */ /************************************************************************* @@ -479,48 +515,52 @@ cash_words_out(Cash *value) static const char * num_word(Cash value) { - static char buf[128]; - static const char *small[] = { - "zero", "one", "two", "three", "four", "five", "six", "seven", - "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", - "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", - "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" - }; - const char **big = small + 18; - int tu = value % 100; - - /* deal with the simple cases first */ - if (value <= 20) - return(small[value]); - - /* is it an even multiple of 100? */ - if (!tu) { - sprintf(buf, "%s hundred", small[value/100]); - return(buf); - } - - /* more than 99? */ - if (value > 99) { - /* is it an even multiple of 10 other than 10? */ - if (value % 10 == 0 && tu > 10) - sprintf(buf, "%s hundred %s", - small[value/100], big[tu/10]); - else if (tu < 20) - sprintf(buf, "%s hundred and %s", - small[value/100], small[tu]); - else - sprintf(buf, "%s hundred %s %s", - small[value/100], big[tu/10], small[tu % 10]); - - } else { - /* is it an even multiple of 10 other than 10? */ - if (value % 10 == 0 && tu > 10) - sprintf(buf, "%s", big[tu/10]); - else if (tu < 20) - sprintf(buf, "%s", small[tu]); + static char buf[128]; + static const char *small[] = { + "zero", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", + "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", + "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" + }; + const char **big = small + 18; + int tu = value % 100; + + /* deal with the simple cases first */ + if (value <= 20) + return (small[value]); + + /* is it an even multiple of 100? */ + if (!tu) + { + sprintf(buf, "%s hundred", small[value / 100]); + return (buf); + } + + /* more than 99? */ + if (value > 99) + { + /* is it an even multiple of 10 other than 10? */ + if (value % 10 == 0 && tu > 10) + sprintf(buf, "%s hundred %s", + small[value / 100], big[tu / 10]); + else if (tu < 20) + sprintf(buf, "%s hundred and %s", + small[value / 100], small[tu]); + else + sprintf(buf, "%s hundred %s %s", + small[value / 100], big[tu / 10], small[tu % 10]); + + } else - sprintf(buf, "%s %s", big[tu/10], small[tu % 10]); - } + { + /* is it an even multiple of 10 other than 10? */ + if (value % 10 == 0 && tu > 10) + sprintf(buf, "%s", big[tu / 10]); + else if (tu < 20) + sprintf(buf, "%s", small[tu]); + else + sprintf(buf, "%s %s", big[tu / 10], small[tu % 10]); + } - return(buf); -} /* num_word() */ + return (buf); +} /* num_word() */ diff --git a/src/backend/utils/adt/char.c b/src/backend/utils/adt/char.c index afb87a4d8b3..24e30054b6b 100644 --- a/src/backend/utils/adt/char.c +++ b/src/backend/utils/adt/char.c @@ -1,384 +1,460 @@ /*------------------------------------------------------------------------- * * char.c-- - * Functions for the built-in type "char". - * Functions for the built-in type "cid". - * Functions for the built-in type "char2". - * Functions for the built-in type "char4". - * Functions for the built-in type "char8". - * Functions for the built-in type "char16". + * Functions for the built-in type "char". + * Functions for the built-in type "cid". + * Functions for the built-in type "char2". + * Functions for the built-in type "char4". + * Functions for the built-in type "char8". + * Functions for the built-in type "char16". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.7 1997/08/12 20:39:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.8 1997/09/07 04:50:02 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include "postgres.h" #include "utils/palloc.h" #include "utils/builtins.h" /* where the declarations go */ -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* - * charin - converts "x" to 'x' + * charin - converts "x" to 'x' */ -int32 charin(char *ch) +int32 +charin(char *ch) { - if (ch == NULL) - return((int32) NULL); - return((int32) *ch); + if (ch == NULL) + return ((int32) NULL); + return ((int32) * ch); } /* - * charout - converts 'x' to "x" + * charout - converts 'x' to "x" */ -char *charout(int32 ch) +char * +charout(int32 ch) { - char *result = (char *) palloc(2); - - result[0] = (char) ch; - result[1] = '\0'; - return(result); + char *result = (char *) palloc(2); + + result[0] = (char) ch; + result[1] = '\0'; + return (result); } /* - * cidin - converts "..." to internal representation. + * cidin - converts "..." to internal representation. * - * NOTE: we must not use 'charin' because cid might be a non - * printable character... + * NOTE: we must not use 'charin' because cid might be a non + * printable character... */ -int32 cidin(char *s) +int32 +cidin(char *s) { - CommandId c; - - if (s==NULL) - c = 0; - else - c = atoi(s); - - return((int32)c); + CommandId c; + + if (s == NULL) + c = 0; + else + c = atoi(s); + + return ((int32) c); } /* - * cidout - converts a cid to "..." + * cidout - converts a cid to "..." * - * NOTE: we must no use 'charout' because cid might be a non - * printable character... + * NOTE: we must no use 'charout' because cid might be a non + * printable character... */ -char *cidout(int32 c) -{ - char *result; - CommandId c2; - - /* - * cid is a number between 0 .. 2^16-1, therefore we need at most - * 6 chars for the string (5 digits + '\0') - * NOTE: print it as an UNSIGNED int! - */ - result = palloc(6); - c2 = (CommandId)c; - sprintf(result, "%u", (unsigned)(c2)); - return(result); +char * +cidout(int32 c) +{ + char *result; + CommandId c2; + + /* + * cid is a number between 0 .. 2^16-1, therefore we need at most 6 + * chars for the string (5 digits + '\0') NOTE: print it as an + * UNSIGNED int! + */ + result = palloc(6); + c2 = (CommandId) c; + sprintf(result, "%u", (unsigned) (c2)); + return (result); } /* - * char16in - converts "..." to internal reprsentation + * char16in - converts "..." to internal reprsentation * - * Note: - * Currently if strlen(s) < 14, the extra chars are nulls + * Note: + * Currently if strlen(s) < 14, the extra chars are nulls */ -char *char16in(char *s) +char * +char16in(char *s) { - char *result; + char *result; - if (s == NULL) - return(NULL); - result = (char *) palloc(16); - strncpy(result, s, 16); - return(result); + if (s == NULL) + return (NULL); + result = (char *) palloc(16); + strncpy(result, s, 16); + return (result); } /* - * char16out - converts internal reprsentation to "..." + * char16out - converts internal reprsentation to "..." */ -char *char16out(char *s) +char * +char16out(char *s) { - char *result = (char *) palloc(17); - - if (s == NULL) { - result[0] = '-'; - result[1] = '\0'; - } else - strNcpy(result, s, 16); - return(result); + char *result = (char *) palloc(17); + + if (s == NULL) + { + result[0] = '-'; + result[1] = '\0'; + } + else + strNcpy(result, s, 16); + return (result); } -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ -bool chareq(int8 arg1, int8 arg2) { return(arg1 == arg2); } -bool charne(int8 arg1, int8 arg2) { return(arg1 != arg2); } -bool charlt(int8 arg1, int8 arg2) { return((uint8)arg1 < (uint8)arg2); } -bool charle(int8 arg1, int8 arg2) { return((uint8)arg1 <= (uint8)arg2); } -bool chargt(int8 arg1, int8 arg2) { return((uint8)arg1 > (uint8)arg2); } -bool charge(int8 arg1, int8 arg2) { return((uint8)arg1 >= (uint8)arg2); } -int8 charpl(int8 arg1, int8 arg2) { return(arg1 + arg2); } -int8 charmi(int8 arg1, int8 arg2) { return(arg1 - arg2); } -int8 charmul(int8 arg1, int8 arg2) { return(arg1 * arg2); } -int8 chardiv(int8 arg1, int8 arg2) { return(arg1 / arg2); } +bool chareq(int8 arg1, int8 arg2) +{ + return (arg1 == arg2); +} +bool charne(int8 arg1, int8 arg2) +{ + return (arg1 != arg2); +} +bool charlt(int8 arg1, int8 arg2) +{ + return ((uint8) arg1 < (uint8) arg2); +} +bool charle(int8 arg1, int8 arg2) +{ + return ((uint8) arg1 <= (uint8) arg2); +} +bool chargt(int8 arg1, int8 arg2) +{ + return ((uint8) arg1 > (uint8) arg2); +} +bool charge(int8 arg1, int8 arg2) +{ + return ((uint8) arg1 >= (uint8) arg2); +} +int8 charpl(int8 arg1, int8 arg2) +{ + return (arg1 + arg2); +} +int8 charmi(int8 arg1, int8 arg2) +{ + return (arg1 - arg2); +} +int8 charmul(int8 arg1, int8 arg2) +{ + return (arg1 * arg2); +} +int8 chardiv(int8 arg1, int8 arg2) +{ + return (arg1 / arg2); +} -bool cideq(int8 arg1, int8 arg2) { return(arg1 == arg2); } +bool cideq(int8 arg1, int8 arg2) +{ + return (arg1 == arg2); +} /* - * char16eq - returns 1 iff arguments are equal - * char16ne - returns 1 iff arguments are not equal + * char16eq - returns 1 iff arguments are equal + * char16ne - returns 1 iff arguments are not equal * - * BUGS: - * Assumes that "xy\0\0a" should be equal to "xy\0b". - * If not, can do the comparison backwards for efficiency. + * BUGS: + * Assumes that "xy\0\0a" should be equal to "xy\0b". + * If not, can do the comparison backwards for efficiency. * - * char16lt - returns 1 iff a < b - * char16le - returns 1 iff a <= b - * char16gt - returns 1 iff a < b - * char16ge - returns 1 iff a <= b + * char16lt - returns 1 iff a < b + * char16le - returns 1 iff a <= b + * char16gt - returns 1 iff a < b + * char16ge - returns 1 iff a <= b * */ -bool char16eq(char *arg1, char *arg2) +bool +char16eq(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 16) == 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 16) == 0); } -bool char16ne(char *arg1, char *arg2) +bool +char16ne(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 16) != 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 16) != 0); } -bool char16lt(char *arg1, char *arg2) +bool +char16lt(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 16) < 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 16) < 0); } -bool char16le(char *arg1, char *arg2) +bool +char16le(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 16) <= 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 16) <= 0); } -bool char16gt(char *arg1, char *arg2) +bool +char16gt(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - - return(strncmp(arg1, arg2, 16) > 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + + return (strncmp(arg1, arg2, 16) > 0); } -bool char16ge(char *arg1, char *arg2) +bool +char16ge(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - - return(strncmp(arg1, arg2, 16) >= 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + + return (strncmp(arg1, arg2, 16) >= 0); } /* ============================== char2 ============================== */ -uint16 char2in(char *s) +uint16 +char2in(char *s) { - uint16 res; - - if (s == NULL) - return(0); - - strncpy((char *) &res, s, 2); - return(res); + uint16 res; + + if (s == NULL) + return (0); + + strncpy((char *) &res, s, 2); + return (res); } -char *char2out(uint16 s) +char * +char2out(uint16 s) { - char *result = (char *) palloc(3); - - strNcpy(result, (char *) &s, 2); - - return(result); + char *result = (char *) palloc(3); + + strNcpy(result, (char *) &s, 2); + + return (result); } -bool char2eq(uint16 a, uint16 b) +bool +char2eq(uint16 a, uint16 b) { - return(strncmp((char *) &a, (char *) &b, 2) == 0); + return (strncmp((char *) &a, (char *) &b, 2) == 0); } -bool char2ne(uint16 a, uint16 b) +bool +char2ne(uint16 a, uint16 b) { - return(strncmp((char *) &a, (char *) &b, 2) != 0); + return (strncmp((char *) &a, (char *) &b, 2) != 0); } -bool char2lt(uint16 a, uint16 b) +bool +char2lt(uint16 a, uint16 b) { - return(strncmp((char *) &a, (char *) &b, 2) < 0); + return (strncmp((char *) &a, (char *) &b, 2) < 0); } -bool char2le(uint16 a, uint16 b) +bool +char2le(uint16 a, uint16 b) { - return(strncmp((char *) &a, (char *) &b, 2) <= 0); + return (strncmp((char *) &a, (char *) &b, 2) <= 0); } -bool char2gt(uint16 a, uint16 b) +bool +char2gt(uint16 a, uint16 b) { - return(strncmp((char *) &a, (char *) &b, 2) > 0); + return (strncmp((char *) &a, (char *) &b, 2) > 0); } -bool char2ge(uint16 a, uint16 b) +bool +char2ge(uint16 a, uint16 b) { - return(strncmp((char *) &a, (char *) &b, 2) >= 0); + return (strncmp((char *) &a, (char *) &b, 2) >= 0); } -int32 char2cmp(uint16 a, uint16 b) +int32 +char2cmp(uint16 a, uint16 b) { - return (strncmp((char *) &a, (char *) &b, 2)); + return (strncmp((char *) &a, (char *) &b, 2)); } /* ============================== char4 ============================== */ -uint32 char4in(char *s) +uint32 +char4in(char *s) { - uint32 res; - - if (s == NULL) - return(0); - - strncpy((char *) &res, s, 4); - - return(res); + uint32 res; + + if (s == NULL) + return (0); + + strncpy((char *) &res, s, 4); + + return (res); } -char *char4out(s) - uint32 s; +char * +char4out(s) +uint32 s; { - char *result = (char *) palloc(5); - - strNcpy(result, (char *) &s, 4); - - return(result); + char *result = (char *) palloc(5); + + strNcpy(result, (char *) &s, 4); + + return (result); } -bool char4eq(uint32 a, uint32 b) +bool +char4eq(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4) == 0); + return (strncmp((char *) &a, (char *) &b, 4) == 0); } -bool char4ne(uint32 a, uint32 b) +bool +char4ne(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4) != 0); + return (strncmp((char *) &a, (char *) &b, 4) != 0); } -bool char4lt(uint32 a, uint32 b) +bool +char4lt(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4) < 0); + return (strncmp((char *) &a, (char *) &b, 4) < 0); } -bool char4le(uint32 a, uint32 b) +bool +char4le(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4) <= 0); + return (strncmp((char *) &a, (char *) &b, 4) <= 0); } -bool char4gt(uint32 a, uint32 b) +bool +char4gt(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4) > 0); + return (strncmp((char *) &a, (char *) &b, 4) > 0); } -bool char4ge(uint32 a, uint32 b) +bool +char4ge(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4) >= 0); + return (strncmp((char *) &a, (char *) &b, 4) >= 0); } -int32 char4cmp(uint32 a, uint32 b) +int32 +char4cmp(uint32 a, uint32 b) { - return(strncmp((char *) &a, (char *) &b, 4)); + return (strncmp((char *) &a, (char *) &b, 4)); } /* ============================== char8 ============================== */ -char *char8in(char *s) +char * +char8in(char *s) { - char *result; - - if (s == NULL) - return((char *) NULL); - - result = (char *) palloc(8); - strncpy(result, s, 8); - return(result); + char *result; + + if (s == NULL) + return ((char *) NULL); + + result = (char *) palloc(8); + strncpy(result, s, 8); + return (result); } -char *char8out(char *s) +char * +char8out(char *s) { - char *result = (char *) palloc(9); - - if (s == NULL) { - result[0] = '-'; - result[1] = '\0'; - } else - strNcpy(result, s, 8); - return(result); + char *result = (char *) palloc(9); + + if (s == NULL) + { + result[0] = '-'; + result[1] = '\0'; + } + else + strNcpy(result, s, 8); + return (result); } -bool char8eq(char *arg1, char *arg2) +bool +char8eq(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 8) == 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 8) == 0); } -bool char8ne(char *arg1, char *arg2) +bool +char8ne(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 8) != 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 8) != 0); } -bool char8lt(char *arg1, char *arg2) +bool +char8lt(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 8) < 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 8) < 0); } -bool char8le(char *arg1, char *arg2) +bool +char8le(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 8) <= 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 8) <= 0); } -bool char8gt(char *arg1, char *arg2) +bool +char8gt(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 8) > 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 8) > 0); } -bool char8ge(char *arg1, char *arg2) +bool +char8ge(char *arg1, char *arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return(strncmp(arg1, arg2, 8) >= 0); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return (strncmp(arg1, arg2, 8) >= 0); } -int32 char8cmp(char *arg1, char *arg2) +int32 +char8cmp(char *arg1, char *arg2) { - return(strncmp(arg1, arg2, 8)); + return (strncmp(arg1, arg2, 8)); } diff --git a/src/backend/utils/adt/chunk.c b/src/backend/utils/adt/chunk.c index 3d9aec0d9e4..fcfc8cdaeb5 100644 --- a/src/backend/utils/adt/chunk.c +++ b/src/backend/utils/adt/chunk.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/chunk.c,v 1.6 1997/08/19 21:34:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/chunk.c,v 1.7 1997/09/07 04:50:04 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,7 @@ #include "utils/memutils.h" #include "libpq/libpq-fs.h" -#include "storage/fd.h" /* for SEEK_ */ +#include "storage/fd.h" /* for SEEK_ */ #include "catalog/pg_type.h" @@ -29,581 +29,666 @@ #include "optimizer/internal.h" #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif #define INFTY 500000000 #define MANY 10000 #define MAXPAT 20 -#define quot_ceil(x,y) (((x)+(y)-1)/(y)) -#define min(x,y) (((x) < (y))? (x) : (y)) -#define max(x,y) (((x) > (y))? (x) : (y)) +#define quot_ceil(x,y) (((x)+(y)-1)/(y)) +#define min(x,y) (((x) < (y))? (x) : (y)) +#define max(x,y) (((x) > (y))? (x) : (y)) static CHUNK_INFO cInfo; /* non-export function prototypes */ -static int _FindBestChunk(int size, int dmax[], int dbest[], int dim, - int A[MAXPAT][MAXDIM+1], int N); -static int get_next(int d[], int k, int C, int dmax[]); -static void initialize_info(CHUNK_INFO *A, int ndim, int dim[], int chunk[]); +static int +_FindBestChunk(int size, int dmax[], int dbest[], int dim, + int A[MAXPAT][MAXDIM + 1], int N); +static int get_next(int d[], int k, int C, int dmax[]); +static void initialize_info(CHUNK_INFO * A, int ndim, int dim[], int chunk[]); + #ifdef LOARRAY -static void _ConvertToChunkFile(int n, int baseSize, int dim[], int C[], - int srcfd, int destfd); -static void read_chunk(int chunk_no[], int C[], char a_chunk[], int srcfd, - int n, int baseSize, int PX[], int dist[]); -static int write_chunk(struct varlena * a_chunk, int ofile); -static int seek_and_read(int pos, int size, char buff[], int fp, int from); +static void +_ConvertToChunkFile(int n, int baseSize, int dim[], int C[], + int srcfd, int destfd); +static void +read_chunk(int chunk_no[], int C[], char a_chunk[], int srcfd, + int n, int baseSize, int PX[], int dist[]); +static int write_chunk(struct varlena * a_chunk, int ofile); +static int seek_and_read(int pos, int size, char buff[], int fp, int from); + #endif -static int GetChunkSize(FILE *fd, int ndim, int dim[MAXDIM], int baseSize, - int d[MAXDIM]); +static int +GetChunkSize(FILE * fd, int ndim, int dim[MAXDIM], int baseSize, + int d[MAXDIM]); /*------------------------------------------------------------------------ * _ChunkArray --- - * converts an input array to chunked format using the information - * provided by the access pattern. + * converts an input array to chunked format using the information + * provided by the access pattern. * Results: - * creates a new file that stores the chunked array and returns - * information about the chunked file + * creates a new file that stores the chunked array and returns + * information about the chunked file *----------------------------------------------------------------------- */ -char * +char * _ChunkArray(int fd, - FILE *afd, - int ndim, - int dim[], - int baseSize, - int *nbytes, - char *chunkfile) + FILE * afd, + int ndim, + int dim[], + int baseSize, + int *nbytes, + char *chunkfile) { #ifdef LOARRAY -int cfd = 0; + int cfd = 0; + #endif - int chunk[MAXDIM], csize; - bool reorgFlag; - - if (chunkfile == NULL) - reorgFlag = true; - else - reorgFlag = false; - + int chunk[MAXDIM], + csize; + bool reorgFlag; + + if (chunkfile == NULL) + reorgFlag = true; + else + reorgFlag = false; + #ifdef LOARRAY - if (reorgFlag) - /* create new LO for chunked file */ - chunkfile = _array_newLO( &cfd, fileFlag ); - else - cfd = LOopen(chunkfile, O_RDONLY); - if (cfd < 0) - elog(WARN, "Unable to open chunk file"); + if (reorgFlag) + /* create new LO for chunked file */ + chunkfile = _array_newLO(&cfd, fileFlag); + else + cfd = LOopen(chunkfile, O_RDONLY); + if (cfd < 0) + elog(WARN, "Unable to open chunk file"); #endif - strcpy (cInfo.lo_name, chunkfile); - - /* find chunk size */ - csize = GetChunkSize(afd, ndim, dim, baseSize, chunk); - + strcpy(cInfo.lo_name, chunkfile); + + /* find chunk size */ + csize = GetChunkSize(afd, ndim, dim, baseSize, chunk); + #ifdef LOARRAY - if (reorgFlag) - /* copy data from input file to chunked file */ - _ConvertToChunkFile(ndim, baseSize, dim, chunk, fd, cfd); + if (reorgFlag) + /* copy data from input file to chunked file */ + _ConvertToChunkFile(ndim, baseSize, dim, chunk, fd, cfd); #endif - - initialize_info(&cInfo, ndim, dim, chunk); - *nbytes = sizeof(CHUNK_INFO); - return (char *) &cInfo ; + + initialize_info(&cInfo, ndim, dim, chunk); + *nbytes = sizeof(CHUNK_INFO); + return (char *) &cInfo; } /*-------------------------------------------------------------------------- * GetChunkSize -- - * given an access pattern and array dimensionality etc, this program - * returns the dimensions of the chunk in "d" + * given an access pattern and array dimensionality etc, this program + * returns the dimensions of the chunk in "d" *----------------------------------------------------------------------- */ static int -GetChunkSize(FILE *fd, - int ndim, - int dim[MAXDIM], - int baseSize, - int d[MAXDIM]) +GetChunkSize(FILE * fd, + int ndim, + int dim[MAXDIM], + int baseSize, + int d[MAXDIM]) { - int N, i, j, csize; - int A[MAXPAT][MAXDIM+1], dmax[MAXDIM]; - - /* - * ----------- read input ------------ - */ - fscanf(fd, "%d", &N); - if ( N > MAXPAT ) - elog(WARN, "array_in: too many access pattern elements"); - for (i = 0; i < N; i++) - for (j = 0; j < ndim+1; j++) - if (fscanf(fd, "%d ", &(A[i][j])) == EOF) - elog (WARN, "array_in: bad access pattern input"); - - /* - * estimate chunk size - */ - for (i = 0; i < ndim; i++) - for (j = 0, dmax[i] = 1; j < N; j++) - if (dmax[i] < A[j][i]) - dmax[i] = A[j][i]; - csize = BLCKSZ/baseSize; - - _FindBestChunk (csize, dmax, d, ndim, A, N); - - return csize; + int N, + i, + j, + csize; + int A[MAXPAT][MAXDIM + 1], + dmax[MAXDIM]; + + /* + * ----------- read input ------------ + */ + fscanf(fd, "%d", &N); + if (N > MAXPAT) + elog(WARN, "array_in: too many access pattern elements"); + for (i = 0; i < N; i++) + for (j = 0; j < ndim + 1; j++) + if (fscanf(fd, "%d ", &(A[i][j])) == EOF) + elog(WARN, "array_in: bad access pattern input"); + + /* + * estimate chunk size + */ + for (i = 0; i < ndim; i++) + for (j = 0, dmax[i] = 1; j < N; j++) + if (dmax[i] < A[j][i]) + dmax[i] = A[j][i]; + csize = BLCKSZ / baseSize; + + _FindBestChunk(csize, dmax, d, ndim, A, N); + + return csize; } /*------------------------------------------------------------------------- * _FindBestChunk -- - * This routine does most of the number crunching to compute the - * optimal chunk shape. + * This routine does most of the number crunching to compute the + * optimal chunk shape. * Called by GetChunkSize *------------------------------------------------------------------------ */ static int _FindBestChunk(int size, - int dmax[], - int dbest[], - int dim, - int A[MAXPAT][MAXDIM+1], - int N) + int dmax[], + int dbest[], + int dim, + int A[MAXPAT][MAXDIM + 1], + int N) { - int d[MAXDIM]; - int tc, mintc = INFTY; - - d[0] = 0; - mintc = INFTY; - while (get_next(d,dim,size, dmax)) { - /* - * compute the number of page fetches for a given - * chunk size (d[]) and access pattern (A[][]) - */ - register int i,j, nc; - for (i = 0, tc = 0; i < N; i++){ - for (j = 0, nc = 1; j < dim; j++) - nc *= quot_ceil(A[i][j], d[j]); - nc *= A[i][dim]; - tc += nc; + int d[MAXDIM]; + int tc, + mintc = INFTY; + + d[0] = 0; + mintc = INFTY; + while (get_next(d, dim, size, dmax)) + { + + /* + * compute the number of page fetches for a given chunk size (d[]) + * and access pattern (A[][]) + */ + register int i, + j, + nc; + + for (i = 0, tc = 0; i < N; i++) + { + for (j = 0, nc = 1; j < dim; j++) + nc *= quot_ceil(A[i][j], d[j]); + nc *= A[i][dim]; + tc += nc; + } + + /* + * tc holds the total number of page fetches + */ + if (mintc >= tc) + { + mintc = tc; + for (j = 0; j < dim; dbest[j] = d[j], j++) + ; + } } - /* - * tc holds the total number of page fetches - */ - if (mintc >= tc) { - mintc = tc; - for (j = 0; j < dim; dbest[j] = d[j], j++) - ; - } - } - return(mintc); + return (mintc); } /*---------------------------------------------------------------------- * get_next -- - * Called by _GetBestChunk to get the next tuple in the lexicographic order + * Called by _GetBestChunk to get the next tuple in the lexicographic order *--------------------------------------------------------------------- */ static int get_next(int d[], int k, int C, int dmax[]) { - register int i,j, temp; - - if (!d[0]) { - temp = C; - for (j = k-1; j >= 0; j--){ - d[j] = min(temp, dmax[j]); - temp = max(1, temp/d[j]); - } - return(1); - } - - for (j = 0, temp = 1; j < k; j++) - temp *= d[j]; - - for (i=k-1; i >= 0; i--){ - temp = temp/d[i]; - if (((temp*(d[i]+1)) < C) && (d[i]+1 <= dmax[i])) - break; - } - if (i < 0) - return(0); - - d[i]++; - j = C/temp; - d[i] = min(dmax[i], j/(j/d[i])); - temp = temp*d[i]; - temp = C/temp; - - for (j = k-1; j > i; j--){ - d[j] = min(temp, dmax[j]); - temp = max(1, temp/d[j]); - } - return(1); + register int i, + j, + temp; + + if (!d[0]) + { + temp = C; + for (j = k - 1; j >= 0; j--) + { + d[j] = min(temp, dmax[j]); + temp = max(1, temp / d[j]); + } + return (1); + } + + for (j = 0, temp = 1; j < k; j++) + temp *= d[j]; + + for (i = k - 1; i >= 0; i--) + { + temp = temp / d[i]; + if (((temp * (d[i] + 1)) < C) && (d[i] + 1 <= dmax[i])) + break; + } + if (i < 0) + return (0); + + d[i]++; + j = C / temp; + d[i] = min(dmax[i], j / (j / d[i])); + temp = temp * d[i]; + temp = C / temp; + + for (j = k - 1; j > i; j--) + { + d[j] = min(temp, dmax[j]); + temp = max(1, temp / d[j]); + } + return (1); } #ifdef LOARRAY -static char a_chunk[BLCKSZ + 4]; /* 4 since a_chunk is in - varlena format */ +static char a_chunk[BLCKSZ + 4]; /* 4 since a_chunk is in varlena + * format */ + #endif static void -initialize_info(CHUNK_INFO *A, int ndim, int dim[], int chunk[]) +initialize_info(CHUNK_INFO * A, int ndim, int dim[], int chunk[]) { - int i; - - for ( i = 0; i < ndim; i++) - A->C[i] = chunk[i]; + int i; + + for (i = 0; i < ndim; i++) + A->C[i] = chunk[i]; } /*-------------------------------------------------------------------------- * Procedure reorganize_data(): - * This procedure reads the input multidimensional array that is organised - * in the order specified by array "X" and breaks it up into chunks of - * dimensions specified in "C". + * This procedure reads the input multidimensional array that is organised + * in the order specified by array "X" and breaks it up into chunks of + * dimensions specified in "C". * - * This is a very slow process, since reading and writing of LARGE files - * may be involved. + * This is a very slow process, since reading and writing of LARGE files + * may be involved. * *------------------------------------------------------------------------- */ #ifdef LOARRAY static void _ConvertToChunkFile(int n, - int baseSize, - int dim[], - int C[], - int srcfd, - int destfd) + int baseSize, + int dim[], + int C[], + int srcfd, + int destfd) { - int max_chunks[MAXDIM], chunk_no[MAXDIM]; - int PX[MAXDIM], dist[MAXDIM]; - int csize = 1, i, temp; - - for (i = 0; i < n; chunk_no[i++] = 0) { - max_chunks[i] = dim[i]/C[i]; - csize *= C[i]; - } - csize *= baseSize; - temp = csize + 4; - memmove(a_chunk, &temp, 4); - - mda_get_prod(n, dim, PX); - mda_get_offset_values(n, dist, PX, C); - for (i = 0; i < n; dist[i] *= baseSize, i++) - ; - do { - read_chunk(chunk_no, C, &(a_chunk[4]), srcfd, n, baseSize, PX, dist); - write_chunk((struct varlena*)a_chunk, destfd); - } while (next_tuple(n, chunk_no, max_chunks) != -1); + int max_chunks[MAXDIM], + chunk_no[MAXDIM]; + int PX[MAXDIM], + dist[MAXDIM]; + int csize = 1, + i, + temp; + + for (i = 0; i < n; chunk_no[i++] = 0) + { + max_chunks[i] = dim[i] / C[i]; + csize *= C[i]; + } + csize *= baseSize; + temp = csize + 4; + memmove(a_chunk, &temp, 4); + + mda_get_prod(n, dim, PX); + mda_get_offset_values(n, dist, PX, C); + for (i = 0; i < n; dist[i] *= baseSize, i++) + ; + do + { + read_chunk(chunk_no, C, &(a_chunk[4]), srcfd, n, baseSize, PX, dist); + write_chunk((struct varlena *) a_chunk, destfd); + } while (next_tuple(n, chunk_no, max_chunks) != -1); } /*-------------------------------------------------------------------------- * read_chunk - * reads a chunk from the input files into a_chunk, the position of the - * chunk is specified by chunk_no + * reads a chunk from the input files into a_chunk, the position of the + * chunk is specified by chunk_no *-------------------------------------------------------------------------- */ static void read_chunk(int chunk_no[], - int C[], - char a_chunk[], - int srcfd, - int n, - int baseSize, - int PX[], - int dist[]) + int C[], + char a_chunk[], + int srcfd, + int n, + int baseSize, + int PX[], + int dist[]) { - int i, j, cp, unit_transfer; - int start_pos, pos[MAXDIM]; - int indx[MAXDIM]; - int fpOff; - - for ( i = start_pos = 0; i < n; i++) { - pos[i] = chunk_no[i] * C[i]; - start_pos += pos[i]*PX[i]; - } - start_pos *= baseSize; - - /* Read a block of dimesion C starting at co-ordinates pos */ - unit_transfer = C[n-1] * baseSize; - - for (i = 0; i < n; indx[i++] = 0) - ; - fpOff = start_pos; - seek_and_read(fpOff, unit_transfer, a_chunk, srcfd, SEEK_SET); - fpOff += unit_transfer; - cp = unit_transfer; - - while ((j = next_tuple(n-1, indx, C)) != -1) { - fpOff += dist[j]; - seek_and_read(fpOff, unit_transfer, &(a_chunk[cp]), srcfd, SEEK_SET); - cp += unit_transfer; - fpOff += unit_transfer; - } + int i, + j, + cp, + unit_transfer; + int start_pos, + pos[MAXDIM]; + int indx[MAXDIM]; + int fpOff; + + for (i = start_pos = 0; i < n; i++) + { + pos[i] = chunk_no[i] * C[i]; + start_pos += pos[i] * PX[i]; + } + start_pos *= baseSize; + + /* Read a block of dimesion C starting at co-ordinates pos */ + unit_transfer = C[n - 1] * baseSize; + + for (i = 0; i < n; indx[i++] = 0) + ; + fpOff = start_pos; + seek_and_read(fpOff, unit_transfer, a_chunk, srcfd, SEEK_SET); + fpOff += unit_transfer; + cp = unit_transfer; + + while ((j = next_tuple(n - 1, indx, C)) != -1) + { + fpOff += dist[j]; + seek_and_read(fpOff, unit_transfer, &(a_chunk[cp]), srcfd, SEEK_SET); + cp += unit_transfer; + fpOff += unit_transfer; + } } /*-------------------------------------------------------------------------- * write_chunk() - * writes a chunk of size csize into the output file + * writes a chunk of size csize into the output file *-------------------------------------------------------------------------- */ static int write_chunk(struct varlena * a_chunk, int ofile) { - int got_n = 0; + int got_n = 0; + #ifdef LOARRAY - got_n = LOwrite (ofile, a_chunk); + got_n = LOwrite(ofile, a_chunk); #endif - return(got_n); + return (got_n); } /*-------------------------------------------------------------------------- * seek_and_read() - * seeks to the asked location in the input file and reads the - * appropriate number of blocks - * Called By: read_chunk() + * seeks to the asked location in the input file and reads the + * appropriate number of blocks + * Called By: read_chunk() *-------------------------------------------------------------------------- */ static int seek_and_read(int pos, int size, char buff[], int fp, int from) { - struct varlena *v = NULL; - - /* Assuming only one file */ - if ( lo_lseek(fp, pos, from ) < 0) - elog(WARN, "File seek error"); + struct varlena *v = NULL; + + /* Assuming only one file */ + if (lo_lseek(fp, pos, from) < 0) + elog(WARN, "File seek error"); #ifdef LOARRAY - v = (struct varlena *) LOread(fp, size); + v = (struct varlena *) LOread(fp, size); #endif - if (VARSIZE(v) - 4 < size) - elog(WARN, "File read error"); - memmove(buff, VARDATA(v), size); - pfree(v); - return(1); - + if (VARSIZE(v) - 4 < size) + elog(WARN, "File read error"); + memmove(buff, VARDATA(v), size); + pfree(v); + return (1); + } -#endif /* LOARRAY */ + +#endif /* LOARRAY */ /*---------------------------------------------------------------------------- * _ReadChunkArray -- - * returns the subarray specified bu the range indices "st" and "endp" - * from the chunked array stored in file "fp" + * returns the subarray specified bu the range indices "st" and "endp" + * from the chunked array stored in file "fp" *--------------------------------------------------------------------------- */ int _ReadChunkArray(int st[], - int endp[], - int bsize, - int fp, - char *destfp, - ArrayType *array, - int isDestLO, - bool *isNull) + int endp[], + int bsize, + int fp, + char *destfp, + ArrayType * array, + int isDestLO, + bool * isNull) { - int i,j,jj; - int n, temp, words_read; - int chunk_span[MAXDIM], chunk_off[MAXDIM]; - int chunk_st[MAXDIM], chunk_end[MAXDIM]; - int block_seek; - - int bptr, *C, csize, *dim, *lb; - int range_st[MAXDIM], range_end[MAXDIM], - range[MAXDIM], array_span[MAXDIM]; - int PA[MAXDIM], PCHUNK[MAXDIM], PC[MAXDIM]; - int to_read; - int cdist[MAXDIM], adist[MAXDIM]; - int dist[MAXDIM], temp_seek; - - int srcOff; /* Needed since LO don't understand SEEK_CUR*/ - char *baseDestFp = (char *)destfp; - - CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array); - n = ARR_NDIM(array); - dim = ARR_DIMS(array); - lb = ARR_LBOUND(array); - C = A->C; - - csize = C[n-1]; - PC[n-1] = 1; - temp = dim[n - 1]/C[n-1]; - for (i = n-2; i >= 0; i--){ - PC[i] = PC[i+1] * temp; - temp = dim[i] / C[i]; - csize *= C[i]; - } - - for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++) - ; - mda_get_prod(n, C, PCHUNK); - mda_get_range(n, array_span, st, endp); - mda_get_prod(n, array_span, PA); - - array2chunk_coord(n, C, st, chunk_st); - array2chunk_coord(n, C, endp, chunk_end); - mda_get_range(n, chunk_span, chunk_st, chunk_end); - mda_get_offset_values(n, dist, PC, chunk_span); - - for (i = 0; i < n; i++) { - range_st[i] = st[i]; - range_end[i] = min(chunk_st[i]*C[i]+C[i]-1, endp[i]); - } - - for (i = j = 0; i < n; i++) - j+= chunk_st[i]*PC[i]; - temp_seek = srcOff = j * csize * bsize; - if (lo_lseek(fp, srcOff, SEEK_SET) < 0) RETURN_NULL; - - jj = n-1; - for (i = 0; i < n; chunk_off[i++] = 0) - ; - words_read = 0; temp_seek = 0; - do { - /* Write chunk (chunk_st) to output buffer */ - mda_get_range(n, array_span, range_st, range_end); - mda_get_offset_values(n, adist, PA, array_span); - mda_get_offset_values(n, cdist, PCHUNK, array_span); - for (i=0; i < n; range[i] = range_st[i]-st[i], i++); - bptr = tuple2linear(n, range, PA); - for (i = 0; i < n; range[i++] = 0); - j = n-1; bptr *= bsize; - if (isDestLO) { - if (lo_lseek((int)destfp, bptr, SEEK_SET) < 0) - RETURN_NULL; - } - else - destfp = baseDestFp + bptr; - for(i = 0, block_seek = 0; i < n; i++) - block_seek += (range_st[i]-(chunk_st[i] + chunk_off[i]) - *C[i])*PCHUNK[i]; - if (dist[jj] + block_seek + temp_seek) { - temp = (dist[jj]*csize+block_seek+temp_seek)*bsize; - srcOff += temp; - if (lo_lseek(fp, srcOff, SEEK_SET) < 0) - RETURN_NULL; - } - for (i = n-1, to_read = bsize; i >= 0; - to_read *= min(C[i], array_span[i]), i--) - if (cdist[i] || adist[i]) - break; - do { - if (cdist[j]) { - srcOff += (cdist[j]*bsize); - if (lo_lseek(fp, srcOff, SEEK_SET) < 0) - RETURN_NULL; - } - block_seek += cdist[j]; - bptr += adist[j]*bsize; - if (isDestLO) { - if (lo_lseek((int)destfp, bptr, SEEK_SET) < 0) - RETURN_NULL; - } - else - destfp = baseDestFp + bptr; - temp = _LOtransfer ((char**)&destfp, to_read, 1, (char**)&fp, 1, isDestLO); - if (temp < to_read) + int i, + j, + jj; + int n, + temp, + words_read; + int chunk_span[MAXDIM], + chunk_off[MAXDIM]; + int chunk_st[MAXDIM], + chunk_end[MAXDIM]; + int block_seek; + + int bptr, + *C, + csize, + *dim, + *lb; + int range_st[MAXDIM], + range_end[MAXDIM], + range[MAXDIM], + array_span[MAXDIM]; + int PA[MAXDIM], + PCHUNK[MAXDIM], + PC[MAXDIM]; + int to_read; + int cdist[MAXDIM], + adist[MAXDIM]; + int dist[MAXDIM], + temp_seek; + + int srcOff; /* Needed since LO don't understand + * SEEK_CUR */ + char *baseDestFp = (char *) destfp; + + CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array); + + n = ARR_NDIM(array); + dim = ARR_DIMS(array); + lb = ARR_LBOUND(array); + C = A->C; + + csize = C[n - 1]; + PC[n - 1] = 1; + temp = dim[n - 1] / C[n - 1]; + for (i = n - 2; i >= 0; i--) + { + PC[i] = PC[i + 1] * temp; + temp = dim[i] / C[i]; + csize *= C[i]; + } + + for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++) + ; + mda_get_prod(n, C, PCHUNK); + mda_get_range(n, array_span, st, endp); + mda_get_prod(n, array_span, PA); + + array2chunk_coord(n, C, st, chunk_st); + array2chunk_coord(n, C, endp, chunk_end); + mda_get_range(n, chunk_span, chunk_st, chunk_end); + mda_get_offset_values(n, dist, PC, chunk_span); + + for (i = 0; i < n; i++) + { + range_st[i] = st[i]; + range_end[i] = min(chunk_st[i] * C[i] + C[i] - 1, endp[i]); + } + + for (i = j = 0; i < n; i++) + j += chunk_st[i] * PC[i]; + temp_seek = srcOff = j * csize * bsize; + if (lo_lseek(fp, srcOff, SEEK_SET) < 0) RETURN_NULL; - srcOff += to_read; - words_read+=to_read; - bptr += to_read; - block_seek += (to_read/bsize); - /* - * compute next tuple in range[] - */ - { - int x; - if (!(i+1)) - j = -1; - else { - range[i] = (range[i]+1)%array_span[i]; - for (x = i; x*(!range[x]); x--) - range[x-1] = (range[x-1]+1)%array_span[x-1]; - if (x) - j = x; - else { - if (range[0]) - j = 0; - else - j = -1; - } - } - } - /* - * end of compute next tuple -- - * j is set to -1 if tuple generation is over - */ - } while (j != -1); - - block_seek = csize - block_seek; - temp_seek = block_seek; - jj = next_tuple(n, chunk_off, chunk_span); - if (jj == -1) - break; - range_st[jj] = (chunk_st[jj]+chunk_off[jj])*C[jj]; - range_end[jj] = min(range_st[jj] + C[jj]-1, endp[jj]); - - for (i = jj+1; i < n; i++) { - range_st[i] = st[i]; - range_end[i] = min((chunk_st[i]+chunk_off[i])*C[i]+C[i]-1, endp[i]); - } - } while (jj != -1); - return(words_read); + + jj = n - 1; + for (i = 0; i < n; chunk_off[i++] = 0) + ; + words_read = 0; + temp_seek = 0; + do + { + /* Write chunk (chunk_st) to output buffer */ + mda_get_range(n, array_span, range_st, range_end); + mda_get_offset_values(n, adist, PA, array_span); + mda_get_offset_values(n, cdist, PCHUNK, array_span); + for (i = 0; i < n; range[i] = range_st[i] - st[i], i++); + bptr = tuple2linear(n, range, PA); + for (i = 0; i < n; range[i++] = 0); + j = n - 1; + bptr *= bsize; + if (isDestLO) + { + if (lo_lseek((int) destfp, bptr, SEEK_SET) < 0) + RETURN_NULL; + } + else + destfp = baseDestFp + bptr; + for (i = 0, block_seek = 0; i < n; i++) + block_seek += (range_st[i] - (chunk_st[i] + chunk_off[i]) + * C[i]) * PCHUNK[i]; + if (dist[jj] + block_seek + temp_seek) + { + temp = (dist[jj] * csize + block_seek + temp_seek) * bsize; + srcOff += temp; + if (lo_lseek(fp, srcOff, SEEK_SET) < 0) + RETURN_NULL; + } + for (i = n - 1, to_read = bsize; i >= 0; + to_read *= min(C[i], array_span[i]), i--) + if (cdist[i] || adist[i]) + break; + do + { + if (cdist[j]) + { + srcOff += (cdist[j] * bsize); + if (lo_lseek(fp, srcOff, SEEK_SET) < 0) + RETURN_NULL; + } + block_seek += cdist[j]; + bptr += adist[j] * bsize; + if (isDestLO) + { + if (lo_lseek((int) destfp, bptr, SEEK_SET) < 0) + RETURN_NULL; + } + else + destfp = baseDestFp + bptr; + temp = _LOtransfer((char **) &destfp, to_read, 1, (char **) &fp, 1, isDestLO); + if (temp < to_read) + RETURN_NULL; + srcOff += to_read; + words_read += to_read; + bptr += to_read; + block_seek += (to_read / bsize); + + /* + * compute next tuple in range[] + */ + { + int x; + + if (!(i + 1)) + j = -1; + else + { + range[i] = (range[i] + 1) % array_span[i]; + for (x = i; x * (!range[x]); x--) + range[x - 1] = (range[x - 1] + 1) % array_span[x - 1]; + if (x) + j = x; + else + { + if (range[0]) + j = 0; + else + j = -1; + } + } + } + + /* + * end of compute next tuple -- j is set to -1 if tuple + * generation is over + */ + } while (j != -1); + + block_seek = csize - block_seek; + temp_seek = block_seek; + jj = next_tuple(n, chunk_off, chunk_span); + if (jj == -1) + break; + range_st[jj] = (chunk_st[jj] + chunk_off[jj]) * C[jj]; + range_end[jj] = min(range_st[jj] + C[jj] - 1, endp[jj]); + + for (i = jj + 1; i < n; i++) + { + range_st[i] = st[i]; + range_end[i] = min((chunk_st[i] + chunk_off[i]) * C[i] + C[i] - 1, endp[i]); + } + } while (jj != -1); + return (words_read); } /*------------------------------------------------------------------------ * _ReadChunkArray1El -- - * returns one element of the chunked array as specified by the index "st" - * the chunked file descriptor is "fp" + * returns one element of the chunked array as specified by the index "st" + * the chunked file descriptor is "fp" *------------------------------------------------------------------------- */ struct varlena * _ReadChunkArray1El(int st[], - int bsize, - int fp, - ArrayType *array, - bool *isNull) + int bsize, + int fp, + ArrayType * array, + bool * isNull) { - int i, j, n, temp, srcOff; - int chunk_st[MAXDIM]; - - int *C, csize, *dim, *lb; - int PCHUNK[MAXDIM], PC[MAXDIM]; - - CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array); - - n = ARR_NDIM(array); - lb = ARR_LBOUND(array); - C = A->C; - dim = ARR_DIMS(array); - - csize = C[n-1]; - PC[n-1] = 1; - temp = dim[n - 1]/C[n-1]; - for (i = n-2; i >= 0; i--){ - PC[i] = PC[i+1] * temp; - temp = dim[i] / C[i]; - csize *= C[i]; - } - - for (i = 0; i < n; st[i] -= lb[i], i++); - mda_get_prod(n, C, PCHUNK); - - array2chunk_coord(n, C, st, chunk_st); - - for (i = j = 0; i < n; i++) - j+= chunk_st[i]*PC[i]; - srcOff = j * csize; - - for(i = 0; i < n; i++) - srcOff += (st[i]-chunk_st[i]*C[i])*PCHUNK[i]; - - srcOff *= bsize; - if (lo_lseek(fp, srcOff, SEEK_SET) < 0) - RETURN_NULL; + int i, + j, + n, + temp, + srcOff; + int chunk_st[MAXDIM]; + + int *C, + csize, + *dim, + *lb; + int PCHUNK[MAXDIM], + PC[MAXDIM]; + + CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array); + + n = ARR_NDIM(array); + lb = ARR_LBOUND(array); + C = A->C; + dim = ARR_DIMS(array); + + csize = C[n - 1]; + PC[n - 1] = 1; + temp = dim[n - 1] / C[n - 1]; + for (i = n - 2; i >= 0; i--) + { + PC[i] = PC[i + 1] * temp; + temp = dim[i] / C[i]; + csize *= C[i]; + } + + for (i = 0; i < n; st[i] -= lb[i], i++); + mda_get_prod(n, C, PCHUNK); + + array2chunk_coord(n, C, st, chunk_st); + + for (i = j = 0; i < n; i++) + j += chunk_st[i] * PC[i]; + srcOff = j * csize; + + for (i = 0; i < n; i++) + srcOff += (st[i] - chunk_st[i] * C[i]) * PCHUNK[i]; + + srcOff *= bsize; + if (lo_lseek(fp, srcOff, SEEK_SET) < 0) + RETURN_NULL; #ifdef LOARRAY - return (struct varlena *) LOread(fp, bsize); + return (struct varlena *) LOread(fp, bsize); #endif - return (struct varlena *) 0; + return (struct varlena *) 0; } - diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index d86bc29429a..40369f9a84e 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -1,25 +1,25 @@ /*------------------------------------------------------------------------- * * date.c-- - * Utilities for the built-in type "AbsoluteTime" (defined in nabstime). - * Functions for the built-in type "RelativeTime". - * Functions for the built-in type "TimeInterval". + * Utilities for the built-in type "AbsoluteTime" (defined in nabstime). + * Functions for the built-in type "RelativeTime". + * Functions for the built-in type "TimeInterval". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.14 1997/09/05 18:11:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.15 1997/09/07 04:50:06 momjian Exp $ * * NOTES - * This code is actually (almost) unused. - * It needs to be integrated with Time and struct trange. + * This code is actually (almost) unused. + * It needs to be integrated with Time and struct trange. * * XXX This code needs to be rewritten to work with the "new" definitions * XXX in h/tim.h. Look for int32's, int, long, etc. in the code. The * XXX definitions in h/tim.h may need to be rethought also. * - * XXX This code has been cleaned up some - avi 07/07/93 + * XXX This code has been cleaned up some - avi 07/07/93 * *------------------------------------------------------------------------- */ @@ -33,910 +33,1017 @@ #include "postgres.h" #include "miscadmin.h" #ifdef HAVE_FLOAT_H -# include <float.h> +#include <float.h> #endif #ifdef HAVE_LIMITS_H -# include <limits.h> +#include <limits.h> #endif #include "access/xact.h" -#include "utils/builtins.h" /* where function declarations go */ +#include "utils/builtins.h" /* where function declarations go */ #include "utils/palloc.h" #include "utils/dt.h" -#define INVALID_RELTIME_STR "Undefined RelTime" -#define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1) -#define RELTIME_LABEL '@' -#define RELTIME_PAST "ago" -#define DIRMAXLEN (sizeof(RELTIME_PAST)-1) +#define INVALID_RELTIME_STR "Undefined RelTime" +#define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1) +#define RELTIME_LABEL '@' +#define RELTIME_PAST "ago" +#define DIRMAXLEN (sizeof(RELTIME_PAST)-1) /* - * Unix epoch is Jan 1 00:00:00 1970. Postgres knows about times - * sixty-eight years on either side of that. - */ + * Unix epoch is Jan 1 00:00:00 1970. Postgres knows about times + * sixty-eight years on either side of that. + */ -#define IsSpace(C) ((C) == ' ') +#define IsSpace(C) ((C) == ' ') -#define T_INTERVAL_INVAL 0 /* data represents no valid interval */ -#define T_INTERVAL_VALID 1 /* data represents a valid interval */ +#define T_INTERVAL_INVAL 0 /* data represents no valid interval */ +#define T_INTERVAL_VALID 1 /* data represents a valid interval */ /* * ['Mon May 10 23:59:12 1943 PST' 'Sun Jan 14 03:14:21 1973 PST'] - * 0 1 2 3 4 5 6 + * 0 1 2 3 4 5 6 * 1234567890123456789012345678901234567890123456789012345678901234 * * we allocate some extra -- timezones are usually 3 characters but * this is not in the POSIX standard... */ -#define T_INTERVAL_LEN 80 -#define INVALID_INTERVAL_STR "Undefined Range" -#define INVALID_INTERVAL_STR_LEN (sizeof(INVALID_INTERVAL_STR)-1) +#define T_INTERVAL_LEN 80 +#define INVALID_INTERVAL_STR "Undefined Range" +#define INVALID_INTERVAL_STR_LEN (sizeof(INVALID_INTERVAL_STR)-1) #define ABSTIMEMIN(t1, t2) abstimele((t1),(t2)) ? (t1) : (t2) #define ABSTIMEMAX(t1, t2) abstimelt((t1),(t2)) ? (t2) : (t1) #if FALSE -static char *unit_tab[] = { +static char *unit_tab[] = { "second", "seconds", "minute", "minutes", "hour", "hours", "day", "days", "week", "weeks", - "month", "months", "year", "years"}; -#define UNITMAXLEN 7 /* max length of a unit name */ -#define NUNITS 14 /* number of different units */ +"month", "months", "year", "years"}; + +#define UNITMAXLEN 7 /* max length of a unit name */ +#define NUNITS 14 /* number of different units */ /* table of seconds per unit (month = 30 days, year = 365 days) */ -static int sec_tab[] = { - 1,1, 60, 60, - 3600, 3600, 86400, 86400, 604800, 604800, - 2592000, 2592000, 31536000, 31536000 }; +static int sec_tab[] = { + 1, 1, 60, 60, + 3600, 3600, 86400, 86400, 604800, 604800, +2592000, 2592000, 31536000, 31536000}; + #endif /* * Function prototypes -- internal to this file only */ -static void reltime2tm(int32 time, struct tm *tm); +static void reltime2tm(int32 time, struct tm * tm); #if FALSE -static int correct_unit(char unit[], int *unptr); -static int correct_dir(char direction[], int *signptr); +static int correct_unit(char unit[], int *unptr); +static int correct_dir(char direction[], int *signptr); + #endif -static int istinterval(char *i_string, - AbsoluteTime *i_start, - AbsoluteTime *i_end); +static int +istinterval(char *i_string, + AbsoluteTime * i_start, + AbsoluteTime * i_end); -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* - * reltimein - converts a reltime string in an internal format + * reltimein - converts a reltime string in an internal format */ RelativeTime reltimein(char *str) { - RelativeTime result; + RelativeTime result; - struct tm tt, *tm = &tt; - double fsec; - int dtype; - char *field[MAXDATEFIELDS]; - int nf, ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN+1]; + struct tm tt, + *tm = &tt; + double fsec; + int dtype; + char *field[MAXDATEFIELDS]; + int nf, + ftype[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - elog(WARN,"Bad (null) date external representation",NULL); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) date external representation", NULL); - if (strlen(str) > MAXDATELEN) - elog( WARN, "Bad (length) reltime external representation '%s'",str); + if (strlen(str) > MAXDATELEN) + elog(WARN, "Bad (length) reltime external representation '%s'", str); - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0)) - elog(WARN,"Bad reltime external representation '%s'",str); + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0)) + elog(WARN, "Bad reltime external representation '%s'", str); #ifdef DATEDEBUG -printf( "reltimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE); + printf("reltimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE); #endif - switch (dtype) { - case DTK_DELTA: - result = ((((tm->tm_hour*60)+tm->tm_min)*60)+tm->tm_sec); - result += (((tm->tm_year*365)+(tm->tm_mon*30)+tm->tm_mday)*(24*60*60)); - return(result); + switch (dtype) + { + case DTK_DELTA: + result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec); + result += (((tm->tm_year * 365) + (tm->tm_mon * 30) + tm->tm_mday) * (24 * 60 * 60)); + return (result); - default: - return(INVALID_RELTIME); - } + default: + return (INVALID_RELTIME); + } - elog(WARN,"Bad reltime (internal coding error) '%s'",str); - return(INVALID_RELTIME); -} /* reltimein() */ + elog(WARN, "Bad reltime (internal coding error) '%s'", str); + return (INVALID_RELTIME); +} /* reltimein() */ /* - * reltimeout - converts the internal format to a reltime string + * reltimeout - converts the internal format to a reltime string */ -char *reltimeout(int32 time) +char * +reltimeout(int32 time) { - char *result; - struct tm tt, *tm = &tt; - char buf[MAXDATELEN+1]; + char *result; + struct tm tt, + *tm = &tt; + char buf[MAXDATELEN + 1]; - if (time == INVALID_RELTIME) { - strcpy( buf, INVALID_RELTIME_STR); + if (time == INVALID_RELTIME) + { + strcpy(buf, INVALID_RELTIME_STR); - } else { - reltime2tm(time, tm); - EncodeTimeSpan( tm, 0, DateStyle, buf); - } + } + else + { + reltime2tm(time, tm); + EncodeTimeSpan(tm, 0, DateStyle, buf); + } - result = PALLOC(strlen(buf)+1); - strcpy( result, buf); + result = PALLOC(strlen(buf) + 1); + strcpy(result, buf); - return(result); -} /* reltimeout() */ + return (result); +} /* reltimeout() */ #define TMODULO(t,q,u) {q = (t / u); \ - if (q != 0) t -= (q * u);} + if (q != 0) t -= (q * u);} static void -reltime2tm(int32 time, struct tm *tm) +reltime2tm(int32 time, struct tm * tm) { - TMODULO(time, tm->tm_year, 31536000); - TMODULO(time, tm->tm_mon, 2592000); - TMODULO(time, tm->tm_mday, 86400); - TMODULO(time, tm->tm_hour, 3600); - TMODULO(time, tm->tm_min, 60); - TMODULO(time, tm->tm_sec, 1); + TMODULO(time, tm->tm_year, 31536000); + TMODULO(time, tm->tm_mon, 2592000); + TMODULO(time, tm->tm_mday, 86400); + TMODULO(time, tm->tm_hour, 3600); + TMODULO(time, tm->tm_min, 60); + TMODULO(time, tm->tm_sec, 1); - return; -} /* reltime2tm() */ + return; +} /* reltime2tm() */ #if FALSE - char *timestring; - long quantity; - register int i; - int unitnr; - - timestring = (char *) palloc(Max(strlen(INVALID_RELTIME_STR), - UNITMAXLEN) + 1); - if (timevalue == INVALID_RELTIME) { - strcpy(timestring,INVALID_RELTIME_STR); - return(timestring); - } - if (timevalue == 0) - i = 1; /* unit = 'seconds' */ - else - for (i = 12; i >= 0; i = i-2) - if ((timevalue % sec_tab[i]) == 0) - break; /* appropriate unit found */ - unitnr = i; - quantity = (timevalue / sec_tab[unitnr]); - if (quantity > 1 || quantity < -1) - unitnr++; /* adjust index for PLURAL of unit */ - if (quantity >= 0) - sprintf( timestring, "%c %lu %s", RELTIME_LABEL, - quantity, unit_tab[unitnr]); - else - sprintf( timestring, "%c %lu %s %s", RELTIME_LABEL, - (quantity * -1), unit_tab[unitnr], RELTIME_PAST); - return(timestring); +char *timestring; +long quantity; +register int i; +int unitnr; + +timestring = (char *) palloc(Max(strlen(INVALID_RELTIME_STR), + UNITMAXLEN) + 1); +if (timevalue == INVALID_RELTIME) +{ + strcpy(timestring, INVALID_RELTIME_STR); + return (timestring); +} + +if (timevalue == 0) + i = 1; /* unit = 'seconds' */ +else + for (i = 12; i >= 0; i = i - 2) + if ((timevalue % sec_tab[i]) == 0) + break; /* appropriate unit found */ +unitnr = i; +quantity = (timevalue / sec_tab[unitnr]); +if (quantity > 1 || quantity < -1) + unitnr++; /* adjust index for PLURAL of unit */ +if (quantity >= 0) + sprintf(timestring, "%c %lu %s", RELTIME_LABEL, + quantity, unit_tab[unitnr]); +else + sprintf(timestring, "%c %lu %s %s", RELTIME_LABEL, + (quantity * -1), unit_tab[unitnr], RELTIME_PAST); +return (timestring); } + #endif /* - * tintervalin - converts an interval string to an internal format + * tintervalin - converts an interval string to an internal format */ -TimeInterval tintervalin(char *intervalstr) -{ - int error; - AbsoluteTime i_start, i_end, t1, t2; - TimeInterval interval; - - interval = (TimeInterval) palloc(sizeof(TimeIntervalData)); - error = istinterval(intervalstr, &t1, &t2); - if (error == 0) - interval->status = T_INTERVAL_INVAL; - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - interval->status = T_INTERVAL_INVAL; /* undefined */ - else { - i_start = ABSTIMEMIN(t1, t2); - i_end = ABSTIMEMAX(t1, t2); - interval->data[0] = i_start; - interval->data[1] = i_end; - interval->status = T_INTERVAL_VALID; - } - return(interval); +TimeInterval +tintervalin(char *intervalstr) +{ + int error; + AbsoluteTime i_start, + i_end, + t1, + t2; + TimeInterval interval; + + interval = (TimeInterval) palloc(sizeof(TimeIntervalData)); + error = istinterval(intervalstr, &t1, &t2); + if (error == 0) + interval->status = T_INTERVAL_INVAL; + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + interval->status = T_INTERVAL_INVAL; /* undefined */ + else + { + i_start = ABSTIMEMIN(t1, t2); + i_end = ABSTIMEMAX(t1, t2); + interval->data[0] = i_start; + interval->data[1] = i_end; + interval->status = T_INTERVAL_VALID; + } + return (interval); } /* - * tintervalout - converts an internal interval format to a string + * tintervalout - converts an internal interval format to a string * */ -char *tintervalout(TimeInterval interval) -{ - char *i_str, *p; - - i_str = (char *) palloc( T_INTERVAL_LEN ); /* ['...' '...'] */ - strcpy(i_str,"[\""); - if (interval->status == T_INTERVAL_INVAL) - strcat(i_str,INVALID_INTERVAL_STR); - else { - p = nabstimeout(interval->data[0]); - strcat(i_str,p); - pfree(p); - strcat(i_str,"\" \""); - p = nabstimeout(interval->data[1]); - strcat(i_str,p); - pfree(p); - } - strcat(i_str,"\"]\0"); - return(i_str); -} - - -/***************************************************************************** - * PUBLIC ROUTINES * +char * +tintervalout(TimeInterval interval) +{ + char *i_str, + *p; + + i_str = (char *) palloc(T_INTERVAL_LEN); /* ['...' '...'] */ + strcpy(i_str, "[\""); + if (interval->status == T_INTERVAL_INVAL) + strcat(i_str, INVALID_INTERVAL_STR); + else + { + p = nabstimeout(interval->data[0]); + strcat(i_str, p); + pfree(p); + strcat(i_str, "\" \""); + p = nabstimeout(interval->data[1]); + strcat(i_str, p); + pfree(p); + } + strcat(i_str, "\"]\0"); + return (i_str); +} + + +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ RelativeTime -timespan_reltime(TimeSpan *timespan) +timespan_reltime(TimeSpan * timespan) { - RelativeTime time; - int year, month; - double span; + RelativeTime time; + int year, + month; + double span; - if (!PointerIsValid(timespan)) - time = INVALID_RELTIME; + if (!PointerIsValid(timespan)) + time = INVALID_RELTIME; - if (TIMESPAN_IS_INVALID(*timespan)) { - time = INVALID_RELTIME; + if (TIMESPAN_IS_INVALID(*timespan)) + { + time = INVALID_RELTIME; - } else { - if (timespan->month == 0) { - year = 0; - month = 0; + } + else + { + if (timespan->month == 0) + { + year = 0; + month = 0; - } else if (abs(timespan->month) >= 12) { - year = (timespan->month / 12); - month = (timespan->month % 12); + } + else if (abs(timespan->month) >= 12) + { + year = (timespan->month / 12); + month = (timespan->month % 12); - } else { - year = 0; - month = timespan->month; - } + } + else + { + year = 0; + month = timespan->month; + } - span = (((((double) 365*year)+((double) 30*month))*86400) + timespan->time); + span = (((((double) 365 * year) + ((double) 30 * month)) * 86400) + timespan->time); #ifdef DATEDEBUG -printf( "timespan_reltime- convert m%d s%f to %f [%d %d]\n", - timespan->month, timespan->time, span, INT_MIN, INT_MAX); + printf("timespan_reltime- convert m%d s%f to %f [%d %d]\n", + timespan->month, timespan->time, span, INT_MIN, INT_MAX); #endif - time = (((span > INT_MIN) && (span < INT_MAX))? span: INVALID_RELTIME); - } + time = (((span > INT_MIN) && (span < INT_MAX)) ? span : INVALID_RELTIME); + } - return(time); -} /* timespan_reltime() */ + return (time); +} /* timespan_reltime() */ -TimeSpan * +TimeSpan * reltime_timespan(RelativeTime reltime) { - TimeSpan *result; - int year, month; + TimeSpan *result; + int year, + month; - if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) - elog(WARN,"Memory allocation failed, can't convert reltime to timespan",NULL); + if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) + elog(WARN, "Memory allocation failed, can't convert reltime to timespan", NULL); - switch(reltime) { - case INVALID_RELTIME: - TIMESPAN_INVALID(*result); - break; + switch (reltime) + { + case INVALID_RELTIME: + TIMESPAN_INVALID(*result); + break; - default: - TMODULO(reltime, year, 31536000); - TMODULO(reltime, month, 2592000); + default: + TMODULO(reltime, year, 31536000); + TMODULO(reltime, month, 2592000); - result->time = reltime; - result->month = ((12*year)+month); - } + result->time = reltime; + result->month = ((12 * year) + month); + } - return(result); -} /* reltime_timespan() */ + return (result); +} /* reltime_timespan() */ /* - * mktinterval - creates a time interval with endpoints t1 and t2 + * mktinterval - creates a time interval with endpoints t1 and t2 */ -TimeInterval mktinterval(AbsoluteTime t1, AbsoluteTime t2) +TimeInterval +mktinterval(AbsoluteTime t1, AbsoluteTime t2) { - AbsoluteTime tstart = ABSTIMEMIN(t1, t2), tend = ABSTIMEMAX(t1, t2); - TimeInterval interval; - - interval = (TimeInterval) palloc(sizeof(TimeIntervalData)); - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - interval->status = T_INTERVAL_INVAL; - else { - interval->status = T_INTERVAL_VALID; - interval->data[0] = tstart; - interval->data[1] = tend; - } - - return interval; + AbsoluteTime tstart = ABSTIMEMIN(t1, t2), + tend = ABSTIMEMAX(t1, t2); + TimeInterval interval; + + interval = (TimeInterval) palloc(sizeof(TimeIntervalData)); + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + interval->status = T_INTERVAL_INVAL; + else + { + interval->status = T_INTERVAL_VALID; + interval->data[0] = tstart; + interval->data[1] = tend; + } + + return interval; } /* - * timepl, timemi and abstimemi use the formula - * abstime + reltime = abstime - * so abstime - reltime = abstime - * and abstime - abstime = reltime + * timepl, timemi and abstimemi use the formula + * abstime + reltime = abstime + * so abstime - reltime = abstime + * and abstime - abstime = reltime */ /* - * timepl - returns the value of (abstime t1 + relime t2) + * timepl - returns the value of (abstime t1 + relime t2) */ -AbsoluteTime timepl(AbsoluteTime t1, RelativeTime t2) +AbsoluteTime +timepl(AbsoluteTime t1, RelativeTime t2) { - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - - if (AbsoluteTimeIsReal(t1) && - RelativeTimeIsValid(t2) && - ((t2 > 0) ? (t1 < NOEND_ABSTIME - t2) - : (t1 > NOSTART_ABSTIME - t2))) /* prevent overflow */ - return (t1 + t2); - - return(INVALID_ABSTIME); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + + if (AbsoluteTimeIsReal(t1) && + RelativeTimeIsValid(t2) && + ((t2 > 0) ? (t1 < NOEND_ABSTIME - t2) + : (t1 > NOSTART_ABSTIME - t2))) /* prevent overflow */ + return (t1 + t2); + + return (INVALID_ABSTIME); } /* - * timemi - returns the value of (abstime t1 - reltime t2) + * timemi - returns the value of (abstime t1 - reltime t2) */ -AbsoluteTime timemi(AbsoluteTime t1, RelativeTime t2) +AbsoluteTime +timemi(AbsoluteTime t1, RelativeTime t2) { - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - - if (AbsoluteTimeIsReal(t1) && - RelativeTimeIsValid(t2) && - ((t2 > 0) ? (t1 > NOSTART_ABSTIME + t2) - : (t1 < NOEND_ABSTIME + t2))) /* prevent overflow */ - return (t1 - t2); - - return(INVALID_ABSTIME); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + + if (AbsoluteTimeIsReal(t1) && + RelativeTimeIsValid(t2) && + ((t2 > 0) ? (t1 > NOSTART_ABSTIME + t2) + : (t1 < NOEND_ABSTIME + t2))) /* prevent overflow */ + return (t1 - t2); + + return (INVALID_ABSTIME); } /* - * abstimemi - returns the value of (abstime t1 - abstime t2) + * abstimemi - returns the value of (abstime t1 - abstime t2) */ -static RelativeTime abstimemi(AbsoluteTime t1, AbsoluteTime t2) +static RelativeTime +abstimemi(AbsoluteTime t1, AbsoluteTime t2) { - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - if (AbsoluteTimeIsReal(t1) && - AbsoluteTimeIsReal(t2)) - return (t1 - t2); - - return(INVALID_RELTIME); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + if (AbsoluteTimeIsReal(t1) && + AbsoluteTimeIsReal(t2)) + return (t1 - t2); + + return (INVALID_RELTIME); } /* - * ininterval - returns 1, iff absolute date is in the interval + * ininterval - returns 1, iff absolute date is in the interval */ -int ininterval(AbsoluteTime t, TimeInterval interval) +int +ininterval(AbsoluteTime t, TimeInterval interval) { - if (interval->status == T_INTERVAL_VALID && t != INVALID_ABSTIME) - return (abstimege(t, interval->data[0]) && - abstimele(t, interval->data[1])); - return(0); + if (interval->status == T_INTERVAL_VALID && t != INVALID_ABSTIME) + return (abstimege(t, interval->data[0]) && + abstimele(t, interval->data[1])); + return (0); } /* - * intervalrel - returns relative time corresponding to interval + * intervalrel - returns relative time corresponding to interval */ -RelativeTime intervalrel(TimeInterval interval) +RelativeTime +intervalrel(TimeInterval interval) { - if (interval->status == T_INTERVAL_VALID) - return(abstimemi(interval->data[1], interval->data[0])); - else - return(INVALID_RELTIME); + if (interval->status == T_INTERVAL_VALID) + return (abstimemi(interval->data[1], interval->data[0])); + else + return (INVALID_RELTIME); } /* - * timenow - returns time "now", internal format + * timenow - returns time "now", internal format * - * Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992 + * Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992 */ -AbsoluteTime timenow() +AbsoluteTime +timenow() { - time_t sec; - if (time(&sec) < 0) - return(INVALID_ABSTIME); - return((AbsoluteTime) sec); + time_t sec; + + if (time(&sec) < 0) + return (INVALID_ABSTIME); + return ((AbsoluteTime) sec); } /* - * reltimeeq - returns 1, iff arguments are equal - * reltimene - returns 1, iff arguments are not equal - * reltimelt - returns 1, iff t1 less than t2 - * reltimegt - returns 1, iff t1 greater than t2 - * reltimele - returns 1, iff t1 less than or equal to t2 - * reltimege - returns 1, iff t1 greater than or equal to t2 + * reltimeeq - returns 1, iff arguments are equal + * reltimene - returns 1, iff arguments are not equal + * reltimelt - returns 1, iff t1 less than t2 + * reltimegt - returns 1, iff t1 greater than t2 + * reltimele - returns 1, iff t1 less than or equal to t2 + * reltimege - returns 1, iff t1 greater than or equal to t2 */ -bool reltimeeq(RelativeTime t1, RelativeTime t2) +bool +reltimeeq(RelativeTime t1, RelativeTime t2) { - if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) - return 0; - return(t1 == t2); + if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) + return 0; + return (t1 == t2); } -bool reltimene(RelativeTime t1, RelativeTime t2) +bool +reltimene(RelativeTime t1, RelativeTime t2) { - if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) - return 0; - return(t1 != t2); + if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) + return 0; + return (t1 != t2); } -bool reltimelt(RelativeTime t1, RelativeTime t2) +bool +reltimelt(RelativeTime t1, RelativeTime t2) { - if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) - return 0; - return(t1 < t2); + if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) + return 0; + return (t1 < t2); } -bool reltimegt(RelativeTime t1, RelativeTime t2) +bool +reltimegt(RelativeTime t1, RelativeTime t2) { - if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) - return 0; - return(t1 > t2); + if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) + return 0; + return (t1 > t2); } -bool reltimele(RelativeTime t1, RelativeTime t2) +bool +reltimele(RelativeTime t1, RelativeTime t2) { - if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) - return 0; - return(t1 <= t2); + if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) + return 0; + return (t1 <= t2); } -bool reltimege(RelativeTime t1, RelativeTime t2) +bool +reltimege(RelativeTime t1, RelativeTime t2) { - if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) - return 0; - return(t1 >= t2); + if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) + return 0; + return (t1 >= t2); } /* - * intervaleq - returns 1, iff interval i1 is equal to interval i2 + * intervaleq - returns 1, iff interval i1 is equal to interval i2 */ -bool intervaleq(TimeInterval i1, TimeInterval i2) +bool +intervaleq(TimeInterval i1, TimeInterval i2) { - if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) - return(0); /* invalid interval */ - return(abstimeeq(i1->data[0], i2->data[0]) && - abstimeeq(i1->data[1], i2->data[1])); + if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) + return (0); /* invalid interval */ + return (abstimeeq(i1->data[0], i2->data[0]) && + abstimeeq(i1->data[1], i2->data[1])); } /* - * intervalleneq - returns 1, iff length of interval i is equal to - * reltime t + * intervalleneq - returns 1, iff length of interval i is equal to + * reltime t */ -bool intervalleneq(TimeInterval i, RelativeTime t) +bool +intervalleneq(TimeInterval i, RelativeTime t) { - RelativeTime rt; - - if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) - return(0); - rt = intervalrel(i); - return (rt != INVALID_RELTIME && rt == t); + RelativeTime rt; + + if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) + return (0); + rt = intervalrel(i); + return (rt != INVALID_RELTIME && rt == t); } /* - * intervallenne - returns 1, iff length of interval i is not equal - * to reltime t + * intervallenne - returns 1, iff length of interval i is not equal + * to reltime t */ -bool intervallenne(TimeInterval i, RelativeTime t) +bool +intervallenne(TimeInterval i, RelativeTime t) { - RelativeTime rt; - - if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) - return(0); - rt = intervalrel(i); - return (rt != INVALID_RELTIME && rt != t); + RelativeTime rt; + + if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) + return (0); + rt = intervalrel(i); + return (rt != INVALID_RELTIME && rt != t); } /* - * intervallenlt - returns 1, iff length of interval i is less than - * reltime t + * intervallenlt - returns 1, iff length of interval i is less than + * reltime t */ -bool intervallenlt(TimeInterval i, RelativeTime t) +bool +intervallenlt(TimeInterval i, RelativeTime t) { - RelativeTime rt; - - if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) - return(0); - rt = intervalrel(i); - return (rt != INVALID_RELTIME && rt < t); + RelativeTime rt; + + if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) + return (0); + rt = intervalrel(i); + return (rt != INVALID_RELTIME && rt < t); } /* - * intervallengt - returns 1, iff length of interval i is greater than - * reltime t + * intervallengt - returns 1, iff length of interval i is greater than + * reltime t */ -bool intervallengt(TimeInterval i, RelativeTime t) +bool +intervallengt(TimeInterval i, RelativeTime t) { - RelativeTime rt; - - if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) - return(0); - rt = intervalrel(i); - return (rt != INVALID_RELTIME && rt > t); + RelativeTime rt; + + if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) + return (0); + rt = intervalrel(i); + return (rt != INVALID_RELTIME && rt > t); } /* - * intervallenle - returns 1, iff length of interval i is less or equal - * than reltime t + * intervallenle - returns 1, iff length of interval i is less or equal + * than reltime t */ -bool intervallenle(TimeInterval i, RelativeTime t) -{ - RelativeTime rt; - - if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) - return(0); - rt = intervalrel(i); - return (rt != INVALID_RELTIME && rt <= t); +bool +intervallenle(TimeInterval i, RelativeTime t) +{ + RelativeTime rt; + + if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) + return (0); + rt = intervalrel(i); + return (rt != INVALID_RELTIME && rt <= t); } /* - * intervallenge - returns 1, iff length of interval i is greater or - * equal than reltime t + * intervallenge - returns 1, iff length of interval i is greater or + * equal than reltime t */ -bool intervallenge(TimeInterval i, RelativeTime t) +bool +intervallenge(TimeInterval i, RelativeTime t) { - RelativeTime rt; - - if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) - return(0); - rt = intervalrel(i); - return (rt != INVALID_RELTIME && rt >= t); + RelativeTime rt; + + if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME)) + return (0); + rt = intervalrel(i); + return (rt != INVALID_RELTIME && rt >= t); } /* - * intervalct - returns 1, iff interval i1 contains interval i2 + * intervalct - returns 1, iff interval i1 contains interval i2 */ -bool intervalct(TimeInterval i1, TimeInterval i2) +bool +intervalct(TimeInterval i1, TimeInterval i2) { - if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) - return(0); - return(abstimele(i1->data[0], i2->data[0]) && - abstimege(i1->data[1], i2->data[1])); + if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) + return (0); + return (abstimele(i1->data[0], i2->data[0]) && + abstimege(i1->data[1], i2->data[1])); } /* - * intervalov - returns 1, iff interval i1 (partially) overlaps i2 + * intervalov - returns 1, iff interval i1 (partially) overlaps i2 */ -bool intervalov(TimeInterval i1, TimeInterval i2) +bool +intervalov(TimeInterval i1, TimeInterval i2) { - if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) - return(0); - return(! (abstimelt(i1->data[1], i2->data[0]) || - abstimegt(i1->data[0], i2->data[1]))); + if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) + return (0); + return (!(abstimelt(i1->data[1], i2->data[0]) || + abstimegt(i1->data[0], i2->data[1]))); } /* - * intervalstart - returns the start of interval i + * intervalstart - returns the start of interval i */ -AbsoluteTime intervalstart(TimeInterval i) +AbsoluteTime +intervalstart(TimeInterval i) { - if (i->status == T_INTERVAL_INVAL) - return INVALID_ABSTIME; - return(i->data[0]); + if (i->status == T_INTERVAL_INVAL) + return INVALID_ABSTIME; + return (i->data[0]); } /* - * intervalend - returns the end of interval i + * intervalend - returns the end of interval i */ -AbsoluteTime intervalend(TimeInterval i) +AbsoluteTime +intervalend(TimeInterval i) { - if (i->status == T_INTERVAL_INVAL) - return INVALID_ABSTIME; - return(i->data[1]); + if (i->status == T_INTERVAL_INVAL) + return INVALID_ABSTIME; + return (i->data[1]); } -/***************************************************************************** - * PRIVATE ROUTINES * +/***************************************************************************** + * PRIVATE ROUTINES * *****************************************************************************/ /* - * isreltime - returns 1, iff datestring is of type reltime - * 2, iff datestring is 'invalid time' identifier - * 0, iff datestring contains a syntax error - * VALID time less or equal +/- `@ 68 years' + * isreltime - returns 1, iff datestring is of type reltime + * 2, iff datestring is 'invalid time' identifier + * 0, iff datestring contains a syntax error + * VALID time less or equal +/- `@ 68 years' * */ -int isreltime(char *str) +int +isreltime(char *str) { - struct tm tt, *tm = &tt; - double fsec; - int dtype; - char *field[MAXDATEFIELDS]; - int nf, ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN+1]; - - if (!PointerIsValid(str)) - return 0; - - if (strlen(str) > MAXDATELEN) - return 0; - - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0)) - return 0; + struct tm tt, + *tm = &tt; + double fsec; + int dtype; + char *field[MAXDATEFIELDS]; + int nf, + ftype[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; + + if (!PointerIsValid(str)) + return 0; + + if (strlen(str) > MAXDATELEN) + return 0; + + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0)) + return 0; + + switch (dtype) + { + case (DTK_DELTA): + return ((abs(tm->tm_year) <= 68) ? 1 : 0); + break; - switch (dtype) { - case (DTK_DELTA): - return((abs(tm->tm_year) <= 68)? 1: 0); - break; + case (DTK_INVALID): + return 2; + break; - case (DTK_INVALID): - return 2; - break; + default: + return 0; + break; + } - default: return 0; - break; - } - - return 0; -} /* isreltime() */ +} /* isreltime() */ #if FALSE - register char *p; - register char c; - int i; - char unit[UNITMAXLEN] ; - char direction[DIRMAXLEN]; - int localSign; - int localUnitNumber; - long localQuantity; - - if (!PointerIsValid(sign)) { +register char *p; +register char c; +int i; +char unit[UNITMAXLEN]; +char direction[DIRMAXLEN]; +int localSign; +int localUnitNumber; +long localQuantity; + +if (!PointerIsValid(sign)) +{ sign = &localSign; - } - if (!PointerIsValid(unitnr)) { +} + +if (!PointerIsValid(unitnr)) +{ unitnr = &localUnitNumber; - } - if (!PointerIsValid(quantity)) { +} + +if (!PointerIsValid(quantity)) +{ quantity = &localQuantity; - } - unit[0] = '\0'; - direction[0] = '\0'; - p = timestring; - /* skip leading blanks */ - while ((c = *p) != '\0') { +} + +unit[0] = '\0'; +direction[0] = '\0'; +p = timestring; + /* skip leading blanks */ +while ((c = *p) != '\0') +{ if (c != ' ') - break; + break; p++; - } - /* Test whether 'invalid time' identifier or not */ - if (!strncmp(INVALID_RELTIME_STR,p,strlen(INVALID_RELTIME_STR) + 1)) - return(2); /* correct 'invalid time' identifier found */ - - /* handle label of relative time */ - if (c != RELTIME_LABEL) - return(0); /*syntax error*/ - c = *++p; - if (c != ' ') return(0); /*syntax error*/ - p++; - /* handle the quantity */ - *quantity = 0; - for (;;) { +} + + /* Test whether 'invalid time' identifier or not */ +if (!strncmp(INVALID_RELTIME_STR, p, strlen(INVALID_RELTIME_STR) + 1)) + return (2); /* correct 'invalid time' identifier found */ + + /* handle label of relative time */ +if (c != RELTIME_LABEL) + return (0); /* syntax error */ +c = *++p; +if (c != ' ') + return (0); /* syntax error */ +p++; + /* handle the quantity */ +*quantity = 0; +for (;;) +{ c = *p; - if (isdigit(c)) { - *quantity = *quantity * 10 + (c -'0'); - p++; - } else { - if (c == ' ' ) - break; /* correct quantity found */ - else - return(0); /* syntax error */ + if (isdigit(c)) + { + *quantity = *quantity * 10 + (c - '0'); + p++; + } + else + { + if (c == ' ') + break; /* correct quantity found */ + else + return (0); /* syntax error */ } - } - /* handle unit */ - p++; - i = 0; - for (;;) { +} + + /* handle unit */ +p++; +i = 0; +for (;;) +{ c = *p; - if (c >= 'a' && c <= 'z' && i <= (UNITMAXLEN - 1)) { - unit[i] = c; - p++; - i++; - } else { - if ((c == ' ' || c == '\0') - && correct_unit(unit, unitnr)) - break; /* correct unit found */ - else - return(0); /* syntax error */ + if (c >= 'a' && c <= 'z' && i <= (UNITMAXLEN - 1)) + { + unit[i] = c; + p++; + i++; + } + else + { + if ((c == ' ' || c == '\0') + && correct_unit(unit, unitnr)) + break; /* correct unit found */ + else + return (0); /* syntax error */ } - } - /* handle optional direction */ - if (c == ' ') +} + + /* handle optional direction */ +if (c == ' ') p++; - i = 0; - *sign = 1; - for (;;) { +i = 0; +*sign = 1; +for (;;) +{ c = *p; - if (c >= 'a' && c <= 'z' && i <= (DIRMAXLEN - 1)) { - direction[i] = c; - p++; - i++; - } else { - if ((c == ' ' || c == '\0') && i == 0) { - *sign = 1; - break; /* no direction specified */ - } - if ((c == ' ' || c == '\0') && i != 0) + if (c >= 'a' && c <= 'z' && i <= (DIRMAXLEN - 1)) + { + direction[i] = c; + p++; + i++; + } + else + { + if ((c == ' ' || c == '\0') && i == 0) { - direction[i] = '\0'; - correct_dir(direction, sign); - break; /* correct direction found */ + *sign = 1; + break; /* no direction specified */ } - else - return(0); /* syntax error*/ + if ((c == ' ' || c == '\0') && i != 0) + { + direction[i] = '\0'; + correct_dir(direction, sign); + break; /* correct direction found */ + } + else + return (0); /* syntax error */ } - } - return(1); +} + +return (1); } /* - * correct_unit - returns 1, iff unit is a correct unit description + * correct_unit - returns 1, iff unit is a correct unit description * - * output parameter: - * unptr: points to an integer which is the appropriate unit number - * (see function isreltime()) - */ -static int correct_unit(char unit[], int *unptr) -{ - int j = 0; - - while (j < NUNITS) { - if (strncmp(unit, unit_tab[j], strlen(unit_tab[j])) == 0) { - *unptr = j; - return(1); + * output parameter: + * unptr: points to an integer which is the appropriate unit number + * (see function isreltime()) + */ +static int +correct_unit(char unit[], int *unptr) +{ + int j = 0; + + while (j < NUNITS) + { + if (strncmp(unit, unit_tab[j], strlen(unit_tab[j])) == 0) + { + *unptr = j; + return (1); + } + j++; } - j++; - } - return (0); /* invalid unit descriptor */ + return (0); /* invalid unit descriptor */ } /* - * correct_dir - returns 1, iff direction is a correct identifier + * correct_dir - returns 1, iff direction is a correct identifier * - * output parameter: - * signptr: points to -1 if dir corresponds to past tense - * else to 1 - */ -static int correct_dir(char direction[], int *signptr) -{ - *signptr = 1; - if (strncmp(RELTIME_PAST, direction, strlen(RELTIME_PAST)+1) == 0) + * output parameter: + * signptr: points to -1 if dir corresponds to past tense + * else to 1 + */ +static int +correct_dir(char direction[], int *signptr) +{ + *signptr = 1; + if (strncmp(RELTIME_PAST, direction, strlen(RELTIME_PAST) + 1) == 0) { - *signptr = -1; - return(1); - } else - return (0); /* invalid direction descriptor */ + *signptr = -1; + return (1); + } + else + return (0); /* invalid direction descriptor */ } + #endif /* - * istinterval - returns 1, iff i_string is a valid interval descr. - * 0, iff i_string is NOT a valid interval desc. - * 2, iff any time is INVALID_ABSTIME + * istinterval - returns 1, iff i_string is a valid interval descr. + * 0, iff i_string is NOT a valid interval desc. + * 2, iff any time is INVALID_ABSTIME * - * output parameter: - * i_start, i_end: interval margins + * output parameter: + * i_start, i_end: interval margins * - * Time interval: - * `[' {` '} `'' <AbsTime> `'' {` '} `'' <AbsTime> `'' {` '} `]' + * Time interval: + * `[' {` '} `'' <AbsTime> `'' {` '} `'' <AbsTime> `'' {` '} `]' * - * OR `Undefined Range' (see also INVALID_INTERVAL_STR) + * OR `Undefined Range' (see also INVALID_INTERVAL_STR) * - * where <AbsTime> satisfies the syntax of absolute time. + * where <AbsTime> satisfies the syntax of absolute time. * - * e.g. [ ' Jan 18 1902' 'Jan 1 00:00:00 1970'] - */ -static int istinterval(char *i_string, - AbsoluteTime *i_start, - AbsoluteTime *i_end) -{ - register char *p,*p1; - register char c; - - p = i_string; - /* skip leading blanks up to '[' */ - while ((c = *p) != '\0') { - if ( IsSpace(c)) - p++; - else if (c != '[') - return(0); /* syntax error */ - else - break; - } - p++; - /* skip leading blanks up to "'" */ - while ((c = *p) != '\0') { - if (IsSpace(c)) - p++; - else if (c != '"') - return (0); /* syntax error */ - else - break; - } - p++; - if (strncmp(INVALID_INTERVAL_STR,p,strlen(INVALID_INTERVAL_STR)) == 0) - return(0); /* undefined range, handled like a syntax err.*/ - /* search for the end of the first date and change it to a NULL*/ - p1 = p; - while ((c = *p1) != '\0') { - if ( c == '"') { - *p1 = '\0'; - break; + * e.g. [ ' Jan 18 1902' 'Jan 1 00:00:00 1970'] + */ +static int +istinterval(char *i_string, + AbsoluteTime * i_start, + AbsoluteTime * i_end) +{ + register char *p, + *p1; + register char c; + + p = i_string; + /* skip leading blanks up to '[' */ + while ((c = *p) != '\0') + { + if (IsSpace(c)) + p++; + else if (c != '[') + return (0); /* syntax error */ + else + break; } - p1++; - } - /* get the first date */ - *i_start = nabstimein(p); /* first absolute date */ - /* rechange NULL at the end of the first date to a "'" */ - *p1 = '"'; - p = ++p1; - /* skip blanks up to "'", beginning of second date*/ - while ((c = *p) != '\0') { - if (IsSpace(c)) - p++; - else if (c != '"') - return (0); /* syntax error */ - else - break; - } - p++; - /* search for the end of the second date and change it to a NULL*/ - p1 = p; - while ((c = *p1) != '\0') { - if ( c == '"') { - *p1 = '\0'; - break; + p++; + /* skip leading blanks up to "'" */ + while ((c = *p) != '\0') + { + if (IsSpace(c)) + p++; + else if (c != '"') + return (0); /* syntax error */ + else + break; } - p1++; - } - /* get the second date */ - *i_end = nabstimein(p); /* second absolute date */ - /* rechange NULL at the end of the first date to a ''' */ - *p1 = '"'; - p = ++p1; - /* skip blanks up to ']'*/ - while ((c = *p) != '\0') { - if ( IsSpace(c)) - p++; - else if (c != ']') - return(0); /*syntax error */ - else - break; - } - p++; - c = *p; - if ( c != '\0' ) - return (0); /* syntax error */ - /* it seems to be a valid interval */ - return(1); + p++; + if (strncmp(INVALID_INTERVAL_STR, p, strlen(INVALID_INTERVAL_STR)) == 0) + return (0); /* undefined range, handled like a syntax + * err. */ + /* search for the end of the first date and change it to a NULL */ + p1 = p; + while ((c = *p1) != '\0') + { + if (c == '"') + { + *p1 = '\0'; + break; + } + p1++; + } + /* get the first date */ + *i_start = nabstimein(p); /* first absolute date */ + /* rechange NULL at the end of the first date to a "'" */ + *p1 = '"'; + p = ++p1; + /* skip blanks up to "'", beginning of second date */ + while ((c = *p) != '\0') + { + if (IsSpace(c)) + p++; + else if (c != '"') + return (0); /* syntax error */ + else + break; + } + p++; + /* search for the end of the second date and change it to a NULL */ + p1 = p; + while ((c = *p1) != '\0') + { + if (c == '"') + { + *p1 = '\0'; + break; + } + p1++; + } + /* get the second date */ + *i_end = nabstimein(p); /* second absolute date */ + /* rechange NULL at the end of the first date to a ''' */ + *p1 = '"'; + p = ++p1; + /* skip blanks up to ']' */ + while ((c = *p) != '\0') + { + if (IsSpace(c)) + p++; + else if (c != ']') + return (0); /* syntax error */ + else + break; + } + p++; + c = *p; + if (c != '\0') + return (0); /* syntax error */ + /* it seems to be a valid interval */ + return (1); } @@ -946,30 +1053,30 @@ static int istinterval(char *i_string, /* * timeofday - - * returns the current time as a text. similar to timenow() but returns - * seconds with more precision (up to microsecs). (I need this to compare - * the Wisconsin benchmark with Illustra whose TimeNow() shows current - * time with precision up to microsecs.) - ay 3/95 + * returns the current time as a text. similar to timenow() but returns + * seconds with more precision (up to microsecs). (I need this to compare + * the Wisconsin benchmark with Illustra whose TimeNow() shows current + * time with precision up to microsecs.) - ay 3/95 */ -text * +text * timeofday(void) { - struct timeval tp; - struct timezone tpz; - char templ[500]; - char buf[500]; - text *tm; - int len = 0; - - gettimeofday(&tp, &tpz); - strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%d %Y %Z", - localtime((time_t *) &tp.tv_sec)); - sprintf(buf, templ, tp.tv_usec); - - len = VARHDRSZ + strlen(buf); - tm = (text *)palloc(len); - VARSIZE(tm) = len; - strncpy(VARDATA(tm), buf, strlen(buf)); - return tm; + struct timeval tp; + struct timezone tpz; + char templ[500]; + char buf[500]; + text *tm; + int len = 0; + + gettimeofday(&tp, &tpz); + strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%d %Y %Z", + localtime((time_t *) & tp.tv_sec)); + sprintf(buf, templ, tp.tv_usec); + + len = VARHDRSZ + strlen(buf); + tm = (text *) palloc(len); + VARSIZE(tm) = len; + strncpy(VARDATA(tm), buf, strlen(buf)); + return tm; } diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 9809ebf5f11..a88bea36e9c 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * datetime.c-- - * implements DATE and TIME data types specified in SQL-92 standard + * implements DATE and TIME data types specified in SQL-92 standard * * Copyright (c) 1994-5, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.13 1997/09/05 18:11:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.14 1997/09/07 04:50:08 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include <limits.h> @@ -25,12 +25,12 @@ #include "utils/datetime.h" #include "access/xact.h" -static int date2tm(DateADT dateVal, int *tzp, struct tm *tm, double *fsec, char **tzn); +static int date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn); -static int day_tab[2][12] = { - {31,28,31,30,31,30,31,31,30,31,30,31}, - {31,29,31,30,31,30,31,31,30,31,30,31} }; +static int day_tab[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, +{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; #define isleap(y) (((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0) @@ -49,7 +49,7 @@ static int day_tab[2][12] = { || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY)))))) /***************************************************************************** - * Date ADT + * Date ADT *****************************************************************************/ @@ -59,234 +59,250 @@ static int day_tab[2][12] = { DateADT date_in(char *str) { - DateADT date; - double fsec; - struct tm tt, *tm = &tt; - int tzp; - int dtype; - int nf; - char *field[MAXDATEFIELDS]; - int ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN+1]; - - if (!PointerIsValid(str)) - elog(WARN,"Bad (null) date external representation",NULL); + DateADT date; + double fsec; + struct tm tt, + *tm = &tt; + int tzp; + int dtype; + int nf; + char *field[MAXDATEFIELDS]; + int ftype[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; + + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) date external representation", NULL); #ifdef DATEDEBUG -printf( "date_in- input string is %s\n", str); + printf("date_in- input string is %s\n", str); #endif - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0)) - elog(WARN,"Bad date external representation %s",str); - - switch (dtype) { - case DTK_DATE: - break; - - case DTK_CURRENT: - GetCurrentTime(tm); - break; - - case DTK_EPOCH: - tm->tm_year = 1970; - tm->tm_mon = 1; - tm->tm_mday = 1; - break; - - default: - elog(WARN,"Unrecognized date external representation %s",str); - } + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0)) + elog(WARN, "Bad date external representation %s", str); + + switch (dtype) + { + case DTK_DATE: + break; + + case DTK_CURRENT: + GetCurrentTime(tm); + break; + + case DTK_EPOCH: + tm->tm_year = 1970; + tm->tm_mon = 1; + tm->tm_mday = 1; + break; + + default: + elog(WARN, "Unrecognized date external representation %s", str); + } - if (tm->tm_year < 0 || tm->tm_year > 32767) - elog(WARN, "date_in: year must be limited to values 0 through 32767 in '%s'", str); - if (tm->tm_mon < 1 || tm->tm_mon > 12) - elog(WARN, "date_in: month must be limited to values 1 through 12 in '%s'", str); - if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon-1]) - elog(WARN, "date_in: day must be limited to values 1 through %d in '%s'", - day_tab[isleap(tm->tm_year)][tm->tm_mon-1], str); + if (tm->tm_year < 0 || tm->tm_year > 32767) + elog(WARN, "date_in: year must be limited to values 0 through 32767 in '%s'", str); + if (tm->tm_mon < 1 || tm->tm_mon > 12) + elog(WARN, "date_in: month must be limited to values 1 through 12 in '%s'", str); + if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) + elog(WARN, "date_in: day must be limited to values 1 through %d in '%s'", + day_tab[isleap(tm->tm_year)][tm->tm_mon - 1], str); - date = (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000,1,1)); + date = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1)); - return(date); -} /* date_in() */ + return (date); +} /* date_in() */ /* date_out() * Given internal format date, convert to text string. */ -char * +char * date_out(DateADT date) { - char *result; - struct tm tt, *tm = &tt; - char buf[MAXDATELEN+1]; + char *result; + struct tm tt, + *tm = &tt; + char buf[MAXDATELEN + 1]; #if FALSE - int year, month, day; + int year, + month, + day; + #endif - j2date( (date + date2j(2000,1,1)), - &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + j2date((date + date2j(2000, 1, 1)), + &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); - EncodeDateOnly( tm, DateStyle, buf); + EncodeDateOnly(tm, DateStyle, buf); #if FALSE - if (EuroDates == 1) /* Output European-format dates */ - sprintf(buf, "%02d-%02d-%04d", day, month, year); - else - sprintf(buf, "%02d-%02d-%04d", month, day, year); + if (EuroDates == 1) /* Output European-format dates */ + sprintf(buf, "%02d-%02d-%04d", day, month, year); + else + sprintf(buf, "%02d-%02d-%04d", month, day, year); #endif - result = PALLOC(strlen(buf)+1); + result = PALLOC(strlen(buf) + 1); - strcpy( result, buf); + strcpy(result, buf); - return(result); -} /* date_out() */ + return (result); +} /* date_out() */ bool date_eq(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1 == dateVal2); + return (dateVal1 == dateVal2); } bool date_ne(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1 != dateVal2); + return (dateVal1 != dateVal2); } bool date_lt(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1 < dateVal2); -} /* date_lt() */ + return (dateVal1 < dateVal2); +} /* date_lt() */ bool date_le(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1 <= dateVal2); -} /* date_le() */ + return (dateVal1 <= dateVal2); +} /* date_le() */ bool date_gt(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1 > dateVal2); -} /* date_gt() */ + return (dateVal1 > dateVal2); +} /* date_gt() */ bool date_ge(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1 >= dateVal2); -} /* date_ge() */ + return (dateVal1 >= dateVal2); +} /* date_ge() */ int date_cmp(DateADT dateVal1, DateADT dateVal2) { - if (dateVal1 < dateVal2) { - return -1; - } else if (dateVal1 > dateVal2) { - return 1; - } - return 0; -} /* date_cmp() */ + if (dateVal1 < dateVal2) + { + return -1; + } + else if (dateVal1 > dateVal2) + { + return 1; + } + return 0; +} /* date_cmp() */ DateADT date_larger(DateADT dateVal1, DateADT dateVal2) { - return(date_gt(dateVal1, dateVal2) ? dateVal1 : dateVal2); -} /* date_larger() */ + return (date_gt(dateVal1, dateVal2) ? dateVal1 : dateVal2); +} /* date_larger() */ DateADT date_smaller(DateADT dateVal1, DateADT dateVal2) { - return(date_lt(dateVal1, dateVal2) ? dateVal1 : dateVal2); -} /* date_smaller() */ + return (date_lt(dateVal1, dateVal2) ? dateVal1 : dateVal2); +} /* date_smaller() */ /* Compute difference between two dates in days. */ int4 date_mi(DateADT dateVal1, DateADT dateVal2) { - return(dateVal1-dateVal2); -} /* date_mi() */ + return (dateVal1 - dateVal2); +} /* date_mi() */ /* Add a number of days to a date, giving a new date. - Must handle both positive and negative numbers of days. */ + Must handle both positive and negative numbers of days. */ DateADT date_pli(DateADT dateVal, int4 days) { - return(dateVal+days); -} /* date_pli() */ + return (dateVal + days); +} /* date_pli() */ /* Subtract a number of days from a date, giving a new date. */ DateADT date_mii(DateADT dateVal, int4 days) { - return(date_pli(dateVal, -days)); -} /* date_mii() */ + return (date_pli(dateVal, -days)); +} /* date_mii() */ /* date_datetime() * Convert date to datetime data type. */ -DateTime * +DateTime * date_datetime(DateADT dateVal) { - DateTime *result; - struct tm tt, *tm = &tt; - int tz; - double fsec = 0; - char *tzn; + DateTime *result; + struct tm tt, + *tm = &tt; + int tz; + double fsec = 0; + char *tzn; - result = PALLOCTYPE(DateTime); + result = PALLOCTYPE(DateTime); - if (date2tm( dateVal, &tz, tm, &fsec, &tzn) != 0) - elog(WARN,"Unable to convert date to datetime",NULL); + if (date2tm(dateVal, &tz, tm, &fsec, &tzn) != 0) + elog(WARN, "Unable to convert date to datetime", NULL); #ifdef DATEDEBUG -printf( "date_datetime- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); -printf( "date_datetime- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); + printf("date_datetime- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); + printf("date_datetime- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); #endif - if (tm2datetime( tm, fsec, &tz, result) != 0) - elog(WARN,"Datetime out of range",NULL); + if (tm2datetime(tm, fsec, &tz, result) != 0) + elog(WARN, "Datetime out of range", NULL); - return(result); -} /* date_datetime() */ + return (result); +} /* date_datetime() */ /* datetime_date() * Convert datetime to date data type. */ DateADT -datetime_date(DateTime *datetime) +datetime_date(DateTime * datetime) { - DateADT result; - struct tm tt, *tm = &tt; - int tz; - double fsec; - char *tzn; + DateADT result; + struct tm tt, + *tm = &tt; + int tz; + double fsec; + char *tzn; - if (!PointerIsValid(datetime)) - elog(WARN,"Unable to convert null datetime to date",NULL); + if (!PointerIsValid(datetime)) + elog(WARN, "Unable to convert null datetime to date", NULL); - if (DATETIME_NOT_FINITE(*datetime)) - elog(WARN,"Unable to convert datetime to date",NULL); + if (DATETIME_NOT_FINITE(*datetime)) + elog(WARN, "Unable to convert datetime to date", NULL); - if (DATETIME_IS_EPOCH(*datetime)) { - datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec, NULL); + if (DATETIME_IS_EPOCH(*datetime)) + { + datetime2tm(SetDateTime(*datetime), NULL, tm, &fsec, NULL); - } else if (DATETIME_IS_CURRENT(*datetime)) { - datetime2tm( SetDateTime(*datetime), &tz, tm, &fsec, &tzn); + } + else if (DATETIME_IS_CURRENT(*datetime)) + { + datetime2tm(SetDateTime(*datetime), &tz, tm, &fsec, &tzn); - } else { - if (datetime2tm( *datetime, &tz, tm, &fsec, &tzn) != 0) - elog(WARN,"Unable to convert datetime to date",NULL); - } + } + else + { + if (datetime2tm(*datetime, &tz, tm, &fsec, &tzn) != 0) + elog(WARN, "Unable to convert datetime to date", NULL); + } - result = (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j( 2000, 1, 1)); + result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1)); - return(result); -} /* datetime_date() */ + return (result); +} /* datetime_date() */ /* abstime_date() @@ -295,289 +311,320 @@ datetime_date(DateTime *datetime) DateADT abstime_date(AbsoluteTime abstime) { - DateADT result; - struct tm tt, *tm = &tt; - int tz; - - switch (abstime) { - case INVALID_ABSTIME: - case NOSTART_ABSTIME: - case NOEND_ABSTIME: - elog(WARN,"Unable to convert reserved abstime value to date",NULL); - /* pretend to drop through to make compiler think that result will be set */ - - case EPOCH_ABSTIME: - result = date2j(1970,1,1) - date2j(2000,1,1); - break; - - case CURRENT_ABSTIME: - GetCurrentTime(tm); - result = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000,1,1); - break; - - default: - abstime2tm(abstime, &tz, tm, NULL); - result = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1); - break; - } + DateADT result; + struct tm tt, + *tm = &tt; + int tz; + + switch (abstime) + { + case INVALID_ABSTIME: + case NOSTART_ABSTIME: + case NOEND_ABSTIME: + elog(WARN, "Unable to convert reserved abstime value to date", NULL); + + /* + * pretend to drop through to make compiler think that result will + * be set + */ + + case EPOCH_ABSTIME: + result = date2j(1970, 1, 1) - date2j(2000, 1, 1); + break; + + case CURRENT_ABSTIME: + GetCurrentTime(tm); + result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + break; + + default: + abstime2tm(abstime, &tz, tm, NULL); + result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + break; + } - return(result); -} /* abstime_date() */ + return (result); +} /* abstime_date() */ /* date2tm() * Convert date to time structure. * Note that date is an implicit local time, but the system calls assume - * that everything is GMT. So, convert to GMT, rotate to local time, - * and then convert again to try to get the time zones correct. + * that everything is GMT. So, convert to GMT, rotate to local time, + * and then convert again to try to get the time zones correct. */ static int -date2tm(DateADT dateVal, int *tzp, struct tm *tm, double *fsec, char **tzn) +date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn) { - struct tm *tx; - time_t utime; - *fsec = 0; + struct tm *tx; + time_t utime; - j2date( (dateVal + date2j( 2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - tm->tm_isdst = -1; + *fsec = 0; - if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) { + j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + tm->tm_isdst = -1; + + if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) + { - /* convert to system time */ - utime = ((dateVal + (date2j(2000,1,1)-date2j(1970,1,1)))*86400); - utime += (12*60*60); /* rotate to noon to get the right day in time zone */ + /* convert to system time */ + utime = ((dateVal + (date2j(2000, 1, 1) - date2j(1970, 1, 1))) * 86400); + utime += (12 * 60 * 60);/* rotate to noon to get the right day in + * time zone */ #ifdef USE_POSIX_TIME - tx = localtime(&utime); + tx = localtime(&utime); #ifdef DATEDEBUG #ifdef HAVE_INT_TIMEZONE -printf( "date2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n", - tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, (double) tm->tm_sec, - tzname[0], tzname[1], tx->tm_isdst); + printf("date2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n", + tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, (double) tm->tm_sec, + tzname[0], tzname[1], tx->tm_isdst); #endif #endif - tm->tm_year = tx->tm_year + 1900; - tm->tm_mon = tx->tm_mon + 1; - tm->tm_mday = tx->tm_mday; + tm->tm_year = tx->tm_year + 1900; + tm->tm_mon = tx->tm_mon + 1; + tm->tm_mday = tx->tm_mday; #if FALSE - tm->tm_hour = tx->tm_hour; - tm->tm_min = tx->tm_min; - tm->tm_sec = tx->tm_sec; + tm->tm_hour = tx->tm_hour; + tm->tm_min = tx->tm_min; + tm->tm_sec = tx->tm_sec; #endif - tm->tm_isdst = tx->tm_isdst; + tm->tm_isdst = tx->tm_isdst; #ifdef HAVE_INT_TIMEZONE - *tzp = (tm->tm_isdst? (timezone - 3600): timezone); - if (tzn != NULL) *tzn = tzname[(tm->tm_isdst > 0)]; - -#else /* !HAVE_INT_TIMEZONE */ - tm->tm_gmtoff = tx->tm_gmtoff; - tm->tm_zone = tx->tm_zone; - - *tzp = (tm->tm_isdst? (tm->tm_gmtoff - 3600): tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ - if (tzn != NULL) *tzn = tm->tm_zone; + *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone); + if (tzn != NULL) + *tzn = tzname[(tm->tm_isdst > 0)]; + +#else /* !HAVE_INT_TIMEZONE */ + tm->tm_gmtoff = tx->tm_gmtoff; + tm->tm_zone = tx->tm_zone; + + *tzp = (tm->tm_isdst ? (tm->tm_gmtoff - 3600) : tm->tm_gmtoff); /* tm_gmtoff is + * Sun/DEC-ism */ + if (tzn != NULL) + *tzn = tm->tm_zone; #endif -#else /* !USE_POSIX_TIME */ - *tzp = CTimeZone; /* V7 conventions; don't know timezone? */ - if (tzn != NULL) *tzn = CTZName; +#else /* !USE_POSIX_TIME */ + *tzp = CTimeZone; /* V7 conventions; don't know timezone? */ + if (tzn != NULL) + *tzn = CTZName; #endif - /* otherwise, outside of timezone range so convert to GMT... */ - } else { + /* otherwise, outside of timezone range so convert to GMT... */ + } + else + { #if FALSE - j2date( (dateVal + date2j( 2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; + j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; #endif #ifdef DATEDEBUG -printf( "date2tm- convert %d-%d-%d %d:%d%d to datetime\n", - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + printf("date2tm- convert %d-%d-%d %d:%d%d to datetime\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - *tzp = 0; - tm->tm_isdst = 0; - if (tzn != NULL) *tzn = NULL; - } + *tzp = 0; + tm->tm_isdst = 0; + if (tzn != NULL) + *tzn = NULL; + } - return 0; -} /* date2tm() */ + return 0; +} /* date2tm() */ /***************************************************************************** - * Time ADT + * Time ADT *****************************************************************************/ -TimeADT * +TimeADT * time_in(char *str) { - TimeADT *time; + TimeADT *time; - double fsec; - struct tm tt, *tm = &tt; + double fsec; + struct tm tt, + *tm = &tt; - int nf; - char lowstr[MAXDATELEN+1]; - char *field[MAXDATEFIELDS]; - int dtype; - int ftype[MAXDATEFIELDS]; + int nf; + char lowstr[MAXDATELEN + 1]; + char *field[MAXDATEFIELDS]; + int dtype; + int ftype[MAXDATEFIELDS]; - if (!PointerIsValid(str)) - elog(WARN,"Bad (null) time external representation",NULL); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) time external representation", NULL); - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeTimeOnly( field, ftype, nf, &dtype, tm, &fsec) != 0)) - elog(WARN,"Bad time external representation '%s'",str); + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec) != 0)) + elog(WARN, "Bad time external representation '%s'", str); - if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) - elog(WARN,"Hour must be limited to values 0 through 23 in '%s'",str); - if ((tm->tm_min < 0) || (tm->tm_min > 59)) - elog(WARN,"Minute must be limited to values 0 through 59 in '%s'",str); - if ((tm->tm_sec < 0) || ((tm->tm_sec + fsec) >= 60)) - elog(WARN,"Second must be limited to values 0 through < 60 in '%s'",str); + if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) + elog(WARN, "Hour must be limited to values 0 through 23 in '%s'", str); + if ((tm->tm_min < 0) || (tm->tm_min > 59)) + elog(WARN, "Minute must be limited to values 0 through 59 in '%s'", str); + if ((tm->tm_sec < 0) || ((tm->tm_sec + fsec) >= 60)) + elog(WARN, "Second must be limited to values 0 through < 60 in '%s'", str); - time = PALLOCTYPE(TimeADT); + time = PALLOCTYPE(TimeADT); - *time = ((((tm->tm_hour*60)+tm->tm_min)*60)+tm->tm_sec+fsec); + *time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); - return(time); -} /* time_in() */ + return (time); +} /* time_in() */ -char * -time_out(TimeADT *time) +char * +time_out(TimeADT * time) { - char *result; - struct tm tt, *tm = &tt; + char *result; + struct tm tt, + *tm = &tt; + #if FALSE - int hour, min, sec; + int hour, + min, + sec; + #endif - double fsec; - char buf[MAXDATELEN+1]; + double fsec; + char buf[MAXDATELEN + 1]; - if (!PointerIsValid(time)) - return NULL; + if (!PointerIsValid(time)) + return NULL; - tm->tm_hour = (*time / (60*60)); - tm->tm_min = (((int) (*time / 60)) % 60); - tm->tm_sec = (((int) *time) % 60); + tm->tm_hour = (*time / (60 * 60)); + tm->tm_min = (((int) (*time / 60)) % 60); + tm->tm_sec = (((int) *time) % 60); - fsec = 0; + fsec = 0; - EncodeTimeOnly( tm, fsec, DateStyle, buf); + EncodeTimeOnly(tm, fsec, DateStyle, buf); #if FALSE - if (sec == 0.0) { - sprintf(buf, "%02d:%02d", hour, min); - - } else { - if (fsec == 0) { - sprintf(buf, "%02d:%02d:%02d", hour, min, sec); - } else { - sprintf(buf, "%02d:%02d:%05.2f", hour, min, (sec+fsec)); + if (sec == 0.0) + { + sprintf(buf, "%02d:%02d", hour, min); + + } + else + { + if (fsec == 0) + { + sprintf(buf, "%02d:%02d:%02d", hour, min, sec); + } + else + { + sprintf(buf, "%02d:%02d:%05.2f", hour, min, (sec + fsec)); + } } - } #endif - result = PALLOC(strlen(buf)+1); + result = PALLOC(strlen(buf) + 1); - strcpy( result, buf); + strcpy(result, buf); - return(result); -} /* time_out() */ + return (result); +} /* time_out() */ bool -time_eq(TimeADT *time1, TimeADT *time2) +time_eq(TimeADT * time1, TimeADT * time2) { - if (!PointerIsValid(time1) || !PointerIsValid(time2)) - return(FALSE); + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return (FALSE); - return(*time1 == *time2); -} /* time_eq() */ + return (*time1 == *time2); +} /* time_eq() */ bool -time_ne(TimeADT *time1, TimeADT *time2) +time_ne(TimeADT * time1, TimeADT * time2) { - if (!PointerIsValid(time1) || !PointerIsValid(time2)) - return(FALSE); + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return (FALSE); - return(*time1 != *time2); -} /* time_eq() */ + return (*time1 != *time2); +} /* time_eq() */ bool -time_lt(TimeADT *time1, TimeADT *time2) +time_lt(TimeADT * time1, TimeADT * time2) { - if (!PointerIsValid(time1) || !PointerIsValid(time2)) - return(FALSE); + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return (FALSE); - return(*time1 < *time2); -} /* time_eq() */ + return (*time1 < *time2); +} /* time_eq() */ bool -time_le(TimeADT *time1, TimeADT *time2) +time_le(TimeADT * time1, TimeADT * time2) { - if (!PointerIsValid(time1) || !PointerIsValid(time2)) - return(FALSE); + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return (FALSE); - return(*time1 <= *time2); -} /* time_eq() */ + return (*time1 <= *time2); +} /* time_eq() */ bool -time_gt(TimeADT *time1, TimeADT *time2) +time_gt(TimeADT * time1, TimeADT * time2) { - if (!PointerIsValid(time1) || !PointerIsValid(time2)) - return(FALSE); + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return (FALSE); - return(*time1 > *time2); -} /* time_eq() */ + return (*time1 > *time2); +} /* time_eq() */ bool -time_ge(TimeADT *time1, TimeADT *time2) +time_ge(TimeADT * time1, TimeADT * time2) { - if (!PointerIsValid(time1) || !PointerIsValid(time2)) - return(FALSE); + if (!PointerIsValid(time1) || !PointerIsValid(time2)) + return (FALSE); - return(*time1 >= *time2); -} /* time_eq() */ + return (*time1 >= *time2); +} /* time_eq() */ int -time_cmp(TimeADT *time1, TimeADT *time2) +time_cmp(TimeADT * time1, TimeADT * time2) { - return((*time1 < *time2)? -1: (((*time1 > *time2)? 1: 0))); -} /* time_cmp() */ + return ((*time1 < *time2) ? -1 : (((*time1 > *time2) ? 1 : 0))); +} /* time_cmp() */ /* datetime_datetime() * Convert date and time to datetime data type. */ -DateTime * -datetime_datetime(DateADT date, TimeADT *time) +DateTime * +datetime_datetime(DateADT date, TimeADT * time) { - DateTime *result; + DateTime *result; - if (!PointerIsValid(time)) { - result = PALLOCTYPE(DateTime); - DATETIME_INVALID(*result); + if (!PointerIsValid(time)) + { + result = PALLOCTYPE(DateTime); + DATETIME_INVALID(*result); - } else { - result = date_datetime(date); - *result += *time; - } + } + else + { + result = date_datetime(date); + *result += *time; + } - return(result); -} /* datetime_datetime() */ + return (result); +} /* datetime_datetime() */ -int32 /* RelativeTime */ +int32 /* RelativeTime */ int42reltime(int32 timevalue) { - return(timevalue); + return (timevalue); } diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c index 493843071cd..eb314176bab 100644 --- a/src/backend/utils/adt/datum.c +++ b/src/backend/utils/adt/datum.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datum.c,v 1.5 1997/08/19 21:34:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datum.c,v 1.6 1997/09/07 04:50:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -49,39 +49,51 @@ Size datumGetSize(Datum value, Oid type, bool byVal, Size len) { - - struct varlena *s; - Size size = 0; - - if (byVal) { - if (len <= sizeof(Datum)) { - size = len; - } else { - elog(WARN, - "datumGetSize: Error: type=%ld, byVaL with len=%d", - (long) type, len); + + struct varlena *s; + Size size = 0; + + if (byVal) + { + if (len <= sizeof(Datum)) + { + size = len; + } + else + { + elog(WARN, + "datumGetSize: Error: type=%ld, byVaL with len=%d", + (long) type, len); + } } - } else { /* not byValue */ - if (len == -1) { - /* - * variable length type - * Look at the varlena struct for its real length... - */ - s = (struct varlena *) DatumGetPointer(value); - if (!PointerIsValid(s)) { - elog(WARN, - "datumGetSize: Invalid Datum Pointer"); - } - size = (Size) VARSIZE(s); - } else { - /* - * fixed length type - */ - size = len; + else + { /* not byValue */ + if (len == -1) + { + + /* + * variable length type Look at the varlena struct for its + * real length... + */ + s = (struct varlena *) DatumGetPointer(value); + if (!PointerIsValid(s)) + { + elog(WARN, + "datumGetSize: Invalid Datum Pointer"); + } + size = (Size) VARSIZE(s); + } + else + { + + /* + * fixed length type + */ + size = len; + } } - } - - return(size); + + return (size); } /*------------------------------------------------------------------------- @@ -97,29 +109,35 @@ datumGetSize(Datum value, Oid type, bool byVal, Size len) Datum datumCopy(Datum value, Oid type, bool byVal, Size len) { - - Size realSize; - Datum res; - char *s; - - - if (byVal) { - res = value; - } else { - if (value == 0) return((Datum)NULL); - realSize = datumGetSize(value, type, byVal, len); - /* - * the value is a pointer. Allocate enough space - * and copy the pointed data. - */ - s = (char *) palloc(realSize); - if (s == NULL) { - elog(WARN,"datumCopy: out of memory\n"); + + Size realSize; + Datum res; + char *s; + + + if (byVal) + { + res = value; } - memmove(s, DatumGetPointer(value), realSize); - res = (Datum)s; - } - return(res); + else + { + if (value == 0) + return ((Datum) NULL); + realSize = datumGetSize(value, type, byVal, len); + + /* + * the value is a pointer. Allocate enough space and copy the + * pointed data. + */ + s = (char *) palloc(realSize); + if (s == NULL) + { + elog(WARN, "datumCopy: out of memory\n"); + } + memmove(s, DatumGetPointer(value), realSize); + res = (Datum) s; + } + return (res); } /*------------------------------------------------------------------------- @@ -135,20 +153,23 @@ datumCopy(Datum value, Oid type, bool byVal, Size len) void datumFree(Datum value, Oid type, bool byVal, Size len) { - - Size realSize; - Pointer s; - - realSize = datumGetSize(value, type, byVal, len); - - if (!byVal) { - /* - * free the space palloced by "datumCopy()" - */ - s = DatumGetPointer(value); - pfree(s); - } + + Size realSize; + Pointer s; + + realSize = datumGetSize(value, type, byVal, len); + + if (!byVal) + { + + /* + * free the space palloced by "datumCopy()" + */ + s = DatumGetPointer(value); + pfree(s); + } } + #endif /*------------------------------------------------------------------------- @@ -167,36 +188,40 @@ datumFree(Datum value, Oid type, bool byVal, Size len) bool datumIsEqual(Datum value1, Datum value2, Oid type, bool byVal, Size len) { - Size size1, size2; - char *s1, *s2; - - if (byVal) { - /* - * just compare the two datums. - * NOTE: just comparing "len" bytes will not do the - * work, because we do not know how these bytes - * are aligned inside the "Datum". - */ - if (value1 == value2) - return(true); - else - return(false); - } else { - /* - * byVal = false - * Compare the bytes pointed by the pointers stored in the - * datums. - */ - size1 = datumGetSize(value1, type, byVal, len); - size2 = datumGetSize(value2, type, byVal, len); - if (size1 != size2) - return(false); - s1 = (char *) DatumGetPointer(value1); - s2 = (char *) DatumGetPointer(value2); - if (!memcmp(s1, s2, size1)) - return(true); + Size size1, + size2; + char *s1, + *s2; + + if (byVal) + { + + /* + * just compare the two datums. NOTE: just comparing "len" bytes + * will not do the work, because we do not know how these bytes + * are aligned inside the "Datum". + */ + if (value1 == value2) + return (true); + else + return (false); + } else - return(false); - } -} + { + /* + * byVal = false Compare the bytes pointed by the pointers stored + * in the datums. + */ + size1 = datumGetSize(value1, type, byVal, len); + size2 = datumGetSize(value2, type, byVal, len); + if (size1 != size2) + return (false); + s1 = (char *) DatumGetPointer(value1); + s2 = (char *) DatumGetPointer(value2); + if (!memcmp(s1, s2, size1)) + return (true); + else + return (false); + } +} diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c index 803f0d63669..b3eca30144c 100644 --- a/src/backend/utils/adt/dt.c +++ b/src/backend/utils/adt/dt.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * dt.c-- - * Functions for the built-in type "dt". + * Functions for the built-in type "dt". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.37 1997/09/06 00:22:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.38 1997/09/07 04:50:11 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,54 +21,57 @@ #include "postgres.h" #include "miscadmin.h" #ifdef HAVE_FLOAT_H -# include <float.h> +#include <float.h> #endif #ifdef HAVE_LIMITS_H -# include <limits.h> +#include <limits.h> #endif #ifndef USE_POSIX_TIME #include <sys/timeb.h> #endif #include "utils/builtins.h" -static int DecodeDate(char *str, int fmask, int *tmask, struct tm *tm); -static int DecodeNumber( int flen, char *field, - int fmask, int *tmask, struct tm *tm, double *fsec); -static int DecodeNumberField( int len, char *str, - int fmask, int *tmask, struct tm *tm, double *fsec); -static int DecodeSpecial(int field, char *lowtoken, int *val); -static int DecodeTime(char *str, int fmask, int *tmask, - struct tm *tm, double *fsec); -static int DecodeTimezone( char *str, int *tzp); -static int DecodeUnits(int field, char *lowtoken, int *val); -static int EncodeSpecialDateTime(DateTime dt, char *str); -static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel); -static DateTime dt2local( DateTime dt, int timezone); -static void dt2time(DateTime dt, int *hour, int *min, double *sec); -static int j2day( int jd); -static int timespan2tm(TimeSpan span, struct tm *tm, float8 *fsec); -static int tm2timespan(struct tm *tm, double fsec, TimeSpan *span); +static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm); +static int +DecodeNumber(int flen, char *field, + int fmask, int *tmask, struct tm * tm, double *fsec); +static int +DecodeNumberField(int len, char *str, + int fmask, int *tmask, struct tm * tm, double *fsec); +static int DecodeSpecial(int field, char *lowtoken, int *val); +static int +DecodeTime(char *str, int fmask, int *tmask, + struct tm * tm, double *fsec); +static int DecodeTimezone(char *str, int *tzp); +static int DecodeUnits(int field, char *lowtoken, int *val); +static int EncodeSpecialDateTime(DateTime dt, char *str); +static datetkn *datebsearch(char *key, datetkn * base, unsigned int nel); +static DateTime dt2local(DateTime dt, int timezone); +static void dt2time(DateTime dt, int *hour, int *min, double *sec); +static int j2day(int jd); +static int timespan2tm(TimeSpan span, struct tm * tm, float8 * fsec); +static int tm2timespan(struct tm * tm, double fsec, TimeSpan * span); #define USE_DATE_CACHE 1 #define ROUND_ALL 0 #define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0))) -int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; +int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; -char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; +char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", +"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; -char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", NULL}; +char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", +"Thursday", "Friday", "Saturday", NULL}; /* TMODULO() * Macro to replace modf(), which is broken on some platforms. */ #define TMODULO(t,q,u) {q = ((t < 0)? ceil(t / u): floor(t / u)); \ - if (q != 0) t -= rint(q * u);} + if (q != 0) t -= rint(q * u);} -static void GetEpochTime( struct tm *tm); +static void GetEpochTime(struct tm * tm); #define UTIME_MINYEAR (1901) #define UTIME_MINMONTH (12) @@ -85,1728 +88,1975 @@ static void GetEpochTime( struct tm *tm); || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY)))))) -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* datetime_in() * Convert a string to internal form. */ -DateTime * +DateTime * datetime_in(char *str) { - DateTime *result; + DateTime *result; - double fsec; - struct tm tt, *tm = &tt; - int tz; - int dtype; - int nf; - char *field[MAXDATEFIELDS]; - int ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN+1]; + double fsec; + struct tm tt, + *tm = &tt; + int tz; + int dtype; + int nf; + char *field[MAXDATEFIELDS]; + int ftype[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - elog(WARN,"Bad (null) datetime external representation",NULL); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) datetime external representation", NULL); - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) - elog(WARN,"Bad datetime external representation %s",str); + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) + elog(WARN, "Bad datetime external representation %s", str); - result = PALLOCTYPE(DateTime); + result = PALLOCTYPE(DateTime); - switch (dtype) { - case DTK_DATE: - if (tm2datetime( tm, fsec, &tz, result) != 0) - elog(WARN,"Datetime out of range %s",str); + switch (dtype) + { + case DTK_DATE: + if (tm2datetime(tm, fsec, &tz, result) != 0) + elog(WARN, "Datetime out of range %s", str); #ifdef DATEDEBUG -printf( "datetime_in- date is %f\n", *result); + printf("datetime_in- date is %f\n", *result); #endif - break; + break; - case DTK_EPOCH: - DATETIME_EPOCH(*result); - break; + case DTK_EPOCH: + DATETIME_EPOCH(*result); + break; - case DTK_CURRENT: - DATETIME_CURRENT(*result); - break; + case DTK_CURRENT: + DATETIME_CURRENT(*result); + break; - case DTK_LATE: - DATETIME_NOEND(*result); - break; + case DTK_LATE: + DATETIME_NOEND(*result); + break; - case DTK_EARLY: - DATETIME_NOBEGIN(*result); - break; + case DTK_EARLY: + DATETIME_NOBEGIN(*result); + break; - case DTK_INVALID: - DATETIME_INVALID(*result); - break; + case DTK_INVALID: + DATETIME_INVALID(*result); + break; - default: - elog(WARN,"Internal coding error, can't input datetime '%s'",str); - } + default: + elog(WARN, "Internal coding error, can't input datetime '%s'", str); + } - return(result); -} /* datetime_in() */ + return (result); +} /* datetime_in() */ /* datetime_out() * Convert a datetime to external form. */ -char * -datetime_out(DateTime *dt) +char * +datetime_out(DateTime * dt) { - char *result; - int tz; - struct tm tt, *tm = &tt; - double fsec; - char *tzn; - char buf[MAXDATELEN+1]; + char *result; + int tz; + struct tm tt, + *tm = &tt; + double fsec; + char *tzn; + char buf[MAXDATELEN + 1]; - if (!PointerIsValid(dt)) - return(NULL); + if (!PointerIsValid(dt)) + return (NULL); - if (DATETIME_IS_RESERVED(*dt)) { - EncodeSpecialDateTime(*dt, buf); + if (DATETIME_IS_RESERVED(*dt)) + { + EncodeSpecialDateTime(*dt, buf); - } else if (datetime2tm( *dt, &tz, tm, &fsec, &tzn) == 0) { - EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); + } + else if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) == 0) + { + EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); - } else { - EncodeSpecialDateTime(DT_INVALID, buf); - } + } + else + { + EncodeSpecialDateTime(DT_INVALID, buf); + } - result = PALLOC(strlen(buf)+1); + result = PALLOC(strlen(buf) + 1); - strcpy( result, buf); + strcpy(result, buf); - return( result); -} /* datetime_out() */ + return (result); +} /* datetime_out() */ /* timespan_in() * Convert a string to internal form. * * External format(s): - * Uses the generic date/time parsing and decoding routines. + * Uses the generic date/time parsing and decoding routines. */ -TimeSpan * +TimeSpan * timespan_in(char *str) { - TimeSpan *span; + TimeSpan *span; - double fsec; - struct tm tt, *tm = &tt; - int dtype; - int nf; - char *field[MAXDATEFIELDS]; - int ftype[MAXDATEFIELDS]; - char lowstr[MAXDATELEN+1]; + double fsec; + struct tm tt, + *tm = &tt; + int dtype; + int nf; + char *field[MAXDATEFIELDS]; + int ftype[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; - tm->tm_year = 0; - tm->tm_mon = 0; - tm->tm_mday = 0; - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - fsec = 0; + tm->tm_year = 0; + tm->tm_mon = 0; + tm->tm_mday = 0; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + fsec = 0; - if (!PointerIsValid(str)) - elog(WARN,"Bad (null) timespan external representation",NULL); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) timespan external representation", NULL); - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0)) - elog(WARN,"Bad timespan external representation '%s'",str); + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0)) + elog(WARN, "Bad timespan external representation '%s'", str); - span = PALLOCTYPE(TimeSpan); + span = PALLOCTYPE(TimeSpan); - switch (dtype) { - case DTK_DELTA: - if (tm2timespan(tm, fsec, span) != 0) { + switch (dtype) + { + case DTK_DELTA: + if (tm2timespan(tm, fsec, span) != 0) + { #if FALSE - TIMESPAN_INVALID(span); + TIMESPAN_INVALID(span); #endif - elog(WARN,"Bad timespan external representation %s",str); - } - break; + elog(WARN, "Bad timespan external representation %s", str); + } + break; - default: - elog(WARN,"Internal coding error, can't input timespan '%s'",str); - } + default: + elog(WARN, "Internal coding error, can't input timespan '%s'", str); + } - return(span); -} /* timespan_in() */ + return (span); +} /* timespan_in() */ /* timespan_out() * Convert a time span to external form. */ -char * -timespan_out(TimeSpan *span) +char * +timespan_out(TimeSpan * span) { - char *result; + char *result; - struct tm tt, *tm = &tt; - double fsec; - char buf[MAXDATELEN+1]; + struct tm tt, + *tm = &tt; + double fsec; + char buf[MAXDATELEN + 1]; - if (!PointerIsValid(span)) - return(NULL); + if (!PointerIsValid(span)) + return (NULL); - if (timespan2tm(*span, tm, &fsec) != 0) - return(NULL); + if (timespan2tm(*span, tm, &fsec) != 0) + return (NULL); - if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0) - elog(WARN,"Unable to format timespan",NULL); + if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0) + elog(WARN, "Unable to format timespan", NULL); - result = PALLOC(strlen(buf)+1); + result = PALLOC(strlen(buf) + 1); - strcpy( result, buf); - return( result); -} /* timespan_out() */ + strcpy(result, buf); + return (result); +} /* timespan_out() */ -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ bool -datetime_finite(DateTime *datetime) +datetime_finite(DateTime * datetime) { - if (!PointerIsValid(datetime)) - return FALSE; + if (!PointerIsValid(datetime)) + return FALSE; - return(! DATETIME_NOT_FINITE(*datetime)); -} /* datetime_finite() */ + return (!DATETIME_NOT_FINITE(*datetime)); +} /* datetime_finite() */ #ifdef NOT_USED bool -timespan_finite(TimeSpan *timespan) +timespan_finite(TimeSpan * timespan) { - if (!PointerIsValid(timespan)) - return FALSE; + if (!PointerIsValid(timespan)) + return FALSE; + + return (!TIMESPAN_NOT_FINITE(*timespan)); +} /* timespan_finite() */ - return(! TIMESPAN_NOT_FINITE(*timespan)); -} /* timespan_finite() */ #endif /*---------------------------------------------------------- - * Relational operators for datetime. + * Relational operators for datetime. *---------------------------------------------------------*/ static void -GetEpochTime( struct tm *tm) +GetEpochTime(struct tm * tm) { - struct tm *t0; - time_t epoch = 0; + struct tm *t0; + time_t epoch = 0; - t0 = gmtime( &epoch); + t0 = gmtime(&epoch); - tm->tm_year = t0->tm_year; - tm->tm_mon = t0->tm_mon; - tm->tm_mday = t0->tm_mday; - tm->tm_hour = t0->tm_hour; - tm->tm_min = t0->tm_min; - tm->tm_sec = t0->tm_sec; + tm->tm_year = t0->tm_year; + tm->tm_mon = t0->tm_mon; + tm->tm_mday = t0->tm_mday; + tm->tm_hour = t0->tm_hour; + tm->tm_min = t0->tm_min; + tm->tm_sec = t0->tm_sec; - if (tm->tm_year < 1900) tm->tm_year += 1900; - tm->tm_mon++; + if (tm->tm_year < 1900) + tm->tm_year += 1900; + tm->tm_mon++; #ifdef DATEDEBUG -printf( "GetEpochTime- %04d-%02d-%02d %02d:%02d:%02d\n", - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + printf("GetEpochTime- %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - return; -} /* GetEpochTime() */ + return; +} /* GetEpochTime() */ DateTime -SetDateTime( DateTime dt) { - struct tm tt; +SetDateTime(DateTime dt) +{ + struct tm tt; - if (DATETIME_IS_CURRENT(dt)) { - GetCurrentTime(&tt); - tm2datetime( &tt, 0, NULL, &dt); - dt = dt2local( dt, -CTimeZone); + if (DATETIME_IS_CURRENT(dt)) + { + GetCurrentTime(&tt); + tm2datetime(&tt, 0, NULL, &dt); + dt = dt2local(dt, -CTimeZone); #ifdef DATEDEBUG -printf( "SetDateTime- current time is %f\n", dt); + printf("SetDateTime- current time is %f\n", dt); #endif - } else { /* if (DATETIME_IS_EPOCH(dt1)) */ - GetEpochTime(&tt); - tm2datetime( &tt, 0, NULL, &dt); + } + else + { /* if (DATETIME_IS_EPOCH(dt1)) */ + GetEpochTime(&tt); + tm2datetime(&tt, 0, NULL, &dt); #ifdef DATEDEBUG -printf( "SetDateTime- epoch time is %f\n", dt); + printf("SetDateTime- epoch time is %f\n", dt); #endif - } + } - return(dt); -} /* SetDateTime() */ + return (dt); +} /* SetDateTime() */ -/* datetime_relop - is datetime1 relop datetime2 +/* datetime_relop - is datetime1 relop datetime2 */ bool -datetime_eq(DateTime *datetime1, DateTime *datetime2) +datetime_eq(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return FALSE; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return FALSE; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) - return FALSE; + if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) + return FALSE; - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - return( dt1 == dt2); -} /* datetime_eq() */ + return (dt1 == dt2); +} /* datetime_eq() */ bool -datetime_ne(DateTime *datetime1, DateTime *datetime2) +datetime_ne(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return FALSE; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return FALSE; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) - return FALSE; + if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) + return FALSE; - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - return( dt1 != dt2); -} /* datetime_ne() */ + return (dt1 != dt2); +} /* datetime_ne() */ bool -datetime_lt(DateTime *datetime1, DateTime *datetime2) +datetime_lt(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return FALSE; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return FALSE; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) - return FALSE; + if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) + return FALSE; - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - return( dt1 < dt2); -} /* datetime_lt() */ + return (dt1 < dt2); +} /* datetime_lt() */ bool -datetime_gt(DateTime *datetime1, DateTime *datetime2) +datetime_gt(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return FALSE; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return FALSE; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) - return FALSE; + if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) + return FALSE; - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); #ifdef DATEDEBUG -printf( "datetime_gt- %f %s greater than %f\n", dt1, ((dt1 > dt2)? "is": "is not"), dt2); + printf("datetime_gt- %f %s greater than %f\n", dt1, ((dt1 > dt2) ? "is" : "is not"), dt2); #endif - return( dt1 > dt2); -} /* datetime_gt() */ + return (dt1 > dt2); +} /* datetime_gt() */ bool -datetime_le(DateTime *datetime1, DateTime *datetime2) +datetime_le(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return FALSE; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return FALSE; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) - return FALSE; + if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) + return FALSE; - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - return( dt1 <= dt2); -} /* datetime_le() */ + return (dt1 <= dt2); +} /* datetime_le() */ bool -datetime_ge(DateTime *datetime1, DateTime *datetime2) +datetime_ge(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return FALSE; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return FALSE; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) - return FALSE; + if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) + return FALSE; - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - return( dt1 >= dt2); -} /* datetime_ge() */ + return (dt1 >= dt2); +} /* datetime_ge() */ -/* datetime_cmp - 3-state comparison for datetime - * collate invalid datetime at the end +/* datetime_cmp - 3-state comparison for datetime + * collate invalid datetime at the end */ int -datetime_cmp(DateTime *datetime1, DateTime *datetime2) +datetime_cmp(DateTime * datetime1, DateTime * datetime2) { - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return 0; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return 0; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - if (DATETIME_IS_INVALID(dt1)) { - return( (DATETIME_IS_INVALID(dt2)? 0: 1)); + if (DATETIME_IS_INVALID(dt1)) + { + return ((DATETIME_IS_INVALID(dt2) ? 0 : 1)); - } else if (DATETIME_IS_INVALID(dt2)) { - return( -1); + } + else if (DATETIME_IS_INVALID(dt2)) + { + return (-1); - } else { - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); - } + } + else + { + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); + } - return( ((dt1 < dt2)? -1: ((dt1 > dt2)? 1: 0))); -} /* datetime_cmp() */ + return (((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0))); +} /* datetime_cmp() */ -/* timespan_relop - is timespan1 relop timespan2 +/* timespan_relop - is timespan1 relop timespan2 */ bool -timespan_eq(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_eq(TimeSpan * timespan1, TimeSpan * timespan2) { - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return FALSE; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return FALSE; - if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) - return FALSE; + if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) + return FALSE; - return( (timespan1->time == timespan2->time) - && (timespan1->month == timespan2->month)); -} /* timespan_eq() */ + return ((timespan1->time == timespan2->time) + && (timespan1->month == timespan2->month)); +} /* timespan_eq() */ bool -timespan_ne(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_ne(TimeSpan * timespan1, TimeSpan * timespan2) { - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return FALSE; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return FALSE; - if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) - return FALSE; + if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) + return FALSE; - return( (timespan1->time != timespan2->time) - || (timespan1->month != timespan2->month)); -} /* timespan_ne() */ + return ((timespan1->time != timespan2->time) + || (timespan1->month != timespan2->month)); +} /* timespan_ne() */ bool -timespan_lt(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_lt(TimeSpan * timespan1, TimeSpan * timespan2) { - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return FALSE; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return FALSE; - if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) - return FALSE; + if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) + return FALSE; - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); - return( span1 < span2); -} /* timespan_lt() */ + return (span1 < span2); +} /* timespan_lt() */ bool -timespan_gt(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_gt(TimeSpan * timespan1, TimeSpan * timespan2) { - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return FALSE; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return FALSE; - if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) - return FALSE; + if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) + return FALSE; - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); - return( span1 > span2); -} /* timespan_gt() */ + return (span1 > span2); +} /* timespan_gt() */ bool -timespan_le(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_le(TimeSpan * timespan1, TimeSpan * timespan2) { - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return FALSE; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return FALSE; - if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) - return FALSE; + if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) + return FALSE; - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); - return( span1 <= span2); -} /* timespan_le() */ + return (span1 <= span2); +} /* timespan_le() */ bool -timespan_ge(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_ge(TimeSpan * timespan1, TimeSpan * timespan2) { - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return FALSE; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return FALSE; - if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) - return FALSE; + if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) + return FALSE; - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); - return( span1 >= span2); -} /* timespan_ge() */ + return (span1 >= span2); +} /* timespan_ge() */ -/* timespan_cmp - 3-state comparison for timespan +/* timespan_cmp - 3-state comparison for timespan */ int -timespan_cmp(TimeSpan *timespan1, TimeSpan *timespan2) +timespan_cmp(TimeSpan * timespan1, TimeSpan * timespan2) { - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return 0; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return 0; - if (TIMESPAN_IS_INVALID(*timespan1)) { - return( TIMESPAN_IS_INVALID(*timespan2)? 0: 1); + if (TIMESPAN_IS_INVALID(*timespan1)) + { + return (TIMESPAN_IS_INVALID(*timespan2) ? 0 : 1); - } else if (TIMESPAN_IS_INVALID(*timespan2)) { - return( -1); - } + } + else if (TIMESPAN_IS_INVALID(*timespan2)) + { + return (-1); + } - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); - return( (span1 < span2)? -1: (span1 > span2)? 1: 0); -} /* timespan_cmp() */ + return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0); +} /* timespan_cmp() */ /*---------------------------------------------------------- - * "Arithmetic" operators on date/times. - * datetime_foo returns foo as an object (pointer) that - * can be passed between languages. - * datetime_xx is an internal routine which returns the - * actual value. + * "Arithmetic" operators on date/times. + * datetime_foo returns foo as an object (pointer) that + * can be passed between languages. + * datetime_xx is an internal routine which returns the + * actual value. *---------------------------------------------------------*/ -DateTime * -datetime_smaller(DateTime *datetime1, DateTime *datetime2) +DateTime * +datetime_smaller(DateTime * datetime1, DateTime * datetime2) { - DateTime *result; + DateTime *result; - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return NULL; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return NULL; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - result = PALLOCTYPE(DateTime); + result = PALLOCTYPE(DateTime); - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - if (DATETIME_IS_INVALID(dt1)) { - *result = dt2; - } else if (DATETIME_IS_INVALID(dt2)) { - *result = dt1; - } else { - *result = ((dt2 < dt1)? dt2: dt1); - } + if (DATETIME_IS_INVALID(dt1)) + { + *result = dt2; + } + else if (DATETIME_IS_INVALID(dt2)) + { + *result = dt1; + } + else + { + *result = ((dt2 < dt1) ? dt2 : dt1); + } - return(result); -} /* datetime_smaller() */ + return (result); +} /* datetime_smaller() */ -DateTime * -datetime_larger(DateTime *datetime1, DateTime *datetime2) +DateTime * +datetime_larger(DateTime * datetime1, DateTime * datetime2) { - DateTime *result; + DateTime *result; - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return NULL; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return NULL; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - result = PALLOCTYPE(DateTime); + result = PALLOCTYPE(DateTime); - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); - if (DATETIME_IS_INVALID(dt1)) { - *result = dt2; - } else if (DATETIME_IS_INVALID(dt2)) { - *result = dt1; - } else { - *result = ((dt2 > dt1)? dt2: dt1); - } + if (DATETIME_IS_INVALID(dt1)) + { + *result = dt2; + } + else if (DATETIME_IS_INVALID(dt2)) + { + *result = dt1; + } + else + { + *result = ((dt2 > dt1) ? dt2 : dt1); + } - return(result); -} /* datetime_larger() */ + return (result); +} /* datetime_larger() */ -TimeSpan * -datetime_mi(DateTime *datetime1, DateTime *datetime2) +TimeSpan * +datetime_mi(DateTime * datetime1, DateTime * datetime2) { - TimeSpan *result; + TimeSpan *result; - DateTime dt1, dt2; + DateTime dt1, + dt2; - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return NULL; + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return NULL; - dt1 = *datetime1; - dt2 = *datetime2; + dt1 = *datetime1; + dt2 = *datetime2; - result = PALLOCTYPE(TimeSpan); + result = PALLOCTYPE(TimeSpan); - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); #ifdef DATEDEBUG -printf( "datetime_mi- evaluate %f - %f\n", dt1, dt2); + printf("datetime_mi- evaluate %f - %f\n", dt1, dt2); #endif - if (DATETIME_IS_INVALID(dt1) - || DATETIME_IS_INVALID(dt2)) { - DATETIME_INVALID( result->time); + if (DATETIME_IS_INVALID(dt1) + || DATETIME_IS_INVALID(dt2)) + { + DATETIME_INVALID(result->time); - } else { - result->time = JROUND(dt1 - dt2); - } - result->month = 0; + } + else + { + result->time = JROUND(dt1 - dt2); + } + result->month = 0; - return(result); -} /* datetime_mi() */ + return (result); +} /* datetime_mi() */ /* datetime_pl_span() * Add a timespan to a datetime data type. * Note that timespan has provisions for qualitative year/month - * units, so try to do the right thing with them. + * units, so try to do the right thing with them. * To add a month, increment the month, and use the same day of month. * Then, if the next month has fewer days, set the day of month - * to the last day of month. + * to the last day of month. */ -DateTime * -datetime_pl_span(DateTime *datetime, TimeSpan *span) +DateTime * +datetime_pl_span(DateTime * datetime, TimeSpan * span) { - DateTime *result; - DateTime dt; - int tz; - char *tzn; + DateTime *result; + DateTime dt; + int tz; + char *tzn; - if ((!PointerIsValid(datetime)) || (!PointerIsValid(span))) - return NULL; + if ((!PointerIsValid(datetime)) || (!PointerIsValid(span))) + return NULL; - result = PALLOCTYPE(DateTime); + result = PALLOCTYPE(DateTime); #ifdef DATEDEBUG -printf( "datetime_pl_span- add %f to %d %f\n", *datetime, span->month, span->time); + printf("datetime_pl_span- add %f to %d %f\n", *datetime, span->month, span->time); #endif - if (DATETIME_NOT_FINITE(*datetime)) { - *result = *datetime; + if (DATETIME_NOT_FINITE(*datetime)) + { + *result = *datetime; - } else if (TIMESPAN_IS_INVALID(*span)) { - DATETIME_INVALID(*result); + } + else if (TIMESPAN_IS_INVALID(*span)) + { + DATETIME_INVALID(*result); - } else { - dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); + } + else + { + dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime); #ifdef ROUND_ALL - dt = JROUND(dt + span->time); + dt = JROUND(dt + span->time); #else - dt += span->time; + dt += span->time; #endif - if (span->month != 0) { - struct tm tt, *tm = &tt; - double fsec; + if (span->month != 0) + { + struct tm tt, + *tm = &tt; + double fsec; - if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) { + if (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0) + { #ifdef DATEDEBUG -printf( "datetime_pl_span- date was %04d-%02d-%02d %02d:%02d:%02d\n", - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + printf("datetime_pl_span- date was %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - tm->tm_mon += span->month; - if (tm->tm_mon > 12) { - tm->tm_year += ((tm->tm_mon-1) / 12); - tm->tm_mon = (((tm->tm_mon-1) % 12) + 1); - } else if (tm->tm_mon < 1) { - tm->tm_year += ((tm->tm_mon / 12) - 1); - tm->tm_mon = ((tm->tm_mon % 12) + 12); - } - - /* adjust for end of month boundary problems... */ - if (tm->tm_mday > mdays[ tm->tm_mon-1]) { - if ((tm->tm_mon == 2) && isleap( tm->tm_year)) { - tm->tm_mday = (mdays[ tm->tm_mon-1]+1); - } else { - tm->tm_mday = mdays[ tm->tm_mon-1]; - } - } + tm->tm_mon += span->month; + if (tm->tm_mon > 12) + { + tm->tm_year += ((tm->tm_mon - 1) / 12); + tm->tm_mon = (((tm->tm_mon - 1) % 12) + 1); + } + else if (tm->tm_mon < 1) + { + tm->tm_year += ((tm->tm_mon / 12) - 1); + tm->tm_mon = ((tm->tm_mon % 12) + 12); + } + + /* adjust for end of month boundary problems... */ + if (tm->tm_mday > mdays[tm->tm_mon - 1]) + { + if ((tm->tm_mon == 2) && isleap(tm->tm_year)) + { + tm->tm_mday = (mdays[tm->tm_mon - 1] + 1); + } + else + { + tm->tm_mday = mdays[tm->tm_mon - 1]; + } + } #ifdef DATEDEBUG -printf( "datetime_pl_span- date becomes %04d-%02d-%02d %02d:%02d:%02d\n", - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + printf("datetime_pl_span- date becomes %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - if (tm2datetime( tm, fsec, &tz, &dt) != 0) - elog(WARN,"Unable to add datetime and timespan",NULL); + if (tm2datetime(tm, fsec, &tz, &dt) != 0) + elog(WARN, "Unable to add datetime and timespan", NULL); + + } + else + { + DATETIME_INVALID(dt); + } + } - } else { - DATETIME_INVALID(dt); - } + *result = dt; } - *result = dt; - } - - return(result); -} /* datetime_pl_span() */ + return (result); +} /* datetime_pl_span() */ -DateTime * -datetime_mi_span(DateTime *datetime, TimeSpan *span) +DateTime * +datetime_mi_span(DateTime * datetime, TimeSpan * span) { - DateTime *result; - TimeSpan tspan; + DateTime *result; + TimeSpan tspan; - if (!PointerIsValid(datetime) || !PointerIsValid(span)) - return NULL; + if (!PointerIsValid(datetime) || !PointerIsValid(span)) + return NULL; - tspan.month = -span->month; - tspan.time = -span->time; + tspan.month = -span->month; + tspan.time = -span->time; - result = datetime_pl_span( datetime, &tspan); + result = datetime_pl_span(datetime, &tspan); - return(result); -} /* datetime_mi_span() */ + return (result); +} /* datetime_mi_span() */ -TimeSpan * -timespan_um(TimeSpan *timespan) +TimeSpan * +timespan_um(TimeSpan * timespan) { - TimeSpan *result; + TimeSpan *result; - if (!PointerIsValid(timespan)) - return NULL; + if (!PointerIsValid(timespan)) + return NULL; - result = PALLOCTYPE(TimeSpan); + result = PALLOCTYPE(TimeSpan); - result->time = -(timespan->time); - result->month = -(timespan->month); + result->time = -(timespan->time); + result->month = -(timespan->month); - return(result); -} /* timespan_um() */ + return (result); +} /* timespan_um() */ -TimeSpan * -timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2) +TimeSpan * +timespan_smaller(TimeSpan * timespan1, TimeSpan * timespan2) { - TimeSpan *result; + TimeSpan *result; - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return NULL; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return NULL; - result = PALLOCTYPE(TimeSpan); + result = PALLOCTYPE(TimeSpan); - if (TIMESPAN_IS_INVALID(*timespan1)) { - result->time = timespan2->time; - result->month = timespan2->month; + if (TIMESPAN_IS_INVALID(*timespan1)) + { + result->time = timespan2->time; + result->month = timespan2->month; - } else if (TIMESPAN_IS_INVALID(*timespan2)) { - result->time = timespan1->time; - result->month = timespan1->month; + } + else if (TIMESPAN_IS_INVALID(*timespan2)) + { + result->time = timespan1->time; + result->month = timespan1->month; - } else { - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + } + else + { + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); #ifdef DATEDEBUG -printf( "timespan_smaller- months %d %d times %f %f spans %f %f\n", - timespan1->month, timespan2->month, timespan1->time, timespan2->time, span1, span2); + printf("timespan_smaller- months %d %d times %f %f spans %f %f\n", + timespan1->month, timespan2->month, timespan1->time, timespan2->time, span1, span2); #endif - if (span2 < span1) { - result->time = timespan2->time; - result->month = timespan2->month; + if (span2 < span1) + { + result->time = timespan2->time; + result->month = timespan2->month; - } else { - result->time = timespan1->time; - result->month = timespan1->month; + } + else + { + result->time = timespan1->time; + result->month = timespan1->month; + } } - } - return(result); -} /* timespan_smaller() */ + return (result); +} /* timespan_smaller() */ -TimeSpan * -timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2) +TimeSpan * +timespan_larger(TimeSpan * timespan1, TimeSpan * timespan2) { - TimeSpan *result; + TimeSpan *result; - double span1, span2; + double span1, + span2; - if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) - return NULL; + if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) + return NULL; - result = PALLOCTYPE(TimeSpan); + result = PALLOCTYPE(TimeSpan); - if (TIMESPAN_IS_INVALID(*timespan1)) { - result->time = timespan2->time; - result->month = timespan2->month; + if (TIMESPAN_IS_INVALID(*timespan1)) + { + result->time = timespan2->time; + result->month = timespan2->month; - } else if (TIMESPAN_IS_INVALID(*timespan2)) { - result->time = timespan1->time; - result->month = timespan1->month; + } + else if (TIMESPAN_IS_INVALID(*timespan2)) + { + result->time = timespan1->time; + result->month = timespan1->month; - } else { - span1 = timespan1->time; - if (timespan1->month != 0) span1 += (timespan1->month * (30.0*86400)); - span2 = timespan2->time; - if (timespan2->month != 0) span2 += (timespan2->month * (30.0*86400)); + } + else + { + span1 = timespan1->time; + if (timespan1->month != 0) + span1 += (timespan1->month * (30.0 * 86400)); + span2 = timespan2->time; + if (timespan2->month != 0) + span2 += (timespan2->month * (30.0 * 86400)); #ifdef DATEDEBUG -printf( "timespan_larger- months %d %d times %f %f spans %f %f\n", - timespan1->month, timespan2->month, timespan1->time, timespan2->time, span1, span2); + printf("timespan_larger- months %d %d times %f %f spans %f %f\n", + timespan1->month, timespan2->month, timespan1->time, timespan2->time, span1, span2); #endif - if (span2 > span1) { - result->time = timespan2->time; - result->month = timespan2->month; + if (span2 > span1) + { + result->time = timespan2->time; + result->month = timespan2->month; - } else { - result->time = timespan1->time; - result->month = timespan1->month; + } + else + { + result->time = timespan1->time; + result->month = timespan1->month; + } } - } - return(result); -} /* timespan_larger() */ + return (result); +} /* timespan_larger() */ -TimeSpan * -timespan_pl(TimeSpan *span1, TimeSpan *span2) +TimeSpan * +timespan_pl(TimeSpan * span1, TimeSpan * span2) { - TimeSpan *result; + TimeSpan *result; - if ((!PointerIsValid(span1)) || (!PointerIsValid(span2))) - return NULL; + if ((!PointerIsValid(span1)) || (!PointerIsValid(span2))) + return NULL; - result = PALLOCTYPE(TimeSpan); + result = PALLOCTYPE(TimeSpan); - result->month = (span1->month + span2->month); - result->time = JROUND(span1->time + span2->time); + result->month = (span1->month + span2->month); + result->time = JROUND(span1->time + span2->time); - return(result); -} /* timespan_pl() */ + return (result); +} /* timespan_pl() */ -TimeSpan * -timespan_mi(TimeSpan *span1, TimeSpan *span2) +TimeSpan * +timespan_mi(TimeSpan * span1, TimeSpan * span2) { - TimeSpan *result; + TimeSpan *result; - if ((!PointerIsValid(span1)) || (!PointerIsValid(span2))) - return NULL; + if ((!PointerIsValid(span1)) || (!PointerIsValid(span2))) + return NULL; - result = PALLOCTYPE(TimeSpan); + result = PALLOCTYPE(TimeSpan); - result->month = (span1->month - span2->month); - result->time = JROUND(span1->time - span2->time); + result->month = (span1->month - span2->month); + result->time = JROUND(span1->time - span2->time); - return(result); -} /* timespan_mi() */ + return (result); +} /* timespan_mi() */ -TimeSpan * -timespan_div(TimeSpan *span1, float8 *arg2) +TimeSpan * +timespan_div(TimeSpan * span1, float8 * arg2) { - TimeSpan *result; + TimeSpan *result; - if ((!PointerIsValid(span1)) || (!PointerIsValid(arg2))) - return NULL; + if ((!PointerIsValid(span1)) || (!PointerIsValid(arg2))) + return NULL; - if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) - elog(WARN,"Memory allocation failed, can't subtract timespans",NULL); + if (!PointerIsValid(result = PALLOCTYPE(TimeSpan))) + elog(WARN, "Memory allocation failed, can't subtract timespans", NULL); - if (*arg2 == 0.0) - elog(WARN,"timespan_div: divide by 0.0 error"); + if (*arg2 == 0.0) + elog(WARN, "timespan_div: divide by 0.0 error"); - result->month = rint(span1->month / *arg2); - result->time = JROUND(span1->time / *arg2); + result->month = rint(span1->month / *arg2); + result->time = JROUND(span1->time / *arg2); - return(result); -} /* timespan_div() */ + return (result); +} /* timespan_div() */ /* datetime_age() * Calculate time difference while retaining year/month fields. * Note that this does not result in an accurate absolute time span - * since year and month are out of context once the arithmetic - * is done. + * since year and month are out of context once the arithmetic + * is done. */ -TimeSpan * -datetime_age(DateTime *datetime1, DateTime *datetime2) +TimeSpan * +datetime_age(DateTime * datetime1, DateTime * datetime2) { - TimeSpan *result; - - DateTime dt1, dt2; - double fsec, fsec1, fsec2; - struct tm tt, *tm = &tt; - struct tm tt1, *tm1 = &tt1; - struct tm tt2, *tm2 = &tt2; + TimeSpan *result; + + DateTime dt1, + dt2; + double fsec, + fsec1, + fsec2; + struct tm tt, + *tm = &tt; + struct tm tt1, + *tm1 = &tt1; + struct tm tt2, + *tm2 = &tt2; + + if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) + return NULL; + + result = PALLOCTYPE(TimeSpan); + + dt1 = *datetime1; + dt2 = *datetime2; + + if (DATETIME_IS_RELATIVE(dt1)) + dt1 = SetDateTime(dt1); + if (DATETIME_IS_RELATIVE(dt2)) + dt2 = SetDateTime(dt2); + + if (DATETIME_IS_INVALID(dt1) + || DATETIME_IS_INVALID(dt2)) + { + DATETIME_INVALID(result->time); - if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) - return NULL; - - result = PALLOCTYPE(TimeSpan); - - dt1 = *datetime1; - dt2 = *datetime2; - - if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); - if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); - - if (DATETIME_IS_INVALID(dt1) - || DATETIME_IS_INVALID(dt2)) { - DATETIME_INVALID( result->time); - - } else if ((datetime2tm( dt1, NULL, tm1, &fsec1, NULL) == 0) - &&(datetime2tm( dt2, NULL, tm2, &fsec2, NULL) == 0)) { - fsec = (fsec1 - fsec2); - tm->tm_sec = (tm1->tm_sec - tm2->tm_sec); - tm->tm_min = (tm1->tm_min - tm2->tm_min); - tm->tm_hour = (tm1->tm_hour - tm2->tm_hour); - tm->tm_mday = (tm1->tm_mday - tm2->tm_mday); - tm->tm_mon = (tm1->tm_mon - tm2->tm_mon); - tm->tm_year = (tm1->tm_year - tm2->tm_year); - - /* flip sign if necessary... */ - if (dt1 < dt2) { - fsec = -fsec; - tm->tm_sec = -tm->tm_sec; - tm->tm_min = -tm->tm_min; - tm->tm_hour = -tm->tm_hour; - tm->tm_mday = -tm->tm_mday; - tm->tm_mon = -tm->tm_mon; - tm->tm_year = -tm->tm_year; } + else if ((datetime2tm(dt1, NULL, tm1, &fsec1, NULL) == 0) + && (datetime2tm(dt2, NULL, tm2, &fsec2, NULL) == 0)) + { + fsec = (fsec1 - fsec2); + tm->tm_sec = (tm1->tm_sec - tm2->tm_sec); + tm->tm_min = (tm1->tm_min - tm2->tm_min); + tm->tm_hour = (tm1->tm_hour - tm2->tm_hour); + tm->tm_mday = (tm1->tm_mday - tm2->tm_mday); + tm->tm_mon = (tm1->tm_mon - tm2->tm_mon); + tm->tm_year = (tm1->tm_year - tm2->tm_year); + + /* flip sign if necessary... */ + if (dt1 < dt2) + { + fsec = -fsec; + tm->tm_sec = -tm->tm_sec; + tm->tm_min = -tm->tm_min; + tm->tm_hour = -tm->tm_hour; + tm->tm_mday = -tm->tm_mday; + tm->tm_mon = -tm->tm_mon; + tm->tm_year = -tm->tm_year; + } - if (tm->tm_sec < 0) { - tm->tm_sec += 60; - tm->tm_min--; - } + if (tm->tm_sec < 0) + { + tm->tm_sec += 60; + tm->tm_min--; + } - if (tm->tm_min < 0) { - tm->tm_min += 60; - tm->tm_hour--; - } + if (tm->tm_min < 0) + { + tm->tm_min += 60; + tm->tm_hour--; + } - if (tm->tm_hour < 0) { - tm->tm_hour += 24; - tm->tm_mday--; - } + if (tm->tm_hour < 0) + { + tm->tm_hour += 24; + tm->tm_mday--; + } - if (tm->tm_mday < 0) { - if (dt1 < dt2) { - tm->tm_mday += mdays[tm1->tm_mon-1]; - if (isleap(tm1->tm_year) && (tm1->tm_mon == 2)) tm->tm_mday++; - tm->tm_mon--; - } else { - tm->tm_mday += mdays[tm2->tm_mon-1]; - if (isleap(tm2->tm_year) && (tm2->tm_mon == 2)) tm->tm_mday++; - tm->tm_mon--; - } - } + if (tm->tm_mday < 0) + { + if (dt1 < dt2) + { + tm->tm_mday += mdays[tm1->tm_mon - 1]; + if (isleap(tm1->tm_year) && (tm1->tm_mon == 2)) + tm->tm_mday++; + tm->tm_mon--; + } + else + { + tm->tm_mday += mdays[tm2->tm_mon - 1]; + if (isleap(tm2->tm_year) && (tm2->tm_mon == 2)) + tm->tm_mday++; + tm->tm_mon--; + } + } - if (tm->tm_mon < 0) { - tm->tm_mon += 12; - tm->tm_year--; - } + if (tm->tm_mon < 0) + { + tm->tm_mon += 12; + tm->tm_year--; + } - /* recover sign if necessary... */ - if (dt1 < dt2) { - fsec = -fsec; - tm->tm_sec = -tm->tm_sec; - tm->tm_min = -tm->tm_min; - tm->tm_hour = -tm->tm_hour; - tm->tm_mday = -tm->tm_mday; - tm->tm_mon = -tm->tm_mon; - tm->tm_year = -tm->tm_year; - } + /* recover sign if necessary... */ + if (dt1 < dt2) + { + fsec = -fsec; + tm->tm_sec = -tm->tm_sec; + tm->tm_min = -tm->tm_min; + tm->tm_hour = -tm->tm_hour; + tm->tm_mday = -tm->tm_mday; + tm->tm_mon = -tm->tm_mon; + tm->tm_year = -tm->tm_year; + } - if (tm2timespan(tm, fsec, result) != 0) { - elog(WARN,"Unable to decode datetime",NULL); - } + if (tm2timespan(tm, fsec, result) != 0) + { + elog(WARN, "Unable to decode datetime", NULL); + } #if FALSE - result->time = (fsec2 - fsec1); - result->time += (tm2->tm_sec - tm1->tm_sec); - result->time += 60*(tm2->tm_min - tm1->tm_min); - result->time += 3600*(tm2->tm_hour - tm1->tm_hour); - result->time += 86400*(tm2->tm_mday - tm1->tm_mday); - - result->month = 12*(tm2->tm_year - tm1->tm_year); - result->month += (tm2->tm_mon - tm1->tm_mon); + result->time = (fsec2 - fsec1); + result->time += (tm2->tm_sec - tm1->tm_sec); + result->time += 60 * (tm2->tm_min - tm1->tm_min); + result->time += 3600 * (tm2->tm_hour - tm1->tm_hour); + result->time += 86400 * (tm2->tm_mday - tm1->tm_mday); + + result->month = 12 * (tm2->tm_year - tm1->tm_year); + result->month += (tm2->tm_mon - tm1->tm_mon); #endif - } else { - elog(WARN,"Unable to decode datetime",NULL); - } + } + else + { + elog(WARN, "Unable to decode datetime", NULL); + } - return(result); -} /* datetime_age() */ + return (result); +} /* datetime_age() */ /*---------------------------------------------------------- - * Conversion operators. + * Conversion operators. *---------------------------------------------------------*/ /* datetime_text() * Convert datetime to text data type. */ -text * -datetime_text(DateTime *datetime) +text * +datetime_text(DateTime * datetime) { - text *result; - char *str; - int len; + text *result; + char *str; + int len; - if (!PointerIsValid(datetime)) - return NULL; + if (!PointerIsValid(datetime)) + return NULL; - str = datetime_out(datetime); + str = datetime_out(datetime); - if (!PointerIsValid(str)) - return NULL; + if (!PointerIsValid(str)) + return NULL; - len = (strlen(str)+VARHDRSZ); + len = (strlen(str) + VARHDRSZ); - result = PALLOC(len); + result = PALLOC(len); - VARSIZE(result) = len; - memmove(VARDATA(result), str, (len-VARHDRSZ)); + VARSIZE(result) = len; + memmove(VARDATA(result), str, (len - VARHDRSZ)); - PFREE(str); + PFREE(str); - return(result); -} /* datetime_text() */ + return (result); +} /* datetime_text() */ /* text_datetime() * Convert text string to datetime. * Text type is not null terminated, so use temporary string - * then call the standard input routine. + * then call the standard input routine. */ -DateTime * -text_datetime(text *str) +DateTime * +text_datetime(text * str) { - DateTime *result; - int i; - char *sp, *dp, dstr[MAXDATELEN+1]; + DateTime *result; + int i; + char *sp, + *dp, + dstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - return NULL; + if (!PointerIsValid(str)) + return NULL; - sp = VARDATA(str); - dp = dstr; - for (i = 0; i < (VARSIZE(str)-VARHDRSZ); i++) *dp++ = *sp++; - *dp = '\0'; + sp = VARDATA(str); + dp = dstr; + for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) + *dp++ = *sp++; + *dp = '\0'; - result = datetime_in(dstr); + result = datetime_in(dstr); - return(result); -} /* text_datetime() */ + return (result); +} /* text_datetime() */ /* timespan_text() * Convert timespan to text data type. */ -text * -timespan_text(TimeSpan *timespan) +text * +timespan_text(TimeSpan * timespan) { - text *result; - char *str; - int len; + text *result; + char *str; + int len; - if (!PointerIsValid(timespan)) - return NULL; + if (!PointerIsValid(timespan)) + return NULL; - str = timespan_out(timespan); + str = timespan_out(timespan); - if (!PointerIsValid(str)) - return NULL; + if (!PointerIsValid(str)) + return NULL; - len = (strlen(str)+VARHDRSZ); + len = (strlen(str) + VARHDRSZ); - result = PALLOC(len); + result = PALLOC(len); - VARSIZE(result) = len; - memmove(VARDATA(result), str, (len-VARHDRSZ)); + VARSIZE(result) = len; + memmove(VARDATA(result), str, (len - VARHDRSZ)); - PFREE(str); + PFREE(str); - return(result); -} /* timespan_text() */ + return (result); +} /* timespan_text() */ /* text_timespan() * Convert text string to timespan. * Text type may not be null terminated, so copy to temporary string - * then call the standard input routine. + * then call the standard input routine. */ #ifdef NOT_USED -TimeSpan * -text_timespan(text *str) +TimeSpan * +text_timespan(text * str) { - TimeSpan *result; - int i; - char *sp, *dp, dstr[MAXDATELEN+1]; + TimeSpan *result; + int i; + char *sp, + *dp, + dstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - return NULL; + if (!PointerIsValid(str)) + return NULL; + + sp = VARDATA(str); + dp = dstr; + for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) + *dp++ = *sp++; + *dp = '\0'; - sp = VARDATA(str); - dp = dstr; - for (i = 0; i < (VARSIZE(str)-VARHDRSZ); i++) *dp++ = *sp++; - *dp = '\0'; + result = timespan_in(dstr); - result = timespan_in(dstr); + return (result); +} /* text_timespan() */ - return(result); -} /* text_timespan() */ #endif /* datetime_trunc() * Extract specified field from datetime. */ -DateTime * -datetime_trunc(text *units, DateTime *datetime) +DateTime * +datetime_trunc(text * units, DateTime * datetime) { - DateTime *result; - - DateTime dt; - int tz; - int type, val; - int i; - char *up, *lp, lowunits[MAXDATELEN+1]; - double fsec; - char *tzn; - struct tm tt, *tm = &tt; - - if ((!PointerIsValid(units)) || (!PointerIsValid(datetime))) - return NULL; - - result = PALLOCTYPE(DateTime); - - up = VARDATA(units); - lp = lowunits; - for (i = 0; i < (VARSIZE(units)-VARHDRSZ); i++) *lp++ = tolower( *up++); - *lp = '\0'; - - type = DecodeUnits( 0, lowunits, &val); + DateTime *result; + + DateTime dt; + int tz; + int type, + val; + int i; + char *up, + *lp, + lowunits[MAXDATELEN + 1]; + double fsec; + char *tzn; + struct tm tt, + *tm = &tt; + + if ((!PointerIsValid(units)) || (!PointerIsValid(datetime))) + return NULL; + + result = PALLOCTYPE(DateTime); + + up = VARDATA(units); + lp = lowunits; + for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) + *lp++ = tolower(*up++); + *lp = '\0'; + + type = DecodeUnits(0, lowunits, &val); #if FALSE - if (type == IGNORE) { - type = DecodeSpecial( 0, lowunits, &val); - } + if (type == IGNORE) + { + type = DecodeSpecial(0, lowunits, &val); + } #endif #ifdef DATEDEBUG -if (type == IGNORE) strcpy(lowunits, "(unknown)"); -printf( "datetime_trunc- units %s type=%d value=%d\n", lowunits, type, val); + if (type == IGNORE) + strcpy(lowunits, "(unknown)"); + printf("datetime_trunc- units %s type=%d value=%d\n", lowunits, type, val); #endif - if (DATETIME_NOT_FINITE(*datetime)) { + if (DATETIME_NOT_FINITE(*datetime)) + { #if FALSE /* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */ - elog(WARN,"Datetime is not finite",NULL); -#endif - *result = 0; - - } else { - dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); - - if ((type == UNITS) && (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0)) { - switch (val) { - case DTK_MILLENIUM: - tm->tm_year = (tm->tm_year/1000)*1000; - case DTK_CENTURY: - tm->tm_year = (tm->tm_year/100)*100; - case DTK_DECADE: - tm->tm_year = (tm->tm_year/10)*10; - case DTK_YEAR: - tm->tm_mon = 1; - case DTK_QUARTER: - tm->tm_mon = (3*(tm->tm_mon/4))+1; - case DTK_MONTH: - tm->tm_mday = 1; - case DTK_DAY: - tm->tm_hour = 0; - case DTK_HOUR: - tm->tm_min = 0; - case DTK_MINUTE: - tm->tm_sec = 0; - case DTK_SECOND: - fsec = 0; - break; - - case DTK_MILLISEC: - fsec = rint(fsec*1000)/1000; - break; - - case DTK_MICROSEC: - fsec = rint(fsec*1000)/1000; - break; - - default: - elog(WARN,"Datetime units %s not supported",lowunits); - result = NULL; - } + elog(WARN, "Datetime is not finite", NULL); +#endif + *result = 0; - if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) { + } + else + { + dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime); + + if ((type == UNITS) && (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0)) + { + switch (val) + { + case DTK_MILLENIUM: + tm->tm_year = (tm->tm_year / 1000) * 1000; + case DTK_CENTURY: + tm->tm_year = (tm->tm_year / 100) * 100; + case DTK_DECADE: + tm->tm_year = (tm->tm_year / 10) * 10; + case DTK_YEAR: + tm->tm_mon = 1; + case DTK_QUARTER: + tm->tm_mon = (3 * (tm->tm_mon / 4)) + 1; + case DTK_MONTH: + tm->tm_mday = 1; + case DTK_DAY: + tm->tm_hour = 0; + case DTK_HOUR: + tm->tm_min = 0; + case DTK_MINUTE: + tm->tm_sec = 0; + case DTK_SECOND: + fsec = 0; + break; + + case DTK_MILLISEC: + fsec = rint(fsec * 1000) / 1000; + break; + + case DTK_MICROSEC: + fsec = rint(fsec * 1000) / 1000; + break; + + default: + elog(WARN, "Datetime units %s not supported", lowunits); + result = NULL; + } + + if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) + { #ifdef USE_POSIX_TIME - tm->tm_isdst = -1; - tm->tm_year -= 1900; - tm->tm_mon -= 1; - tm->tm_isdst = -1; - mktime(tm); - tm->tm_year += 1900; - tm->tm_mon += 1; + tm->tm_isdst = -1; + tm->tm_year -= 1900; + tm->tm_mon -= 1; + tm->tm_isdst = -1; + mktime(tm); + tm->tm_year += 1900; + tm->tm_mon += 1; #ifdef HAVE_INT_TIMEZONE - tz = ((tm->tm_isdst > 0)? (timezone - 3600): timezone); + tz = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -#else /* !HAVE_INT_TIMEZONE */ - tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ +#else /* !HAVE_INT_TIMEZONE */ + tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ #endif -#else /* !USE_POSIX_TIME */ - tz = CTimeZone; +#else /* !USE_POSIX_TIME */ + tz = CTimeZone; #endif - } else { - tm->tm_isdst = 0; - tz = 0; - } + } + else + { + tm->tm_isdst = 0; + tz = 0; + } - if (tm2datetime( tm, fsec, &tz, result) != 0) - elog(WARN,"Unable to truncate datetime to %s",lowunits); + if (tm2datetime(tm, fsec, &tz, result) != 0) + elog(WARN, "Unable to truncate datetime to %s", lowunits); #if FALSE - } else if ((type == RESERV) && (val == DTK_EPOCH)) { - DATETIME_EPOCH(*result); - *result = dt - SetDateTime(*result); + } + else if ((type == RESERV) && (val == DTK_EPOCH)) + { + DATETIME_EPOCH(*result); + *result = dt - SetDateTime(*result); #endif - } else { - elog(WARN,"Datetime units %s not recognized",lowunits); - result = NULL; + } + else + { + elog(WARN, "Datetime units %s not recognized", lowunits); + result = NULL; + } } - } - return(result); -} /* datetime_trunc() */ + return (result); +} /* datetime_trunc() */ /* timespan_trunc() * Extract specified field from timespan. */ -TimeSpan * -timespan_trunc(text *units, TimeSpan *timespan) +TimeSpan * +timespan_trunc(text * units, TimeSpan * timespan) { - TimeSpan *result; - - int type, val; - int i; - char *up, *lp, lowunits[MAXDATELEN+1]; - double fsec; - struct tm tt, *tm = &tt; - - if ((!PointerIsValid(units)) || (!PointerIsValid(timespan))) - return NULL; - - result = PALLOCTYPE(TimeSpan); - - up = VARDATA(units); - lp = lowunits; - for (i = 0; i < (VARSIZE(units)-VARHDRSZ); i++) *lp++ = tolower( *up++); - *lp = '\0'; - - type = DecodeUnits( 0, lowunits, &val); + TimeSpan *result; + + int type, + val; + int i; + char *up, + *lp, + lowunits[MAXDATELEN + 1]; + double fsec; + struct tm tt, + *tm = &tt; + + if ((!PointerIsValid(units)) || (!PointerIsValid(timespan))) + return NULL; + + result = PALLOCTYPE(TimeSpan); + + up = VARDATA(units); + lp = lowunits; + for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) + *lp++ = tolower(*up++); + *lp = '\0'; + + type = DecodeUnits(0, lowunits, &val); #if FALSE - if (type == IGNORE) { - type = DecodeSpecial( 0, lowunits, &val); - } + if (type == IGNORE) + { + type = DecodeSpecial(0, lowunits, &val); + } #endif #ifdef DATEDEBUG -if (type == IGNORE) strcpy(lowunits, "(unknown)"); -printf( "timespan_trunc- units %s type=%d value=%d\n", lowunits, type, val); + if (type == IGNORE) + strcpy(lowunits, "(unknown)"); + printf("timespan_trunc- units %s type=%d value=%d\n", lowunits, type, val); #endif - if (TIMESPAN_IS_INVALID(*timespan)) { + if (TIMESPAN_IS_INVALID(*timespan)) + { #if FALSE - elog(WARN,"Timespan is not finite",NULL); + elog(WARN, "Timespan is not finite", NULL); #endif - result = NULL; - - } else if (type == UNITS) { - - if (timespan2tm(*timespan, tm, &fsec) == 0) { - switch (val) { - case DTK_MILLENIUM: - tm->tm_year = (tm->tm_year/1000)*1000; - case DTK_CENTURY: - tm->tm_year = (tm->tm_year/100)*100; - case DTK_DECADE: - tm->tm_year = (tm->tm_year/10)*10; - case DTK_YEAR: - tm->tm_mon = 0; - case DTK_QUARTER: - tm->tm_mon = (3*(tm->tm_mon/4)); - case DTK_MONTH: - tm->tm_mday = 0; - case DTK_DAY: - tm->tm_hour = 0; - case DTK_HOUR: - tm->tm_min = 0; - case DTK_MINUTE: - tm->tm_sec = 0; - case DTK_SECOND: - fsec = 0; - break; - - case DTK_MILLISEC: - fsec = rint(fsec*1000)/1000; - break; - - case DTK_MICROSEC: - fsec = rint(fsec*1000)/1000; - break; - - default: - elog(WARN,"Timespan units %s not supported",lowunits); result = NULL; - } - - if (tm2timespan(tm, fsec, result) != 0) - elog(WARN,"Unable to truncate timespan to %s",lowunits); - } else { - elog(NOTICE,"Timespan out of range",NULL); - result = NULL; } + else if (type == UNITS) + { + + if (timespan2tm(*timespan, tm, &fsec) == 0) + { + switch (val) + { + case DTK_MILLENIUM: + tm->tm_year = (tm->tm_year / 1000) * 1000; + case DTK_CENTURY: + tm->tm_year = (tm->tm_year / 100) * 100; + case DTK_DECADE: + tm->tm_year = (tm->tm_year / 10) * 10; + case DTK_YEAR: + tm->tm_mon = 0; + case DTK_QUARTER: + tm->tm_mon = (3 * (tm->tm_mon / 4)); + case DTK_MONTH: + tm->tm_mday = 0; + case DTK_DAY: + tm->tm_hour = 0; + case DTK_HOUR: + tm->tm_min = 0; + case DTK_MINUTE: + tm->tm_sec = 0; + case DTK_SECOND: + fsec = 0; + break; + + case DTK_MILLISEC: + fsec = rint(fsec * 1000) / 1000; + break; + + case DTK_MICROSEC: + fsec = rint(fsec * 1000) / 1000; + break; + + default: + elog(WARN, "Timespan units %s not supported", lowunits); + result = NULL; + } + + if (tm2timespan(tm, fsec, result) != 0) + elog(WARN, "Unable to truncate timespan to %s", lowunits); + + } + else + { + elog(NOTICE, "Timespan out of range", NULL); + result = NULL; + } #if FALSE - } else if ((type == RESERV) && (val == DTK_EPOCH)) { - *result = timespan->time; - if (timespan->month != 0) { - *result += ((365.25*86400)*(timespan->month / 12)); - *result += ((30*86400)*(timespan->month % 12)); } + else if ((type == RESERV) && (val == DTK_EPOCH)) + { + *result = timespan->time; + if (timespan->month != 0) + { + *result += ((365.25 * 86400) * (timespan->month / 12)); + *result += ((30 * 86400) * (timespan->month % 12)); + } #endif - } else { - elog(WARN,"Timespan units %s not recognized",units); - result = NULL; - } + } + else + { + elog(WARN, "Timespan units %s not recognized", units); + result = NULL; + } - return(result); -} /* timespan_trunc() */ + return (result); +} /* timespan_trunc() */ /* datetime_part() * Extract specified field from datetime. */ float64 -datetime_part(text *units, DateTime *datetime) +datetime_part(text * units, DateTime * datetime) { - float64 result; - - DateTime dt; - int tz; - int type, val; - int i; - char *up, *lp, lowunits[MAXDATELEN+1]; - double fsec; - char *tzn; - struct tm tt, *tm = &tt; - - if ((!PointerIsValid(units)) || (!PointerIsValid(datetime))) - return NULL; - - result = PALLOCTYPE(float64data); - - up = VARDATA(units); - lp = lowunits; - for (i = 0; i < (VARSIZE(units)-VARHDRSZ); i++) *lp++ = tolower( *up++); - *lp = '\0'; - - type = DecodeUnits( 0, lowunits, &val); - if (type == IGNORE) { - type = DecodeSpecial( 0, lowunits, &val); - } + float64 result; + + DateTime dt; + int tz; + int type, + val; + int i; + char *up, + *lp, + lowunits[MAXDATELEN + 1]; + double fsec; + char *tzn; + struct tm tt, + *tm = &tt; + + if ((!PointerIsValid(units)) || (!PointerIsValid(datetime))) + return NULL; + + result = PALLOCTYPE(float64data); + + up = VARDATA(units); + lp = lowunits; + for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) + *lp++ = tolower(*up++); + *lp = '\0'; + + type = DecodeUnits(0, lowunits, &val); + if (type == IGNORE) + { + type = DecodeSpecial(0, lowunits, &val); + } #ifdef DATEDEBUG -if (type == IGNORE) strcpy(lowunits, "(unknown)"); -printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val); + if (type == IGNORE) + strcpy(lowunits, "(unknown)"); + printf("datetime_part- units %s type=%d value=%d\n", lowunits, type, val); #endif - if (DATETIME_NOT_FINITE(*datetime)) { + if (DATETIME_NOT_FINITE(*datetime)) + { #if FALSE /* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */ - elog(WARN,"Datetime is not finite",NULL); + elog(WARN, "Datetime is not finite", NULL); #endif - *result = 0; - - } else { - dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); - - if ((type == UNITS) && (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0)) { - switch (val) { - case DTK_TZ: - *result = tz; - break; - - case DTK_MICROSEC: - *result = (fsec*1000000); - break; - - case DTK_MILLISEC: - *result = (fsec*1000); - break; - - case DTK_SECOND: - *result = (tm->tm_sec + fsec); - break; - - case DTK_MINUTE: - *result = tm->tm_min; - break; - - case DTK_HOUR: - *result = tm->tm_hour; - break; - - case DTK_DAY: - *result = tm->tm_mday; - break; - - case DTK_MONTH: - *result = tm->tm_mon; - break; - - case DTK_QUARTER: - *result = (tm->tm_mon/4)+1; - break; - - case DTK_YEAR: - *result = tm->tm_year; - break; - - case DTK_DECADE: - *result = (tm->tm_year/10)+1; - break; - - case DTK_CENTURY: - *result = (tm->tm_year/100)+1; - break; - - case DTK_MILLENIUM: - *result = (tm->tm_year/1000)+1; - break; - - default: - elog(WARN,"Datetime units %s not supported",lowunits); *result = 0; - } - - } else if (type == RESERV) { - switch (val) { - case DTK_EPOCH: - DATETIME_EPOCH(*result); - *result = dt - SetDateTime(*result); - break; - case DTK_DOW: - if (datetime2tm( dt, &tz, tm, &fsec, &tzn) != 0) - elog(WARN,"Unable to encode datetime",NULL); - - *result = j2day( date2j( tm->tm_year, tm->tm_mon, tm->tm_mday)); - break; + } + else + { + dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime); + + if ((type == UNITS) && (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0)) + { + switch (val) + { + case DTK_TZ: + *result = tz; + break; + + case DTK_MICROSEC: + *result = (fsec * 1000000); + break; + + case DTK_MILLISEC: + *result = (fsec * 1000); + break; + + case DTK_SECOND: + *result = (tm->tm_sec + fsec); + break; + + case DTK_MINUTE: + *result = tm->tm_min; + break; + + case DTK_HOUR: + *result = tm->tm_hour; + break; + + case DTK_DAY: + *result = tm->tm_mday; + break; + + case DTK_MONTH: + *result = tm->tm_mon; + break; + + case DTK_QUARTER: + *result = (tm->tm_mon / 4) + 1; + break; + + case DTK_YEAR: + *result = tm->tm_year; + break; + + case DTK_DECADE: + *result = (tm->tm_year / 10) + 1; + break; + + case DTK_CENTURY: + *result = (tm->tm_year / 100) + 1; + break; + + case DTK_MILLENIUM: + *result = (tm->tm_year / 1000) + 1; + break; + + default: + elog(WARN, "Datetime units %s not supported", lowunits); + *result = 0; + } - default: - elog(WARN,"Datetime units %s not supported",lowunits); - *result = 0; - } + } + else if (type == RESERV) + { + switch (val) + { + case DTK_EPOCH: + DATETIME_EPOCH(*result); + *result = dt - SetDateTime(*result); + break; + + case DTK_DOW: + if (datetime2tm(dt, &tz, tm, &fsec, &tzn) != 0) + elog(WARN, "Unable to encode datetime", NULL); + + *result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); + break; + + default: + elog(WARN, "Datetime units %s not supported", lowunits); + *result = 0; + } - } else { - elog(WARN,"Datetime units %s not recognized",lowunits); - *result = 0; + } + else + { + elog(WARN, "Datetime units %s not recognized", lowunits); + *result = 0; + } } - } - return(result); -} /* datetime_part() */ + return (result); +} /* datetime_part() */ /* timespan_part() * Extract specified field from timespan. */ float64 -timespan_part(text *units, TimeSpan *timespan) +timespan_part(text * units, TimeSpan * timespan) { - float64 result; - - int type, val; - int i; - char *up, *lp, lowunits[MAXDATELEN+1]; - double fsec; - struct tm tt, *tm = &tt; - - if ((!PointerIsValid(units)) || (!PointerIsValid(timespan))) - return NULL; - - result = PALLOCTYPE(float64data); - - up = VARDATA(units); - lp = lowunits; - for (i = 0; i < (VARSIZE(units)-VARHDRSZ); i++) *lp++ = tolower( *up++); - *lp = '\0'; - - type = DecodeUnits( 0, lowunits, &val); - if (type == IGNORE) { - type = DecodeSpecial( 0, lowunits, &val); - } + float64 result; + + int type, + val; + int i; + char *up, + *lp, + lowunits[MAXDATELEN + 1]; + double fsec; + struct tm tt, + *tm = &tt; + + if ((!PointerIsValid(units)) || (!PointerIsValid(timespan))) + return NULL; + + result = PALLOCTYPE(float64data); + + up = VARDATA(units); + lp = lowunits; + for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) + *lp++ = tolower(*up++); + *lp = '\0'; + + type = DecodeUnits(0, lowunits, &val); + if (type == IGNORE) + { + type = DecodeSpecial(0, lowunits, &val); + } #ifdef DATEDEBUG -if (type == IGNORE) strcpy(lowunits, "(unknown)"); -printf( "timespan_part- units %s type=%d value=%d\n", lowunits, type, val); + if (type == IGNORE) + strcpy(lowunits, "(unknown)"); + printf("timespan_part- units %s type=%d value=%d\n", lowunits, type, val); #endif - if (TIMESPAN_IS_INVALID(*timespan)) { + if (TIMESPAN_IS_INVALID(*timespan)) + { #if FALSE - elog(WARN,"Timespan is not finite",NULL); + elog(WARN, "Timespan is not finite", NULL); #endif - *result = 0; - - } else if (type == UNITS) { - - if (timespan2tm(*timespan, tm, &fsec) == 0) { - switch (val) { - case DTK_MICROSEC: - *result = (fsec*1000000); - break; - - case DTK_MILLISEC: - *result = (fsec*1000); - break; - - case DTK_SECOND: - *result = (tm->tm_sec + fsec); - break; - - case DTK_MINUTE: - *result = tm->tm_min; - break; - - case DTK_HOUR: - *result = tm->tm_hour; - break; - - case DTK_DAY: - *result = tm->tm_mday; - break; - - case DTK_MONTH: - *result = tm->tm_mon; - break; - - case DTK_QUARTER: - *result = (tm->tm_mon/4)+1; - break; - - case DTK_YEAR: - *result = tm->tm_year; - break; - - case DTK_DECADE: - *result = (tm->tm_year/10)+1; - break; - - case DTK_CENTURY: - *result = (tm->tm_year/100)+1; - break; + *result = 0; - case DTK_MILLENIUM: - *result = (tm->tm_year/1000)+1; - break; + } + else if (type == UNITS) + { + + if (timespan2tm(*timespan, tm, &fsec) == 0) + { + switch (val) + { + case DTK_MICROSEC: + *result = (fsec * 1000000); + break; + + case DTK_MILLISEC: + *result = (fsec * 1000); + break; + + case DTK_SECOND: + *result = (tm->tm_sec + fsec); + break; + + case DTK_MINUTE: + *result = tm->tm_min; + break; + + case DTK_HOUR: + *result = tm->tm_hour; + break; + + case DTK_DAY: + *result = tm->tm_mday; + break; + + case DTK_MONTH: + *result = tm->tm_mon; + break; + + case DTK_QUARTER: + *result = (tm->tm_mon / 4) + 1; + break; + + case DTK_YEAR: + *result = tm->tm_year; + break; + + case DTK_DECADE: + *result = (tm->tm_year / 10) + 1; + break; + + case DTK_CENTURY: + *result = (tm->tm_year / 100) + 1; + break; + + case DTK_MILLENIUM: + *result = (tm->tm_year / 1000) + 1; + break; + + default: + elog(WARN, "Timespan units %s not yet supported", units); + result = NULL; + } - default: - elog(WARN,"Timespan units %s not yet supported",units); - result = NULL; - } + } + else + { + elog(NOTICE, "Timespan out of range", NULL); + *result = 0; + } - } else { - elog(NOTICE,"Timespan out of range",NULL); - *result = 0; } + else if ((type == RESERV) && (val == DTK_EPOCH)) + { + *result = timespan->time; + if (timespan->month != 0) + { + *result += ((365.25 * 86400) * (timespan->month / 12)); + *result += ((30 * 86400) * (timespan->month % 12)); + } - } else if ((type == RESERV) && (val == DTK_EPOCH)) { - *result = timespan->time; - if (timespan->month != 0) { - *result += ((365.25*86400)*(timespan->month / 12)); - *result += ((30*86400)*(timespan->month % 12)); + } + else + { + elog(WARN, "Timespan units %s not recognized", units); + *result = 0; } - } else { - elog(WARN,"Timespan units %s not recognized",units); - *result = 0; - } - - return(result); -} /* timespan_part() */ + return (result); +} /* timespan_part() */ /* datetime_zone() * Encode datetime type with specified time zone. */ -text * -datetime_zone(text *zone, DateTime *datetime) -{ - text *result; - - DateTime dt; - int tz; - int type, val; - int i; - char *up, *lp, lowzone[MAXDATELEN+1]; - char *tzn, upzone[MAXDATELEN+1]; - double fsec; - struct tm tt, *tm = &tt; - char buf[MAXDATELEN+1]; - int len; - - if ((!PointerIsValid(zone)) || (!PointerIsValid(datetime))) - return NULL; - - up = VARDATA(zone); - lp = lowzone; - for (i = 0; i < (VARSIZE(zone)-VARHDRSZ); i++) *lp++ = tolower( *up++); - *lp = '\0'; +text * +datetime_zone(text * zone, DateTime * datetime) +{ + text *result; + + DateTime dt; + int tz; + int type, + val; + int i; + char *up, + *lp, + lowzone[MAXDATELEN + 1]; + char *tzn, + upzone[MAXDATELEN + 1]; + double fsec; + struct tm tt, + *tm = &tt; + char buf[MAXDATELEN + 1]; + int len; + + if ((!PointerIsValid(zone)) || (!PointerIsValid(datetime))) + return NULL; + + up = VARDATA(zone); + lp = lowzone; + for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++) + *lp++ = tolower(*up++); + *lp = '\0'; - type = DecodeSpecial( 0, lowzone, &val); + type = DecodeSpecial(0, lowzone, &val); #ifdef DATEDEBUG -if (type == IGNORE) strcpy(lowzone, "(unknown)"); -printf( "datetime_zone- zone %s type=%d value=%d\n", lowzone, type, val); + if (type == IGNORE) + strcpy(lowzone, "(unknown)"); + printf("datetime_zone- zone %s type=%d value=%d\n", lowzone, type, val); #endif - if (DATETIME_NOT_FINITE(*datetime)) { - /* could return null but Postgres doesn't like that currently. - tgl 97/06/12 */ - elog(WARN,"Datetime is not finite",NULL); - result = NULL; + if (DATETIME_NOT_FINITE(*datetime)) + { - } else if ((type == TZ) || (type == DTZ)) { - tm->tm_isdst = ((type == DTZ)? 1: 0); - tz = val * 60; + /* + * could return null but Postgres doesn't like that currently. - + * tgl 97/06/12 + */ + elog(WARN, "Datetime is not finite", NULL); + result = NULL; - dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); - dt = dt2local( dt, tz); + } + else if ((type == TZ) || (type == DTZ)) + { + tm->tm_isdst = ((type == DTZ) ? 1 : 0); + tz = val * 60; - if (datetime2tm( dt, NULL, tm, &fsec, NULL) != 0) - elog(WARN,"Datetime not legal",NULL); + dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime); + dt = dt2local(dt, tz); - up = upzone; - lp = lowzone; - for (i = 0; *lp != '\0'; i++) *up++ = toupper( *lp++); - *up = '\0'; + if (datetime2tm(dt, NULL, tm, &fsec, NULL) != 0) + elog(WARN, "Datetime not legal", NULL); - tzn = upzone; - EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); + up = upzone; + lp = lowzone; + for (i = 0; *lp != '\0'; i++) + *up++ = toupper(*lp++); + *up = '\0'; - len = (strlen(buf)+VARHDRSZ); + tzn = upzone; + EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); - result = PALLOC(len); + len = (strlen(buf) + VARHDRSZ); - VARSIZE(result) = len; - memmove(VARDATA(result), buf, (len-VARHDRSZ)); + result = PALLOC(len); + + VARSIZE(result) = len; + memmove(VARDATA(result), buf, (len - VARHDRSZ)); - } else { - elog(WARN,"Time zone %s not recognized",lowzone); - result = NULL; - } + } + else + { + elog(WARN, "Time zone %s not recognized", lowzone); + result = NULL; + } - return(result); -} /* datetime_zone() */ + return (result); +} /* datetime_zone() */ -/***************************************************************************** - * PRIVATE ROUTINES * +/***************************************************************************** + * PRIVATE ROUTINES * *****************************************************************************/ /* definitions for squeezing values into "value" */ -#define ABS_SIGNBIT (char) 0200 -#define VALMASK (char) 0177 -#define NEG(n) ((n)|ABS_SIGNBIT) +#define ABS_SIGNBIT (char) 0200 +#define VALMASK (char) 0177 +#define NEG(n) ((n)|ABS_SIGNBIT) #define SIGNEDCHAR(c) ((c)&ABS_SIGNBIT? -((c)&VALMASK): (c)) -#define FROMVAL(tp) (-SIGNEDCHAR((tp)->value) * 10) /* uncompress */ +#define FROMVAL(tp) (-SIGNEDCHAR((tp)->value) * 10) /* uncompress */ #define TOVAL(tp, v) ((tp)->value = ((v) < 0? NEG((-(v))/10): (v)/10)) /* @@ -1814,253 +2064,270 @@ printf( "datetime_zone- zone %s type=%d value=%d\n", lowzone, type, val); * entries by 10 and truncate the text field at MAXTOKLEN characters. * the text field is not guaranteed to be NULL-terminated. */ -static datetkn datetktbl[] = { -/* text token lexval */ -{ EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */ -{ "acsst", DTZ, 63}, /* Cent. Australia */ -{ "acst", TZ, 57}, /* Cent. Australia */ -{ DA_D, ADBC, AD}, /* "ad" for years >= 0 */ -{ "abstime", IGNORE, 0}, /* "abstime" for pre-v6.1 "Invalid Abstime" */ -{ "adt", DTZ, NEG(18)}, /* Atlantic Daylight Time */ -{ "aesst", DTZ, 66}, /* E. Australia */ -{ "aest", TZ, 60}, /* Australia Eastern Std Time */ -{ "ahst", TZ, 60}, /* Alaska-Hawaii Std Time */ -{ "allballs", RESERV, DTK_ZULU}, /* 00:00:00 */ -{ "am", AMPM, AM}, -{ "apr", MONTH, 4}, -{ "april", MONTH, 4}, -{ "ast", TZ, NEG(24)}, /* Atlantic Std Time (Canada) */ -{ "at", IGNORE, 0}, /* "at" (throwaway) */ -{ "aug", MONTH, 8}, -{ "august", MONTH, 8}, -{ "awsst", DTZ, 54}, /* W. Australia */ -{ "awst", TZ, 48}, /* W. Australia */ -{ DB_C, ADBC, BC}, /* "bc" for years < 0 */ -{ "bst", TZ, 6}, /* British Summer Time */ -{ "bt", TZ, 18}, /* Baghdad Time */ -{ "cadt", DTZ, 63}, /* Central Australian DST */ -{ "cast", TZ, 57}, /* Central Australian ST */ -{ "cat", TZ, NEG(60)}, /* Central Alaska Time */ -{ "cct", TZ, 48}, /* China Coast */ -{ "cdt", DTZ, NEG(30)}, /* Central Daylight Time */ -{ "cet", TZ, 6}, /* Central European Time */ -{ "cetdst", DTZ, 12}, /* Central European Dayl.Time */ -{ "cst", TZ, NEG(36)}, /* Central Standard Time */ -{ DCURRENT, RESERV, DTK_CURRENT}, /* "current" is always now */ -{ "dec", MONTH, 12}, -{ "december", MONTH, 12}, -{ "dnt", TZ, 6}, /* Dansk Normal Tid */ -{ "dow", RESERV, DTK_DOW}, /* day of week */ -{ "dst", DTZMOD, 6}, -{ "east", TZ, NEG(60)}, /* East Australian Std Time */ -{ "edt", DTZ, NEG(24)}, /* Eastern Daylight Time */ -{ "eet", TZ, 12}, /* East. Europe, USSR Zone 1 */ -{ "eetdst", DTZ, 18}, /* Eastern Europe */ -{ EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */ +static datetkn datetktbl[] = { +/* text token lexval */ + {EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */ + {"acsst", DTZ, 63}, /* Cent. Australia */ + {"acst", TZ, 57}, /* Cent. Australia */ + {DA_D, ADBC, AD}, /* "ad" for years >= 0 */ + {"abstime", IGNORE, 0}, /* "abstime" for pre-v6.1 "Invalid + * Abstime" */ + {"adt", DTZ, NEG(18)}, /* Atlantic Daylight Time */ + {"aesst", DTZ, 66}, /* E. Australia */ + {"aest", TZ, 60}, /* Australia Eastern Std Time */ + {"ahst", TZ, 60}, /* Alaska-Hawaii Std Time */ + {"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */ + {"am", AMPM, AM}, + {"apr", MONTH, 4}, + {"april", MONTH, 4}, + {"ast", TZ, NEG(24)}, /* Atlantic Std Time (Canada) */ + {"at", IGNORE, 0}, /* "at" (throwaway) */ + {"aug", MONTH, 8}, + {"august", MONTH, 8}, + {"awsst", DTZ, 54}, /* W. Australia */ + {"awst", TZ, 48}, /* W. Australia */ + {DB_C, ADBC, BC}, /* "bc" for years < 0 */ + {"bst", TZ, 6}, /* British Summer Time */ + {"bt", TZ, 18}, /* Baghdad Time */ + {"cadt", DTZ, 63}, /* Central Australian DST */ + {"cast", TZ, 57}, /* Central Australian ST */ + {"cat", TZ, NEG(60)}, /* Central Alaska Time */ + {"cct", TZ, 48}, /* China Coast */ + {"cdt", DTZ, NEG(30)}, /* Central Daylight Time */ + {"cet", TZ, 6}, /* Central European Time */ + {"cetdst", DTZ, 12}, /* Central European Dayl.Time */ + {"cst", TZ, NEG(36)}, /* Central Standard Time */ + {DCURRENT, RESERV, DTK_CURRENT}, /* "current" is always now */ + {"dec", MONTH, 12}, + {"december", MONTH, 12}, + {"dnt", TZ, 6}, /* Dansk Normal Tid */ + {"dow", RESERV, DTK_DOW}, /* day of week */ + {"dst", DTZMOD, 6}, + {"east", TZ, NEG(60)}, /* East Australian Std Time */ + {"edt", DTZ, NEG(24)}, /* Eastern Daylight Time */ + {"eet", TZ, 12}, /* East. Europe, USSR Zone 1 */ + {"eetdst", DTZ, 18}, /* Eastern Europe */ + {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */ #if USE_AUSTRALIAN_RULES -{ "est", TZ, 60}, /* Australia Eastern Std Time */ + {"est", TZ, 60}, /* Australia Eastern Std Time */ #else -{ "est", TZ, NEG(30)}, /* Eastern Standard Time */ -#endif -{ "feb", MONTH, 2}, -{ "february", MONTH, 2}, -{ "fri", DOW, 5}, -{ "friday", DOW, 5}, -{ "fst", TZ, 6}, /* French Summer Time */ -{ "fwt", DTZ, 12}, /* French Winter Time */ -{ "gmt", TZ, 0}, /* Greenwish Mean Time */ -{ "gst", TZ, 60}, /* Guam Std Time, USSR Zone 9 */ -{ "hdt", DTZ, NEG(54)}, /* Hawaii/Alaska */ -{ "hmt", DTZ, 18}, /* Hellas ? ? */ -{ "hst", TZ, NEG(60)}, /* Hawaii Std Time */ -{ "idle", TZ, 72}, /* Intl. Date Line, East */ -{ "idlw", TZ, NEG(72)}, /* Intl. Date Line, West */ -{ LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */ -{ INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid time */ -{ "ist", TZ, 12}, /* Israel */ -{ "it", TZ, 22}, /* Iran Time */ -{ "jan", MONTH, 1}, -{ "january", MONTH, 1}, -{ "jst", TZ, 54}, /* Japan Std Time,USSR Zone 8 */ -{ "jt", TZ, 45}, /* Java Time */ -{ "jul", MONTH, 7}, -{ "july", MONTH, 7}, -{ "jun", MONTH, 6}, -{ "june", MONTH, 6}, -{ "kst", TZ, 54}, /* Korea Standard Time */ -{ "ligt", TZ, 60}, /* From Melbourne, Australia */ -{ "mar", MONTH, 3}, -{ "march", MONTH, 3}, -{ "may", MONTH, 5}, -{ "mdt", DTZ, NEG(36)}, /* Mountain Daylight Time */ -{ "mest", DTZ, 12}, /* Middle Europe Summer Time */ -{ "met", TZ, 6}, /* Middle Europe Time */ -{ "metdst", DTZ, 12}, /* Middle Europe Daylight Time*/ -{ "mewt", TZ, 6}, /* Middle Europe Winter Time */ -{ "mez", TZ, 6}, /* Middle Europe Zone */ -{ "mon", DOW, 1}, -{ "monday", DOW, 1}, -{ "mst", TZ, NEG(42)}, /* Mountain Standard Time */ -{ "mt", TZ, 51}, /* Moluccas Time */ -{ "ndt", DTZ, NEG(15)}, /* Nfld. Daylight Time */ -{ "nft", TZ, NEG(21)}, /* Newfoundland Standard Time */ -{ "nor", TZ, 6}, /* Norway Standard Time */ -{ "nov", MONTH, 11}, -{ "november", MONTH, 11}, -{ NOW, RESERV, DTK_NOW}, /* current transaction time */ -{ "nst", TZ, NEG(21)}, /* Nfld. Standard Time */ -{ "nt", TZ, NEG(66)}, /* Nome Time */ -{ "nzdt", DTZ, 78}, /* New Zealand Daylight Time */ -{ "nzst", TZ, 72}, /* New Zealand Standard Time */ -{ "nzt", TZ, 72}, /* New Zealand Time */ -{ "oct", MONTH, 10}, -{ "october", MONTH, 10}, -{ "on", IGNORE, 0}, /* "on" (throwaway) */ -{ "pdt", DTZ, NEG(42)}, /* Pacific Daylight Time */ -{ "pm", AMPM, PM}, -{ "pst", TZ, NEG(48)}, /* Pacific Standard Time */ -{ "sadt", DTZ, 63}, /* S. Australian Dayl. Time */ -{ "sast", TZ, 57}, /* South Australian Std Time */ -{ "sat", DOW, 6}, -{ "saturday", DOW, 6}, -{ "sep", MONTH, 9}, -{ "sept", MONTH, 9}, -{ "september", MONTH, 9}, -{ "set", TZ, NEG(6)}, /* Seychelles Time ?? */ -{ "sst", DTZ, 12}, /* Swedish Summer Time */ -{ "sun", DOW, 0}, -{ "sunday", DOW, 0}, -{ "swt", TZ, 6}, /* Swedish Winter Time */ -{ "thu", DOW, 4}, -{ "thur", DOW, 4}, -{ "thurs", DOW, 4}, -{ "thursday", DOW, 4}, -{ TODAY, RESERV, DTK_TODAY}, /* midnight */ -{ TOMORROW, RESERV, DTK_TOMORROW}, /* tomorrow midnight */ -{ "tue", DOW, 2}, -{ "tues", DOW, 2}, -{ "tuesday", DOW, 2}, -{ "undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid time */ -{ "ut", TZ, 0}, -{ "utc", TZ, 0}, -{ "wadt", DTZ, 48}, /* West Australian DST */ -{ "wast", TZ, 42}, /* West Australian Std Time */ -{ "wat", TZ, NEG(6)}, /* West Africa Time */ -{ "wdt", DTZ, 54}, /* West Australian DST */ -{ "wed", DOW, 3}, -{ "wednesday", DOW, 3}, -{ "weds", DOW, 3}, -{ "wet", TZ, 0}, /* Western Europe */ -{ "wetdst", DTZ, 6}, /* Western Europe */ -{ "wst", TZ, 48}, /* West Australian Std Time */ -{ "ydt", DTZ, NEG(48)}, /* Yukon Daylight Time */ -{ YESTERDAY, RESERV, DTK_YESTERDAY}, /* yesterday midnight */ -{ "yst", TZ, NEG(54)}, /* Yukon Standard Time */ -{ "zp4", TZ, NEG(24)}, /* GMT +4 hours. */ -{ "zp5", TZ, NEG(30)}, /* GMT +5 hours. */ -{ "zp6", TZ, NEG(36)}, /* GMT +6 hours. */ -{ "z", RESERV, DTK_ZULU}, /* 00:00:00 */ -{ ZULU, RESERV, DTK_ZULU}, /* 00:00:00 */ + {"est", TZ, NEG(30)}, /* Eastern Standard Time */ +#endif + {"feb", MONTH, 2}, + {"february", MONTH, 2}, + {"fri", DOW, 5}, + {"friday", DOW, 5}, + {"fst", TZ, 6}, /* French Summer Time */ + {"fwt", DTZ, 12}, /* French Winter Time */ + {"gmt", TZ, 0}, /* Greenwish Mean Time */ + {"gst", TZ, 60}, /* Guam Std Time, USSR Zone 9 */ + {"hdt", DTZ, NEG(54)}, /* Hawaii/Alaska */ + {"hmt", DTZ, 18}, /* Hellas ? ? */ + {"hst", TZ, NEG(60)}, /* Hawaii Std Time */ + {"idle", TZ, 72}, /* Intl. Date Line, East */ + {"idlw", TZ, NEG(72)}, /* Intl. Date Line, West */ + {LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */ + {INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid + * time */ + {"ist", TZ, 12}, /* Israel */ + {"it", TZ, 22}, /* Iran Time */ + {"jan", MONTH, 1}, + {"january", MONTH, 1}, + {"jst", TZ, 54}, /* Japan Std Time,USSR Zone 8 */ + {"jt", TZ, 45}, /* Java Time */ + {"jul", MONTH, 7}, + {"july", MONTH, 7}, + {"jun", MONTH, 6}, + {"june", MONTH, 6}, + {"kst", TZ, 54}, /* Korea Standard Time */ + {"ligt", TZ, 60}, /* From Melbourne, Australia */ + {"mar", MONTH, 3}, + {"march", MONTH, 3}, + {"may", MONTH, 5}, + {"mdt", DTZ, NEG(36)}, /* Mountain Daylight Time */ + {"mest", DTZ, 12}, /* Middle Europe Summer Time */ + {"met", TZ, 6}, /* Middle Europe Time */ + {"metdst", DTZ, 12}, /* Middle Europe Daylight Time */ + {"mewt", TZ, 6}, /* Middle Europe Winter Time */ + {"mez", TZ, 6}, /* Middle Europe Zone */ + {"mon", DOW, 1}, + {"monday", DOW, 1}, + {"mst", TZ, NEG(42)}, /* Mountain Standard Time */ + {"mt", TZ, 51}, /* Moluccas Time */ + {"ndt", DTZ, NEG(15)}, /* Nfld. Daylight Time */ + {"nft", TZ, NEG(21)}, /* Newfoundland Standard Time */ + {"nor", TZ, 6}, /* Norway Standard Time */ + {"nov", MONTH, 11}, + {"november", MONTH, 11}, + {NOW, RESERV, DTK_NOW}, /* current transaction time */ + {"nst", TZ, NEG(21)}, /* Nfld. Standard Time */ + {"nt", TZ, NEG(66)}, /* Nome Time */ + {"nzdt", DTZ, 78}, /* New Zealand Daylight Time */ + {"nzst", TZ, 72}, /* New Zealand Standard Time */ + {"nzt", TZ, 72}, /* New Zealand Time */ + {"oct", MONTH, 10}, + {"october", MONTH, 10}, + {"on", IGNORE, 0}, /* "on" (throwaway) */ + {"pdt", DTZ, NEG(42)}, /* Pacific Daylight Time */ + {"pm", AMPM, PM}, + {"pst", TZ, NEG(48)}, /* Pacific Standard Time */ + {"sadt", DTZ, 63}, /* S. Australian Dayl. Time */ + {"sast", TZ, 57}, /* South Australian Std Time */ + {"sat", DOW, 6}, + {"saturday", DOW, 6}, + {"sep", MONTH, 9}, + {"sept", MONTH, 9}, + {"september", MONTH, 9}, + {"set", TZ, NEG(6)}, /* Seychelles Time ?? */ + {"sst", DTZ, 12}, /* Swedish Summer Time */ + {"sun", DOW, 0}, + {"sunday", DOW, 0}, + {"swt", TZ, 6}, /* Swedish Winter Time */ + {"thu", DOW, 4}, + {"thur", DOW, 4}, + {"thurs", DOW, 4}, + {"thursday", DOW, 4}, + {TODAY, RESERV, DTK_TODAY}, /* midnight */ + {TOMORROW, RESERV, DTK_TOMORROW}, /* tomorrow midnight */ + {"tue", DOW, 2}, + {"tues", DOW, 2}, + {"tuesday", DOW, 2}, + {"undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid + * time */ + {"ut", TZ, 0}, + {"utc", TZ, 0}, + {"wadt", DTZ, 48}, /* West Australian DST */ + {"wast", TZ, 42}, /* West Australian Std Time */ + {"wat", TZ, NEG(6)}, /* West Africa Time */ + {"wdt", DTZ, 54}, /* West Australian DST */ + {"wed", DOW, 3}, + {"wednesday", DOW, 3}, + {"weds", DOW, 3}, + {"wet", TZ, 0}, /* Western Europe */ + {"wetdst", DTZ, 6}, /* Western Europe */ + {"wst", TZ, 48}, /* West Australian Std Time */ + {"ydt", DTZ, NEG(48)}, /* Yukon Daylight Time */ + {YESTERDAY, RESERV, DTK_YESTERDAY}, /* yesterday midnight */ + {"yst", TZ, NEG(54)}, /* Yukon Standard Time */ + {"zp4", TZ, NEG(24)}, /* GMT +4 hours. */ + {"zp5", TZ, NEG(30)}, /* GMT +5 hours. */ + {"zp6", TZ, NEG(36)}, /* GMT +6 hours. */ + {"z", RESERV, DTK_ZULU}, /* 00:00:00 */ + {ZULU, RESERV, DTK_ZULU}, /* 00:00:00 */ }; static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0]; -static datetkn deltatktbl[] = { -/* text token lexval */ -{ "@", IGNORE, 0}, /* postgres relative time prefix */ -{ DAGO, AGO, 0}, /* "ago" indicates negative time offset */ -{ "c", UNITS, DTK_CENTURY}, /* "century" relative time units */ -{ "cent", UNITS, DTK_CENTURY}, /* "century" relative time units */ -{ "centuries", UNITS, DTK_CENTURY}, /* "centuries" relative time units */ -{ DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative time units */ -{ "d", UNITS, DTK_DAY}, /* "day" relative time units */ -{ DDAY, UNITS, DTK_DAY}, /* "day" relative time units */ -{ "days", UNITS, DTK_DAY}, /* "days" relative time units */ -{ "dec", UNITS, DTK_DECADE}, /* "decade" relative time units */ -{ "decs", UNITS, DTK_DECADE}, /* "decades" relative time units */ -{ DDECADE, UNITS, DTK_DECADE}, /* "decade" relative time units */ -{ "decades", UNITS, DTK_DECADE}, /* "decades" relative time units */ -{ "h", UNITS, DTK_HOUR}, /* "hour" relative time units */ -{ DHOUR, UNITS, DTK_HOUR}, /* "hour" relative time units */ -{ "hours", UNITS, DTK_HOUR}, /* "hours" relative time units */ -{ "hr", UNITS, DTK_HOUR}, /* "hour" relative time units */ -{ "hrs", UNITS, DTK_HOUR}, /* "hours" relative time units */ -{ INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid time */ -{ "m", UNITS, DTK_MINUTE}, /* "minute" relative time units */ -{ "microsecon", UNITS, DTK_MILLISEC}, /* "microsecond" relative time units */ -{ "mil", UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ -{ "mils", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ -{ "millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ -{ DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ -{ "millisecon", UNITS, DTK_MILLISEC}, /* "millisecond" relative time units */ -{ "min", UNITS, DTK_MINUTE}, /* "minute" relative time units */ -{ "mins", UNITS, DTK_MINUTE}, /* "minutes" relative time units */ -{ "mins", UNITS, DTK_MINUTE}, /* "minutes" relative time units */ -{ DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative time units */ -{ "minutes", UNITS, DTK_MINUTE}, /* "minutes" relative time units */ -{ "mon", UNITS, DTK_MONTH}, /* "months" relative time units */ -{ "mons", UNITS, DTK_MONTH}, /* "months" relative time units */ -{ DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */ -{ "months", UNITS, DTK_MONTH}, /* "months" relative time units */ -{ "ms", UNITS, DTK_MILLISEC}, /* "millisecond" relative time units */ -{ "msec", UNITS, DTK_MILLISEC}, /* "millisecond" relative time units */ -{ DMILLISEC, UNITS, DTK_MILLISEC}, /* "millisecond" relative time units */ -{ "mseconds", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time units */ -{ "msecs", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time units */ -{ "qtr", UNITS, DTK_QUARTER}, /* "quarter" relative time units */ -{ DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time units */ -{ "reltime", IGNORE, 0}, /* "reltime" for pre-v6.1 "Undefined Reltime" */ -{ "s", UNITS, DTK_SECOND}, /* "second" relative time units */ -{ "sec", UNITS, DTK_SECOND}, /* "second" relative time units */ -{ DSECOND, UNITS, DTK_SECOND}, /* "second" relative time units */ -{ "seconds", UNITS, DTK_SECOND}, /* "seconds" relative time units */ -{ "secs", UNITS, DTK_SECOND}, /* "seconds" relative time units */ -{ DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */ -{ "tz", UNITS, DTK_TZ}, /* "timezone" time offset */ -{ "undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid time */ -{ "us", UNITS, DTK_MICROSEC}, /* "microsecond" relative time units */ -{ "usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time units */ -{ DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative time units */ -{ "useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative time units */ -{ "usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative time units */ -{ "w", UNITS, DTK_WEEK}, /* "week" relative time units */ -{ DWEEK, UNITS, DTK_WEEK}, /* "week" relative time units */ -{ "weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */ -{ "y", UNITS, DTK_YEAR}, /* "year" relative time units */ -{ DYEAR, UNITS, DTK_YEAR}, /* "year" relative time units */ -{ "years", UNITS, DTK_YEAR}, /* "years" relative time units */ -{ "yr", UNITS, DTK_YEAR}, /* "year" relative time units */ -{ "yrs", UNITS, DTK_YEAR}, /* "years" relative time units */ +static datetkn deltatktbl[] = { +/* text token lexval */ + {"@", IGNORE, 0}, /* postgres relative time prefix */ + {DAGO, AGO, 0}, /* "ago" indicates negative time offset */ + {"c", UNITS, DTK_CENTURY}, /* "century" relative time units */ + {"cent", UNITS, DTK_CENTURY}, /* "century" relative time units */ + {"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative time units */ + {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative time units */ + {"d", UNITS, DTK_DAY}, /* "day" relative time units */ + {DDAY, UNITS, DTK_DAY}, /* "day" relative time units */ + {"days", UNITS, DTK_DAY}, /* "days" relative time units */ + {"dec", UNITS, DTK_DECADE}, /* "decade" relative time units */ + {"decs", UNITS, DTK_DECADE},/* "decades" relative time units */ + {DDECADE, UNITS, DTK_DECADE}, /* "decade" relative time units */ + {"decades", UNITS, DTK_DECADE}, /* "decades" relative time units */ + {"h", UNITS, DTK_HOUR}, /* "hour" relative time units */ + {DHOUR, UNITS, DTK_HOUR}, /* "hour" relative time units */ + {"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */ + {"hr", UNITS, DTK_HOUR}, /* "hour" relative time units */ + {"hrs", UNITS, DTK_HOUR}, /* "hours" relative time units */ + {INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid + * time */ + {"m", UNITS, DTK_MINUTE}, /* "minute" relative time units */ + {"microsecon", UNITS, DTK_MILLISEC}, /* "microsecond" relative + * time units */ + {"mil", UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ + {"mils", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ + {"millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ + {DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ + {"millisecon", UNITS, DTK_MILLISEC}, /* "millisecond" relative + * time units */ + {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */ + {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */ + {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */ + {DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative time units */ + {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative time units */ + {"mon", UNITS, DTK_MONTH}, /* "months" relative time units */ + {"mons", UNITS, DTK_MONTH}, /* "months" relative time units */ + {DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */ + {"months", UNITS, DTK_MONTH}, /* "months" relative time units */ + {"ms", UNITS, DTK_MILLISEC},/* "millisecond" relative time units */ + {"msec", UNITS, DTK_MILLISEC}, /* "millisecond" relative time + * units */ + {DMILLISEC, UNITS, DTK_MILLISEC}, /* "millisecond" relative time + * units */ + {"mseconds", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time + * units */ + {"msecs", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time + * units */ + {"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time units */ + {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time units */ + {"reltime", IGNORE, 0}, /* "reltime" for pre-v6.1 "Undefined + * Reltime" */ + {"s", UNITS, DTK_SECOND}, /* "second" relative time units */ + {"sec", UNITS, DTK_SECOND}, /* "second" relative time units */ + {DSECOND, UNITS, DTK_SECOND}, /* "second" relative time units */ + {"seconds", UNITS, DTK_SECOND}, /* "seconds" relative time units */ + {"secs", UNITS, DTK_SECOND},/* "seconds" relative time units */ + {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */ + {"tz", UNITS, DTK_TZ}, /* "timezone" time offset */ + {"undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid + * time */ + {"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */ + {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time + * units */ + {DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative time + * units */ + {"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative time + * units */ + {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative time + * units */ + {"w", UNITS, DTK_WEEK}, /* "week" relative time units */ + {DWEEK, UNITS, DTK_WEEK}, /* "week" relative time units */ + {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */ + {"y", UNITS, DTK_YEAR}, /* "year" relative time units */ + {DYEAR, UNITS, DTK_YEAR}, /* "year" relative time units */ + {"years", UNITS, DTK_YEAR}, /* "years" relative time units */ + {"yr", UNITS, DTK_YEAR}, /* "year" relative time units */ + {"yrs", UNITS, DTK_YEAR}, /* "years" relative time units */ }; static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0]; #if USE_DATE_CACHE -datetkn *datecache[MAXDATEFIELDS] = {NULL}; +datetkn *datecache[MAXDATEFIELDS] = {NULL}; + +datetkn *deltacache[MAXDATEFIELDS] = {NULL}; -datetkn *deltacache[MAXDATEFIELDS] = {NULL}; #endif /* * Calendar time to Julian date conversions. * Julian date is commonly used in astronomical applications, - * since it is numerically accurate and computationally simple. + * since it is numerically accurate and computationally simple. * The algorithms here will accurately convert between Julian day - * and calendar date for all non-negative Julian days - * (i.e. from Nov 23, -4713 on). + * and calendar date for all non-negative Julian days + * (i.e. from Nov 23, -4713 on). * * Ref: Explanatory Supplement to the Astronomical Almanac, 1992. - * University Science Books, 20 Edgehill Rd. Mill Valley CA 94941. + * University Science Books, 20 Edgehill Rd. Mill Valley CA 94941. * * Use the algorithm by Henry Fliegel, a former NASA/JPL colleague - * now at Aerospace Corp. (hi, Henry!) + * now at Aerospace Corp. (hi, Henry!) * * These routines will be used by other date/time packages - tgl 97/02/25 */ /* Set the minimum year to one greater than the year of the first valid day - * to avoid having to check year and day both. - tgl 97/05/08 + * to avoid having to check year and day both. - tgl 97/05/08 */ #define JULIAN_MINYEAR (-4713) @@ -2074,45 +2341,50 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL}; int date2j(int y, int m, int d) { - int m12 = (m-14)/12; + int m12 = (m - 14) / 12; - return((1461*(y+4800+m12))/4 + (367*(m-2-12*(m12)))/12 - - (3*((y+4900+m12)/100))/4 + d - 32075); -} /* date2j() */ + return ((1461 * (y + 4800 + m12)) / 4 + (367 * (m - 2 - 12 * (m12))) / 12 + - (3 * ((y + 4900 + m12) / 100)) / 4 + d - 32075); +} /* date2j() */ void -j2date( int jd, int *year, int *month, int *day) +j2date(int jd, int *year, int *month, int *day) { - int j, y, m, d; - - int i, l, n; - - l = jd + 68569; - n = (4*l)/146097; - l -= (146097*n+3)/4; - i = (4000*(l+1))/1461001; - l += 31 - (1461*i)/4; - j = (80*l)/2447; - d = l - (2447*j)/80; - l = j/11; - m = (j+2) - (12*l); - y = 100*(n-49)+i+l; - - *year = y; - *month = m; - *day = d; - return; -} /* j2date() */ + int j, + y, + m, + d; + + int i, + l, + n; + + l = jd + 68569; + n = (4 * l) / 146097; + l -= (146097 * n + 3) / 4; + i = (4000 * (l + 1)) / 1461001; + l += 31 - (1461 * i) / 4; + j = (80 * l) / 2447; + d = l - (2447 * j) / 80; + l = j / 11; + m = (j + 2) - (12 * l); + y = 100 * (n - 49) + i + l; + + *year = y; + *month = m; + *day = d; + return; +} /* j2date() */ static int -j2day( int date) +j2day(int date) { - int day; + int day; - day = (date+1) % 7; + day = (date + 1) % 7; - return(day); -} /* j2day() */ + return (day); +} /* j2day() */ /* datetime2tm() @@ -2120,141 +2392,159 @@ j2day( int date) * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * Returns: - * 0 on success - * -1 on out of range + * 0 on success + * -1 on out of range * * For dates within the system-supported time_t range, convert to the - * local time zone. If out of this range, leave as GMT. - tgl 97/05/27 + * local time zone. If out of this range, leave as GMT. - tgl 97/05/27 */ int -datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec, char **tzn) +datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn) { - double date, date0, time, sec; - time_t utime; + double date, + date0, + time, + sec; + time_t utime; + #ifdef USE_POSIX_TIME - struct tm *tx; + struct tm *tx; + #endif - date0 = date2j(2000,1,1); + date0 = date2j(2000, 1, 1); - time = dt; - TMODULO(time,date,86400e0); + time = dt; + TMODULO(time, date, 86400e0); - if (time < 0) { - time += 86400; - date -= 1; - } + if (time < 0) + { + time += 86400; + date -= 1; + } - /* Julian day routine does not work for negative Julian days */ - if (date < -date0) - return -1; + /* Julian day routine does not work for negative Julian days */ + if (date < -date0) + return -1; - /* add offset to go from J2000 back to standard Julian date */ - date += date0; + /* add offset to go from J2000 back to standard Julian date */ + date += date0; #ifdef DATEDEBUG -printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time); + printf("datetime2tm- date is %f (%f %f)\n", dt, date, time); #endif - j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - dt2time( time, &tm->tm_hour, &tm->tm_min, &sec); + j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + dt2time(time, &tm->tm_hour, &tm->tm_min, &sec); #ifdef DATEDEBUG -printf( "datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); -printf( "datetime2tm- time is %02d:%02d:%02.0f\n", tm->tm_hour, tm->tm_min, sec); + printf("datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); + printf("datetime2tm- time is %02d:%02d:%02.0f\n", tm->tm_hour, tm->tm_min, sec); #endif - *fsec = JROUND(sec); - TMODULO(*fsec,tm->tm_sec,1); + *fsec = JROUND(sec); + TMODULO(*fsec, tm->tm_sec, 1); #ifdef DATEDEBUG -printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); + printf("datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); #endif - if (tzp != NULL) { - if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) { - utime = (dt + (date0-date2j(1970,1,1))*86400); + if (tzp != NULL) + { + if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) + { + utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400); #if FALSE - if (utime < -1) utime++; + if (utime < -1) + utime++; #endif #ifdef USE_POSIX_TIME - tx = localtime(&utime); + tx = localtime(&utime); #ifdef DATEDEBUG #ifdef HAVE_INT_TIMEZONE -printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n", - tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec, - tzname[0], tzname[1], tx->tm_isdst); + printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n", + tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec, + tzname[0], tzname[1], tx->tm_isdst); #else -printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s dst=%d\n", - tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec, - tx->tm_zone, tx->tm_isdst); + printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s dst=%d\n", + tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec, + tx->tm_zone, tx->tm_isdst); #endif #else #endif - tm->tm_year = tx->tm_year + 1900; - tm->tm_mon = tx->tm_mon + 1; - tm->tm_mday = tx->tm_mday; - tm->tm_hour = tx->tm_hour; - tm->tm_min = tx->tm_min; + tm->tm_year = tx->tm_year + 1900; + tm->tm_mon = tx->tm_mon + 1; + tm->tm_mday = tx->tm_mday; + tm->tm_hour = tx->tm_hour; + tm->tm_min = tx->tm_min; #if FALSE /* XXX HACK * Argh! My Linux box puts in a 1 second offset for dates less than 1970 - * but only if the seconds field was non-zero. So, don't copy the seconds - * field and instead carry forward from the original - tgl 97/06/18 + * but only if the seconds field was non-zero. So, don't copy the seconds + * field and instead carry forward from the original - tgl 97/06/18 * Note that GNU/Linux uses the standard freeware zic package as do - * many other platforms so this may not be GNU/Linux/ix86-specific. + * many other platforms so this may not be GNU/Linux/ix86-specific. */ - tm->tm_sec = tx->tm_sec; + tm->tm_sec = tx->tm_sec; #endif - tm->tm_isdst = tx->tm_isdst; + tm->tm_isdst = tx->tm_isdst; #ifdef HAVE_INT_TIMEZONE - *tzp = (tm->tm_isdst? (timezone - 3600): timezone); - if (tzn != NULL) *tzn = tzname[(tm->tm_isdst > 0)]; + *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone); + if (tzn != NULL) + *tzn = tzname[(tm->tm_isdst > 0)]; -#else /* !HAVE_INT_TIMEZONE */ - tm->tm_gmtoff = tx->tm_gmtoff; - tm->tm_zone = tx->tm_zone; +#else /* !HAVE_INT_TIMEZONE */ + tm->tm_gmtoff = tx->tm_gmtoff; + tm->tm_zone = tx->tm_zone; - *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ - if (tzn != NULL) *tzn = tm->tm_zone; + *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ + if (tzn != NULL) + *tzn = tm->tm_zone; #endif -#else /* !USE_POSIX_TIME */ - *tzp = CTimeZone; /* V7 conventions; don't know timezone? */ - if (tzn != NULL) *tzn = CTZName; +#else /* !USE_POSIX_TIME */ + *tzp = CTimeZone; /* V7 conventions; don't know timezone? */ + if (tzn != NULL) + *tzn = CTZName; #endif - } else { - *tzp = 0; - tm->tm_isdst = 0; - if (tzn != NULL) *tzn = NULL; - } + } + else + { + *tzp = 0; + tm->tm_isdst = 0; + if (tzn != NULL) + *tzn = NULL; + } - dt = dt2local( dt, *tzp); + dt = dt2local(dt, *tzp); - } else { - tm->tm_isdst = 0; - if (tzn != NULL) *tzn = NULL; - } + } + else + { + tm->tm_isdst = 0; + if (tzn != NULL) + *tzn = NULL; + } #ifdef DATEDEBUG -printf( "datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); -printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); + printf("datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday); + printf("datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); #endif #ifdef DATEDEBUG #ifdef USE_POSIX_TIME #ifdef HAVE_INT_TIMEZONE -printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n", - tzname[tm->tm_isdst != 0], ((tzp != NULL)? *tzp: 0), CTimeZone, CDayLight); + printf("datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n", + tzname[tm->tm_isdst != 0], ((tzp != NULL) ? *tzp : 0), CTimeZone, CDayLight); #endif #endif #endif - return 0; -} /* datetime2tm() */ + return 0; +} /* datetime2tm() */ /* tm2datetime() @@ -2263,109 +2553,115 @@ printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n", * Also, month is one-based, _not_ zero-based. */ int -tm2datetime( struct tm *tm, double fsec, int *tzp, DateTime *result) { +tm2datetime(struct tm * tm, double fsec, int *tzp, DateTime * result) +{ - double date, time; + double date, + time; - /* Julian day routines are not correct for negative Julian days */ - if (! IS_VALID_JULIAN( tm->tm_year, tm->tm_mon, tm->tm_mday)) - return(-1); + /* Julian day routines are not correct for negative Julian days */ + if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday)) + return (-1); - date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1); - time = time2t(tm->tm_hour,tm->tm_min,(tm->tm_sec + fsec)); - *result = (date*86400+time); + date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + time = time2t(tm->tm_hour, tm->tm_min, (tm->tm_sec + fsec)); + *result = (date * 86400 + time); #ifdef DATEDEBUG -printf( "tm2datetime- date is %f (%f %f %d)\n", *result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec)); -printf( "tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); + printf("tm2datetime- date is %f (%f %f %d)\n", *result, date, time, (((tm->tm_hour * 60) + tm->tm_min) * 60 + tm->tm_sec)); + printf("tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); #endif - if (tzp != NULL) *result = dt2local(*result, -(*tzp)); + if (tzp != NULL) + *result = dt2local(*result, -(*tzp)); - return 0; -} /* tm2datetime() */ + return 0; +} /* tm2datetime() */ /* timespan2tm() * Convert a timespan data type to a tm structure. */ static int -timespan2tm(TimeSpan span, struct tm *tm, float8 *fsec) +timespan2tm(TimeSpan span, struct tm * tm, float8 * fsec) { - double time; + double time; - if (span.month != 0) { - tm->tm_year = span.month / 12; - tm->tm_mon = span.month % 12; + if (span.month != 0) + { + tm->tm_year = span.month / 12; + tm->tm_mon = span.month % 12; - } else { - tm->tm_year = 0; - tm->tm_mon = 0; - } + } + else + { + tm->tm_year = 0; + tm->tm_mon = 0; + } #ifdef ROUND_ALL - time = JROUND(span.time); + time = JROUND(span.time); #else - time = span.time; + time = span.time; #endif - TMODULO(time, tm->tm_mday, 86400e0); - TMODULO(time, tm->tm_hour, 3600e0); - TMODULO(time, tm->tm_min, 60e0); - TMODULO(time, tm->tm_sec, 1); - *fsec = time; + TMODULO(time, tm->tm_mday, 86400e0); + TMODULO(time, tm->tm_hour, 3600e0); + TMODULO(time, tm->tm_min, 60e0); + TMODULO(time, tm->tm_sec, 1); + *fsec = time; #ifdef DATEDEBUG -printf( "timespan2tm- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span.month, span.time, - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); + printf("timespan2tm- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span.month, span.time, + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); #endif - return 0; -} /* timespan2tm() */ + return 0; +} /* timespan2tm() */ static int -tm2timespan( struct tm *tm, double fsec, TimeSpan *span) +tm2timespan(struct tm * tm, double fsec, TimeSpan * span) { - span->month = ((tm->tm_year*12)+tm->tm_mon); - span->time = ((((((tm->tm_mday*24)+tm->tm_hour)*60)+tm->tm_min)*60)+tm->tm_sec); - span->time = JROUND(span->time + fsec); + span->month = ((tm->tm_year * 12) + tm->tm_mon); + span->time = ((((((tm->tm_mday * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60) + tm->tm_sec); + span->time = JROUND(span->time + fsec); #ifdef DATEDEBUG -printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month, span->time, - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); + printf("tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month, span->time, + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); #endif - return 0; -} /* tm2timespan() */ + return 0; +} /* tm2timespan() */ -static DateTime +static DateTime dt2local(DateTime dt, int tz) { - dt -= tz; - dt = JROUND(dt); - return(dt); -} /* dt2local() */ + dt -= tz; + dt = JROUND(dt); + return (dt); +} /* dt2local() */ double time2t(const int hour, const int min, const double sec) { - return((((hour*60)+min)*60)+sec); -} /* time2t() */ + return ((((hour * 60) + min) * 60) + sec); +} /* time2t() */ static void dt2time(DateTime jd, int *hour, int *min, double *sec) { - double time; + double time; - time = jd; + time = jd; - *hour = (time/3600); - time -= ((*hour)*3600); - *min = (time/60); - time -= ((*min)*60); - *sec = JROUND(time); + *hour = (time / 3600); + time -= ((*hour) * 3600); + *min = (time / 60); + time -= ((*min) * 60); + *sec = JROUND(time); - return; -} /* dt2time() */ + return; +} /* dt2time() */ /* @@ -2378,469 +2674,561 @@ dt2time(DateTime jd, int *hour, int *min, double *sec) * Break string into tokens based on a date/time context. */ int -ParseDateTime( char *timestr, char *lowstr, - char *field[], int ftype[], int maxfields, int *numfields) -{ - int nf = 0; - char *cp = timestr; - char *lp = lowstr; - -#ifdef DATEDEBUG -printf( "ParseDateTime- input string is %s\n", timestr); -#endif - /* outer loop through fields */ - while (*cp != '\0') { - field[nf] = lp; - - /* leading digit? then date or time */ - if (isdigit(*cp)) { - *lp++ = *cp++; - while (isdigit(*cp)) *lp++ = *cp++; - /* time field? */ - if (*cp == ':') { - ftype[nf] = DTK_TIME; - while (isdigit(*cp) || (*cp == ':') || (*cp == '.')) - *lp++ = *cp++; - - /* date field? allow embedded text month */ - } else if ((*cp == '-') || (*cp == '/') || (*cp == '.')) { - ftype[nf] = DTK_DATE; - while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.')) - *lp++ = tolower(*cp++); - - /* otherwise, number only and will determine year, month, or day later */ - } else { - ftype[nf] = DTK_NUMBER; - } - - /* text? then date string, month, day of week, special, or timezone */ - } else if (isalpha(*cp)) { - ftype[nf] = DTK_STRING; - *lp++ = tolower(*cp++); - while (isalpha(*cp)) *lp++ = tolower(*cp++); - - /* full date string with leading text month? */ - if ((*cp == '-') || (*cp == '/') || (*cp == '.')) { - ftype[nf] = DTK_DATE; - while (isdigit(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.')) - *lp++ = tolower(*cp++); - } - - /* skip leading spaces */ - } else if (isspace(*cp)) { - cp++; - continue; - - /* sign? then special or numeric timezone */ - } else if ((*cp == '+') || (*cp == '-')) { - *lp++ = *cp++; - /* soak up leading whitespace */ - while (isspace(*cp)) cp++; - /* numeric timezone? */ - if (isdigit(*cp)) { - ftype[nf] = DTK_TZ; - *lp++ = *cp++; - while (isdigit(*cp) || (*cp == ':')) *lp++ = *cp++; - - /* special? */ - } else if (isalpha(*cp)) { - ftype[nf] = DTK_SPECIAL; - *lp++ = tolower(*cp++); - while (isalpha(*cp)) *lp++ = tolower(*cp++); - - /* otherwise something wrong... */ - } else { - return -1; - } +ParseDateTime(char *timestr, char *lowstr, + char *field[], int ftype[], int maxfields, int *numfields) +{ + int nf = 0; + char *cp = timestr; + char *lp = lowstr; - /* ignore punctuation but use as delimiter */ - } else if (ispunct(*cp)) { - cp++; - continue; +#ifdef DATEDEBUG + printf("ParseDateTime- input string is %s\n", timestr); +#endif + /* outer loop through fields */ + while (*cp != '\0') + { + field[nf] = lp; + + /* leading digit? then date or time */ + if (isdigit(*cp)) + { + *lp++ = *cp++; + while (isdigit(*cp)) + *lp++ = *cp++; + /* time field? */ + if (*cp == ':') + { + ftype[nf] = DTK_TIME; + while (isdigit(*cp) || (*cp == ':') || (*cp == '.')) + *lp++ = *cp++; + + /* date field? allow embedded text month */ + } + else if ((*cp == '-') || (*cp == '/') || (*cp == '.')) + { + ftype[nf] = DTK_DATE; + while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.')) + *lp++ = tolower(*cp++); + + /* + * otherwise, number only and will determine year, month, + * or day later + */ + } + else + { + ftype[nf] = DTK_NUMBER; + } + + /* + * text? then date string, month, day of week, special, or + * timezone + */ + } + else if (isalpha(*cp)) + { + ftype[nf] = DTK_STRING; + *lp++ = tolower(*cp++); + while (isalpha(*cp)) + *lp++ = tolower(*cp++); + + /* full date string with leading text month? */ + if ((*cp == '-') || (*cp == '/') || (*cp == '.')) + { + ftype[nf] = DTK_DATE; + while (isdigit(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.')) + *lp++ = tolower(*cp++); + } + + /* skip leading spaces */ + } + else if (isspace(*cp)) + { + cp++; + continue; - } else { - return -1; - } + /* sign? then special or numeric timezone */ + } + else if ((*cp == '+') || (*cp == '-')) + { + *lp++ = *cp++; + /* soak up leading whitespace */ + while (isspace(*cp)) + cp++; + /* numeric timezone? */ + if (isdigit(*cp)) + { + ftype[nf] = DTK_TZ; + *lp++ = *cp++; + while (isdigit(*cp) || (*cp == ':')) + *lp++ = *cp++; + + /* special? */ + } + else if (isalpha(*cp)) + { + ftype[nf] = DTK_SPECIAL; + *lp++ = tolower(*cp++); + while (isalpha(*cp)) + *lp++ = tolower(*cp++); + + /* otherwise something wrong... */ + } + else + { + return -1; + } + + /* ignore punctuation but use as delimiter */ + } + else if (ispunct(*cp)) + { + cp++; + continue; - /* force in a delimiter */ - *lp++ = '\0'; - nf++; - if (nf > MAXDATEFIELDS) { - return -1; - } + } + else + { + return -1; + } + + /* force in a delimiter */ + *lp++ = '\0'; + nf++; + if (nf > MAXDATEFIELDS) + { + return -1; + } #ifdef DATEDEBUG -printf( "ParseDateTime- set field[%d] to %s type %d\n", (nf-1), field[nf-1], ftype[nf-1]); + printf("ParseDateTime- set field[%d] to %s type %d\n", (nf - 1), field[nf - 1], ftype[nf - 1]); #endif - } + } - *numfields = nf; + *numfields = nf; - return 0; -} /* ParseDateTime() */ + return 0; +} /* ParseDateTime() */ /* DecodeDateTime() * Interpret previously parsed fields for general date and time. * Return 0 if full date, 1 if only time, and -1 if problems. - * External format(s): - * "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>" - * "Fri Feb-7-1997 15:23:27" - * "Feb-7-1997 15:23:27" - * "2-7-1997 15:23:27" - * "1997-2-7 15:23:27" - * "1997.038 15:23:27" (day of year 1-366) - * Also supports input in compact time: - * "970207 152327" - * "97038 152327" + * External format(s): + * "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>" + * "Fri Feb-7-1997 15:23:27" + * "Feb-7-1997 15:23:27" + * "2-7-1997 15:23:27" + * "1997-2-7 15:23:27" + * "1997.038 15:23:27" (day of year 1-366) + * Also supports input in compact time: + * "970207 152327" + * "97038 152327" * * Use the system-provided functions to get the current time zone - * if not specified in the input string. + * if not specified in the input string. * If the date is outside the time_t system-supported time range, - * then assume GMT time zone. - tgl 97/05/27 + * then assume GMT time zone. - tgl 97/05/27 */ int -DecodeDateTime( char *field[], int ftype[], int nf, - int *dtype, struct tm *tm, double *fsec, int *tzp) +DecodeDateTime(char *field[], int ftype[], int nf, + int *dtype, struct tm * tm, double *fsec, int *tzp) { - int fmask = 0, tmask, type; - int i; - int flen, val; - int mer = HR24; - int bc = FALSE; + int fmask = 0, + tmask, + type; + int i; + int flen, + val; + int mer = HR24; + int bc = FALSE; + + *dtype = DTK_DATE; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + *fsec = 0; + tm->tm_isdst = -1; /* don't know daylight savings time status + * apriori */ + if (tzp != NULL) + *tzp = 0; - *dtype = DTK_DATE; - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - *fsec = 0; - tm->tm_isdst = -1; /* don't know daylight savings time status apriori */ - if (tzp != NULL) *tzp = 0; + for (i = 0; i < nf; i++) + { +#ifdef DATEDEBUG + printf("DecodeDateTime- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); +#endif + switch (ftype[i]) + { + case DTK_DATE: + if (DecodeDate(field[i], fmask, &tmask, tm) != 0) + return -1; + break; + + case DTK_TIME: + if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) + return -1; + + /* + * check upper limit on hours; other limits checked in + * DecodeTime() + */ + if (tm->tm_hour > 23) + return -1; + break; + + case DTK_TZ: + if (tzp == NULL) + return -1; + if (DecodeTimezone(field[i], tzp) != 0) + return -1; + tmask = DTK_M(TZ); + break; + + case DTK_NUMBER: + flen = strlen(field[i]); + + if (flen > 4) + { + if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec) != 0) + return -1; + + } + else + { + if (DecodeNumber(flen, field[i], fmask, &tmask, tm, fsec) != 0) + return -1; + } + break; + + case DTK_STRING: + case DTK_SPECIAL: + type = DecodeSpecial(i, field[i], &val); +#ifdef DATEDEBUG + printf("DecodeDateTime- special field[%d] %s type=%d value=%d\n", i, field[i], type, val); +#endif + if (type == IGNORE) + continue; - for (i = 0; i < nf; i++) { + tmask = DTK_M(type); + switch (type) + { + case RESERV: #ifdef DATEDEBUG -printf( "DecodeDateTime- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); + printf("DecodeDateTime- RESERV field %s value is %d\n", field[i], val); #endif - switch (ftype[i]) { - case DTK_DATE: - if (DecodeDate(field[i], fmask, &tmask, tm) != 0) return -1; - break; - - case DTK_TIME: - if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1; - /* check upper limit on hours; other limits checked in DecodeTime() */ - if (tm->tm_hour > 23) return -1; - break; - - case DTK_TZ: - if (tzp == NULL) return -1; - if (DecodeTimezone( field[i], tzp) != 0) return -1; - tmask = DTK_M(TZ); - break; - - case DTK_NUMBER: - flen = strlen(field[i]); - - if (flen > 4) { - if (DecodeNumberField( flen, field[i], fmask, &tmask, tm, fsec) != 0) - return -1; - - } else { - if (DecodeNumber( flen, field[i], fmask, &tmask, tm, fsec) != 0) - return -1; - } - break; - - case DTK_STRING: - case DTK_SPECIAL: - type = DecodeSpecial( i, field[i], &val); -#ifdef DATEDEBUG -printf( "DecodeDateTime- special field[%d] %s type=%d value=%d\n", i, field[i], type, val); -#endif - if (type == IGNORE) continue; - - tmask = DTK_M(type); - switch (type) { - case RESERV: -#ifdef DATEDEBUG -printf( "DecodeDateTime- RESERV field %s value is %d\n", field[i], val); -#endif - switch (val) { - case DTK_NOW: - tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ)); - *dtype = DTK_DATE; - GetCurrentTime(tm); - if (tzp != NULL) *tzp = CTimeZone; - break; - - case DTK_YESTERDAY: - tmask = DTK_DATE_M; - *dtype = DTK_DATE; - GetCurrentTime(tm); - j2date( (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday)-1), - &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - break; - - case DTK_TODAY: - tmask = DTK_DATE_M; - *dtype = DTK_DATE; - GetCurrentTime(tm); - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - break; - - case DTK_TOMORROW: - tmask = DTK_DATE_M; - *dtype = DTK_DATE; - GetCurrentTime(tm); - j2date( (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday)+1), - &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - break; - - case DTK_ZULU: - tmask = (DTK_TIME_M | DTK_M(TZ)); - *dtype = DTK_DATE; - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - if (tzp != NULL) *tzp = 0; - break; + switch (val) + { + case DTK_NOW: + tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ)); + *dtype = DTK_DATE; + GetCurrentTime(tm); + if (tzp != NULL) + *tzp = CTimeZone; + break; + + case DTK_YESTERDAY: + tmask = DTK_DATE_M; + *dtype = DTK_DATE; + GetCurrentTime(tm); + j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1), + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + break; + + case DTK_TODAY: + tmask = DTK_DATE_M; + *dtype = DTK_DATE; + GetCurrentTime(tm); + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + break; + + case DTK_TOMORROW: + tmask = DTK_DATE_M; + *dtype = DTK_DATE; + GetCurrentTime(tm); + j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1), + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + break; + + case DTK_ZULU: + tmask = (DTK_TIME_M | DTK_M(TZ)); + *dtype = DTK_DATE; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + if (tzp != NULL) + *tzp = 0; + break; + + default: + *dtype = val; + } + + break; + + case MONTH: +#ifdef DATEDEBUG + printf("DecodeDateTime- month field %s value is %d\n", field[i], val); +#endif + tm->tm_mon = val; + break; + + /* + * daylight savings time modifier (solves "MET DST" + * syntax) + */ + case DTZMOD: + tmask |= DTK_M(DTZ); + tm->tm_isdst = 1; + if (tzp == NULL) + return -1; + *tzp += val * 60; + break; + + case DTZ: + + /* + * set mask for TZ here _or_ check for DTZ later when + * getting default timezone + */ + tmask |= DTK_M(TZ); + tm->tm_isdst = 1; + if (tzp == NULL) + return -1; + *tzp = val * 60; + break; + + case TZ: + tm->tm_isdst = 0; + if (tzp == NULL) + return -1; + *tzp = val * 60; + break; + + case IGNORE: + break; + + case AMPM: + mer = val; + break; + + case ADBC: + bc = (val == BC); + break; + + case DOW: + tm->tm_wday = val; + break; + + default: + return -1; + } + break; default: - *dtype = val; + return -1; } - break; - - case MONTH: #ifdef DATEDEBUG -printf( "DecodeDateTime- month field %s value is %d\n", field[i], val); + printf("DecodeDateTime- field[%d] %s (%08x/%08x) value is %d\n", + i, field[i], fmask, tmask, val); #endif - tm->tm_mon = val; - break; - /* daylight savings time modifier (solves "MET DST" syntax) */ - case DTZMOD: - tmask |= DTK_M(DTZ); - tm->tm_isdst = 1; - if (tzp == NULL) return -1; - *tzp += val * 60; - break; - - case DTZ: - /* set mask for TZ here _or_ check for DTZ later when getting default timezone */ - tmask |= DTK_M(TZ); - tm->tm_isdst = 1; - if (tzp == NULL) return -1; - *tzp = val * 60; - break; - - case TZ: - tm->tm_isdst = 0; - if (tzp == NULL) return -1; - *tzp = val * 60; - break; - - case IGNORE: - break; - - case AMPM: - mer = val; - break; - - case ADBC: - bc = (val == BC); - break; - - case DOW: - tm->tm_wday = val; - break; - - default: - return -1; - } - break; - - default: - return -1; + if (tmask & fmask) + return -1; + fmask |= tmask; } -#ifdef DATEDEBUG -printf( "DecodeDateTime- field[%d] %s (%08x/%08x) value is %d\n", - i, field[i], fmask, tmask, val); -#endif - - if (tmask & fmask) return -1; - fmask |= tmask; - } + /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */ + if (bc) + tm->tm_year = -(tm->tm_year - 1); - /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */ - if (bc) tm->tm_year = -(tm->tm_year-1); - - if ((mer != HR24) && (tm->tm_hour > 12)) - return -1; - if (mer == PM) tm->tm_hour += 12; + if ((mer != HR24) && (tm->tm_hour > 12)) + return -1; + if (mer == PM) + tm->tm_hour += 12; #ifdef DATEDEBUG -printf( "DecodeDateTime- mask %08x (%08x)", fmask, DTK_DATE_M); -printf( " set y%04d m%02d d%02d", tm->tm_year, tm->tm_mon, tm->tm_mday); -printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); + printf("DecodeDateTime- mask %08x (%08x)", fmask, DTK_DATE_M); + printf(" set y%04d m%02d d%02d", tm->tm_year, tm->tm_mon, tm->tm_mday); + printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M)) - return(((fmask & DTK_TIME_M) == DTK_TIME_M)? 1: -1); + if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M)) + return (((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1); - /* timezone not specified? then find local timezone if possible */ - if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M) - && (tzp != NULL) && (! (fmask & DTK_M(TZ)))) { + /* timezone not specified? then find local timezone if possible */ + if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M) + && (tzp != NULL) && (!(fmask & DTK_M(TZ)))) + { - /* daylight savings time modifier but no standard timezone? then error */ - if (fmask & DTK_M(DTZMOD)) return -1; + /* + * daylight savings time modifier but no standard timezone? then + * error + */ + if (fmask & DTK_M(DTZMOD)) + return -1; - if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) { + if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) + { #ifdef USE_POSIX_TIME - tm->tm_year -= 1900; - tm->tm_mon -= 1; - tm->tm_isdst = -1; - mktime(tm); - tm->tm_year += 1900; - tm->tm_mon += 1; + tm->tm_year -= 1900; + tm->tm_mon -= 1; + tm->tm_isdst = -1; + mktime(tm); + tm->tm_year += 1900; + tm->tm_mon += 1; #ifdef HAVE_INT_TIMEZONE - *tzp = ((tm->tm_isdst > 0)? (timezone - 3600): timezone); + *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); -#else /* !HAVE_INT_TIMEZONE */ - *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ +#else /* !HAVE_INT_TIMEZONE */ + *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ #endif -#else /* !USE_POSIX_TIME */ - *tzp = CTimeZone; +#else /* !USE_POSIX_TIME */ + *tzp = CTimeZone; #endif - } else { - tm->tm_isdst = 0; - *tzp = 0; + } + else + { + tm->tm_isdst = 0; + *tzp = 0; + } } - } - return 0; -} /* DecodeDateTime() */ + return 0; +} /* DecodeDateTime() */ /* DecodeTimeOnly() * Interpret parsed string as time fields only. */ int -DecodeTimeOnly( char *field[], int ftype[], int nf, int *dtype, struct tm *tm, double *fsec) +DecodeTimeOnly(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, double *fsec) { - int fmask, tmask, type; - int i; - int flen, val; - int mer = HR24; - - *dtype = DTK_TIME; - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - tm->tm_isdst = -1; /* don't know daylight savings time status apriori */ + int fmask, + tmask, + type; + int i; + int flen, + val; + int mer = HR24; + + *dtype = DTK_TIME; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + tm->tm_isdst = -1; /* don't know daylight savings time status + * apriori */ - fmask = DTK_DATE_M; + fmask = DTK_DATE_M; - for (i = 0; i < nf; i++) { + for (i = 0; i < nf; i++) + { #ifdef DATEDEBUG -printf( "DecodeTimeOnly- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); + printf("DecodeTimeOnly- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); #endif - switch (ftype[i]) { - case DTK_TIME: - if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1; - break; - - case DTK_NUMBER: - flen = strlen(field[i]); - - if (DecodeNumberField( flen, field[i], fmask, &tmask, tm, fsec) != 0) - return -1; - break; - - case DTK_STRING: - case DTK_SPECIAL: - type = DecodeSpecial( i, field[i], &val); + switch (ftype[i]) + { + case DTK_TIME: + if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) + return -1; + break; + + case DTK_NUMBER: + flen = strlen(field[i]); + + if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec) != 0) + return -1; + break; + + case DTK_STRING: + case DTK_SPECIAL: + type = DecodeSpecial(i, field[i], &val); #ifdef DATEDEBUG -printf( "DecodeTimeOnly- special field[%d] %s type=%d value=%d\n", i, field[i], type, val); + printf("DecodeTimeOnly- special field[%d] %s type=%d value=%d\n", i, field[i], type, val); #endif - if (type == IGNORE) continue; + if (type == IGNORE) + continue; - tmask = DTK_M(type); - switch (type) { - case RESERV: + tmask = DTK_M(type); + switch (type) + { + case RESERV: #ifdef DATEDEBUG -printf( "DecodeTimeOnly- RESERV field %s value is %d\n", field[i], val); + printf("DecodeTimeOnly- RESERV field %s value is %d\n", field[i], val); #endif - switch (val) { - case DTK_NOW: - tmask = DTK_TIME_M; - *dtype = DTK_TIME; - GetCurrentTime(tm); - break; - - case DTK_ZULU: - tmask = (DTK_TIME_M | DTK_M(TZ)); - *dtype = DTK_TIME; - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - tm->tm_isdst = 0; - break; + switch (val) + { + case DTK_NOW: + tmask = DTK_TIME_M; + *dtype = DTK_TIME; + GetCurrentTime(tm); + break; + + case DTK_ZULU: + tmask = (DTK_TIME_M | DTK_M(TZ)); + *dtype = DTK_TIME; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + tm->tm_isdst = 0; + break; + + default: + return -1; + } + + break; + + case IGNORE: + break; + + case AMPM: + mer = val; + break; + + default: + return -1; + } + break; default: - return -1; + return -1; } - break; - - case IGNORE: - break; - - case AMPM: - mer = val; - break; - - default: - return -1; - } - break; - - default: - return -1; - } - - if (tmask & fmask) return -1; - fmask |= tmask; + if (tmask & fmask) + return -1; + fmask |= tmask; #ifdef DATEDEBUG -printf( "DecodeTimeOnly- field[%d] %s value is %d\n", i, field[i], val); + printf("DecodeTimeOnly- field[%d] %s value is %d\n", i, field[i], val); #endif - } + } #ifdef DATEDEBUG -printf( "DecodeTimeOnly- mask %08x (%08x)", fmask, DTK_TIME_M); -printf( " %02d:%02d:%02d (%f)\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); + printf("DecodeTimeOnly- mask %08x (%08x)", fmask, DTK_TIME_M); + printf(" %02d:%02d:%02d (%f)\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); #endif - if ((mer != HR24) && (tm->tm_hour > 12)) - return -1; - if (mer == PM) tm->tm_hour += 12; + if ((mer != HR24) && (tm->tm_hour > 12)) + return -1; + if (mer == PM) + tm->tm_hour += 12; - if ((fmask & DTK_TIME_M) != DTK_TIME_M) - return -1; + if ((fmask & DTK_TIME_M) != DTK_TIME_M) + return -1; - return 0; -} /* DecodeTimeOnly() */ + return 0; +} /* DecodeTimeOnly() */ /* DecodeDate() @@ -2848,390 +3236,472 @@ printf( " %02d:%02d:%02d (%f)\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); * Insist on a complete set of fields. */ static int -DecodeDate(char *str, int fmask, int *tmask, struct tm *tm) +DecodeDate(char *str, int fmask, int *tmask, struct tm * tm) { - double fsec; - - int nf = 0; - int i, len; - int type, val, dmask = 0; - char *field[MAXDATEFIELDS]; - - /* parse this string... */ - while ((*str != '\0') && (nf < MAXDATEFIELDS)) { - /* skip field separators */ - while (! isalnum(*str)) str++; + double fsec; + + int nf = 0; + int i, + len; + int type, + val, + dmask = 0; + char *field[MAXDATEFIELDS]; + + /* parse this string... */ + while ((*str != '\0') && (nf < MAXDATEFIELDS)) + { + /* skip field separators */ + while (!isalnum(*str)) + str++; + + field[nf] = str; + if (isdigit(*str)) + { + while (isdigit(*str)) + str++; + } + else if (isalpha(*str)) + { + while (isalpha(*str)) + str++; + } - field[nf] = str; - if (isdigit(*str)) { - while (isdigit(*str)) str++; - } else if (isalpha(*str)) { - while (isalpha(*str)) str++; + if (*str != '\0') + *str++ = '\0'; + nf++; } - if (*str != '\0') *str++ = '\0'; - nf++; - } - - /* don't allow too many fields */ - if (nf > 3) return -1; - - *tmask = 0; - - /* look first for text fields, since that will be unambiguous month */ - for (i = 0; i < nf; i++) { - if (isalpha(*field[i])) { - type = DecodeSpecial( i, field[i], &val); - if (type == IGNORE) continue; + /* don't allow too many fields */ + if (nf > 3) + return -1; - dmask = DTK_M(type); - switch (type) { - case MONTH: + *tmask = 0; + + /* look first for text fields, since that will be unambiguous month */ + for (i = 0; i < nf; i++) + { + if (isalpha(*field[i])) + { + type = DecodeSpecial(i, field[i], &val); + if (type == IGNORE) + continue; + + dmask = DTK_M(type); + switch (type) + { + case MONTH: #ifdef DATEDEBUG -printf( "DecodeDate- month field %s value is %d\n", field[i], val); + printf("DecodeDate- month field %s value is %d\n", field[i], val); #endif - tm->tm_mon = val; - break; + tm->tm_mon = val; + break; - default: + default: #ifdef DATEDEBUG -printf( "DecodeDate- illegal field %s value is %d\n", field[i], val); + printf("DecodeDate- illegal field %s value is %d\n", field[i], val); #endif - return -1; - } - if (fmask & dmask) return -1; + return -1; + } + if (fmask & dmask) + return -1; - fmask |= dmask; - *tmask |= dmask; + fmask |= dmask; + *tmask |= dmask; - /* mark this field as being completed */ - field[i] = NULL; + /* mark this field as being completed */ + field[i] = NULL; + } } - } - /* now pick up remaining numeric fields */ - for (i = 0; i < nf; i++) { - if (field[i] == NULL) continue; + /* now pick up remaining numeric fields */ + for (i = 0; i < nf; i++) + { + if (field[i] == NULL) + continue; - if ((len = strlen(field[i])) <= 0) - return -1; + if ((len = strlen(field[i])) <= 0) + return -1; - if (DecodeNumber( len, field[i], fmask, &dmask, tm, &fsec) != 0) - return -1; + if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec) != 0) + return -1; - if (fmask & dmask) return -1; + if (fmask & dmask) + return -1; - fmask |= dmask; - *tmask |= dmask; - } + fmask |= dmask; + *tmask |= dmask; + } - return 0; -} /* DecodeDate() */ + return 0; +} /* DecodeDate() */ /* DecodeTime() * Decode time string which includes delimiters. * Only check the lower limit on hours, since this same code - * can be used to represent time spans. + * can be used to represent time spans. */ static int -DecodeTime(char *str, int fmask, int *tmask, struct tm *tm, double *fsec) +DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec) { - char *cp; + char *cp; - *tmask = DTK_TIME_M; + *tmask = DTK_TIME_M; - tm->tm_hour = strtol( str, &cp, 10); - if (*cp != ':') return -1; - str = cp+1; - tm->tm_min = strtol( str, &cp, 10); - if (*cp == '\0') { - tm->tm_sec = 0; - *fsec = 0; + tm->tm_hour = strtol(str, &cp, 10); + if (*cp != ':') + return -1; + str = cp + 1; + tm->tm_min = strtol(str, &cp, 10); + if (*cp == '\0') + { + tm->tm_sec = 0; + *fsec = 0; - } else if (*cp != ':') { - return -1; + } + else if (*cp != ':') + { + return -1; - } else { - str = cp+1; - tm->tm_sec = strtol( str, &cp, 10); - if (*cp == '\0') { - *fsec = 0; - } else if (*cp == '.') { - str = cp; - *fsec = strtod( str, &cp); - if (cp == str) return -1; - } else { - return -1; } - } + else + { + str = cp + 1; + tm->tm_sec = strtol(str, &cp, 10); + if (*cp == '\0') + { + *fsec = 0; + } + else if (*cp == '.') + { + str = cp; + *fsec = strtod(str, &cp); + if (cp == str) + return -1; + } + else + { + return -1; + } + } - /* do a sanity check */ - if ((tm->tm_hour < 0) - || (tm->tm_min < 0) || (tm->tm_min > 59) - || (tm->tm_sec < 0) || (tm->tm_sec > 59)) return -1; + /* do a sanity check */ + if ((tm->tm_hour < 0) + || (tm->tm_min < 0) || (tm->tm_min > 59) + || (tm->tm_sec < 0) || (tm->tm_sec > 59)) + return -1; - return 0; -} /* DecodeTime() */ + return 0; +} /* DecodeTime() */ /* DecodeNumber() * Interpret numeric field as a date value in context. */ static int -DecodeNumber( int flen, char *str, int fmask, int *tmask, struct tm *tm, double *fsec) +DecodeNumber(int flen, char *str, int fmask, int *tmask, struct tm * tm, double *fsec) { - int val; - char *cp; + int val; + char *cp; - *tmask = 0; + *tmask = 0; - val = strtol( str, &cp, 10); - if (cp == str) return -1; - if (*cp == '.') { - *fsec = strtod( cp, &cp); - if (*cp != '\0') return -1; - } + val = strtol(str, &cp, 10); + if (cp == str) + return -1; + if (*cp == '.') + { + *fsec = strtod(cp, &cp); + if (*cp != '\0') + return -1; + } #ifdef DATEDEBUG -printf( "DecodeNumber- %s is %d fmask=%08x tmask=%08x\n", str, val, fmask, *tmask); + printf("DecodeNumber- %s is %d fmask=%08x tmask=%08x\n", str, val, fmask, *tmask); #endif - /* enough digits to be unequivocal year? */ - if (flen == 4) { + /* enough digits to be unequivocal year? */ + if (flen == 4) + { #ifdef DATEDEBUG -printf( "DecodeNumber- match %d (%s) as year\n", val, str); + printf("DecodeNumber- match %d (%s) as year\n", val, str); #endif - *tmask = DTK_M(YEAR); - - /* already have a year? then see if we can substitute... */ - if (fmask & DTK_M(YEAR)) { - if ((!(fmask & DTK_M(DAY))) - && ((tm->tm_year >= 1) && (tm->tm_year <= 31))) { + *tmask = DTK_M(YEAR); + + /* already have a year? then see if we can substitute... */ + if (fmask & DTK_M(YEAR)) + { + if ((!(fmask & DTK_M(DAY))) + && ((tm->tm_year >= 1) && (tm->tm_year <= 31))) + { #ifdef DATEDEBUG -printf( "DecodeNumber- misidentified year previously; swap with day %d\n", tm->tm_mday); + printf("DecodeNumber- misidentified year previously; swap with day %d\n", tm->tm_mday); #endif - tm->tm_mday = tm->tm_year; - *tmask = DTK_M(DAY); - } - } - - tm->tm_year = val; + tm->tm_mday = tm->tm_year; + *tmask = DTK_M(DAY); + } + } - /* special case day of year? */ - } else if ((flen == 3) && (fmask & DTK_M(YEAR)) - && ((val >= 1) && (val <= 366))) { - *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY)); - tm->tm_yday = val; - j2date((date2j(tm->tm_year,1,1)+tm->tm_yday-1), - &tm->tm_year,&tm->tm_mon,&tm->tm_mday); + tm->tm_year = val; - /* already have year? then could be month */ - } else if ((fmask & DTK_M(YEAR)) && (! (fmask & DTK_M(MONTH))) - && ((val >= 1) && (val <= 12))) { + /* special case day of year? */ + } + else if ((flen == 3) && (fmask & DTK_M(YEAR)) + && ((val >= 1) && (val <= 366))) + { + *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY)); + tm->tm_yday = val; + j2date((date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1), + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + + /* already have year? then could be month */ + } + else if ((fmask & DTK_M(YEAR)) && (!(fmask & DTK_M(MONTH))) + && ((val >= 1) && (val <= 12))) + { #ifdef DATEDEBUG -printf( "DecodeNumber- match %d (%s) as month\n", val, str); + printf("DecodeNumber- match %d (%s) as month\n", val, str); #endif - *tmask = DTK_M(MONTH); - tm->tm_mon = val; + *tmask = DTK_M(MONTH); + tm->tm_mon = val; - /* no year and EuroDates enabled? then could be day */ - } else if ((EuroDates || (fmask & DTK_M(MONTH))) - && (!(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY))) - && ((val >= 1) && (val <= 31))) { + /* no year and EuroDates enabled? then could be day */ + } + else if ((EuroDates || (fmask & DTK_M(MONTH))) + && (!(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY))) + && ((val >= 1) && (val <= 31))) + { #ifdef DATEDEBUG -printf( "DecodeNumber- match %d (%s) as day\n", val, str); + printf("DecodeNumber- match %d (%s) as day\n", val, str); #endif - *tmask = DTK_M(DAY); - tm->tm_mday = val; + *tmask = DTK_M(DAY); + tm->tm_mday = val; - } else if ((! (fmask & DTK_M(MONTH))) - && ((val >= 1) && (val <= 12))) { + } + else if ((!(fmask & DTK_M(MONTH))) + && ((val >= 1) && (val <= 12))) + { #ifdef DATEDEBUG -printf( "DecodeNumber- (2) match %d (%s) as month\n", val, str); + printf("DecodeNumber- (2) match %d (%s) as month\n", val, str); #endif - *tmask = DTK_M(MONTH); - tm->tm_mon = val; + *tmask = DTK_M(MONTH); + tm->tm_mon = val; - } else if ((! (fmask & DTK_M(DAY))) - && ((val >= 1) && (val <= 31))) { + } + else if ((!(fmask & DTK_M(DAY))) + && ((val >= 1) && (val <= 31))) + { #ifdef DATEDEBUG -printf( "DecodeNumber- (2) match %d (%s) as day\n", val, str); + printf("DecodeNumber- (2) match %d (%s) as day\n", val, str); #endif - *tmask = DTK_M(DAY); - tm->tm_mday = val; + *tmask = DTK_M(DAY); + tm->tm_mday = val; - } else if (! (fmask & DTK_M(YEAR))) { + } + else if (!(fmask & DTK_M(YEAR))) + { #ifdef DATEDEBUG -printf( "DecodeNumber- (2) match %d (%s) as year\n", val, str); + printf("DecodeNumber- (2) match %d (%s) as year\n", val, str); #endif - *tmask = DTK_M(YEAR); - tm->tm_year = val; - if (tm->tm_year < 70) { - tm->tm_year += 2000; - } else if (tm->tm_year < 100) { - tm->tm_year += 1900; - } + *tmask = DTK_M(YEAR); + tm->tm_year = val; + if (tm->tm_year < 70) + { + tm->tm_year += 2000; + } + else if (tm->tm_year < 100) + { + tm->tm_year += 1900; + } - } else { - return -1; - } + } + else + { + return -1; + } - return 0; -} /* DecodeNumber() */ + return 0; +} /* DecodeNumber() */ /* DecodeNumberField() * Interpret numeric string as a concatenated date field. */ static int -DecodeNumberField( int len, char *str, int fmask, int *tmask, struct tm *tm, double *fsec) +DecodeNumberField(int len, char *str, int fmask, int *tmask, struct tm * tm, double *fsec) { - char *cp; + char *cp; - /* yyyymmdd? */ - if (len == 8) { + /* yyyymmdd? */ + if (len == 8) + { #ifdef DATEDEBUG -printf( "DecodeNumberField- %s is 8 character date fmask=%08x tmask=%08x\n", str, fmask, *tmask); + printf("DecodeNumberField- %s is 8 character date fmask=%08x tmask=%08x\n", str, fmask, *tmask); #endif - *tmask = DTK_DATE_M; + *tmask = DTK_DATE_M; - tm->tm_mday = atoi(str+6); - *(str+6) = '\0'; - tm->tm_mon = atoi(str+4); - *(str+4) = '\0'; - tm->tm_year = atoi(str+0); + tm->tm_mday = atoi(str + 6); + *(str + 6) = '\0'; + tm->tm_mon = atoi(str + 4); + *(str + 4) = '\0'; + tm->tm_year = atoi(str + 0); - /* yymmdd or hhmmss? */ - } else if (len == 6) { + /* yymmdd or hhmmss? */ + } + else if (len == 6) + { #ifdef DATEDEBUG -printf( "DecodeNumberField- %s is 6 characters fmask=%08x tmask=%08x\n", str, fmask, *tmask); + printf("DecodeNumberField- %s is 6 characters fmask=%08x tmask=%08x\n", str, fmask, *tmask); #endif - if (fmask & DTK_DATE_M) { + if (fmask & DTK_DATE_M) + { #ifdef DATEDEBUG -printf( "DecodeNumberField- %s is time field fmask=%08x tmask=%08x\n", str, fmask, *tmask); + printf("DecodeNumberField- %s is time field fmask=%08x tmask=%08x\n", str, fmask, *tmask); #endif - *tmask = DTK_TIME_M; - tm->tm_sec = atoi(str+4); - *(str+4) = '\0'; - tm->tm_min = atoi(str+2); - *(str+2) = '\0'; - tm->tm_hour = atoi(str+0); + *tmask = DTK_TIME_M; + tm->tm_sec = atoi(str + 4); + *(str + 4) = '\0'; + tm->tm_min = atoi(str + 2); + *(str + 2) = '\0'; + tm->tm_hour = atoi(str + 0); - } else { + } + else + { #ifdef DATEDEBUG -printf( "DecodeNumberField- %s is date field fmask=%08x tmask=%08x\n", str, fmask, *tmask); + printf("DecodeNumberField- %s is date field fmask=%08x tmask=%08x\n", str, fmask, *tmask); #endif - *tmask = DTK_DATE_M; - tm->tm_mday = atoi(str+4); - *(str+4) = '\0'; - tm->tm_mon = atoi(str+2); - *(str+2) = '\0'; - tm->tm_year = atoi(str+0); - } + *tmask = DTK_DATE_M; + tm->tm_mday = atoi(str + 4); + *(str + 4) = '\0'; + tm->tm_mon = atoi(str + 2); + *(str + 2) = '\0'; + tm->tm_year = atoi(str + 0); + } - } else if (strchr(str,'.') != NULL) { + } + else if (strchr(str, '.') != NULL) + { #ifdef DATEDEBUG -printf( "DecodeNumberField- %s is time field fmask=%08x tmask=%08x\n", str, fmask, *tmask); + printf("DecodeNumberField- %s is time field fmask=%08x tmask=%08x\n", str, fmask, *tmask); #endif - *tmask = DTK_TIME_M; - tm->tm_sec = strtod( (str+4), &cp); - if (cp == (str+4)) return -1; - if (*cp == '.') { - *fsec = strtod( cp, NULL); - } - *(str+4) = '\0'; - tm->tm_min = strtod( (str+2), &cp); - *(str+2) = '\0'; - tm->tm_hour = strtod( (str+0), &cp); + *tmask = DTK_TIME_M; + tm->tm_sec = strtod((str + 4), &cp); + if (cp == (str + 4)) + return -1; + if (*cp == '.') + { + *fsec = strtod(cp, NULL); + } + *(str + 4) = '\0'; + tm->tm_min = strtod((str + 2), &cp); + *(str + 2) = '\0'; + tm->tm_hour = strtod((str + 0), &cp); - } else { - return -1; - } + } + else + { + return -1; + } - return 0; -} /* DecodeNumberField() */ + return 0; +} /* DecodeNumberField() */ /* DecodeTimezone() * Interpret string as a numeric timezone. */ static int -DecodeTimezone( char *str, int *tzp) +DecodeTimezone(char *str, int *tzp) { - int tz; - int hr, min; - char *cp; - int len; + int tz; + int hr, + min; + char *cp; + int len; - /* assume leading character is "+" or "-" */ - hr = strtol( (str+1), &cp, 10); + /* assume leading character is "+" or "-" */ + hr = strtol((str + 1), &cp, 10); - /* explicit delimiter? */ - if (*cp == ':') { - min = strtol( (cp+1), &cp, 10); + /* explicit delimiter? */ + if (*cp == ':') + { + min = strtol((cp + 1), &cp, 10); - /* otherwise, might have run things together... */ - } else if ((*cp == '\0') && ((len = strlen(str)) > 3)) { - min = strtol( (str+len-2), &cp, 10); - *(str+len-2) = '\0'; - hr = strtol( (str+1), &cp, 10); + /* otherwise, might have run things together... */ + } + else if ((*cp == '\0') && ((len = strlen(str)) > 3)) + { + min = strtol((str + len - 2), &cp, 10); + *(str + len - 2) = '\0'; + hr = strtol((str + 1), &cp, 10); - } else { - min = 0; - } + } + else + { + min = 0; + } - tz = (hr*60+min)*60; - if (*str == '-') tz = -tz; + tz = (hr * 60 + min) * 60; + if (*str == '-') + tz = -tz; - *tzp = -tz; - return( *cp != '\0'); -} /* DecodeTimezone() */ + *tzp = -tz; + return (*cp != '\0'); +} /* DecodeTimezone() */ /* DecodeSpecial() * Decode text string using lookup table. * Implement a cache lookup since it is likely that dates - * will be related in format. + * will be related in format. */ static int DecodeSpecial(int field, char *lowtoken, int *val) { - int type; - datetkn *tp; + int type; + datetkn *tp; #if USE_DATE_CACHE - if ((datecache[field] != NULL) - && (strncmp(lowtoken,datecache[field]->token,TOKMAXLEN) == 0)) { - tp = datecache[field]; - } else { + if ((datecache[field] != NULL) + && (strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0)) + { + tp = datecache[field]; + } + else + { #endif - tp = datebsearch(lowtoken, datetktbl, szdatetktbl); + tp = datebsearch(lowtoken, datetktbl, szdatetktbl); #if USE_DATE_CACHE - } - datecache[field] = tp; -#endif - if (tp == NULL) { - type = IGNORE; - *val = 0; - } else { - type = tp->type; - switch (type) { - case TZ: - case DTZ: - case DTZMOD: - *val = FROMVAL(tp); - break; + } + datecache[field] = tp; +#endif + if (tp == NULL) + { + type = IGNORE; + *val = 0; + } + else + { + type = tp->type; + switch (type) + { + case TZ: + case DTZ: + case DTZMOD: + *val = FROMVAL(tp); + break; - default: - *val = tp->value; - break; + default: + *val = tp->value; + break; + } } - } - return(type); -} /* DecodeSpecial() */ + return (type); +} /* DecodeSpecial() */ /* DecodeDateDelta() @@ -3239,212 +3709,239 @@ DecodeSpecial(int field, char *lowtoken, int *val) * Return 0 if decoded and -1 if problems. * * If code is changed to read fields from first to last, - * then use READ_FORWARD-bracketed code to allow sign - * to persist to subsequent unsigned fields. + * then use READ_FORWARD-bracketed code to allow sign + * to persist to subsequent unsigned fields. */ int -DecodeDateDelta( char *field[], int ftype[], int nf, int *dtype, struct tm *tm, double *fsec) +DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, double *fsec) { - int is_before = FALSE; + int is_before = FALSE; + #if READ_FORWARD - int is_neg = FALSE; + int is_neg = FALSE; + #endif - int fmask = 0, tmask, type; - int i, ii; - int flen, val; - char *cp; - double sec; + int fmask = 0, + tmask, + type; + int i, + ii; + int flen, + val; + char *cp; + double sec; - *dtype = DTK_DELTA; + *dtype = DTK_DELTA; - type = SECOND; - tm->tm_year = 0; - tm->tm_mon = 0; - tm->tm_mday = 0; - tm->tm_hour = 0; - tm->tm_min = 0; - tm->tm_sec = 0; - *fsec = 0; + type = SECOND; + tm->tm_year = 0; + tm->tm_mon = 0; + tm->tm_mday = 0; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + *fsec = 0; - /* read through list forwards to pick up initial time fields, if any */ - for (ii = 0; ii < nf; ii++) { + /* read through list forwards to pick up initial time fields, if any */ + for (ii = 0; ii < nf; ii++) + { #ifdef DATEDEBUG -printf( "DecodeDateDelta- field[%d] is %s (type %d)\n", ii, field[ii], ftype[ii]); + printf("DecodeDateDelta- field[%d] is %s (type %d)\n", ii, field[ii], ftype[ii]); #endif - if (ftype[ii] == DTK_TIME) { - if (DecodeTime(field[ii], fmask, &tmask, tm, fsec) != 0) return -1; - fmask |= tmask; + if (ftype[ii] == DTK_TIME) + { + if (DecodeTime(field[ii], fmask, &tmask, tm, fsec) != 0) + return -1; + fmask |= tmask; - } else { - break; + } + else + { + break; + } } - } - /* read through remaining list backwards to pick up units before values */ - for (i = nf-1; i >= ii; i--) { + /* + * read through remaining list backwards to pick up units before + * values + */ + for (i = nf - 1; i >= ii; i--) + { #ifdef DATEDEBUG -printf( "DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); + printf("DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); #endif - switch (ftype[i]) { - case DTK_TIME: - /* already read in forward-scan above so return error */ + switch (ftype[i]) + { + case DTK_TIME: + /* already read in forward-scan above so return error */ #if FALSE - if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1; + if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) + return -1; #endif - return -1; - break; + return -1; + break; - case DTK_TZ: /* timezone is a token with a leading sign character */ + case DTK_TZ: /* timezone is a token with a leading sign + * character */ #if READ_FORWARD - is_neg = (*field[i] == '-'); + is_neg = (*field[i] == '-'); #endif - case DTK_NUMBER: - val = strtol( field[i], &cp, 10); + case DTK_NUMBER: + val = strtol(field[i], &cp, 10); #if READ_FORWARD - if (is_neg && (val > 0)) val = -val; -#endif - if (*cp == '.') { - *fsec = strtod( cp, NULL); - if (val < 0) *fsec = - (*fsec); - } - flen = strlen(field[i]); - tmask = 0; /* DTK_M(type); */ - - switch (type) { - case DTK_MICROSEC: - *fsec += (val * 1e-6); - break; - - case DTK_MILLISEC: - *fsec += (val * 1e-3); - break; - - case DTK_SECOND: - tm->tm_sec += val; - tmask = DTK_M(SECOND); - break; - - case DTK_MINUTE: - tm->tm_min += val; - tmask = DTK_M(MINUTE); - break; - - case DTK_HOUR: - tm->tm_hour += val; - tmask = DTK_M(HOUR); - break; - - case DTK_DAY: - tm->tm_mday += val; - tmask = ((fmask & DTK_M(DAY))? 0: DTK_M(DAY)); - break; - - case DTK_WEEK: - tm->tm_mday += val*7; - tmask = ((fmask & DTK_M(DAY))? 0: DTK_M(DAY)); - break; - - case DTK_MONTH: - tm->tm_mon += val; - tmask = DTK_M(MONTH); - break; - - case DTK_YEAR: - tm->tm_year += val; - tmask = ((fmask & DTK_M(YEAR))? 0: DTK_M(YEAR)); - break; - - case DTK_DECADE: - tm->tm_year += val*10; - tmask = ((fmask & DTK_M(YEAR))? 0: DTK_M(YEAR)); - break; - - case DTK_CENTURY: - tm->tm_year += val*100; - tmask = ((fmask & DTK_M(YEAR))? 0: DTK_M(YEAR)); - break; - - case DTK_MILLENIUM: - tm->tm_year += val*1000; - tmask = ((fmask & DTK_M(YEAR))? 0: DTK_M(YEAR)); - break; - - default: - return -1; - } - break; - - case DTK_STRING: - case DTK_SPECIAL: - type = DecodeUnits( i, field[i], &val); + if (is_neg && (val > 0)) + val = -val; +#endif + if (*cp == '.') + { + *fsec = strtod(cp, NULL); + if (val < 0) + *fsec = -(*fsec); + } + flen = strlen(field[i]); + tmask = 0; /* DTK_M(type); */ + + switch (type) + { + case DTK_MICROSEC: + *fsec += (val * 1e-6); + break; + + case DTK_MILLISEC: + *fsec += (val * 1e-3); + break; + + case DTK_SECOND: + tm->tm_sec += val; + tmask = DTK_M(SECOND); + break; + + case DTK_MINUTE: + tm->tm_min += val; + tmask = DTK_M(MINUTE); + break; + + case DTK_HOUR: + tm->tm_hour += val; + tmask = DTK_M(HOUR); + break; + + case DTK_DAY: + tm->tm_mday += val; + tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY)); + break; + + case DTK_WEEK: + tm->tm_mday += val * 7; + tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY)); + break; + + case DTK_MONTH: + tm->tm_mon += val; + tmask = DTK_M(MONTH); + break; + + case DTK_YEAR: + tm->tm_year += val; + tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); + break; + + case DTK_DECADE: + tm->tm_year += val * 10; + tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); + break; + + case DTK_CENTURY: + tm->tm_year += val * 100; + tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); + break; + + case DTK_MILLENIUM: + tm->tm_year += val * 1000; + tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); + break; + + default: + return -1; + } + break; + + case DTK_STRING: + case DTK_SPECIAL: + type = DecodeUnits(i, field[i], &val); #ifdef DATEDEBUG -printf( "DecodeDateDelta- special field[%d] %s type=%d value=%d\n", i, field[i], type, val); + printf("DecodeDateDelta- special field[%d] %s type=%d value=%d\n", i, field[i], type, val); #endif - if (type == IGNORE) continue; + if (type == IGNORE) + continue; - tmask = 0; /* DTK_M(type); */ - switch (type) { - case UNITS: + tmask = 0; /* DTK_M(type); */ + switch (type) + { + case UNITS: #ifdef DATEDEBUG -printf( "DecodeDateDelta- UNITS field %s value is %d\n", field[i], val); + printf("DecodeDateDelta- UNITS field %s value is %d\n", field[i], val); #endif - type = val; - break; + type = val; + break; - case AGO: - is_before = TRUE; - type = val; - break; + case AGO: + is_before = TRUE; + type = val; + break; - case RESERV: - tmask = (DTK_DATE_M || DTK_TIME_M); - *dtype = val; - break; + case RESERV: + tmask = (DTK_DATE_M || DTK_TIME_M); + *dtype = val; + break; - default: - return -1; - } - break; + default: + return -1; + } + break; - default: - return -1; - } + default: + return -1; + } #ifdef DATEDEBUG -printf( "DecodeDateDelta- (%08x/%08x) field[%d] %s value is %d\n", - fmask, tmask, i, field[i], val); + printf("DecodeDateDelta- (%08x/%08x) field[%d] %s value is %d\n", + fmask, tmask, i, field[i], val); #endif - if (tmask & fmask) return -1; - fmask |= tmask; - } + if (tmask & fmask) + return -1; + fmask |= tmask; + } - if (*fsec != 0) { - TMODULO(*fsec,sec,1); - tm->tm_sec += sec; - } + if (*fsec != 0) + { + TMODULO(*fsec, sec, 1); + tm->tm_sec += sec; + } - if (is_before) { - *fsec = -(*fsec); - tm->tm_sec = -(tm->tm_sec); - tm->tm_min = -(tm->tm_min); - tm->tm_hour = -(tm->tm_hour); - tm->tm_mday = -(tm->tm_mday); - tm->tm_mon = -(tm->tm_mon); - tm->tm_year = -(tm->tm_year); - } + if (is_before) + { + *fsec = -(*fsec); + tm->tm_sec = -(tm->tm_sec); + tm->tm_min = -(tm->tm_min); + tm->tm_hour = -(tm->tm_hour); + tm->tm_mday = -(tm->tm_mday); + tm->tm_mon = -(tm->tm_mon); + tm->tm_year = -(tm->tm_year); + } #ifdef DATEDEBUG -printf( "DecodeDateDelta- mask %08x (%08x)", fmask, DTK_DATE_M); -printf( " set y%04d m%02d d%02d", tm->tm_year, tm->tm_mon, tm->tm_mday); -printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); + printf("DecodeDateDelta- mask %08x (%08x)", fmask, DTK_DATE_M); + printf(" set y%04d m%02d d%02d", tm->tm_year, tm->tm_mon, tm->tm_mday); + printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - /* ensure that at least one time field has been found */ - return((fmask != 0)? 0: -1); -} /* DecodeDateDelta() */ + /* ensure that at least one time field has been found */ + return ((fmask != 0) ? 0 : -1); +} /* DecodeDateDelta() */ /* DecodeUnits() @@ -3454,34 +3951,43 @@ printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); static int DecodeUnits(int field, char *lowtoken, int *val) { - int type; - datetkn *tp; + int type; + datetkn *tp; #if USE_DATE_CACHE - if ((deltacache[field] != NULL) - && (strncmp(lowtoken,deltacache[field]->token,TOKMAXLEN) == 0)) { - tp = deltacache[field]; - } else { + if ((deltacache[field] != NULL) + && (strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0)) + { + tp = deltacache[field]; + } + else + { #endif - tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl); + tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl); #if USE_DATE_CACHE - } - deltacache[field] = tp; + } + deltacache[field] = tp; #endif - if (tp == NULL) { - type = IGNORE; - *val = 0; - } else { - type = tp->type; - if ((type == TZ) || (type == DTZ)) { - *val = FROMVAL(tp); - } else { - *val = tp->value; + if (tp == NULL) + { + type = IGNORE; + *val = 0; + } + else + { + type = tp->type; + if ((type == TZ) || (type == DTZ)) + { + *val = FROMVAL(tp); + } + else + { + *val = tp->value; + } } - } - return(type); -} /* DecodeUnits() */ + return (type); +} /* DecodeUnits() */ /* datebsearch() @@ -3489,25 +3995,28 @@ DecodeUnits(int field, char *lowtoken, int *val) * is WAY faster than the generic bsearch(). */ static datetkn * -datebsearch(char *key, datetkn *base, unsigned int nel) +datebsearch(char *key, datetkn * base, unsigned int nel) { - register datetkn *last = base + nel - 1, *position; - register int result; - - while (last >= base) { - position = base + ((last - base) >> 1); - result = key[0] - position->token[0]; - if (result == 0) { - result = strncmp(key, position->token, TOKMAXLEN); - if (result == 0) - return position; + register datetkn *last = base + nel - 1, + *position; + register int result; + + while (last >= base) + { + position = base + ((last - base) >> 1); + result = key[0] - position->token[0]; + if (result == 0) + { + result = strncmp(key, position->token, TOKMAXLEN); + if (result == 0) + return position; + } + if (result < 0) + last = position - 1; + else + base = position + 1; } - if (result < 0) - last = position - 1; - else - base = position + 1; - } - return NULL; + return NULL; } @@ -3517,373 +4026,466 @@ datebsearch(char *key, datetkn *base, unsigned int nel) static int EncodeSpecialDateTime(DateTime dt, char *str) { - if (DATETIME_IS_RESERVED(dt)) { - if (DATETIME_IS_INVALID(dt)) { - strcpy( str, INVALID); + if (DATETIME_IS_RESERVED(dt)) + { + if (DATETIME_IS_INVALID(dt)) + { + strcpy(str, INVALID); - } else if (DATETIME_IS_NOBEGIN(dt)) { - strcpy( str, EARLY); + } + else if (DATETIME_IS_NOBEGIN(dt)) + { + strcpy(str, EARLY); - } else if (DATETIME_IS_NOEND(dt)) { - strcpy( str, LATE); + } + else if (DATETIME_IS_NOEND(dt)) + { + strcpy(str, LATE); - } else if (DATETIME_IS_CURRENT(dt)) { - strcpy( str, DCURRENT); + } + else if (DATETIME_IS_CURRENT(dt)) + { + strcpy(str, DCURRENT); - } else if (DATETIME_IS_EPOCH(dt)) { - strcpy( str, EPOCH); + } + else if (DATETIME_IS_EPOCH(dt)) + { + strcpy(str, EPOCH); - } else { + } + else + { #ifdef DATEDEBUG -printf( "EncodeSpecialDateTime- unrecognized date\n"); + printf("EncodeSpecialDateTime- unrecognized date\n"); #endif - strcpy( str, INVALID); + strcpy(str, INVALID); + } + return (TRUE); } - return(TRUE); - } - return(FALSE); -} /* EncodeSpecialDateTime() */ + return (FALSE); +} /* EncodeSpecialDateTime() */ /* EncodeDateOnly() * Encode date as local time. */ -int EncodeDateOnly(struct tm *tm, int style, char *str) +int +EncodeDateOnly(struct tm * tm, int style, char *str) { #if FALSE - int day; + int day; + #endif - if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) - return -1; + if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) + return -1; - /* compatible with ISO date formats */ - if (style == USE_ISO_DATES) { - if (tm->tm_year > 0) { - sprintf( str, "%04d-%02d-%02d", - tm->tm_year, tm->tm_mon, tm->tm_mday); + /* compatible with ISO date formats */ + if (style == USE_ISO_DATES) + { + if (tm->tm_year > 0) + { + sprintf(str, "%04d-%02d-%02d", + tm->tm_year, tm->tm_mon, tm->tm_mday); - } else { - sprintf( str, "%04d-%02d-%02d %s", - -(tm->tm_year-1), tm->tm_mon, tm->tm_mday, "BC"); - } + } + else + { + sprintf(str, "%04d-%02d-%02d %s", + -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC"); + } - /* compatible with Oracle/Ingres date formats */ - } else if (style == USE_SQL_DATES) { - if (EuroDates) { - sprintf( str, "%02d/%02d", tm->tm_mday, tm->tm_mon); - } else { - sprintf( str, "%02d/%02d", tm->tm_mon, tm->tm_mday); + /* compatible with Oracle/Ingres date formats */ } - if (tm->tm_year > 0) { - sprintf( (str+5), "/%04d", tm->tm_year); + else if (style == USE_SQL_DATES) + { + if (EuroDates) + { + sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); + } + else + { + sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); + } + if (tm->tm_year > 0) + { + sprintf((str + 5), "/%04d", tm->tm_year); - } else { - sprintf( (str+5), "/%04d %s", -(tm->tm_year-1), "BC"); - } + } + else + { + sprintf((str + 5), "/%04d %s", -(tm->tm_year - 1), "BC"); + } - /* backward-compatible with traditional Postgres abstime dates */ - } else { /* if (style == USE_POSTGRES_DATES) */ + /* backward-compatible with traditional Postgres abstime dates */ + } + else + { /* if (style == USE_POSTGRES_DATES) */ #if FALSE - day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday); + day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); #ifdef DATEDEBUG -printf( "EncodeDateOnly- day is %d\n", day); + printf("EncodeDateOnly- day is %d\n", day); #endif - tm->tm_wday = j2day( day); + tm->tm_wday = j2day(day); - strncpy( str, days[tm->tm_wday], 3); - strcpy( (str+3), " "); + strncpy(str, days[tm->tm_wday], 3); + strcpy((str + 3), " "); - if (EuroDates) { - sprintf( (str+4), "%02d %3s", tm->tm_mday, months[tm->tm_mon-1]); - } else { - sprintf( (str+4), "%3s %02d", months[tm->tm_mon-1], tm->tm_mday); - } - if (tm->tm_year > 0) { - sprintf( (str+10), " %04d", tm->tm_year); + if (EuroDates) + { + sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]); + } + else + { + sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday); + } + if (tm->tm_year > 0) + { + sprintf((str + 10), " %04d", tm->tm_year); - } else { - sprintf( (str+10), " %04d %s", -(tm->tm_year-1), "BC"); - } + } + else + { + sprintf((str + 10), " %04d %s", -(tm->tm_year - 1), "BC"); + } #endif - /* traditional date-only style for Postgres */ - if (EuroDates) { - sprintf( str, "%02d-%02d", tm->tm_mday, tm->tm_mon); - } else { - sprintf( str, "%02d-%02d", tm->tm_mon, tm->tm_mday); - } - if (tm->tm_year > 0) { - sprintf( (str+5), "-%04d", tm->tm_year); + /* traditional date-only style for Postgres */ + if (EuroDates) + { + sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon); + } + else + { + sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday); + } + if (tm->tm_year > 0) + { + sprintf((str + 5), "-%04d", tm->tm_year); - } else { - sprintf( (str+5), "-%04d %s", -(tm->tm_year-1), "BC"); + } + else + { + sprintf((str + 5), "-%04d %s", -(tm->tm_year - 1), "BC"); + } } - } #ifdef DATEDEBUG -printf( "EncodeDateOnly- date result is %s\n", str); + printf("EncodeDateOnly- date result is %s\n", str); #endif - return(TRUE); -} /* EncodeDateOnly() */ + return (TRUE); +} /* EncodeDateOnly() */ /* EncodeTimeOnly() * Encode time fields only. */ -int EncodeTimeOnly(struct tm *tm, double fsec, int style, char *str) +int +EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str) { - double sec; + double sec; - if ((tm->tm_hour < 0) || (tm->tm_hour > 24)) - return -1; + if ((tm->tm_hour < 0) || (tm->tm_hour > 24)) + return -1; - sec = (tm->tm_sec + fsec); + sec = (tm->tm_sec + fsec); - sprintf( str, "%02d:%02d:", tm->tm_hour, tm->tm_min); - sprintf( (str+6), ((fsec != 0)? "%05.2f": "%02.0f"), sec); + sprintf(str, "%02d:%02d:", tm->tm_hour, tm->tm_min); + sprintf((str + 6), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec); #ifdef DATEDEBUG -printf( "EncodeTimeOnly- time result is %s\n", str); + printf("EncodeTimeOnly- time result is %s\n", str); #endif - return(TRUE); -} /* EncodeTimeOnly() */ + return (TRUE); +} /* EncodeTimeOnly() */ /* EncodeDateTime() * Encode date and time interpreted as local time. */ -int EncodeDateTime(struct tm *tm, double fsec, int *tzp, char **tzn, int style, char *str) +int +EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str) { - int day, hour, min; - double sec; + int day, + hour, + min; + double sec; - if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) - return -1; + if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) + return -1; - sec = (tm->tm_sec + fsec); + sec = (tm->tm_sec + fsec); #ifdef DATEDEBUG #ifdef USE_POSIX_TIME #ifdef HAVE_INT_TIMEZONE -printf( "EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n", - *tzn, tzname[0], *tzp, CTimeZone, tm->tm_isdst, CDayLight); + printf("EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n", + *tzn, tzname[0], *tzp, CTimeZone, tm->tm_isdst, CDayLight); #else -printf( "EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n", - *tzn, tm->tm_zone, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight); + printf("EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n", + *tzn, tm->tm_zone, (-tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight); #endif #else -printf( "EncodeDateTime- timezone is %s (%s); offset is %d; daylight is %d\n", - *tzn, CTZName, CTimeZone, CDayLight); + printf("EncodeDateTime- timezone is %s (%s); offset is %d; daylight is %d\n", + *tzn, CTZName, CTimeZone, CDayLight); #endif #endif - /* compatible with ISO date formats */ - if (style == USE_ISO_DATES) { - if (tm->tm_year > 0) { - sprintf( str, "%04d-%02d-%02d %02d:%02d:", - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); - sprintf( (str+17), ((fsec != 0)? "%05.2f": "%02.0f"), sec); + /* compatible with ISO date formats */ + if (style == USE_ISO_DATES) + { + if (tm->tm_year > 0) + { + sprintf(str, "%04d-%02d-%02d %02d:%02d:", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); + sprintf((str + 17), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec); + + if ((*tzn != NULL) && (tm->tm_isdst >= 0)) + { + if (tzp != NULL) + { + hour = -(*tzp / 3600); + min = ((abs(*tzp) / 60) % 60); + } + else + { + hour = 0; + min = 0; + } + sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); + } - if ((*tzn != NULL) && (tm->tm_isdst >= 0)) { - if (tzp != NULL) { - hour = -(*tzp / 3600); - min = ((abs(*tzp) / 60) % 60); - } else { - hour = 0; - min = 0; } - sprintf( (str+strlen(str)), ((min != 0)? "%+03d:%02d": "%+03d"), hour, min); - } + else + { + if (tm->tm_hour || tm->tm_min) + { + sprintf(str, "%04d-%02d-%02d %02d:%02d %s", + -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, "BC"); + } + else + { + sprintf(str, "%04d-%02d-%02d %s", + -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC"); + } + } - } else { - if (tm->tm_hour || tm->tm_min) { - sprintf( str, "%04d-%02d-%02d %02d:%02d %s", - -(tm->tm_year-1), tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, "BC"); - } else { - sprintf( str, "%04d-%02d-%02d %s", - -(tm->tm_year-1), tm->tm_mon, tm->tm_mday, "BC"); - } + /* compatible with Oracle/Ingres date formats */ } + else if (style == USE_SQL_DATES) + { + if (EuroDates) + { + sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); + } + else + { + sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); + } + if (tm->tm_year > 0) + { + sprintf((str + 5), "/%04d %02d:%02d:%05.2f", + tm->tm_year, tm->tm_hour, tm->tm_min, sec); - /* compatible with Oracle/Ingres date formats */ - } else if (style == USE_SQL_DATES) { - if (EuroDates) { - sprintf( str, "%02d/%02d", tm->tm_mday, tm->tm_mon); - } else { - sprintf( str, "%02d/%02d", tm->tm_mon, tm->tm_mday); - } - if (tm->tm_year > 0) { - sprintf( (str+5), "/%04d %02d:%02d:%05.2f", - tm->tm_year, tm->tm_hour, tm->tm_min, sec); + if ((*tzn != NULL) && (tm->tm_isdst >= 0)) + { + strcpy((str + 22), " "); + strcpy((str + 23), *tzn); + } - if ((*tzn != NULL) && (tm->tm_isdst >= 0)) { - strcpy( (str+22), " "); - strcpy( (str+23), *tzn); - } + } + else + { + sprintf((str + 5), "/%04d %02d:%02d %s", + -(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC"); + } - } else { - sprintf( (str+5), "/%04d %02d:%02d %s", - -(tm->tm_year-1), tm->tm_hour, tm->tm_min, "BC"); + /* backward-compatible with traditional Postgres abstime dates */ } - - /* backward-compatible with traditional Postgres abstime dates */ - } else { /* if (style == USE_POSTGRES_DATES) */ - day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday); + else + { /* if (style == USE_POSTGRES_DATES) */ + day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); #ifdef DATEDEBUG -printf( "EncodeDateTime- day is %d\n", day); + printf("EncodeDateTime- day is %d\n", day); #endif - tm->tm_wday = j2day( day); + tm->tm_wday = j2day(day); - strncpy( str, days[tm->tm_wday], 3); - strcpy( (str+3), " "); + strncpy(str, days[tm->tm_wday], 3); + strcpy((str + 3), " "); - if (EuroDates) { - sprintf( (str+4), "%02d %3s", tm->tm_mday, months[tm->tm_mon-1]); - } else { - sprintf( (str+4), "%3s %02d", months[tm->tm_mon-1], tm->tm_mday); - } - if (tm->tm_year > 0) { - sprintf( (str+10), " %02d:%02d", tm->tm_hour, tm->tm_min); - if (fsec != 0) { - sprintf( (str+16), ":%05.2f %04d", sec, tm->tm_year); - if ((*tzn != NULL) && (tm->tm_isdst >= 0)) { - strcpy( (str+27), " "); - strcpy( (str+28), *tzn); + if (EuroDates) + { + sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]); } - } else { - sprintf( (str+16), ":%02.0f %04d", sec, tm->tm_year); - if ((*tzn != NULL) && (tm->tm_isdst >= 0)) { - strcpy( (str+24), " "); - strcpy( (str+25), *tzn); + else + { + sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday); } - } + if (tm->tm_year > 0) + { + sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min); + if (fsec != 0) + { + sprintf((str + 16), ":%05.2f %04d", sec, tm->tm_year); + if ((*tzn != NULL) && (tm->tm_isdst >= 0)) + { + strcpy((str + 27), " "); + strcpy((str + 28), *tzn); + } + } + else + { + sprintf((str + 16), ":%02.0f %04d", sec, tm->tm_year); + if ((*tzn != NULL) && (tm->tm_isdst >= 0)) + { + strcpy((str + 24), " "); + strcpy((str + 25), *tzn); + } + } - } else { - sprintf( (str+10), " %02d:%02d %04d %s", - tm->tm_hour, tm->tm_min, -(tm->tm_year-1), "BC"); + } + else + { + sprintf((str + 10), " %02d:%02d %04d %s", + tm->tm_hour, tm->tm_min, -(tm->tm_year - 1), "BC"); + } } - } #ifdef DATEDEBUG -printf( "EncodeDateTime- date result is %s\n", str); + printf("EncodeDateTime- date result is %s\n", str); #endif - return(TRUE); -} /* EncodeDateTime() */ + return (TRUE); +} /* EncodeDateTime() */ /* EncodeTimeSpan() * Interpret time structure as a delta time and convert to string. * * Pass a flag to specify the style of string, but only implement - * the traditional Postgres style for now. - tgl 97/03/27 + * the traditional Postgres style for now. - tgl 97/03/27 */ -int EncodeTimeSpan(struct tm *tm, double fsec, int style, char *str) -{ - int is_before = FALSE; - int is_nonzero = FALSE; - char *cp; - - strcpy( str, "@"); - cp = str+strlen(str); - - if (tm->tm_year != 0) { - is_nonzero = TRUE; - is_before |= (tm->tm_year < 0); - sprintf( cp, " %d year%s", abs(tm->tm_year), ((abs(tm->tm_year) != 1)? "s": "")); - cp += strlen(cp); - } - - if (tm->tm_mon != 0) { - is_nonzero = TRUE; - is_before |= (tm->tm_mon < 0); - sprintf( cp, " %d mon%s", abs(tm->tm_mon), ((abs(tm->tm_mon) != 1)? "s": "")); - cp += strlen(cp); - } - - if (tm->tm_mday != 0) { - is_nonzero = TRUE; - is_before |= (tm->tm_mday < 0); - sprintf( cp, " %d day%s", abs(tm->tm_mday), ((abs(tm->tm_mday) != 1)? "s": "")); - cp += strlen(cp); - } - - if (tm->tm_hour != 0) { - is_nonzero = TRUE; - is_before |= (tm->tm_hour < 0); - sprintf( cp, " %d hour%s", abs(tm->tm_hour), ((abs(tm->tm_hour) != 1)? "s": "")); - cp += strlen(cp); - } - - if (tm->tm_min != 0) { - is_nonzero = TRUE; - is_before |= (tm->tm_min < 0); - sprintf( cp, " %d min%s", abs(tm->tm_min), ((abs(tm->tm_min) != 1)? "s": "")); - cp += strlen(cp); - } - - /* fractional seconds? */ - if (fsec != 0) { - is_nonzero = TRUE; - fsec += tm->tm_sec; - is_before |= (fsec < 0); - sprintf( cp, " %.2f secs", fabs(fsec)); - cp += strlen(cp); - - /* otherwise, integer seconds only? */ - } else if (tm->tm_sec != 0) { - is_nonzero = TRUE; - is_before |= (tm->tm_sec < 0); - sprintf( cp, " %d sec%s", abs(tm->tm_sec), ((abs(tm->tm_sec) != 1)? "s": "")); - cp += strlen(cp); - } - - /* identically zero? then put in a unitless zero... */ - if (! is_nonzero) { - strcat( cp, " 0"); - cp += strlen(cp); - } - - if (is_before) { - strcat( cp, " ago"); - cp += strlen(cp); - } - -#ifdef DATEDEBUG -printf( "EncodeTimeSpan- result is %s\n", str); -#endif - - return 0; -} /* EncodeTimeSpan() */ +int +EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) +{ + int is_before = FALSE; + int is_nonzero = FALSE; + char *cp; + + strcpy(str, "@"); + cp = str + strlen(str); + + if (tm->tm_year != 0) + { + is_nonzero = TRUE; + is_before |= (tm->tm_year < 0); + sprintf(cp, " %d year%s", abs(tm->tm_year), ((abs(tm->tm_year) != 1) ? "s" : "")); + cp += strlen(cp); + } + + if (tm->tm_mon != 0) + { + is_nonzero = TRUE; + is_before |= (tm->tm_mon < 0); + sprintf(cp, " %d mon%s", abs(tm->tm_mon), ((abs(tm->tm_mon) != 1) ? "s" : "")); + cp += strlen(cp); + } + + if (tm->tm_mday != 0) + { + is_nonzero = TRUE; + is_before |= (tm->tm_mday < 0); + sprintf(cp, " %d day%s", abs(tm->tm_mday), ((abs(tm->tm_mday) != 1) ? "s" : "")); + cp += strlen(cp); + } + + if (tm->tm_hour != 0) + { + is_nonzero = TRUE; + is_before |= (tm->tm_hour < 0); + sprintf(cp, " %d hour%s", abs(tm->tm_hour), ((abs(tm->tm_hour) != 1) ? "s" : "")); + cp += strlen(cp); + } + + if (tm->tm_min != 0) + { + is_nonzero = TRUE; + is_before |= (tm->tm_min < 0); + sprintf(cp, " %d min%s", abs(tm->tm_min), ((abs(tm->tm_min) != 1) ? "s" : "")); + cp += strlen(cp); + } + + /* fractional seconds? */ + if (fsec != 0) + { + is_nonzero = TRUE; + fsec += tm->tm_sec; + is_before |= (fsec < 0); + sprintf(cp, " %.2f secs", fabs(fsec)); + cp += strlen(cp); + + /* otherwise, integer seconds only? */ + } + else if (tm->tm_sec != 0) + { + is_nonzero = TRUE; + is_before |= (tm->tm_sec < 0); + sprintf(cp, " %d sec%s", abs(tm->tm_sec), ((abs(tm->tm_sec) != 1) ? "s" : "")); + cp += strlen(cp); + } + + /* identically zero? then put in a unitless zero... */ + if (!is_nonzero) + { + strcat(cp, " 0"); + cp += strlen(cp); + } + + if (is_before) + { + strcat(cp, " ago"); + cp += strlen(cp); + } + +#ifdef DATEDEBUG + printf("EncodeTimeSpan- result is %s\n", str); +#endif + + return 0; +} /* EncodeTimeSpan() */ #if defined(linux) && defined(PPC) -int datetime_is_epoch(double j) +int +datetime_is_epoch(double j) { - static union { - double epoch; - unsigned char c[8]; - } u; + static union + { + double epoch; + unsigned char c[8]; + } u; - u.c[0] = 0x80; /* sign bit */ - u.c[1] = 0x10; /* DBL_MIN */ + u.c[0] = 0x80; /* sign bit */ + u.c[1] = 0x10; /* DBL_MIN */ - return(j == u.epoch); + return (j == u.epoch); } -int datetime_is_current(double j) +int +datetime_is_current(double j) { - static union { - double current; - unsigned char c[8]; - } u; + static union + { + double current; + unsigned char c[8]; + } u; - u.c[1] = 0x10; /* DBL_MIN */ + u.c[1] = 0x10; /* DBL_MIN */ - return(j == u.current); + return (j == u.current); } + #endif diff --git a/src/backend/utils/adt/filename.c b/src/backend/utils/adt/filename.c index a14b8283b59..445de98a77a 100644 --- a/src/backend/utils/adt/filename.c +++ b/src/backend/utils/adt/filename.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * filename.c-- - * + * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/filename.c,v 1.8 1997/08/12 20:15:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/filename.c,v 1.9 1997/09/07 04:50:14 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,95 +20,118 @@ #include "postgres.h" #include <miscadmin.h> -#include "utils/builtins.h" /* where function declarations go */ +#include "utils/builtins.h" /* where function declarations go */ -char * +char * filename_in(char *file) { - char *str; - int ind = 0; - - /* - * XXX - HACK CITY --- REDO - * should let the shell do expansions (shexpand) - */ + char *str; + int ind = 0; - str = (char *) palloc(MAXPATHLEN * sizeof(*str)); - str[0] = '\0'; - if (file[0] == '~') { - if (file[1] == '\0' || file[1] == '/') { - /* Home directory */ - - char *userName; - struct passwd *pw; - - userName = GetPgUserName(); - - if ((pw = getpwnam(userName)) == NULL) { - elog(WARN, "User %s is not a Unix user on the db server.", - userName); - } - - strcpy(str, pw->pw_dir); - - ind = 1; - } else { - /* Someone else's directory */ - char name[16], *p; - struct passwd *pw; - int len; - - if ((p = (char *) strchr(file, '/')) == NULL) { - strcpy(name, file+1); - len = strlen(name); - } else { - len = (p - file) - 1; - strNcpy(name, file+1, len); - } - /*printf("name: %s\n");*/ - if ((pw = getpwnam(name)) == NULL) { - elog(WARN, "No such user: %s\n", name); - ind = 0; - } else { - strcpy(str, pw->pw_dir); - ind = len + 1; - } - } - } else if (file[0] == '$') { /* $POSTGRESHOME, etc. expand it. */ - char environment[80], *envirp, *p; - int len; - - if ((p = (char *) strchr(file, '/')) == NULL) { - strcpy(environment, file+1); - len = strlen(environment); - } else { - len = (p - file) - 1; - strNcpy(environment, file+1, len); + /* + * XXX - HACK CITY --- REDO should let the shell do expansions + * (shexpand) + */ + + str = (char *) palloc(MAXPATHLEN * sizeof(*str)); + str[0] = '\0'; + if (file[0] == '~') + { + if (file[1] == '\0' || file[1] == '/') + { + /* Home directory */ + + char *userName; + struct passwd *pw; + + userName = GetPgUserName(); + + if ((pw = getpwnam(userName)) == NULL) + { + elog(WARN, "User %s is not a Unix user on the db server.", + userName); + } + + strcpy(str, pw->pw_dir); + + ind = 1; + } + else + { + /* Someone else's directory */ + char name[16], + *p; + struct passwd *pw; + int len; + + if ((p = (char *) strchr(file, '/')) == NULL) + { + strcpy(name, file + 1); + len = strlen(name); + } + else + { + len = (p - file) - 1; + strNcpy(name, file + 1, len); + } + /* printf("name: %s\n"); */ + if ((pw = getpwnam(name)) == NULL) + { + elog(WARN, "No such user: %s\n", name); + ind = 0; + } + else + { + strcpy(str, pw->pw_dir); + ind = len + 1; + } + } } - envirp = getenv(environment); - if (envirp) { - strcpy(str, envirp); - ind = len + 1; + else if (file[0] == '$') + { /* $POSTGRESHOME, etc. expand it. */ + char environment[80], + *envirp, + *p; + int len; + + if ((p = (char *) strchr(file, '/')) == NULL) + { + strcpy(environment, file + 1); + len = strlen(environment); + } + else + { + len = (p - file) - 1; + strNcpy(environment, file + 1, len); + } + envirp = getenv(environment); + if (envirp) + { + strcpy(str, envirp); + ind = len + 1; + } + else + { + elog(WARN, "Couldn't find %s in your environment", environment); + } } - else { - elog(WARN,"Couldn't find %s in your environment", environment); + else + { + ind = 0; } - } else { - ind = 0; - } - strcat(str, file+ind); - return(str); + strcat(str, file + ind); + return (str); } -char * +char * filename_out(char *s) { - char *ret; - - if (!s) - return((char *) NULL); - ret = (char *) palloc(strlen(s) + 1); - if (!ret) - elog(WARN, "filename_out: palloc failed"); - return(strcpy(ret, s)); + char *ret; + + if (!s) + return ((char *) NULL); + ret = (char *) palloc(strlen(s) + 1); + if (!ret) + elog(WARN, "filename_out: palloc failed"); + return (strcpy(ret, s)); } diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 3518fd7d4cc..32d78fb2ba7 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -1,66 +1,66 @@ /*------------------------------------------------------------------------- * * float.c-- - * Functions for the built-in floating-point types. + * Functions for the built-in floating-point types. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.17 1997/07/28 00:55:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.18 1997/09/07 04:50:15 momjian Exp $ * *------------------------------------------------------------------------- */ /* * OLD COMMENTS - * Basic float4 ops: - * float4in, float4out, float4abs, float4um - * Basic float8 ops: - * float8in, float8inAd, float8out, float8outAd, float8abs, float8um - * Arithmetic operators: - * float4pl, float4mi, float4mul, float4div - * float8pl, float8mi, float8mul, float8div - * Comparison operators: - * float4eq, float4ne, float4lt, float4le, float4gt, float4ge - * float8eq, float8ne, float8lt, float8le, float8gt, float8ge - * Conversion routines: - * ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2 + * Basic float4 ops: + * float4in, float4out, float4abs, float4um + * Basic float8 ops: + * float8in, float8inAd, float8out, float8outAd, float8abs, float8um + * Arithmetic operators: + * float4pl, float4mi, float4mul, float4div + * float8pl, float8mi, float8mul, float8div + * Comparison operators: + * float4eq, float4ne, float4lt, float4le, float4gt, float4ge + * float8eq, float8ne, float8lt, float8le, float8gt, float8ge + * Conversion routines: + * ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2 * - * Random float8 ops: - * dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1 - * Arithmetic operators: - * float48pl, float48mi, float48mul, float48div - * float84pl, float84mi, float84mul, float84div - * Comparison operators: - * float48eq, float48ne, float48lt, float48le, float48gt, float48ge - * float84eq, float84ne, float84lt, float84le, float84gt, float84ge + * Random float8 ops: + * dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1 + * Arithmetic operators: + * float48pl, float48mi, float48mul, float48div + * float84pl, float84mi, float84mul, float84div + * Comparison operators: + * float48eq, float48ne, float48lt, float48le, float48gt, float48ge + * float84eq, float84ne, float84lt, float84le, float84gt, float84ge * - * (You can do the arithmetic and comparison stuff using conversion - * routines, but then you pay the overhead of converting...) + * (You can do the arithmetic and comparison stuff using conversion + * routines, but then you pay the overhead of converting...) * * XXX GLUESOME STUFF. FIX IT! -AY '94 * - * Added some additional conversion routines and cleaned up - * a bit of the existing code. Need to change the error checking - * for calls to pow(), exp() since on some machines (my Linux box - * included) these routines do not set errno. - tgl 97/05/10 + * Added some additional conversion routines and cleaned up + * a bit of the existing code. Need to change the error checking + * for calls to pow(), exp() since on some machines (my Linux box + * included) these routines do not set errno. - tgl 97/05/10 */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include <ctype.h> #include <stdlib.h> #include <errno.h> -#include <float.h> /* faked on sunos4 */ +#include <float.h> /* faked on sunos4 */ #include <math.h> #include "postgres.h" #ifdef HAVE_LIMITS_H -# include <limits.h> +#include <limits.h> #endif #include "fmgr.h" -#include "utils/builtins.h" /* for ftod() prototype */ +#include "utils/builtins.h" /* for ftod() prototype */ #include "utils/palloc.h" @@ -71,65 +71,73 @@ #define SHRT_MIN (-32768) #endif -#define FORMAT 'g' /* use "g" output format as standard format */ +#define FORMAT 'g' /* use "g" output format as standard + * format */ /* not sure what the following should be, but better to make it over-sufficient */ -#define MAXFLOATWIDTH 64 +#define MAXFLOATWIDTH 64 #define MAXDOUBLEWIDTH 128 #if !(NeXT && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_2) - /* NS3.3 has conflicting declarations of these in <math.h> */ + /* NS3.3 has conflicting declarations of these in <math.h> */ #ifndef atof extern double atof(const char *p); + #endif #ifndef HAVE_CBRT -# define cbrt my_cbrt - static double cbrt(double x); -#else -# if !defined(nextstep) - extern double cbrt(double x); -# endif -#endif +#define cbrt my_cbrt +static double cbrt(double x); + +#else +#if !defined(nextstep) +extern double cbrt(double x); + +#endif +#endif #ifndef HAVE_RINT -# define rint my_rint - static double rint(double x); -#else - extern double rint(double x); -#endif +#define rint my_rint +static double rint(double x); + +#else +extern double rint(double x); + +#endif #ifndef HAVE_ISINF -# define isinf my_isinf - static int isinf(double x); -#else - extern int isinf(double x); -#endif +#define isinf my_isinf +static int isinf(double x); + +#else +extern int isinf(double x); -#endif +#endif + +#endif /* ========== USER I/O ROUTINES ========== */ - - -#define FLOAT4_MAX FLT_MAX -#define FLOAT4_MIN FLT_MIN -#define FLOAT8_MAX DBL_MAX -#define FLOAT8_MIN DBL_MIN - -/* + + +#define FLOAT4_MAX FLT_MAX +#define FLOAT4_MIN FLT_MIN +#define FLOAT8_MAX DBL_MAX +#define FLOAT8_MIN DBL_MIN + +/* * if FLOAT8_MIN and FLOAT8_MAX are the limits of the range a * double can store, then how are we ever going to wind up * with something stored in a double that is outside those - * limits? (and similarly for FLOAT4_{MIN,MAX}/float.) + * limits? (and similarly for FLOAT4_{MIN,MAX}/float.) * doesn't make sense to me, and it causes a * floating point exception on linuxalpha, so UNSAFE_FLOATS * it is. * (maybe someone wanted to allow for values other than DBL_MIN/ * DBL_MAX for FLOAT8_MIN/FLOAT8_MAX?) - * --djm 12/12/96 - * according to Richard Henderson this is a known bug in gcc on - * the Alpha. might as well leave the workaround in + * --djm 12/12/96 + * according to Richard Henderson this is a known bug in gcc on + * the Alpha. might as well leave the workaround in * until the distributions are updated. - * --djm 12/16/96 + * --djm 12/16/96 */ #if defined(linuxalpha) && !defined(UNSAFE_FLOATS) #define UNSAFE_FLOATS @@ -138,1157 +146,1240 @@ extern double atof(const char *p); /* check to see if a float4 val is outside of the FLOAT4_MIN, FLOAT4_MAX bounds. - + raise an elog warning if it is */ -static void CheckFloat4Val(double val) +static void +CheckFloat4Val(double val) { - /* defining unsafe floats's will make float4 and float8 ops faster - at the cost of safety, of course! */ + + /* + * defining unsafe floats's will make float4 and float8 ops faster at + * the cost of safety, of course! + */ #ifdef UNSAFE_FLOATS - return; + return; #else - if (fabs(val) > FLOAT4_MAX) - elog(WARN,"\tBad float4 input format -- overflow\n"); - if (val != 0.0 && fabs(val) < FLOAT4_MIN) - elog(WARN,"\tBad float4 input format -- underflow\n"); - return; -#endif /* UNSAFE_FLOATS */ + if (fabs(val) > FLOAT4_MAX) + elog(WARN, "\tBad float4 input format -- overflow\n"); + if (val != 0.0 && fabs(val) < FLOAT4_MIN) + elog(WARN, "\tBad float4 input format -- underflow\n"); + return; +#endif /* UNSAFE_FLOATS */ } /* check to see if a float8 val is outside of the FLOAT8_MIN, FLOAT8_MAX bounds. - + raise an elog warning if it is */ -void CheckFloat8Val(double val) +void +CheckFloat8Val(double val) { - /* defining unsafe floats's will make float4 and float8 ops faster - at the cost of safety, of course! */ + + /* + * defining unsafe floats's will make float4 and float8 ops faster at + * the cost of safety, of course! + */ #ifdef UNSAFE_FLOATS - return; + return; #else - if (fabs(val) > FLOAT8_MAX) - elog(WARN,"\tBad float8 input format -- overflow\n"); - if (val != 0.0 && fabs(val) < FLOAT8_MIN) - elog(WARN,"\tBad float8 input format -- underflow\n"); - return; -#endif /* UNSAFE_FLOATS */ + if (fabs(val) > FLOAT8_MAX) + elog(WARN, "\tBad float8 input format -- overflow\n"); + if (val != 0.0 && fabs(val) < FLOAT8_MIN) + elog(WARN, "\tBad float8 input format -- underflow\n"); + return; +#endif /* UNSAFE_FLOATS */ } /* - * float4in - converts "num" to float - * restricted syntax: - * {<sp>} [+|-] {digit} [.{digit}] [<exp>] - * where <sp> is a space, digit is 0-9, - * <exp> is "e" or "E" followed by an integer. + * float4in - converts "num" to float + * restricted syntax: + * {<sp>} [+|-] {digit} [.{digit}] [<exp>] + * where <sp> is a space, digit is 0-9, + * <exp> is "e" or "E" followed by an integer. */ -float32 float4in(char *num) -{ - float32 result = (float32) palloc(sizeof(float32data)); - double val; - char* endptr; - - errno = 0; - val = strtod(num,&endptr); - if (*endptr != '\0' || errno == ERANGE) - elog(WARN,"\tBad float4 input format\n"); - - /* if we get here, we have a legal double, still need to check to see - if it's a legal float */ - - CheckFloat4Val(val); - - *result = val; - return result; +float32 +float4in(char *num) +{ + float32 result = (float32) palloc(sizeof(float32data)); + double val; + char *endptr; + + errno = 0; + val = strtod(num, &endptr); + if (*endptr != '\0' || errno == ERANGE) + elog(WARN, "\tBad float4 input format\n"); + + /* + * if we get here, we have a legal double, still need to check to see + * if it's a legal float + */ + + CheckFloat4Val(val); + + *result = val; + return result; } /* - * float4out - converts a float4 number to a string - * using a standard output format + * float4out - converts a float4 number to a string + * using a standard output format */ -char *float4out(float32 num) +char * +float4out(float32 num) { - char *ascii = (char *)palloc(MAXFLOATWIDTH+1); - - if (!num) - return strcpy(ascii, "(null)"); - - sprintf(ascii, "%.*g", FLT_DIG, *num); - return(ascii); + char *ascii = (char *) palloc(MAXFLOATWIDTH + 1); + + if (!num) + return strcpy(ascii, "(null)"); + + sprintf(ascii, "%.*g", FLT_DIG, *num); + return (ascii); } /* - * float8in - converts "num" to float8 - * restricted syntax: - * {<sp>} [+|-] {digit} [.{digit}] [<exp>] - * where <sp> is a space, digit is 0-9, - * <exp> is "e" or "E" followed by an integer. + * float8in - converts "num" to float8 + * restricted syntax: + * {<sp>} [+|-] {digit} [.{digit}] [<exp>] + * where <sp> is a space, digit is 0-9, + * <exp> is "e" or "E" followed by an integer. */ -float64 float8in(char *num) +float64 +float8in(char *num) { - float64 result = (float64) palloc(sizeof(float64data)); - double val; - char* endptr; - - errno = 0; - val = strtod(num,&endptr); - if (*endptr != '\0' || errno == ERANGE) - elog(WARN,"\tBad float8 input format\n"); - - CheckFloat8Val(val); - *result = val; - return(result); + float64 result = (float64) palloc(sizeof(float64data)); + double val; + char *endptr; + + errno = 0; + val = strtod(num, &endptr); + if (*endptr != '\0' || errno == ERANGE) + elog(WARN, "\tBad float8 input format\n"); + + CheckFloat8Val(val); + *result = val; + return (result); } /* - * float8out - converts float8 number to a string - * using a standard output format + * float8out - converts float8 number to a string + * using a standard output format */ -char *float8out(float64 num) +char * +float8out(float64 num) { - char *ascii = (char *)palloc(MAXDOUBLEWIDTH+1); - - if (!num) - return strcpy(ascii, "(null)"); + char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1); + + if (!num) + return strcpy(ascii, "(null)"); - if (isnan(*num)) - return strcpy(ascii, "NaN"); - if (isinf(*num)) - return strcpy(ascii, "Infinity"); + if (isnan(*num)) + return strcpy(ascii, "NaN"); + if (isinf(*num)) + return strcpy(ascii, "Infinity"); - sprintf(ascii, "%.*g", DBL_DIG, *num); - return(ascii); + sprintf(ascii, "%.*g", DBL_DIG, *num); + return (ascii); } /* ========== PUBLIC ROUTINES ========== */ /* - * ====================== - * FLOAT4 BASE OPERATIONS - * ====================== + * ====================== + * FLOAT4 BASE OPERATIONS + * ====================== */ /* - * float4abs - returns a pointer to |arg1| (absolute value) + * float4abs - returns a pointer to |arg1| (absolute value) */ -float32 float4abs(float32 arg1) +float32 +float4abs(float32 arg1) { - float32 result; - double val; - - if (!arg1) - return (float32)NULL; - - val = fabs(*arg1); + float32 result; + double val; - CheckFloat4Val(val); + if (!arg1) + return (float32) NULL; - result = (float32) palloc(sizeof(float32data)); - *result = val; - return(result); + val = fabs(*arg1); + + CheckFloat4Val(val); + + result = (float32) palloc(sizeof(float32data)); + *result = val; + return (result); } /* - * float4um - returns a pointer to -arg1 (unary minus) + * float4um - returns a pointer to -arg1 (unary minus) */ -float32 float4um(float32 arg1) +float32 +float4um(float32 arg1) { - float32 result; - double val; - - if (!arg1) - return (float32)NULL; - - val = ((*arg1 != 0) ? -(*arg1): *arg1); - CheckFloat4Val(val); + float32 result; + double val; + + if (!arg1) + return (float32) NULL; + + val = ((*arg1 != 0) ? -(*arg1) : *arg1); + CheckFloat4Val(val); - result = (float32) palloc(sizeof(float32data)); - *result = val; - return(result); + result = (float32) palloc(sizeof(float32data)); + *result = val; + return (result); } -float32 float4larger(float32 arg1, float32 arg2) +float32 +float4larger(float32 arg1, float32 arg2) { - float32 result; - - if (!arg1 || !arg2) - return (float32)NULL; - - result = (float32) palloc(sizeof(float32data)); - - *result = ((*arg1 > *arg2) ? *arg1 : *arg2); - return result; + float32 result; + + if (!arg1 || !arg2) + return (float32) NULL; + + result = (float32) palloc(sizeof(float32data)); + + *result = ((*arg1 > *arg2) ? *arg1 : *arg2); + return result; } -float32 float4smaller(float32 arg1, float32 arg2) +float32 +float4smaller(float32 arg1, float32 arg2) { - float32 result; - - if (!arg1 || !arg2) - return (float32)NULL; - - result = (float32) palloc(sizeof(float32data)); - - *result = ((*arg1 > *arg2) ? *arg2 : *arg1); - return result; + float32 result; + + if (!arg1 || !arg2) + return (float32) NULL; + + result = (float32) palloc(sizeof(float32data)); + + *result = ((*arg1 > *arg2) ? *arg2 : *arg1); + return result; } /* - * ====================== - * FLOAT8 BASE OPERATIONS - * ====================== + * ====================== + * FLOAT8 BASE OPERATIONS + * ====================== */ /* - * float8abs - returns a pointer to |arg1| (absolute value) + * float8abs - returns a pointer to |arg1| (absolute value) */ -float64 float8abs(float64 arg1) +float64 +float8abs(float64 arg1) { - float64 result; - double val; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - val = fabs(*arg1); - CheckFloat8Val(val); - *result = val; - return(result); + float64 result; + double val; + + if (!arg1) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + val = fabs(*arg1); + CheckFloat8Val(val); + *result = val; + return (result); } /* - * float8um - returns a pointer to -arg1 (unary minus) + * float8um - returns a pointer to -arg1 (unary minus) */ -float64 float8um(float64 arg1) +float64 +float8um(float64 arg1) { - float64 result; - double val; + float64 result; + double val; + + if (!arg1) + return (float64) NULL; + + val = ((*arg1 != 0) ? -(*arg1) : *arg1); - if (!arg1) - return (float64)NULL; - - val = ((*arg1 != 0)? -(*arg1): *arg1); - - CheckFloat8Val(val); - result = (float64) palloc(sizeof(float64data)); - *result = val; - return(result); + CheckFloat8Val(val); + result = (float64) palloc(sizeof(float64data)); + *result = val; + return (result); } -float64 float8larger(float64 arg1, float64 arg2) +float64 +float8larger(float64 arg1, float64 arg2) { - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = ((*arg1 > *arg2) ? *arg1 : *arg2); - return result; + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = ((*arg1 > *arg2) ? *arg1 : *arg2); + return result; } -float64 float8smaller(float64 arg1, float64 arg2) +float64 +float8smaller(float64 arg1, float64 arg2) { - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = ((*arg1 > *arg2) ? *arg2 : *arg1); - return result; + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = ((*arg1 > *arg2) ? *arg2 : *arg1); + return result; } /* - * ==================== - * ARITHMETIC OPERATORS - * ==================== + * ==================== + * ARITHMETIC OPERATORS + * ==================== */ /* - * float4pl - returns a pointer to arg1 + arg2 - * float4mi - returns a pointer to arg1 - arg2 - * float4mul - returns a pointer to arg1 * arg2 - * float4div - returns a pointer to arg1 / arg2 - * float4inc - returns a poniter to arg1 + 1.0 + * float4pl - returns a pointer to arg1 + arg2 + * float4mi - returns a pointer to arg1 - arg2 + * float4mul - returns a pointer to arg1 * arg2 + * float4div - returns a pointer to arg1 / arg2 + * float4inc - returns a poniter to arg1 + 1.0 */ -float32 float4pl(float32 arg1, float32 arg2) +float32 +float4pl(float32 arg1, float32 arg2) { - float32 result; - double val; - - if (!arg1 || !arg2) - return (float32)NULL; - - val = *arg1 + *arg2; - CheckFloat4Val(val); + float32 result; + double val; + + if (!arg1 || !arg2) + return (float32) NULL; - result = (float32) palloc(sizeof(float32data)); - *result = val; + val = *arg1 + *arg2; + CheckFloat4Val(val); - return(result); + result = (float32) palloc(sizeof(float32data)); + *result = val; + + return (result); } -float32 float4mi(float32 arg1, float32 arg2) +float32 +float4mi(float32 arg1, float32 arg2) { - float32 result; - double val; - - if (!arg1 || !arg2) - return (float32)NULL; - - val = *arg1 - *arg2; + float32 result; + double val; + + if (!arg1 || !arg2) + return (float32) NULL; + + val = *arg1 - *arg2; - CheckFloat4Val(val); - result = (float32) palloc(sizeof(float32data)); - *result = val; - return(result); + CheckFloat4Val(val); + result = (float32) palloc(sizeof(float32data)); + *result = val; + return (result); } -float32 float4mul(float32 arg1, float32 arg2) +float32 +float4mul(float32 arg1, float32 arg2) { - float32 result; - double val; - - if (!arg1 || !arg2) - return (float32)NULL; - - val = *arg1 * *arg2; + float32 result; + double val; - CheckFloat4Val(val); - result = (float32) palloc(sizeof(float32data)); - *result = val; - return(result); + if (!arg1 || !arg2) + return (float32) NULL; + + val = *arg1 * *arg2; + + CheckFloat4Val(val); + result = (float32) palloc(sizeof(float32data)); + *result = val; + return (result); } -float32 float4div(float32 arg1, float32 arg2) +float32 +float4div(float32 arg1, float32 arg2) { - float32 result; - double val; - - if (!arg1 || !arg2) - return (float32)NULL; - - if (*arg2 == 0.0) - elog(WARN,"float4div: divide by 0.0 error"); + float32 result; + double val; + + if (!arg1 || !arg2) + return (float32) NULL; + + if (*arg2 == 0.0) + elog(WARN, "float4div: divide by 0.0 error"); - val = *arg1 / *arg2; - - CheckFloat4Val(val); - result = (float32) palloc(sizeof(float32data)); - *result = *arg1 / *arg2; - return(result); + val = *arg1 / *arg2; + + CheckFloat4Val(val); + result = (float32) palloc(sizeof(float32data)); + *result = *arg1 / *arg2; + return (result); } -float32 float4inc(float32 arg1) +float32 +float4inc(float32 arg1) { - double val; + double val; + + if (!arg1) + return (float32) NULL; - if (!arg1) - return (float32)NULL; - - val = *arg1 + (float32data)1.0; - CheckFloat4Val(val); - *arg1 = val; - return arg1; + val = *arg1 + (float32data) 1.0; + CheckFloat4Val(val); + *arg1 = val; + return arg1; } /* - * float8pl - returns a pointer to arg1 + arg2 - * float8mi - returns a pointer to arg1 - arg2 - * float8mul - returns a pointer to arg1 * arg2 - * float8div - returns a pointer to arg1 / arg2 - * float8inc - returns a pointer to arg1 + 1.0 + * float8pl - returns a pointer to arg1 + arg2 + * float8mi - returns a pointer to arg1 - arg2 + * float8mul - returns a pointer to arg1 * arg2 + * float8div - returns a pointer to arg1 / arg2 + * float8inc - returns a pointer to arg1 + 1.0 */ -float64 float8pl(float64 arg1, float64 arg2) -{ - float64 result; - double val; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - val = *arg1 + *arg2; - CheckFloat8Val(val); - *result = val; - return(result); -} - -float64 float8mi(float64 arg1, float64 arg2) -{ - float64 result; - double val; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - val = *arg1 - *arg2; - CheckFloat8Val(val); - *result = val; - return(result); -} - -float64 float8mul(float64 arg1, float64 arg2) -{ - float64 result; - double val; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - val = *arg1 * *arg2; - CheckFloat8Val(val); - *result = val; - return(result); -} - -float64 float8div(float64 arg1, float64 arg2) -{ - float64 result; - double val; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - if (*arg2 == 0.0) - elog(WARN,"float8div: divide by 0.0 error"); - - val = *arg1 / *arg2; - CheckFloat8Val(val); - *result = val; - return(result); -} - -float64 float8inc(float64 arg1) -{ - double val; - if (!arg1) - return (float64)NULL; - - val = *arg1 + (float64data)1.0; - CheckFloat8Val(val); - *arg1 = val; - return(arg1); +float64 +float8pl(float64 arg1, float64 arg2) +{ + float64 result; + double val; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + val = *arg1 + *arg2; + CheckFloat8Val(val); + *result = val; + return (result); +} + +float64 +float8mi(float64 arg1, float64 arg2) +{ + float64 result; + double val; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + val = *arg1 - *arg2; + CheckFloat8Val(val); + *result = val; + return (result); +} + +float64 +float8mul(float64 arg1, float64 arg2) +{ + float64 result; + double val; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + val = *arg1 * *arg2; + CheckFloat8Val(val); + *result = val; + return (result); +} + +float64 +float8div(float64 arg1, float64 arg2) +{ + float64 result; + double val; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + if (*arg2 == 0.0) + elog(WARN, "float8div: divide by 0.0 error"); + + val = *arg1 / *arg2; + CheckFloat8Val(val); + *result = val; + return (result); +} + +float64 +float8inc(float64 arg1) +{ + double val; + + if (!arg1) + return (float64) NULL; + + val = *arg1 + (float64data) 1.0; + CheckFloat8Val(val); + *arg1 = val; + return (arg1); } /* - * ==================== - * COMPARISON OPERATORS - * ==================== + * ==================== + * COMPARISON OPERATORS + * ==================== */ /* - * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations + * float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations */ -bool float4eq(float32 arg1, float32 arg2) +bool +float4eq(float32 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; + if (!arg1 || !arg2) + return 0; - return(*arg1 == *arg2); + return (*arg1 == *arg2); } -bool float4ne(float32 arg1, float32 arg2) +bool +float4ne(float32 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 != *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 != *arg2); } -bool float4lt(float32 arg1, float32 arg2) +bool +float4lt(float32 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 < *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 < *arg2); } -bool float4le(float32 arg1, float32 arg2) +bool +float4le(float32 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 <= *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 <= *arg2); } -bool float4gt(float32 arg1, float32 arg2) +bool +float4gt(float32 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 > *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 > *arg2); } -bool float4ge(float32 arg1, float32 arg2) +bool +float4ge(float32 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 >= *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 >= *arg2); } /* - * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations + * float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations */ -bool float8eq(float64 arg1, float64 arg2) +bool +float8eq(float64 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 == *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 == *arg2); } -bool float8ne(float64 arg1, float64 arg2) +bool +float8ne(float64 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 != *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 != *arg2); } -bool float8lt(float64 arg1, float64 arg2) +bool +float8lt(float64 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 < *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 < *arg2); } -bool float8le(float64 arg1, float64 arg2) +bool +float8le(float64 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 <= *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 <= *arg2); } -bool float8gt(float64 arg1, float64 arg2) +bool +float8gt(float64 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 > *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 > *arg2); } -bool float8ge(float64 arg1, float64 arg2) +bool +float8ge(float64 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 >= *arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 >= *arg2); } /* - * =================== - * CONVERSION ROUTINES - * =================== + * =================== + * CONVERSION ROUTINES + * =================== */ /* - * ftod - converts a float4 number to a float8 number + * ftod - converts a float4 number to a float8 number */ -float64 ftod(float32 num) +float64 +ftod(float32 num) { - float64 result; - - if (!num) - return (float64)NULL; + float64 result; + + if (!num) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); - result = (float64) palloc(sizeof(float64data)); - - *result = *num; - return(result); + *result = *num; + return (result); } /* - * dtof - converts a float8 number to a float4 number + * dtof - converts a float8 number to a float4 number */ -float32 dtof(float64 num) +float32 +dtof(float64 num) { - float32 result; - - if (!num) - return (float32)NULL; + float32 result; - CheckFloat4Val(*num); + if (!num) + return (float32) NULL; - result = (float32) palloc(sizeof(float32data)); + CheckFloat4Val(*num); - *result = *num; - return(result); + result = (float32) palloc(sizeof(float32data)); + + *result = *num; + return (result); } /* - * dtoi4 - converts a float8 number to an int4 number + * dtoi4 - converts a float8 number to an int4 number */ -int32 dtoi4(float64 num) +int32 +dtoi4(float64 num) { - int32 result; - - if (!num) - elog(WARN,"dtoi4: unable to convert null",NULL); + int32 result; + + if (!num) + elog(WARN, "dtoi4: unable to convert null", NULL); - if ((*num < INT_MIN) || (*num > INT_MAX)) - elog(WARN,"dtoi4: integer out of range",NULL); + if ((*num < INT_MIN) || (*num > INT_MAX)) + elog(WARN, "dtoi4: integer out of range", NULL); - result = rint(*num); - return(result); + result = rint(*num); + return (result); } /* - * dtoi2 - converts a float8 number to an int2 number + * dtoi2 - converts a float8 number to an int2 number */ -int16 dtoi2(float64 num) +int16 +dtoi2(float64 num) { - int16 result; - - if (!num) - elog(WARN,"dtoi2: unable to convert null",NULL); + int16 result; + + if (!num) + elog(WARN, "dtoi2: unable to convert null", NULL); - if ((*num < SHRT_MIN) || (*num > SHRT_MAX)) - elog(WARN,"dtoi2: integer out of range",NULL); + if ((*num < SHRT_MIN) || (*num > SHRT_MAX)) + elog(WARN, "dtoi2: integer out of range", NULL); - result = rint(*num); - return(result); + result = rint(*num); + return (result); } /* - * i4tod - converts an int4 number to a float8 number + * i4tod - converts an int4 number to a float8 number */ -float64 i4tod(int32 num) +float64 +i4tod(int32 num) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - - *result = num; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + + *result = num; + return (result); } /* - * i2tod - converts an int2 number to a float8 number + * i2tod - converts an int2 number to a float8 number */ -float64 i2tod(int16 num) +float64 +i2tod(int16 num) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - - *result = num; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + + *result = num; + return (result); } /* - * ftoi4 - converts a float8 number to an int4 number + * ftoi4 - converts a float8 number to an int4 number */ -int32 ftoi4(float32 num) +int32 +ftoi4(float32 num) { - int32 result; - - if (!num) - elog(WARN,"ftoi4: unable to convert null",NULL); + int32 result; - if ((*num < INT_MIN) || (*num > INT_MAX)) - elog(WARN,"ftoi4: integer out of range",NULL); + if (!num) + elog(WARN, "ftoi4: unable to convert null", NULL); - result = rint(*num); - return(result); + if ((*num < INT_MIN) || (*num > INT_MAX)) + elog(WARN, "ftoi4: integer out of range", NULL); + + result = rint(*num); + return (result); } /* - * ftoi2 - converts a float8 number to an int2 number + * ftoi2 - converts a float8 number to an int2 number */ -int16 ftoi2(float32 num) +int16 +ftoi2(float32 num) { - int16 result; - - if (!num) - elog(WARN,"ftoi2: unable to convert null",NULL); + int16 result; + + if (!num) + elog(WARN, "ftoi2: unable to convert null", NULL); - if ((*num < SHRT_MIN) || (*num > SHRT_MAX)) - elog(WARN,"ftoi2: integer out of range",NULL); + if ((*num < SHRT_MIN) || (*num > SHRT_MAX)) + elog(WARN, "ftoi2: integer out of range", NULL); - result = rint(*num); - return(result); + result = rint(*num); + return (result); } /* - * i4tof - converts an int4 number to a float8 number + * i4tof - converts an int4 number to a float8 number */ -float32 i4tof(int32 num) +float32 +i4tof(int32 num) { - float32 result; - - result = (float32) palloc(sizeof(float32data)); - - *result = num; - return(result); + float32 result; + + result = (float32) palloc(sizeof(float32data)); + + *result = num; + return (result); } /* - * i2tof - converts an int2 number to a float8 number + * i2tof - converts an int2 number to a float8 number */ -float32 i2tof(int16 num) +float32 +i2tof(int16 num) { - float32 result; - - result = (float32) palloc(sizeof(float32data)); - - *result = num; - return(result); + float32 result; + + result = (float32) palloc(sizeof(float32data)); + + *result = num; + return (result); } /* - * ======================= - * RANDOM FLOAT8 OPERATORS - * ======================= + * ======================= + * RANDOM FLOAT8 OPERATORS + * ======================= */ /* - * dround - returns a pointer to ROUND(arg1) + * dround - returns a pointer to ROUND(arg1) */ -float64 dround(float64 arg1) +float64 +dround(float64 arg1) { - float64 result; - double tmp; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp = *arg1; - *result = (float64data) rint(tmp); - return(result); + float64 result; + double tmp; + + if (!arg1) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; + *result = (float64data) rint(tmp); + return (result); } /* - * dtrunc - returns a pointer to truncation of arg1, - * arg1 >= 0 ... the greatest integer as float8 less - * than or equal to arg1 - * arg1 < 0 ... the greatest integer as float8 greater - * than or equal to arg1 + * dtrunc - returns a pointer to truncation of arg1, + * arg1 >= 0 ... the greatest integer as float8 less + * than or equal to arg1 + * arg1 < 0 ... the greatest integer as float8 greater + * than or equal to arg1 */ -float64 dtrunc(float64 arg1) -{ - float64 result; - double tmp; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp = *arg1; - if (*arg1 >= 0) - *result = (float64data) floor(tmp); - else - *result = (float64data) -(floor(-tmp)); - return(result); -} - - -/* - * dsqrt - returns a pointer to square root of arg1 +float64 +dtrunc(float64 arg1) +{ + float64 result; + double tmp; + + if (!arg1) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; + if (*arg1 >= 0) + *result = (float64data) floor(tmp); + else + *result = (float64data) - (floor(-tmp)); + return (result); +} + + +/* + * dsqrt - returns a pointer to square root of arg1 */ -float64 dsqrt(float64 arg1) +float64 +dsqrt(float64 arg1) { - float64 result; - double tmp; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp = *arg1; - *result = (float64data) sqrt(tmp); - return (result); + float64 result; + double tmp; + + if (!arg1) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; + *result = (float64data) sqrt(tmp); + return (result); } /* - * dcbrt - returns a pointer to cube root of arg1 + * dcbrt - returns a pointer to cube root of arg1 */ -float64 dcbrt(float64 arg1) +float64 +dcbrt(float64 arg1) { - float64 result; - double tmp; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp = *arg1; - *result = (float64data) cbrt(tmp); - return(result); + float64 result; + double tmp; + + if (!arg1) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; + *result = (float64data) cbrt(tmp); + return (result); } /* - * dpow - returns a pointer to pow(arg1,arg2) + * dpow - returns a pointer to pow(arg1,arg2) */ -float64 dpow(float64 arg1, float64 arg2) -{ - float64 result; - double tmp1, tmp2; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp1 = *arg1; - tmp2 = *arg2; +float64 +dpow(float64 arg1, float64 arg2) +{ + float64 result; + double tmp1, + tmp2; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp1 = *arg1; + tmp2 = *arg2; #ifndef finite - errno = 0; + errno = 0; #endif - *result = (float64data) pow(tmp1, tmp2); + *result = (float64data) pow(tmp1, tmp2); #ifndef finite - if (errno == ERANGE) + if (errno == ERANGE) #else - if (!finite(*result)) + if (!finite(*result)) #endif - elog(WARN, "pow() returned a floating point out of the range\n"); + elog(WARN, "pow() returned a floating point out of the range\n"); - CheckFloat8Val(*result); - return(result); + CheckFloat8Val(*result); + return (result); } /* - * dexp - returns a pointer to the exponential function of arg1 + * dexp - returns a pointer to the exponential function of arg1 */ -float64 dexp(float64 arg1) -{ - float64 result; - double tmp; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp = *arg1; +float64 +dexp(float64 arg1) +{ + float64 result; + double tmp; + + if (!arg1) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; #ifndef finite - errno = 0; + errno = 0; #endif - *result = (float64data) exp(tmp); + *result = (float64data) exp(tmp); #ifndef finite - if (errno == ERANGE) + if (errno == ERANGE) #else - if (!finite(*result)) + if (!finite(*result)) #endif - elog(WARN, "exp() returned a floating point out of range\n"); + elog(WARN, "exp() returned a floating point out of range\n"); - CheckFloat8Val(*result); - return(result); + CheckFloat8Val(*result); + return (result); } /* - * dlog1 - returns a pointer to the natural logarithm of arg1 - * ("dlog" is already a logging routine...) + * dlog1 - returns a pointer to the natural logarithm of arg1 + * ("dlog" is already a logging routine...) */ -float64 dlog1(float64 arg1) +float64 +dlog1(float64 arg1) { - float64 result; - double tmp; - - if (!arg1) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - tmp = *arg1; - if (tmp == 0.0) - elog(WARN, "can't take log of 0!"); - if (tmp < 0) - elog(WARN, "can't take log of a negative number"); - *result = (float64data) log(tmp); + float64 result; + double tmp; + + if (!arg1) + return (float64) NULL; - CheckFloat8Val(*result); - return(result); + result = (float64) palloc(sizeof(float64data)); + + tmp = *arg1; + if (tmp == 0.0) + elog(WARN, "can't take log of 0!"); + if (tmp < 0) + elog(WARN, "can't take log of a negative number"); + *result = (float64data) log(tmp); + + CheckFloat8Val(*result); + return (result); } /* - * ==================== - * ARITHMETIC OPERATORS - * ==================== + * ==================== + * ARITHMETIC OPERATORS + * ==================== */ /* - * float48pl - returns a pointer to arg1 + arg2 - * float48mi - returns a pointer to arg1 - arg2 - * float48mul - returns a pointer to arg1 * arg2 - * float48div - returns a pointer to arg1 / arg2 + * float48pl - returns a pointer to arg1 + arg2 + * float48mi - returns a pointer to arg1 - arg2 + * float48mul - returns a pointer to arg1 * arg2 + * float48div - returns a pointer to arg1 / arg2 */ -float64 float48pl(float32 arg1, float64 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = *arg1 + *arg2; - CheckFloat8Val(*result); - return(result); -} - -float64 float48mi(float32 arg1, float64 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = *arg1 - *arg2; - CheckFloat8Val(*result); - return(result); -} - -float64 float48mul(float32 arg1, float64 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = *arg1 * *arg2; - CheckFloat8Val(*result); - return(result); -} - -float64 float48div(float32 arg1, float64 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - if (*arg2 == 0.0) - elog(WARN, "float48div: divide by 0.0 error!"); - - *result = *arg1 / *arg2; - CheckFloat8Val(*result); - return(result); +float64 +float48pl(float32 arg1, float64 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = *arg1 + *arg2; + CheckFloat8Val(*result); + return (result); +} + +float64 +float48mi(float32 arg1, float64 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = *arg1 - *arg2; + CheckFloat8Val(*result); + return (result); +} + +float64 +float48mul(float32 arg1, float64 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = *arg1 * *arg2; + CheckFloat8Val(*result); + return (result); +} + +float64 +float48div(float32 arg1, float64 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + if (*arg2 == 0.0) + elog(WARN, "float48div: divide by 0.0 error!"); + + *result = *arg1 / *arg2; + CheckFloat8Val(*result); + return (result); } /* - * float84pl - returns a pointer to arg1 + arg2 - * float84mi - returns a pointer to arg1 - arg2 - * float84mul - returns a pointer to arg1 * arg2 - * float84div - returns a pointer to arg1 / arg2 + * float84pl - returns a pointer to arg1 + arg2 + * float84mi - returns a pointer to arg1 - arg2 + * float84mul - returns a pointer to arg1 * arg2 + * float84div - returns a pointer to arg1 / arg2 */ -float64 float84pl(float64 arg1, float32 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = *arg1 + *arg2; - CheckFloat8Val(*result); - return(result); -} - -float64 float84mi(float64 arg1, float32 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = *arg1 - *arg2; - CheckFloat8Val(*result); - return(result); -} - -float64 float84mul(float64 arg1, float32 arg2) -{ - - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - *result = *arg1 * *arg2; - CheckFloat8Val(*result); - return(result); -} - -float64 float84div(float64 arg1, float32 arg2) -{ - float64 result; - - if (!arg1 || !arg2) - return (float64)NULL; - - result = (float64) palloc(sizeof(float64data)); - - if (*arg2 == 0.0) - elog(WARN, "float48div: divide by 0.0 error!"); - - *result = *arg1 / *arg2; - CheckFloat8Val(*result); - return(result); +float64 +float84pl(float64 arg1, float32 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = *arg1 + *arg2; + CheckFloat8Val(*result); + return (result); +} + +float64 +float84mi(float64 arg1, float32 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = *arg1 - *arg2; + CheckFloat8Val(*result); + return (result); +} + +float64 +float84mul(float64 arg1, float32 arg2) +{ + + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + *result = *arg1 * *arg2; + CheckFloat8Val(*result); + return (result); +} + +float64 +float84div(float64 arg1, float32 arg2) +{ + float64 result; + + if (!arg1 || !arg2) + return (float64) NULL; + + result = (float64) palloc(sizeof(float64data)); + + if (*arg2 == 0.0) + elog(WARN, "float48div: divide by 0.0 error!"); + + *result = *arg1 / *arg2; + CheckFloat8Val(*result); + return (result); } /* - * ==================== - * COMPARISON OPERATORS - * ==================== + * ==================== + * COMPARISON OPERATORS + * ==================== */ /* - * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations + * float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations */ -bool float48eq(float32 arg1, float64 arg2) +bool +float48eq(float32 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 == (float)*arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 == (float) *arg2); } -bool float48ne(float32 arg1, float64 arg2) +bool +float48ne(float32 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 != (float)*arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 != (float) *arg2); } -bool float48lt(float32 arg1, float64 arg2) +bool +float48lt(float32 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 < (float)*arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 < (float) *arg2); } -bool float48le(float32 arg1, float64 arg2) +bool +float48le(float32 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 <= (float)*arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 <= (float) *arg2); } -bool float48gt(float32 arg1, float64 arg2) +bool +float48gt(float32 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 > (float)*arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 > (float) *arg2); } -bool float48ge(float32 arg1, float64 arg2) +bool +float48ge(float32 arg1, float64 arg2) { - if (!arg1 || !arg2) - return 0; - - return(*arg1 >= (float)*arg2); + if (!arg1 || !arg2) + return 0; + + return (*arg1 >= (float) *arg2); } /* - * float84{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations + * float84{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations */ -bool float84eq(float64 arg1, float32 arg2) +bool +float84eq(float64 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return((float)*arg1 == *arg2); + if (!arg1 || !arg2) + return 0; + + return ((float) *arg1 == *arg2); } -bool float84ne(float64 arg1, float32 arg2) +bool +float84ne(float64 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return((float)*arg1 != *arg2); + if (!arg1 || !arg2) + return 0; + + return ((float) *arg1 != *arg2); } -bool float84lt(float64 arg1, float32 arg2) +bool +float84lt(float64 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return((float)*arg1 < *arg2); + if (!arg1 || !arg2) + return 0; + + return ((float) *arg1 < *arg2); } -bool float84le(float64 arg1, float32 arg2) +bool +float84le(float64 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return((float)*arg1 <= *arg2); + if (!arg1 || !arg2) + return 0; + + return ((float) *arg1 <= *arg2); } -bool float84gt(float64 arg1, float32 arg2) +bool +float84gt(float64 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return((float)*arg1 > *arg2); + if (!arg1 || !arg2) + return 0; + + return ((float) *arg1 > *arg2); } -bool float84ge(float64 arg1, float32 arg2) +bool +float84ge(float64 arg1, float32 arg2) { - if (!arg1 || !arg2) - return 0; - - return((float)*arg1 >= *arg2); + if (!arg1 || !arg2) + return 0; + + return ((float) *arg1 >= *arg2); } /* ========== PRIVATE ROUTINES ========== */ @@ -1304,7 +1395,7 @@ bool float84ge(float64 arg1, float32 arg2) * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ @@ -1314,89 +1405,115 @@ bool float84ge(float64 arg1, float32 arg2) * Return x rounded to integral value according to the prevailing * rounding mode. * Method: - * Using floating addition. + * Using floating addition. * Exception: - * Inexact flag raised if x not equal to rint(x). + * Inexact flag raised if x not equal to rint(x). */ #ifdef __STDC__ static const double #else - static double +static double #endif - one = 1.0, - TWO52[2]={ + one = 1.0, + TWO52[2] = { 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ - }; + -4.50359962737049600000e+15,/* 0xC3300000, 0x00000000 */ +}; #ifdef __STDC__ -static double rint(double x) +static double +rint(double x) #else - static double rint(x) - double x; +static double +rint(x) +double x; + #endif { - int i0,n0,j0,sx; - unsigned i,i1; - double w,t; - n0 = (*((int *)&one)>>29)^1; - i0 = *(n0+(int*)&x); - sx = (i0>>31)&1; - i1 = *(1-n0+(int*)&x); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { - if(((i0&0x7fffffff)|i1)==0) return x; - i1 |= (i0&0x0fffff); - i0 &= 0xfffe0000; - i0 |= ((i1|-i1)>>12)&0x80000; - *(n0+(int*)&x)=i0; - w = TWO52[sx]+x; - t = w-TWO52[sx]; - i0 = *(n0+(int*)&t); - *(n0+(int*)&t) = (i0&0x7fffffff)|(sx<<31); - return t; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - i>>=1; - if(((i0&i)|i1)!=0) { - if(j0==19) i1 = 0x40000000; else - i0 = (i0&(~i))|((0x20000)>>j0); - } + int i0, + n0, + j0, + sx; + unsigned i, + i1; + double w, + t; + + n0 = (*((int *) &one) >> 29) ^ 1; + i0 = *(n0 + (int *) &x); + sx = (i0 >> 31) & 1; + i1 = *(1 - n0 + (int *) &x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) + { + if (j0 < 0) + { + if (((i0 & 0x7fffffff) | i1) == 0) + return x; + i1 |= (i0 & 0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1 | -i1) >> 12) & 0x80000; + *(n0 + (int *) &x) = i0; + w = TWO52[sx] + x; + t = w - TWO52[sx]; + i0 = *(n0 + (int *) &t); + *(n0 + (int *) &t) = (i0 & 0x7fffffff) | (sx << 31); + return t; + } + else + { + i = (0x000fffff) >> j0; + if (((i0 & i) | i1) == 0) + return x; /* x is integral */ + i >>= 1; + if (((i0 & i) | i1) != 0) + { + if (j0 == 19) + i1 = 0x40000000; + else + i0 = (i0 & (~i)) | ((0x20000) >> j0); + } + } + } + else if (j0 > 51) + { + if (j0 == 0x400) + return x + x; /* inf or NaN */ + else + return x; /* x is integral */ + } + else + { + i = ((unsigned) (0xffffffff)) >> (j0 - 20); + if ((i1 & i) == 0) + return x; /* x is integral */ + i >>= 1; + if ((i1 & i) != 0) + i1 = (i1 & (~i)) | ((0x40000000) >> (j0 - 20)); } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - i>>=1; - if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); - } - *(n0+(int*)&x) = i0; - *(1-n0+(int*)&x) = i1; - w = TWO52[sx]+x; - return w-TWO52[sx]; -} - -#endif /* !HAVE_RINT */ + *(n0 + (int *) &x) = i0; + *(1 - n0 + (int *) &x) = i1; + w = TWO52[sx] + x; + return w - TWO52[sx]; +} + +#endif /* !HAVE_RINT */ #ifndef HAVE_CBRT static - double - cbrt(x) -double x; +double +cbrt(x) +double x; { - int isneg = (x < 0.0); - double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0); - - return(isneg ? -tmpres : tmpres); + int isneg = (x < 0.0); + double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0); + + return (isneg ? -tmpres : tmpres); } -#endif /* !HAVE_CBRT */ +#endif /* !HAVE_CBRT */ #ifndef HAVE_ISINF @@ -1404,89 +1521,104 @@ double x; #ifdef CLASS_CONFLICT /* we want the math symbol */ #undef class -#endif /* CLASS_CONFICT */ +#endif /* CLASS_CONFICT */ -static int isinf(x) - double x; +static int +isinf(x) +double x; { - int fpclass = class(x); - if (fpclass == FP_PLUS_INF) - return(1); - if (fpclass == FP_MINUS_INF) - return(-1); - return(0); + int fpclass = class(x); + + if (fpclass == FP_PLUS_INF) + return (1); + if (fpclass == FP_MINUS_INF) + return (-1); + return (0); } -#endif /* aix */ + +#endif /* aix */ #if defined(ultrix4) #include <fp_class.h> -static int isinf(x) - double x; +static int +isinf(x) +double x; { - int fpclass = fp_class_d(x); - if (fpclass == FP_POS_INF) - return(1); - if (fpclass == FP_NEG_INF) - return(-1); - return(0); + int fpclass = fp_class_d(x); + + if (fpclass == FP_POS_INF) + return (1); + if (fpclass == FP_NEG_INF) + return (-1); + return (0); } -#endif /* ultrix4 */ + +#endif /* ultrix4 */ #if defined(alpha) #include <fp_class.h> -static int isinf(x) - double x; +static int +isinf(x) +double x; { - int fpclass = fp_class(x); - if (fpclass == FP_POS_INF) - return(1); - if (fpclass == FP_NEG_INF) - return(-1); - return(0); + int fpclass = fp_class(x); + + if (fpclass == FP_POS_INF) + return (1); + if (fpclass == FP_NEG_INF) + return (-1); + return (0); } -#endif /* alpha */ + +#endif /* alpha */ #if defined(sparc_solaris) || defined(i386_solaris) || defined(svr4) || \ - defined(sco) + defined(sco) #include <ieeefp.h> static int - isinf(d) -double d; -{ - fpclass_t type = fpclass(d); - switch (type) { - case FP_SNAN: - case FP_QNAN: - case FP_NINF: - case FP_PINF: - return (1); - default: - break; - } - - return (0); -} -#endif /* sparc_solaris */ +isinf(d) +double d; +{ + fpclass_t type = fpclass(d); + + switch (type) + { + case FP_SNAN: + case FP_QNAN: + case FP_NINF: + case FP_PINF: + return (1); + default: + break; + } + + return (0); +} + +#endif /* sparc_solaris */ #if defined(irix5) #include <ieeefp.h> static int - isinf(d) -double d; -{ - fpclass_t type = fpclass(d); - switch (type) { - case FP_SNAN: - case FP_QNAN: - case FP_NINF: - case FP_PINF: - return (1); - default: - break; - } - - return (0); -} -#endif /* irix5 */ - -#endif /* !HAVE_ISINF */ +isinf(d) +double d; +{ + fpclass_t type = fpclass(d); + + switch (type) + { + case FP_SNAN: + case FP_QNAN: + case FP_NINF: + case FP_PINF: + return (1); + default: + break; + } + + return (0); +} + +#endif /* irix5 */ + +#endif /* !HAVE_ISINF */ diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index d805ba7a220..71b478788ef 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -1,21 +1,21 @@ /*------------------------------------------------------------------------- * * geo_ops.c-- - * 2D geometric operations + * 2D geometric operations * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.19 1997/09/05 20:20:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.20 1997/09/07 04:50:18 momjian Exp $ * *------------------------------------------------------------------------- */ #include <math.h> #include <limits.h> #include <float.h> -#include <stdio.h> /* for sprintf proto, etc. */ -#include <stdlib.h> /* for strtod, etc. */ +#include <stdio.h> /* for sprintf proto, etc. */ +#include <stdlib.h> /* for strtod, etc. */ #include <string.h> #include <ctype.h> @@ -28,38 +28,38 @@ #define PI 3.1415926536 #endif -static int point_inside( Point *p, int npts, Point plist[]); -static int lseg_crossing( double x, double y, double px, double py); -static BOX *box_construct(double x1, double x2, double y1, double y2); -static BOX *box_copy(BOX *box); -static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2); -static double box_ht(BOX *box); -static double box_wd(BOX *box); -static double circle_ar(CIRCLE *circle); -static CIRCLE *circle_copy(CIRCLE *circle); -static LINE *line_construct_pm(Point *pt, double m); -static bool line_horizontal(LINE *line); -static Point *line_interpt(LINE *l1, LINE *l2); -static bool line_intersect(LINE *l1, LINE *l2); -static bool line_parallel(LINE *l1, LINE *l2); -static bool line_vertical(LINE *line); -static double lseg_dt(LSEG *l1, LSEG *l2); -static void make_bound_box(POLYGON *poly); -static PATH *path_copy(PATH *path); -static bool plist_same(int npts, Point p1[], Point p2[]); -static Point *point_construct(double x, double y); -static Point *point_copy(Point *pt); -static int single_decode(char *str, float8 *x, char **ss); -static int single_encode(float8 x, char *str); -static int pair_decode(char *str, float8 *x, float8 *y, char **s); -static int pair_encode(float8 x, float8 y, char *str); -static int pair_count(char *s, char delim); -static int path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p); -static char *path_encode( bool closed, int npts, Point *pt); -static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2); -static double box_ar(BOX *box); -static Point *interpt_sl(LSEG *lseg, LINE *line); -static LINE *line_construct_pp(Point *pt1, Point *pt2); +static int point_inside(Point * p, int npts, Point plist[]); +static int lseg_crossing(double x, double y, double px, double py); +static BOX *box_construct(double x1, double x2, double y1, double y2); +static BOX *box_copy(BOX * box); +static BOX *box_fill(BOX * result, double x1, double x2, double y1, double y2); +static double box_ht(BOX * box); +static double box_wd(BOX * box); +static double circle_ar(CIRCLE * circle); +static CIRCLE *circle_copy(CIRCLE * circle); +static LINE *line_construct_pm(Point * pt, double m); +static bool line_horizontal(LINE * line); +static Point *line_interpt(LINE * l1, LINE * l2); +static bool line_intersect(LINE * l1, LINE * l2); +static bool line_parallel(LINE * l1, LINE * l2); +static bool line_vertical(LINE * line); +static double lseg_dt(LSEG * l1, LSEG * l2); +static void make_bound_box(POLYGON * poly); +static PATH *path_copy(PATH * path); +static bool plist_same(int npts, Point p1[], Point p2[]); +static Point *point_construct(double x, double y); +static Point *point_copy(Point * pt); +static int single_decode(char *str, float8 * x, char **ss); +static int single_encode(float8 x, char *str); +static int pair_decode(char *str, float8 * x, float8 * y, char **s); +static int pair_encode(float8 x, float8 y, char *str); +static int pair_count(char *s, char delim); +static int path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point * p); +static char *path_encode(bool closed, int npts, Point * pt); +static void statlseg_construct(LSEG * lseg, Point * pt1, Point * pt2); +static double box_ar(BOX * box); +static Point *interpt_sl(LSEG * lseg, LINE * line); +static LINE *line_construct_pp(Point * pt1, Point * pt2); /* @@ -68,203 +68,248 @@ static LINE *line_construct_pp(Point *pt1, Point *pt2); * LDELIM_EP, RDELIM_EP are left and right delimiters for paths with endpoints. */ -#define LDELIM '(' -#define RDELIM ')' -#define DELIM ',' -#define LDELIM_EP '[' -#define RDELIM_EP ']' -#define LDELIM_C '<' -#define RDELIM_C '>' +#define LDELIM '(' +#define RDELIM ')' +#define DELIM ',' +#define LDELIM_EP '[' +#define RDELIM_EP ']' +#define LDELIM_C '<' +#define RDELIM_C '>' /* Maximum number of output digits printed */ #define P_MAXDIG DBL_DIG #define P_MAXLEN (2*(P_MAXDIG+7)+1) -static int digits8 = P_MAXDIG; +static int digits8 = P_MAXDIG; /* * Geometric data types are composed of points. * This code tries to support a common format throughout the data types, - * to allow for more predictable usage and data type conversion. + * to allow for more predictable usage and data type conversion. * The fundamental unit is the point. Other units are line segments, - * open paths, boxes, closed paths, and polygons (which should be considered - * non-intersecting closed paths). + * open paths, boxes, closed paths, and polygons (which should be considered + * non-intersecting closed paths). * * Data representation is as follows: - * point: (x,y) - * line segment: [(x1,y1),(x2,y2)] - * box: (x1,y1),(x2,y2) - * open path: [(x1,y1),...,(xn,yn)] - * closed path: ((x1,y1),...,(xn,yn)) - * polygon: ((x1,y1),...,(xn,yn)) + * point: (x,y) + * line segment: [(x1,y1),(x2,y2)] + * box: (x1,y1),(x2,y2) + * open path: [(x1,y1),...,(xn,yn)] + * closed path: ((x1,y1),...,(xn,yn)) + * polygon: ((x1,y1),...,(xn,yn)) * * For boxes, the points are opposite corners with the first point at the top right. * For closed paths and polygons, the points should be reordered to allow - * fast and correct equality comparisons. + * fast and correct equality comparisons. * * XXX perhaps points in complex shapes should be reordered internally - * to allow faster internal operations, but should keep track of input order - * and restore that order for text output - tgl 97/01/16 + * to allow faster internal operations, but should keep track of input order + * and restore that order for text output - tgl 97/01/16 */ -static int single_decode(char *str, float8 *x, char **s) +static int +single_decode(char *str, float8 * x, char **s) { - char *cp; + char *cp; - if (!PointerIsValid(str)) - return(FALSE); + if (!PointerIsValid(str)) + return (FALSE); - while (isspace( *str)) str++; - *x = strtod( str, &cp); + while (isspace(*str)) + str++; + *x = strtod(str, &cp); #ifdef GEODEBUG -fprintf( stderr, "single_decode- (%x) try decoding %s to %g\n", (cp-str), str, *x); + fprintf(stderr, "single_decode- (%x) try decoding %s to %g\n", (cp - str), str, *x); #endif - if (cp <= str) return(FALSE); - while (isspace( *cp)) cp++; - - if (s != NULL) *s = cp; + if (cp <= str) + return (FALSE); + while (isspace(*cp)) + cp++; - return(TRUE); -} /* single_decode() */ + if (s != NULL) + *s = cp; -static int single_encode(float8 x, char *str) -{ - sprintf(str, "%.*g", digits8, x); - return(TRUE); -} /* single_encode() */ + return (TRUE); +} /* single_decode() */ -static int pair_decode(char *str, float8 *x, float8 *y, char **s) +static int +single_encode(float8 x, char *str) { - int has_delim; - char *cp; - - if (!PointerIsValid(str)) - return(FALSE); - - while (isspace( *str)) str++; - if ((has_delim = (*str == LDELIM))) str++; + sprintf(str, "%.*g", digits8, x); + return (TRUE); +} /* single_encode() */ - while (isspace( *str)) str++; - *x = strtod( str, &cp); - if (cp <= str) return(FALSE); - while (isspace( *cp)) cp++; - if (*cp++ != DELIM) return(FALSE); - while (isspace( *cp)) cp++; - *y = strtod( cp, &str); - if (str <= cp) return(FALSE); - while (isspace( *str)) str++; - if (has_delim) { - if (*str != RDELIM) return(FALSE); - str++; - while (isspace( *str)) str++; - } - if (s != NULL) *s = str; +static int +pair_decode(char *str, float8 * x, float8 * y, char **s) +{ + int has_delim; + char *cp; + + if (!PointerIsValid(str)) + return (FALSE); + + while (isspace(*str)) + str++; + if ((has_delim = (*str == LDELIM))) + str++; + + while (isspace(*str)) + str++; + *x = strtod(str, &cp); + if (cp <= str) + return (FALSE); + while (isspace(*cp)) + cp++; + if (*cp++ != DELIM) + return (FALSE); + while (isspace(*cp)) + cp++; + *y = strtod(cp, &str); + if (str <= cp) + return (FALSE); + while (isspace(*str)) + str++; + if (has_delim) + { + if (*str != RDELIM) + return (FALSE); + str++; + while (isspace(*str)) + str++; + } + if (s != NULL) + *s = str; - return(TRUE); + return (TRUE); } -static int pair_encode(float8 x, float8 y, char *str) +static int +pair_encode(float8 x, float8 y, char *str) { - sprintf(str, "%.*g,%.*g", digits8, x, digits8, y); - return(TRUE); + sprintf(str, "%.*g,%.*g", digits8, x, digits8, y); + return (TRUE); } -static int path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p) -{ - int depth = 0; - char *s, *cp; - int i; - - s = str; - while (isspace( *s)) s++; - if ((*isopen = (*s == LDELIM_EP))) { - /* no open delimiter allowed? */ - if (! opentype) return(FALSE); - depth++; - s++; - while (isspace( *s)) s++; +static int +path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point * p) +{ + int depth = 0; + char *s, + *cp; + int i; + + s = str; + while (isspace(*s)) + s++; + if ((*isopen = (*s == LDELIM_EP))) + { + /* no open delimiter allowed? */ + if (!opentype) + return (FALSE); + depth++; + s++; + while (isspace(*s)) + s++; - } else if (*s == LDELIM) { - cp = (s+1); - while (isspace( *cp)) cp++; - if (*cp == LDELIM) { - /* nested delimiters with only one point? */ - if (npts <= 1) return(FALSE); - depth++; - s = cp; - } else if (strrchr( s, LDELIM) == s) { - depth++; - s = cp; } - } - - for (i = 0; i < npts; i++) { - if (! pair_decode( s, &(p->x), &(p->y), &s)) - return(FALSE); + else if (*s == LDELIM) + { + cp = (s + 1); + while (isspace(*cp)) + cp++; + if (*cp == LDELIM) + { + /* nested delimiters with only one point? */ + if (npts <= 1) + return (FALSE); + depth++; + s = cp; + } + else if (strrchr(s, LDELIM) == s) + { + depth++; + s = cp; + } + } - if (*s == DELIM) s++; - p++; - } + for (i = 0; i < npts; i++) + { + if (!pair_decode(s, &(p->x), &(p->y), &s)) + return (FALSE); - while (depth > 0) { - if ((*s == RDELIM) - || ((*s == RDELIM_EP) && (*isopen) && (depth == 1))) { - depth--; - s++; - while (isspace( *s)) s++; - } else { - return(FALSE); + if (*s == DELIM) + s++; + p++; } - } - *ss = s; - return(TRUE); -} /* path_decode() */ + while (depth > 0) + { + if ((*s == RDELIM) + || ((*s == RDELIM_EP) && (*isopen) && (depth == 1))) + { + depth--; + s++; + while (isspace(*s)) + s++; + } + else + { + return (FALSE); + } + } + *ss = s; + + return (TRUE); +} /* path_decode() */ + +static char * +path_encode(bool closed, int npts, Point * pt) +{ + char *result = PALLOC(npts * (P_MAXLEN + 3) + 2); + + char *cp; + int i; + + cp = result; + switch (closed) + { + case TRUE: + *cp++ = LDELIM; + break; + case FALSE: + *cp++ = LDELIM_EP; + break; + default: + break; + } -static char *path_encode( bool closed, int npts, Point *pt) -{ - char *result = PALLOC(npts*(P_MAXLEN+3)+2); + for (i = 0; i < npts; i++) + { + *cp++ = LDELIM; + if (!pair_encode(pt->x, pt->y, cp)) + elog(WARN, "Unable to format path", NULL); + cp += strlen(cp); + *cp++ = RDELIM; + *cp++ = DELIM; + pt++; + } + cp--; + switch (closed) + { + case TRUE: + *cp++ = RDELIM; + break; + case FALSE: + *cp++ = RDELIM_EP; + break; + default: + break; + } + *cp = '\0'; - char *cp; - int i; - - cp = result; - switch (closed) { - case TRUE: - *cp++ = LDELIM; - break; - case FALSE: - *cp++ = LDELIM_EP; - break; - default: - break; - } - - for (i = 0; i < npts; i++) { - *cp++ = LDELIM; - if (! pair_encode( pt->x, pt->y, cp)) - elog (WARN, "Unable to format path", NULL); - cp += strlen(cp); - *cp++ = RDELIM; - *cp++ = DELIM; - pt++; - } - cp--; - switch (closed) { - case TRUE: - *cp++ = RDELIM; - break; - case FALSE: - *cp++ = RDELIM_EP; - break; - default: - break; - } - *cp = '\0'; - - return(result); -} /* path_encode() */ + return (result); +} /* path_encode() */ /*------------------------------------------------------------- * pair_count - count the number of points @@ -273,20 +318,22 @@ static char *path_encode( bool closed, int npts, Point *pt) * '(1,3,2,4)' * require an odd number of delim characters in the string *-------------------------------------------------------------*/ -static int pair_count(char *s, char delim) +static int +pair_count(char *s, char delim) { - int ndelim = 0; + int ndelim = 0; - while ((s = strchr( s, delim)) != NULL) { - ndelim++; - s++; - } - return((ndelim % 2)? ((ndelim+1)/2): -1); + while ((s = strchr(s, delim)) != NULL) + { + ndelim++; + s++; + } + return ((ndelim % 2) ? ((ndelim + 1) / 2) : -1); } /*********************************************************************** ** - ** Routines for two-dimensional boxes. + ** Routines for two-dimensional boxes. ** ***********************************************************************/ @@ -294,716 +341,795 @@ static int pair_count(char *s, char delim) * Formatting and conversion routines. *---------------------------------------------------------*/ -/* box_in - convert a string to internal form. +/* box_in - convert a string to internal form. * - * External format: (two corners of box) - * "(f8, f8), (f8, f8)" - * also supports the older style "(f8, f8, f8, f8)" + * External format: (two corners of box) + * "(f8, f8), (f8, f8)" + * also supports the older style "(f8, f8, f8, f8)" */ -BOX *box_in(char *str) +BOX * +box_in(char *str) { - BOX *box = PALLOCTYPE(BOX); + BOX *box = PALLOCTYPE(BOX); - int isopen; - char *s; - double x, y; + int isopen; + char *s; + double x, + y; - if (!PointerIsValid(str)) - elog (WARN," Bad (null) box external representation",NULL); + if (!PointerIsValid(str)) + elog(WARN, " Bad (null) box external representation", NULL); - if ((! path_decode(FALSE, 2, str, &isopen, &s, &(box->high))) - || (*s != '\0')) - elog (WARN, "Bad box external representation '%s'",str); + if ((!path_decode(FALSE, 2, str, &isopen, &s, &(box->high))) + || (*s != '\0')) + elog(WARN, "Bad box external representation '%s'", str); - /* reorder corners if necessary... */ - if (box->high.x < box->low.x) { - x = box->high.x; - box->high.x = box->low.x; - box->low.x = x; - } - if (box->high.y < box->low.y) { - y = box->high.y; - box->high.y = box->low.y; - box->low.y = y; - } + /* reorder corners if necessary... */ + if (box->high.x < box->low.x) + { + x = box->high.x; + box->high.x = box->low.x; + box->low.x = x; + } + if (box->high.y < box->low.y) + { + y = box->high.y; + box->high.y = box->low.y; + box->low.y = y; + } - return(box); -} /* box_in() */ + return (box); +} /* box_in() */ -/* box_out - convert a box to external form. +/* box_out - convert a box to external form. */ -char *box_out(BOX *box) +char * +box_out(BOX * box) { - if (!PointerIsValid(box)) - return(NULL); + if (!PointerIsValid(box)) + return (NULL); - return( path_encode( -1, 2, (Point *) &(box->high))); -} /* box_out() */ + return (path_encode(-1, 2, (Point *) & (box->high))); +} /* box_out() */ -/* box_construct - fill in a new box. +/* box_construct - fill in a new box. */ -static BOX *box_construct(double x1, double x2, double y1, double y2) +static BOX * +box_construct(double x1, double x2, double y1, double y2) { - BOX *result = PALLOCTYPE(BOX); + BOX *result = PALLOCTYPE(BOX); - return( box_fill(result, x1, x2, y1, y2) ); + return (box_fill(result, x1, x2, y1, y2)); } -/* box_fill - fill in a static box +/* box_fill - fill in a static box */ -static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2) +static BOX * +box_fill(BOX * result, double x1, double x2, double y1, double y2) { - if (x1 > x2) { - result->high.x = x1; - result->low.x = x2; - } else { - result->high.x = x2; - result->low.x = x1; - } - if (y1 > y2) { - result->high.y = y1; - result->low.y = y2; - } else { - result->high.y = y2; - result->low.y = y1; - } - - return(result); + if (x1 > x2) + { + result->high.x = x1; + result->low.x = x2; + } + else + { + result->high.x = x2; + result->low.x = x1; + } + if (y1 > y2) + { + result->high.y = y1; + result->low.y = y2; + } + else + { + result->high.y = y2; + result->low.y = y1; + } + + return (result); } -/* box_copy - copy a box +/* box_copy - copy a box */ -static BOX *box_copy(BOX *box) +static BOX * +box_copy(BOX * box) { - BOX *result = PALLOCTYPE(BOX); + BOX *result = PALLOCTYPE(BOX); - memmove((char *) result, (char *) box, sizeof(BOX)); - - return(result); + memmove((char *) result, (char *) box, sizeof(BOX)); + + return (result); } /*---------------------------------------------------------- - * Relational operators for BOXes. - * <, >, <=, >=, and == are based on box area. + * Relational operators for BOXes. + * <, >, <=, >=, and == are based on box area. *---------------------------------------------------------*/ -/* box_same - are two boxes identical? +/* box_same - are two boxes identical? */ -bool box_same(BOX *box1, BOX *box2) +bool +box_same(BOX * box1, BOX * box2) { - return((FPeq(box1->high.x,box2->high.x) && FPeq(box1->low.x,box2->low.x)) && - (FPeq(box1->high.y,box2->high.y) && FPeq(box1->low.y,box2->low.y))); + return ((FPeq(box1->high.x, box2->high.x) && FPeq(box1->low.x, box2->low.x)) && + (FPeq(box1->high.y, box2->high.y) && FPeq(box1->low.y, box2->low.y))); } -/* box_overlap - does box1 overlap box2? +/* box_overlap - does box1 overlap box2? */ -bool box_overlap(BOX *box1, BOX *box2) +bool +box_overlap(BOX * box1, BOX * box2) { - return(((FPge(box1->high.x,box2->high.x) && FPle(box1->low.x,box2->high.x)) || - (FPge(box2->high.x,box1->high.x) && FPle(box2->low.x,box1->high.x))) && - ((FPge(box1->high.y,box2->high.y) && FPle(box1->low.y,box2->high.y)) || - (FPge(box2->high.y,box1->high.y) && FPle(box2->low.y,box1->high.y))) ); + return (((FPge(box1->high.x, box2->high.x) && FPle(box1->low.x, box2->high.x)) || + (FPge(box2->high.x, box1->high.x) && FPle(box2->low.x, box1->high.x))) && + ((FPge(box1->high.y, box2->high.y) && FPle(box1->low.y, box2->high.y)) || + (FPge(box2->high.y, box1->high.y) && FPle(box2->low.y, box1->high.y)))); } -/* box_overleft - is the right edge of box1 to the left of - * the right edge of box2? +/* box_overleft - is the right edge of box1 to the left of + * the right edge of box2? * - * This is "less than or equal" for the end of a time range, - * when time ranges are stored as rectangles. + * This is "less than or equal" for the end of a time range, + * when time ranges are stored as rectangles. */ -bool box_overleft(BOX *box1, BOX *box2) +bool +box_overleft(BOX * box1, BOX * box2) { - return(FPle(box1->high.x,box2->high.x)); + return (FPle(box1->high.x, box2->high.x)); } -/* box_left - is box1 strictly left of box2? +/* box_left - is box1 strictly left of box2? */ -bool box_left(BOX *box1, BOX *box2) +bool +box_left(BOX * box1, BOX * box2) { - return(FPlt(box1->high.x,box2->low.x)); + return (FPlt(box1->high.x, box2->low.x)); } -/* box_right - is box1 strictly right of box2? +/* box_right - is box1 strictly right of box2? */ -bool box_right(BOX *box1, BOX *box2) +bool +box_right(BOX * box1, BOX * box2) { - return(FPgt(box1->low.x,box2->high.x)); + return (FPgt(box1->low.x, box2->high.x)); } -/* box_overright - is the left edge of box1 to the right of - * the left edge of box2? +/* box_overright - is the left edge of box1 to the right of + * the left edge of box2? * - * This is "greater than or equal" for time ranges, when time ranges - * are stored as rectangles. + * This is "greater than or equal" for time ranges, when time ranges + * are stored as rectangles. */ -bool box_overright(BOX *box1, BOX *box2) +bool +box_overright(BOX * box1, BOX * box2) { - return(box1->low.x >= box2->low.x); + return (box1->low.x >= box2->low.x); } -/* box_contained - is box1 contained by box2? +/* box_contained - is box1 contained by box2? */ -bool box_contained(BOX *box1, BOX *box2) +bool +box_contained(BOX * box1, BOX * box2) { - return((FPle(box1->high.x,box2->high.x) && FPge(box1->low.x,box2->low.x)) && - (FPle(box1->high.y,box2->high.y) && FPge(box1->low.y,box2->low.y))); + return ((FPle(box1->high.x, box2->high.x) && FPge(box1->low.x, box2->low.x)) && + (FPle(box1->high.y, box2->high.y) && FPge(box1->low.y, box2->low.y))); } -/* box_contain - does box1 contain box2? +/* box_contain - does box1 contain box2? */ -bool box_contain(BOX *box1, BOX *box2) +bool +box_contain(BOX * box1, BOX * box2) { - return((FPge(box1->high.x,box2->high.x) && FPle(box1->low.x,box2->low.x) && - FPge(box1->high.y,box2->high.y) && FPle(box1->low.y,box2->low.y))); + return ((FPge(box1->high.x, box2->high.x) && FPle(box1->low.x, box2->low.x) && + FPge(box1->high.y, box2->high.y) && FPle(box1->low.y, box2->low.y))); } -/* box_positionop - - * is box1 entirely {above,below} box2? +/* box_positionop - + * is box1 entirely {above,below} box2? */ -bool box_below(BOX *box1, BOX *box2) +bool +box_below(BOX * box1, BOX * box2) { - return( FPle(box1->high.y,box2->low.y) ); + return (FPle(box1->high.y, box2->low.y)); } -bool box_above(BOX *box1, BOX *box2) +bool +box_above(BOX * box1, BOX * box2) { - return( FPge(box1->low.y,box2->high.y) ); + return (FPge(box1->low.y, box2->high.y)); } -/* box_relop - is area(box1) relop area(box2), within - * our accuracy constraint? +/* box_relop - is area(box1) relop area(box2), within + * our accuracy constraint? */ -bool box_lt(BOX *box1, BOX *box2) +bool +box_lt(BOX * box1, BOX * box2) { - return( FPlt(box_ar(box1), box_ar(box2)) ); + return (FPlt(box_ar(box1), box_ar(box2))); } -bool box_gt(BOX *box1, BOX *box2) +bool +box_gt(BOX * box1, BOX * box2) { - return( FPgt(box_ar(box1), box_ar(box2)) ); + return (FPgt(box_ar(box1), box_ar(box2))); } -bool box_eq(BOX *box1, BOX *box2) +bool +box_eq(BOX * box1, BOX * box2) { - return( FPeq(box_ar(box1), box_ar(box2)) ); + return (FPeq(box_ar(box1), box_ar(box2))); } -bool box_le(BOX *box1, BOX *box2) +bool +box_le(BOX * box1, BOX * box2) { - return( FPle(box_ar(box1), box_ar(box2)) ); + return (FPle(box_ar(box1), box_ar(box2))); } -bool box_ge(BOX *box1, BOX *box2) +bool +box_ge(BOX * box1, BOX * box2) { - return( FPge(box_ar(box1), box_ar(box2)) ); + return (FPge(box_ar(box1), box_ar(box2))); } /*---------------------------------------------------------- - * "Arithmetic" operators on boxes. - * box_foo returns foo as an object (pointer) that + * "Arithmetic" operators on boxes. + * box_foo returns foo as an object (pointer) that can be passed between languages. - * box_xx is an internal routine which returns the - * actual value (and cannot be handed back to - * LISP). + * box_xx is an internal routine which returns the + * actual value (and cannot be handed back to + * LISP). *---------------------------------------------------------*/ -/* box_area - returns the area of the box. +/* box_area - returns the area of the box. */ -double *box_area(BOX *box) +double * +box_area(BOX * box) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); - *result = box_wd(box) * box_ht(box); - - return(result); + *result = box_wd(box) * box_ht(box); + + return (result); } -/* box_width - returns the width of the box - * (horizontal magnitude). +/* box_width - returns the width of the box + * (horizontal magnitude). */ -double *box_width(BOX *box) +double * +box_width(BOX * box) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); + + *result = box->high.x - box->low.x; - *result = box->high.x - box->low.x; - - return(result); -} /* box_width() */ + return (result); +} /* box_width() */ -/* box_height - returns the height of the box - * (vertical magnitude). +/* box_height - returns the height of the box + * (vertical magnitude). */ -double *box_height(BOX *box) +double * +box_height(BOX * box) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); + + *result = box->high.y - box->low.y; - *result = box->high.y - box->low.y; - - return(result); + return (result); } -/* box_distance - returns the distance between the - * center points of two boxes. +/* box_distance - returns the distance between the + * center points of two boxes. */ -double *box_distance(BOX *box1, BOX *box2) +double * +box_distance(BOX * box1, BOX * box2) { - double *result = PALLOCTYPE(double); - Point *a, *b; - - a = box_center(box1); - b = box_center(box2); - *result = HYPOT(a->x - b->x, a->y - b->y); - - PFREE(a); - PFREE(b); - return(result); + double *result = PALLOCTYPE(double); + Point *a, + *b; + + a = box_center(box1); + b = box_center(box2); + *result = HYPOT(a->x - b->x, a->y - b->y); + + PFREE(a); + PFREE(b); + return (result); } -/* box_center - returns the center point of the box. +/* box_center - returns the center point of the box. */ -Point *box_center(BOX *box) +Point * +box_center(BOX * box) { - Point *result = PALLOCTYPE(Point); + Point *result = PALLOCTYPE(Point); - result->x = (box->high.x + box->low.x) / 2.0; - result->y = (box->high.y + box->low.y) / 2.0; - - return(result); + result->x = (box->high.x + box->low.x) / 2.0; + result->y = (box->high.y + box->low.y) / 2.0; + + return (result); } -/* box_ar - returns the area of the box. +/* box_ar - returns the area of the box. */ -static double box_ar(BOX *box) +static double +box_ar(BOX * box) { - return( box_wd(box) * box_ht(box) ); + return (box_wd(box) * box_ht(box)); } -/* box_wd - returns the width (length) of the box - * (horizontal magnitude). +/* box_wd - returns the width (length) of the box + * (horizontal magnitude). */ -static double box_wd(BOX *box) +static double +box_wd(BOX * box) { - return( box->high.x - box->low.x ); + return (box->high.x - box->low.x); } -/* box_ht - returns the height of the box - * (vertical magnitude). +/* box_ht - returns the height of the box + * (vertical magnitude). */ -static double box_ht(BOX *box) +static double +box_ht(BOX * box) { - return( box->high.y - box->low.y ); + return (box->high.y - box->low.y); } -/* box_dt - returns the distance between the - * center points of two boxes. +/* box_dt - returns the distance between the + * center points of two boxes. */ #ifdef NOT_USED -static double box_dt(BOX *box1, BOX *box2) -{ - double result; - Point *a, *b; - - a = box_center(box1); - b = box_center(box2); - result = HYPOT(a->x - b->x, a->y - b->y); - - PFREE(a); - PFREE(b); - return(result); +static double +box_dt(BOX * box1, BOX * box2) +{ + double result; + Point *a, + *b; + + a = box_center(box1); + b = box_center(box2); + result = HYPOT(a->x - b->x, a->y - b->y); + + PFREE(a); + PFREE(b); + return (result); } + #endif /*---------------------------------------------------------- - * Funky operations. + * Funky operations. *---------------------------------------------------------*/ -/* box_intersect - - * returns the overlapping portion of two boxes, - * or NULL if they do not intersect. +/* box_intersect - + * returns the overlapping portion of two boxes, + * or NULL if they do not intersect. */ -BOX *box_intersect(BOX *box1, BOX *box2) +BOX * +box_intersect(BOX * box1, BOX * box2) { - BOX *result; + BOX *result; + + if (!box_overlap(box1, box2)) + return (NULL); - if (! box_overlap(box1,box2)) - return(NULL); + result = PALLOCTYPE(BOX); - result = PALLOCTYPE(BOX); + result->high.x = Min(box1->high.x, box2->high.x); + result->low.x = Max(box1->low.x, box2->low.x); + result->high.y = Min(box1->high.y, box2->high.y); + result->low.y = Max(box1->low.y, box2->low.y); - result->high.x = Min(box1->high.x, box2->high.x); - result->low.x = Max(box1->low.x, box2->low.x); - result->high.y = Min(box1->high.y, box2->high.y); - result->low.y = Max(box1->low.y, box2->low.y); - - return(result); + return (result); } -/* box_diagonal - - * returns a line segment which happens to be the - * positive-slope diagonal of "box". - * provided, of course, we have LSEGs. +/* box_diagonal - + * returns a line segment which happens to be the + * positive-slope diagonal of "box". + * provided, of course, we have LSEGs. */ -LSEG *box_diagonal(BOX *box) +LSEG * +box_diagonal(BOX * box) { - Point p1, p2; - - p1.x = box->high.x; - p1.y = box->high.y; - p2.x = box->low.x; - p2.y = box->low.y; - return( lseg_construct( &p1, &p2 ) ); - + Point p1, + p2; + + p1.x = box->high.x; + p1.y = box->high.y; + p2.x = box->low.x; + p2.y = box->low.y; + return (lseg_construct(&p1, &p2)); + } /*********************************************************************** ** - ** Routines for 2D lines. - ** Lines are not intended to be used as ADTs per se, - ** but their ops are useful tools for other ADT ops. Thus, - ** there are few relops. + ** Routines for 2D lines. + ** Lines are not intended to be used as ADTs per se, + ** but their ops are useful tools for other ADT ops. Thus, + ** there are few relops. ** ***********************************************************************/ /*---------------------------------------------------------- - * Conversion routines from one line formula to internal. - * Internal form: Ax+By+C=0 + * Conversion routines from one line formula to internal. + * Internal form: Ax+By+C=0 *---------------------------------------------------------*/ -static LINE * /* point-slope */ -line_construct_pm(Point *pt, double m) +static LINE * /* point-slope */ +line_construct_pm(Point * pt, double m) { - LINE *result = PALLOCTYPE(LINE); + LINE *result = PALLOCTYPE(LINE); - /* use "mx - y + yinter = 0" */ - result->A = m; - result->B = -1.0; - result->C = pt->y - m * pt->x; + /* use "mx - y + yinter = 0" */ + result->A = m; + result->B = -1.0; + result->C = pt->y - m * pt->x; - result->m = m; + result->m = m; - return(result); -} /* line_construct_pm() */ + return (result); +} /* line_construct_pm() */ -static LINE * /* two points */ -line_construct_pp(Point *pt1, Point *pt2) +static LINE * /* two points */ +line_construct_pp(Point * pt1, Point * pt2) { - LINE *result = PALLOCTYPE(LINE); + LINE *result = PALLOCTYPE(LINE); - if (FPeq(pt1->x, pt2->x)) { /* vertical */ - /* use "x = C" */ - result->A = -1; - result->B = 0; - result->C = pt1->x; + if (FPeq(pt1->x, pt2->x)) + { /* vertical */ + /* use "x = C" */ + result->A = -1; + result->B = 0; + result->C = pt1->x; #ifdef GEODEBUG -printf( "line_construct_pp- line is vertical\n"); + printf("line_construct_pp- line is vertical\n"); #endif - result->m = DBL_MAX; + result->m = DBL_MAX; - } else if (FPeq(pt1->y, pt2->y)) { /* horizontal */ - /* use "x = C" */ - result->A = 0; - result->B = -1; - result->C = pt1->y; + } + else if (FPeq(pt1->y, pt2->y)) + { /* horizontal */ + /* use "x = C" */ + result->A = 0; + result->B = -1; + result->C = pt1->y; #ifdef GEODEBUG -printf( "line_construct_pp- line is horizontal\n"); + printf("line_construct_pp- line is horizontal\n"); #endif - result->m = 0.0; + result->m = 0.0; - } else { - /* use "mx - y + yinter = 0" */ + } + else + { + /* use "mx - y + yinter = 0" */ #if FALSE - result->A = (pt1->y - pt2->y) / (pt1->x - pt2->x); + result->A = (pt1->y - pt2->y) / (pt1->x - pt2->x); #endif - result->A = (pt2->y - pt1->y) / (pt2->x - pt1->x); - result->B = -1.0; - result->C = pt1->y - result->A * pt1->x; + result->A = (pt2->y - pt1->y) / (pt2->x - pt1->x); + result->B = -1.0; + result->C = pt1->y - result->A * pt1->x; #ifdef GEODEBUG -printf( "line_construct_pp- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n", - digits8, (pt2->x - pt1->x), digits8, (pt2->y - pt1->y)); + printf("line_construct_pp- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n", + digits8, (pt2->x - pt1->x), digits8, (pt2->y - pt1->y)); #endif - result->m = result->A; - } - return(result); -} /* line_construct_pp() */ + result->m = result->A; + } + return (result); +} /* line_construct_pp() */ /*---------------------------------------------------------- - * Relative position routines. + * Relative position routines. *---------------------------------------------------------*/ -static bool line_intersect(LINE *l1, LINE *l2) +static bool +line_intersect(LINE * l1, LINE * l2) { - return( ! line_parallel(l1, l2) ); + return (!line_parallel(l1, l2)); } -static bool line_parallel(LINE *l1, LINE *l2) +static bool +line_parallel(LINE * l1, LINE * l2) { #if FALSE - return( FPeq(l1->m, l2->m) ); + return (FPeq(l1->m, l2->m)); #endif - if (FPzero(l1->B)) { - return(FPzero(l2->B)); - } + if (FPzero(l1->B)) + { + return (FPzero(l2->B)); + } - return(FPeq(l2->A, l1->A*(l2->B / l1->B))); -} /* line_parallel() */ + return (FPeq(l2->A, l1->A * (l2->B / l1->B))); +} /* line_parallel() */ #ifdef NOT_USED -bool line_perp(LINE *l1, LINE *l2) +bool +line_perp(LINE * l1, LINE * l2) { #if FALSE - if (l1->m) - return( FPeq(l2->m / l1->m, -1.0) ); - else if (l2->m) - return( FPeq(l1->m / l2->m, -1.0) ); + if (l1->m) + return (FPeq(l2->m / l1->m, -1.0)); + else if (l2->m) + return (FPeq(l1->m / l2->m, -1.0)); #endif - if (FPzero(l1->A)) { - return( FPzero(l2->B) ); - } else if (FPzero(l1->B)) { - return( FPzero(l2->A) ); - } - - return( FPeq(((l1->A * l2->B) / (l1->B * l2->A)), -1.0) ); -} /* line_perp() */ + if (FPzero(l1->A)) + { + return (FPzero(l2->B)); + } + else if (FPzero(l1->B)) + { + return (FPzero(l2->A)); + } + + return (FPeq(((l1->A * l2->B) / (l1->B * l2->A)), -1.0)); +} /* line_perp() */ + #endif -static bool line_vertical(LINE *line) +static bool +line_vertical(LINE * line) { #if FALSE - return( FPeq(line->A, -1.0) && FPzero(line->B) ); + return (FPeq(line->A, -1.0) && FPzero(line->B)); #endif - return( FPzero(line->B) ); -} /* line_vertical() */ + return (FPzero(line->B)); +} /* line_vertical() */ -static bool line_horizontal(LINE *line) +static bool +line_horizontal(LINE * line) { #if FALSE - return( FPzero(line->m) ); + return (FPzero(line->m)); #endif - return( FPzero(line->A) ); -} /* line_horizontal() */ + return (FPzero(line->A)); +} /* line_horizontal() */ #ifdef NOT_USED -bool line_eq(LINE *l1, LINE *l2) -{ - double k; - - if (! FPzero(l2->A)) - k = l1->A / l2->A; - else if (! FPzero(l2->B)) - k = l1->B / l2->B; - else if (! FPzero(l2->C)) - k = l1->C / l2->C; - else - k = 1.0; - - return( FPeq(l1->A, k * l2->A) && - FPeq(l1->B, k * l2->B) && - FPeq(l1->C, k * l2->C) ); +bool +line_eq(LINE * l1, LINE * l2) +{ + double k; + + if (!FPzero(l2->A)) + k = l1->A / l2->A; + else if (!FPzero(l2->B)) + k = l1->B / l2->B; + else if (!FPzero(l2->C)) + k = l1->C / l2->C; + else + k = 1.0; + + return (FPeq(l1->A, k * l2->A) && + FPeq(l1->B, k * l2->B) && + FPeq(l1->C, k * l2->C)); } + #endif /*---------------------------------------------------------- - * Line arithmetic routines. + * Line arithmetic routines. *---------------------------------------------------------*/ -double * /* distance between l1, l2 */ -line_distance(LINE *l1, LINE *l2) -{ - double *result = PALLOCTYPE(double); - Point *tmp; - - if (line_intersect(l1, l2)) { - *result = 0.0; - return(result); - } - if (line_vertical(l1)) - *result = fabs(l1->C - l2->C); - else { - tmp = point_construct(0.0, l1->C); - result = dist_pl(tmp, l2); - PFREE(tmp); - } - return(result); +double * /* distance between l1, l2 */ +line_distance(LINE * l1, LINE * l2) +{ + double *result = PALLOCTYPE(double); + Point *tmp; + + if (line_intersect(l1, l2)) + { + *result = 0.0; + return (result); + } + if (line_vertical(l1)) + *result = fabs(l1->C - l2->C); + else + { + tmp = point_construct(0.0, l1->C); + result = dist_pl(tmp, l2); + PFREE(tmp); + } + return (result); } /* line_interpt() * Point where two lines l1, l2 intersect (if any) */ -static Point * -line_interpt(LINE *l1, LINE *l2) +static Point * +line_interpt(LINE * l1, LINE * l2) { - Point *result; - double x, y; - - if (line_parallel(l1, l2)) - return(NULL); + Point *result; + double x, + y; + + if (line_parallel(l1, l2)) + return (NULL); #if FALSE - if (line_vertical(l1)) - result = point_construct(l2->m * l1->C + l2->C, l1->C); - else if (line_vertical(l2)) - result = point_construct(l1->m * l2->C + l1->C, l2->C); - else { - x = (l1->C - l2->C) / (l2->A - l1->A); - result = point_construct(x, l1->m * x + l1->C); - } + if (line_vertical(l1)) + result = point_construct(l2->m * l1->C + l2->C, l1->C); + else if (line_vertical(l2)) + result = point_construct(l1->m * l2->C + l1->C, l2->C); + else + { + x = (l1->C - l2->C) / (l2->A - l1->A); + result = point_construct(x, l1->m * x + l1->C); + } #endif - if (line_vertical(l1)) { + if (line_vertical(l1)) + { #if FALSE - x = l1->C; - y = -((l2->A * x + l2->C) / l2->B); + x = l1->C; + y = -((l2->A * x + l2->C) / l2->B); #endif - x = l1->C; - y = (l2->A * x + l2->C); + x = l1->C; + y = (l2->A * x + l2->C); - } else if (line_vertical(l2)) { + } + else if (line_vertical(l2)) + { #if FALSE - x = l2->C; - y = -((l1->A * x + l1->C) / l1->B); + x = l2->C; + y = -((l1->A * x + l1->C) / l1->B); #endif - x = l2->C; - y = (l1->A * x + l1->C); + x = l2->C; + y = (l1->A * x + l1->C); - } else { + } + else + { #if FALSE - x = (l2->B * l1->C - l1->B * l2->C) / (l2->A * l1->B - l1->A * l2->B); - y = -((l1->A * x + l1->C) / l1->B); + x = (l2->B * l1->C - l1->B * l2->C) / (l2->A * l1->B - l1->A * l2->B); + y = -((l1->A * x + l1->C) / l1->B); #endif - x = (l1->C - l2->C) / (l2->A - l1->A); - y = (l1->A * x + l1->C); - } - result = point_construct(x, y); + x = (l1->C - l2->C) / (l2->A - l1->A); + y = (l1->A * x + l1->C); + } + result = point_construct(x, y); #ifdef GEODEBUG -printf( "line_interpt- lines are A=%.*g, B=%.*g, C=%.*g, A=%.*g, B=%.*g, C=%.*g\n", - digits8, l1->A, digits8, l1->B, digits8, l1->C, digits8, l2->A, digits8, l2->B, digits8, l2->C); -printf( "line_interpt- lines intersect at (%.*g,%.*g)\n", digits8, x, digits8, y); + printf("line_interpt- lines are A=%.*g, B=%.*g, C=%.*g, A=%.*g, B=%.*g, C=%.*g\n", + digits8, l1->A, digits8, l1->B, digits8, l1->C, digits8, l2->A, digits8, l2->B, digits8, l2->C); + printf("line_interpt- lines intersect at (%.*g,%.*g)\n", digits8, x, digits8, y); #endif - return(result); -} /* line_interpt() */ + return (result); +} /* line_interpt() */ /*********************************************************************** ** - ** Routines for 2D paths (sequences of line segments, also - ** called `polylines'). + ** Routines for 2D paths (sequences of line segments, also + ** called `polylines'). ** - ** This is not a general package for geometric paths, - ** which of course include polygons; the emphasis here - ** is on (for example) usefulness in wire layout. + ** This is not a general package for geometric paths, + ** which of course include polygons; the emphasis here + ** is on (for example) usefulness in wire layout. ** ***********************************************************************/ /*---------------------------------------------------------- - * String to path / path to string conversion. - * External format: - * "((xcoord, ycoord),... )" - * "[(xcoord, ycoord),... ]" - * "(xcoord, ycoord),... " - * "[xcoord, ycoord,... ]" - * Also support older format: - * "(closed, npts, xcoord, ycoord,... )" + * String to path / path to string conversion. + * External format: + * "((xcoord, ycoord),... )" + * "[(xcoord, ycoord),... ]" + * "(xcoord, ycoord),... " + * "[xcoord, ycoord,... ]" + * Also support older format: + * "(closed, npts, xcoord, ycoord,... )" *---------------------------------------------------------*/ -PATH *path_in(char *str) +PATH * +path_in(char *str) { - PATH *path; + PATH *path; - int isopen; - char *s; - int npts; - int size; - int depth = 0; + int isopen; + char *s; + int npts; + int size; + int depth = 0; - if (!PointerIsValid(str)) - elog(WARN, "Bad (null) path external representation"); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) path external representation"); - if ((npts = pair_count(str, ',')) <= 0) - elog(WARN, "Bad path external representation '%s'", str); + if ((npts = pair_count(str, ',')) <= 0) + elog(WARN, "Bad path external representation '%s'", str); - s = str; - while (isspace( *s)) s++; + s = str; + while (isspace(*s)) + s++; - /* skip single leading paren */ - if ((*s == LDELIM) && (strrchr( s, LDELIM) == s)) { - s++; - depth++; - } + /* skip single leading paren */ + if ((*s == LDELIM) && (strrchr(s, LDELIM) == s)) + { + s++; + depth++; + } - size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * npts); - path = PALLOC(size); + size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * npts); + path = PALLOC(size); - path->size = size; - path->npts = npts; + path->size = size; + path->npts = npts; - if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0]))) - && (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM))) - elog (WARN, "Bad path external representation '%s'",str); + if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0]))) + && (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM))) + elog(WARN, "Bad path external representation '%s'", str); - path->closed = (! isopen); + path->closed = (!isopen); - return(path); -} /* path_in() */ + return (path); +} /* path_in() */ -char *path_out(PATH *path) +char * +path_out(PATH * path) { - if (!PointerIsValid(path)) - return NULL; + if (!PointerIsValid(path)) + return NULL; - return( path_encode( path->closed, path->npts, (Point *) &(path->p[0]))); -} /* path_out() */ + return (path_encode(path->closed, path->npts, (Point *) & (path->p[0]))); +} /* path_out() */ /*---------------------------------------------------------- - * Relational operators. - * These are based on the path cardinality, - * as stupid as that sounds. + * Relational operators. + * These are based on the path cardinality, + * as stupid as that sounds. * - * Better relops and access methods coming soon. + * Better relops and access methods coming soon. *---------------------------------------------------------*/ -bool path_n_lt(PATH *p1, PATH *p2) +bool +path_n_lt(PATH * p1, PATH * p2) { - return( (p1->npts < p2->npts ) ); + return ((p1->npts < p2->npts)); } -bool path_n_gt(PATH *p1, PATH *p2) +bool +path_n_gt(PATH * p1, PATH * p2) { - return( (p1->npts > p2->npts ) ); + return ((p1->npts > p2->npts)); } -bool path_n_eq(PATH *p1, PATH *p2) +bool +path_n_eq(PATH * p1, PATH * p2) { - return( (p1->npts == p2->npts) ); + return ((p1->npts == p2->npts)); } -bool path_n_le(PATH *p1, PATH *p2) +bool +path_n_le(PATH * p1, PATH * p2) { - return( (p1->npts <= p2->npts ) ); + return ((p1->npts <= p2->npts)); } -bool path_n_ge(PATH *p1, PATH *p2) +bool +path_n_ge(PATH * p1, PATH * p2) { - return( (p1->npts >= p2->npts ) ); + return ((p1->npts >= p2->npts)); } @@ -1012,1206 +1138,1350 @@ bool path_n_ge(PATH *p1, PATH *p2) *---------------------------------------------------------*/ bool -path_isclosed( PATH *path) +path_isclosed(PATH * path) { - if (!PointerIsValid(path)) - return FALSE; + if (!PointerIsValid(path)) + return FALSE; - return(path->closed); -} /* path_isclosed() */ + return (path->closed); +} /* path_isclosed() */ bool -path_isopen( PATH *path) +path_isopen(PATH * path) { - if (!PointerIsValid(path)) - return FALSE; + if (!PointerIsValid(path)) + return FALSE; - return(! path->closed); -} /* path_isopen() */ + return (!path->closed); +} /* path_isopen() */ int4 -path_npoints( PATH *path) +path_npoints(PATH * path) { - if (!PointerIsValid(path)) - return 0; + if (!PointerIsValid(path)) + return 0; - return(path->npts); -} /* path_npoints() */ + return (path->npts); +} /* path_npoints() */ -PATH * -path_close(PATH *path) +PATH * +path_close(PATH * path) { - PATH *result; + PATH *result; - if (!PointerIsValid(path)) - return(NULL); + if (!PointerIsValid(path)) + return (NULL); - result = path_copy(path); - result->closed = TRUE; + result = path_copy(path); + result->closed = TRUE; - return(result); -} /* path_close() */ + return (result); +} /* path_close() */ -PATH * -path_open(PATH *path) +PATH * +path_open(PATH * path) { - PATH *result; + PATH *result; - if (!PointerIsValid(path)) - return(NULL); + if (!PointerIsValid(path)) + return (NULL); - result = path_copy(path); - result->closed = FALSE; + result = path_copy(path); + result->closed = FALSE; - return(result); -} /* path_open() */ + return (result); +} /* path_open() */ -PATH * -path_copy(PATH *path) +PATH * +path_copy(PATH * path) { - PATH *result; - int size; + PATH *result; + int size; - size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * path->npts); - result = PALLOC(size); + size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * path->npts); + result = PALLOC(size); - memmove((char *) result, (char *) path, size); - return(result); -} /* path_copy() */ + memmove((char *) result, (char *) path, size); + return (result); +} /* path_copy() */ /* path_inter - - * Does p1 intersect p2 at any point? - * Use bounding boxes for a quick (O(n)) check, then do a - * O(n^2) iterative edge check. - */ -bool path_inter(PATH *p1, PATH *p2) -{ - BOX b1, b2; - int i, j; - LSEG seg1, seg2; - - b1.high.x = b1.low.x = p1->p[0].x; - b1.high.y = b1.low.y = p1->p[0].y; - for (i = 1; i < p1->npts; i++) { - b1.high.x = Max(p1->p[i].x, b1.high.x); - b1.high.y = Max(p1->p[i].y, b1.high.y); - b1.low.x = Min(p1->p[i].x, b1.low.x); - b1.low.y = Min(p1->p[i].y, b1.low.y); - } - b2.high.x = b2.low.x = p2->p[0].x; - b2.high.y = b2.low.y = p2->p[0].y; - for (i = 1; i < p2->npts; i++) { - b2.high.x = Max(p2->p[i].x, b2.high.x); - b2.high.y = Max(p2->p[i].y, b2.high.y); - b2.low.x = Min(p2->p[i].x, b2.low.x); - b2.low.y = Min(p2->p[i].y, b2.low.y); - } - if (! box_overlap(&b1, &b2)) - return(0); - - /* pairwise check lseg intersections */ - for (i = 0; i < p1->npts - 1; i++) { - for (j = 0; j < p2->npts - 1; j++) { - statlseg_construct(&seg1, &p1->p[i], &p1->p[i+1]); - statlseg_construct(&seg2, &p2->p[j], &p2->p[j+1]); - if (lseg_intersect(&seg1, &seg2)) - return(1); - } - } - - /* if we dropped through, no two segs intersected */ - return(0); + * Does p1 intersect p2 at any point? + * Use bounding boxes for a quick (O(n)) check, then do a + * O(n^2) iterative edge check. + */ +bool +path_inter(PATH * p1, PATH * p2) +{ + BOX b1, + b2; + int i, + j; + LSEG seg1, + seg2; + + b1.high.x = b1.low.x = p1->p[0].x; + b1.high.y = b1.low.y = p1->p[0].y; + for (i = 1; i < p1->npts; i++) + { + b1.high.x = Max(p1->p[i].x, b1.high.x); + b1.high.y = Max(p1->p[i].y, b1.high.y); + b1.low.x = Min(p1->p[i].x, b1.low.x); + b1.low.y = Min(p1->p[i].y, b1.low.y); + } + b2.high.x = b2.low.x = p2->p[0].x; + b2.high.y = b2.low.y = p2->p[0].y; + for (i = 1; i < p2->npts; i++) + { + b2.high.x = Max(p2->p[i].x, b2.high.x); + b2.high.y = Max(p2->p[i].y, b2.high.y); + b2.low.x = Min(p2->p[i].x, b2.low.x); + b2.low.y = Min(p2->p[i].y, b2.low.y); + } + if (!box_overlap(&b1, &b2)) + return (0); + + /* pairwise check lseg intersections */ + for (i = 0; i < p1->npts - 1; i++) + { + for (j = 0; j < p2->npts - 1; j++) + { + statlseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]); + statlseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]); + if (lseg_intersect(&seg1, &seg2)) + return (1); + } + } + + /* if we dropped through, no two segs intersected */ + return (0); } /* this essentially does a cartesian product of the lsegs in the two paths, and finds the min distance between any two lsegs */ -double *path_distance(PATH *p1, PATH *p2) +double * +path_distance(PATH * p1, PATH * p2) { - double *min = NULL, *tmp; - int i,j; - LSEG seg1, seg2; + double *min = NULL, + *tmp; + int i, + j; + LSEG seg1, + seg2; /* - statlseg_construct(&seg1, &p1->p[0], &p1->p[1]); - statlseg_construct(&seg2, &p2->p[0], &p2->p[1]); - min = lseg_distance(&seg1, &seg2); + statlseg_construct(&seg1, &p1->p[0], &p1->p[1]); + statlseg_construct(&seg2, &p2->p[0], &p2->p[1]); + min = lseg_distance(&seg1, &seg2); */ - for (i = 0; i < p1->npts - 1; i++) - for (j = 0; j < p2->npts - 1; j++) - { - statlseg_construct(&seg1, &p1->p[i], &p1->p[i+1]); - statlseg_construct(&seg2, &p2->p[j], &p2->p[j+1]); - - tmp = lseg_distance(&seg1, &seg2); - if ((min == NULL) || (*min < *tmp)) { - if (min != NULL) PFREE(min); - min = tmp; - } else { - PFREE(tmp); + for (i = 0; i < p1->npts - 1; i++) + for (j = 0; j < p2->npts - 1; j++) + { + statlseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]); + statlseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]); + + tmp = lseg_distance(&seg1, &seg2); + if ((min == NULL) || (*min < *tmp)) + { + if (min != NULL) + PFREE(min); + min = tmp; + } + else + { + PFREE(tmp); + } } - } - return(min); + return (min); } /*---------------------------------------------------------- - * "Arithmetic" operations. + * "Arithmetic" operations. *---------------------------------------------------------*/ -double *path_length(PATH *path) +double * +path_length(PATH * path) { - double *result; - int i; + double *result; + int i; - result = PALLOCTYPE(double); + result = PALLOCTYPE(double); - *result = 0; - for (i = 0; i < (path->npts - 1); i++) - *result += point_dt(&path->p[i], &path->p[i+1]); + *result = 0; + for (i = 0; i < (path->npts - 1); i++) + *result += point_dt(&path->p[i], &path->p[i + 1]); - return(result); -} /* path_length() */ + return (result); +} /* path_length() */ #ifdef NOT_USED -double path_ln(PATH *path) +double +path_ln(PATH * path) { - double result; - int i; + double result; + int i; - result = 0; - for (i = 0; i < (path->npts - 1); i++) - result += point_dt(&path->p[i], &path->p[i+1]); + result = 0; + for (i = 0; i < (path->npts - 1); i++) + result += point_dt(&path->p[i], &path->p[i + 1]); + + return (result); +} /* path_ln() */ - return(result); -} /* path_ln() */ #endif /*********************************************************************** ** - ** Routines for 2D points. + ** Routines for 2D points. ** ***********************************************************************/ /*---------------------------------------------------------- - * String to point, point to string conversion. - * External format: - * "(x,y)" - * "x,y" + * String to point, point to string conversion. + * External format: + * "(x,y)" + * "x,y" *---------------------------------------------------------*/ -Point * +Point * point_in(char *str) { - Point *point; + Point *point; + + double x, + y; + char *s; - double x, y; - char *s; - - if (! PointerIsValid( str)) - elog(WARN, "Bad (null) point external representation"); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) point external representation"); - if (! pair_decode( str, &x, &y, &s) || (strlen(s) > 0)) - elog (WARN, "Bad point external representation '%s'",str); + if (!pair_decode(str, &x, &y, &s) || (strlen(s) > 0)) + elog(WARN, "Bad point external representation '%s'", str); - point = PALLOCTYPE(Point); + point = PALLOCTYPE(Point); - point->x = x; - point->y = y; + point->x = x; + point->y = y; - return(point); -} /* point_in() */ + return (point); +} /* point_in() */ -char * -point_out(Point *pt) +char * +point_out(Point * pt) { - if (! PointerIsValid(pt)) - return(NULL); + if (!PointerIsValid(pt)) + return (NULL); - return( path_encode( -1, 1, pt)); -} /* point_out() */ + return (path_encode(-1, 1, pt)); +} /* point_out() */ -static Point *point_construct(double x, double y) +static Point * +point_construct(double x, double y) { - Point *result = PALLOCTYPE(Point); + Point *result = PALLOCTYPE(Point); - result->x = x; - result->y = y; - return(result); + result->x = x; + result->y = y; + return (result); } -static Point *point_copy(Point *pt) +static Point * +point_copy(Point * pt) { - Point *result; + Point *result; - if (! PointerIsValid( pt)) - return(NULL); + if (!PointerIsValid(pt)) + return (NULL); - result = PALLOCTYPE(Point); + result = PALLOCTYPE(Point); - result->x = pt->x; - result->y = pt->y; - return(result); + result->x = pt->x; + result->y = pt->y; + return (result); } /*---------------------------------------------------------- - * Relational operators for Points. - * Since we do have a sense of coordinates being - * "equal" to a given accuracy (point_vert, point_horiz), - * the other ops must preserve that sense. This means - * that results may, strictly speaking, be a lie (unless - * EPSILON = 0.0). + * Relational operators for Points. + * Since we do have a sense of coordinates being + * "equal" to a given accuracy (point_vert, point_horiz), + * the other ops must preserve that sense. This means + * that results may, strictly speaking, be a lie (unless + * EPSILON = 0.0). *---------------------------------------------------------*/ -bool point_left(Point *pt1, Point *pt2) +bool +point_left(Point * pt1, Point * pt2) { - return( FPlt(pt1->x, pt2->x) ); + return (FPlt(pt1->x, pt2->x)); } -bool point_right(Point *pt1, Point *pt2) +bool +point_right(Point * pt1, Point * pt2) { - return( FPgt(pt1->x, pt2->x) ); + return (FPgt(pt1->x, pt2->x)); } -bool point_above(Point *pt1, Point *pt2) +bool +point_above(Point * pt1, Point * pt2) { - return( FPgt(pt1->y, pt2->y) ); + return (FPgt(pt1->y, pt2->y)); } -bool point_below(Point *pt1, Point *pt2) +bool +point_below(Point * pt1, Point * pt2) { - return( FPlt(pt1->y, pt2->y) ); + return (FPlt(pt1->y, pt2->y)); } -bool point_vert(Point *pt1, Point *pt2) +bool +point_vert(Point * pt1, Point * pt2) { - return( FPeq( pt1->x, pt2->x ) ); + return (FPeq(pt1->x, pt2->x)); } -bool point_horiz(Point *pt1, Point *pt2) +bool +point_horiz(Point * pt1, Point * pt2) { - return( FPeq( pt1->y, pt2->y ) ); + return (FPeq(pt1->y, pt2->y)); } -bool point_eq(Point *pt1, Point *pt2) +bool +point_eq(Point * pt1, Point * pt2) { - return( point_horiz(pt1, pt2) && point_vert(pt1, pt2) ); + return (point_horiz(pt1, pt2) && point_vert(pt1, pt2)); } /*---------------------------------------------------------- - * "Arithmetic" operators on points. + * "Arithmetic" operators on points. *---------------------------------------------------------*/ -int32 pointdist(Point *p1, Point *p2) +int32 +pointdist(Point * p1, Point * p2) { - int32 result; - - result = point_dt(p1, p2); - return(result); + int32 result; + + result = point_dt(p1, p2); + return (result); } -double *point_distance(Point *pt1, Point *pt2) +double * +point_distance(Point * pt1, Point * pt2) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); - *result = HYPOT( pt1->x - pt2->x, pt1->y - pt2->y ); - return(result); + *result = HYPOT(pt1->x - pt2->x, pt1->y - pt2->y); + return (result); } -double point_dt(Point *pt1, Point *pt2) +double +point_dt(Point * pt1, Point * pt2) { - return( HYPOT( pt1->x - pt2->x, pt1->y - pt2->y ) ); + return (HYPOT(pt1->x - pt2->x, pt1->y - pt2->y)); } -double *point_slope(Point *pt1, Point *pt2) +double * +point_slope(Point * pt1, Point * pt2) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); - if (point_vert(pt1, pt2)) - *result = (double)DBL_MAX; - else - *result = (pt1->y - pt2->y) / (pt1->x - pt1->x); - return(result); + if (point_vert(pt1, pt2)) + *result = (double) DBL_MAX; + else + *result = (pt1->y - pt2->y) / (pt1->x - pt1->x); + return (result); } -double point_sl(Point *pt1, Point *pt2) +double +point_sl(Point * pt1, Point * pt2) { - return( point_vert(pt1, pt2) - ? (double)DBL_MAX - : (pt1->y - pt2->y) / (pt1->x - pt2->x) ); + return (point_vert(pt1, pt2) + ? (double) DBL_MAX + : (pt1->y - pt2->y) / (pt1->x - pt2->x)); } /*********************************************************************** ** - ** Routines for 2D line segments. + ** Routines for 2D line segments. ** ***********************************************************************/ /*---------------------------------------------------------- - * String to lseg, lseg to string conversion. - * External forms: "[(x1, y1), (x2, y2)]" - * "(x1, y1), (x2, y2)" - * "x1, y1, x2, y2" - * closed form ok "((x1, y1), (x2, y2))" - * (old form) "(x1, y1, x2, y2)" + * String to lseg, lseg to string conversion. + * External forms: "[(x1, y1), (x2, y2)]" + * "(x1, y1), (x2, y2)" + * "x1, y1, x2, y2" + * closed form ok "((x1, y1), (x2, y2))" + * (old form) "(x1, y1, x2, y2)" *---------------------------------------------------------*/ -LSEG *lseg_in(char *str) +LSEG * +lseg_in(char *str) { - LSEG *lseg; + LSEG *lseg; + + int isopen; + char *s; - int isopen; - char *s; + if (!PointerIsValid(str)) + elog(WARN, " Bad (null) lseg external representation", NULL); - if (!PointerIsValid(str)) - elog (WARN," Bad (null) lseg external representation",NULL); + lseg = PALLOCTYPE(LSEG); - lseg = PALLOCTYPE(LSEG); + if ((!path_decode(TRUE, 2, str, &isopen, &s, &(lseg->p[0]))) + || (*s != '\0')) + elog(WARN, "Bad lseg external representation '%s'", str); - if ((! path_decode(TRUE, 2, str, &isopen, &s, &(lseg->p[0]))) - || (*s != '\0')) - elog (WARN, "Bad lseg external representation '%s'",str); + lseg->m = point_sl(&lseg->p[0], &lseg->p[1]); - lseg->m = point_sl(&lseg->p[0], &lseg->p[1]); - - return(lseg); -} /* lseg_in() */ + return (lseg); +} /* lseg_in() */ -char *lseg_out(LSEG *ls) +char * +lseg_out(LSEG * ls) { - if (!PointerIsValid(ls)) - return(NULL); + if (!PointerIsValid(ls)) + return (NULL); - return( path_encode( FALSE, 2, (Point *) &(ls->p[0]))); -} /* lseg_out() */ + return (path_encode(FALSE, 2, (Point *) & (ls->p[0]))); +} /* lseg_out() */ /* lseg_construct - - * form a LSEG from two Points. + * form a LSEG from two Points. */ -LSEG *lseg_construct(Point *pt1, Point *pt2) +LSEG * +lseg_construct(Point * pt1, Point * pt2) { - LSEG *result = PALLOCTYPE(LSEG); + LSEG *result = PALLOCTYPE(LSEG); - result->p[0].x = pt1->x; - result->p[0].y = pt1->y; - result->p[1].x = pt2->x; - result->p[1].y = pt2->y; + result->p[0].x = pt1->x; + result->p[0].y = pt1->y; + result->p[1].x = pt2->x; + result->p[1].y = pt2->y; - result->m = point_sl(pt1, pt2); - - return(result); + result->m = point_sl(pt1, pt2); + + return (result); } /* like lseg_construct, but assume space already allocated */ -static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2) +static void +statlseg_construct(LSEG * lseg, Point * pt1, Point * pt2) { - lseg->p[0].x = pt1->x; - lseg->p[0].y = pt1->y; - lseg->p[1].x = pt2->x; - lseg->p[1].y = pt2->y; + lseg->p[0].x = pt1->x; + lseg->p[0].y = pt1->y; + lseg->p[1].x = pt2->x; + lseg->p[1].y = pt2->y; - lseg->m = point_sl(pt1, pt2); + lseg->m = point_sl(pt1, pt2); } /*---------------------------------------------------------- - * Relative position routines. + * Relative position routines. *---------------------------------------------------------*/ /* - ** find intersection of the two lines, and see if it falls on + ** find intersection of the two lines, and see if it falls on ** both segments. */ -bool lseg_intersect(LSEG *l1, LSEG *l2) -{ - LINE *ln; - Point *interpt; - bool retval; - - ln = line_construct_pp(&l2->p[0], &l2->p[1]); - interpt = interpt_sl(l1, ln); - - if (interpt != NULL && on_ps(interpt, l2)) /* interpt on l1 and l2 */ - retval = TRUE; - else retval = FALSE; - if (interpt != NULL) PFREE(interpt); - PFREE(ln); - return(retval); +bool +lseg_intersect(LSEG * l1, LSEG * l2) +{ + LINE *ln; + Point *interpt; + bool retval; + + ln = line_construct_pp(&l2->p[0], &l2->p[1]); + interpt = interpt_sl(l1, ln); + + if (interpt != NULL && on_ps(interpt, l2)) /* interpt on l1 and l2 */ + retval = TRUE; + else + retval = FALSE; + if (interpt != NULL) + PFREE(interpt); + PFREE(ln); + return (retval); } -bool lseg_parallel(LSEG *l1, LSEG *l2) +bool +lseg_parallel(LSEG * l1, LSEG * l2) { #if FALSE - return( FPeq(l1->m, l2->m) ); + return (FPeq(l1->m, l2->m)); #endif - return( FPeq( point_sl( &(l1->p[0]), &(l1->p[1])), - point_sl( &(l2->p[0]), &(l2->p[1]))) ); -} /* lseg_parallel() */ + return (FPeq(point_sl(&(l1->p[0]), &(l1->p[1])), + point_sl(&(l2->p[0]), &(l2->p[1])))); +} /* lseg_parallel() */ -bool lseg_perp(LSEG *l1, LSEG *l2) +bool +lseg_perp(LSEG * l1, LSEG * l2) { - double m1, m2; + double m1, + m2; - m1 = point_sl( &(l1->p[0]), &(l1->p[1])); - m2 = point_sl( &(l2->p[0]), &(l2->p[1])); + m1 = point_sl(&(l1->p[0]), &(l1->p[1])); + m2 = point_sl(&(l2->p[0]), &(l2->p[1])); - if (! FPzero(m1)) - return( FPeq(m2 / m1, -1.0) ); - else if (! FPzero(m2)) - return( FPeq(m1 / m2, -1.0) ); - return(0); /* both 0.0 */ -} /* lseg_perp() */ + if (!FPzero(m1)) + return (FPeq(m2 / m1, -1.0)); + else if (!FPzero(m2)) + return (FPeq(m1 / m2, -1.0)); + return (0); /* both 0.0 */ +} /* lseg_perp() */ -bool lseg_vertical(LSEG *lseg) +bool +lseg_vertical(LSEG * lseg) { - return( FPeq(lseg->p[0].x, lseg->p[1].x) ); + return (FPeq(lseg->p[0].x, lseg->p[1].x)); } -bool lseg_horizontal(LSEG *lseg) +bool +lseg_horizontal(LSEG * lseg) { - return( FPeq(lseg->p[0].y, lseg->p[1].y) ); + return (FPeq(lseg->p[0].y, lseg->p[1].y)); } -bool lseg_eq(LSEG *l1, LSEG *l2) +bool +lseg_eq(LSEG * l1, LSEG * l2) { - return( FPeq(l1->p[0].x, l2->p[0].x) && - FPeq(l1->p[1].y, l2->p[1].y) && - FPeq(l1->p[0].x, l2->p[0].x) && - FPeq(l1->p[1].y, l2->p[1].y) ); + return (FPeq(l1->p[0].x, l2->p[0].x) && + FPeq(l1->p[1].y, l2->p[1].y) && + FPeq(l1->p[0].x, l2->p[0].x) && + FPeq(l1->p[1].y, l2->p[1].y)); } /*---------------------------------------------------------- - * Line arithmetic routines. + * Line arithmetic routines. *---------------------------------------------------------*/ /* lseg_distance - - * If two segments don't intersect, then the closest - * point will be from one of the endpoints to the other - * segment. + * If two segments don't intersect, then the closest + * point will be from one of the endpoints to the other + * segment. */ -double *lseg_distance(LSEG *l1, LSEG *l2) +double * +lseg_distance(LSEG * l1, LSEG * l2) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); - *result = lseg_dt( l1, l2); + *result = lseg_dt(l1, l2); - return(result); + return (result); } /* distance between l1, l2 */ static double -lseg_dt(LSEG *l1, LSEG *l2) -{ - double *d, result; - - if (lseg_intersect(l1, l2)) - return(0.0); - - d = dist_ps(&l1->p[0], l2); - result = *d; - PFREE(d); - d = dist_ps(&l1->p[1], l2); - result = Min(result, *d); - PFREE(d); +lseg_dt(LSEG * l1, LSEG * l2) +{ + double *d, + result; + + if (lseg_intersect(l1, l2)) + return (0.0); + + d = dist_ps(&l1->p[0], l2); + result = *d; + PFREE(d); + d = dist_ps(&l1->p[1], l2); + result = Min(result, *d); + PFREE(d); #if FALSE /* XXX Why are we checking distances from all endpoints to the other segment? * One set of endpoints should be sufficient - tgl 97/07/03 */ - d = dist_ps(&l2->p[0], l1); - result = Min(result, *d); - PFREE(d); - d = dist_ps(&l2->p[1], l1); - result = Min(result, *d); - PFREE(d); + d = dist_ps(&l2->p[0], l1); + result = Min(result, *d); + PFREE(d); + d = dist_ps(&l2->p[1], l1); + result = Min(result, *d); + PFREE(d); #endif - - return(result); -} /* lseg_dt() */ + + return (result); +} /* lseg_dt() */ -Point * -lseg_center(LSEG *lseg) +Point * +lseg_center(LSEG * lseg) { - Point *result; + Point *result; - if (!PointerIsValid(lseg)) - return(NULL); + if (!PointerIsValid(lseg)) + return (NULL); - result = PALLOCTYPE(Point); + result = PALLOCTYPE(Point); - result->x = (lseg->p[0].x - lseg->p[1].x) / 2; - result->y = (lseg->p[0].y - lseg->p[1].y) / 2; + result->x = (lseg->p[0].x - lseg->p[1].x) / 2; + result->y = (lseg->p[0].y - lseg->p[1].y) / 2; - return(result); -} /* lseg_center() */ + return (result); +} /* lseg_center() */ /* lseg_interpt - - * Find the intersection point of two segments (if any). - * Find the intersection of the appropriate lines; if the - * point is not on a given segment, there is no valid segment - * intersection point at all. + * Find the intersection point of two segments (if any). + * Find the intersection of the appropriate lines; if the + * point is not on a given segment, there is no valid segment + * intersection point at all. * If there is an intersection, then check explicitly for matching - * endpoints since there may be rounding effects with annoying - * lsb residue. - tgl 1997-07-09 - */ -Point * -lseg_interpt(LSEG *l1, LSEG *l2) -{ - Point *result; - LINE *tmp1, *tmp2; - - if (!PointerIsValid(l1) || !PointerIsValid(l2)) - return(NULL); - - tmp1 = line_construct_pp(&l1->p[0], &l1->p[1]); - tmp2 = line_construct_pp(&l2->p[0], &l2->p[1]); - result = line_interpt(tmp1, tmp2); - if (PointerIsValid(result)) { - if (on_ps(result, l1)) { - if ((FPeq( l1->p[0].x, l2->p[0].x) && FPeq( l1->p[0].y, l2->p[0].y)) - || (FPeq( l1->p[0].x, l2->p[1].x) && FPeq( l1->p[0].y, l2->p[1].y))) { - result->x = l1->p[0].x; - result->y = l1->p[0].y; - - } else if ((FPeq( l1->p[1].x, l2->p[0].x) && FPeq( l1->p[1].y, l2->p[0].y)) - || (FPeq( l1->p[1].x, l2->p[1].x) && FPeq( l1->p[1].y, l2->p[1].y))) { - result->x = l1->p[1].x; - result->y = l1->p[1].y; - } - } else { - PFREE(result); - result = NULL; - } - } - PFREE(tmp1); - PFREE(tmp2); - - return(result); -} /* lseg_interpt() */ + * endpoints since there may be rounding effects with annoying + * lsb residue. - tgl 1997-07-09 + */ +Point * +lseg_interpt(LSEG * l1, LSEG * l2) +{ + Point *result; + LINE *tmp1, + *tmp2; + + if (!PointerIsValid(l1) || !PointerIsValid(l2)) + return (NULL); + + tmp1 = line_construct_pp(&l1->p[0], &l1->p[1]); + tmp2 = line_construct_pp(&l2->p[0], &l2->p[1]); + result = line_interpt(tmp1, tmp2); + if (PointerIsValid(result)) + { + if (on_ps(result, l1)) + { + if ((FPeq(l1->p[0].x, l2->p[0].x) && FPeq(l1->p[0].y, l2->p[0].y)) + || (FPeq(l1->p[0].x, l2->p[1].x) && FPeq(l1->p[0].y, l2->p[1].y))) + { + result->x = l1->p[0].x; + result->y = l1->p[0].y; + + } + else if ((FPeq(l1->p[1].x, l2->p[0].x) && FPeq(l1->p[1].y, l2->p[0].y)) + || (FPeq(l1->p[1].x, l2->p[1].x) && FPeq(l1->p[1].y, l2->p[1].y))) + { + result->x = l1->p[1].x; + result->y = l1->p[1].y; + } + } + else + { + PFREE(result); + result = NULL; + } + } + PFREE(tmp1); + PFREE(tmp2); + + return (result); +} /* lseg_interpt() */ /*********************************************************************** ** - ** Routines for position comparisons of differently-typed - ** 2D objects. + ** Routines for position comparisons of differently-typed + ** 2D objects. ** ***********************************************************************/ -#define ABOVE 1 -#define BELOW 0 -#define UNDEF -1 +#define ABOVE 1 +#define BELOW 0 +#define UNDEF -1 /*--------------------------------------------------------------------- - * dist_ - * Minimum distance from one object to another. + * dist_ + * Minimum distance from one object to another. *-------------------------------------------------------------------*/ -double *dist_pl(Point *pt, LINE *line) +double * +dist_pl(Point * pt, LINE * line) { - double *result = PALLOCTYPE(double); + double *result = PALLOCTYPE(double); - *result = (line->A * pt->x + line->B * pt->y + line->C) / - HYPOT(line->A, line->B); - - return(result); + *result = (line->A * pt->x + line->B * pt->y + line->C) / + HYPOT(line->A, line->B); + + return (result); } -double *dist_ps(Point *pt, LSEG *lseg) +double * +dist_ps(Point * pt, LSEG * lseg) { - double m; /* slope of perp. */ - LINE *ln; - double *result, *tmpdist; - Point *ip; + double m; /* slope of perp. */ + LINE *ln; + double *result, + *tmpdist; + Point *ip; /* * Construct a line perpendicular to the input segment * and through the input point */ - if (lseg->p[1].x == lseg->p[0].x) { - m = 0; - } else if (lseg->p[1].y == lseg->p[0].y) { /* slope is infinite */ - m = (double)DBL_MAX; - } else { + if (lseg->p[1].x == lseg->p[0].x) + { + m = 0; + } + else if (lseg->p[1].y == lseg->p[0].y) + { /* slope is infinite */ + m = (double) DBL_MAX; + } + else + { #if FALSE - m = (-1) * (lseg->p[1].y - lseg->p[0].y) / - (lseg->p[1].x - lseg->p[0].x); + m = (-1) * (lseg->p[1].y - lseg->p[0].y) / + (lseg->p[1].x - lseg->p[0].x); #endif - m = ((lseg->p[0].y - lseg->p[1].y) / (lseg->p[1].x - lseg->p[0].x)); - } - ln = line_construct_pm(pt, m); + m = ((lseg->p[0].y - lseg->p[1].y) / (lseg->p[1].x - lseg->p[0].x)); + } + ln = line_construct_pm(pt, m); #ifdef GEODEBUG -printf( "dist_ps- line is A=%g B=%g C=%g from (point) slope (%f,%f) %g\n", - ln->A, ln->B, ln->C, pt->x, pt->y, m); + printf("dist_ps- line is A=%g B=%g C=%g from (point) slope (%f,%f) %g\n", + ln->A, ln->B, ln->C, pt->x, pt->y, m); #endif /* * Calculate distance to the line segment - * or to the endpoints of the segment. + * or to the endpoints of the segment. */ - /* intersection is on the line segment? */ - if ((ip = interpt_sl(lseg, ln)) != NULL) { - result = point_distance(pt, ip); + /* intersection is on the line segment? */ + if ((ip = interpt_sl(lseg, ln)) != NULL) + { + result = point_distance(pt, ip); #ifdef GEODEBUG -printf( "dist_ps- distance is %f to intersection point is (%f,%f)\n", - *result, ip->x, ip->y); + printf("dist_ps- distance is %f to intersection point is (%f,%f)\n", + *result, ip->x, ip->y); #endif - /* otherwise, intersection is not on line segment */ - } else { - result = point_distance(pt, &lseg->p[0]); - tmpdist = point_distance(pt, &lseg->p[1]); - if (*tmpdist < *result) *result = *tmpdist; - PFREE (tmpdist); - } - - if (ip != NULL) PFREE(ip); - PFREE(ln); - return (result); + /* otherwise, intersection is not on line segment */ + } + else + { + result = point_distance(pt, &lseg->p[0]); + tmpdist = point_distance(pt, &lseg->p[1]); + if (*tmpdist < *result) + *result = *tmpdist; + PFREE(tmpdist); + } + + if (ip != NULL) + PFREE(ip); + PFREE(ln); + return (result); } /* - ** Distance from a point to a path - */ -double *dist_ppath(Point *pt, PATH *path) -{ - double *result; - double *tmp; - int i; - LSEG lseg; - - switch (path->npts) { - /* no points in path? then result is undefined... */ - case 0: - result = NULL; - break; - /* one point in path? then get distance between two points... */ - case 1: - result = point_distance(pt, &path->p[0]); - break; - default: - /* make sure the path makes sense... */ - Assert(path->npts > 1); - /* - * the distance from a point to a path is the smallest distance - * from the point to any of its constituent segments. - */ - result = PALLOCTYPE(double); - for (i = 0; i < path->npts - 1; i++) { - statlseg_construct(&lseg, &path->p[i], &path->p[i+1]); - tmp = dist_ps(pt, &lseg); - if (i == 0 || *tmp < *result) - *result = *tmp; - PFREE(tmp); + ** Distance from a point to a path + */ +double * +dist_ppath(Point * pt, PATH * path) +{ + double *result; + double *tmp; + int i; + LSEG lseg; + + switch (path->npts) + { + /* no points in path? then result is undefined... */ + case 0: + result = NULL; + break; + /* one point in path? then get distance between two points... */ + case 1: + result = point_distance(pt, &path->p[0]); + break; + default: + /* make sure the path makes sense... */ + Assert(path->npts > 1); + + /* + * the distance from a point to a path is the smallest distance + * from the point to any of its constituent segments. + */ + result = PALLOCTYPE(double); + for (i = 0; i < path->npts - 1; i++) + { + statlseg_construct(&lseg, &path->p[i], &path->p[i + 1]); + tmp = dist_ps(pt, &lseg); + if (i == 0 || *tmp < *result) + *result = *tmp; + PFREE(tmp); + } + break; } - break; - } - return(result); + return (result); } -double *dist_pb(Point *pt, BOX *box) +double * +dist_pb(Point * pt, BOX * box) { - Point *tmp; - double *result; - - tmp = close_pb(pt, box); - result = point_distance(tmp, pt); - PFREE(tmp); + Point *tmp; + double *result; + + tmp = close_pb(pt, box); + result = point_distance(tmp, pt); + PFREE(tmp); - return(result); + return (result); } -double *dist_sl(LSEG *lseg, LINE *line) +double * +dist_sl(LSEG * lseg, LINE * line) { - double *result, *d2; + double *result, + *d2; - if (inter_sl(lseg, line)) { - result = PALLOCTYPE(double); - *result = 0.0; + if (inter_sl(lseg, line)) + { + result = PALLOCTYPE(double); + *result = 0.0; - } else { - result = dist_pl(&lseg->p[0], line); - d2 = dist_pl(&lseg->p[1], line); - if (*d2 > *result) { - PFREE( result); - result = d2; - } else { - PFREE( d2); } - } - - return(result); + else + { + result = dist_pl(&lseg->p[0], line); + d2 = dist_pl(&lseg->p[1], line); + if (*d2 > *result) + { + PFREE(result); + result = d2; + } + else + { + PFREE(d2); + } + } + + return (result); } -double *dist_sb(LSEG *lseg, BOX *box) +double * +dist_sb(LSEG * lseg, BOX * box) { - Point *tmp; - double *result; - - tmp = close_sb(lseg, box); - if (tmp == NULL) { - result = PALLOCTYPE(double); - *result = 0.0; - } else { - result = dist_pb(tmp, box); - PFREE(tmp); - } - - return(result); + Point *tmp; + double *result; + + tmp = close_sb(lseg, box); + if (tmp == NULL) + { + result = PALLOCTYPE(double); + *result = 0.0; + } + else + { + result = dist_pb(tmp, box); + PFREE(tmp); + } + + return (result); } -double *dist_lb(LINE *line, BOX *box) +double * +dist_lb(LINE * line, BOX * box) { - Point *tmp; - double *result; - - tmp = close_lb(line, box); - if (tmp == NULL) { - result = PALLOCTYPE(double); - *result = 0.0; - } else { - result = dist_pb(tmp, box); - PFREE(tmp); - } - - return(result); + Point *tmp; + double *result; + + tmp = close_lb(line, box); + if (tmp == NULL) + { + result = PALLOCTYPE(double); + *result = 0.0; + } + else + { + result = dist_pb(tmp, box); + PFREE(tmp); + } + + return (result); } -double * -dist_cpoly(CIRCLE *circle, POLYGON *poly) +double * +dist_cpoly(CIRCLE * circle, POLYGON * poly) { - double *result; - int i; - double *d; - LSEG seg; + double *result; + int i; + double *d; + LSEG seg; - if (!PointerIsValid(circle) || !PointerIsValid(poly)) - elog (WARN, "Invalid (null) input for distance", NULL); + if (!PointerIsValid(circle) || !PointerIsValid(poly)) + elog(WARN, "Invalid (null) input for distance", NULL); - if (point_inside( &(circle->center), poly->npts, poly->p)) { + if (point_inside(&(circle->center), poly->npts, poly->p)) + { #ifdef GEODEBUG -printf( "dist_cpoly- center inside of polygon\n"); + printf("dist_cpoly- center inside of polygon\n"); #endif - result = PALLOCTYPE(double); + result = PALLOCTYPE(double); - *result = 0; - return(result); - } - - /* initialize distance with segment between first and last points */ - seg.p[0].x = poly->p[0].x; - seg.p[0].y = poly->p[0].y; - seg.p[1].x = poly->p[poly->npts-1].x; - seg.p[1].y = poly->p[poly->npts-1].y; - result = dist_ps( &(circle->center), &seg); + *result = 0; + return (result); + } + + /* initialize distance with segment between first and last points */ + seg.p[0].x = poly->p[0].x; + seg.p[0].y = poly->p[0].y; + seg.p[1].x = poly->p[poly->npts - 1].x; + seg.p[1].y = poly->p[poly->npts - 1].y; + result = dist_ps(&(circle->center), &seg); #ifdef GEODEBUG -printf( "dist_cpoly- segment 0/n distance is %f\n", *result); + printf("dist_cpoly- segment 0/n distance is %f\n", *result); #endif - /* check distances for other segments */ - for (i = 0; (i < poly->npts - 1); i++) { - seg.p[0].x = poly->p[i].x; - seg.p[0].y = poly->p[i].y; - seg.p[1].x = poly->p[i+1].x; - seg.p[1].y = poly->p[i+1].y; - d = dist_ps( &(circle->center), &seg); + /* check distances for other segments */ + for (i = 0; (i < poly->npts - 1); i++) + { + seg.p[0].x = poly->p[i].x; + seg.p[0].y = poly->p[i].y; + seg.p[1].x = poly->p[i + 1].x; + seg.p[1].y = poly->p[i + 1].y; + d = dist_ps(&(circle->center), &seg); #ifdef GEODEBUG -printf( "dist_cpoly- segment %d distance is %f\n", (i+1), *d); + printf("dist_cpoly- segment %d distance is %f\n", (i + 1), *d); #endif - if (*d < *result) *result = *d; - PFREE(d); - } + if (*d < *result) + *result = *d; + PFREE(d); + } - *result -= circle->radius; - if (*result < 0) *result = 0; + *result -= circle->radius; + if (*result < 0) + *result = 0; - return(result); -} /* dist_cpoly() */ + return (result); +} /* dist_cpoly() */ /*--------------------------------------------------------------------- - * interpt_ - * Intersection point of objects. - * We choose to ignore the "point" of intersection between - * lines and boxes, since there are typically two. + * interpt_ + * Intersection point of objects. + * We choose to ignore the "point" of intersection between + * lines and boxes, since there are typically two. *-------------------------------------------------------------------*/ -static Point *interpt_sl(LSEG *lseg, LINE *line) +static Point * +interpt_sl(LSEG * lseg, LINE * line) { - LINE *tmp; - Point *p; - - tmp = line_construct_pp(&lseg->p[0], &lseg->p[1]); - p = line_interpt(tmp, line); + LINE *tmp; + Point *p; + + tmp = line_construct_pp(&lseg->p[0], &lseg->p[1]); + p = line_interpt(tmp, line); #ifdef GEODEBUG -printf( "interpt_sl- segment is (%.*g %.*g) (%.*g %.*g)\n", - digits8, lseg->p[0].x, digits8, lseg->p[0].y, digits8, lseg->p[1].x, digits8, lseg->p[1].y); -printf( "interpt_sl- segment becomes line A=%.*g B=%.*g C=%.*g\n", - digits8, tmp->A, digits8, tmp->B, digits8, tmp->C); + printf("interpt_sl- segment is (%.*g %.*g) (%.*g %.*g)\n", + digits8, lseg->p[0].x, digits8, lseg->p[0].y, digits8, lseg->p[1].x, digits8, lseg->p[1].y); + printf("interpt_sl- segment becomes line A=%.*g B=%.*g C=%.*g\n", + digits8, tmp->A, digits8, tmp->B, digits8, tmp->C); #endif - if (PointerIsValid(p)) { + if (PointerIsValid(p)) + { #ifdef GEODEBUG -printf( "interpt_sl- intersection point is (%.*g %.*g)\n", digits8, p->x, digits8, p->y); + printf("interpt_sl- intersection point is (%.*g %.*g)\n", digits8, p->x, digits8, p->y); #endif - if (on_ps(p, lseg)) { + if (on_ps(p, lseg)) + { #ifdef GEODEBUG -printf( "interpt_sl- intersection point is on segment\n"); + printf("interpt_sl- intersection point is on segment\n"); #endif - } else { - PFREE(p); - p = NULL; + } + else + { + PFREE(p); + p = NULL; + } } - } - - PFREE(tmp); - return(p); + + PFREE(tmp); + return (p); } /*--------------------------------------------------------------------- - * close_ - * Point of closest proximity between objects. + * close_ + * Point of closest proximity between objects. *-------------------------------------------------------------------*/ -/* close_pl - - * The intersection point of a perpendicular of the line - * through the point. +/* close_pl - + * The intersection point of a perpendicular of the line + * through the point. */ -Point *close_pl(Point *pt, LINE *line) +Point * +close_pl(Point * pt, LINE * line) { - Point *result; - LINE *tmp; - double invm; - - result = PALLOCTYPE(Point); + Point *result; + LINE *tmp; + double invm; + + result = PALLOCTYPE(Point); #if FALSE - if (FPeq(line->A, -1.0) && FPzero(line->B)) { /* vertical */ - } + if (FPeq(line->A, -1.0) && FPzero(line->B)) + { /* vertical */ + } #endif - if (line_vertical(line)) { - result->x = line->C; - result->y = pt->y; - return(result); + if (line_vertical(line)) + { + result->x = line->C; + result->y = pt->y; + return (result); #if FALSE - } else if (FPzero(line->m)) { /* horizontal */ + } + else if (FPzero(line->m)) + { /* horizontal */ #endif - } else if (line_horizontal(line)) { - result->x = pt->x; - result->y = line->C; - return(result); - } - /* drop a perpendicular and find the intersection point */ + } + else if (line_horizontal(line)) + { + result->x = pt->x; + result->y = line->C; + return (result); + } + /* drop a perpendicular and find the intersection point */ #if FALSE - invm = -1.0 / line->m; + invm = -1.0 / line->m; #endif - /* invert and flip the sign on the slope to get a perpendicular */ - invm = line->B / line->A; - tmp = line_construct_pm(pt, invm); - result = line_interpt(tmp, line); - return(result); -} /* close_pl() */ - - -/* close_ps - - * Take the closest endpoint if the point is left, right, - * above, or below the segment, otherwise find the intersection - * point of the segment and its perpendicular through the point. - */ -Point *close_ps(Point *pt, LSEG *lseg) -{ - Point *result; - LINE *tmp; - double invm; - int xh, yh; - - result = NULL; - xh = lseg->p[0].x < lseg->p[1].x; - yh = lseg->p[0].y < lseg->p[1].y; - if (pt->x < lseg->p[!xh].x) - result = point_copy(&lseg->p[!xh]); - else if (pt->x > lseg->p[xh].x) - result = point_copy(&lseg->p[xh]); - else if (pt->y < lseg->p[!yh].y) - result = point_copy(&lseg->p[!yh]); - else if (pt->y > lseg->p[yh].y) - result = point_copy(&lseg->p[yh]); - if (result) - return(result); + /* invert and flip the sign on the slope to get a perpendicular */ + invm = line->B / line->A; + tmp = line_construct_pm(pt, invm); + result = line_interpt(tmp, line); + return (result); +} /* close_pl() */ + + +/* close_ps - + * Take the closest endpoint if the point is left, right, + * above, or below the segment, otherwise find the intersection + * point of the segment and its perpendicular through the point. + */ +Point * +close_ps(Point * pt, LSEG * lseg) +{ + Point *result; + LINE *tmp; + double invm; + int xh, + yh; + + result = NULL; + xh = lseg->p[0].x < lseg->p[1].x; + yh = lseg->p[0].y < lseg->p[1].y; + if (pt->x < lseg->p[!xh].x) + result = point_copy(&lseg->p[!xh]); + else if (pt->x > lseg->p[xh].x) + result = point_copy(&lseg->p[xh]); + else if (pt->y < lseg->p[!yh].y) + result = point_copy(&lseg->p[!yh]); + else if (pt->y > lseg->p[yh].y) + result = point_copy(&lseg->p[yh]); + if (result) + return (result); #if FALSE - if (FPeq(lseg->p[0].x, lseg->p[1].x)) /* vertical */ + if (FPeq(lseg->p[0].x, lseg->p[1].x)) /* vertical */ #endif - if (lseg_vertical(lseg)) { - result->x = lseg->p[0].x; - result->y = pt->y; - return(result); + if (lseg_vertical(lseg)) + { + result->x = lseg->p[0].x; + result->y = pt->y; + return (result); #if FALSE - } else if (FPzero(lseg->m)) { /* horizontal */ + } + else if (FPzero(lseg->m)) + { /* horizontal */ #endif - } else if (lseg_horizontal(lseg)) { - result->x = pt->x; - result->y = lseg->p[0].y; - return(result); - } - + } + else if (lseg_horizontal(lseg)) + { + result->x = pt->x; + result->y = lseg->p[0].y; + return (result); + } + #if FALSE - invm = -1.0 / lseg->m; + invm = -1.0 / lseg->m; #endif - invm = -1.0 / point_sl(&(lseg->p[0]), &(lseg->p[1])); - tmp = line_construct_pm(pt, invm); - result = interpt_sl(lseg, tmp); - return(result); -} /* close_ps() */ + invm = -1.0 / point_sl(&(lseg->p[0]), &(lseg->p[1])); + tmp = line_construct_pm(pt, invm); + result = interpt_sl(lseg, tmp); + return (result); +} /* close_ps() */ -Point *close_pb(Point *pt, BOX *box) +Point * +close_pb(Point * pt, BOX * box) { - /* think about this one for a while */ - elog(WARN, "close_pb not implemented", NULL); + /* think about this one for a while */ + elog(WARN, "close_pb not implemented", NULL); - return(NULL); + return (NULL); } -Point *close_sl(LSEG *lseg, LINE *line) +Point * +close_sl(LSEG * lseg, LINE * line) { - Point *result; - double *d1, *d2; + Point *result; + double *d1, + *d2; - result = interpt_sl(lseg, line); - if (result) - return(result); - d1 = dist_pl(&lseg->p[0], line); - d2 = dist_pl(&lseg->p[1], line); - if (d1 < d2) - result = point_copy(&lseg->p[0]); - else - result = point_copy(&lseg->p[1]); - - PFREE(d1); - PFREE(d2); - return(result); + result = interpt_sl(lseg, line); + if (result) + return (result); + d1 = dist_pl(&lseg->p[0], line); + d2 = dist_pl(&lseg->p[1], line); + if (d1 < d2) + result = point_copy(&lseg->p[0]); + else + result = point_copy(&lseg->p[1]); + + PFREE(d1); + PFREE(d2); + return (result); } -Point *close_sb(LSEG *lseg, BOX *box) +Point * +close_sb(LSEG * lseg, BOX * box) { - /* think about this one for a while */ - elog(WARN, "close_sb not implemented", NULL); + /* think about this one for a while */ + elog(WARN, "close_sb not implemented", NULL); - return(NULL); + return (NULL); } -Point *close_lb(LINE *line, BOX *box) +Point * +close_lb(LINE * line, BOX * box) { - /* think about this one for a while */ - elog(WARN, "close_lb not implemented", NULL); + /* think about this one for a while */ + elog(WARN, "close_lb not implemented", NULL); - return(NULL); + return (NULL); } /*--------------------------------------------------------------------- - * on_ - * Whether one object lies completely within another. + * on_ + * Whether one object lies completely within another. *-------------------------------------------------------------------*/ /* on_pl - - * Does the point satisfy the equation? + * Does the point satisfy the equation? */ -bool on_pl(Point *pt, LINE *line) +bool +on_pl(Point * pt, LINE * line) { - if (!PointerIsValid(pt) || !PointerIsValid(line)) - return(FALSE); + if (!PointerIsValid(pt) || !PointerIsValid(line)) + return (FALSE); - return( FPzero(line->A * pt->x + line->B * pt->y + line->C) ); + return (FPzero(line->A * pt->x + line->B * pt->y + line->C)); } /* on_ps - - * Determine colinearity by detecting a triangle inequality. + * Determine colinearity by detecting a triangle inequality. * This algorithm seems to behave nicely even with lsb residues - tgl 1997-07-09 */ -bool on_ps(Point *pt, LSEG *lseg) +bool +on_ps(Point * pt, LSEG * lseg) { - if (!PointerIsValid(pt) || !PointerIsValid(lseg)) - return(FALSE); + if (!PointerIsValid(pt) || !PointerIsValid(lseg)) + return (FALSE); - return( FPeq (point_dt(pt, &lseg->p[0]) + point_dt(pt, &lseg->p[1]), - point_dt(&lseg->p[0], &lseg->p[1])) ); + return (FPeq(point_dt(pt, &lseg->p[0]) + point_dt(pt, &lseg->p[1]), + point_dt(&lseg->p[0], &lseg->p[1]))); } -bool on_pb(Point *pt, BOX *box) +bool +on_pb(Point * pt, BOX * box) { - if (!PointerIsValid(pt) || !PointerIsValid(box)) - return(FALSE); + if (!PointerIsValid(pt) || !PointerIsValid(box)) + return (FALSE); - return( pt->x <= box->high.x && pt->x >= box->low.x && - pt->y <= box->high.y && pt->y >= box->low.y ); + return (pt->x <= box->high.x && pt->x >= box->low.x && + pt->y <= box->high.y && pt->y >= box->low.y); } -/* on_ppath - - * Whether a point lies within (on) a polyline. - * If open, we have to (groan) check each segment. +/* on_ppath - + * Whether a point lies within (on) a polyline. + * If open, we have to (groan) check each segment. * (uses same algorithm as for point intersecting segment - tgl 1997-07-09) - * If closed, we use the old O(n) ray method for point-in-polygon. - * The ray is horizontal, from pt out to the right. - * Each segment that crosses the ray counts as an - * intersection; note that an endpoint or edge may touch - * but not cross. - * (we can do p-in-p in lg(n), but it takes preprocessing) + * If closed, we use the old O(n) ray method for point-in-polygon. + * The ray is horizontal, from pt out to the right. + * Each segment that crosses the ray counts as an + * intersection; note that an endpoint or edge may touch + * but not cross. + * (we can do p-in-p in lg(n), but it takes preprocessing) */ -#define NEXT(A) ((A+1) % path->npts) /* cyclic "i+1" */ +#define NEXT(A) ((A+1) % path->npts) /* cyclic "i+1" */ -bool on_ppath(Point *pt, PATH *path) +bool +on_ppath(Point * pt, PATH * path) { #if FALSE - int above, next, /* is the seg above the ray? */ - inter, /* # of times path crosses ray */ - hi; /* index inc of higher seg (0,1) */ - double x, yh, yl, xh, xl; + int above, + next, /* is the seg above the ray? */ + inter, /* # of times path crosses ray */ + hi; /* index inc of higher seg (0,1) */ + double x, + yh, + yl, + xh, + xl; + #endif - int i, n; - double a, b; - - if (!PointerIsValid(pt) || !PointerIsValid(path)) - return(FALSE); - - if (! path->closed) { /*-- OPEN --*/ - n = path->npts - 1; - a = point_dt(pt, &path->p[0]); - for (i = 0; i < n; i++) { - b = point_dt(pt, &path->p[i+1]); - if (FPeq(a+b, - point_dt(&path->p[i], &path->p[i+1]))) - return(1); - a = b; - } - return(0); - } - - return(point_inside( pt, path->npts, path->p)); + int i, + n; + double a, + b; + + if (!PointerIsValid(pt) || !PointerIsValid(path)) + return (FALSE); + + if (!path->closed) + { /*-- OPEN --*/ + n = path->npts - 1; + a = point_dt(pt, &path->p[0]); + for (i = 0; i < n; i++) + { + b = point_dt(pt, &path->p[i + 1]); + if (FPeq(a + b, + point_dt(&path->p[i], &path->p[i + 1]))) + return (1); + a = b; + } + return (0); + } + + return (point_inside(pt, path->npts, path->p)); #if FALSE - inter = 0; /*-- CLOSED --*/ - above = FPgt(path->p[0].y, pt->y) ? ABOVE : - FPlt(path->p[0].y, pt->y) ? BELOW : UNDEF; - - for (i = 0; i < path->npts; i++) { - hi = path->p[i].y < path->p[NEXT(i)].y; - /* must take care of wrap around to original vertex for closed paths */ - yh = (i+hi < path->npts) ? path->p[i+hi].y : path->p[0].y; - yl = (i+!hi < path->npts) ? path->p[i+!hi].y : path->p[0].y; - hi = path->p[i].x < path->p[NEXT(i)].x; - xh = (i+hi < path->npts) ? path->p[i+hi].x : path->p[0].x; - xl = (i+!hi < path->npts) ? path->p[i+!hi].x : path->p[0].x; - /* skip seg if it doesn't touch the ray */ - - if (FPeq(yh, yl)) /* horizontal seg? */ - if (FPge(pt->x, xl) && FPle(pt->x, xh) && - FPeq(pt->y, yh)) - return(1); /* pt lies on seg */ - else - continue; /* skip other hz segs */ - if (FPlt(yh, pt->y) || /* pt is strictly below seg */ - FPgt(yl, pt->y)) /* strictly above */ - continue; - - /* seg touches the ray, find out where */ - - x = FPeq(xh, xl) /* vertical seg? */ - ? path->p[i].x - : (pt->y - path->p[i].y) / - point_sl(&path->p[i], - &path->p[NEXT(i)]) + - path->p[i].x; - if (FPeq(x, pt->x)) /* pt lies on this seg */ - return(1); - - /* does the seg actually cross the ray? */ - - next = FPgt(path->p[NEXT(i)].y, pt->y) ? ABOVE : - FPlt(path->p[NEXT(i)].y, pt->y) ? BELOW : above; - inter += FPge(x, pt->x) && next != above; - above = next; - } - return( above == UNDEF || /* path is horizontal */ - inter % 2); /* odd # of intersections */ + inter = 0; /*-- CLOSED --*/ + above = FPgt(path->p[0].y, pt->y) ? ABOVE : + FPlt(path->p[0].y, pt->y) ? BELOW : UNDEF; + + for (i = 0; i < path->npts; i++) + { + hi = path->p[i].y < path->p[NEXT(i)].y; + + /* + * must take care of wrap around to original vertex for closed + * paths + */ + yh = (i + hi < path->npts) ? path->p[i + hi].y : path->p[0].y; + yl = (i + !hi < path->npts) ? path->p[i + !hi].y : path->p[0].y; + hi = path->p[i].x < path->p[NEXT(i)].x; + xh = (i + hi < path->npts) ? path->p[i + hi].x : path->p[0].x; + xl = (i + !hi < path->npts) ? path->p[i + !hi].x : path->p[0].x; + /* skip seg if it doesn't touch the ray */ + + if (FPeq(yh, yl)) /* horizontal seg? */ + if (FPge(pt->x, xl) && FPle(pt->x, xh) && + FPeq(pt->y, yh)) + return (1); /* pt lies on seg */ + else + continue; /* skip other hz segs */ + if (FPlt(yh, pt->y) || /* pt is strictly below seg */ + FPgt(yl, pt->y)) /* strictly above */ + continue; + + /* seg touches the ray, find out where */ + + x = FPeq(xh, xl) /* vertical seg? */ + ? path->p[i].x + : (pt->y - path->p[i].y) / + point_sl(&path->p[i], + &path->p[NEXT(i)]) + + path->p[i].x; + if (FPeq(x, pt->x)) /* pt lies on this seg */ + return (1); + + /* does the seg actually cross the ray? */ + + next = FPgt(path->p[NEXT(i)].y, pt->y) ? ABOVE : + FPlt(path->p[NEXT(i)].y, pt->y) ? BELOW : above; + inter += FPge(x, pt->x) && next != above; + above = next; + } + return (above == UNDEF || /* path is horizontal */ + inter % 2); /* odd # of intersections */ #endif -} /* on_ppath() */ +} /* on_ppath() */ -bool on_sl(LSEG *lseg, LINE *line) +bool +on_sl(LSEG * lseg, LINE * line) { - if (!PointerIsValid(lseg) || !PointerIsValid(line)) - return(FALSE); + if (!PointerIsValid(lseg) || !PointerIsValid(line)) + return (FALSE); - return( on_pl(&lseg->p[0], line) && on_pl(&lseg->p[1], line) ); -} /* on_sl() */ + return (on_pl(&lseg->p[0], line) && on_pl(&lseg->p[1], line)); +} /* on_sl() */ -bool on_sb(LSEG *lseg, BOX *box) +bool +on_sb(LSEG * lseg, BOX * box) { - if (!PointerIsValid(lseg) || !PointerIsValid(box)) - return(FALSE); + if (!PointerIsValid(lseg) || !PointerIsValid(box)) + return (FALSE); - return( on_pb(&lseg->p[0], box) && on_pb(&lseg->p[1], box) ); -} /* on_sb() */ + return (on_pb(&lseg->p[0], box) && on_pb(&lseg->p[1], box)); +} /* on_sb() */ /*--------------------------------------------------------------------- - * inter_ - * Whether one object intersects another. + * inter_ + * Whether one object intersects another. *-------------------------------------------------------------------*/ -bool inter_sl(LSEG *lseg, LINE *line) +bool +inter_sl(LSEG * lseg, LINE * line) { - Point *tmp; + Point *tmp; - if (!PointerIsValid(lseg) || !PointerIsValid(line)) - return(FALSE); + if (!PointerIsValid(lseg) || !PointerIsValid(line)) + return (FALSE); - tmp = interpt_sl(lseg, line); - if (tmp) { - PFREE(tmp); - return(1); - } - return(0); + tmp = interpt_sl(lseg, line); + if (tmp) + { + PFREE(tmp); + return (1); + } + return (0); } /* XXX segment and box should be able to intersect; tgl - 97/01/09 */ -bool inter_sb(LSEG *lseg, BOX *box) +bool +inter_sb(LSEG * lseg, BOX * box) { - return(0); + return (0); } /* XXX line and box should be able to intersect; tgl - 97/01/09 */ -bool inter_lb(LINE *line, BOX *box) +bool +inter_lb(LINE * line, BOX * box) { - return(0); + return (0); } /*------------------------------------------------------------------ * The following routines define a data type and operator class for - * POLYGONS .... Part of which (the polygon's bounding box) is built on + * POLYGONS .... Part of which (the polygon's bounding box) is built on * top of the BOX data type. * * make_bound_box - create the bounding box for the input polygon @@ -2220,77 +2490,91 @@ bool inter_lb(LINE *line, BOX *box) /*--------------------------------------------------------------------- * Make the smallest bounding box for the given polygon. *---------------------------------------------------------------------*/ -static void make_bound_box(POLYGON *poly) -{ - int i; - double x1,y1,x2,y2; +static void +make_bound_box(POLYGON * poly) +{ + int i; + double x1, + y1, + x2, + y2; + + if (poly->npts > 0) + { + x2 = x1 = poly->p[0].x; + y2 = y1 = poly->p[0].y; + for (i = 1; i < poly->npts; i++) + { + if (poly->p[i].x < x1) + x1 = poly->p[i].x; + if (poly->p[i].x > x2) + x2 = poly->p[i].x; + if (poly->p[i].y < y1) + y1 = poly->p[i].y; + if (poly->p[i].y > y2) + y2 = poly->p[i].y; + } - if (poly->npts > 0) { - x2 = x1 = poly->p[0].x; - y2 = y1 = poly->p[0].y; - for (i = 1; i < poly->npts; i++) { - if (poly->p[i].x < x1) x1 = poly->p[i].x; - if (poly->p[i].x > x2) x2 = poly->p[i].x; - if (poly->p[i].y < y1) y1 = poly->p[i].y; - if (poly->p[i].y > y2) y2 = poly->p[i].y; + box_fill(&(poly->boundbox), x1, x2, y1, y2); + } + else + { + elog(WARN, "Unable to create bounding box for empty polygon", NULL); } - - box_fill(&(poly->boundbox), x1, x2, y1, y2); - } else { - elog (WARN, "Unable to create bounding box for empty polygon", NULL); - } } /*------------------------------------------------------------------ * poly_in - read in the polygon from a string specification * - * External format: - * "((x0,y0),...,(xn,yn))" - * "x0,y0,...,xn,yn" - * also supports the older style "(x1,...,xn,y1,...yn)" + * External format: + * "((x0,y0),...,(xn,yn))" + * "x0,y0,...,xn,yn" + * also supports the older style "(x1,...,xn,y1,...yn)" *------------------------------------------------------------------*/ -POLYGON *poly_in(char *str) +POLYGON * +poly_in(char *str) { - POLYGON *poly; - int npts; - int size; - int isopen; - char *s; + POLYGON *poly; + int npts; + int size; + int isopen; + char *s; - if (!PointerIsValid(str)) - elog (WARN," Bad (null) polygon external representation"); + if (!PointerIsValid(str)) + elog(WARN, " Bad (null) polygon external representation"); - if ((npts = pair_count(str, ',')) <= 0) - elog(WARN, "Bad polygon external representation '%s'", str); + if ((npts = pair_count(str, ',')) <= 0) + elog(WARN, "Bad polygon external representation '%s'", str); - size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * npts); - poly = PALLOC(size); + size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * npts); + poly = PALLOC(size); - memset((char *) poly, 0, size); /* zero any holes */ - poly->size = size; - poly->npts = npts; + memset((char *) poly, 0, size); /* zero any holes */ + poly->size = size; + poly->npts = npts; - if ((! path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0]))) - || (*s != '\0')) - elog (WARN, "Bad polygon external representation '%s'",str); + if ((!path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0]))) + || (*s != '\0')) + elog(WARN, "Bad polygon external representation '%s'", str); - make_bound_box(poly); + make_bound_box(poly); - return( poly); -} /* poly_in() */ + return (poly); +} /* poly_in() */ /*--------------------------------------------------------------- - * poly_out - convert internal POLYGON representation to the - * character string format "((f8,f8),...,(f8,f8))" - * also support old format "(f8,f8,...,f8,f8)" + * poly_out - convert internal POLYGON representation to the + * character string format "((f8,f8),...,(f8,f8))" + * also support old format "(f8,f8,...,f8,f8)" *---------------------------------------------------------------*/ -char *poly_out(POLYGON *poly) +char * +poly_out(POLYGON * poly) { - if (!PointerIsValid(poly)) - return NULL; + if (!PointerIsValid(poly)) + return NULL; - return( path_encode( TRUE, poly->npts, &(poly->p[0]))); -} /* poly_out() */ + return (path_encode(TRUE, poly->npts, &(poly->p[0]))); +} /* poly_out() */ /*------------------------------------------------------- @@ -2298,9 +2582,10 @@ char *poly_out(POLYGON *poly) * the right most point of A left of the left most point * of B? *-------------------------------------------------------*/ -bool poly_left(POLYGON *polya, POLYGON *polyb) +bool +poly_left(POLYGON * polya, POLYGON * polyb) { - return (polya->boundbox.high.x < polyb->boundbox.low.x); + return (polya->boundbox.high.x < polyb->boundbox.low.x); } /*------------------------------------------------------- @@ -2308,9 +2593,10 @@ bool poly_left(POLYGON *polya, POLYGON *polyb) * the left most point of A left of the right most point * of B? *-------------------------------------------------------*/ -bool poly_overleft(POLYGON *polya, POLYGON *polyb) +bool +poly_overleft(POLYGON * polya, POLYGON * polyb) { - return (polya->boundbox.low.x <= polyb->boundbox.high.x); + return (polya->boundbox.low.x <= polyb->boundbox.high.x); } /*------------------------------------------------------- @@ -2318,9 +2604,10 @@ bool poly_overleft(POLYGON *polya, POLYGON *polyb) * the left most point of A right of the right most point * of B? *-------------------------------------------------------*/ -bool poly_right(POLYGON *polya, POLYGON *polyb) +bool +poly_right(POLYGON * polya, POLYGON * polyb) { - return( polya->boundbox.low.x > polyb->boundbox.high.x); + return (polya->boundbox.low.x > polyb->boundbox.high.x); } /*------------------------------------------------------- @@ -2328,45 +2615,49 @@ bool poly_right(POLYGON *polya, POLYGON *polyb) * the right most point of A right of the left most point * of B? *-------------------------------------------------------*/ -bool poly_overright(POLYGON *polya, POLYGON *polyb) +bool +poly_overright(POLYGON * polya, POLYGON * polyb) { - return( polya->boundbox.high.x > polyb->boundbox.low.x); + return (polya->boundbox.high.x > polyb->boundbox.low.x); } /*------------------------------------------------------- * Is polygon A the same as polygon B? i.e. are all the * points the same? * Check all points for matches in both forward and reverse - * direction since polygons are non-directional and are - * closed shapes. + * direction since polygons are non-directional and are + * closed shapes. *-------------------------------------------------------*/ -bool poly_same(POLYGON *polya, POLYGON *polyb) +bool +poly_same(POLYGON * polya, POLYGON * polyb) { - if (! PointerIsValid( polya) || ! PointerIsValid( polyb)) - return FALSE; + if (!PointerIsValid(polya) || !PointerIsValid(polyb)) + return FALSE; - if (polya->npts != polyb->npts) - return FALSE; + if (polya->npts != polyb->npts) + return FALSE; - return(plist_same( polya->npts, polya->p, polyb->p)); + return (plist_same(polya->npts, polya->p, polyb->p)); #if FALSE - for (i = 0; i < polya->npts; i++) { - if ((polya->p[i].x != polyb->p[i].x) - || (polya->p[i].y != polyb->p[i].y)) - return FALSE; - } - return TRUE; + for (i = 0; i < polya->npts; i++) + { + if ((polya->p[i].x != polyb->p[i].x) + || (polya->p[i].y != polyb->p[i].y)) + return FALSE; + } + return TRUE; #endif -} /* poly_same() */ +} /* poly_same() */ /*----------------------------------------------------------------- * Determine if polygon A overlaps polygon B by determining if * their bounding boxes overlap. *-----------------------------------------------------------------*/ -bool poly_overlap(POLYGON *polya, POLYGON *polyb) +bool +poly_overlap(POLYGON * polya, POLYGON * polyb) { - return box_overlap(&(polya->boundbox), &(polyb->boundbox)); + return box_overlap(&(polya->boundbox), &(polyb->boundbox)); } @@ -2375,484 +2666,504 @@ bool poly_overlap(POLYGON *polya, POLYGON *polyb) * bounding box contains B's bounding box. *-----------------------------------------------------------------*/ #if FALSE -bool poly_contain(POLYGON *polya, POLYGON *polyb) +bool +poly_contain(POLYGON * polya, POLYGON * polyb) { - return box_contain(&(polya->boundbox), &(polyb->boundbox)); + return box_contain(&(polya->boundbox), &(polyb->boundbox)); } + #endif bool -poly_contain(POLYGON *polya, POLYGON *polyb) +poly_contain(POLYGON * polya, POLYGON * polyb) { - int i; + int i; - if (!PointerIsValid(polya) || !PointerIsValid(polyb)) - return(FALSE); + if (!PointerIsValid(polya) || !PointerIsValid(polyb)) + return (FALSE); - if (box_contain(&(polya->boundbox), &(polyb->boundbox))) { - for (i = 0; i < polyb->npts; i++) { - if (point_inside(&(polyb->p[i]), polya->npts, &(polya->p[0])) == 0) { + if (box_contain(&(polya->boundbox), &(polyb->boundbox))) + { + for (i = 0; i < polyb->npts; i++) + { + if (point_inside(&(polyb->p[i]), polya->npts, &(polya->p[0])) == 0) + { #if GEODEBUG -printf( "poly_contain- point (%f,%f) not in polygon\n", polyb->p[i].x, polyb->p[i].y); + printf("poly_contain- point (%f,%f) not in polygon\n", polyb->p[i].x, polyb->p[i].y); #endif - return(FALSE); - } - } - for (i = 0; i < polya->npts; i++) { - if (point_inside(&(polya->p[i]), polyb->npts, &(polyb->p[0])) == 1) { + return (FALSE); + } + } + for (i = 0; i < polya->npts; i++) + { + if (point_inside(&(polya->p[i]), polyb->npts, &(polyb->p[0])) == 1) + { #if GEODEBUG -printf( "poly_contain- point (%f,%f) in polygon\n", polya->p[i].x, polya->p[i].y); + printf("poly_contain- point (%f,%f) in polygon\n", polya->p[i].x, polya->p[i].y); #endif - return(FALSE); - } + return (FALSE); + } + } + return (TRUE); } - return(TRUE); - } #if GEODEBUG -printf( "poly_contain- bound box ((%f,%f),(%f,%f)) not inside ((%f,%f),(%f,%f))\n", - polyb->boundbox.low.x,polyb->boundbox.low.y,polyb->boundbox.high.x,polyb->boundbox.high.y, - polya->boundbox.low.x,polya->boundbox.low.y,polya->boundbox.high.x,polya->boundbox.high.y); + printf("poly_contain- bound box ((%f,%f),(%f,%f)) not inside ((%f,%f),(%f,%f))\n", + polyb->boundbox.low.x, polyb->boundbox.low.y, polyb->boundbox.high.x, polyb->boundbox.high.y, + polya->boundbox.low.x, polya->boundbox.low.y, polya->boundbox.high.x, polya->boundbox.high.y); #endif - return(FALSE); -} /* poly_contain() */ + return (FALSE); +} /* poly_contain() */ /*----------------------------------------------------------------- - * Determine if polygon A is contained by polygon B by determining + * Determine if polygon A is contained by polygon B by determining * if A's bounding box is contained by B's bounding box. *-----------------------------------------------------------------*/ #if FALSE -bool poly_contained(POLYGON *polya, POLYGON *polyb) +bool +poly_contained(POLYGON * polya, POLYGON * polyb) { - return(box_contained(&(polya->boundbox), &(polyb->boundbox))); + return (box_contained(&(polya->boundbox), &(polyb->boundbox))); } + #endif -bool poly_contained(POLYGON *polya, POLYGON *polyb) +bool +poly_contained(POLYGON * polya, POLYGON * polyb) { - return(poly_contain(polyb, polya)); -} /* poly_contained() */ + return (poly_contain(polyb, polya)); +} /* poly_contained() */ /* poly_contain_pt() * Test to see if the point is inside the polygon. * Code adapted from integer-based routines in - * Wn: A Server for the HTTP - * File: wn/image.c - * Version 1.15.1 - * Copyright (C) 1995 <by John Franks> + * Wn: A Server for the HTTP + * File: wn/image.c + * Version 1.15.1 + * Copyright (C) 1995 <by John Franks> * (code offered for use by J. Franks in Linux Journal letter.) */ bool -poly_contain_pt( POLYGON *poly, Point *p) +poly_contain_pt(POLYGON * poly, Point * p) { - if (!PointerIsValid(poly) || !PointerIsValid(p)) - return(FALSE); + if (!PointerIsValid(poly) || !PointerIsValid(p)) + return (FALSE); - return(point_inside(p, poly->npts, &(poly->p[0])) != 0); -} /* poly_contain_pt() */ + return (point_inside(p, poly->npts, &(poly->p[0])) != 0); +} /* poly_contain_pt() */ bool -pt_contained_poly( Point *p, POLYGON *poly) +pt_contained_poly(Point * p, POLYGON * poly) { - if (!PointerIsValid(p) || !PointerIsValid(poly)) - return(FALSE); + if (!PointerIsValid(p) || !PointerIsValid(poly)) + return (FALSE); - return(poly_contain_pt( poly, p)); -} /* pt_contained_poly() */ + return (poly_contain_pt(poly, p)); +} /* pt_contained_poly() */ -double * -poly_distance( POLYGON *polya, POLYGON *polyb) +double * +poly_distance(POLYGON * polya, POLYGON * polyb) { - double *result; + double *result; - if (!PointerIsValid(polya) || !PointerIsValid(polyb)) - return(NULL); + if (!PointerIsValid(polya) || !PointerIsValid(polyb)) + return (NULL); - result = PALLOCTYPE(double); + result = PALLOCTYPE(double); - *result = 0; + *result = 0; - return(result); -} /* poly_distance() */ + return (result); +} /* poly_distance() */ /*********************************************************************** ** - ** Routines for 2D points. + ** Routines for 2D points. ** ***********************************************************************/ -Point * -point(float8 *x, float8 *y) +Point * +point(float8 * x, float8 * y) { - if (! (PointerIsValid(x) && PointerIsValid(y))) - return(NULL); + if (!(PointerIsValid(x) && PointerIsValid(y))) + return (NULL); - return(point_construct(*x, *y)); -} /* point() */ + return (point_construct(*x, *y)); +} /* point() */ -Point * -point_add(Point *p1, Point *p2) +Point * +point_add(Point * p1, Point * p2) { - Point *result; + Point *result; - if (! (PointerIsValid(p1) && PointerIsValid(p2))) - return(NULL); + if (!(PointerIsValid(p1) && PointerIsValid(p2))) + return (NULL); - result = PALLOCTYPE(Point); + result = PALLOCTYPE(Point); - result->x = (p1->x + p2->x); - result->y = (p1->y + p2->y); + result->x = (p1->x + p2->x); + result->y = (p1->y + p2->y); - return(result); -} /* point_add() */ + return (result); +} /* point_add() */ -Point * -point_sub(Point *p1, Point *p2) +Point * +point_sub(Point * p1, Point * p2) { - Point *result; + Point *result; - if (! (PointerIsValid(p1) && PointerIsValid(p2))) - return(NULL); + if (!(PointerIsValid(p1) && PointerIsValid(p2))) + return (NULL); - result = PALLOCTYPE(Point); + result = PALLOCTYPE(Point); - result->x = (p1->x - p2->x); - result->y = (p1->y - p2->y); + result->x = (p1->x - p2->x); + result->y = (p1->y - p2->y); - return(result); -} /* point_sub() */ + return (result); +} /* point_sub() */ -Point * -point_mul(Point *p1, Point *p2) +Point * +point_mul(Point * p1, Point * p2) { - Point *result; + Point *result; - if (! (PointerIsValid(p1) && PointerIsValid(p2))) - return(NULL); + if (!(PointerIsValid(p1) && PointerIsValid(p2))) + return (NULL); - result = PALLOCTYPE(Point); + result = PALLOCTYPE(Point); - result->x = (p1->x*p2->x) - (p1->y*p2->y); - result->y = (p1->x*p2->y) + (p1->y*p2->x); + result->x = (p1->x * p2->x) - (p1->y * p2->y); + result->y = (p1->x * p2->y) + (p1->y * p2->x); - return(result); -} /* point_mul() */ + return (result); +} /* point_mul() */ -Point * -point_div(Point *p1, Point *p2) +Point * +point_div(Point * p1, Point * p2) { - Point *result; - double div; + Point *result; + double div; - if (! (PointerIsValid(p1) && PointerIsValid(p2))) - return(NULL); + if (!(PointerIsValid(p1) && PointerIsValid(p2))) + return (NULL); - result = PALLOCTYPE(Point); + result = PALLOCTYPE(Point); - div = (p2->x*p2->x) + (p2->y*p2->y); + div = (p2->x * p2->x) + (p2->y * p2->y); - if (div == 0.0) - elog(WARN,"point_div: divide by 0.0 error"); + if (div == 0.0) + elog(WARN, "point_div: divide by 0.0 error"); - result->x = ((p1->x*p2->x) + (p1->y*p2->y)) / div; - result->y = ((p2->x*p1->y) - (p2->y*p1->x)) / div; + result->x = ((p1->x * p2->x) + (p1->y * p2->y)) / div; + result->y = ((p2->x * p1->y) - (p2->y * p1->x)) / div; - return(result); -} /* point_div() */ + return (result); +} /* point_div() */ /*********************************************************************** ** - ** Routines for 2D boxes. + ** Routines for 2D boxes. ** ***********************************************************************/ -BOX * -box(Point *p1, Point *p2) +BOX * +box(Point * p1, Point * p2) { - BOX *result; + BOX *result; - if (! (PointerIsValid(p1) && PointerIsValid(p2))) - return(NULL); + if (!(PointerIsValid(p1) && PointerIsValid(p2))) + return (NULL); - result = box_construct( p1->x, p2->x, p1->y, p2->y); + result = box_construct(p1->x, p2->x, p1->y, p2->y); - return(result); -} /* box() */ + return (result); +} /* box() */ -BOX * -box_add(BOX *box, Point *p) +BOX * +box_add(BOX * box, Point * p) { - BOX *result; + BOX *result; - if (! (PointerIsValid(box) && PointerIsValid(p))) - return(NULL); + if (!(PointerIsValid(box) && PointerIsValid(p))) + return (NULL); - result = box_construct( (box->high.x + p->x), (box->low.x + p->x), - (box->high.y + p->y), (box->low.y + p->y)); + result = box_construct((box->high.x + p->x), (box->low.x + p->x), + (box->high.y + p->y), (box->low.y + p->y)); - return(result); -} /* box_add() */ + return (result); +} /* box_add() */ -BOX * -box_sub(BOX *box, Point *p) +BOX * +box_sub(BOX * box, Point * p) { - BOX *result; + BOX *result; - if (! (PointerIsValid(box) && PointerIsValid(p))) - return(NULL); + if (!(PointerIsValid(box) && PointerIsValid(p))) + return (NULL); - result = box_construct( (box->high.x - p->x), (box->low.x - p->x), - (box->high.y - p->y), (box->low.y - p->y)); + result = box_construct((box->high.x - p->x), (box->low.x - p->x), + (box->high.y - p->y), (box->low.y - p->y)); - return(result); -} /* box_sub() */ + return (result); +} /* box_sub() */ -BOX * -box_mul(BOX *box, Point *p) +BOX * +box_mul(BOX * box, Point * p) { - BOX *result; - Point *high, *low; + BOX *result; + Point *high, + *low; - if (! (PointerIsValid(box) && PointerIsValid(p))) - return(NULL); + if (!(PointerIsValid(box) && PointerIsValid(p))) + return (NULL); - high = point_mul( &box->high, p); - low = point_mul( &box->low, p); + high = point_mul(&box->high, p); + low = point_mul(&box->low, p); - result = box_construct( high->x, low->x, high->y, low->y); - PFREE( high); - PFREE( low); + result = box_construct(high->x, low->x, high->y, low->y); + PFREE(high); + PFREE(low); - return(result); -} /* box_mul() */ + return (result); +} /* box_mul() */ -BOX * -box_div(BOX *box, Point *p) +BOX * +box_div(BOX * box, Point * p) { - BOX *result; - Point *high, *low; + BOX *result; + Point *high, + *low; - if (! (PointerIsValid(box) && PointerIsValid(p))) - return(NULL); + if (!(PointerIsValid(box) && PointerIsValid(p))) + return (NULL); - high = point_div( &box->high, p); - low = point_div( &box->low, p); + high = point_div(&box->high, p); + low = point_div(&box->low, p); - result = box_construct( high->x, low->x, high->y, low->y); - PFREE( high); - PFREE( low); + result = box_construct(high->x, low->x, high->y, low->y); + PFREE(high); + PFREE(low); - return(result); -} /* box_div() */ + return (result); +} /* box_div() */ /*********************************************************************** ** - ** Routines for 2D lines. - ** Lines are not intended to be used as ADTs per se, - ** but their ops are useful tools for other ADT ops. Thus, - ** there are few relops. + ** Routines for 2D lines. + ** Lines are not intended to be used as ADTs per se, + ** but their ops are useful tools for other ADT ops. Thus, + ** there are few relops. ** ***********************************************************************/ /*********************************************************************** ** - ** Routines for 2D paths. + ** Routines for 2D paths. ** ***********************************************************************/ /* path_add() * Concatenate two paths (only if they are both open). */ -PATH * -path_add(PATH *p1, PATH *p2) +PATH * +path_add(PATH * p1, PATH * p2) { - PATH *result; - int size; - int i; + PATH *result; + int size; + int i; - if (! (PointerIsValid(p1) && PointerIsValid(p2)) - || p1->closed || p2->closed) - return(NULL); + if (!(PointerIsValid(p1) && PointerIsValid(p2)) + || p1->closed || p2->closed) + return (NULL); - size = offsetof(PATH, p[0]) + (sizeof(p1->p[0]) * (p1->npts+p2->npts)); - result = PALLOC(size); + size = offsetof(PATH, p[0]) + (sizeof(p1->p[0]) * (p1->npts + p2->npts)); + result = PALLOC(size); - result->size = size; - result->npts = (p1->npts+p2->npts); - result->closed = p1->closed; + result->size = size; + result->npts = (p1->npts + p2->npts); + result->closed = p1->closed; - for (i=0; i<p1->npts; i++) { - result->p[i].x = p1->p[i].x; - result->p[i].y = p1->p[i].y; - } - for (i=0; i<p2->npts; i++) { - result->p[i+p1->npts].x = p2->p[i].x; - result->p[i+p1->npts].y = p2->p[i].y; - } + for (i = 0; i < p1->npts; i++) + { + result->p[i].x = p1->p[i].x; + result->p[i].y = p1->p[i].y; + } + for (i = 0; i < p2->npts; i++) + { + result->p[i + p1->npts].x = p2->p[i].x; + result->p[i + p1->npts].y = p2->p[i].y; + } - return(result); -} /* path_add() */ + return (result); +} /* path_add() */ /* path_add_pt() * Translation operator. */ -PATH * -path_add_pt(PATH *path, Point *point) +PATH * +path_add_pt(PATH * path, Point * point) { - PATH *result; - int i; + PATH *result; + int i; - if ((!PointerIsValid(path)) || (!PointerIsValid(point))) - return(NULL); + if ((!PointerIsValid(path)) || (!PointerIsValid(point))) + return (NULL); - result = path_copy(path); + result = path_copy(path); - for (i=0; i<path->npts; i++) { - result->p[i].x += point->x; - result->p[i].y += point->y; - } + for (i = 0; i < path->npts; i++) + { + result->p[i].x += point->x; + result->p[i].y += point->y; + } - return(result); -} /* path_add_pt() */ + return (result); +} /* path_add_pt() */ -PATH * -path_sub_pt(PATH *path, Point *point) +PATH * +path_sub_pt(PATH * path, Point * point) { - PATH *result; - int i; + PATH *result; + int i; - if ((!PointerIsValid(path)) || (!PointerIsValid(point))) - return(NULL); + if ((!PointerIsValid(path)) || (!PointerIsValid(point))) + return (NULL); - result = path_copy(path); + result = path_copy(path); - for (i=0; i<path->npts; i++) { - result->p[i].x -= point->x; - result->p[i].y -= point->y; - } + for (i = 0; i < path->npts; i++) + { + result->p[i].x -= point->x; + result->p[i].y -= point->y; + } - return(result); -} /* path_sub_pt() */ + return (result); +} /* path_sub_pt() */ /* path_mul_pt() * Rotation and scaling operators. */ -PATH * -path_mul_pt(PATH *path, Point *point) +PATH * +path_mul_pt(PATH * path, Point * point) { - PATH *result; - Point *p; - int i; + PATH *result; + Point *p; + int i; - if ((!PointerIsValid(path)) || (!PointerIsValid(point))) - return(NULL); + if ((!PointerIsValid(path)) || (!PointerIsValid(point))) + return (NULL); - result = path_copy(path); + result = path_copy(path); - for (i=0; i<path->npts; i++) { - p = point_mul( &path->p[i], point); - result->p[i].x = p->x; - result->p[i].y = p->y; - PFREE(p); - } + for (i = 0; i < path->npts; i++) + { + p = point_mul(&path->p[i], point); + result->p[i].x = p->x; + result->p[i].y = p->y; + PFREE(p); + } - return(result); -} /* path_mul_pt() */ + return (result); +} /* path_mul_pt() */ -PATH * -path_div_pt(PATH *path, Point *point) +PATH * +path_div_pt(PATH * path, Point * point) { - PATH *result; - Point *p; - int i; + PATH *result; + Point *p; + int i; - if ((!PointerIsValid(path)) || (!PointerIsValid(point))) - return(NULL); + if ((!PointerIsValid(path)) || (!PointerIsValid(point))) + return (NULL); - result = path_copy(path); + result = path_copy(path); - for (i=0; i<path->npts; i++) { - p = point_div( &path->p[i], point); - result->p[i].x = p->x; - result->p[i].y = p->y; - PFREE(p); - } + for (i = 0; i < path->npts; i++) + { + p = point_div(&path->p[i], point); + result->p[i].x = p->x; + result->p[i].y = p->y; + PFREE(p); + } - return(result); -} /* path_div_pt() */ + return (result); +} /* path_div_pt() */ bool -path_contain_pt( PATH *path, Point *p) +path_contain_pt(PATH * path, Point * p) { - if (!PointerIsValid(path) || !PointerIsValid(p)) - return(FALSE); + if (!PointerIsValid(path) || !PointerIsValid(p)) + return (FALSE); - return( (path->closed? (point_inside(p, path->npts, &(path->p[0])) != 0): FALSE)); -} /* path_contain_pt() */ + return ((path->closed ? (point_inside(p, path->npts, &(path->p[0])) != 0) : FALSE)); +} /* path_contain_pt() */ bool -pt_contained_path( Point *p, PATH *path) +pt_contained_path(Point * p, PATH * path) { - if (!PointerIsValid(p) || !PointerIsValid(path)) - return(FALSE); + if (!PointerIsValid(p) || !PointerIsValid(path)) + return (FALSE); - return( path_contain_pt( path, p)); -} /* pt_contained_path() */ + return (path_contain_pt(path, p)); +} /* pt_contained_path() */ -Point * -path_center(PATH *path) +Point * +path_center(PATH * path) { - Point *result; + Point *result; - if (!PointerIsValid(path)) - return(NULL); + if (!PointerIsValid(path)) + return (NULL); - elog(WARN, "path_center not implemented", NULL); + elog(WARN, "path_center not implemented", NULL); - result = PALLOCTYPE(Point); - result = NULL; + result = PALLOCTYPE(Point); + result = NULL; - return(result); -} /* path_center() */ + return (result); +} /* path_center() */ -POLYGON *path_poly(PATH *path) +POLYGON * +path_poly(PATH * path) { - POLYGON *poly; - int size; - int i; + POLYGON *poly; + int size; + int i; - if (!PointerIsValid(path)) - return(NULL); + if (!PointerIsValid(path)) + return (NULL); - if (!path->closed) - elog(WARN, "Open path cannot be converted to polygon",NULL); + if (!path->closed) + elog(WARN, "Open path cannot be converted to polygon", NULL); - size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * path->npts); - poly = PALLOC(size); + size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * path->npts); + poly = PALLOC(size); - poly->size = size; - poly->npts = path->npts; + poly->size = size; + poly->npts = path->npts; - for (i=0; i<path->npts; i++) { - poly->p[i].x = path->p[i].x; - poly->p[i].y = path->p[i].y; - } + for (i = 0; i < path->npts; i++) + { + poly->p[i].x = path->p[i].x; + poly->p[i].y = path->p[i].y; + } - make_bound_box(poly); + make_bound_box(poly); - return(poly); -} /* path_polygon() */ + return (poly); +} /* path_polygon() */ /* upgradepath() @@ -2860,157 +3171,163 @@ POLYGON *path_poly(PATH *path) * * Old-style: '(closed,#pts,x1,y1,...)' where closed is a boolean flag * New-style: '((x1,y1),...)' for closed path - * '[(x1,y1),...]' for open path + * '[(x1,y1),...]' for open path */ PATH -*upgradepath(PATH *path) +* upgradepath(PATH * path) { - PATH *result; - int size, npts; - int i; + PATH *result; + int size, + npts; + int i; - if (!PointerIsValid(path) || (path->npts < 2)) - return(NULL); + if (!PointerIsValid(path) || (path->npts < 2)) + return (NULL); - if (! isoldpath(path)) - elog(WARN,"upgradepath: path already upgraded?",NULL); + if (!isoldpath(path)) + elog(WARN, "upgradepath: path already upgraded?", NULL); - npts = (path->npts-1); - size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * npts); - result = PALLOC(size); - memset((char *) result, 0, size); + npts = (path->npts - 1); + size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * npts); + result = PALLOC(size); + memset((char *) result, 0, size); - result->size = size; - result->npts = npts; - result->closed = (path->p[0].x != 0); + result->size = size; + result->npts = npts; + result->closed = (path->p[0].x != 0); - for (i=0; i<result->npts; i++) { - result->p[i].x = path->p[i+1].x; - result->p[i].y = path->p[i+1].y; - } + for (i = 0; i < result->npts; i++) + { + result->p[i].x = path->p[i + 1].x; + result->p[i].y = path->p[i + 1].y; + } - return(result); -} /* upgradepath() */ + return (result); +} /* upgradepath() */ bool -isoldpath(PATH *path) +isoldpath(PATH * path) { - if (!PointerIsValid(path) || (path->npts < 2)) - return(FALSE); + if (!PointerIsValid(path) || (path->npts < 2)) + return (FALSE); - return(path->npts == (path->p[0].y+1)); -} /* isoldpath() */ + return (path->npts == (path->p[0].y + 1)); +} /* isoldpath() */ /*********************************************************************** ** - ** Routines for 2D polygons. + ** Routines for 2D polygons. ** ***********************************************************************/ int4 -poly_npoints(POLYGON *poly) +poly_npoints(POLYGON * poly) { - if (!PointerIsValid(poly)) - return(0); + if (!PointerIsValid(poly)) + return (0); - return(poly->npts); -} /* poly_npoints() */ + return (poly->npts); +} /* poly_npoints() */ -Point * -poly_center(POLYGON *poly) +Point * +poly_center(POLYGON * poly) { - Point *result; - CIRCLE *circle; + Point *result; + CIRCLE *circle; - if (!PointerIsValid(poly)) - return(NULL); + if (!PointerIsValid(poly)) + return (NULL); - if (PointerIsValid(circle = poly_circle(poly))) { - result = circle_center(circle); - PFREE(circle); + if (PointerIsValid(circle = poly_circle(poly))) + { + result = circle_center(circle); + PFREE(circle); - } else { - result = NULL; - } + } + else + { + result = NULL; + } - return(result); -} /* poly_center() */ + return (result); +} /* poly_center() */ -BOX * -poly_box(POLYGON *poly) +BOX * +poly_box(POLYGON * poly) { - BOX *box; + BOX *box; - if (!PointerIsValid(poly) || (poly->npts < 1)) - return(NULL); + if (!PointerIsValid(poly) || (poly->npts < 1)) + return (NULL); - box = box_copy( &poly->boundbox); + box = box_copy(&poly->boundbox); - return(box); -} /* poly_box() */ + return (box); +} /* poly_box() */ /* box_poly() * Convert a box to a polygon. */ -POLYGON * -box_poly(BOX *box) +POLYGON * +box_poly(BOX * box) { - POLYGON *poly; - int size; + POLYGON *poly; + int size; - if (!PointerIsValid(box)) - return(NULL); + if (!PointerIsValid(box)) + return (NULL); - /* map four corners of the box to a polygon */ - size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * 4); - poly = PALLOC(size); + /* map four corners of the box to a polygon */ + size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * 4); + poly = PALLOC(size); - poly->size = size; - poly->npts = 4; + poly->size = size; + poly->npts = 4; - poly->p[0].x = box->low.x; - poly->p[0].y = box->low.y; - poly->p[1].x = box->low.x; - poly->p[1].y = box->high.y; - poly->p[2].x = box->high.x; - poly->p[2].y = box->high.y; - poly->p[3].x = box->high.x; - poly->p[3].y = box->low.y; + poly->p[0].x = box->low.x; + poly->p[0].y = box->low.y; + poly->p[1].x = box->low.x; + poly->p[1].y = box->high.y; + poly->p[2].x = box->high.x; + poly->p[2].y = box->high.y; + poly->p[3].x = box->high.x; + poly->p[3].y = box->low.y; - box_fill( &poly->boundbox, box->high.x, box->low.x, box->high.y, box->low.y); + box_fill(&poly->boundbox, box->high.x, box->low.x, box->high.y, box->low.y); - return(poly); -} /* box_poly() */ + return (poly); +} /* box_poly() */ -PATH * -poly_path(POLYGON *poly) +PATH * +poly_path(POLYGON * poly) { - PATH *path; - int size; - int i; + PATH *path; + int size; + int i; - if (!PointerIsValid(poly) || (poly->npts < 0)) - return(NULL); + if (!PointerIsValid(poly) || (poly->npts < 0)) + return (NULL); - size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * poly->npts); - path = PALLOC(size); + size = offsetof(PATH, p[0]) + (sizeof(path->p[0]) * poly->npts); + path = PALLOC(size); - path->size = size; - path->npts = poly->npts; - path->closed = TRUE; + path->size = size; + path->npts = poly->npts; + path->closed = TRUE; - for (i=0; i<poly->npts; i++) { - path->p[i].x = poly->p[i].x; - path->p[i].y = poly->p[i].y; - } + for (i = 0; i < poly->npts; i++) + { + path->p[i].x = poly->p[i].x; + path->p[i].y = poly->p[i].y; + } - return(path); -} /* poly_path() */ + return (path); +} /* poly_path() */ /* upgradepoly() @@ -3019,86 +3336,98 @@ poly_path(POLYGON *poly) * New-style: '(x1,y1,x2,y2,...)' */ POLYGON -*upgradepoly(POLYGON *poly) +* upgradepoly(POLYGON * poly) { - POLYGON *result; - int size; - int n2, i, ii; + POLYGON *result; + int size; + int n2, + i, + ii; - if (!PointerIsValid(poly) || (poly->npts < 1)) - return(NULL); + if (!PointerIsValid(poly) || (poly->npts < 1)) + return (NULL); - size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * poly->npts); - result = PALLOC(size); - memset((char *) result, 0, size); + size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * poly->npts); + result = PALLOC(size); + memset((char *) result, 0, size); - result->size = size; - result->npts = poly->npts; + result->size = size; + result->npts = poly->npts; - n2 = poly->npts/2; + n2 = poly->npts / 2; - for (i=0; i<n2; i++) { - result->p[2*i].x = poly->p[i].x; /* even indices */ - result->p[2*i+1].x = poly->p[i].y; /* odd indices */ - } + for (i = 0; i < n2; i++) + { + result->p[2 * i].x = poly->p[i].x; /* even indices */ + result->p[2 * i + 1].x = poly->p[i].y; /* odd indices */ + } - if ((ii = ((poly->npts % 2)? 1: 0))) { - result->p[poly->npts-1].x = poly->p[n2].x; - result->p[0].y = poly->p[n2].y; - } + if ((ii = ((poly->npts % 2) ? 1 : 0))) + { + result->p[poly->npts - 1].x = poly->p[n2].x; + result->p[0].y = poly->p[n2].y; + } - for (i=0; i<n2; i++) { - result->p[2*i+ii].y = poly->p[i+n2+ii].x; /* even (+offset) indices */ - result->p[2*i+ii+1].y = poly->p[i+n2+ii].y; /* odd (+offset) indices */ - } + for (i = 0; i < n2; i++) + { + result->p[2 * i + ii].y = poly->p[i + n2 + ii].x; /* even (+offset) + * indices */ + result->p[2 * i + ii + 1].y = poly->p[i + n2 + ii].y; /* odd (+offset) indices */ + } - return(result); -} /* upgradepoly() */ + return (result); +} /* upgradepoly() */ /* revertpoly() * Reverse effect of upgradepoly(). */ POLYGON -*revertpoly(POLYGON *poly) +* revertpoly(POLYGON * poly) { - POLYGON *result; - int size; - int n2, i, ii; + POLYGON *result; + int size; + int n2, + i, + ii; - if (!PointerIsValid(poly) || (poly->npts < 1)) - return(NULL); + if (!PointerIsValid(poly) || (poly->npts < 1)) + return (NULL); - size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * poly->npts); - result = PALLOC(size); - memset((char *) result, 0, size); + size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * poly->npts); + result = PALLOC(size); + memset((char *) result, 0, size); - result->size = size; - result->npts = poly->npts; + result->size = size; + result->npts = poly->npts; - n2 = poly->npts/2; + n2 = poly->npts / 2; - for (i=0; i<n2; i++) { - result->p[i].x = poly->p[2*i].x; /* even indices */ - result->p[i].y = poly->p[2*i+1].x; /* odd indices */ - } + for (i = 0; i < n2; i++) + { + result->p[i].x = poly->p[2 * i].x; /* even indices */ + result->p[i].y = poly->p[2 * i + 1].x; /* odd indices */ + } - if ((ii = ((poly->npts % 2)? 1: 0))) { - result->p[n2].x = poly->p[poly->npts-1].x; - result->p[n2].y = poly->p[0].y; - } + if ((ii = ((poly->npts % 2) ? 1 : 0))) + { + result->p[n2].x = poly->p[poly->npts - 1].x; + result->p[n2].y = poly->p[0].y; + } - for (i=0; i<n2; i++) { - result->p[i+n2+ii].x = poly->p[2*i+ii].y; /* even (+offset) indices */ - result->p[i+n2+ii].y = poly->p[2*i+ii+1].y; /* odd (+offset) indices */ - } + for (i = 0; i < n2; i++) + { + result->p[i + n2 + ii].x = poly->p[2 * i + ii].y; /* even (+offset) + * indices */ + result->p[i + n2 + ii].y = poly->p[2 * i + ii + 1].y; /* odd (+offset) indices */ + } - return(result); -} /* revertpoly() */ + return (result); +} /* revertpoly() */ /*********************************************************************** ** - ** Routines for circles. + ** Routines for circles. ** ***********************************************************************/ @@ -3106,594 +3435,645 @@ POLYGON * Formatting and conversion routines. *---------------------------------------------------------*/ -/* circle_in - convert a string to internal form. +/* circle_in - convert a string to internal form. * - * External format: (center and radius of circle) - * "((f8,f8)<f8>)" - * also supports quick entry style "(f8,f8,f8)" + * External format: (center and radius of circle) + * "((f8,f8)<f8>)" + * also supports quick entry style "(f8,f8,f8)" */ -CIRCLE *circle_in(char *str) -{ - CIRCLE *circle; - - char *s, *cp; - int depth = 0; - - if (!PointerIsValid(str)) - elog (WARN," Bad (null) circle external representation",NULL); - - circle = PALLOCTYPE(CIRCLE); - - s = str; - while (isspace( *s)) s++; - if ((*s == LDELIM_C) || (*s == LDELIM)) { - depth++; - cp = (s+1); - while (isspace( *cp)) cp++; - if (*cp == LDELIM) { - s = cp; +CIRCLE * +circle_in(char *str) +{ + CIRCLE *circle; + + char *s, + *cp; + int depth = 0; + + if (!PointerIsValid(str)) + elog(WARN, " Bad (null) circle external representation", NULL); + + circle = PALLOCTYPE(CIRCLE); + + s = str; + while (isspace(*s)) + s++; + if ((*s == LDELIM_C) || (*s == LDELIM)) + { + depth++; + cp = (s + 1); + while (isspace(*cp)) + cp++; + if (*cp == LDELIM) + { + s = cp; + } } - } - - if (! pair_decode( s, &circle->center.x, &circle->center.y, &s)) - elog (WARN, "Bad circle external representation '%s'",str); - - if (*s == DELIM) s++; - while (isspace( *s)) s++; - if ((! single_decode( s, &circle->radius, &s)) || (circle->radius < 0)) - elog (WARN, "Bad circle external representation '%s'",str); - - while (depth > 0) { - if ((*s == RDELIM) - || ((*s == RDELIM_C) && (depth == 1))) { - depth--; - s++; - while (isspace( *s)) s++; - } else { - elog (WARN, "Bad circle external representation '%s'",str); + if (!pair_decode(s, &circle->center.x, &circle->center.y, &s)) + elog(WARN, "Bad circle external representation '%s'", str); + + if (*s == DELIM) + s++; + while (isspace(*s)) + s++; + + if ((!single_decode(s, &circle->radius, &s)) || (circle->radius < 0)) + elog(WARN, "Bad circle external representation '%s'", str); + + while (depth > 0) + { + if ((*s == RDELIM) + || ((*s == RDELIM_C) && (depth == 1))) + { + depth--; + s++; + while (isspace(*s)) + s++; + } + else + { + elog(WARN, "Bad circle external representation '%s'", str); + } } - } - if (*s != '\0') - elog (WARN, "Bad circle external representation '%s'",str); + if (*s != '\0') + elog(WARN, "Bad circle external representation '%s'", str); - return(circle); -} /* circle_in() */ + return (circle); +} /* circle_in() */ -/* circle_out - convert a circle to external form. +/* circle_out - convert a circle to external form. */ -char *circle_out(CIRCLE *circle) +char * +circle_out(CIRCLE * circle) { - char *result; - char *cp; + char *result; + char *cp; - if (!PointerIsValid(circle)) - return(NULL); + if (!PointerIsValid(circle)) + return (NULL); - result = PALLOC(3*(P_MAXLEN+1)+3); + result = PALLOC(3 * (P_MAXLEN + 1) + 3); - cp = result; - *cp++ = LDELIM_C; - *cp++ = LDELIM; - if (! pair_encode( circle->center.x, circle->center.y, cp)) - elog (WARN, "Unable to format circle", NULL); + cp = result; + *cp++ = LDELIM_C; + *cp++ = LDELIM; + if (!pair_encode(circle->center.x, circle->center.y, cp)) + elog(WARN, "Unable to format circle", NULL); - cp += strlen(cp); - *cp++ = RDELIM; - *cp++ = DELIM; - if (! single_encode( circle->radius, cp)) - elog (WARN, "Unable to format circle", NULL); + cp += strlen(cp); + *cp++ = RDELIM; + *cp++ = DELIM; + if (!single_encode(circle->radius, cp)) + elog(WARN, "Unable to format circle", NULL); - cp += strlen(cp); - *cp++ = RDELIM_C; - *cp = '\0'; + cp += strlen(cp); + *cp++ = RDELIM_C; + *cp = '\0'; - return(result); -} /* circle_out() */ + return (result); +} /* circle_out() */ /*---------------------------------------------------------- - * Relational operators for CIRCLEs. - * <, >, <=, >=, and == are based on circle area. + * Relational operators for CIRCLEs. + * <, >, <=, >=, and == are based on circle area. *---------------------------------------------------------*/ -/* circles identical? +/* circles identical? */ -bool circle_same(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_same(CIRCLE * circle1, CIRCLE * circle2) { - return( FPeq(circle1->radius,circle2->radius) - && FPeq(circle1->center.x,circle2->center.x) - && FPeq(circle1->center.y,circle2->center.y)); + return (FPeq(circle1->radius, circle2->radius) + && FPeq(circle1->center.x, circle2->center.x) + && FPeq(circle1->center.y, circle2->center.y)); } -/* circle_overlap - does circle1 overlap circle2? +/* circle_overlap - does circle1 overlap circle2? */ -bool circle_overlap(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_overlap(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle(point_dt(&circle1->center,&circle2->center),(circle1->radius+circle2->radius))); + return (FPle(point_dt(&circle1->center, &circle2->center), (circle1->radius + circle2->radius))); } -/* circle_overleft - is the right edge of circle1 to the left of - * the right edge of circle2? +/* circle_overleft - is the right edge of circle1 to the left of + * the right edge of circle2? */ -bool circle_overleft(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_overleft(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle((circle1->center.x+circle1->radius),(circle2->center.x+circle2->radius))); + return (FPle((circle1->center.x + circle1->radius), (circle2->center.x + circle2->radius))); } -/* circle_left - is circle1 strictly left of circle2? +/* circle_left - is circle1 strictly left of circle2? */ -bool circle_left(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_left(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle((circle1->center.x+circle1->radius),(circle2->center.x-circle2->radius))); + return (FPle((circle1->center.x + circle1->radius), (circle2->center.x - circle2->radius))); } -/* circle_right - is circle1 strictly right of circle2? +/* circle_right - is circle1 strictly right of circle2? */ -bool circle_right(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_right(CIRCLE * circle1, CIRCLE * circle2) { - return( FPge((circle1->center.x-circle1->radius),(circle2->center.x+circle2->radius))); + return (FPge((circle1->center.x - circle1->radius), (circle2->center.x + circle2->radius))); } -/* circle_overright - is the left edge of circle1 to the right of - * the left edge of circle2? +/* circle_overright - is the left edge of circle1 to the right of + * the left edge of circle2? */ -bool circle_overright(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_overright(CIRCLE * circle1, CIRCLE * circle2) { - return( FPge((circle1->center.x-circle1->radius),(circle2->center.x-circle2->radius))); + return (FPge((circle1->center.x - circle1->radius), (circle2->center.x - circle2->radius))); } -/* circle_contained - is circle1 contained by circle2? +/* circle_contained - is circle1 contained by circle2? */ -bool circle_contained(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_contained(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle((point_dt(&circle1->center,&circle2->center)+circle1->radius),circle2->radius)); + return (FPle((point_dt(&circle1->center, &circle2->center) + circle1->radius), circle2->radius)); } -/* circle_contain - does circle1 contain circle2? +/* circle_contain - does circle1 contain circle2? */ -bool circle_contain(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_contain(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle((point_dt(&circle1->center,&circle2->center)+circle2->radius),circle1->radius)); + return (FPle((point_dt(&circle1->center, &circle2->center) + circle2->radius), circle1->radius)); } -/* circle_positionop - - * is circle1 entirely {above,below} circle2? +/* circle_positionop - + * is circle1 entirely {above,below} circle2? */ -bool circle_below(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_below(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle((circle1->center.y+circle1->radius),(circle2->center.y-circle2->radius))); + return (FPle((circle1->center.y + circle1->radius), (circle2->center.y - circle2->radius))); } -bool circle_above(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_above(CIRCLE * circle1, CIRCLE * circle2) { - return( FPge((circle1->center.y-circle1->radius),(circle2->center.y+circle2->radius))); + return (FPge((circle1->center.y - circle1->radius), (circle2->center.y + circle2->radius))); } -/* circle_relop - is area(circle1) relop area(circle2), within - * our accuracy constraint? +/* circle_relop - is area(circle1) relop area(circle2), within + * our accuracy constraint? */ -bool circle_eq(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_eq(CIRCLE * circle1, CIRCLE * circle2) { - return( FPeq(circle_ar(circle1), circle_ar(circle2)) ); -} /* circle_eq() */ + return (FPeq(circle_ar(circle1), circle_ar(circle2))); +} /* circle_eq() */ -bool circle_ne(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_ne(CIRCLE * circle1, CIRCLE * circle2) { - return( !circle_eq(circle1, circle2)); -} /* circle_ne() */ + return (!circle_eq(circle1, circle2)); +} /* circle_ne() */ -bool circle_lt(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_lt(CIRCLE * circle1, CIRCLE * circle2) { - return( FPlt(circle_ar(circle1), circle_ar(circle2)) ); -} /* circle_lt() */ + return (FPlt(circle_ar(circle1), circle_ar(circle2))); +} /* circle_lt() */ -bool circle_gt(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_gt(CIRCLE * circle1, CIRCLE * circle2) { - return( FPgt(circle_ar(circle1), circle_ar(circle2)) ); -} /* circle_gt() */ + return (FPgt(circle_ar(circle1), circle_ar(circle2))); +} /* circle_gt() */ -bool circle_le(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_le(CIRCLE * circle1, CIRCLE * circle2) { - return( FPle(circle_ar(circle1), circle_ar(circle2)) ); -} /* circle_le() */ + return (FPle(circle_ar(circle1), circle_ar(circle2))); +} /* circle_le() */ -bool circle_ge(CIRCLE *circle1, CIRCLE *circle2) +bool +circle_ge(CIRCLE * circle1, CIRCLE * circle2) { - return( FPge(circle_ar(circle1), circle_ar(circle2)) ); -} /* circle_ge() */ + return (FPge(circle_ar(circle1), circle_ar(circle2))); +} /* circle_ge() */ /*---------------------------------------------------------- - * "Arithmetic" operators on circles. - * circle_foo returns foo as an object (pointer) that + * "Arithmetic" operators on circles. + * circle_foo returns foo as an object (pointer) that can be passed between languages. - * circle_xx is an internal routine which returns the - * actual value. + * circle_xx is an internal routine which returns the + * actual value. *---------------------------------------------------------*/ -static CIRCLE * -circle_copy(CIRCLE *circle) +static CIRCLE * +circle_copy(CIRCLE * circle) { - CIRCLE *result; + CIRCLE *result; - if (!PointerIsValid(circle)) - return NULL; + if (!PointerIsValid(circle)) + return NULL; - result = PALLOCTYPE(CIRCLE); + result = PALLOCTYPE(CIRCLE); - memmove((char *) result, (char *) circle, sizeof(CIRCLE)); - return(result); -} /* circle_copy() */ + memmove((char *) result, (char *) circle, sizeof(CIRCLE)); + return (result); +} /* circle_copy() */ /* circle_add_pt() * Translation operator. */ -CIRCLE * -circle_add_pt(CIRCLE *circle, Point *point) +CIRCLE * +circle_add_pt(CIRCLE * circle, Point * point) { - CIRCLE *result; + CIRCLE *result; - if (!PointerIsValid(circle) || !PointerIsValid(point)) - return(NULL); + if (!PointerIsValid(circle) || !PointerIsValid(point)) + return (NULL); - result = circle_copy(circle); + result = circle_copy(circle); - result->center.x += point->x; - result->center.y += point->y; + result->center.x += point->x; + result->center.y += point->y; - return(result); -} /* circle_add_pt() */ + return (result); +} /* circle_add_pt() */ -CIRCLE * -circle_sub_pt(CIRCLE *circle, Point *point) +CIRCLE * +circle_sub_pt(CIRCLE * circle, Point * point) { - CIRCLE *result; + CIRCLE *result; - if (!PointerIsValid(circle) || !PointerIsValid(point)) - return(NULL); + if (!PointerIsValid(circle) || !PointerIsValid(point)) + return (NULL); - result = circle_copy(circle); + result = circle_copy(circle); - result->center.x -= point->x; - result->center.y -= point->y; + result->center.x -= point->x; + result->center.y -= point->y; - return(result); -} /* circle_sub_pt() */ + return (result); +} /* circle_sub_pt() */ /* circle_mul_pt() * Rotation and scaling operators. */ -CIRCLE * -circle_mul_pt(CIRCLE *circle, Point *point) +CIRCLE * +circle_mul_pt(CIRCLE * circle, Point * point) { - CIRCLE *result; - Point *p; + CIRCLE *result; + Point *p; - if (!PointerIsValid(circle) || !PointerIsValid(point)) - return(NULL); + if (!PointerIsValid(circle) || !PointerIsValid(point)) + return (NULL); - result = circle_copy(circle); + result = circle_copy(circle); - p = point_mul( &circle->center, point); - result->center.x = p->x; - result->center.y = p->y; - PFREE(p); - result->radius *= HYPOT( point->x, point->y); + p = point_mul(&circle->center, point); + result->center.x = p->x; + result->center.y = p->y; + PFREE(p); + result->radius *= HYPOT(point->x, point->y); - return(result); -} /* circle_mul_pt() */ + return (result); +} /* circle_mul_pt() */ -CIRCLE * -circle_div_pt(CIRCLE *circle, Point *point) +CIRCLE * +circle_div_pt(CIRCLE * circle, Point * point) { - CIRCLE *result; - Point *p; + CIRCLE *result; + Point *p; - if (!PointerIsValid(circle) || !PointerIsValid(point)) - return(NULL); + if (!PointerIsValid(circle) || !PointerIsValid(point)) + return (NULL); - result = circle_copy(circle); + result = circle_copy(circle); - p = point_div( &circle->center, point); - result->center.x = p->x; - result->center.y = p->y; - PFREE(p); - result->radius /= HYPOT( point->x, point->y); + p = point_div(&circle->center, point); + result->center.x = p->x; + result->center.y = p->y; + PFREE(p); + result->radius /= HYPOT(point->x, point->y); - return(result); -} /* circle_div_pt() */ + return (result); +} /* circle_div_pt() */ -/* circle_area - returns the area of the circle. +/* circle_area - returns the area of the circle. */ -double *circle_area(CIRCLE *circle) +double * +circle_area(CIRCLE * circle) { - double *result; + double *result; - result = PALLOCTYPE(double); - *result = circle_ar(circle); + result = PALLOCTYPE(double); + *result = circle_ar(circle); - return(result); + return (result); } -/* circle_diameter - returns the diameter of the circle. +/* circle_diameter - returns the diameter of the circle. */ -double *circle_diameter(CIRCLE *circle) +double * +circle_diameter(CIRCLE * circle) { - double *result; + double *result; - result = PALLOCTYPE(double); - *result = (2*circle->radius); + result = PALLOCTYPE(double); + *result = (2 * circle->radius); - return(result); + return (result); } -/* circle_radius - returns the radius of the circle. +/* circle_radius - returns the radius of the circle. */ -double *circle_radius(CIRCLE *circle) +double * +circle_radius(CIRCLE * circle) { - double *result; + double *result; - result = PALLOCTYPE(double); - *result = circle->radius; + result = PALLOCTYPE(double); + *result = circle->radius; - return(result); + return (result); } -/* circle_distance - returns the distance between - * two circles. +/* circle_distance - returns the distance between + * two circles. */ -double *circle_distance(CIRCLE *circle1, CIRCLE *circle2) +double * +circle_distance(CIRCLE * circle1, CIRCLE * circle2) { - double *result; + double *result; - result = PALLOCTYPE(double); - *result = (point_dt(&circle1->center,&circle2->center) - - (circle1->radius + circle2->radius)); - if (*result < 0) *result = 0; + result = PALLOCTYPE(double); + *result = (point_dt(&circle1->center, &circle2->center) + - (circle1->radius + circle2->radius)); + if (*result < 0) + *result = 0; - return(result); -} /* circle_distance() */ + return (result); +} /* circle_distance() */ bool -circle_contain_pt(CIRCLE *circle, Point *point) +circle_contain_pt(CIRCLE * circle, Point * point) { - bool within; - double *d; + bool within; + double *d; - if (!PointerIsValid(circle) || !PointerIsValid(point)) - return(FALSE); + if (!PointerIsValid(circle) || !PointerIsValid(point)) + return (FALSE); - d = point_distance(&(circle->center), point); - within = (*d <= circle->radius); - PFREE(d); + d = point_distance(&(circle->center), point); + within = (*d <= circle->radius); + PFREE(d); - return(within); -} /* circle_contain_pt() */ + return (within); +} /* circle_contain_pt() */ bool -pt_contained_circle(Point *point, CIRCLE *circle) +pt_contained_circle(Point * point, CIRCLE * circle) { - return(circle_contain_pt(circle,point)); -} /* circle_contain_pt() */ + return (circle_contain_pt(circle, point)); +} /* circle_contain_pt() */ -/* dist_pc - returns the distance between - * a point and a circle. +/* dist_pc - returns the distance between + * a point and a circle. */ -double *dist_pc(Point *point, CIRCLE *circle) +double * +dist_pc(Point * point, CIRCLE * circle) { - double *result; + double *result; - result = PALLOCTYPE(double); + result = PALLOCTYPE(double); - *result = (point_dt(point,&circle->center) - circle->radius); - if (*result < 0) *result = 0; + *result = (point_dt(point, &circle->center) - circle->radius); + if (*result < 0) + *result = 0; - return(result); -} /* dist_pc() */ + return (result); +} /* dist_pc() */ -/* circle_center - returns the center point of the circle. +/* circle_center - returns the center point of the circle. */ -Point *circle_center(CIRCLE *circle) +Point * +circle_center(CIRCLE * circle) { - Point *result; + Point *result; - result = PALLOCTYPE(Point); - result->x = circle->center.x; - result->y = circle->center.y; + result = PALLOCTYPE(Point); + result->x = circle->center.x; + result->y = circle->center.y; - return(result); + return (result); } -/* circle_ar - returns the area of the circle. +/* circle_ar - returns the area of the circle. */ -static double circle_ar(CIRCLE *circle) +static double +circle_ar(CIRCLE * circle) { - return(PI*(circle->radius*circle->radius)); + return (PI * (circle->radius * circle->radius)); } -/* circle_dt - returns the distance between the - * center points of two circlees. +/* circle_dt - returns the distance between the + * center points of two circlees. */ #ifdef NOT_USED -double circle_dt(CIRCLE *circle1, CIRCLE *circle2) +double +circle_dt(CIRCLE * circle1, CIRCLE * circle2) { - double result; + double result; - result = point_dt(&circle1->center,&circle2->center); + result = point_dt(&circle1->center, &circle2->center); - return(result); + return (result); } + #endif /*---------------------------------------------------------- - * Conversion operators. + * Conversion operators. *---------------------------------------------------------*/ -CIRCLE *circle(Point *center, float8 *radius) +CIRCLE * +circle(Point * center, float8 * radius) { - CIRCLE *result; + CIRCLE *result; - if (! (PointerIsValid(center) && PointerIsValid(radius))) - return(NULL); + if (!(PointerIsValid(center) && PointerIsValid(radius))) + return (NULL); - result = PALLOCTYPE(CIRCLE); + result = PALLOCTYPE(CIRCLE); - result->center.x = center->x; - result->center.y = center->y; - result->radius = *radius; + result->center.x = center->x; + result->center.y = center->y; + result->radius = *radius; - return(result); + return (result); } -BOX * -circle_box(CIRCLE *circle) +BOX * +circle_box(CIRCLE * circle) { - BOX *box; - double delta; + BOX *box; + double delta; - if (!PointerIsValid(circle)) - return(NULL); + if (!PointerIsValid(circle)) + return (NULL); - box = PALLOCTYPE(BOX); + box = PALLOCTYPE(BOX); - delta = circle->radius / sqrt(2.0e0); + delta = circle->radius / sqrt(2.0e0); - box->high.x = circle->center.x + delta; - box->low.x = circle->center.x - delta; - box->high.y = circle->center.y + delta; - box->low.y = circle->center.y - delta; + box->high.x = circle->center.x + delta; + box->low.x = circle->center.x - delta; + box->high.y = circle->center.y + delta; + box->low.y = circle->center.y - delta; - return(box); -} /* circle_box() */ + return (box); +} /* circle_box() */ /* box_circle() * Convert a box to a circle. */ -CIRCLE * -box_circle(BOX *box) +CIRCLE * +box_circle(BOX * box) { - CIRCLE *circle; + CIRCLE *circle; - if (!PointerIsValid(box)) - return(NULL); + if (!PointerIsValid(box)) + return (NULL); - circle = PALLOCTYPE(CIRCLE); + circle = PALLOCTYPE(CIRCLE); - circle->center.x = (box->high.x + box->low.x) / 2; - circle->center.y = (box->high.y + box->low.y) / 2; + circle->center.x = (box->high.x + box->low.x) / 2; + circle->center.y = (box->high.y + box->low.y) / 2; - circle->radius = point_dt(&circle->center, &box->high); + circle->radius = point_dt(&circle->center, &box->high); - return(circle); -} /* box_circle() */ + return (circle); +} /* box_circle() */ -POLYGON *circle_poly(int npts, CIRCLE *circle) +POLYGON * +circle_poly(int npts, CIRCLE * circle) { - POLYGON *poly; - int size; - int i; - double angle; + POLYGON *poly; + int size; + int i; + double angle; - if (!PointerIsValid(circle)) - return(NULL); + if (!PointerIsValid(circle)) + return (NULL); - if (FPzero(circle->radius) || (npts < 2)) - elog (WARN, "Unable to convert circle to polygon", NULL); + if (FPzero(circle->radius) || (npts < 2)) + elog(WARN, "Unable to convert circle to polygon", NULL); - size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * npts); - poly = PALLOC(size); + size = offsetof(POLYGON, p[0]) + (sizeof(poly->p[0]) * npts); + poly = PALLOC(size); - memset((char *) poly, 0, size); /* zero any holes */ - poly->size = size; - poly->npts = npts; + memset((char *) poly, 0, size); /* zero any holes */ + poly->size = size; + poly->npts = npts; - for (i=0;i<npts;i++) { - angle = i*(2*PI/npts); - poly->p[i].x = circle->center.x - (circle->radius*cos(angle)); - poly->p[i].y = circle->center.y + (circle->radius*sin(angle)); - } + for (i = 0; i < npts; i++) + { + angle = i * (2 * PI / npts); + poly->p[i].x = circle->center.x - (circle->radius * cos(angle)); + poly->p[i].y = circle->center.y + (circle->radius * sin(angle)); + } - make_bound_box(poly); + make_bound_box(poly); - return(poly); + return (poly); } -/* poly_circle - convert polygon to circle +/* poly_circle - convert polygon to circle * * XXX This algorithm should use weighted means of line segments - * rather than straight average values of points - tgl 97/01/21. + * rather than straight average values of points - tgl 97/01/21. */ -CIRCLE *poly_circle(POLYGON *poly) +CIRCLE * +poly_circle(POLYGON * poly) { - CIRCLE *circle; - int i; + CIRCLE *circle; + int i; - if (!PointerIsValid(poly)) - return(NULL); + if (!PointerIsValid(poly)) + return (NULL); - if (poly->npts < 2) - elog (WARN, "Unable to convert polygon to circle", NULL); + if (poly->npts < 2) + elog(WARN, "Unable to convert polygon to circle", NULL); - circle = PALLOCTYPE(CIRCLE); + circle = PALLOCTYPE(CIRCLE); - circle->center.x = 0; - circle->center.y = 0; - circle->radius = 0; + circle->center.x = 0; + circle->center.y = 0; + circle->radius = 0; - for (i=0;i<poly->npts;i++) { - circle->center.x += poly->p[i].x; - circle->center.y += poly->p[i].y; - } - circle->center.x /= poly->npts; - circle->center.y /= poly->npts; + for (i = 0; i < poly->npts; i++) + { + circle->center.x += poly->p[i].x; + circle->center.y += poly->p[i].y; + } + circle->center.x /= poly->npts; + circle->center.y /= poly->npts; - for (i=0;i<poly->npts;i++) { - circle->radius += point_dt( &poly->p[i], &circle->center); - } - circle->radius /= poly->npts; + for (i = 0; i < poly->npts; i++) + { + circle->radius += point_dt(&poly->p[i], &circle->center); + } + circle->radius /= poly->npts; - if (FPzero(circle->radius)) - elog (WARN, "Unable to convert polygon to circle", NULL); + if (FPzero(circle->radius)) + elog(WARN, "Unable to convert polygon to circle", NULL); - return(circle); -} /* poly_circle() */ + return (circle); +} /* poly_circle() */ /*********************************************************************** ** - ** Private routines for multiple types. + ** Private routines for multiple types. ** ***********************************************************************/ #define HIT_IT INT_MAX static int -point_inside( Point *p, int npts, Point plist[]) +point_inside(Point * p, int npts, Point plist[]) { - double x0, y0; - double px, py; + double x0, + y0; + double px, + py; - int i; - double x, y; - int cross, crossnum; + int i; + double x, + y; + int cross, + crossnum; /* * We calculate crossnum, which is twice the crossing number of a @@ -3704,36 +4084,41 @@ point_inside( Point *p, int npts, Point plist[]) * positive X-axis. */ - crossnum = 0; - i = 0; - if (npts <= 0) return 0; + crossnum = 0; + i = 0; + if (npts <= 0) + return 0; + + x0 = plist[0].x - p->x; + y0 = plist[0].y - p->y; - x0 = plist[0].x - p->x; - y0 = plist[0].y - p->y; + px = x0; + py = y0; + for (i = 1; i < npts; i++) + { + x = plist[i].x - p->x; + y = plist[i].y - p->y; - px = x0; - py = y0; - for (i = 1; i < npts; i++) { - x = plist[i].x - p->x; - y = plist[i].y - p->y; + if ((cross = lseg_crossing(x, y, px, py)) == HIT_IT) + { + return 2; + } + crossnum += cross; - if ( (cross = lseg_crossing( x, y, px, py)) == HIT_IT ) { - return 2; + px = x; + py = y; + } + if ((cross = lseg_crossing(x0, y0, px, py)) == HIT_IT) + { + return 2; } crossnum += cross; - - px = x; - py = y; - } - if ( (cross = lseg_crossing( x0, y0, px, py)) == HIT_IT ) { - return 2; - } - crossnum += cross; - if ( crossnum != 0 ) { - return 1; - } - return 0; -} /* point_inside() */ + if (crossnum != 0) + { + return 1; + } + return 0; +} /* point_inside() */ /* lseg_crossing() @@ -3745,91 +4130,115 @@ point_inside( Point *p, int npts, Point plist[]) */ static int -lseg_crossing( double x, double y, double px, double py) +lseg_crossing(double x, double y, double px, double py) { - double z; - int sgn; + double z; + int sgn; - /* If (px,py) = (0,0) and not first call we have already sent HIT_IT */ + /* If (px,py) = (0,0) and not first call we have already sent HIT_IT */ - if (FPzero( y)) { - if (FPzero( x)) { - return(HIT_IT); + if (FPzero(y)) + { + if (FPzero(x)) + { + return (HIT_IT); - } else if (FPgt( x, 0)) { - if (FPzero( py)) return(FPgt( px, 0)? 0 : HIT_IT); - return(FPlt( py, 0)? 1 : -1); + } + else if (FPgt(x, 0)) + { + if (FPzero(py)) + return (FPgt(px, 0) ? 0 : HIT_IT); + return (FPlt(py, 0) ? 1 : -1); - } else { /* x < 0 */ - if (FPzero( py)) return(FPlt( px, 0)? 0 : HIT_IT); - return(0); + } + else + { /* x < 0 */ + if (FPzero(py)) + return (FPlt(px, 0) ? 0 : HIT_IT); + return (0); + } } - } - /* Now we know y != 0; set sgn to sign of y */ - sgn = (FPgt( y, 0)? 1 : -1); - if (FPzero( py)) return(FPlt( px, 0)? 0 : sgn); + /* Now we know y != 0; set sgn to sign of y */ + sgn = (FPgt(y, 0) ? 1 : -1); + if (FPzero(py)) + return (FPlt(px, 0) ? 0 : sgn); - if (FPgt( (sgn * py), 0)) { /* y and py have same sign */ - return(0); + if (FPgt((sgn * py), 0)) + { /* y and py have same sign */ + return (0); - } else { /* y and py have opposite signs */ - if (FPge( x, 0) && FPgt( px, 0)) return(2 * sgn); - if (FPlt( x, 0) && FPle( px, 0)) return(0); - - z = (x-px) * y - (y-py) * x; - if (FPzero( z)) return(HIT_IT); - return( FPgt( (sgn*z), 0)? 0 : 2 * sgn); - } -} /* lseg_crossing() */ + } + else + { /* y and py have opposite signs */ + if (FPge(x, 0) && FPgt(px, 0)) + return (2 * sgn); + if (FPlt(x, 0) && FPle(px, 0)) + return (0); + + z = (x - px) * y - (y - py) * x; + if (FPzero(z)) + return (HIT_IT); + return (FPgt((sgn * z), 0) ? 0 : 2 * sgn); + } +} /* lseg_crossing() */ -static bool +static bool plist_same(int npts, Point p1[], Point p2[]) { - int i, ii, j; - - /* find match for first point */ - for (i = 0; i < npts; i++) { - if ((FPeq( p2[i].x, p1[0].x)) - && (FPeq( p2[i].y, p1[0].y))) { - - /* match found? then look forward through remaining points */ - for (ii = 1, j = i+1; ii < npts; ii++, j++) { - if (j >= npts) j = 0; - if ((!FPeq( p2[j].x, p1[ii].x)) - || (!FPeq( p2[j].y, p1[ii].y))) { + int i, + ii, + j; + + /* find match for first point */ + for (i = 0; i < npts; i++) + { + if ((FPeq(p2[i].x, p1[0].x)) + && (FPeq(p2[i].y, p1[0].y))) + { + + /* match found? then look forward through remaining points */ + for (ii = 1, j = i + 1; ii < npts; ii++, j++) + { + if (j >= npts) + j = 0; + if ((!FPeq(p2[j].x, p1[ii].x)) + || (!FPeq(p2[j].y, p1[ii].y))) + { #ifdef GEODEBUG -printf( "plist_same- %d failed forward match with %d\n", j, ii); + printf("plist_same- %d failed forward match with %d\n", j, ii); #endif - break; - } - } + break; + } + } #ifdef GEODEBUG -printf( "plist_same- ii = %d/%d after forward match\n", ii, npts); + printf("plist_same- ii = %d/%d after forward match\n", ii, npts); #endif - if (ii == npts) - return(TRUE); - - /* match not found forwards? then look backwards */ - for (ii = 1, j = i-1; ii < npts; ii++, j--) { - if (j < 0) j = (npts-1); - if ((!FPeq( p2[j].x, p1[ii].x)) - || (!FPeq( p2[j].y, p1[ii].y))) { + if (ii == npts) + return (TRUE); + + /* match not found forwards? then look backwards */ + for (ii = 1, j = i - 1; ii < npts; ii++, j--) + { + if (j < 0) + j = (npts - 1); + if ((!FPeq(p2[j].x, p1[ii].x)) + || (!FPeq(p2[j].y, p1[ii].y))) + { #ifdef GEODEBUG -printf( "plist_same- %d failed reverse match with %d\n", j, ii); + printf("plist_same- %d failed reverse match with %d\n", j, ii); #endif - break; - } - } + break; + } + } #ifdef GEODEBUG -printf( "plist_same- ii = %d/%d after reverse match\n", ii, npts); + printf("plist_same- ii = %d/%d after reverse match\n", ii, npts); #endif - if (ii == npts) - return(TRUE); + if (ii == npts) + return (TRUE); + } } - } - - return(FALSE); -} /* plist_same() */ + return (FALSE); +} /* plist_same() */ diff --git a/src/backend/utils/adt/geo_selfuncs.c b/src/backend/utils/adt/geo_selfuncs.c index f0f7bc48d5f..240639d6eda 100644 --- a/src/backend/utils/adt/geo_selfuncs.c +++ b/src/backend/utils/adt/geo_selfuncs.c @@ -1,16 +1,16 @@ /*------------------------------------------------------------------------- * * geo-selfuncs.c-- - * Selectivity routines registered in the operator catalog in the - * "oprrest" and "oprjoin" attributes. + * Selectivity routines registered in the operator catalog in the + * "oprrest" and "oprjoin" attributes. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_selfuncs.c,v 1.3 1997/08/19 21:34:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_selfuncs.c,v 1.4 1997/09/07 04:50:20 momjian Exp $ * - * XXX These are totally bogus. + * XXX These are totally bogus. * *------------------------------------------------------------------------- */ @@ -22,112 +22,116 @@ #include "utils/builtins.h" float64 -areasel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) +areasel(Oid opid, + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 4.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 4.0; + return (result); } float64 areajoinsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 4.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 4.0; + return (result); } /* - * Selectivity functions for rtrees. These are bogus -- unless we know - * the actual key distribution in the index, we can't make a good prediction - * of the selectivity of these operators. + * Selectivity functions for rtrees. These are bogus -- unless we know + * the actual key distribution in the index, we can't make a good prediction + * of the selectivity of these operators. * - * In general, rtrees need to search multiple subtrees in order to guarantee - * that all occurrences of the same key have been found. Because of this, - * the heuristic selectivity functions we return are higher than they would - * otherwise be. + * In general, rtrees need to search multiple subtrees in order to guarantee + * that all occurrences of the same key have been found. Because of this, + * the heuristic selectivity functions we return are higher than they would + * otherwise be. */ /* - * left_sel -- How likely is a box to be strictly left of (right of, above, - * below) a given box? + * left_sel -- How likely is a box to be strictly left of (right of, above, + * below) a given box? */ #ifdef NOT_USED float64 leftsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 6.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 6.0; + return (result); } + #endif #ifdef NOT_USED float64 leftjoinsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 6.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 6.0; + return (result); } + #endif /* - * contsel -- How likely is a box to contain (be contained by) a given box? + * contsel -- How likely is a box to contain (be contained by) a given box? */ #ifdef NOT_USED float64 contsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 10.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 10.0; + return (result); } + #endif #ifdef NOT_USED float64 contjoinsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 10.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 10.0; + return (result); } + #endif diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 57f5b32d132..c7ea5f71fcc 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -1,29 +1,29 @@ /*------------------------------------------------------------------------- * * int.c-- - * Functions for the built-in integer types. + * Functions for the built-in integer types. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.4 1997/03/14 23:20:26 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.5 1997/09/07 04:50:21 momjian Exp $ * *------------------------------------------------------------------------- */ /* * OLD COMMENTS - * I/O routines: - * int2in, int2out, int28in, int28out, int4in, int4out - * Conversion routines: - * itoi - * Boolean operators: - * inteq, intne, intlt, intle, intgt, intge - * Arithmetic operators: - * intpl, intmi, int4mul, intdiv + * I/O routines: + * int2in, int2out, int28in, int28out, int4in, int4out + * Conversion routines: + * itoi + * Boolean operators: + * inteq, intne, intlt, intle, intgt, intge + * Arithmetic operators: + * intpl, intmi, int4mul, intdiv * - * Arithmetic operators: - * intmod, int4fac + * Arithmetic operators: + * intmod, int4fac * * XXX makes massive and possibly unwarranted type promotion assumptions. * fix me when we figure out what we want to do about ANSIfication... @@ -32,311 +32,482 @@ #include "postgres.h" #include "fmgr.h" -#include "utils/builtins.h" /* where the declarations go */ +#include "utils/builtins.h" /* where the declarations go */ -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* - * int2in - converts "num" to short + * int2in - converts "num" to short */ -int32 int2in(char *num) +int32 +int2in(char *num) { - return((int32) pg_atoi(num, sizeof(int16), '\0')); + return ((int32) pg_atoi(num, sizeof(int16), '\0')); } /* - * int2out - converts short to "num" + * int2out - converts short to "num" */ -char *int2out(int16 sh) +char * +int2out(int16 sh) { - char *result; - - result = (char *)palloc(7); /* assumes sign, 5 digits, '\0' */ - itoa((int) sh, result); - return(result); + char *result; + + result = (char *) palloc(7);/* assumes sign, 5 digits, '\0' */ + itoa((int) sh, result); + return (result); } /* - * int28in - converts "num num ..." to internal form + * int28in - converts "num num ..." to internal form * - * Note: - * Fills any nonexistent digits with NULLs. + * Note: + * Fills any nonexistent digits with NULLs. */ -int16 *int28in(char *shs) -{ - register int16 (*result)[]; - int nums; - - if (shs == NULL) - return(NULL); - result = (int16 (*)[]) palloc(sizeof(int16 [8])); - if ((nums = sscanf(shs, "%hd%hd%hd%hd%hd%hd%hd%hd", - *result, - *result + 1, - *result + 2, - *result + 3, - *result + 4, - *result + 5, - *result + 6, - *result + 7)) != 8) { - do - (*result)[nums++] = 0; - while (nums < 8); - } - return((int16 *) result); +int16 * +int28in(char *shs) +{ + register int16(*result)[]; + int nums; + + if (shs == NULL) + return (NULL); + result = (int16(*)[]) palloc(sizeof(int16[8])); + if ((nums = sscanf(shs, "%hd%hd%hd%hd%hd%hd%hd%hd", + *result, + *result + 1, + *result + 2, + *result + 3, + *result + 4, + *result + 5, + *result + 6, + *result + 7)) != 8) + { + do + (*result)[nums++] = 0; + while (nums < 8); + } + return ((int16 *) result); } /* - * int28out - converts internal form to "num num ..." + * int28out - converts internal form to "num num ..." */ -char *int28out(int16 (*shs)[]) -{ - register int num; - register int16 *sp; - register char *rp; - char *result; - - if (shs == NULL) { - result = (char *)palloc(2); - result[0] = '-'; - result[1] = '\0'; - return(result); - } - rp = result = (char *)palloc(8 * 7); /* assumes sign, 5 digits, ' ' */ - sp = *shs; - for (num = 8; num != 0; num--) { - itoa(*sp++, rp); - while (*++rp != '\0') - ; - *rp++ = ' '; - } - *--rp = '\0'; - return(result); +char * +int28out(int16(*shs)[]) +{ + register int num; + register int16 *sp; + register char *rp; + char *result; + + if (shs == NULL) + { + result = (char *) palloc(2); + result[0] = '-'; + result[1] = '\0'; + return (result); + } + rp = result = (char *) palloc(8 * 7); /* assumes sign, 5 digits, + * ' ' */ + sp = *shs; + for (num = 8; num != 0; num--) + { + itoa(*sp++, rp); + while (*++rp != '\0') + ; + *rp++ = ' '; + } + *--rp = '\0'; + return (result); } /* - * int28in - converts "num num ..." to internal form + * int28in - converts "num num ..." to internal form * - * Note: - * Fills any nonexistent digits with NULLs. + * Note: + * Fills any nonexistent digits with NULLs. */ -int32 *int44in(char *input_string) -{ - int32 *foo = (int32 *)palloc(4*sizeof(int32)); - register int i = 0; - - i = sscanf(input_string, - "%d, %d, %d, %d", - &foo[0], - &foo[1], - &foo[2], - &foo[3]); - while (i < 4) - foo[i++] = 0; - - return(foo); +int32 * +int44in(char *input_string) +{ + int32 *foo = (int32 *) palloc(4 * sizeof(int32)); + register int i = 0; + + i = sscanf(input_string, + "%d, %d, %d, %d", + &foo[0], + &foo[1], + &foo[2], + &foo[3]); + while (i < 4) + foo[i++] = 0; + + return (foo); } /* - * int28out - converts internal form to "num num ..." + * int28out - converts internal form to "num num ..." */ -char *int44out(int32 an_array[]) -{ - int temp = 4; - char *output_string = NULL; - int i; - - if ( temp > 0 ) { - char *walk; - output_string = (char *)palloc(16*temp); /* assume 15 digits + sign */ - walk = output_string; - for ( i = 0 ; i < temp ; i++ ) { - itoa(an_array[i],walk); - while (*++walk != '\0') - ; - *walk++ = ' '; +char * +int44out(int32 an_array[]) +{ + int temp = 4; + char *output_string = NULL; + int i; + + if (temp > 0) + { + char *walk; + + output_string = (char *) palloc(16 * temp); /* assume 15 digits + + * sign */ + walk = output_string; + for (i = 0; i < temp; i++) + { + itoa(an_array[i], walk); + while (*++walk != '\0') + ; + *walk++ = ' '; + } + *--walk = '\0'; } - *--walk = '\0'; - } - return(output_string); + return (output_string); } -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ /* - * int4in - converts "num" to int4 + * int4in - converts "num" to int4 */ -int32 int4in(char *num) +int32 +int4in(char *num) { - return(pg_atoi(num, sizeof(int32), '\0')); + return (pg_atoi(num, sizeof(int32), '\0')); } /* - * int4out - converts int4 to "num" + * int4out - converts int4 to "num" */ -char *int4out(int32 l) +char * +int4out(int32 l) { - char *result; - - result = (char *)palloc(12); /* assumes sign, 10 digits, '\0' */ - ltoa(l, result); - return(result); + char *result; + + result = (char *) palloc(12); /* assumes sign, 10 digits, '\0' */ + ltoa(l, result); + return (result); } /* - * =================== - * CONVERSION ROUTINES - * =================== + * =================== + * CONVERSION ROUTINES + * =================== */ -int32 i2toi4(int16 arg1) +int32 +i2toi4(int16 arg1) { - return((int32) arg1); + return ((int32) arg1); } -int16 i4toi2(int32 arg1) +int16 +i4toi2(int32 arg1) { - if (arg1< -0x8000) - elog(NOTICE, "i4toi2: \"%d\" causes int2 underflow", arg1); - if (arg1 > 0x7FFF) - elog(NOTICE, "i4toi2: \"%d\" causes int2 overflow", arg1); - - return((int16) arg1); + if (arg1 < -0x8000) + elog(NOTICE, "i4toi2: \"%d\" causes int2 underflow", arg1); + if (arg1 > 0x7FFF) + elog(NOTICE, "i4toi2: \"%d\" causes int2 overflow", arg1); + + return ((int16) arg1); } /* - * ========================= - * BOOLEAN OPERATOR ROUTINES - * ========================= + * ========================= + * BOOLEAN OPERATOR ROUTINES + * ========================= */ /* - * inteq - returns 1 iff arg1 == arg2 - * intne - returns 1 iff arg1 != arg2 - * intlt - returns 1 iff arg1 < arg2 - * intle - returns 1 iff arg1 <= arg2 - * intgt - returns 1 iff arg1 > arg2 - * intge - returns 1 iff arg1 >= arg2 + * inteq - returns 1 iff arg1 == arg2 + * intne - returns 1 iff arg1 != arg2 + * intlt - returns 1 iff arg1 < arg2 + * intle - returns 1 iff arg1 <= arg2 + * intgt - returns 1 iff arg1 > arg2 + * intge - returns 1 iff arg1 >= arg2 */ -bool int4eq(int32 arg1, int32 arg2) { return(arg1 == arg2); } -bool int4ne(int32 arg1, int32 arg2) { return(arg1 != arg2); } -bool int4lt(int32 arg1, int32 arg2) { return(arg1 < arg2); } -bool int4le(int32 arg1, int32 arg2) { return(arg1 <= arg2); } -bool int4gt(int32 arg1, int32 arg2) { return(arg1 > arg2); } -bool int4ge(int32 arg1, int32 arg2) { return(arg1 >= arg2); } - -bool int2eq(int16 arg1, int16 arg2) { return(arg1 == arg2); } -bool int2ne(int16 arg1, int16 arg2) { return(arg1 != arg2); } -bool int2lt(int16 arg1, int16 arg2) { return(arg1 < arg2); } -bool int2le(int16 arg1, int16 arg2) { return(arg1 <= arg2); } -bool int2gt(int16 arg1, int16 arg2) { return(arg1 > arg2); } -bool int2ge(int16 arg1, int16 arg2) { return(arg1 >= arg2); } - -bool int24eq(int32 arg1, int32 arg2) { return(arg1 == arg2); } -bool int24ne(int32 arg1, int32 arg2) { return(arg1 != arg2); } -bool int24lt(int32 arg1, int32 arg2) { return(arg1 < arg2); } -bool int24le(int32 arg1, int32 arg2) { return(arg1 <= arg2); } -bool int24gt(int32 arg1, int32 arg2) { return(arg1 > arg2); } -bool int24ge(int32 arg1, int32 arg2) { return(arg1 >= arg2); } - -bool int42eq(int32 arg1, int32 arg2) { return(arg1 == arg2); } -bool int42ne(int32 arg1, int32 arg2) { return(arg1 != arg2); } -bool int42lt(int32 arg1, int32 arg2) { return(arg1 < arg2); } -bool int42le(int32 arg1, int32 arg2) { return(arg1 <= arg2); } -bool int42gt(int32 arg1, int32 arg2) { return(arg1 > arg2); } -bool int42ge(int32 arg1, int32 arg2) { return(arg1 >= arg2); } - - -bool keyfirsteq(int16 *arg1, int16 arg2) { return(*arg1 == arg2); } +bool int4eq(int32 arg1, int32 arg2) +{ + return (arg1 == arg2); +} +bool int4ne(int32 arg1, int32 arg2) +{ + return (arg1 != arg2); +} +bool int4lt(int32 arg1, int32 arg2) +{ + return (arg1 < arg2); +} +bool int4le(int32 arg1, int32 arg2) +{ + return (arg1 <= arg2); +} +bool int4gt(int32 arg1, int32 arg2) +{ + return (arg1 > arg2); +} +bool int4ge(int32 arg1, int32 arg2) +{ + return (arg1 >= arg2); +} + +bool int2eq(int16 arg1, int16 arg2) +{ + return (arg1 == arg2); +} +bool int2ne(int16 arg1, int16 arg2) +{ + return (arg1 != arg2); +} +bool int2lt(int16 arg1, int16 arg2) +{ + return (arg1 < arg2); +} +bool int2le(int16 arg1, int16 arg2) +{ + return (arg1 <= arg2); +} +bool int2gt(int16 arg1, int16 arg2) +{ + return (arg1 > arg2); +} +bool int2ge(int16 arg1, int16 arg2) +{ + return (arg1 >= arg2); +} + +bool int24eq(int32 arg1, int32 arg2) +{ + return (arg1 == arg2); +} +bool int24ne(int32 arg1, int32 arg2) +{ + return (arg1 != arg2); +} +bool int24lt(int32 arg1, int32 arg2) +{ + return (arg1 < arg2); +} +bool int24le(int32 arg1, int32 arg2) +{ + return (arg1 <= arg2); +} +bool int24gt(int32 arg1, int32 arg2) +{ + return (arg1 > arg2); +} +bool int24ge(int32 arg1, int32 arg2) +{ + return (arg1 >= arg2); +} + +bool int42eq(int32 arg1, int32 arg2) +{ + return (arg1 == arg2); +} +bool int42ne(int32 arg1, int32 arg2) +{ + return (arg1 != arg2); +} +bool int42lt(int32 arg1, int32 arg2) +{ + return (arg1 < arg2); +} +bool int42le(int32 arg1, int32 arg2) +{ + return (arg1 <= arg2); +} +bool int42gt(int32 arg1, int32 arg2) +{ + return (arg1 > arg2); +} +bool int42ge(int32 arg1, int32 arg2) +{ + return (arg1 >= arg2); +} + + +bool keyfirsteq(int16 * arg1, int16 arg2) +{ + return (*arg1 == arg2); +} /* - * int[24]pl - returns arg1 + arg2 - * int[24]mi - returns arg1 - arg2 - * int[24]mul - returns arg1 * arg2 - * int[24]div - returns arg1 / arg2 + * int[24]pl - returns arg1 + arg2 + * int[24]mi - returns arg1 - arg2 + * int[24]mul - returns arg1 * arg2 + * int[24]div - returns arg1 / arg2 */ -int32 int4um(int32 arg) { return(-arg); } -int32 int4pl(int32 arg1, int32 arg2) { return(arg1 + arg2); } -int32 int4mi(int32 arg1, int32 arg2) { return(arg1 - arg2); } -int32 int4mul(int32 arg1, int32 arg2) { return(arg1 * arg2); } -int32 int4div(int32 arg1, int32 arg2) { return(arg1 / arg2); } -int32 int4inc(int32 arg) { return(arg + (int32)1); } - -int16 int2um(int16 arg) { return(-arg); } -int16 int2pl(int16 arg1, int16 arg2) { return(arg1 + arg2); } -int16 int2mi(int16 arg1, int16 arg2) { return(arg1 - arg2); } -int16 int2mul(int16 arg1, int16 arg2) { return(arg1 * arg2); } -int16 int2div(int16 arg1, int16 arg2) { return(arg1 / arg2); } -int16 int2inc(int16 arg) { return(arg + (int16)1); } - -int32 int24pl(int32 arg1, int32 arg2) { return(arg1 + arg2); } -int32 int24mi(int32 arg1, int32 arg2) { return(arg1 - arg2); } -int32 int24mul(int32 arg1, int32 arg2) { return(arg1 * arg2); } -int32 int24div(int32 arg1, int32 arg2) { return(arg1 / arg2); } - -int32 int42pl(int32 arg1, int32 arg2) { return(arg1 + arg2); } -int32 int42mi(int32 arg1, int32 arg2) { return(arg1 - arg2); } -int32 int42mul(int32 arg1, int32 arg2) { return(arg1 * arg2); } -int32 int42div(int32 arg1, int32 arg2) { return(arg1 / arg2); } - +int32 int4um(int32 arg) +{ + return (-arg); +} +int32 int4pl(int32 arg1, int32 arg2) +{ + return (arg1 + arg2); +} +int32 int4mi(int32 arg1, int32 arg2) +{ + return (arg1 - arg2); +} +int32 int4mul(int32 arg1, int32 arg2) +{ + return (arg1 * arg2); +} +int32 int4div(int32 arg1, int32 arg2) +{ + return (arg1 / arg2); +} +int32 int4inc(int32 arg) +{ + return (arg + (int32) 1); +} + +int16 int2um(int16 arg) +{ + return (-arg); +} +int16 int2pl(int16 arg1, int16 arg2) +{ + return (arg1 + arg2); +} +int16 int2mi(int16 arg1, int16 arg2) +{ + return (arg1 - arg2); +} +int16 int2mul(int16 arg1, int16 arg2) +{ + return (arg1 * arg2); +} +int16 int2div(int16 arg1, int16 arg2) +{ + return (arg1 / arg2); +} +int16 int2inc(int16 arg) +{ + return (arg + (int16) 1); +} + +int32 int24pl(int32 arg1, int32 arg2) +{ + return (arg1 + arg2); +} +int32 int24mi(int32 arg1, int32 arg2) +{ + return (arg1 - arg2); +} +int32 int24mul(int32 arg1, int32 arg2) +{ + return (arg1 * arg2); +} +int32 int24div(int32 arg1, int32 arg2) +{ + return (arg1 / arg2); +} + +int32 int42pl(int32 arg1, int32 arg2) +{ + return (arg1 + arg2); +} +int32 int42mi(int32 arg1, int32 arg2) +{ + return (arg1 - arg2); +} +int32 int42mul(int32 arg1, int32 arg2) +{ + return (arg1 * arg2); +} +int32 int42div(int32 arg1, int32 arg2) +{ + return (arg1 / arg2); +} + /* - * int[24]mod - returns arg1 mod arg2 + * int[24]mod - returns arg1 mod arg2 */ -int32 int4mod(int32 arg1, int32 arg2) { return(arg1 % arg2); } -int32 int2mod(int16 arg1, int16 arg2) { return(arg1 % arg2); } -int32 int24mod(int32 arg1, int32 arg2) { return(arg1 % arg2); } -int32 int42mod(int32 arg1, int32 arg2) { return(arg1 % arg2); } - +int32 int4mod(int32 arg1, int32 arg2) +{ + return (arg1 % arg2); +} +int32 int2mod(int16 arg1, int16 arg2) +{ + return (arg1 % arg2); +} +int32 int24mod(int32 arg1, int32 arg2) +{ + return (arg1 % arg2); +} +int32 int42mod(int32 arg1, int32 arg2) +{ + return (arg1 % arg2); +} + /* - * int[24]fac - returns arg1! + * int[24]fac - returns arg1! */ -int32 int4fac(int32 arg1) +int32 +int4fac(int32 arg1) { - int32 result; - - if (arg1 < 1) - result = 0; - else - for (result = 1; arg1 > 0; --arg1) - result *= arg1; - return(result); + int32 result; + + if (arg1 < 1) + result = 0; + else + for (result = 1; arg1 > 0; --arg1) + result *= arg1; + return (result); } -int32 int2fac(int16 arg1) +int32 +int2fac(int16 arg1) { - int16 result; - - if (arg1 < 1) - result = 0; - else - for (result = 1; arg1 > 0; --arg1) - result *= arg1; - return(result); + int16 result; + + if (arg1 < 1) + result = 0; + else + for (result = 1; arg1 > 0; --arg1) + result *= arg1; + return (result); } -int16 int2larger(int16 arg1, int16 arg2) +int16 +int2larger(int16 arg1, int16 arg2) { - return ((arg1 > arg2) ? arg1 : arg2); + return ((arg1 > arg2) ? arg1 : arg2); } -int16 int2smaller(int16 arg1, int16 arg2) +int16 +int2smaller(int16 arg1, int16 arg2) { - return ((arg1 < arg2) ? arg1 : arg2); + return ((arg1 < arg2) ? arg1 : arg2); } -int32 int4larger(int32 arg1, int32 arg2) +int32 +int4larger(int32 arg1, int32 arg2) { - return ((arg1 > arg2) ? arg1 : arg2); + return ((arg1 > arg2) ? arg1 : arg2); } -int32 int4smaller(int32 arg1, int32 arg2) +int32 +int4smaller(int32 arg1, int32 arg2) { - return ((arg1 < arg2) ? arg1 : arg2); + return ((arg1 < arg2) ? arg1 : arg2); } diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c index 50b31514b2a..a3fdbce8855 100644 --- a/src/backend/utils/adt/like.c +++ b/src/backend/utils/adt/like.c @@ -1,225 +1,236 @@ /*------------------------------------------------------------------------- * * like.c-- - * like expression handling code. + * like expression handling code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * /usr/local/devel/pglite/cvs/src/backend/utils/adt/like.c,v 1.1 1995/07/30 23:55:36 emkxp01 Exp + * /usr/local/devel/pglite/cvs/src/backend/utils/adt/like.c,v 1.1 1995/07/30 23:55:36 emkxp01 Exp * * - * NOTES - * A big hack of the regexp.c code!! Contributed by - * Keith Parks <emkxp01@mtcc.demon.co.uk> (7/95). + * NOTES + * A big hack of the regexp.c code!! Contributed by + * Keith Parks <emkxp01@mtcc.demon.co.uk> (7/95). * * *------------------------------------------------------------------------- */ #include <string.h> -#include "postgres.h" /* postgres system include file */ +#include "postgres.h" /* postgres system include file */ #include "utils/palloc.h" -#include "utils/builtins.h" /* where the function declarations go */ +#include "utils/builtins.h" /* where the function declarations go */ -static int like(char *text, char *p); +static int like(char *text, char *p); /* - * interface routines called by the function manager + * interface routines called by the function manager */ /* fixedlen_like: a generic fixed length like routine - s - the string to match against (not necessarily null-terminated) - p - the pattern - charlen - the length of the string + s - the string to match against (not necessarily null-terminated) + p - the pattern + charlen - the length of the string */ -static bool -fixedlen_like(char *s, struct varlena* p, int charlen) +static bool +fixedlen_like(char *s, struct varlena * p, int charlen) { - char *sterm, *pterm; - int result; - - if (!s || !p) - return FALSE; - - /* be sure sterm is null-terminated */ - sterm = (char *) palloc(charlen + 1); - strNcpy(sterm, s, charlen); - - /* p is a text = varlena, not a string so we have to make - * a string from the vl_data field of the struct. */ - - /* palloc the length of the text + the null character */ - pterm = (char *) palloc(VARSIZE(p) - VARHDRSZ + 1); - memmove(pterm, VARDATA(p), VARSIZE(p) - VARHDRSZ); - *(pterm + VARSIZE(p) - VARHDRSZ) = (char)NULL; - - /* do the regexp matching */ - result = like(sterm, pterm); - - pfree(sterm); - pfree(pterm); - - return ((bool) result); + char *sterm, + *pterm; + int result; + + if (!s || !p) + return FALSE; + + /* be sure sterm is null-terminated */ + sterm = (char *) palloc(charlen + 1); + strNcpy(sterm, s, charlen); + + /* + * p is a text = varlena, not a string so we have to make a string + * from the vl_data field of the struct. + */ + + /* palloc the length of the text + the null character */ + pterm = (char *) palloc(VARSIZE(p) - VARHDRSZ + 1); + memmove(pterm, VARDATA(p), VARSIZE(p) - VARHDRSZ); + *(pterm + VARSIZE(p) - VARHDRSZ) = (char) NULL; + + /* do the regexp matching */ + result = like(sterm, pterm); + + pfree(sterm); + pfree(pterm); + + return ((bool) result); } -bool -char2like(uint16 arg1, struct varlena *p) +bool +char2like(uint16 arg1, struct varlena * p) { - char *s = (char *) &arg1; - return (fixedlen_like(s, p, 2)); -} + char *s = (char *) &arg1; -bool -char2nlike(uint16 arg1, struct varlena *p) + return (fixedlen_like(s, p, 2)); +} + +bool +char2nlike(uint16 arg1, struct varlena * p) { - return (!char2like(arg1, p)); + return (!char2like(arg1, p)); } -bool -char4like(uint32 arg1, struct varlena *p) +bool +char4like(uint32 arg1, struct varlena * p) { - char *s = (char *) &arg1; - return (fixedlen_like(s, p, 4)); + char *s = (char *) &arg1; + + return (fixedlen_like(s, p, 4)); } -bool -char4nlike(uint32 arg1, struct varlena *p) +bool +char4nlike(uint32 arg1, struct varlena * p) { - return (!char4like(arg1, p)); + return (!char4like(arg1, p)); } -bool -char8like(char *s, struct varlena *p) +bool +char8like(char *s, struct varlena * p) { - return (fixedlen_like(s, p, 8)); + return (fixedlen_like(s, p, 8)); } -bool -char8nlike(char *s, struct varlena *p) +bool +char8nlike(char *s, struct varlena * p) { - return (!char8like(s, p)); + return (!char8like(s, p)); } -bool -char16like(char *s, struct varlena *p) +bool +char16like(char *s, struct varlena * p) { - return (fixedlen_like(s, p, 16)); + return (fixedlen_like(s, p, 16)); } -bool -char16nlike(char *s, struct varlena *p) + +bool +char16nlike(char *s, struct varlena * p) { - return (!char16like(s, p)); + return (!char16like(s, p)); } -bool -namelike(NameData *n, struct varlena *p) +bool +namelike(NameData * n, struct varlena * p) { - if (!n) return FALSE; - return (fixedlen_like(n->data, p, NAMEDATALEN)); + if (!n) + return FALSE; + return (fixedlen_like(n->data, p, NAMEDATALEN)); } -bool -namenlike(NameData *s, struct varlena *p) +bool +namenlike(NameData * s, struct varlena * p) { - return (!namelike(s, p)); + return (!namelike(s, p)); } -bool -textlike(struct varlena *s, struct varlena *p) +bool +textlike(struct varlena * s, struct varlena * p) { - if (!s) return FALSE; - return (fixedlen_like(VARDATA(s), p, VARSIZE(s) - VARHDRSZ)); + if (!s) + return FALSE; + return (fixedlen_like(VARDATA(s), p, VARSIZE(s) - VARHDRSZ)); } -bool textnlike(struct varlena *s, struct varlena *p) +bool +textnlike(struct varlena * s, struct varlena * p) { - return (!textlike(s, p)); + return (!textlike(s, p)); } -/* $Revision: 1.6 $ -** "like.c" A first attempt at a LIKE operator for Postgres95. +/* $Revision: 1.7 $ +** "like.c" A first attempt at a LIKE operator for Postgres95. +** +** Originally written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. +** Rich $alz is now <rsalz@bbn.com>. +** Special thanks to Lars Mathiesen <thorinn@diku.dk> for the LABORT code. +** +** This code was shamelessly stolen from the "pql" code by myself and +** slightly modified :) +** +** All references to the word "star" were replaced by "percent" +** All references to the word "wild" were replaced by "like" +** +** All the nice shell RE matching stuff was replaced by just "_" and "%" ** -** Originally written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. -** Rich $alz is now <rsalz@bbn.com>. -** Special thanks to Lars Mathiesen <thorinn@diku.dk> for the LABORT code. -** -** This code was shamelessly stolen from the "pql" code by myself and -** slightly modified :) -** -** All references to the word "star" were replaced by "percent" -** All references to the word "wild" were replaced by "like" -** -** All the nice shell RE matching stuff was replaced by just "_" and "%" -** -** As I don't have a copy of the SQL standard handy I wasn't sure whether -** to leave in the '\' escape character handling. (I suspect the standard -** handles "%%" as a single literal percent) +** As I don't have a copy of the SQL standard handy I wasn't sure whether +** to leave in the '\' escape character handling. (I suspect the standard +** handles "%%" as a single literal percent) ** -** Keith Parks. <keith@mtcc.demon.co.uk> +** Keith Parks. <keith@mtcc.demon.co.uk> ** -** [SQL92 lets you specify the escape character by saying -** LIKE <pattern> ESCAPE <escape character>. We are a small operation -** so we force you to use '\'. - ay 7/95] +** [SQL92 lets you specify the escape character by saying +** LIKE <pattern> ESCAPE <escape character>. We are a small operation +** so we force you to use '\'. - ay 7/95] ** */ -#define LIKE_TRUE 1 -#define LIKE_FALSE 0 -#define LIKE_ABORT -1 +#define LIKE_TRUE 1 +#define LIKE_FALSE 0 +#define LIKE_ABORT -1 /* -** Match text and p, return LIKE_TRUE, LIKE_FALSE, or LIKE_ABORT. +** Match text and p, return LIKE_TRUE, LIKE_FALSE, or LIKE_ABORT. */ static int DoMatch(register char *text, register char *p) { - register int matched; - - for ( ; *p; text++, p++) { - if (*text == '\0' && *p != '%') - return LIKE_ABORT; - switch (*p) { - case '\\': - /* Literal match with following character. */ - p++; - /* FALLTHROUGH */ - default: - if (*text != *p) - return LIKE_FALSE; - continue; - case '_': - /* Match anything. */ - continue; - case '%': - while (*++p == '%') - /* Consecutive percents act just like one. */ - continue; - if (*p == '\0') - /* Trailing percent matches everything. */ - return LIKE_TRUE; - while (*text) - if ((matched = DoMatch(text++, p)) != LIKE_FALSE) - return matched; - return LIKE_ABORT; + register int matched; + + for (; *p; text++, p++) + { + if (*text == '\0' && *p != '%') + return LIKE_ABORT; + switch (*p) + { + case '\\': + /* Literal match with following character. */ + p++; + /* FALLTHROUGH */ + default: + if (*text != *p) + return LIKE_FALSE; + continue; + case '_': + /* Match anything. */ + continue; + case '%': + while (*++p == '%') + /* Consecutive percents act just like one. */ + continue; + if (*p == '\0') + /* Trailing percent matches everything. */ + return LIKE_TRUE; + while (*text) + if ((matched = DoMatch(text++, p)) != LIKE_FALSE) + return matched; + return LIKE_ABORT; + } } - } - return *text == '\0'; + return *text == '\0'; } /* -** User-level routine. Returns TRUE or FALSE. +** User-level routine. Returns TRUE or FALSE. */ static int like(char *text, char *p) { - if (p[0] == '%' && p[1] == '\0') - return TRUE; - return (DoMatch(text, p) == LIKE_TRUE); + if (p[0] == '%' && p[1] == '\0') + return TRUE; + return (DoMatch(text, p) == LIKE_TRUE); } diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 95dfcfc8ca1..f04152cf6d2 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * misc.c-- - * + * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v 1.7 1997/07/28 00:55:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v 1.8 1997/09/07 04:50:23 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,70 +18,73 @@ #include "catalog/pg_type.h" #include "utils/builtins.h" -#include "port-protos.h" /* For random(), sometimes */ +#include "port-protos.h" /* For random(), sometimes */ /*------------------------------------------------------------------------- - * Check if data is Null + * Check if data is Null */ bool -nullvalue(Datum value, bool *isNull) +nullvalue(Datum value, bool * isNull) { - if (*isNull) { - *isNull = false; - return(true); - } - return(false); - + if (*isNull) + { + *isNull = false; + return (true); + } + return (false); + } /*----------------------------------------------------------------------* - * check if data is not Null * + * check if data is not Null * *--------------------------------------------------------------------- */ bool -nonnullvalue(Datum value, bool *isNull) +nonnullvalue(Datum value, bool * isNull) { - if (*isNull) { - *isNull = false; - return(false); - } - return(true); - + if (*isNull) + { + *isNull = false; + return (false); + } + return (true); + } /* * oidrand (oid o, int4 X)- - * takes in an oid and a int4 X, and will return 'true' - * about 1/X of the time. - * Useful for doing random sampling or subsetting. - * if X == 0, this will always return true; + * takes in an oid and a int4 X, and will return 'true' + * about 1/X of the time. + * Useful for doing random sampling or subsetting. + * if X == 0, this will always return true; * * Example use: - * select * from TEMP where oidrand(TEMP.oid, 10) + * select * from TEMP where oidrand(TEMP.oid, 10) * will return about 1/10 of the tuples in TEMP * */ -bool +bool oidrand(Oid o, int32 X) { - bool result; + bool result; - if (X == 0) return true; + if (X == 0) + return true; - result = (random() % X == 0); - return result; + result = (random() % X == 0); + return result; } /* oidsrand(int32 X) - - seeds the random number generator - always return true -*/ + seeds the random number generator + always return true +*/ bool oidsrand(int32 X) { - srand(X); - return true; + srand(X); + return true; } @@ -89,5 +92,5 @@ oidsrand(int32 X) int32 userfntest(int i) { - return (i); + return (i); } diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 0e56a2816ee..9eb5ed36281 100644 --- a/src/backend/utils/adt/nabstime.c +++ b/src/backend/utils/adt/nabstime.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * nabstime.c-- - * parse almost any absolute date getdate(3) can (& some it can't) + * parse almost any absolute date getdate(3) can (& some it can't) * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.31 1997/08/19 21:34:42 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.32 1997/09/07 04:50:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,10 +19,10 @@ #include "postgres.h" #include <miscadmin.h> #ifdef HAVE_FLOAT_H -# include <float.h> +#include <float.h> #endif #ifdef HAVE_LIMITS_H -# include <limits.h> +#include <limits.h> #endif #ifndef USE_POSIX_TIME #include <sys/timeb.h> @@ -30,10 +30,10 @@ #include "utils/builtins.h" #include "access/xact.h" -static AbsoluteTime tm2abstime(struct tm *tm, int tz); +static AbsoluteTime tm2abstime(struct tm * tm, int tz); -#define MIN_DAYNUM -24856 /* December 13, 1901 */ -#define MAX_DAYNUM 24854 /* January 18, 2038 */ +#define MIN_DAYNUM -24856 /* December 13, 1901 */ +#define MAX_DAYNUM 24854 /* January 18, 2038 */ /* GetCurrentAbsoluteTime() @@ -45,300 +45,344 @@ static AbsoluteTime tm2abstime(struct tm *tm, int tz); AbsoluteTime GetCurrentAbsoluteTime(void) { - time_t now; + time_t now; #ifdef USE_POSIX_TIME - struct tm *tm; + struct tm *tm; - now = time(NULL); -#else /* ! USE_POSIX_TIME */ - struct timeb tb; /* the old V7-ism */ + now = time(NULL); +#else /* ! USE_POSIX_TIME */ + struct timeb tb; /* the old V7-ism */ - ftime(&tb); - now = tb.time; + ftime(&tb); + now = tb.time; #endif - if (! HasCTZSet) { + if (!HasCTZSet) + { #ifdef USE_POSIX_TIME #if defined(HAVE_TZSET) && defined(HAVE_INT_TIMEZONE) - tm = localtime(&now); - - CDayLight = tm->tm_isdst; - CTimeZone = (tm->tm_isdst? (timezone - 3600): timezone); - strcpy( CTZName, tzname[tm->tm_isdst]); -#else /* !HAVE_TZSET */ - tm = localtime(&now); - - CTimeZone = - tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */ - CDayLight = (tm->tm_isdst > 0); - /* XXX is there a better way to get local timezone string w/o tzname? - tgl 97/03/18 */ - strftime( CTZName, MAXTZLEN, "%Z", tm); - /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */ - strcpy(CTZName, tm->tm_zone); + tm = localtime(&now); + + CDayLight = tm->tm_isdst; + CTimeZone = (tm->tm_isdst ? (timezone - 3600) : timezone); + strcpy(CTZName, tzname[tm->tm_isdst]); +#else /* !HAVE_TZSET */ + tm = localtime(&now); + + CTimeZone = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */ + CDayLight = (tm->tm_isdst > 0); + + /* + * XXX is there a better way to get local timezone string w/o + * tzname? - tgl 97/03/18 + */ + strftime(CTZName, MAXTZLEN, "%Z", tm); + + /* + * XXX FreeBSD man pages indicate that this should work - tgl + * 97/04/23 + */ + strcpy(CTZName, tm->tm_zone); +#endif +#else /* ! USE_POSIX_TIME */ + CTimeZone = tb.timezone * 60; + CDayLight = (tb.dstflag != 0); + + /* + * XXX does this work to get the local timezone string in V7? - + * tgl 97/03/18 + */ + strftime(CTZName, MAXTZLEN, "%Z", localtime(&now)); #endif -#else /* ! USE_POSIX_TIME */ - CTimeZone = tb.timezone * 60; - CDayLight = (tb.dstflag != 0); - /* XXX does this work to get the local timezone string in V7? - tgl 97/03/18 */ - strftime( CTZName, MAXTZLEN, "%Z", localtime(&now)); -#endif - }; + }; #ifdef DATEDEBUG -printf( "GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTC\n", - CTZName, CTimeZone); + printf("GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTC\n", + CTZName, CTimeZone); #endif - return((AbsoluteTime) now); -} /* GetCurrentAbsoluteTime() */ + return ((AbsoluteTime) now); +} /* GetCurrentAbsoluteTime() */ void -GetCurrentTime(struct tm *tm) +GetCurrentTime(struct tm * tm) { - int tz; + int tz; - abstime2tm( GetCurrentTransactionStartTime(), &tz, tm, NULL); + abstime2tm(GetCurrentTransactionStartTime(), &tz, tm, NULL); - return; -} /* GetCurrentTime() */ + return; +} /* GetCurrentTime() */ void -abstime2tm(AbsoluteTime time, int *tzp, struct tm *tm, char *tzn) +abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn) { #ifdef USE_POSIX_TIME - struct tm *tx; -#else /* ! USE_POSIX_TIME */ - struct timeb tb; /* the old V7-ism */ + struct tm *tx; - ftime(&tb); +#else /* ! USE_POSIX_TIME */ + struct timeb tb; /* the old V7-ism */ + + ftime(&tb); #endif #ifdef USE_POSIX_TIME - if (tzp != NULL) { - tx = localtime((time_t *) &time); - } else { - tx = gmtime((time_t *) &time); - }; + if (tzp != NULL) + { + tx = localtime((time_t *) & time); + } + else + { + tx = gmtime((time_t *) & time); + }; #else #endif #ifdef DATEDEBUG #ifdef HAVE_INT_TIMEZONE -printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s %s dst=%d\n", - tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec, - tzname[0], tzname[1], tx->tm_isdst); + printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s %s dst=%d\n", + tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec, + tzname[0], tzname[1], tx->tm_isdst); #else -printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s dst=%d\n", - tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec, - tx->tm_zone, tx->tm_isdst); + printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s dst=%d\n", + tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec, + tx->tm_zone, tx->tm_isdst); #endif #else #endif - tm->tm_year = tx->tm_year+1900; - tm->tm_mon = tx->tm_mon+1; - tm->tm_mday = tx->tm_mday; - tm->tm_hour = tx->tm_hour; - tm->tm_min = tx->tm_min; - tm->tm_sec = tx->tm_sec; - tm->tm_isdst = tx->tm_isdst; + tm->tm_year = tx->tm_year + 1900; + tm->tm_mon = tx->tm_mon + 1; + tm->tm_mday = tx->tm_mday; + tm->tm_hour = tx->tm_hour; + tm->tm_min = tx->tm_min; + tm->tm_sec = tx->tm_sec; + tm->tm_isdst = tx->tm_isdst; #ifdef USE_POSIX_TIME #ifdef HAVE_INT_TIMEZONE - if (tzp != NULL) *tzp = (tm->tm_isdst? (timezone - 3600): timezone); - if (tzn != NULL) strcpy( tzn, tzname[tm->tm_isdst]); -#else /* !HAVE_INT_TIMEZONE */ - tm->tm_gmtoff = tx->tm_gmtoff; - tm->tm_zone = tx->tm_zone; - - if (tzp != NULL) *tzp = - tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */ - /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */ - if (tzn != NULL) strcpy( tzn, tm->tm_zone); + if (tzp != NULL) + *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone); + if (tzn != NULL) + strcpy(tzn, tzname[tm->tm_isdst]); +#else /* !HAVE_INT_TIMEZONE */ + tm->tm_gmtoff = tx->tm_gmtoff; + tm->tm_zone = tx->tm_zone; + + if (tzp != NULL) + *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */ + /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */ + if (tzn != NULL) + strcpy(tzn, tm->tm_zone); +#endif +#else /* ! USE_POSIX_TIME */ + if (tzp != NULL) + *tzp = tb.timezone * 60; + + /* + * XXX does this work to get the local timezone string in V7? - tgl + * 97/03/18 + */ + if (tzn != NULL) + strftime(tzn, MAXTZLEN, "%Z", localtime(&now)); #endif -#else /* ! USE_POSIX_TIME */ - if (tzp != NULL) *tzp = tb.timezone * 60; - /* XXX does this work to get the local timezone string in V7? - tgl 97/03/18 */ - if (tzn != NULL) strftime( tzn, MAXTZLEN, "%Z", localtime(&now)); -#endif - return; -} /* abstime2tm() */ + return; +} /* abstime2tm() */ /* tm2abstime() * Convert a tm structure to abstime. * Note that tm has full year (not 1900-based) and 1-based month. */ -static AbsoluteTime -tm2abstime( struct tm *tm, int tz) +static AbsoluteTime +tm2abstime(struct tm * tm, int tz) { - int day, sec; + int day, + sec; - /* validate, before going out of range on some members */ - if (tm->tm_year < 1901 || tm->tm_year > 2038 - || tm->tm_mon < 1 || tm->tm_mon > 12 - || tm->tm_mday < 1 || tm->tm_mday > 31 - || tm->tm_hour < 0 || tm->tm_hour >= 24 - || tm->tm_min < 0 || tm->tm_min > 59 - || tm->tm_sec < 0 || tm->tm_sec > 59) - return(INVALID_ABSTIME); + /* validate, before going out of range on some members */ + if (tm->tm_year < 1901 || tm->tm_year > 2038 + || tm->tm_mon < 1 || tm->tm_mon > 12 + || tm->tm_mday < 1 || tm->tm_mday > 31 + || tm->tm_hour < 0 || tm->tm_hour >= 24 + || tm->tm_min < 0 || tm->tm_min > 59 + || tm->tm_sec < 0 || tm->tm_sec > 59) + return (INVALID_ABSTIME); - day = (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j( 1970, 1, 1)); + day = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(1970, 1, 1)); - /* check for time out of range */ - if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM)) - return(INVALID_ABSTIME); + /* check for time out of range */ + if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM)) + return (INVALID_ABSTIME); - /* convert to seconds */ - sec = tm->tm_sec + tz + (tm->tm_min +(day*24 + tm->tm_hour)*60)*60; + /* convert to seconds */ + sec = tm->tm_sec + tz + (tm->tm_min + (day * 24 + tm->tm_hour) * 60) * 60; - /* check for overflow */ - if ((day == MAX_DAYNUM && sec < 0) || - (day == MIN_DAYNUM && sec > 0)) - return(INVALID_ABSTIME); + /* check for overflow */ + if ((day == MAX_DAYNUM && sec < 0) || + (day == MIN_DAYNUM && sec > 0)) + return (INVALID_ABSTIME); - /* check for reserved values (e.g. "current" on edge of usual range */ - if (!AbsoluteTimeIsReal(sec)) - return(INVALID_ABSTIME); + /* check for reserved values (e.g. "current" on edge of usual range */ + if (!AbsoluteTimeIsReal(sec)) + return (INVALID_ABSTIME); - return(sec); -} /* tm2abstime() */ + return (sec); +} /* tm2abstime() */ /* nabstimein() * Decode date/time string and return abstime. */ AbsoluteTime -nabstimein(char* str) +nabstimein(char *str) { - AbsoluteTime result; + AbsoluteTime result; - double fsec; - int tz = 0; - struct tm date, *tm = &date; + double fsec; + int tz = 0; + struct tm date, + *tm = &date; - char *field[MAXDATEFIELDS]; - char lowstr[MAXDATELEN+1]; - int dtype; - int nf, ftype[MAXDATEFIELDS]; + char *field[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; + int dtype; + int nf, + ftype[MAXDATEFIELDS]; - if (!PointerIsValid(str)) - elog(WARN,"Bad (null) abstime external representation",NULL); + if (!PointerIsValid(str)) + elog(WARN, "Bad (null) abstime external representation", NULL); - if (strlen(str) > MAXDATELEN) - elog( WARN, "Bad (length) abstime external representation '%s'",str); + if (strlen(str) > MAXDATELEN) + elog(WARN, "Bad (length) abstime external representation '%s'", str); - if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) - || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) - elog( WARN, "Bad abstime external representation '%s'",str); + if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) + || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) + elog(WARN, "Bad abstime external representation '%s'", str); #ifdef DATEDEBUG -printf( "nabstimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE); + printf("nabstimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE); #endif - switch (dtype) { - case DTK_DATE: - result = tm2abstime(tm, tz); - break; + switch (dtype) + { + case DTK_DATE: + result = tm2abstime(tm, tz); + break; - case DTK_EPOCH: - result = EPOCH_ABSTIME; - break; + case DTK_EPOCH: + result = EPOCH_ABSTIME; + break; - case DTK_CURRENT: - result = CURRENT_ABSTIME; - break; + case DTK_CURRENT: + result = CURRENT_ABSTIME; + break; - case DTK_LATE: - result = NOEND_ABSTIME; - break; + case DTK_LATE: + result = NOEND_ABSTIME; + break; - case DTK_EARLY: - result = NOSTART_ABSTIME; - break; + case DTK_EARLY: + result = NOSTART_ABSTIME; + break; - case DTK_INVALID: - result = INVALID_ABSTIME; - break; + case DTK_INVALID: + result = INVALID_ABSTIME; + break; - default: - elog(WARN,"Bad abstime (internal coding error) '%s'",str); - result = INVALID_ABSTIME; - break; - }; + default: + elog(WARN, "Bad abstime (internal coding error) '%s'", str); + result = INVALID_ABSTIME; + break; + }; - return result; -} /* nabstimein() */ + return result; +} /* nabstimein() */ /* nabstimeout() * Given an AbsoluteTime return the English text version of the date */ -char * +char * nabstimeout(AbsoluteTime time) { - char* result; - int tz; - double fsec = 0; - struct tm tt, *tm = &tt; - char buf[MAXDATELEN+1]; - char zone[MAXDATELEN+1], *tzn = zone; - - switch (time) { - case EPOCH_ABSTIME: strcpy(buf, EPOCH); break; - case INVALID_ABSTIME: strcpy(buf, INVALID); break; - case CURRENT_ABSTIME: strcpy(buf, DCURRENT); break; - case NOEND_ABSTIME: strcpy(buf, LATE); break; - case NOSTART_ABSTIME: strcpy(buf, EARLY); break; - default: - abstime2tm( time, &tz, tm, tzn); + char *result; + int tz; + double fsec = 0; + struct tm tt, + *tm = &tt; + char buf[MAXDATELEN + 1]; + char zone[MAXDATELEN + 1], + *tzn = zone; + + switch (time) + { + case EPOCH_ABSTIME: + strcpy(buf, EPOCH); + break; + case INVALID_ABSTIME: + strcpy(buf, INVALID); + break; + case CURRENT_ABSTIME: + strcpy(buf, DCURRENT); + break; + case NOEND_ABSTIME: + strcpy(buf, LATE); + break; + case NOSTART_ABSTIME: + strcpy(buf, EARLY); + break; + default: + abstime2tm(time, &tz, tm, tzn); #if DATEDEBUG #endif - EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); - break; - } + EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); + break; + } - result = PALLOC(strlen(buf) + 1); - strcpy(result, buf); + result = PALLOC(strlen(buf) + 1); + strcpy(result, buf); - return(result); -} /* nabstimeout() */ + return (result); +} /* nabstimeout() */ /* - * AbsoluteTimeIsBefore -- true iff time1 is before time2. - * AbsoluteTimeIsBefore -- true iff time1 is after time2. + * AbsoluteTimeIsBefore -- true iff time1 is before time2. + * AbsoluteTimeIsBefore -- true iff time1 is after time2. */ bool AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2) { - Assert(AbsoluteTimeIsValid(time1)); - Assert(AbsoluteTimeIsValid(time2)); + Assert(AbsoluteTimeIsValid(time1)); + Assert(AbsoluteTimeIsValid(time2)); - if (time1 == CURRENT_ABSTIME) - time1 = GetCurrentTransactionStartTime(); + if (time1 == CURRENT_ABSTIME) + time1 = GetCurrentTransactionStartTime(); - if (time2 == CURRENT_ABSTIME) - time2 = GetCurrentTransactionStartTime(); + if (time2 == CURRENT_ABSTIME) + time2 = GetCurrentTransactionStartTime(); - return (time1 < time2); + return (time1 < time2); } bool AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2) { - Assert(AbsoluteTimeIsValid(time1)); - Assert(AbsoluteTimeIsValid(time2)); + Assert(AbsoluteTimeIsValid(time1)); + Assert(AbsoluteTimeIsValid(time2)); - if (time1 == CURRENT_ABSTIME) - time1 = GetCurrentTransactionStartTime(); + if (time1 == CURRENT_ABSTIME) + time1 = GetCurrentTransactionStartTime(); - if (time2 == CURRENT_ABSTIME) - time2 = GetCurrentTransactionStartTime(); + if (time2 == CURRENT_ABSTIME) + time2 = GetCurrentTransactionStartTime(); - return (time1 > time2); + return (time1 > time2); } @@ -347,95 +391,95 @@ AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2) bool abstime_finite(AbsoluteTime abstime) { - return((abstime != INVALID_ABSTIME) - && (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME)); -} /* abstime_datetime() */ + return ((abstime != INVALID_ABSTIME) + && (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME)); +} /* abstime_datetime() */ /* - * abstimeeq - returns 1, iff arguments are equal - * abstimene - returns 1, iff arguments are not equal - * abstimelt - returns 1, iff t1 less than t2 - * abstimegt - returns 1, iff t1 greater than t2 - * abstimele - returns 1, iff t1 less than or equal to t2 - * abstimege - returns 1, iff t1 greater than or equal to t2 + * abstimeeq - returns 1, iff arguments are equal + * abstimene - returns 1, iff arguments are not equal + * abstimelt - returns 1, iff t1 less than t2 + * abstimegt - returns 1, iff t1 greater than t2 + * abstimele - returns 1, iff t1 less than or equal to t2 + * abstimege - returns 1, iff t1 greater than or equal to t2 */ bool abstimeeq(AbsoluteTime t1, AbsoluteTime t2) { - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return(FALSE); - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - return(t1 == t2); + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + return (FALSE); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + return (t1 == t2); } bool abstimene(AbsoluteTime t1, AbsoluteTime t2) -{ - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return(FALSE); - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - return(t1 != t2); +{ + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + return (FALSE); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + return (t1 != t2); } bool abstimelt(AbsoluteTime t1, AbsoluteTime t2) -{ - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return(FALSE); - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - return(t1 < t2); +{ + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + return (FALSE); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + return (t1 < t2); } bool abstimegt(AbsoluteTime t1, AbsoluteTime t2) -{ - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return(FALSE); - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - return(t1 > t2); +{ + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + return (FALSE); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + return (t1 > t2); } bool abstimele(AbsoluteTime t1, AbsoluteTime t2) -{ - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return(FALSE); - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - return(t1 <= t2); +{ + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + return (FALSE); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + return (t1 <= t2); } bool abstimege(AbsoluteTime t1, AbsoluteTime t2) -{ - if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) - return(FALSE); - if (t1 == CURRENT_ABSTIME) - t1 = GetCurrentTransactionStartTime(); - if (t2 == CURRENT_ABSTIME) - t2 = GetCurrentTransactionStartTime(); - - return(t1 >= t2); +{ + if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) + return (FALSE); + if (t1 == CURRENT_ABSTIME) + t1 = GetCurrentTransactionStartTime(); + if (t2 == CURRENT_ABSTIME) + t2 = GetCurrentTransactionStartTime(); + + return (t1 >= t2); } @@ -443,77 +487,93 @@ abstimege(AbsoluteTime t1, AbsoluteTime t2) * Convert datetime to abstime. */ AbsoluteTime -datetime_abstime(DateTime *datetime) +datetime_abstime(DateTime * datetime) { - AbsoluteTime result; - - double fsec; - struct tm tt, *tm = &tt; - - if (!PointerIsValid(datetime)) { - result = INVALID_ABSTIME; - - } else if (DATETIME_IS_INVALID(*datetime)) { - result = INVALID_ABSTIME; - - } else if (DATETIME_IS_NOBEGIN(*datetime)) { - result = NOSTART_ABSTIME; - - } else if (DATETIME_IS_NOEND(*datetime)) { - result = NOEND_ABSTIME; - - } else { - if (DATETIME_IS_RELATIVE(*datetime)) { - datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec, NULL); - result = tm2abstime( tm, 0); - - } else if (datetime2tm( *datetime, NULL, tm, &fsec, NULL) == 0) { - result = tm2abstime( tm, 0); - - } else { - result = INVALID_ABSTIME; + AbsoluteTime result; + + double fsec; + struct tm tt, + *tm = &tt; + + if (!PointerIsValid(datetime)) + { + result = INVALID_ABSTIME; + + } + else if (DATETIME_IS_INVALID(*datetime)) + { + result = INVALID_ABSTIME; + + } + else if (DATETIME_IS_NOBEGIN(*datetime)) + { + result = NOSTART_ABSTIME; + + } + else if (DATETIME_IS_NOEND(*datetime)) + { + result = NOEND_ABSTIME; + + } + else + { + if (DATETIME_IS_RELATIVE(*datetime)) + { + datetime2tm(SetDateTime(*datetime), NULL, tm, &fsec, NULL); + result = tm2abstime(tm, 0); + + } + else if (datetime2tm(*datetime, NULL, tm, &fsec, NULL) == 0) + { + result = tm2abstime(tm, 0); + + } + else + { + result = INVALID_ABSTIME; + }; }; - }; - return(result); -} /* datetime_abstime() */ + return (result); +} /* datetime_abstime() */ /* abstime_datetime() * Convert datetime to abstime. */ -DateTime * +DateTime * abstime_datetime(AbsoluteTime abstime) { - DateTime *result; + DateTime *result; - if (!PointerIsValid(result = PALLOCTYPE(DateTime))) - elog(WARN,"Unable to allocate space to convert abstime to datetime",NULL); + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN, "Unable to allocate space to convert abstime to datetime", NULL); - switch (abstime) { - case INVALID_ABSTIME: - DATETIME_INVALID(*result); - break; + switch (abstime) + { + case INVALID_ABSTIME: + DATETIME_INVALID(*result); + break; - case NOSTART_ABSTIME: - DATETIME_NOBEGIN(*result); - break; + case NOSTART_ABSTIME: + DATETIME_NOBEGIN(*result); + break; - case NOEND_ABSTIME: - DATETIME_NOEND(*result); - break; + case NOEND_ABSTIME: + DATETIME_NOEND(*result); + break; - case EPOCH_ABSTIME: - DATETIME_EPOCH(*result); - break; + case EPOCH_ABSTIME: + DATETIME_EPOCH(*result); + break; - case CURRENT_ABSTIME: - DATETIME_CURRENT(*result); - break; + case CURRENT_ABSTIME: + DATETIME_CURRENT(*result); + break; - default: - *result = abstime + ((date2j( 1970, 1, 1) - date2j( 2000, 1, 1))*86400); - break; - }; + default: + *result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400); + break; + }; - return(result); -} /* abstime_datetime() */ + return (result); +} /* abstime_datetime() */ diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index 7ef599b3dee..b0de03ff602 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -1,203 +1,221 @@ /*------------------------------------------------------------------------- * * name.c-- - * Functions for the built-in type "name". + * Functions for the built-in type "name". * name replaces char16 and is carefully implemented so that it * is a string of length NAMEDATALEN. DO NOT use hard-coded constants anywhere * always use NAMEDATALEN as the symbolic constant! - jolly 8/21/95 - * + * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.6 1997/08/19 21:34:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.7 1997/09/07 04:50:27 momjian Exp $ * *------------------------------------------------------------------------- */ #include <string.h> #include "postgres.h" -#include "utils/builtins.h" /* where the declarations go */ -#include "utils/palloc.h" /* where the declarations go */ +#include "utils/builtins.h" /* where the declarations go */ +#include "utils/palloc.h" /* where the declarations go */ -/***************************************************************************** - * USER I/O ROUTINES (none) * +/***************************************************************************** + * USER I/O ROUTINES (none) * *****************************************************************************/ /* - * namein - converts "..." to internal representation + * namein - converts "..." to internal representation * - * Note: - * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls - * Now, always NULL terminated + * Note: + * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls + * Now, always NULL terminated */ -NameData *namein(char *s) +NameData * +namein(char *s) { - NameData *result; - - if (s == NULL) - return(NULL); - result = (NameData*) palloc(NAMEDATALEN); - /* always keep it null-padded */ - strNcpy(result->data, s, NAMEDATALEN-1); - return(result); + NameData *result; + + if (s == NULL) + return (NULL); + result = (NameData *) palloc(NAMEDATALEN); + /* always keep it null-padded */ + strNcpy(result->data, s, NAMEDATALEN - 1); + return (result); } /* - * nameout - converts internal reprsentation to "..." + * nameout - converts internal reprsentation to "..." */ -char *nameout(NameData *s) +char * +nameout(NameData * s) { - if (s == NULL) - return "-"; - else - return pstrdup(s->data); + if (s == NULL) + return "-"; + else + return pstrdup(s->data); } -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ /* - * nameeq - returns 1 iff arguments are equal - * namene - returns 1 iff arguments are not equal + * nameeq - returns 1 iff arguments are equal + * namene - returns 1 iff arguments are not equal * - * BUGS: - * Assumes that "xy\0\0a" should be equal to "xy\0b". - * If not, can do the comparison backwards for efficiency. + * BUGS: + * Assumes that "xy\0\0a" should be equal to "xy\0b". + * If not, can do the comparison backwards for efficiency. * - * namelt - returns 1 iff a < b - * namele - returns 1 iff a <= b - * namegt - returns 1 iff a < b - * namege - returns 1 iff a <= b + * namelt - returns 1 iff a < b + * namele - returns 1 iff a <= b + * namegt - returns 1 iff a < b + * namege - returns 1 iff a <= b * */ -bool nameeq(NameData *arg1, NameData *arg2) +bool +nameeq(NameData * arg1, NameData * arg2) { - if (!arg1 || !arg2) - return 0; - else - return ((bool) strncmp(arg1->data, arg2->data, NAMEDATALEN) == 0); + if (!arg1 || !arg2) + return 0; + else + return ((bool) strncmp(arg1->data, arg2->data, NAMEDATALEN) == 0); } -bool namene(NameData *arg1, NameData *arg2) +bool +namene(NameData * arg1, NameData * arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) != 0)); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return ((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) != 0)); } -bool namelt(NameData *arg1, NameData *arg2) +bool +namelt(NameData * arg1, NameData * arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) < 0)); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return ((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) < 0)); } -bool namele(NameData *arg1, NameData *arg2) +bool +namele(NameData * arg1, NameData * arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - return((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) <= 0)); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + return ((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) <= 0)); } -bool namegt(NameData *arg1, NameData *arg2) +bool +namegt(NameData * arg1, NameData * arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - - return((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) > 0)); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + + return ((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) > 0)); } -bool namege(NameData *arg1, NameData *arg2) +bool +namege(NameData * arg1, NameData * arg2) { - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - - return((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) >= 0)); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + + return ((bool) (strncmp(arg1->data, arg2->data, NAMEDATALEN) >= 0)); } /* (see char.c for comparison/operation routines) */ -int namecpy(Name n1, Name n2) +int +namecpy(Name n1, Name n2) { - if (!n1 || !n2) - return(-1); - strncpy(n1->data, n2->data, NAMEDATALEN); - return(0); + if (!n1 || !n2) + return (-1); + strncpy(n1->data, n2->data, NAMEDATALEN); + return (0); } #ifdef NOT_USED -int namecat(Name n1, Name n2) +int +namecat(Name n1, Name n2) { - return(namestrcat(n1, n2->data)); /* n2 can't be any longer than n1 */ + return (namestrcat(n1, n2->data)); /* n2 can't be any longer than n1 */ } + #endif -int namecmp(Name n1, Name n2) +int +namecmp(Name n1, Name n2) { - return(strncmp(n1->data, n2->data, NAMEDATALEN)); + return (strncmp(n1->data, n2->data, NAMEDATALEN)); } -int +int namestrcpy(Name name, char *str) { - if (!name || !str) - return(-1); - strNcpy(name->data, str, NAMEDATALEN-1); - return(0); + if (!name || !str) + return (-1); + strNcpy(name->data, str, NAMEDATALEN - 1); + return (0); } #ifdef NOT_USED -int namestrcat(Name name, char *str) +int +namestrcat(Name name, char *str) { - int i; - char *p, *q; - - if (!name || !str) - return(-1); - for (i = 0, p = name->data; i < NAMEDATALEN && *p; ++i, ++p) - ; - for (q = str; i < NAMEDATALEN; ++i, ++p, ++q) { - *p = *q; - if (!*q) - break; - } - return(0); + int i; + char *p, + *q; + + if (!name || !str) + return (-1); + for (i = 0, p = name->data; i < NAMEDATALEN && *p; ++i, ++p) + ; + for (q = str; i < NAMEDATALEN; ++i, ++p, ++q) + { + *p = *q; + if (!*q) + break; + } + return (0); } + #endif -int +int namestrcmp(Name name, char *str) { - if (!name && !str) - return(0); - if (!name) - return(-1); /* NULL < anything */ - if (!str) - return(1); /* NULL < anything */ - return(strncmp(name->data, str, NAMEDATALEN)); + if (!name && !str) + return (0); + if (!name) + return (-1); /* NULL < anything */ + if (!str) + return (1); /* NULL < anything */ + return (strncmp(name->data, str, NAMEDATALEN)); } -/***************************************************************************** - * PRIVATE ROUTINES * +/***************************************************************************** + * PRIVATE ROUTINES * *****************************************************************************/ #ifdef NOT_USED -uint32 +uint32 NameComputeLength(Name name) { - char *charP; - int length; - - for (length = 0, charP = name->data; - length < NAMEDATALEN && *charP != '\0'; - length++, charP++) { - ; - } - return (uint32)length; + char *charP; + int length; + + for (length = 0, charP = name->data; + length < NAMEDATALEN && *charP != '\0'; + length++, charP++) + { + ; + } + return (uint32) length; } + #endif diff --git a/src/backend/utils/adt/not_in.c b/src/backend/utils/adt/not_in.c index a78e7dc31ce..0bc51eb6f19 100644 --- a/src/backend/utils/adt/not_in.c +++ b/src/backend/utils/adt/not_in.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * not_in.c-- - * Executes the "not_in" operator for any data type + * Executes the "not_in" operator for any data type * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.3 1997/08/19 21:34:48 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.4 1997/09/07 04:50:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -27,81 +27,85 @@ #include "postgres.h" #include "access/heapam.h" #include "access/relscan.h" -#include "utils/builtins.h" /* where function decls go */ +#include "utils/builtins.h" /* where function decls go */ -static int my_varattno(Relation rd, char *a); +static int my_varattno(Relation rd, char *a); /* ---------------------------------------------------------------- - * + * * ---------------------------------------------------------------- */ bool int4notin(int16 not_in_arg, char *relation_and_attr) { - Relation relation_to_scan; - int left_side_argument, integer_value; - HeapTuple current_tuple; - HeapScanDesc scan_descriptor; - bool dummy, retval; - int attrid; - char *relation, *attribute; - char my_copy[32]; - Datum value; - NameData relNameData; - ScanKeyData skeyData; - - strcpy(my_copy, relation_and_attr); - - relation = (char *) strtok(my_copy, "."); - attribute = (char *) strtok(NULL, "."); - - - /* fetch tuple OID */ - - left_side_argument = not_in_arg; - - /* Open the relation and get a relation descriptor */ - - namestrcpy(&relNameData,relation); - relation_to_scan = heap_openr(relNameData.data); - attrid = my_varattno(relation_to_scan, attribute); - - /* the last argument should be a ScanKey, not an integer! - jolly*/ - /* it looks like the arguments are out of order, too */ - /* but skeyData is never initialized! does this work?? - ay 2/95 */ - scan_descriptor = heap_beginscan(relation_to_scan, false, NULL, 0, - &skeyData); - - retval = true; - - /* do a scan of the relation, and do the check */ - for (current_tuple = heap_getnext(scan_descriptor, 0, NULL); - current_tuple != NULL && retval; - current_tuple = heap_getnext(scan_descriptor, 0, NULL)) + Relation relation_to_scan; + int left_side_argument, + integer_value; + HeapTuple current_tuple; + HeapScanDesc scan_descriptor; + bool dummy, + retval; + int attrid; + char *relation, + *attribute; + char my_copy[32]; + Datum value; + NameData relNameData; + ScanKeyData skeyData; + + strcpy(my_copy, relation_and_attr); + + relation = (char *) strtok(my_copy, "."); + attribute = (char *) strtok(NULL, "."); + + + /* fetch tuple OID */ + + left_side_argument = not_in_arg; + + /* Open the relation and get a relation descriptor */ + + namestrcpy(&relNameData, relation); + relation_to_scan = heap_openr(relNameData.data); + attrid = my_varattno(relation_to_scan, attribute); + + /* the last argument should be a ScanKey, not an integer! - jolly */ + /* it looks like the arguments are out of order, too */ + /* but skeyData is never initialized! does this work?? - ay 2/95 */ + scan_descriptor = heap_beginscan(relation_to_scan, false, NULL, 0, + &skeyData); + + retval = true; + + /* do a scan of the relation, and do the check */ + for (current_tuple = heap_getnext(scan_descriptor, 0, NULL); + current_tuple != NULL && retval; + current_tuple = heap_getnext(scan_descriptor, 0, NULL)) { - value = PointerGetDatum(heap_getattr(current_tuple, - InvalidBuffer, - (AttrNumber) attrid, - RelationGetTupleDescriptor(relation_to_scan), - &dummy)); - - integer_value = DatumGetInt16(value); - if (left_side_argument == integer_value) + value = PointerGetDatum(heap_getattr(current_tuple, + InvalidBuffer, + (AttrNumber) attrid, + RelationGetTupleDescriptor(relation_to_scan), + &dummy)); + + integer_value = DatumGetInt16(value); + if (left_side_argument == integer_value) { - retval = false; + retval = false; } } - - /* close the relation */ - heap_close(relation_to_scan); - return(retval); + + /* close the relation */ + heap_close(relation_to_scan); + return (retval); } -bool oidnotin(Oid the_oid, char *compare) +bool +oidnotin(Oid the_oid, char *compare) { - if (the_oid == InvalidOid) - return false; - return(int4notin(the_oid, compare)); + if (the_oid == InvalidOid) + return false; + return (int4notin(the_oid, compare)); } /* @@ -109,15 +113,17 @@ bool oidnotin(Oid the_oid, char *compare) * If varattno (in parser/catalog_utils.h) ever is added to * cinterface.a, this routine should go away */ -static int my_varattno(Relation rd, char *a) +static int +my_varattno(Relation rd, char *a) { - int i; - - for (i = 0; i < rd->rd_rel->relnatts; i++) { - if (!namestrcmp(&rd->rd_att->attrs[i]->attname, a)) { - return(i+1); + int i; + + for (i = 0; i < rd->rd_rel->relnatts; i++) + { + if (!namestrcmp(&rd->rd_att->attrs[i]->attname, a)) + { + return (i + 1); + } } - } - return(-1); + return (-1); } - diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c index 7f14317a700..3fd4ae382be 100644 --- a/src/backend/utils/adt/numutils.c +++ b/src/backend/utils/adt/numutils.c @@ -1,410 +1,449 @@ /*------------------------------------------------------------------------- * * numutils.c-- - * utility functions for I/O of built-in numeric types. + * utility functions for I/O of built-in numeric types. * - * integer: itoa, ltoa - * floating point: ftoa, atof1 + * integer: itoa, ltoa + * floating point: ftoa, atof1 * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/numutils.c,v 1.13 1997/08/19 21:34:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/numutils.c,v 1.14 1997/09/07 04:50:33 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <errno.h> #include <math.h> #include "postgres.h" #include "utils/builtins.h" /* where the declarations go */ #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif -#include <port-protos.h> /* ecvt(), fcvt() */ +#include <port-protos.h> /* ecvt(), fcvt() */ int32 pg_atoi(char *s, int size, int c) { - long l; - char *badp = (char *) NULL; - - Assert(s); - - errno = 0; - l = strtol(s, &badp, 10); - if (errno) /* strtol must set ERANGE */ - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); - if (badp && *badp && (*badp != c)) - elog(WARN, "pg_atoi: error in \"%s\": can\'t parse \"%s\"", s, badp); - - switch (size) { - case sizeof(int32): + long l; + char *badp = (char *) NULL; + + Assert(s); + + errno = 0; + l = strtol(s, &badp, 10); + if (errno) /* strtol must set ERANGE */ + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + if (badp && *badp && (*badp != c)) + elog(WARN, "pg_atoi: error in \"%s\": can\'t parse \"%s\"", s, badp); + + switch (size) + { + case sizeof(int32): #ifdef HAS_LONG_LONG - /* won't get ERANGE on these with 64-bit longs... */ - if (l < -0x80000000L) { - errno = ERANGE; - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); - } - if (l > 0x7fffffffL) { - errno = ERANGE; - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); - } -#endif /* HAS_LONG_LONG */ - break; - case sizeof(int16): - if (l < -0x8000) { - errno = ERANGE; - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); - } - if (l > 0x7fff) { - errno = ERANGE; - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); - } - break; - case sizeof(int8): - if (l < -0x80) { - errno = ERANGE; - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); - } - if (l > 0x7f) { - errno = ERANGE; - elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + /* won't get ERANGE on these with 64-bit longs... */ + if (l < -0x80000000L) + { + errno = ERANGE; + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + } + if (l > 0x7fffffffL) + { + errno = ERANGE; + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + } +#endif /* HAS_LONG_LONG */ + break; + case sizeof(int16): + if (l < -0x8000) + { + errno = ERANGE; + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + } + if (l > 0x7fff) + { + errno = ERANGE; + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + } + break; + case sizeof(int8): + if (l < -0x80) + { + errno = ERANGE; + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + } + if (l > 0x7f) + { + errno = ERANGE; + elog(WARN, "pg_atoi: error reading \"%s\": %m", s); + } + break; + default: + elog(WARN, "pg_atoi: invalid result size: %d", size); } - break; - default: - elog(WARN, "pg_atoi: invalid result size: %d", size); - } - return((int32) l); + return ((int32) l); } /* - * itoa - converts a short int to its string represention + * itoa - converts a short int to its string represention * - * Note: - * previously based on ~ingres/source/gutil/atoi.c - * now uses vendor's sprintf conversion + * Note: + * previously based on ~ingres/source/gutil/atoi.c + * now uses vendor's sprintf conversion */ void itoa(int i, char *a) { - sprintf(a, "%hd", (short)i); + sprintf(a, "%hd", (short) i); } /* - * ltoa - converts a long int to its string represention + * ltoa - converts a long int to its string represention * - * Note: - * previously based on ~ingres/source/gutil/atoi.c - * now uses vendor's sprintf conversion + * Note: + * previously based on ~ingres/source/gutil/atoi.c + * now uses vendor's sprintf conversion */ void ltoa(int32 l, char *a) { - sprintf(a, "%d", l); + sprintf(a, "%d", l); } /* - ** ftoa - FLOATING POINT TO ASCII CONVERSION + ** ftoa - FLOATING POINT TO ASCII CONVERSION ** - ** CODE derived from ingres, ~ingres/source/gutil/ftoa.c + ** CODE derived from ingres, ~ingres/source/gutil/ftoa.c ** - ** 'Value' is converted to an ascii character string and stored - ** into 'ascii'. Ascii should have room for at least 'width' + 1 - ** characters. 'Width' is the width of the output field (max). - ** 'Prec' is the number of characters to put after the decimal - ** point. The format of the output string is controlled by - ** 'format'. + ** 'Value' is converted to an ascii character string and stored + ** into 'ascii'. Ascii should have room for at least 'width' + 1 + ** characters. 'Width' is the width of the output field (max). + ** 'Prec' is the number of characters to put after the decimal + ** point. The format of the output string is controlled by + ** 'format'. ** - ** 'Format' can be: - ** e or E: "E" format output - ** f or F: "F" format output - ** g or G: "F" format output if it will fit, otherwise - ** use "E" format. - ** n or N: same as G, but decimal points will not always - ** be aligned. + ** 'Format' can be: + ** e or E: "E" format output + ** f or F: "F" format output + ** g or G: "F" format output if it will fit, otherwise + ** use "E" format. + ** n or N: same as G, but decimal points will not always + ** be aligned. ** - ** If 'format' is upper case, the "E" comes out in upper case; - ** otherwise it comes out in lower case. + ** If 'format' is upper case, the "E" comes out in upper case; + ** otherwise it comes out in lower case. ** - ** When the field width is not big enough, it fills the field with - ** stars ("*****") and returns zero. Normal return is the width - ** of the output field (sometimes shorter than 'width'). + ** When the field width is not big enough, it fills the field with + ** stars ("*****") and returns zero. Normal return is the width + ** of the output field (sometimes shorter than 'width'). */ #ifdef NOT_USED int ftoa(double value, char *ascii, int width, int prec1, char format) { #ifndef HAVE_FCVT - char out[256]; - char fmt[256]; - int ret; + char out[256]; + char fmt[256]; + int ret; sprintf(fmt, "%%%d.%d%c", width, prec1, format); sprintf(out, fmt, value); - if ((ret = strlen(out)) > width) { + if ((ret = strlen(out)) > width) + { memset(ascii, '*', width - 2); ascii[width] = 0; - return(0); + return (0); } strcpy(ascii, out); - return(ret); + return (ret); #else - auto int expon; - auto int sign; - register int avail = 0; - register char *a = NULL; - register char *p = NULL; - char mode; - int lowercase; - int prec; -/* extern char *ecvt(), *fcvt();*/ - - prec = prec1; - mode = format; - lowercase = 'a' - 'A'; - if (mode >= 'a') - mode -= 'a' - 'A'; - else - lowercase = 0; - - if (mode != 'E') { - /* try 'F' style output */ - p = fcvt(value, prec, &expon, &sign); - avail = width; - a = ascii; - - /* output sign */ - if (sign) { - avail--; - *a++ = '-'; + auto int expon; + auto int sign; + register int avail = 0; + register char *a = NULL; + register char *p = NULL; + char mode; + int lowercase; + int prec; + +/* extern char *ecvt(), *fcvt();*/ + + prec = prec1; + mode = format; + lowercase = 'a' - 'A'; + if (mode >= 'a') + mode -= 'a' - 'A'; + else + lowercase = 0; + + if (mode != 'E') + { + /* try 'F' style output */ + p = fcvt(value, prec, &expon, &sign); + avail = width; + a = ascii; + + /* output sign */ + if (sign) + { + avail--; + *a++ = '-'; + } + + /* output '0' before the decimal point */ + if (expon <= 0) + { + *a++ = '0'; + avail--; + } + + /* compute space length left after dec pt and fraction */ + avail -= prec + 1; + if (mode == 'G') + avail -= 4; + + if (avail >= expon) + { + + /* it fits. output */ + while (expon > 0) + { + /* output left of dp */ + expon--; + if (*p) + { + *a++ = *p++; + } + else + *a++ = '0'; + } + + /* output fraction (right of dec pt) */ + avail = expon; + goto frac_out; + } + /* won't fit; let's hope for G format */ } - - /* output '0' before the decimal point */ - if (expon <= 0) { - *a++ = '0'; - avail--; + + if (mode != 'F') + { + /* try to do E style output */ + p = ecvt(value, prec + 1, &expon, &sign); + avail = width - 5; + a = ascii; + + /* output the sign */ + if (sign) + { + *a++ = '-'; + avail--; + } } - - /* compute space length left after dec pt and fraction */ - avail -= prec + 1; - if (mode == 'G') - avail -= 4; - - if (avail >= expon) { - - /* it fits. output */ - while (expon > 0) { - /* output left of dp */ - expon--; - if (*p) { - *a++ = *p++; - } else - *a++ = '0'; - } - - /* output fraction (right of dec pt) */ - avail = expon; - goto frac_out; + + /* check for field too small */ + if (mode == 'F' || avail < prec) + { + /* sorry joker, you lose */ + a = ascii; + for (avail = width; avail > 0; avail--) + *a++ = '*'; + *a = 0; + return (0); } - /* won't fit; let's hope for G format */ - } - - if (mode != 'F') { - /* try to do E style output */ - p = ecvt(value, prec + 1, &expon, &sign); - avail = width - 5; - a = ascii; - - /* output the sign */ - if (sign) { - *a++ = '-'; - avail--; + + /* it fits; output the number */ + mode = 'E'; + + /* output the LHS single digit */ + *a++ = *p++; + expon--; + + /* output the rhs */ + avail = 1; + +frac_out: + *a++ = '.'; + while (prec > 0) + { + prec--; + if (avail < 0) + { + avail++; + *a++ = '0'; + } + else + { + if (*p) + *a++ = *p++; + else + *a++ = '0'; + } } - } - - /* check for field too small */ - if (mode == 'F' || avail < prec) { - /* sorry joker, you lose */ - a = ascii; - for (avail = width; avail > 0; avail--) - *a++ = '*'; - *a = 0; - return (0); - } - - /* it fits; output the number */ - mode = 'E'; - - /* output the LHS single digit */ - *a++ = *p++; - expon--; - - /* output the rhs */ - avail = 1; - - frac_out: - *a++ = '.'; - while (prec > 0) { - prec--; - if (avail < 0) { - avail++; - *a++ = '0'; - } else { - if (*p) - *a++ = *p++; - else - *a++ = '0'; + + /* output the exponent */ + if (mode == 'E') + { + *a++ = 'E' + lowercase; + if (expon < 0) + { + *a++ = '-'; + expon = -expon; + } + else + *a++ = '+'; + *a++ = (expon / 10) % 10 + '0'; + *a++ = expon % 10 + '0'; } - } - - /* output the exponent */ - if (mode == 'E') { - *a++ = 'E' + lowercase; - if (expon < 0) { - *a++ = '-'; - expon = -expon; - } else - *a++ = '+'; - *a++ = (expon / 10) % 10 + '0'; - *a++ = expon % 10 + '0'; - } - - /* output spaces on the end in G format */ - if (mode == 'G') { - *a++ = ' '; - *a++ = ' '; - *a++ = ' '; - *a++ = ' '; - } - - /* finally, we can return */ - *a = 0; - avail = a - ascii; - return (avail); -#endif /* !BSD44_derived */ + + /* output spaces on the end in G format */ + if (mode == 'G') + { + *a++ = ' '; + *a++ = ' '; + *a++ = ' '; + *a++ = ' '; + } + + /* finally, we can return */ + *a = 0; + avail = a - ascii; + return (avail); +#endif /* !BSD44_derived */ } + #endif /* - ** atof1 - ASCII TO FLOATING CONVERSION + ** atof1 - ASCII TO FLOATING CONVERSION ** - ** CODE derived from ~ingres/source/gutil/atof.c + ** CODE derived from ~ingres/source/gutil/atof.c ** - ** Converts the string 'str' to floating point and stores the - ** result into the cell pointed to by 'val'. + ** Converts the string 'str' to floating point and stores the + ** result into the cell pointed to by 'val'. ** - ** The syntax which it accepts is pretty much what you would - ** expect. Basically, it is: - ** {<sp>} [+|-] {<sp>} {<digit>} [.{digit}] {<sp>} [<exp>] - ** where <exp> is "e" or "E" followed by an integer, <sp> is a - ** space character, <digit> is zero through nine, [] is zero or - ** one, and {} is zero or more. + ** The syntax which it accepts is pretty much what you would + ** expect. Basically, it is: + ** {<sp>} [+|-] {<sp>} {<digit>} [.{digit}] {<sp>} [<exp>] + ** where <exp> is "e" or "E" followed by an integer, <sp> is a + ** space character, <digit> is zero through nine, [] is zero or + ** one, and {} is zero or more. ** - ** Parameters: - ** str -- string to convert. - ** val -- pointer to place to put the result (which - ** must be type double). + ** Parameters: + ** str -- string to convert. + ** val -- pointer to place to put the result (which + ** must be type double). ** - ** Returns: - ** zero -- ok. - ** -1 -- syntax error. - ** +1 -- overflow (not implemented). + ** Returns: + ** zero -- ok. + ** -1 -- syntax error. + ** +1 -- overflow (not implemented). ** - ** Side Effects: - ** clobbers *val. + ** Side Effects: + ** clobbers *val. */ #ifdef NOT_USED int atof1(char *str, double *val) { - register char *p; - double v; - double fact; - int minus; - register char c; - int expon; - register int gotmant; - - v = 0.0; - p = str; - minus = 0; - - /* skip leading blanks */ - while ((c = *p) != '\0') { - if (c != ' ') - break; - p++; - } - - /* handle possible sign */ - switch (c) { - case '-': - minus++; - - case '+': - p++; - } - - /* skip blanks after sign */ - while ((c = *p) != '\0') { - if (c != ' ') - break; - p++; - } - - /* start collecting the number to the decimal point */ - gotmant = 0; - for (;;) { - c = *p; - if (c < '0' || c > '9') - break; - v = v * 10.0 + (c - '0'); - gotmant++; - p++; - } - - /* check for fractional part */ - if (c == '.') { - fact = 1.0; - for (;;) { - c = *++p; - if (c < '0' || c > '9') - break; - fact *= 0.1; - v += (c - '0') * fact; - gotmant++; + register char *p; + double v; + double fact; + int minus; + register char c; + int expon; + register int gotmant; + + v = 0.0; + p = str; + minus = 0; + + /* skip leading blanks */ + while ((c = *p) != '\0') + { + if (c != ' ') + break; + p++; + } + + /* handle possible sign */ + switch (c) + { + case '-': + minus++; + + case '+': + p++; } - } - - /* skip blanks before possible exponent */ - while ((c = *p) != '\0') { - if (c != ' ') - break; - p++; - } - - /* test for exponent */ - if (c == 'e' || c == 'E') { - p++; - expon = pg_atoi(p, sizeof(expon), '\0'); - if (!gotmant) - v = 1.0; - fact = expon; - v *= pow(10.0, fact); - } else { - /* if no exponent, then nothing */ - if (c != 0) - return (-1); - } - - /* store the result and exit */ - if (minus) - v = -v; - *val = v; - return (0); + + /* skip blanks after sign */ + while ((c = *p) != '\0') + { + if (c != ' ') + break; + p++; + } + + /* start collecting the number to the decimal point */ + gotmant = 0; + for (;;) + { + c = *p; + if (c < '0' || c > '9') + break; + v = v * 10.0 + (c - '0'); + gotmant++; + p++; + } + + /* check for fractional part */ + if (c == '.') + { + fact = 1.0; + for (;;) + { + c = *++p; + if (c < '0' || c > '9') + break; + fact *= 0.1; + v += (c - '0') * fact; + gotmant++; + } + } + + /* skip blanks before possible exponent */ + while ((c = *p) != '\0') + { + if (c != ' ') + break; + p++; + } + + /* test for exponent */ + if (c == 'e' || c == 'E') + { + p++; + expon = pg_atoi(p, sizeof(expon), '\0'); + if (!gotmant) + v = 1.0; + fact = expon; + v *= pow(10.0, fact); + } + else + { + /* if no exponent, then nothing */ + if (c != 0) + return (-1); + } + + /* store the result and exit */ + if (minus) + v = -v; + *val = v; + return (0); } + #endif diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index 977fe87fbca..864c272c793 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * oid.c-- - * Functions for the built-in type Oid. + * Functions for the built-in type Oid. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.8 1997/08/24 23:07:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.9 1997/09/07 04:50:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,114 +16,125 @@ #include <string.h> #include "postgres.h" -#include "utils/builtins.h" /* where function declarations go */ +#include "utils/builtins.h" /* where function declarations go */ -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* - * oid8in - converts "num num ..." to internal form + * oid8in - converts "num num ..." to internal form * - * Note: - * Fills any nonexistent digits with NULL oids. + * Note: + * Fills any nonexistent digits with NULL oids. */ -Oid *oid8in(char *oidString) +Oid * +oid8in(char *oidString) { - register Oid (*result)[]; - int nums; - - if (oidString == NULL) - return(NULL); - result = (Oid (*)[]) palloc(sizeof(Oid [8])); - if ((nums = sscanf(oidString, "%d%d%d%d%d%d%d%d", - &(*result)[0], - &(*result)[1], - &(*result)[2], - &(*result)[3], - &(*result)[4], - &(*result)[5], - &(*result)[6], - &(*result)[7])) != 8) { - do - (*result)[nums++] = 0; - while (nums < 8); - } - return((Oid *) result); + register Oid(*result)[]; + int nums; + + if (oidString == NULL) + return (NULL); + result = (Oid(*)[]) palloc(sizeof(Oid[8])); + if ((nums = sscanf(oidString, "%d%d%d%d%d%d%d%d", + &(*result)[0], + &(*result)[1], + &(*result)[2], + &(*result)[3], + &(*result)[4], + &(*result)[5], + &(*result)[6], + &(*result)[7])) != 8) + { + do + (*result)[nums++] = 0; + while (nums < 8); + } + return ((Oid *) result); } /* - * oid8out - converts internal form to "num num ..." + * oid8out - converts internal form to "num num ..." */ -char *oid8out(Oid (*oidArray)[]) +char * +oid8out(Oid(*oidArray)[]) { - register int num; - register Oid *sp; - register char *rp; - char *result; - - if (oidArray == NULL) { - result = (char *) palloc(2); - result[0] = '-'; - result[1] = '\0'; - return(result); - } - - /* assumes sign, 10 digits, ' ' */ - rp = result = (char *) palloc(8 * 12); - sp = *oidArray; - for (num = 8; num != 0; num--) { - ltoa(*sp++, rp); - while (*++rp != '\0') - ; - *rp++ = ' '; - } - *--rp = '\0'; - return(result); + register int num; + register Oid *sp; + register char *rp; + char *result; + + if (oidArray == NULL) + { + result = (char *) palloc(2); + result[0] = '-'; + result[1] = '\0'; + return (result); + } + + /* assumes sign, 10 digits, ' ' */ + rp = result = (char *) palloc(8 * 12); + sp = *oidArray; + for (num = 8; num != 0; num--) + { + ltoa(*sp++, rp); + while (*++rp != '\0') + ; + *rp++ = ' '; + } + *--rp = '\0'; + return (result); } -Oid oidin(char *s) +Oid +oidin(char *s) { - return(int4in(s)); + return (int4in(s)); } -char *oidout(Oid o) +char * +oidout(Oid o) { - return(int4out(o)); + return (int4out(o)); } -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ /* * If you change this function, change heap_keytest() * because we have hardcoded this in there as an optimization */ -bool oideq(Oid arg1, Oid arg2) +bool +oideq(Oid arg1, Oid arg2) { - return(arg1 == arg2); + return (arg1 == arg2); } -bool oidne(Oid arg1, Oid arg2) +bool +oidne(Oid arg1, Oid arg2) { - return(arg1 != arg2); + return (arg1 != arg2); } -bool oid8eq(Oid arg1[], Oid arg2[]) +bool +oid8eq(Oid arg1[], Oid arg2[]) { - return (bool)(memcmp(arg1, arg2, 8 * sizeof(Oid)) == 0); + return (bool) (memcmp(arg1, arg2, 8 * sizeof(Oid)) == 0); } -bool oideqint4(Oid arg1, int32 arg2) +bool +oideqint4(Oid arg1, int32 arg2) { /* oid is unsigned, but int4 is signed */ - return (arg2 >= 0 && arg1 == arg2); + return (arg2 >= 0 && arg1 == arg2); } -bool int4eqoid(int32 arg1, Oid arg2) +bool +int4eqoid(int32 arg1, Oid arg2) { /* oid is unsigned, but int4 is signed */ - return (arg1 >= 0 && arg1 == arg2); + return (arg1 >= 0 && arg1 == arg2); } - diff --git a/src/backend/utils/adt/oidint2.c b/src/backend/utils/adt/oidint2.c index 4d92821e8d8..009ab233f78 100644 --- a/src/backend/utils/adt/oidint2.c +++ b/src/backend/utils/adt/oidint2.c @@ -1,120 +1,120 @@ /*------------------------------------------------------------------------- * * oidint2.c-- - * Functions for the built-in type "oidint2". + * Functions for the built-in type "oidint2". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/oidint2.c,v 1.1.1.1 1996/07/09 06:22:05 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/oidint2.c,v 1.2 1997/09/07 04:50:35 momjian Exp $ * *------------------------------------------------------------------------- */ #include <stdio.h> #include "postgres.h" #include "utils/palloc.h" -#include "utils/builtins.h" /* for pg_atoi() */ +#include "utils/builtins.h" /* for pg_atoi() */ #include "utils/oidcompos.h" /* where function declarations go */ OidInt2 oidint2in(char *o) { - OidInt2 oi; - char *p; - - oi = (OidInt2) palloc(sizeof(OidInt2Data)); - - for (p = o; *p != '\0' && *p != '/'; p++) - continue; - - oi->oi_oid = (Oid) pg_atoi(o, sizeof(Oid), '/'); - if (*p == '\0') { - oi->oi_int2 = 0; - } else { - oi->oi_int2 = (int16) pg_atoi(++p, sizeof(int2), '\0'); - } - - return (oi); + OidInt2 oi; + char *p; + + oi = (OidInt2) palloc(sizeof(OidInt2Data)); + + for (p = o; *p != '\0' && *p != '/'; p++) + continue; + + oi->oi_oid = (Oid) pg_atoi(o, sizeof(Oid), '/'); + if (*p == '\0') + { + oi->oi_int2 = 0; + } + else + { + oi->oi_int2 = (int16) pg_atoi(++p, sizeof(int2), '\0'); + } + + return (oi); } -char * +char * oidint2out(OidInt2 o) { - char *r; - - /* - * -2147483647/-32767 - * 0 1 - * 1234567890123456789 - */ - r = (char *) palloc(19); - sprintf(r, "%d/%d", o->oi_oid, o->oi_int2); - - return (r); + char *r; + + /* + * -2147483647/-32767 0 1 1234567890123456789 + */ + r = (char *) palloc(19); + sprintf(r, "%d/%d", o->oi_oid, o->oi_int2); + + return (r); } bool oidint2lt(OidInt2 o1, OidInt2 o2) { - return - ((bool) (o1->oi_oid < o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int2 < o2->oi_int2))); + return + ((bool) (o1->oi_oid < o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int2 < o2->oi_int2))); } bool oidint2le(OidInt2 o1, OidInt2 o2) { - return ((bool) (o1->oi_oid < o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int2 <= o2->oi_int2))); + return ((bool) (o1->oi_oid < o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int2 <= o2->oi_int2))); } bool oidint2eq(OidInt2 o1, OidInt2 o2) { - return ((bool) (o1->oi_oid == o2->oi_oid && o1->oi_int2 == o2->oi_int2)); + return ((bool) (o1->oi_oid == o2->oi_oid && o1->oi_int2 == o2->oi_int2)); } bool oidint2ge(OidInt2 o1, OidInt2 o2) { - return ((bool) (o1->oi_oid > o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int2 >= o2->oi_int2))); + return ((bool) (o1->oi_oid > o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int2 >= o2->oi_int2))); } bool oidint2gt(OidInt2 o1, OidInt2 o2) { - return ((bool) (o1->oi_oid > o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int2 > o2->oi_int2))); + return ((bool) (o1->oi_oid > o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int2 > o2->oi_int2))); } bool oidint2ne(OidInt2 o1, OidInt2 o2) { - return ((bool) (o1->oi_oid != o2->oi_oid || o1->oi_int2 != o2->oi_int2)); + return ((bool) (o1->oi_oid != o2->oi_oid || o1->oi_int2 != o2->oi_int2)); } int oidint2cmp(OidInt2 o1, OidInt2 o2) { - if (oidint2lt(o1, o2)) - return (-1); - else if (oidint2eq(o1, o2)) - return (0); - else - return (1); + if (oidint2lt(o1, o2)) + return (-1); + else if (oidint2eq(o1, o2)) + return (0); + else + return (1); } OidInt2 mkoidint2(Oid v_oid, uint16 v_int2) { - OidInt2 o; - - o = (OidInt2) palloc(sizeof(OidInt2Data)); - o->oi_oid = v_oid; - o->oi_int2 = v_int2; - return (o); -} + OidInt2 o; + o = (OidInt2) palloc(sizeof(OidInt2Data)); + o->oi_oid = v_oid; + o->oi_int2 = v_int2; + return (o); +} diff --git a/src/backend/utils/adt/oidint4.c b/src/backend/utils/adt/oidint4.c index d0844411a73..c4da5141acf 100644 --- a/src/backend/utils/adt/oidint4.c +++ b/src/backend/utils/adt/oidint4.c @@ -1,111 +1,120 @@ /*------------------------------------------------------------------------- * * oidint4.c-- - * Functions for the built-in type "oidint4". + * Functions for the built-in type "oidint4". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/oidint4.c,v 1.1.1.1 1996/07/09 06:22:05 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/oidint4.c,v 1.2 1997/09/07 04:50:36 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include "postgres.h" #include "utils/palloc.h" #include "utils/builtins.h" #include "utils/oidcompos.h" /* where function declarations go */ -OidInt4 oidint4in(char *o) +OidInt4 +oidint4in(char *o) { - OidInt4 oi; - char *p; - - oi = (OidInt4) palloc(sizeof(OidInt4Data)); - - for (p = o; *p != '\0' && *p != '/'; p++) - continue; - - oi->oi_oid = (Oid) pg_atoi(o, sizeof(Oid), '/'); - if (*p == '\0') { - oi->oi_int4 = 0; - } else { - oi->oi_int4 = pg_atoi(++p, sizeof(int4), '\0'); - } - - return (oi); + OidInt4 oi; + char *p; + + oi = (OidInt4) palloc(sizeof(OidInt4Data)); + + for (p = o; *p != '\0' && *p != '/'; p++) + continue; + + oi->oi_oid = (Oid) pg_atoi(o, sizeof(Oid), '/'); + if (*p == '\0') + { + oi->oi_int4 = 0; + } + else + { + oi->oi_int4 = pg_atoi(++p, sizeof(int4), '\0'); + } + + return (oi); } -char *oidint4out(OidInt4 o) +char * +oidint4out(OidInt4 o) { - char *r; - - /* - * -2147483647/-2147483647 - * 0 1 2 - * 123456789012345678901234 - */ - r = (char *) palloc(24); - sprintf(r, "%d/%d", o->oi_oid, o->oi_int4); - - return (r); + char *r; + + /* + * -2147483647/-2147483647 0 1 2 + * 123456789012345678901234 + */ + r = (char *) palloc(24); + sprintf(r, "%d/%d", o->oi_oid, o->oi_int4); + + return (r); } -bool oidint4lt(OidInt4 o1, OidInt4 o2) +bool +oidint4lt(OidInt4 o1, OidInt4 o2) { - return + return ((bool) (o1->oi_oid < o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int4 < o2->oi_int4))); + (o1->oi_oid == o2->oi_oid && o1->oi_int4 < o2->oi_int4))); } -bool oidint4le(OidInt4 o1, OidInt4 o2) +bool +oidint4le(OidInt4 o1, OidInt4 o2) { - return ((bool) (o1->oi_oid < o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int4 <= o2->oi_int4))); + return ((bool) (o1->oi_oid < o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int4 <= o2->oi_int4))); } -bool oidint4eq(OidInt4 o1, OidInt4 o2) +bool +oidint4eq(OidInt4 o1, OidInt4 o2) { - return ((bool) (o1->oi_oid == o2->oi_oid && o1->oi_int4 == o2->oi_int4)); + return ((bool) (o1->oi_oid == o2->oi_oid && o1->oi_int4 == o2->oi_int4)); } -bool oidint4ge(OidInt4 o1, OidInt4 o2) +bool +oidint4ge(OidInt4 o1, OidInt4 o2) { - return ((bool) (o1->oi_oid > o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int4 >= o2->oi_int4))); + return ((bool) (o1->oi_oid > o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int4 >= o2->oi_int4))); } -bool oidint4gt(OidInt4 o1, OidInt4 o2) +bool +oidint4gt(OidInt4 o1, OidInt4 o2) { - return ((bool) (o1->oi_oid > o2->oi_oid || - (o1->oi_oid == o2->oi_oid && o1->oi_int4 > o2->oi_int4))); + return ((bool) (o1->oi_oid > o2->oi_oid || + (o1->oi_oid == o2->oi_oid && o1->oi_int4 > o2->oi_int4))); } -bool oidint4ne(OidInt4 o1, OidInt4 o2) +bool +oidint4ne(OidInt4 o1, OidInt4 o2) { - return ((bool) (o1->oi_oid != o2->oi_oid || o1->oi_int4 != o2->oi_int4)); + return ((bool) (o1->oi_oid != o2->oi_oid || o1->oi_int4 != o2->oi_int4)); } -int oidint4cmp(OidInt4 o1, OidInt4 o2) +int +oidint4cmp(OidInt4 o1, OidInt4 o2) { - if (oidint4lt(o1, o2)) - return (-1); - else if (oidint4eq(o1, o2)) - return (0); - else - return (1); + if (oidint4lt(o1, o2)) + return (-1); + else if (oidint4eq(o1, o2)) + return (0); + else + return (1); } -OidInt4 mkoidint4(Oid v_oid, uint32 v_int4) +OidInt4 +mkoidint4(Oid v_oid, uint32 v_int4) { - OidInt4 o; - - o = (OidInt4) palloc(sizeof(OidInt4Data)); - o->oi_oid = v_oid; - o->oi_int4 = v_int4; - return (o); -} - - + OidInt4 o; + o = (OidInt4) palloc(sizeof(OidInt4Data)); + o->oi_oid = v_oid; + o->oi_int4 = v_int4; + return (o); +} diff --git a/src/backend/utils/adt/oidname.c b/src/backend/utils/adt/oidname.c index 425fa78f65c..30a081f2531 100644 --- a/src/backend/utils/adt/oidname.c +++ b/src/backend/utils/adt/oidname.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * oidname.c-- - * adt for multiple key indices involving oid and name. Used for cache - * index scans (could also be used in the general case with name). + * adt for multiple key indices involving oid and name. Used for cache + * index scans (could also be used in the general case with name). * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/oidname.c,v 1.4 1997/08/12 20:16:03 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/oidname.c,v 1.5 1997/09/07 04:50:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,106 +17,109 @@ #include "postgres.h" #include "utils/oidcompos.h" /* where function declarations go */ -#include "utils/builtins.h" /* for pg_atoi() */ +#include "utils/builtins.h" /* for pg_atoi() */ #include "utils/palloc.h" OidName oidnamein(char *inStr) { - OidName oc; - char *inptr; - - oc = (OidName) palloc(sizeof(OidNameData)); - - memset(oc, 0, sizeof(OidNameData)); - for (inptr = inStr; *inptr && *inptr != ','; inptr++) - ; - - if (*inptr) { - oc->id = (Oid) pg_atoi(inStr, sizeof(Oid), ','); - /* copy one less to ensure null-padding */ - ++inptr; - strNcpy(oc->name.data,inptr,NAMEDATALEN-1); - }else - elog(WARN, "Bad input data for type oidname"); - - return oc; + OidName oc; + char *inptr; + + oc = (OidName) palloc(sizeof(OidNameData)); + + memset(oc, 0, sizeof(OidNameData)); + for (inptr = inStr; *inptr && *inptr != ','; inptr++) + ; + + if (*inptr) + { + oc->id = (Oid) pg_atoi(inStr, sizeof(Oid), ','); + /* copy one less to ensure null-padding */ + ++inptr; + strNcpy(oc->name.data, inptr, NAMEDATALEN - 1); + } + else + elog(WARN, "Bad input data for type oidname"); + + return oc; } -char * +char * oidnameout(OidName oidname) { - char buf[30+NAMEDATALEN]; /* oidname length + oid length + some safety */ - char *res; - - sprintf(buf, "%d,%s", oidname->id, oidname->name.data); - res = pstrdup(buf); - return(res); + char buf[30 + NAMEDATALEN]; /* oidname length + oid + * length + some safety */ + char *res; + + sprintf(buf, "%d,%s", oidname->id, oidname->name.data); + res = pstrdup(buf); + return (res); } bool oidnamelt(OidName o1, OidName o2) { - return (bool) - (o1->id < o2->id || - (o1->id == o2->id && namecmp(&o1->name, &o2->name) < 0)); + return (bool) + (o1->id < o2->id || + (o1->id == o2->id && namecmp(&o1->name, &o2->name) < 0)); } bool oidnamele(OidName o1, OidName o2) { - return (bool) - (o1->id < o2->id || - (o1->id == o2->id && namecmp(&o1->name,&o2->name) <= 0)); + return (bool) + (o1->id < o2->id || + (o1->id == o2->id && namecmp(&o1->name, &o2->name) <= 0)); } bool oidnameeq(OidName o1, OidName o2) { - return (bool) - (o1->id == o2->id && - (namecmp(&o1->name, &o2->name) == 0)); + return (bool) + (o1->id == o2->id && + (namecmp(&o1->name, &o2->name) == 0)); } bool oidnamene(OidName o1, OidName o2) { - return (bool) - (o1->id != o2->id || - (namecmp(&o1->name,&o2->name) != 0)); + return (bool) + (o1->id != o2->id || + (namecmp(&o1->name, &o2->name) != 0)); } bool oidnamege(OidName o1, OidName o2) { - return (bool) (o1->id > o2->id || (o1->id == o2->id && - namecmp(&o1->name, &o2->name) >= 0)); + return (bool) (o1->id > o2->id || (o1->id == o2->id && + namecmp(&o1->name, &o2->name) >= 0)); } bool oidnamegt(OidName o1, OidName o2) { - return (bool) (o1->id > o2->id || (o1->id == o2->id && - namecmp(&o1->name, &o2->name) > 0)); + return (bool) (o1->id > o2->id || (o1->id == o2->id && + namecmp(&o1->name, &o2->name) > 0)); } int oidnamecmp(OidName o1, OidName o2) { - if (o1->id == o2->id) - return (namecmp(&o1->name,&o2->name)); - - return (o1->id < o2->id) ? -1 : 1; + if (o1->id == o2->id) + return (namecmp(&o1->name, &o2->name)); + + return (o1->id < o2->id) ? -1 : 1; } OidName mkoidname(Oid id, char *name) { - OidName oidname; - - oidname = (OidName) palloc(sizeof(Oid)+NAMEDATALEN); - - oidname->id = id; - namestrcpy(&oidname->name,name); - return oidname; + OidName oidname; + + oidname = (OidName) palloc(sizeof(Oid) + NAMEDATALEN); + + oidname->id = id; + namestrcpy(&oidname->name, name); + return oidname; } diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 6082311c54a..99acb57b58f 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -1,7 +1,7 @@ /* - * Edmund Mergl <E.Mergl@bawue.de> + * Edmund Mergl <E.Mergl@bawue.de> * - * $Id: oracle_compat.c,v 1.7 1997/07/29 16:12:01 thomas Exp $ + * $Id: oracle_compat.c,v 1.8 1997/09/07 04:50:38 momjian Exp $ * */ @@ -10,16 +10,16 @@ #include "postgres.h" -text *lower(text *string); -text *upper(text *string); -text *initcap(text *string); -text *lpad(text *string1, int4 len, text *string2); -text *rpad(text *string1, int4 len, text *string2); -text *btrim(text *string, text *set); -text *ltrim(text *string, text *set); -text *rtrim(text *string, text *set); -text *substr(text *string, int4 m, int4 n); -text *translate(text *string, char from, char to); +text *lower(text * string); +text *upper(text * string); +text *initcap(text * string); +text *lpad(text * string1, int4 len, text * string2); +text *rpad(text * string1, int4 len, text * string2); +text *btrim(text * string, text * set); +text *ltrim(text * string, text * set); +text *rtrim(text * string, text * set); +text *substr(text * string, int4 m, int4 n); +text *translate(text * string, char from, char to); /******************************************************************** @@ -28,35 +28,37 @@ text *translate(text *string, char from, char to); * * Syntax: * - * text *lower(text *string) + * text *lower(text *string) * * Purpose: * - * Returns string, with all letters forced to lowercase. + * Returns string, with all letters forced to lowercase. * ********************************************************************/ -text * -lower(text *string) +text * +lower(text * string) { - text *ret; - char *ptr, *ptr_ret; - int m; + text *ret; + char *ptr, + *ptr_ret; + int m; - if ((string == (text *)NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) - return string; + if ((string == (text *) NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) + return string; - ret = (text *)palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); + ret = (text *) palloc(VARSIZE(string)); + VARSIZE(ret) = VARSIZE(string); - ptr = VARDATA(string); - ptr_ret = VARDATA(ret); + ptr = VARDATA(string); + ptr_ret = VARDATA(ret); - while (m--) { - *ptr_ret++ = tolower(*ptr++); - } + while (m--) + { + *ptr_ret++ = tolower(*ptr++); + } - return ret; + return ret; } @@ -66,35 +68,37 @@ lower(text *string) * * Syntax: * - * text *upper(text *string) + * text *upper(text *string) * * Purpose: * - * Returns string, with all letters forced to uppercase. + * Returns string, with all letters forced to uppercase. * ********************************************************************/ -text * -upper(text *string) +text * +upper(text * string) { - text *ret; - char *ptr, *ptr_ret; - int m; + text *ret; + char *ptr, + *ptr_ret; + int m; - if ((string == (text *)NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) - return string; + if ((string == (text *) NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) + return string; - ret = (text *)palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); + ret = (text *) palloc(VARSIZE(string)); + VARSIZE(ret) = VARSIZE(string); - ptr = VARDATA(string); - ptr_ret = VARDATA(ret); + ptr = VARDATA(string); + ptr_ret = VARDATA(ret); - while (m--) { - *ptr_ret++ = toupper(*ptr++); - } + while (m--) + { + *ptr_ret++ = toupper(*ptr++); + } - return ret; + return ret; } @@ -104,44 +108,49 @@ upper(text *string) * * Syntax: * - * text *initcap(text *string) + * text *initcap(text *string) * * Purpose: * - * Returns string, with first letter of each word in uppercase, - * all other letters in lowercase. A word is delimited by white - * space. + * Returns string, with first letter of each word in uppercase, + * all other letters in lowercase. A word is delimited by white + * space. * ********************************************************************/ -text * -initcap(text *string) +text * +initcap(text * string) { - text *ret; - char *ptr, *ptr_ret; - int m; - - if ((string == (text *)NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) - return string; - - ret = (text *)palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); - - ptr = VARDATA(string); - ptr_ret = VARDATA(ret); - - *ptr_ret++ = toupper(*ptr++); - --m; - - while (m--) { - if (*(ptr_ret - 1) == ' ' || *(ptr_ret - 1) == ' ') { - *ptr_ret++ = toupper(*ptr++); - } else { - *ptr_ret++ = tolower(*ptr++); - } - } - - return ret; + text *ret; + char *ptr, + *ptr_ret; + int m; + + if ((string == (text *) NULL) || ((m = VARSIZE(string) - VARHDRSZ) <= 0)) + return string; + + ret = (text *) palloc(VARSIZE(string)); + VARSIZE(ret) = VARSIZE(string); + + ptr = VARDATA(string); + ptr_ret = VARDATA(ret); + + *ptr_ret++ = toupper(*ptr++); + --m; + + while (m--) + { + if (*(ptr_ret - 1) == ' ' || *(ptr_ret - 1) == ' ') + { + *ptr_ret++ = toupper(*ptr++); + } + else + { + *ptr_ret++ = tolower(*ptr++); + } + } + + return ret; } @@ -151,48 +160,53 @@ initcap(text *string) * * Syntax: * - * text *lpad(text *string1, int4 len, text *string2) + * text *lpad(text *string1, int4 len, text *string2) * * Purpose: * - * Returns string1, left-padded to length len with the sequence of - * characters in string2. + * Returns string1, left-padded to length len with the sequence of + * characters in string2. * ********************************************************************/ -text * -lpad(text *string1, int4 len, text *string2) +text * +lpad(text * string1, int4 len, text * string2) { - text *ret; - char *ptr1, *ptr2, *ptr_ret; - int m, n; - - if ((string1 == (text *)NULL) || - (len <= (VARSIZE(string1) - VARHDRSZ)) || - ((m = len - VARSIZE(string1) + VARHDRSZ) <= 0) || - (string2 == (text *)NULL) || - ((VARSIZE(string2) - VARHDRSZ) <= 0)) - return string1; - - ret = (text *)palloc(VARHDRSZ + len); - VARSIZE(ret) = VARHDRSZ + len; - - ptr2 = VARDATA(string2); - ptr_ret = VARDATA(ret); - - while (m--) { - *ptr_ret++ = *ptr2; - ptr2 = ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1 ? VARDATA(string2) : ++ptr2; - } - - n = VARSIZE(string1) - VARHDRSZ; - ptr1 = VARDATA(string1); - - while (n--) { - *ptr_ret++ = *ptr1++; - } - - return ret; + text *ret; + char *ptr1, + *ptr2, + *ptr_ret; + int m, + n; + + if ((string1 == (text *) NULL) || + (len <= (VARSIZE(string1) - VARHDRSZ)) || + ((m = len - VARSIZE(string1) + VARHDRSZ) <= 0) || + (string2 == (text *) NULL) || + ((VARSIZE(string2) - VARHDRSZ) <= 0)) + return string1; + + ret = (text *) palloc(VARHDRSZ + len); + VARSIZE(ret) = VARHDRSZ + len; + + ptr2 = VARDATA(string2); + ptr_ret = VARDATA(ret); + + while (m--) + { + *ptr_ret++ = *ptr2; + ptr2 = ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1 ? VARDATA(string2) : ++ptr2; + } + + n = VARSIZE(string1) - VARHDRSZ; + ptr1 = VARDATA(string1); + + while (n--) + { + *ptr_ret++ = *ptr1++; + } + + return ret; } @@ -202,48 +216,53 @@ lpad(text *string1, int4 len, text *string2) * * Syntax: * - * text *rpad(text *string1, int4 len, text *string2) + * text *rpad(text *string1, int4 len, text *string2) * * Purpose: * - * Returns string1, right-padded to length len with the sequence of - * characters in string2. + * Returns string1, right-padded to length len with the sequence of + * characters in string2. * ********************************************************************/ -text * -rpad(text *string1, int4 len, text *string2) +text * +rpad(text * string1, int4 len, text * string2) { - text *ret; - char *ptr1, *ptr2, *ptr_ret; - int m, n; - - if ((string1 == (text *)NULL) || - (len <= (VARSIZE(string1) - VARHDRSZ)) || - ((m = len - VARSIZE(string1) + VARHDRSZ) <= 0) || - (string2 == (text *)NULL) || - ((VARSIZE(string2) - VARHDRSZ) <= 0)) - return string1; - - ret = (text *)palloc(VARHDRSZ + len); - VARSIZE(ret) = VARHDRSZ + len; - - n = VARSIZE(string1) - VARHDRSZ; - ptr1 = VARDATA(string1); - ptr_ret = VARDATA(ret); - - while (n--) { - *ptr_ret++ = *ptr1++; - } - - ptr2 = VARDATA(string2); - - while (m--) { - *ptr_ret++ = *ptr2; - ptr2 = ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1 ? VARDATA(string2) : ++ptr2; - } - - return ret; + text *ret; + char *ptr1, + *ptr2, + *ptr_ret; + int m, + n; + + if ((string1 == (text *) NULL) || + (len <= (VARSIZE(string1) - VARHDRSZ)) || + ((m = len - VARSIZE(string1) + VARHDRSZ) <= 0) || + (string2 == (text *) NULL) || + ((VARSIZE(string2) - VARHDRSZ) <= 0)) + return string1; + + ret = (text *) palloc(VARHDRSZ + len); + VARSIZE(ret) = VARHDRSZ + len; + + n = VARSIZE(string1) - VARHDRSZ; + ptr1 = VARDATA(string1); + ptr_ret = VARDATA(ret); + + while (n--) + { + *ptr_ret++ = *ptr1++; + } + + ptr2 = VARDATA(string2); + + while (m--) + { + *ptr_ret++ = *ptr2; + ptr2 = ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1 ? VARDATA(string2) : ++ptr2; + } + + return ret; } @@ -253,73 +272,84 @@ rpad(text *string1, int4 len, text *string2) * * Syntax: * - * text *btrim(text *string, text *set) + * text *btrim(text *string, text *set) * * Purpose: * - * Returns string with characters removed from the front and back - * up to the first character not in set. + * Returns string with characters removed from the front and back + * up to the first character not in set. * ********************************************************************/ -text * -btrim(text *string, text *set) +text * +btrim(text * string, text * set) { - text *ret; - char *ptr, *end, *ptr2, *end2; - int m; - - if ((string == (text *)NULL) || - ((m = VARSIZE(string) - VARHDRSZ) <= 0) || - (set == (text *)NULL) || - ((VARSIZE(set) - VARHDRSZ) <= 0)) - return string; - - ptr = VARDATA(string); - ptr2 = VARDATA(set); - end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; - - while (m--) { - while (ptr2 <= end2) { - if (*ptr == *ptr2) { - break; - } - ++ptr2; - } - if (*ptr != *ptr2) { - break; - } - ptr++; - ptr2 = VARDATA(set); - } - - ++m; - - end = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1; - ptr2 = VARDATA(set); - - while (m--) { - while (ptr2 <= end2) { - if (*end == *ptr2) { - break; - } - ++ptr2; - } - if (*end != *ptr2) { - break; - } - --end; - ptr2 = VARDATA(set); - } - - ++m; - - ret = (text *)palloc(VARHDRSZ + m); - VARSIZE(ret) = VARHDRSZ + m; - memcpy(VARDATA(ret),ptr,m); - - return ret; -} /* btrim() */ + text *ret; + char *ptr, + *end, + *ptr2, + *end2; + int m; + + if ((string == (text *) NULL) || + ((m = VARSIZE(string) - VARHDRSZ) <= 0) || + (set == (text *) NULL) || + ((VARSIZE(set) - VARHDRSZ) <= 0)) + return string; + + ptr = VARDATA(string); + ptr2 = VARDATA(set); + end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; + + while (m--) + { + while (ptr2 <= end2) + { + if (*ptr == *ptr2) + { + break; + } + ++ptr2; + } + if (*ptr != *ptr2) + { + break; + } + ptr++; + ptr2 = VARDATA(set); + } + + ++m; + + end = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1; + ptr2 = VARDATA(set); + + while (m--) + { + while (ptr2 <= end2) + { + if (*end == *ptr2) + { + break; + } + ++ptr2; + } + if (*end != *ptr2) + { + break; + } + --end; + ptr2 = VARDATA(set); + } + + ++m; + + ret = (text *) palloc(VARHDRSZ + m); + VARSIZE(ret) = VARHDRSZ + m; + memcpy(VARDATA(ret), ptr, m); + + return ret; +} /* btrim() */ /******************************************************************** @@ -328,54 +358,60 @@ btrim(text *string, text *set) * * Syntax: * - * text *ltrim(text *string, text *set) + * text *ltrim(text *string, text *set) * * Purpose: * - * Returns string with initial characters removed up to the first - * character not in set. + * Returns string with initial characters removed up to the first + * character not in set. * ********************************************************************/ -text * -ltrim(text *string, text *set) +text * +ltrim(text * string, text * set) { - text *ret; - char *ptr, *ptr2, *end2; - int m; - - if ((string == (text *)NULL) || - ((m = VARSIZE(string) - VARHDRSZ) <= 0) || - (set == (text *)NULL) || - ((VARSIZE(set) - VARHDRSZ) <= 0)) - return string; - - ptr = VARDATA(string); - ptr2 = VARDATA(set); - end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; - - while (m--) { - while (ptr2 <= end2) { - if (*ptr == *ptr2) { - break; - } - ++ptr2; - } - if (*ptr != *ptr2) { - break; - } - ptr++; - ptr2 = VARDATA(set); - } - - ++m; - - ret = (text *)palloc(VARHDRSZ + m); - VARSIZE(ret) = VARHDRSZ + m; - - memcpy(VARDATA(ret),ptr,m); - - return ret; + text *ret; + char *ptr, + *ptr2, + *end2; + int m; + + if ((string == (text *) NULL) || + ((m = VARSIZE(string) - VARHDRSZ) <= 0) || + (set == (text *) NULL) || + ((VARSIZE(set) - VARHDRSZ) <= 0)) + return string; + + ptr = VARDATA(string); + ptr2 = VARDATA(set); + end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; + + while (m--) + { + while (ptr2 <= end2) + { + if (*ptr == *ptr2) + { + break; + } + ++ptr2; + } + if (*ptr != *ptr2) + { + break; + } + ptr++; + ptr2 = VARDATA(set); + } + + ++m; + + ret = (text *) palloc(VARHDRSZ + m); + VARSIZE(ret) = VARHDRSZ + m; + + memcpy(VARDATA(ret), ptr, m); + + return ret; } @@ -385,61 +421,69 @@ ltrim(text *string, text *set) * * Syntax: * - * text *rtrim(text *string, text *set) + * text *rtrim(text *string, text *set) * * Purpose: * - * Returns string with final characters removed after the last - * character not in set. + * Returns string with final characters removed after the last + * character not in set. * ********************************************************************/ -text * -rtrim(text *string, text *set) +text * +rtrim(text * string, text * set) { - text *ret; - char *ptr, *ptr2, *end2, *ptr_ret; - int m; - - if ((string == (text *)NULL) || - ((m = VARSIZE(string) - VARHDRSZ) <= 0) || - (set == (text *)NULL) || - ((VARSIZE(set) - VARHDRSZ) <= 0)) - return string; - - ptr = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1; - ptr2 = VARDATA(set); - end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; - - while (m--) { - while (ptr2 <= end2) { - if (*ptr == *ptr2) { - break; - } - ++ptr2; - } - if (*ptr != *ptr2) { - break; - } - --ptr; - ptr2 = VARDATA(set); - } - - ++m; - - ret = (text *)palloc(VARHDRSZ + m); - VARSIZE(ret) = VARHDRSZ + m; + text *ret; + char *ptr, + *ptr2, + *end2, + *ptr_ret; + int m; + + if ((string == (text *) NULL) || + ((m = VARSIZE(string) - VARHDRSZ) <= 0) || + (set == (text *) NULL) || + ((VARSIZE(set) - VARHDRSZ) <= 0)) + return string; + + ptr = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1; + ptr2 = VARDATA(set); + end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; + + while (m--) + { + while (ptr2 <= end2) + { + if (*ptr == *ptr2) + { + break; + } + ++ptr2; + } + if (*ptr != *ptr2) + { + break; + } + --ptr; + ptr2 = VARDATA(set); + } + + ++m; + + ret = (text *) palloc(VARHDRSZ + m); + VARSIZE(ret) = VARHDRSZ + m; #if FALSE - memcpy(VARDATA(ret),ptr-VARSIZE(ret)+m,m); + memcpy(VARDATA(ret), ptr - VARSIZE(ret) + m, m); #endif - ptr_ret = VARDATA(ret) + m - 1; + ptr_ret = VARDATA(ret) + m - 1; - while (m--) { - *ptr_ret-- = *ptr--; - } + while (m--) + { + *ptr_ret-- = *ptr--; + } - return ret; + return ret; } @@ -449,40 +493,42 @@ rtrim(text *string, text *set) * * Syntax: * - * text *substr(text *string, int4 m, int4 n) + * text *substr(text *string, int4 m, int4 n) * * Purpose: * - * Returns a portion of string, beginning at character m, n - * characters long. The first position of string is 1. + * Returns a portion of string, beginning at character m, n + * characters long. The first position of string is 1. * ********************************************************************/ -text * -substr(text *string, int4 m, int4 n) +text * +substr(text * string, int4 m, int4 n) { - text *ret; - char *ptr, *ptr_ret; - int len; + text *ret; + char *ptr, + *ptr_ret; + int len; - if ((string == (text *)NULL) || - (m <= 0) || (n <= 0) || - ((len = VARSIZE(string) - VARHDRSZ - m) <= 0)) - return string; + if ((string == (text *) NULL) || + (m <= 0) || (n <= 0) || + ((len = VARSIZE(string) - VARHDRSZ - m) <= 0)) + return string; - len = len + 1 < n ? len + 1 : n; + len = len + 1 < n ? len + 1 : n; - ret = (text *)palloc(VARHDRSZ + len); - VARSIZE(ret) = VARHDRSZ + len; + ret = (text *) palloc(VARHDRSZ + len); + VARSIZE(ret) = VARHDRSZ + len; - ptr = VARDATA(string) + m - 1; - ptr_ret = VARDATA(ret); + ptr = VARDATA(string) + m - 1; + ptr_ret = VARDATA(ret); - while (len--) { - *ptr_ret++ = *ptr++; - } + while (len--) + { + *ptr_ret++ = *ptr++; + } - return ret; + return ret; } @@ -492,39 +538,41 @@ substr(text *string, int4 m, int4 n) * * Syntax: * - * text *translate(text *string, char from, char to) + * text *translate(text *string, char from, char to) * * Purpose: * - * Returns string after replacing all occurences of from with - * the corresponding character in to. TRANSLATE will not remove - * characters. + * Returns string after replacing all occurences of from with + * the corresponding character in to. TRANSLATE will not remove + * characters. * ********************************************************************/ -text * -translate(text *string, char from, char to) +text * +translate(text * string, char from, char to) { - text *ret; - char *ptr, *ptr_ret; - int m; + text *ret; + char *ptr, + *ptr_ret; + int m; - if ((string == (text *)NULL) || - ((m = VARSIZE(string) - VARHDRSZ) <= 0)) - return string; + if ((string == (text *) NULL) || + ((m = VARSIZE(string) - VARHDRSZ) <= 0)) + return string; - ret = (text *)palloc(VARSIZE(string)); - VARSIZE(ret) = VARSIZE(string); + ret = (text *) palloc(VARSIZE(string)); + VARSIZE(ret) = VARSIZE(string); - ptr = VARDATA(string); - ptr_ret = VARDATA(ret); + ptr = VARDATA(string); + ptr_ret = VARDATA(ret); - while (m--) { - *ptr_ret++ = *ptr == from ? to : *ptr; - ptr++; - } + while (m--) + { + *ptr_ret++ = *ptr == from ? to : *ptr; + ptr++; + } - return ret; + return ret; } diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c index a0d61b8304c..e7d982785ba 100644 --- a/src/backend/utils/adt/regexp.c +++ b/src/backend/utils/adt/regexp.c @@ -1,42 +1,42 @@ /*------------------------------------------------------------------------- * * regexp.c-- - * regular expression handling code. + * regular expression handling code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regexp.c,v 1.7 1997/08/12 22:54:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/regexp.c,v 1.8 1997/09/07 04:50:39 momjian Exp $ * - * Alistair Crooks added the code for the regex caching - * agc - cached the regular expressions used - there's a good chance - * that we'll get a hit, so this saves a compile step for every - * attempted match. I haven't actually measured the speed improvement, - * but it `looks' a lot quicker visually when watching regression - * test output. + * Alistair Crooks added the code for the regex caching + * agc - cached the regular expressions used - there's a good chance + * that we'll get a hit, so this saves a compile step for every + * attempted match. I haven't actually measured the speed improvement, + * but it `looks' a lot quicker visually when watching regression + * test output. * - * agc - incorporated Keith Bostic's Berkeley regex code into - * the tree for all ports. To distinguish this regex code from any that - * is existent on a platform, I've prepended the string "pg95_" to - * the functions regcomp, regerror, regexec and regfree. - * Fixed a bug that was originally a typo by me, where `i' was used - * instead of `oldest' when compiling regular expressions - benign - * results mostly, although occasionally it bit you... + * agc - incorporated Keith Bostic's Berkeley regex code into + * the tree for all ports. To distinguish this regex code from any that + * is existent on a platform, I've prepended the string "pg95_" to + * the functions regcomp, regerror, regexec and regfree. + * Fixed a bug that was originally a typo by me, where `i' was used + * instead of `oldest' when compiling regular expressions - benign + * results mostly, although occasionally it bit you... * * *------------------------------------------------------------------------- */ #include <string.h> -#include "postgres.h" /* postgres system include file */ +#include "postgres.h" /* postgres system include file */ #include <regex/regex.h> -#include "utils/builtins.h" /* where the function declarations go */ +#include "utils/builtins.h" /* where the function declarations go */ #if defined(DISABLE_XOPEN_NLS) #undef _XOPEN_SOURCE -#endif /* DISABLE_XOPEN_NLS */ +#endif /* DISABLE_XOPEN_NLS */ /* this is the number of cached regular expressions held. */ #ifndef MAX_CACHED_RES @@ -44,297 +44,329 @@ #endif /* this structure describes a cached regular expression */ -struct cached_re_str { - struct varlena *cre_text; /* pattern as a text* */ - char *cre_s; /* pattern as null-terminated string */ - int cre_type; /* compiled-type: extended,icase etc */ - regex_t cre_re; /* the compiled regular expression */ +struct cached_re_str +{ + struct varlena *cre_text; /* pattern as a text* */ + char *cre_s; /* pattern as null-terminated string */ + int cre_type; /* compiled-type: extended,icase etc */ + regex_t cre_re; /* the compiled regular expression */ unsigned long cre_lru; /* lru tag */ }; -static int rec = 0; /* # of cached re's */ -static struct cached_re_str rev[MAX_CACHED_RES]; /* cached re's */ -static unsigned long lru; /* system lru tag */ +static int rec = 0; /* # of cached re's */ +static struct cached_re_str rev[MAX_CACHED_RES]; /* cached re's */ +static unsigned long lru; /* system lru tag */ /* attempt to compile `re' as an re, then match it against text */ /* cflags - flag to regcomp indicates case sensitivity */ static int -RE_compile_and_execute(struct varlena *text_re, char *text, int cflags) +RE_compile_and_execute(struct varlena * text_re, char *text, int cflags) { - int oldest; - int n; - int i; - char *re; - int regcomp_result; - - re = textout(text_re); - /* find a previously compiled regular expression */ - for (i = 0 ; i < rec ; i++) { - if (rev[i].cre_s) { - if (strcmp(rev[i].cre_s, re) == 0) { - if (rev[i].cre_type == cflags) { - rev[i].cre_lru = ++lru; - pfree(re); - return(pg95_regexec(&rev[i].cre_re, - text, 0, - (regmatch_t *) NULL, 0) == 0); - } + int oldest; + int n; + int i; + char *re; + int regcomp_result; + + re = textout(text_re); + /* find a previously compiled regular expression */ + for (i = 0; i < rec; i++) + { + if (rev[i].cre_s) + { + if (strcmp(rev[i].cre_s, re) == 0) + { + if (rev[i].cre_type == cflags) + { + rev[i].cre_lru = ++lru; + pfree(re); + return (pg95_regexec(&rev[i].cre_re, + text, 0, + (regmatch_t *) NULL, 0) == 0); + } + } } - } - } - + } + /* we didn't find it - make room in the cache for it */ - if (rec == MAX_CACHED_RES) { + if (rec == MAX_CACHED_RES) + { /* cache is full - find the oldest entry */ - for (oldest = 0, i = 1 ; i < rec ; i++) { - if (rev[i].cre_lru < rev[oldest].cre_lru) { + for (oldest = 0, i = 1; i < rec; i++) + { + if (rev[i].cre_lru < rev[oldest].cre_lru) + { oldest = i; } } - } else { + } + else + { oldest = rec++; } /* if there was an old re, then de-allocate the space it used */ - if (rev[oldest].cre_s != (char *) NULL) { - for (lru = i = 0 ; i < rec ; i++) { + if (rev[oldest].cre_s != (char *) NULL) + { + for (lru = i = 0; i < rec; i++) + { rev[i].cre_lru = (rev[i].cre_lru - rev[oldest].cre_lru) / 2; - if (rev[i].cre_lru > lru) { + if (rev[i].cre_lru > lru) + { lru = rev[i].cre_lru; } - } + } pg95_regfree(&rev[oldest].cre_re); - /* use malloc/free for the cre_s field because the storage - has to persist across transactions */ - free(rev[oldest].cre_s); + + /* + * use malloc/free for the cre_s field because the storage has to + * persist across transactions + */ + free(rev[oldest].cre_s); } /* compile the re */ regcomp_result = pg95_regcomp(&rev[oldest].cre_re, re, cflags); - if ( regcomp_result == 0) { + if (regcomp_result == 0) + { n = strlen(re); - /* use malloc/free for the cre_s field because the storage - has to persist across transactions */ + + /* + * use malloc/free for the cre_s field because the storage has to + * persist across transactions + */ rev[oldest].cre_s = (char *) malloc(n + 1); memmove(rev[oldest].cre_s, re, n); rev[oldest].cre_s[n] = 0; - rev[oldest].cre_text = text_re; + rev[oldest].cre_text = text_re; rev[oldest].cre_lru = ++lru; - rev[oldest].cre_type = cflags; + rev[oldest].cre_type = cflags; pfree(re); - /* agc - fixed an old typo here */ - return(pg95_regexec(&rev[oldest].cre_re, text, 0, - (regmatch_t *) NULL, 0) == 0); - } else { - char errMsg[1000]; - /* re didn't compile */ - rev[oldest].cre_s = (char *) NULL; - pg95_regerror(regcomp_result, &rev[oldest].cre_re, errMsg, - sizeof(errMsg)); - elog(WARN,"regcomp failed with error %s",errMsg); + /* agc - fixed an old typo here */ + return (pg95_regexec(&rev[oldest].cre_re, text, 0, + (regmatch_t *) NULL, 0) == 0); + } + else + { + char errMsg[1000]; + + /* re didn't compile */ + rev[oldest].cre_s = (char *) NULL; + pg95_regerror(regcomp_result, &rev[oldest].cre_re, errMsg, + sizeof(errMsg)); + elog(WARN, "regcomp failed with error %s", errMsg); } /* not reached */ - return(0); + return (0); } /* - * interface routines called by the function manager + * interface routines called by the function manager */ /* fixedlen_regexeq: a generic fixed length regexp routine - s - the string to match against (not necessarily null-terminated) - p - the pattern - charlen - the length of the string + s - the string to match against (not necessarily null-terminated) + p - the pattern + charlen - the length of the string */ -static bool -fixedlen_regexeq(char *s, struct varlena* p, int charlen, int cflags) +static bool +fixedlen_regexeq(char *s, struct varlena * p, int charlen, int cflags) { - char *sterm; - int result; - - if (!s || !p) - return FALSE; - - /* be sure sterm is null-terminated */ - sterm = (char *) palloc(charlen + 1); - strNcpy(sterm, s, charlen); - - result = RE_compile_and_execute(p, sterm, cflags); - - pfree(sterm); - - return ((bool) result); + char *sterm; + int result; + + if (!s || !p) + return FALSE; + + /* be sure sterm is null-terminated */ + sterm = (char *) palloc(charlen + 1); + strNcpy(sterm, s, charlen); + + result = RE_compile_and_execute(p, sterm, cflags); + + pfree(sterm); + + return ((bool) result); } /* - * routines that use the regexp stuff + * routines that use the regexp stuff */ -bool -char2regexeq(uint16 arg1, struct varlena *p) +bool +char2regexeq(uint16 arg1, struct varlena * p) { - char *s = (char *) &arg1; - return (fixedlen_regexeq(s, p, 2, REG_EXTENDED)); + char *s = (char *) &arg1; + + return (fixedlen_regexeq(s, p, 2, REG_EXTENDED)); } -bool -char2regexne(uint16 arg1, struct varlena *p) +bool +char2regexne(uint16 arg1, struct varlena * p) { - return (!char2regexeq(arg1, p)); + return (!char2regexeq(arg1, p)); } -bool -char4regexeq(uint32 arg1, struct varlena *p) +bool +char4regexeq(uint32 arg1, struct varlena * p) { - char *s = (char *) &arg1; - return (fixedlen_regexeq(s, p, 4, REG_EXTENDED)); + char *s = (char *) &arg1; + + return (fixedlen_regexeq(s, p, 4, REG_EXTENDED)); } -bool -char4regexne(uint32 arg1, struct varlena *p) +bool +char4regexne(uint32 arg1, struct varlena * p) { - return (!char4regexeq(arg1, p)); + return (!char4regexeq(arg1, p)); } -bool -char8regexeq(char *s, struct varlena *p) +bool +char8regexeq(char *s, struct varlena * p) { - return (fixedlen_regexeq(s, p, 8, REG_EXTENDED)); + return (fixedlen_regexeq(s, p, 8, REG_EXTENDED)); } -bool -char8regexne(char *s, struct varlena *p) +bool +char8regexne(char *s, struct varlena * p) { - return (!char8regexeq(s, p)); + return (!char8regexeq(s, p)); } -bool -char16regexeq(char *s, struct varlena *p) +bool +char16regexeq(char *s, struct varlena * p) { - return (fixedlen_regexeq(s, p, 16, REG_EXTENDED)); + return (fixedlen_regexeq(s, p, 16, REG_EXTENDED)); } -bool -char16regexne(char *s, struct varlena *p) +bool +char16regexne(char *s, struct varlena * p) { - return (!char16regexeq(s, p)); + return (!char16regexeq(s, p)); } -bool -nameregexeq(NameData *n, struct varlena *p) +bool +nameregexeq(NameData * n, struct varlena * p) { - if (!n) return FALSE; - return (fixedlen_regexeq(n->data, p, NAMEDATALEN, REG_EXTENDED)); + if (!n) + return FALSE; + return (fixedlen_regexeq(n->data, p, NAMEDATALEN, REG_EXTENDED)); } -bool -nameregexne(NameData *s, struct varlena *p) + +bool +nameregexne(NameData * s, struct varlena * p) { - return (!nameregexeq(s, p)); + return (!nameregexeq(s, p)); } -bool -textregexeq(struct varlena *s, struct varlena *p) +bool +textregexeq(struct varlena * s, struct varlena * p) { - if (!s) return (FALSE); - return (fixedlen_regexeq(VARDATA(s), p, VARSIZE(s) - VARHDRSZ, REG_EXTENDED)); + if (!s) + return (FALSE); + return (fixedlen_regexeq(VARDATA(s), p, VARSIZE(s) - VARHDRSZ, REG_EXTENDED)); } -bool -textregexne(struct varlena *s, struct varlena *p) +bool +textregexne(struct varlena * s, struct varlena * p) { - return (!textregexeq(s, p)); + return (!textregexeq(s, p)); } /* * routines that use the regexp stuff, but ignore the case. - * for this, we use the REG_ICASE flag to pg95_regcomp + * for this, we use the REG_ICASE flag to pg95_regcomp */ -bool -char2icregexeq(uint16 arg1, struct varlena *p) +bool +char2icregexeq(uint16 arg1, struct varlena * p) { - char *s = (char *) &arg1; - return (fixedlen_regexeq(s, p, 2, REG_ICASE | REG_EXTENDED)); + char *s = (char *) &arg1; + + return (fixedlen_regexeq(s, p, 2, REG_ICASE | REG_EXTENDED)); } - -bool -char2icregexne(uint16 arg1, struct varlena *p) + +bool +char2icregexne(uint16 arg1, struct varlena * p) { - return (!char2icregexeq(arg1, p)); + return (!char2icregexeq(arg1, p)); } -bool -char4icregexeq(uint32 arg1, struct varlena *p) +bool +char4icregexeq(uint32 arg1, struct varlena * p) { - char *s = (char *) &arg1; - return (fixedlen_regexeq(s, p, 4, REG_ICASE | REG_EXTENDED )); + char *s = (char *) &arg1; + + return (fixedlen_regexeq(s, p, 4, REG_ICASE | REG_EXTENDED)); } -bool -char4icregexne(uint32 arg1, struct varlena *p) +bool +char4icregexne(uint32 arg1, struct varlena * p) { - return (!char4icregexeq(arg1, p)); + return (!char4icregexeq(arg1, p)); } - -bool -char8icregexeq(char *s, struct varlena *p) + +bool +char8icregexeq(char *s, struct varlena * p) { - return (fixedlen_regexeq(s, p, 8, REG_ICASE | REG_EXTENDED)); + return (fixedlen_regexeq(s, p, 8, REG_ICASE | REG_EXTENDED)); } -bool -char8icregexne(char *s, struct varlena *p) +bool +char8icregexne(char *s, struct varlena * p) { - return (!char8icregexeq(s, p)); + return (!char8icregexeq(s, p)); } -bool -char16icregexeq(char *s, struct varlena *p) +bool +char16icregexeq(char *s, struct varlena * p) { - return (fixedlen_regexeq(s, p, 16, REG_ICASE | REG_EXTENDED)); + return (fixedlen_regexeq(s, p, 16, REG_ICASE | REG_EXTENDED)); } -bool -char16icregexne(char *s, struct varlena *p) +bool +char16icregexne(char *s, struct varlena * p) { - return (!char16icregexeq(s, p)); + return (!char16icregexeq(s, p)); } -bool -texticregexeq(struct varlena *s, struct varlena *p) +bool +texticregexeq(struct varlena * s, struct varlena * p) { - if (!s) return FALSE; - return (fixedlen_regexeq(VARDATA(s), p, VARSIZE(s) - VARHDRSZ, - REG_ICASE | REG_EXTENDED)); + if (!s) + return FALSE; + return (fixedlen_regexeq(VARDATA(s), p, VARSIZE(s) - VARHDRSZ, + REG_ICASE | REG_EXTENDED)); } -bool -texticregexne(struct varlena *s, struct varlena *p) +bool +texticregexne(struct varlena * s, struct varlena * p) { - return (!texticregexeq(s, p)); + return (!texticregexeq(s, p)); } -bool -nameicregexeq(NameData *n, struct varlena *p) +bool +nameicregexeq(NameData * n, struct varlena * p) { - if (!n) return FALSE; - return (fixedlen_regexeq(n->data, p, NAMEDATALEN, - REG_ICASE | REG_EXTENDED)); + if (!n) + return FALSE; + return (fixedlen_regexeq(n->data, p, NAMEDATALEN, + REG_ICASE | REG_EXTENDED)); } -bool -nameicregexne(NameData *s, struct varlena *p) + +bool +nameicregexne(NameData * s, struct varlena * p) { - return (!nameicregexeq(s, p)); + return (!nameicregexeq(s, p)); } - diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 04442cb42df..6a4e8b01e50 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * regproc.c-- - * Functions for the built-in type "RegProcedure". + * Functions for the built-in type "RegProcedure". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.5 1997/08/12 20:16:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.6 1997/09/07 04:50:41 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,129 +19,140 @@ #include "utils/palloc.h" #include "catalog/catname.h" -#include "utils/builtins.h" /* where function declarations go */ +#include "utils/builtins.h" /* where function declarations go */ -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ /* - * regprocin - converts "proname" to proid + * regprocin - converts "proname" to proid * - * proid of NULL signifies unknown + * proid of NULL signifies unknown */ -int32 regprocin(char *proname) +int32 +regprocin(char *proname) { - Relation proc; - HeapScanDesc procscan; - HeapTuple proctup; - ScanKeyData key; - RegProcedure result = (Oid)0; - bool isnull; - - if (proname == NULL) - return(0); - proc = heap_openr(ProcedureRelationName); - if (!RelationIsValid(proc)) { - elog(WARN, "regprocin: could not open %s", - ProcedureRelationName); - return(0); - } - ScanKeyEntryInitialize(&key, - (bits16)0, - (AttrNumber)1, - (RegProcedure)F_CHAR16EQ, - (Datum)proname); - - procscan = heap_beginscan(proc, 0, NowTimeQual, 1, &key); - if (!HeapScanIsValid(procscan)) { - heap_close(proc); - elog(WARN, "regprocin: could not being scan of %s", - ProcedureRelationName); - return(0); - } - proctup = heap_getnext(procscan, 0, (Buffer *) NULL); - switch (HeapTupleIsValid(proctup)) { - case 1: - result = (RegProcedure) heap_getattr(proctup, - InvalidBuffer, - ObjectIdAttributeNumber, - RelationGetTupleDescriptor(proc), - &isnull); - if (isnull) { - elog(FATAL, "regprocin: null procedure %s", proname); + Relation proc; + HeapScanDesc procscan; + HeapTuple proctup; + ScanKeyData key; + RegProcedure result = (Oid) 0; + bool isnull; + + if (proname == NULL) + return (0); + proc = heap_openr(ProcedureRelationName); + if (!RelationIsValid(proc)) + { + elog(WARN, "regprocin: could not open %s", + ProcedureRelationName); + return (0); + } + ScanKeyEntryInitialize(&key, + (bits16) 0, + (AttrNumber) 1, + (RegProcedure) F_CHAR16EQ, + (Datum) proname); + + procscan = heap_beginscan(proc, 0, NowTimeQual, 1, &key); + if (!HeapScanIsValid(procscan)) + { + heap_close(proc); + elog(WARN, "regprocin: could not being scan of %s", + ProcedureRelationName); + return (0); } - break; - case 0: - result = (RegProcedure) 0; + proctup = heap_getnext(procscan, 0, (Buffer *) NULL); + switch (HeapTupleIsValid(proctup)) + { + case 1: + result = (RegProcedure) heap_getattr(proctup, + InvalidBuffer, + ObjectIdAttributeNumber, + RelationGetTupleDescriptor(proc), + &isnull); + if (isnull) + { + elog(FATAL, "regprocin: null procedure %s", proname); + } + break; + case 0: + result = (RegProcedure) 0; #ifdef EBUG - elog(DEBUG, "regprocin: no such procedure %s", proname); -#endif /* defined(EBUG) */ - } - heap_endscan(procscan); - heap_close(proc); - return((int32) result); + elog(DEBUG, "regprocin: no such procedure %s", proname); +#endif /* defined(EBUG) */ + } + heap_endscan(procscan); + heap_close(proc); + return ((int32) result); } /* - * regprocout - converts proid to "proname" + * regprocout - converts proid to "proname" */ -char *regprocout(RegProcedure proid) +char * +regprocout(RegProcedure proid) { - Relation proc; - HeapScanDesc procscan; - HeapTuple proctup; - char *result; - ScanKeyData key; - - result = (char *)palloc(NAMEDATALEN); - proc = heap_openr(ProcedureRelationName); - if (!RelationIsValid(proc)) { - elog(WARN, "regprocout: could not open %s", - ProcedureRelationName); - return(0); - } - ScanKeyEntryInitialize(&key, - (bits16)0, - (AttrNumber)ObjectIdAttributeNumber, - (RegProcedure)F_INT4EQ, - (Datum)proid); - - procscan = heap_beginscan(proc, 0, NowTimeQual, 1, &key); - if (!HeapScanIsValid(procscan)) { - heap_close(proc); - elog(WARN, "regprocin: could not being scan of %s", - ProcedureRelationName); - return(0); - } - proctup = heap_getnext(procscan, 0, (Buffer *)NULL); - switch (HeapTupleIsValid(proctup)) { - char *s; - bool isnull; - case 1: - s = (char *) heap_getattr(proctup, InvalidBuffer, 1, - RelationGetTupleDescriptor(proc), &isnull); - if (!isnull) { - strNcpy(result, s, 16); - break; + Relation proc; + HeapScanDesc procscan; + HeapTuple proctup; + char *result; + ScanKeyData key; + + result = (char *) palloc(NAMEDATALEN); + proc = heap_openr(ProcedureRelationName); + if (!RelationIsValid(proc)) + { + elog(WARN, "regprocout: could not open %s", + ProcedureRelationName); + return (0); + } + ScanKeyEntryInitialize(&key, + (bits16) 0, + (AttrNumber) ObjectIdAttributeNumber, + (RegProcedure) F_INT4EQ, + (Datum) proid); + + procscan = heap_beginscan(proc, 0, NowTimeQual, 1, &key); + if (!HeapScanIsValid(procscan)) + { + heap_close(proc); + elog(WARN, "regprocin: could not being scan of %s", + ProcedureRelationName); + return (0); } - elog(FATAL, "regprocout: null procedure %d", proid); - /*FALLTHROUGH*/ - case 0: - result[0] = '-'; - result[1] = '\0'; + proctup = heap_getnext(procscan, 0, (Buffer *) NULL); + switch (HeapTupleIsValid(proctup)) + { + char *s; + bool isnull; + + case 1: + s = (char *) heap_getattr(proctup, InvalidBuffer, 1, + RelationGetTupleDescriptor(proc), &isnull); + if (!isnull) + { + strNcpy(result, s, 16); + break; + } + elog(FATAL, "regprocout: null procedure %d", proid); + /* FALLTHROUGH */ + case 0: + result[0] = '-'; + result[1] = '\0'; #ifdef EBUG - elog(DEBUG, "regprocout: no such procedure %d", proid); -#endif /* defined(EBUG) */ - } - heap_endscan(procscan); - heap_close(proc); - return(result); + elog(DEBUG, "regprocout: no such procedure %d", proid); +#endif /* defined(EBUG) */ + } + heap_endscan(procscan); + heap_close(proc); + return (result); } -/***************************************************************************** - * PUBLIC ROUTINES * +/***************************************************************************** + * PUBLIC ROUTINES * *****************************************************************************/ /* regproctooid() @@ -149,13 +160,13 @@ char *regprocout(RegProcedure proid) * Define RegprocToOid() as a macro in builtins.h. * Referenced in pg_proc.h. - tgl 97/04/26 */ -Oid regproctooid(RegProcedure rp) +Oid +regproctooid(RegProcedure rp) { - return (Oid)rp; + return (Oid) rp; } /* (see int.c for comparison/operation routines) */ /* ========== PRIVATE ROUTINES ========== */ - diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index fe90feda72d..3f8c225ca9e 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * selfuncs.c-- - * Selectivity functions for system catalogs and builtin types + * Selectivity functions for system catalogs and builtin types * - * These routines are registered in the operator catalog in the - * "oprrest" and "oprjoin" attributes. + * These routines are registered in the operator catalog in the + * "oprrest" and "oprjoin" attributes. * - * XXX check all the functions--I suspect them to be 1-based. + * XXX check all the functions--I suspect them to be 1-based. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.8 1997/08/21 03:02:04 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.9 1997/09/07 04:50:42 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -22,10 +22,10 @@ #include "postgres.h" #include "access/heapam.h" -#include "utils/tqual.h" /* for NowTimeQual */ +#include "utils/tqual.h" /* for NowTimeQual */ #include "fmgr.h" -#include "utils/builtins.h" /* for textout() prototype - and where the declarations go */ +#include "utils/builtins.h" /* for textout() prototype and where the + * declarations go */ #include "utils/palloc.h" #include "catalog/catname.h" @@ -34,580 +34,624 @@ #include "catalog/pg_statistic.h" /* N is not a valid var/constant or relation id */ -#define NONVALUE(N) ((N) == -1) +#define NONVALUE(N) ((N) == -1) -/* +/* * generalize the test for functional index selectivity request */ #define FunctionalSelectivity(nIndKeys,attNum) (attNum==InvalidAttrNumber) static float32data getattdisbursion(Oid relid, AttrNumber attnum); -static void gethilokey(Oid relid, AttrNumber attnum, Oid opid, - char **high, char **low); +static void +gethilokey(Oid relid, AttrNumber attnum, Oid opid, + char **high, char **low); /* - * eqsel - Selectivity of "=" for any data type. + * eqsel - Selectivity of "=" for any data type. */ float64 eqsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - if (NONVALUE(attno) || NONVALUE(relid)) - *result = 0.1; - else - *result = (float64data)getattdisbursion(relid, (int) attno); - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + if (NONVALUE(attno) || NONVALUE(relid)) + *result = 0.1; + else + *result = (float64data) getattdisbursion(relid, (int) attno); + return (result); } /* - * neqsel - Selectivity of "!=" for any data type. + * neqsel - Selectivity of "!=" for any data type. */ float64 neqsel(Oid opid, - Oid relid, - AttrNumber attno, - char *value, - int32 flag) + Oid relid, + AttrNumber attno, + char *value, + int32 flag) { - float64 result; - - result = eqsel(opid, relid, attno, value, flag); - *result = 1.0 - *result; - return(result); + float64 result; + + result = eqsel(opid, relid, attno, value, flag); + *result = 1.0 - *result; + return (result); } /* - * intltsel - Selectivity of "<" for integers. - * Should work for both longs and shorts. + * intltsel - Selectivity of "<" for integers. + * Should work for both longs and shorts. */ float64 intltsel(Oid opid, - Oid relid, - AttrNumber attno, - int32 value, - int32 flag) + Oid relid, + AttrNumber attno, + int32 value, + int32 flag) { - float64 result; - char *highchar, *lowchar; - long val, high, low, top, bottom; - - result = (float64) palloc(sizeof(float64data)); - if (NONVALUE(attno) || NONVALUE(relid)) - *result = 1.0 / 3; - else { - /* XXX val = atol(value);*/ - val = value; - gethilokey(relid, (int) attno, opid, &highchar, &lowchar); - if (*highchar == 'n' || *lowchar == 'n') { - *result = 1.0/3.0; - return (result); - } - high = atol(highchar); - low = atol(lowchar); - if ((flag & SEL_RIGHT && val < low) || - (!(flag & SEL_RIGHT) && val > high)) { - float32data nvals; - nvals = getattdisbursion(relid, (int) attno); - if (nvals == 0) - *result = 1.0 / 3.0; - else { - *result = 3.0 * (float64data)nvals; - if (*result > 1.0) - *result = 1; - } - }else { - bottom = high - low; - if (bottom == 0) - ++bottom; - if (flag & SEL_RIGHT) - top = val - low; - else - top = high - val; - if (top > bottom) - *result = 1.0; - else { - if (top == 0) - ++top; - *result = ((1.0 * top) / bottom); - } + float64 result; + char *highchar, + *lowchar; + long val, + high, + low, + top, + bottom; + + result = (float64) palloc(sizeof(float64data)); + if (NONVALUE(attno) || NONVALUE(relid)) + *result = 1.0 / 3; + else + { + /* XXX val = atol(value); */ + val = value; + gethilokey(relid, (int) attno, opid, &highchar, &lowchar); + if (*highchar == 'n' || *lowchar == 'n') + { + *result = 1.0 / 3.0; + return (result); + } + high = atol(highchar); + low = atol(lowchar); + if ((flag & SEL_RIGHT && val < low) || + (!(flag & SEL_RIGHT) && val > high)) + { + float32data nvals; + + nvals = getattdisbursion(relid, (int) attno); + if (nvals == 0) + *result = 1.0 / 3.0; + else + { + *result = 3.0 * (float64data) nvals; + if (*result > 1.0) + *result = 1; + } + } + else + { + bottom = high - low; + if (bottom == 0) + ++bottom; + if (flag & SEL_RIGHT) + top = val - low; + else + top = high - val; + if (top > bottom) + *result = 1.0; + else + { + if (top == 0) + ++top; + *result = ((1.0 * top) / bottom); + } + } } - } - return(result); + return (result); } /* - * intgtsel - Selectivity of ">" for integers. - * Should work for both longs and shorts. + * intgtsel - Selectivity of ">" for integers. + * Should work for both longs and shorts. */ float64 intgtsel(Oid opid, - Oid relid, - AttrNumber attno, - int32 value, - int32 flag) + Oid relid, + AttrNumber attno, + int32 value, + int32 flag) { - float64 result; - int notflag; - - if (flag & 0) - notflag = flag & ~SEL_RIGHT; - else - notflag = flag | SEL_RIGHT; - result = intltsel(opid, relid, attno, value, (int32) notflag); - return(result); + float64 result; + int notflag; + + if (flag & 0) + notflag = flag & ~SEL_RIGHT; + else + notflag = flag | SEL_RIGHT; + result = intltsel(opid, relid, attno, value, (int32) notflag); + return (result); } /* - * eqjoinsel - Join selectivity of "=" + * eqjoinsel - Join selectivity of "=" */ float64 eqjoinsel(Oid opid, - Oid relid1, - AttrNumber attno1, - Oid relid2, - AttrNumber attno2) + Oid relid1, + AttrNumber attno1, + Oid relid2, + AttrNumber attno2) { - float64 result; - float32data num1, num2, max; - - result = (float64) palloc(sizeof(float64data)); - if (NONVALUE(attno1) || NONVALUE(relid1) || - NONVALUE(attno2) || NONVALUE(relid2)) - *result = 0.1; - else { - num1 = getattdisbursion(relid1, (int) attno1); - num2 = getattdisbursion(relid2, (int) attno2); - max = (num1 > num2) ? num1 : num2; - if (max == 0) - *result = 1.0; + float64 result; + float32data num1, + num2, + max; + + result = (float64) palloc(sizeof(float64data)); + if (NONVALUE(attno1) || NONVALUE(relid1) || + NONVALUE(attno2) || NONVALUE(relid2)) + *result = 0.1; else - *result = (float64data)max; - } - return(result); + { + num1 = getattdisbursion(relid1, (int) attno1); + num2 = getattdisbursion(relid2, (int) attno2); + max = (num1 > num2) ? num1 : num2; + if (max == 0) + *result = 1.0; + else + *result = (float64data) max; + } + return (result); } /* - * neqjoinsel - Join selectivity of "!=" + * neqjoinsel - Join selectivity of "!=" */ float64 neqjoinsel(Oid opid, - Oid relid1, - AttrNumber attno1, - Oid relid2, - AttrNumber attno2) + Oid relid1, + AttrNumber attno1, + Oid relid2, + AttrNumber attno2) { - float64 result; - - result = eqjoinsel(opid, relid1, attno1, relid2, attno2); - *result = 1.0 - *result; - return(result); + float64 result; + + result = eqjoinsel(opid, relid1, attno1, relid2, attno2); + *result = 1.0 - *result; + return (result); } /* - * intltjoinsel - Join selectivity of "<" + * intltjoinsel - Join selectivity of "<" */ float64 intltjoinsel(Oid opid, - Oid relid1, - AttrNumber attno1, - Oid relid2, - AttrNumber attno2) + Oid relid1, + AttrNumber attno1, + Oid relid2, + AttrNumber attno2) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 3.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 3.0; + return (result); } /* - * intgtjoinsel - Join selectivity of ">" + * intgtjoinsel - Join selectivity of ">" */ float64 intgtjoinsel(Oid opid, - Oid relid1, - AttrNumber attno1, - Oid relid2, - AttrNumber attno2) + Oid relid1, + AttrNumber attno1, + Oid relid2, + AttrNumber attno2) { - float64 result; - - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 3.0; - return(result); + float64 result; + + result = (float64) palloc(sizeof(float64data)); + *result = 1.0 / 3.0; + return (result); } /* - * getattdisbursion - Retrieves the number of values within an attribute. + * getattdisbursion - Retrieves the number of values within an attribute. * - * Note: - * getattdisbursion and gethilokey both currently use keyed - * relation scans and amgetattr. Alternatively, - * the relation scan could be non-keyed and the tuple - * returned could be cast (struct X *) tuple + tuple->t_hoff. - * The first method is good for testing the implementation, - * but the second may ultimately be faster?!? In any case, - * using the cast instead of amgetattr would be - * more efficient. However, the cast will not work - * for gethilokey which accesses stahikey in struct statistic. + * Note: + * getattdisbursion and gethilokey both currently use keyed + * relation scans and amgetattr. Alternatively, + * the relation scan could be non-keyed and the tuple + * returned could be cast (struct X *) tuple + tuple->t_hoff. + * The first method is good for testing the implementation, + * but the second may ultimately be faster?!? In any case, + * using the cast instead of amgetattr would be + * more efficient. However, the cast will not work + * for gethilokey which accesses stahikey in struct statistic. */ -static float32data +static float32data getattdisbursion(Oid relid, AttrNumber attnum) { - HeapTuple atp; - float32data nvals; - int32 ntuples; - - atp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0,0); - if (!HeapTupleIsValid(atp)) { - elog(WARN, "getattdisbursion: no attribute tuple %d %d", - relid, attnum); - return(0); - } - nvals = ((AttributeTupleForm ) GETSTRUCT(atp))->attdisbursion; - if (nvals > 0) return(nvals); - - atp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(relid), - 0,0,0); - /* XXX -- use number of tuples as number of distinctive values - just for now, in case number of distinctive values is - not cached */ - if (!HeapTupleIsValid(atp)) { - elog(WARN, "getattdisbursion: no relation tuple %d", relid); - return(0); - } - ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; - /* Look above how nvals is used. - vadim 04/09/97 */ - if ( ntuples > 0 ) - nvals = 1.0 / ntuples; - - return(nvals); + HeapTuple atp; + float32data nvals; + int32 ntuples; + + atp = SearchSysCacheTuple(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); + if (!HeapTupleIsValid(atp)) + { + elog(WARN, "getattdisbursion: no attribute tuple %d %d", + relid, attnum); + return (0); + } + nvals = ((AttributeTupleForm) GETSTRUCT(atp))->attdisbursion; + if (nvals > 0) + return (nvals); + + atp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(relid), + 0, 0, 0); + + /* + * XXX -- use number of tuples as number of distinctive values just + * for now, in case number of distinctive values is not cached + */ + if (!HeapTupleIsValid(atp)) + { + elog(WARN, "getattdisbursion: no relation tuple %d", relid); + return (0); + } + ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; + /* Look above how nvals is used. - vadim 04/09/97 */ + if (ntuples > 0) + nvals = 1.0 / ntuples; + + return (nvals); } /* - * gethilokey - Returns a pointer to strings containing - * the high and low keys within an attribute. + * gethilokey - Returns a pointer to strings containing + * the high and low keys within an attribute. * - * Currently returns "0", and "0" in high and low if the statistic - * catalog does not contain the proper tuple. Eventually, the - * statistic demon should have the tuple maintained, and it should - * elog() if the tuple is missing. + * Currently returns "0", and "0" in high and low if the statistic + * catalog does not contain the proper tuple. Eventually, the + * statistic demon should have the tuple maintained, and it should + * elog() if the tuple is missing. * - * XXX Question: is this worth sticking in the catalog caches, - * or will this get invalidated too often? + * XXX Question: is this worth sticking in the catalog caches, + * or will this get invalidated too often? */ static void gethilokey(Oid relid, - AttrNumber attnum, - Oid opid, - char **high, - char **low) + AttrNumber attnum, + Oid opid, + char **high, + char **low) { - register Relation rdesc; - register HeapScanDesc sdesc; - static ScanKeyData key[3] = { - { 0, Anum_pg_statistic_starelid, F_OIDEQ }, - { 0, Anum_pg_statistic_staattnum, F_INT2EQ }, - { 0, Anum_pg_statistic_staop, F_OIDEQ } - }; - bool isnull; - HeapTuple tuple; - - rdesc = heap_openr(StatisticRelationName); - - key[0].sk_argument = ObjectIdGetDatum(relid); - key[1].sk_argument = Int16GetDatum((int16) attnum); - key[2].sk_argument = ObjectIdGetDatum(opid); - sdesc = heap_beginscan(rdesc, 0, NowTimeQual, 3, key); - tuple = heap_getnext(sdesc, 0, (Buffer *) NULL); - if (!HeapTupleIsValid(tuple)) { - *high = "n"; - *low = "n"; - /* XXX elog(WARN, "gethilokey: statistic tuple not found");*/ - return; - } - *high = textout((struct varlena *) - heap_getattr(tuple, - InvalidBuffer, - Anum_pg_statistic_stahikey, - RelationGetTupleDescriptor(rdesc), - &isnull)); - if (isnull) - elog(DEBUG, "gethilokey: high key is null"); - *low = textout((struct varlena *) - heap_getattr(tuple, - InvalidBuffer, - Anum_pg_statistic_stalokey, - RelationGetTupleDescriptor(rdesc), - &isnull)); - if (isnull) - elog(DEBUG, "gethilokey: low key is null"); - heap_endscan(sdesc); - heap_close(rdesc); + register Relation rdesc; + register HeapScanDesc sdesc; + static ScanKeyData key[3] = { + {0, Anum_pg_statistic_starelid, F_OIDEQ}, + {0, Anum_pg_statistic_staattnum, F_INT2EQ}, + {0, Anum_pg_statistic_staop, F_OIDEQ} + }; + bool isnull; + HeapTuple tuple; + + rdesc = heap_openr(StatisticRelationName); + + key[0].sk_argument = ObjectIdGetDatum(relid); + key[1].sk_argument = Int16GetDatum((int16) attnum); + key[2].sk_argument = ObjectIdGetDatum(opid); + sdesc = heap_beginscan(rdesc, 0, NowTimeQual, 3, key); + tuple = heap_getnext(sdesc, 0, (Buffer *) NULL); + if (!HeapTupleIsValid(tuple)) + { + *high = "n"; + *low = "n"; + + /* + * XXX elog(WARN, "gethilokey: statistic tuple not + * found"); + */ + return; + } + *high = textout((struct varlena *) + heap_getattr(tuple, + InvalidBuffer, + Anum_pg_statistic_stahikey, + RelationGetTupleDescriptor(rdesc), + &isnull)); + if (isnull) + elog(DEBUG, "gethilokey: high key is null"); + *low = textout((struct varlena *) + heap_getattr(tuple, + InvalidBuffer, + Anum_pg_statistic_stalokey, + RelationGetTupleDescriptor(rdesc), + &isnull)); + if (isnull) + elog(DEBUG, "gethilokey: low key is null"); + heap_endscan(sdesc); + heap_close(rdesc); } float64 btreesel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - float64 result; - float64data resultData; - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) { - /* - * Need to call the functions selectivity - * function here. For now simply assume it's - * 1/3 since functions don't currently - * have selectivity functions - */ - resultData = 1.0 / 3.0; - result = &resultData; - } - else { - result = (float64)fmgr(get_oprrest (operatorObjectId), - (char*)operatorObjectId, - (char*)indrelid, - (char*)(int)attributeNumber, - (char*)constValue, - (char*)constFlag, - NULL); - } - - if (!PointerIsValid(result)) - elog(WARN, "Btree Selectivity: bad pointer"); - if (*result < 0.0 || *result > 1.0) - elog(WARN, "Btree Selectivity: bad value %lf", *result); - - return(result); + float64 result; + float64data resultData; + + if (FunctionalSelectivity(nIndexKeys, attributeNumber)) + { + + /* + * Need to call the functions selectivity function here. For now + * simply assume it's 1/3 since functions don't currently have + * selectivity functions + */ + resultData = 1.0 / 3.0; + result = &resultData; + } + else + { + result = (float64) fmgr(get_oprrest(operatorObjectId), + (char *) operatorObjectId, + (char *) indrelid, + (char *) (int) attributeNumber, + (char *) constValue, + (char *) constFlag, + NULL); + } + + if (!PointerIsValid(result)) + elog(WARN, "Btree Selectivity: bad pointer"); + if (*result < 0.0 || *result > 1.0) + elog(WARN, "Btree Selectivity: bad value %lf", *result); + + return (result); } float64 btreenpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - float64 temp, result; - float64data tempData; - HeapTuple atp; - int npage; - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) { - /* - * Need to call the functions selectivity - * function here. For now simply assume it's - * 1/3 since functions don't currently - * have selectivity functions - */ - tempData = 1.0 / 3.0; - temp = &tempData; - } - else { - temp = (float64)fmgr(get_oprrest (operatorObjectId), - (char*)operatorObjectId, - (char*)indrelid, - (char*)(int)attributeNumber, - (char*)constValue, - (char*)constFlag, - NULL); - } - atp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexrelid), - 0,0,0); - if (!HeapTupleIsValid(atp)) { - elog(WARN, "btreenpage: no index tuple %d", indexrelid); - return(0); - } - - npage = ((Form_pg_class) GETSTRUCT(atp))->relpages; - result = (float64)palloc(sizeof(float64data)); - *result = *temp * npage; - return(result); + float64 temp, + result; + float64data tempData; + HeapTuple atp; + int npage; + + if (FunctionalSelectivity(nIndexKeys, attributeNumber)) + { + + /* + * Need to call the functions selectivity function here. For now + * simply assume it's 1/3 since functions don't currently have + * selectivity functions + */ + tempData = 1.0 / 3.0; + temp = &tempData; + } + else + { + temp = (float64) fmgr(get_oprrest(operatorObjectId), + (char *) operatorObjectId, + (char *) indrelid, + (char *) (int) attributeNumber, + (char *) constValue, + (char *) constFlag, + NULL); + } + atp = SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(indexrelid), + 0, 0, 0); + if (!HeapTupleIsValid(atp)) + { + elog(WARN, "btreenpage: no index tuple %d", indexrelid); + return (0); + } + + npage = ((Form_pg_class) GETSTRUCT(atp))->relpages; + result = (float64) palloc(sizeof(float64data)); + *result = *temp * npage; + return (result); } float64 hashsel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - - float64 result; - float64data resultData; - HeapTuple atp; - int ntuples; - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) { - /* - * Need to call the functions selectivity - * function here. For now simply use 1/Number of Tuples - * since functions don't currently - * have selectivity functions - */ - - atp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(indexrelid), - 0,0,0); - if (!HeapTupleIsValid(atp)) { - elog(WARN, "hashsel: no index tuple %d", indexrelid); - return(0); - } - ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; - if (ntuples > 0) { - resultData = 1.0 / (float64data) ntuples; + + float64 result; + float64data resultData; + HeapTuple atp; + int ntuples; + + if (FunctionalSelectivity(nIndexKeys, attributeNumber)) + { + + /* + * Need to call the functions selectivity function here. For now + * simply use 1/Number of Tuples since functions don't currently + * have selectivity functions + */ + + atp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(indexrelid), + 0, 0, 0); + if (!HeapTupleIsValid(atp)) + { + elog(WARN, "hashsel: no index tuple %d", indexrelid); + return (0); + } + ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; + if (ntuples > 0) + { + resultData = 1.0 / (float64data) ntuples; + } + else + { + resultData = (float64data) (1.0 / 100.0); + } + result = &resultData; + } - else { - resultData = (float64data) (1.0 / 100.0); + else + { + result = (float64) fmgr(get_oprrest(operatorObjectId), + (char *) operatorObjectId, + (char *) indrelid, + (char *) (int) attributeNumber, + (char *) constValue, + (char *) constFlag, + NULL); } - result = &resultData; - - } - else { - result = (float64)fmgr(get_oprrest (operatorObjectId), - (char*)operatorObjectId, - (char*)indrelid, - (char*)(int)attributeNumber, - (char*)constValue, - (char*)constFlag, - NULL); - } - - if (!PointerIsValid(result)) - elog(WARN, "Hash Table Selectivity: bad pointer"); - if (*result < 0.0 || *result > 1.0) - elog(WARN, "Hash Table Selectivity: bad value %lf", *result); - - return(result); - - + + if (!PointerIsValid(result)) + elog(WARN, "Hash Table Selectivity: bad pointer"); + if (*result < 0.0 || *result > 1.0) + elog(WARN, "Hash Table Selectivity: bad value %lf", *result); + + return (result); + + } float64 hashnpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - float64 temp, result; - float64data tempData; - HeapTuple atp; - int npage; - int ntuples; - - atp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(indexrelid), - 0,0,0); - if (!HeapTupleIsValid(atp)) { - elog(WARN, "hashsel: no index tuple %d", indexrelid); - return(0); - } - - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) { - /* - * Need to call the functions selectivity - * function here. For now, use 1/Number of Tuples - * since functions don't currently - * have selectivity functions - */ - - ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; - if (ntuples > 0) { - tempData = 1.0 / (float64data) ntuples; + float64 temp, + result; + float64data tempData; + HeapTuple atp; + int npage; + int ntuples; + + atp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(indexrelid), + 0, 0, 0); + if (!HeapTupleIsValid(atp)) + { + elog(WARN, "hashsel: no index tuple %d", indexrelid); + return (0); + } + + + if (FunctionalSelectivity(nIndexKeys, attributeNumber)) + { + + /* + * Need to call the functions selectivity function here. For now, + * use 1/Number of Tuples since functions don't currently have + * selectivity functions + */ + + ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; + if (ntuples > 0) + { + tempData = 1.0 / (float64data) ntuples; + } + else + { + tempData = (float64data) (1.0 / 100.0); + } + temp = &tempData; + } - else { - tempData = (float64data) (1.0 / 100.0); + else + { + temp = (float64) fmgr(get_oprrest(operatorObjectId), + (char *) operatorObjectId, + (char *) indrelid, + (char *) (int) attributeNumber, + (char *) constValue, + (char *) constFlag, + NULL); } - temp = &tempData; - - } - else { - temp = (float64)fmgr(get_oprrest (operatorObjectId), - (char*)operatorObjectId, - (char*)indrelid, - (char*)(int)attributeNumber, - (char*)constValue, - (char*)constFlag, - NULL); - } - - npage = ((Form_pg_class) GETSTRUCT(atp))->relpages; - result = (float64)palloc(sizeof(float64data)); - *result = *temp * npage; - return(result); + + npage = ((Form_pg_class) GETSTRUCT(atp))->relpages; + result = (float64) palloc(sizeof(float64data)); + *result = *temp * npage; + return (result); } float64 rtsel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - return (btreesel(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); + return (btreesel(operatorObjectId, indrelid, attributeNumber, + constValue, constFlag, nIndexKeys, indexrelid)); } float64 rtnpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - return (btreenpage(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); + return (btreenpage(operatorObjectId, indrelid, attributeNumber, + constValue, constFlag, nIndexKeys, indexrelid)); } float64 gistsel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - return (btreesel(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); + return (btreesel(operatorObjectId, indrelid, attributeNumber, + constValue, constFlag, nIndexKeys, indexrelid)); } float64 gistnpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) + Oid indrelid, + AttrNumber attributeNumber, + char *constValue, + int32 constFlag, + int32 nIndexKeys, + Oid indexrelid) { - return (btreenpage(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); + return (btreenpage(operatorObjectId, indrelid, attributeNumber, + constValue, constFlag, nIndexKeys, indexrelid)); } diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c index 55ca1f4b643..72f0a615a66 100644 --- a/src/backend/utils/adt/sets.c +++ b/src/backend/utils/adt/sets.c @@ -1,163 +1,173 @@ /*------------------------------------------------------------------------- * * sets.c-- - * Functions for sets, which are defined by queries. - * Example: a set is defined as being the result of the query - * retrieve (X.all) + * Functions for sets, which are defined by queries. + * Example: a set is defined as being the result of the query + * retrieve (X.all) * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.5 1997/08/12 22:54:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.6 1997/09/07 04:50:43 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include "postgres.h" #include "access/heapam.h" #include "access/relscan.h" #include "access/xact.h" -#include "catalog/pg_proc.h" /* for Form_pg_proc */ -#include "utils/syscache.h" /* for PROOID */ -#include "catalog/catname.h" /* for ProcedureRelationName */ -#include "catalog/indexing.h" /* for Num_pg_proc_indices */ +#include "catalog/pg_proc.h" /* for Form_pg_proc */ +#include "utils/syscache.h" /* for PROOID */ +#include "catalog/catname.h" /* for ProcedureRelationName */ +#include "catalog/indexing.h" /* for Num_pg_proc_indices */ #include "storage/lmgr.h" -#include "utils/sets.h" /* for GENERICSETNAME */ +#include "utils/sets.h" /* for GENERICSETNAME */ #include "tcop/dest.h" #include "fmgr.h" -extern CommandDest whereToSendOutput; /* defined in tcop/postgres.c */ +extern CommandDest whereToSendOutput; /* defined in tcop/postgres.c */ /* - * SetDefine - converts query string defining set to an oid + * SetDefine - converts query string defining set to an oid * - * The query string is used to store the set as a function in - * pg_proc. The name of the function is then changed to use the - * OID of its tuple in pg_proc. + * The query string is used to store the set as a function in + * pg_proc. The name of the function is then changed to use the + * OID of its tuple in pg_proc. */ Oid SetDefine(char *querystr, char *typename) { - Oid setoid; - char *procname = GENERICSETNAME; - char *fileName = "-"; - char realprocname[16]; - HeapTuple tup, newtup = NULL; - Form_pg_proc proc; - Relation procrel; - int i; - Datum replValue[Natts_pg_proc]; - char replNull[Natts_pg_proc]; - char repl[Natts_pg_proc]; - HeapScanDesc pg_proc_scan; - Buffer buffer; - ItemPointerData ipdata; - - static ScanKeyData oidKey[1] = { - { 0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure }}; - - - setoid = ProcedureCreate(procname, /* changed below, after oid known */ - true, /* returnsSet */ - typename, /* returnTypeName */ - "sql", /* languageName */ - querystr, /* sourceCode */ - fileName, /* fileName */ - false, /* canCache */ - true, /* trusted */ - 100, /* byte_pct */ - 0, /* perbyte_cpu */ - 0, /* percall_cpu */ - 100, /* outin_ratio */ - NIL, /* argList */ - whereToSendOutput); - /* Since we're still inside this command of the transaction, we can't - * see the results of the procedure definition unless we pretend - * we've started the next command. (Postgres's solution to the - * Halloween problem is to not allow you to see the results of your - * command until you start the next command.) - */ - CommandCounterIncrement(); - tup = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(setoid), - 0,0,0); - if (!HeapTupleIsValid(tup)) - elog(WARN, "setin: unable to define set %s", querystr); - - /* We can tell whether the set was already defined by checking - * the name. If it's GENERICSETNAME, the set is new. If it's - * "set<some oid>" it's already defined. - */ - proc = (Form_pg_proc)GETSTRUCT(tup); - if (!strcmp((char*)procname, (char*)&(proc->proname))) { - /* make the real proc name */ - sprintf(realprocname, "set%u", setoid); - - /* set up the attributes to be modified or kept the same */ - repl[0] = 'r'; - for (i = 1; i < Natts_pg_proc; i++) repl[i] = ' '; - replValue[0] = (Datum)realprocname; - for (i = 1; i < Natts_pg_proc; i++) replValue[i] = (Datum)0; - for (i = 0; i < Natts_pg_proc; i++) replNull[i] = ' '; - - /* change the pg_proc tuple */ - procrel = heap_openr(ProcedureRelationName); - RelationSetLockForWrite(procrel); - fmgr_info(ObjectIdEqualRegProcedure, - &oidKey[0].sk_func, - &oidKey[0].sk_nargs); - oidKey[0].sk_argument = ObjectIdGetDatum(setoid); - pg_proc_scan = heap_beginscan(procrel, - 0, - SelfTimeQual, - 1, - oidKey); - tup = heap_getnext(pg_proc_scan, 0, &buffer); - if (HeapTupleIsValid(tup)) { - newtup = heap_modifytuple(tup, - buffer, - procrel, - replValue, - replNull, - repl); - - /* XXX may not be necessary */ - ItemPointerCopy(&tup->t_ctid, &ipdata); - - setheapoverride(true); - heap_replace(procrel, &ipdata, newtup); - setheapoverride(false); - - setoid = newtup->t_oid; - } else - elog(WARN, "setin: could not find new set oid tuple"); - heap_endscan(pg_proc_scan); - - if (RelationGetRelationTupleForm(procrel)->relhasindex) - { - Relation idescs[Num_pg_proc_indices]; - - CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); - CatalogCloseIndices(Num_pg_proc_indices, idescs); - } - RelationUnsetLockForWrite(procrel); - heap_close(procrel); - } - return setoid; + Oid setoid; + char *procname = GENERICSETNAME; + char *fileName = "-"; + char realprocname[16]; + HeapTuple tup, + newtup = NULL; + Form_pg_proc proc; + Relation procrel; + int i; + Datum replValue[Natts_pg_proc]; + char replNull[Natts_pg_proc]; + char repl[Natts_pg_proc]; + HeapScanDesc pg_proc_scan; + Buffer buffer; + ItemPointerData ipdata; + + static ScanKeyData oidKey[1] = { + {0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure}}; + + + setoid = ProcedureCreate(procname, /* changed below, after oid known */ + true, /* returnsSet */ + typename, /* returnTypeName */ + "sql", /* languageName */ + querystr, /* sourceCode */ + fileName, /* fileName */ + false, /* canCache */ + true, /* trusted */ + 100, /* byte_pct */ + 0, /* perbyte_cpu */ + 0, /* percall_cpu */ + 100, /* outin_ratio */ + NIL, /* argList */ + whereToSendOutput); + + /* + * Since we're still inside this command of the transaction, we can't + * see the results of the procedure definition unless we pretend we've + * started the next command. (Postgres's solution to the Halloween + * problem is to not allow you to see the results of your command + * until you start the next command.) + */ + CommandCounterIncrement(); + tup = SearchSysCacheTuple(PROOID, + ObjectIdGetDatum(setoid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(WARN, "setin: unable to define set %s", querystr); + + /* + * We can tell whether the set was already defined by checking the + * name. If it's GENERICSETNAME, the set is new. If it's "set<some + * oid>" it's already defined. + */ + proc = (Form_pg_proc) GETSTRUCT(tup); + if (!strcmp((char *) procname, (char *) &(proc->proname))) + { + /* make the real proc name */ + sprintf(realprocname, "set%u", setoid); + + /* set up the attributes to be modified or kept the same */ + repl[0] = 'r'; + for (i = 1; i < Natts_pg_proc; i++) + repl[i] = ' '; + replValue[0] = (Datum) realprocname; + for (i = 1; i < Natts_pg_proc; i++) + replValue[i] = (Datum) 0; + for (i = 0; i < Natts_pg_proc; i++) + replNull[i] = ' '; + + /* change the pg_proc tuple */ + procrel = heap_openr(ProcedureRelationName); + RelationSetLockForWrite(procrel); + fmgr_info(ObjectIdEqualRegProcedure, + &oidKey[0].sk_func, + &oidKey[0].sk_nargs); + oidKey[0].sk_argument = ObjectIdGetDatum(setoid); + pg_proc_scan = heap_beginscan(procrel, + 0, + SelfTimeQual, + 1, + oidKey); + tup = heap_getnext(pg_proc_scan, 0, &buffer); + if (HeapTupleIsValid(tup)) + { + newtup = heap_modifytuple(tup, + buffer, + procrel, + replValue, + replNull, + repl); + + /* XXX may not be necessary */ + ItemPointerCopy(&tup->t_ctid, &ipdata); + + setheapoverride(true); + heap_replace(procrel, &ipdata, newtup); + setheapoverride(false); + + setoid = newtup->t_oid; + } + else + elog(WARN, "setin: could not find new set oid tuple"); + heap_endscan(pg_proc_scan); + + if (RelationGetRelationTupleForm(procrel)->relhasindex) + { + Relation idescs[Num_pg_proc_indices]; + + CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); + CatalogCloseIndices(Num_pg_proc_indices, idescs); + } + RelationUnsetLockForWrite(procrel); + heap_close(procrel); + } + return setoid; } -/* This function is a placeholder. The parser uses the OID of this +/* This function is a placeholder. The parser uses the OID of this * function to fill in the :funcid field of a set. This routine is - * never executed. At runtime, the OID of the actual set is substituted + * never executed. At runtime, the OID of the actual set is substituted * into the :funcid. */ int seteval(Oid funcoid) { - return 17; + return 17; } diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c index 6fb4e589ad8..fe10f2b58e3 100644 --- a/src/backend/utils/adt/tid.c +++ b/src/backend/utils/adt/tid.c @@ -1,89 +1,90 @@ /*------------------------------------------------------------------------- * * tid.c-- - * Functions for the built-in type tuple id + * Functions for the built-in type tuple id * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.2 1996/11/06 06:50:05 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.3 1997/09/07 04:50:46 momjian Exp $ * * NOTES - * input routine largely stolen from boxin(). + * input routine largely stolen from boxin(). * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include "postgres.h" #include "storage/bufpage.h" #include "utils/palloc.h" -#include "utils/builtins.h" /* where function declarations go */ +#include "utils/builtins.h" /* where function declarations go */ -#define LDELIM '(' -#define RDELIM ')' -#define DELIM ',' -#define NTIDARGS 2 +#define LDELIM '(' +#define RDELIM ')' +#define DELIM ',' +#define NTIDARGS 2 /* ---------------------------------------------------------------- - * tidin + * tidin * ---------------------------------------------------------------- */ ItemPointer tidin(char *str) { - char *p, *coord[NTIDARGS]; - int i; - ItemPointer result; - - BlockNumber blockNumber; - OffsetNumber offsetNumber; - - if (str == NULL) - return NULL; - - for (i = 0, p = str; *p && i < NTIDARGS && *p != RDELIM; p++) - if (*p == DELIM || (*p == LDELIM && !i)) - coord[i++] = p + 1; - - if (i < NTIDARGS - 1) - return NULL; - - blockNumber = (BlockNumber) atoi(coord[0]); - offsetNumber = (OffsetNumber) atoi(coord[1]); - - result = (ItemPointer) palloc(sizeof(ItemPointerData)); - - ItemPointerSet(result, blockNumber, offsetNumber); - - return result; + char *p, + *coord[NTIDARGS]; + int i; + ItemPointer result; + + BlockNumber blockNumber; + OffsetNumber offsetNumber; + + if (str == NULL) + return NULL; + + for (i = 0, p = str; *p && i < NTIDARGS && *p != RDELIM; p++) + if (*p == DELIM || (*p == LDELIM && !i)) + coord[i++] = p + 1; + + if (i < NTIDARGS - 1) + return NULL; + + blockNumber = (BlockNumber) atoi(coord[0]); + offsetNumber = (OffsetNumber) atoi(coord[1]); + + result = (ItemPointer) palloc(sizeof(ItemPointerData)); + + ItemPointerSet(result, blockNumber, offsetNumber); + + return result; } /* ---------------------------------------------------------------- - * tidout + * tidout * ---------------------------------------------------------------- */ -char * +char * tidout(ItemPointer itemPtr) { - BlockNumber blockNumber; - OffsetNumber offsetNumber; - BlockId blockId; - char buf[32]; - char *str; - - blockId = &(itemPtr->ip_blkid); - - blockNumber = BlockIdGetBlockNumber(blockId); - offsetNumber = itemPtr->ip_posid; - - sprintf(buf, "(%d,%d)", blockNumber, offsetNumber); - - str = (char *) palloc(strlen(buf)+1); - strcpy(str, buf); - - return str; + BlockNumber blockNumber; + OffsetNumber offsetNumber; + BlockId blockId; + char buf[32]; + char *str; + + blockId = &(itemPtr->ip_blkid); + + blockNumber = BlockIdGetBlockNumber(blockId); + offsetNumber = itemPtr->ip_posid; + + sprintf(buf, "(%d,%d)", blockNumber, offsetNumber); + + str = (char *) palloc(strlen(buf) + 1); + strcpy(str, buf); + + return str; } diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 4d3a8f9af21..d9ed6d299c5 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -16,7 +16,7 @@ static const char * cpstr(const char *s, char *buf) { - char in = 0; + char in = 0; while (isspace(*s)) s++; @@ -26,7 +26,7 @@ cpstr(const char *s, char *buf) if (strchr("-,:/", *s)) { buf[in] = 0; - return(s + 1); + return (s + 1); } if (in < 16) @@ -36,72 +36,76 @@ cpstr(const char *s, char *buf) buf[in] = 0; return s; } + #endif /* assumes dd/mm/yyyy unless first item is month in word form */ time_t timestamp_in(const char *timestamp_str) { - int4 result; + int4 result; #if FALSE - struct tm input_time; - char buf[18]; - const char *p; + struct tm input_time; + char buf[18]; + const char *p; static const char *mstr[] = { "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december" }; - memset(&input_time, 0, sizeof(input_time)); + memset(&input_time, 0, sizeof(input_time)); p = cpstr(timestamp_str, buf); - if (isdigit(buf[0])) /* must be dd/mm/yyyy */ + if (isdigit(buf[0])) /* must be dd/mm/yyyy */ { input_time.tm_mday = atoi(buf); p = cpstr(p, buf); if (!buf[0]) elog(WARN, "timestamp_in: timestamp \"%s\" not a proper date", - timestamp_str); + timestamp_str); if (isdigit(buf[0])) { input_time.tm_mon = atoi(buf) - 1; if (input_time.tm_mon < 0 || input_time.tm_mon > 11) elog(WARN, "timestamp_in: timestamp \"%s\" invalid month", - timestamp_str); + timestamp_str); } else { - int i; + int i; + for (i = 0; i < 12; i++) if (strncmp(mstr[i], buf, strlen(buf)) == 0) break; if (1 > 11) elog(WARN, "timestamp_in: timestamp \"%s\" invalid month", - timestamp_str); + timestamp_str); input_time.tm_mon = i; } } - else /* must be month/dd/yyyy */ + else +/* must be month/dd/yyyy */ { - int i; + int i; + for (i = 0; i < 12; i++) if (strncmp(mstr[i], buf, strlen(buf)) == 0) break; if (1 > 11) elog(WARN, "timestamp_in: timestamp \"%s\" invalid month", - timestamp_str); + timestamp_str); input_time.tm_mon = i; p = cpstr(p, buf); input_time.tm_mday = atoi(buf); if (!input_time.tm_mday || input_time.tm_mday > 31) elog(WARN, "timestamp_in: timestamp \"%s\" not a proper date", - timestamp_str); - } + timestamp_str); + } p = cpstr(p, buf); if (!buf[0] || !isdigit(buf[0])) elog(WARN, "timestamp_in: timestamp \"%s\" not a proper date", - timestamp_str); + timestamp_str); if ((input_time.tm_year = atoi(buf)) < 1900) input_time.tm_year += 1900; @@ -113,102 +117,104 @@ timestamp_in(const char *timestamp_str) p = cpstr(p, buf); input_time.tm_sec = atoi(buf); - /* use mktime(), but make this GMT, not local time */ - result = mktime(&input_time); + /* use mktime(), but make this GMT, not local time */ + result = mktime(&input_time); #endif - result = nabstimein( (char *) timestamp_str); + result = nabstimein((char *) timestamp_str); - return result; + return result; } -char * +char * timestamp_out(time_t timestamp) { - char *result; - int tz; - double fsec = 0; - struct tm tt, *tm = &tt; - char buf[MAXDATELEN+1]; - char zone[MAXDATELEN+1], *tzn = zone; + char *result; + int tz; + double fsec = 0; + struct tm tt, + *tm = &tt; + char buf[MAXDATELEN + 1]; + char zone[MAXDATELEN + 1], + *tzn = zone; #if FALSE - time = localtime(×tamp); + time = localtime(×tamp); - sprintf(result, "%04d-%02d-%02d %02d:%02d:%02d", - time->tm_year+1900, time->tm_mon+1, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); + sprintf(result, "%04d-%02d-%02d %02d:%02d:%02d", + time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); #endif - abstime2tm( timestamp, &tz, tm, tzn); - EncodeDateTime( tm, fsec, &tz, &tzn, USE_ISO_DATES, buf); + abstime2tm(timestamp, &tz, tm, tzn); + EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf); - result = palloc(strlen(buf)+1); - strcpy( result, buf); - return result; + result = palloc(strlen(buf) + 1); + strcpy(result, buf); + return result; } time_t now(void) { - time_t sec; + time_t sec; - time(&sec); - return(sec); + time(&sec); + return (sec); } bool timestampeq(time_t t1, time_t t2) { - return difftime(t1, t2) == 0; + return difftime(t1, t2) == 0; } bool timestampne(time_t t1, time_t t2) { - return difftime(t1, t2) != 0; + return difftime(t1, t2) != 0; } bool timestamplt(time_t t1, time_t t2) { - return difftime(t1, t2) > 0; + return difftime(t1, t2) > 0; } bool timestampgt(time_t t1, time_t t2) { - return difftime(t1, t2) < 0; + return difftime(t1, t2) < 0; } bool timestample(time_t t1, time_t t2) { - return difftime(t1, t2) >= 0; + return difftime(t1, t2) >= 0; } bool timestampge(time_t t1, time_t t2) { - return difftime(t1, t2) <= 0; + return difftime(t1, t2) <= 0; } -DateTime * +DateTime * timestamp_datetime(time_t timestamp) { - DateTime *result; + DateTime *result; - double fsec = 0; - struct tm *tm; + double fsec = 0; + struct tm *tm; - if (!PointerIsValid(result = PALLOCTYPE(DateTime))) - elog(WARN,"Memory allocation failed, can't convert timestamp to datetime",NULL); + if (!PointerIsValid(result = PALLOCTYPE(DateTime))) + elog(WARN, "Memory allocation failed, can't convert timestamp to datetime", NULL); - tm = localtime((time_t *) ×tamp); - tm->tm_year += 1900; - tm->tm_mon += 1; + tm = localtime((time_t *) & timestamp); + tm->tm_year += 1900; + tm->tm_mon += 1; - if (tm2datetime(tm, fsec, NULL, result) != 0) - elog(WARN,"Unable to convert timestamp to datetime",timestamp_out(timestamp)); + if (tm2datetime(tm, fsec, NULL, result) != 0) + elog(WARN, "Unable to convert timestamp to datetime", timestamp_out(timestamp)); - return(result); -} /* timestamp_datetime() */ + return (result); +} /* timestamp_datetime() */ diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 538063c6225..106ff5dad26 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * varchar.c-- - * Functions for the built-in type char() and varchar(). + * Functions for the built-in type char() and varchar(). * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.8 1997/08/12 20:16:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.9 1997/09/07 04:52:53 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include "postgres.h" #include "utils/builtins.h" @@ -35,488 +35,524 @@ * the length for the comparison functions. (The difference between "text" * is that we truncate and possibly blank-pad the string at insertion time.) * - * - ay 6/95 + * - ay 6/95 */ -/***************************************************************************** - * bpchar - char() * +/***************************************************************************** + * bpchar - char() * *****************************************************************************/ /* * bpcharin - - * converts a string of char() type to the internal representation. - * len is the length specified in () plus 4 bytes. (XXX dummy is here - * because we pass typelem as the second argument for array_in.) + * converts a string of char() type to the internal representation. + * len is the length specified in () plus 4 bytes. (XXX dummy is here + * because we pass typelem as the second argument for array_in.) */ -char * +char * bpcharin(char *s, int dummy, int typlen) { - char *result, *r; - int len = typlen - 4; - int i; - - if (s == NULL) - return((char *) NULL); - - if (typlen == -1) { - /* - * this is here because some functions can't supply the typlen - */ - len = strlen(s); - typlen = len + 4; - } - - if (len > 4096) - elog(WARN, "bpcharin: length of char() must be less than 4096"); - - result = (char *) palloc(typlen); - *(int32*)result = typlen; - r = result + 4; - for(i=0; i < len; i++, r++, s++) { - *r = *s; - if (*r == '\0') - break; - } - /* blank pad the string if necessary */ - for(; i < len; i++) { - *r++ = ' '; - } - return(result); + char *result, + *r; + int len = typlen - 4; + int i; + + if (s == NULL) + return ((char *) NULL); + + if (typlen == -1) + { + + /* + * this is here because some functions can't supply the typlen + */ + len = strlen(s); + typlen = len + 4; + } + + if (len > 4096) + elog(WARN, "bpcharin: length of char() must be less than 4096"); + + result = (char *) palloc(typlen); + *(int32 *) result = typlen; + r = result + 4; + for (i = 0; i < len; i++, r++, s++) + { + *r = *s; + if (*r == '\0') + break; + } + /* blank pad the string if necessary */ + for (; i < len; i++) + { + *r++ = ' '; + } + return (result); } -char * +char * bpcharout(char *s) { - char *result; - int len; - - if (s == NULL) { - result = (char *) palloc(2); - result[0] = '-'; - result[1] = '\0'; - } else { - len = *(int32*)s - 4; - result = (char *) palloc(len+1); - strNcpy(result, s+4, len); /* these are blank-padded */ - } - return(result); + char *result; + int len; + + if (s == NULL) + { + result = (char *) palloc(2); + result[0] = '-'; + result[1] = '\0'; + } + else + { + len = *(int32 *) s - 4; + result = (char *) palloc(len + 1); + strNcpy(result, s + 4, len); /* these are blank-padded */ + } + return (result); } -/***************************************************************************** - * varchar - varchar() * +/***************************************************************************** + * varchar - varchar() * *****************************************************************************/ /* * vcharin - - * converts a string of varchar() type to the internal representation. - * len is the length specified in () plus 4 bytes. (XXX dummy is here - * because we pass typelem as the second argument for array_in.) + * converts a string of varchar() type to the internal representation. + * len is the length specified in () plus 4 bytes. (XXX dummy is here + * because we pass typelem as the second argument for array_in.) */ -char * +char * varcharin(char *s, int dummy, int typlen) { - char *result; - int len = typlen - 4; - - if (s == NULL) - return((char *) NULL); - - if (typlen == -1) { - /* - * this is here because some functions can't supply the typlen - */ - len = strlen(s); - typlen = len + 4; - } - - if (len > 4096) - elog(WARN, "varcharin: length of char() must be less than 4096"); - - result = (char *) palloc(typlen); - *(int32*)result = typlen; - strncpy(result+4, s, len); - - return(result); + char *result; + int len = typlen - 4; + + if (s == NULL) + return ((char *) NULL); + + if (typlen == -1) + { + + /* + * this is here because some functions can't supply the typlen + */ + len = strlen(s); + typlen = len + 4; + } + + if (len > 4096) + elog(WARN, "varcharin: length of char() must be less than 4096"); + + result = (char *) palloc(typlen); + *(int32 *) result = typlen; + strncpy(result + 4, s, len); + + return (result); } -char * +char * varcharout(char *s) { - char *result; - int len; - - if (s == NULL) { - result = (char *) palloc(2); - result[0] = '-'; - result[1] = '\0'; - } else { - len = *(int32*)s - 4; - result = (char *) palloc(len+1); - strNcpy(result, s+4, len); - } - return(result); + char *result; + int len; + + if (s == NULL) + { + result = (char *) palloc(2); + result[0] = '-'; + result[1] = '\0'; + } + else + { + len = *(int32 *) s - 4; + result = (char *) palloc(len + 1); + strNcpy(result, s + 4, len); + } + return (result); } /***************************************************************************** - * Comparison Functions used for bpchar + * Comparison Functions used for bpchar *****************************************************************************/ static int bcTruelen(char *arg) { - char *s = arg + 4; - int i; - int len; - - len = *(int32*)arg - 4; - for(i=len-1; i >= 0; i--) { - if (s[i] != ' ') - break; - } - return (i+1); + char *s = arg + 4; + int i; + int len; + + len = *(int32 *) arg - 4; + for (i = len - 1; i >= 0; i--) + { + if (s[i] != ' ') + break; + } + return (i + 1); } bool bpchareq(char *arg1, char *arg2) { - int len1, len2; + int len1, + len2; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); + if (len1 != len2) + return 0; - if (len1!=len2) - return 0; - - return(strncmp(arg1+4, arg2+4, len1) == 0); + return (strncmp(arg1 + 4, arg2 + 4, len1) == 0); } bool bpcharne(char *arg1, char *arg2) { - int len1, len2; + int len1, + len2; - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); - if (len1!=len2) - return 1; + if (len1 != len2) + return 1; - return(strncmp(arg1+4, arg2+4, len1) != 0); + return (strncmp(arg1 + 4, arg2 + 4, len1) != 0); } bool bpcharlt(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (cmp == 0) - return (len1<len2); - else - return (cmp < 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (cmp == 0) + return (len1 < len2); + else + return (cmp < 0); } bool bpcharle(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (0 == cmp) - return (bool)(len1 <= len2 ? 1 : 0); - else - return (bool)(cmp <= 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (0 == cmp) + return (bool) (len1 <= len2 ? 1 : 0); + else + return (bool) (cmp <= 0); } bool bpchargt(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (cmp == 0) - return (len1 > len2); - else - return (cmp > 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (cmp == 0) + return (len1 > len2); + else + return (cmp > 0); } bool bpcharge(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (0 == cmp) - return (bool)(len1 >= len2 ? 1 : 0); - else - return (bool)(cmp >= 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (0 == cmp) + return (bool) (len1 >= len2 ? 1 : 0); + else + return (bool) (cmp >= 0); } int32 bpcharcmp(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - len1 = bcTruelen(arg1); - len2 = bcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if ((0 == cmp) && (len1 != len2)) - return (int32)(len1 < len2 ? -1 : 1); - else - return cmp; + int len1, + len2; + int cmp; + + len1 = bcTruelen(arg1); + len2 = bcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if ((0 == cmp) && (len1 != len2)) + return (int32) (len1 < len2 ? -1 : 1); + else + return cmp; } /***************************************************************************** - * Comparison Functions used for varchar + * Comparison Functions used for varchar *****************************************************************************/ static int vcTruelen(char *arg) { - char *s = arg + 4; - int i; - int len; - - len = *(int32*)arg - 4; - for(i=0; i < len; i++) { - if (*s++ == '\0') - break; - } - return i; + char *s = arg + 4; + int i; + int len; + + len = *(int32 *) arg - 4; + for (i = 0; i < len; i++) + { + if (*s++ == '\0') + break; + } + return i; } bool varchareq(char *arg1, char *arg2) { - int len1, len2; + int len1, + len2; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); + if (len1 != len2) + return 0; - if (len1!=len2) - return 0; - - return(strncmp(arg1+4, arg2+4, len1) == 0); + return (strncmp(arg1 + 4, arg2 + 4, len1) == 0); } bool varcharne(char *arg1, char *arg2) { - int len1, len2; + int len1, + len2; - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); - if (len1!=len2) - return 1; + if (len1 != len2) + return 1; - return(strncmp(arg1+4, arg2+4, len1) != 0); + return (strncmp(arg1 + 4, arg2 + 4, len1) != 0); } bool varcharlt(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (cmp == 0) - return (len1<len2); - else - return (cmp < 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (cmp == 0) + return (len1 < len2); + else + return (cmp < 0); } bool varcharle(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (0 == cmp) - return (bool)( len1 <= len2 ? 1 : 0); - else - return (bool)(cmp <= 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (0 == cmp) + return (bool) (len1 <= len2 ? 1 : 0); + else + return (bool) (cmp <= 0); } bool varchargt(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); - - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (cmp == 0) - return (len1 > len2); - else - return (cmp > 0); + int len1, + len2; + int cmp; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); + + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (cmp == 0) + return (len1 > len2); + else + return (cmp > 0); } bool varcharge(char *arg1, char *arg2) { - int len1, len2; - int cmp; + int len1, + len2; + int cmp; - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); - cmp = strncmp(arg1+4, arg2+4, Min(len1,len2)); - if (0 == cmp) - return (bool)(len1 >= len2 ? 1 : 0); - else - return (bool)(cmp >= 0); + cmp = strncmp(arg1 + 4, arg2 + 4, Min(len1, len2)); + if (0 == cmp) + return (bool) (len1 >= len2 ? 1 : 0); + else + return (bool) (cmp >= 0); } int32 varcharcmp(char *arg1, char *arg2) { - int len1, len2; - int cmp; - - len1 = vcTruelen(arg1); - len2 = vcTruelen(arg2); - cmp = (strncmp(arg1+4, arg2+4, Min(len1,len2))); - if ((0 == cmp) && (len1 != len2)) - return (int32)(len1 < len2 ? -1 : 1); - else - return (int32)(cmp); + int len1, + len2; + int cmp; + + len1 = vcTruelen(arg1); + len2 = vcTruelen(arg2); + cmp = (strncmp(arg1 + 4, arg2 + 4, Min(len1, len2))); + if ((0 == cmp) && (len1 != len2)) + return (int32) (len1 < len2 ? -1 : 1); + else + return (int32) (cmp); } /***************************************************************************** * Hash functions (modified from hashtext in access/hash/hashfunc.c) *****************************************************************************/ -uint32 hashbpchar(struct varlena *key) +uint32 +hashbpchar(struct varlena * key) { - int keylen; - char *keydata; - uint32 n; - int loop; - - keydata = VARDATA(key); - keylen = bcTruelen((char*)key); - -#define HASHC n = *keydata++ + 65599 * n - - n = 0; - if (keylen > 0) { - loop = (keylen + 8 - 1) >> 3; - - switch (keylen & (8 - 1)) { - case 0: - do { /* All fall throughs */ - HASHC; - case 7: - HASHC; - case 6: - HASHC; - case 5: - HASHC; - case 4: - HASHC; - case 3: - HASHC; - case 2: - HASHC; - case 1: - HASHC; - } while (--loop); + int keylen; + char *keydata; + uint32 n; + int loop; + + keydata = VARDATA(key); + keylen = bcTruelen((char *) key); + +#define HASHC n = *keydata++ + 65599 * n + + n = 0; + if (keylen > 0) + { + loop = (keylen + 8 - 1) >> 3; + + switch (keylen & (8 - 1)) + { + case 0: + do + { /* All fall throughs */ + HASHC; + case 7: + HASHC; + case 6: + HASHC; + case 5: + HASHC; + case 4: + HASHC; + case 3: + HASHC; + case 2: + HASHC; + case 1: + HASHC; + } while (--loop); + } } - } - return (n); -} + return (n); +} -uint32 hashvarchar(struct varlena *key) +uint32 +hashvarchar(struct varlena * key) { - int keylen; - char *keydata; - uint32 n; - int loop; - - keydata = VARDATA(key); - keylen = vcTruelen((char*)key); - -#define HASHC n = *keydata++ + 65599 * n - - n = 0; - if (keylen > 0) { - loop = (keylen + 8 - 1) >> 3; - - switch (keylen & (8 - 1)) { - case 0: - do { /* All fall throughs */ - HASHC; - case 7: - HASHC; - case 6: - HASHC; - case 5: - HASHC; - case 4: - HASHC; - case 3: - HASHC; - case 2: - HASHC; - case 1: - HASHC; - } while (--loop); + int keylen; + char *keydata; + uint32 n; + int loop; + + keydata = VARDATA(key); + keylen = vcTruelen((char *) key); + +#define HASHC n = *keydata++ + 65599 * n + + n = 0; + if (keylen > 0) + { + loop = (keylen + 8 - 1) >> 3; + + switch (keylen & (8 - 1)) + { + case 0: + do + { /* All fall throughs */ + HASHC; + case 7: + HASHC; + case 6: + HASHC; + case 5: + HASHC; + case 4: + HASHC; + case 3: + HASHC; + case 2: + HASHC; + case 1: + HASHC; + } while (--loop); + } } - } - return (n); -} - + return (n); +} diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 7c25cfd67b8..273fae92e9e 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * varlena.c-- - * Functions for the variable-length built-in types. + * Functions for the variable-length built-in types. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.18 1997/08/19 21:34:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.19 1997/09/07 04:52:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,64 +16,65 @@ #include "postgres.h" #include "utils/palloc.h" -#include "utils/builtins.h" /* where function declarations go */ +#include "utils/builtins.h" /* where function declarations go */ -/***************************************************************************** - * USER I/O ROUTINES * +/***************************************************************************** + * USER I/O ROUTINES * *****************************************************************************/ -#define VAL(CH) ((CH) - '0') -#define DIG(VAL) ((VAL) + '0') +#define VAL(CH) ((CH) - '0') +#define DIG(VAL) ((VAL) + '0') /* - * byteain - converts from printable representation of byte array + * byteain - converts from printable representation of byte array * - * Non-printable characters must be passed as '\nnn' (octal) and are - * converted to internal form. '\' must be passed as '\\'. - * elog(WARN, ...) if bad form. + * Non-printable characters must be passed as '\nnn' (octal) and are + * converted to internal form. '\' must be passed as '\\'. + * elog(WARN, ...) if bad form. * - * BUGS: - * The input is scaned twice. - * The error checking of input is minimal. + * BUGS: + * The input is scaned twice. + * The error checking of input is minimal. */ struct varlena * byteain(char *inputText) { - register char *tp; - register char *rp; - register int byte; - struct varlena *result; - - if (inputText == NULL) - elog(WARN, "Bad input string for type bytea"); - - for (byte = 0, tp = inputText; *tp != '\0'; byte++) - if (*tp++ == '\\') - { - if (*tp == '\\') - tp++; - else if (!isdigit(*tp++) || - !isdigit(*tp++) || - !isdigit(*tp++)) - elog(WARN, "Bad input string for type bytea"); - } - tp = inputText; - byte += sizeof(int32); /* varlena? */ - result = (struct varlena *) palloc(byte); - result->vl_len = byte; /* varlena? */ - rp = result->vl_dat; - while (*tp != '\0') - if (*tp != '\\' || *++tp == '\\') - *rp++ = *tp++; - else { - byte = VAL(*tp++); - byte <<= 3; - byte += VAL(*tp++); - byte <<= 3; - *rp++ = byte + VAL(*tp++); - } - return(result); + register char *tp; + register char *rp; + register int byte; + struct varlena *result; + + if (inputText == NULL) + elog(WARN, "Bad input string for type bytea"); + + for (byte = 0, tp = inputText; *tp != '\0'; byte++) + if (*tp++ == '\\') + { + if (*tp == '\\') + tp++; + else if (!isdigit(*tp++) || + !isdigit(*tp++) || + !isdigit(*tp++)) + elog(WARN, "Bad input string for type bytea"); + } + tp = inputText; + byte += sizeof(int32); /* varlena? */ + result = (struct varlena *) palloc(byte); + result->vl_len = byte; /* varlena? */ + rp = result->vl_dat; + while (*tp != '\0') + if (*tp != '\\' || *++tp == '\\') + *rp++ = *tp++; + else + { + byte = VAL(*tp++); + byte <<= 3; + byte += VAL(*tp++); + byte <<= 3; + *rp++ = byte + VAL(*tp++); + } + return (result); } /* @@ -85,114 +86,120 @@ byteain(char *inputText) struct varlena * shove_bytes(unsigned char *stuff, int len) { - struct varlena *result; - - result = (struct varlena *) palloc(len + sizeof(int32)); - result->vl_len = len; - memmove(result->vl_dat, - stuff + sizeof(int32), - len - sizeof(int32)); - return(result); + struct varlena *result; + + result = (struct varlena *) palloc(len + sizeof(int32)); + result->vl_len = len; + memmove(result->vl_dat, + stuff + sizeof(int32), + len - sizeof(int32)); + return (result); } + #endif /* - * byteaout - converts to printable representation of byte array + * byteaout - converts to printable representation of byte array * - * Non-printable characters are inserted as '\nnn' (octal) and '\' as - * '\\'. + * Non-printable characters are inserted as '\nnn' (octal) and '\' as + * '\\'. * - * NULL vlena should be an error--returning string with NULL for now. + * NULL vlena should be an error--returning string with NULL for now. */ -char * -byteaout(struct varlena *vlena) +char * +byteaout(struct varlena * vlena) { - register char *vp; - register char *rp; - register int val; /* holds unprintable chars */ - int i; - int len; - static char *result; - - if (vlena == NULL) { - result = (char *) palloc(2); - result[0] = '-'; - result[1] = '\0'; - return(result); - } - vp = vlena->vl_dat; - len = 1; /* empty string has 1 char */ - for (i = vlena->vl_len - sizeof(int32); i != 0; i--, vp++) /* varlena? */ - if (*vp == '\\') - len += 2; - else if (isascii(*vp) && isprint(*vp)) - len++; - else - len += 4; - rp = result = (char *) palloc(len); - vp = vlena->vl_dat; - for (i = vlena->vl_len - sizeof(int32); i != 0; i--) /* varlena? */ - if (*vp == '\\') { - vp++; - *rp++ = '\\'; - *rp++ = '\\'; - } else if (isascii(*vp) && isprint(*vp)) - *rp++ = *vp++; - else { - val = *vp++; - *rp = '\\'; - rp += 3; - *rp-- = DIG(val & 07); - val >>= 3; - *rp-- = DIG(val & 07); - val >>= 3; - *rp = DIG(val & 03); - rp += 3; + register char *vp; + register char *rp; + register int val; /* holds unprintable chars */ + int i; + int len; + static char *result; + + if (vlena == NULL) + { + result = (char *) palloc(2); + result[0] = '-'; + result[1] = '\0'; + return (result); } - *rp = '\0'; - return(result); + vp = vlena->vl_dat; + len = 1; /* empty string has 1 char */ + for (i = vlena->vl_len - sizeof(int32); i != 0; i--, vp++) /* varlena? */ + if (*vp == '\\') + len += 2; + else if (isascii(*vp) && isprint(*vp)) + len++; + else + len += 4; + rp = result = (char *) palloc(len); + vp = vlena->vl_dat; + for (i = vlena->vl_len - sizeof(int32); i != 0; i--) /* varlena? */ + if (*vp == '\\') + { + vp++; + *rp++ = '\\'; + *rp++ = '\\'; + } + else if (isascii(*vp) && isprint(*vp)) + *rp++ = *vp++; + else + { + val = *vp++; + *rp = '\\'; + rp += 3; + *rp-- = DIG(val & 07); + val >>= 3; + *rp-- = DIG(val & 07); + val >>= 3; + *rp = DIG(val & 03); + rp += 3; + } + *rp = '\0'; + return (result); } /* - * textin - converts "..." to internal representation + * textin - converts "..." to internal representation */ struct varlena * textin(char *inputText) { - struct varlena *result; - int len; - - if (inputText == NULL) - return(NULL); - len = strlen(inputText) + VARHDRSZ; - result = (struct varlena *) palloc(len); - VARSIZE(result) = len; - memmove(VARDATA(result), inputText, len - VARHDRSZ); - return(result); + struct varlena *result; + int len; + + if (inputText == NULL) + return (NULL); + len = strlen(inputText) + VARHDRSZ; + result = (struct varlena *) palloc(len); + VARSIZE(result) = len; + memmove(VARDATA(result), inputText, len - VARHDRSZ); + return (result); } /* - * textout - converts internal representation to "..." + * textout - converts internal representation to "..." */ -char * -textout(struct varlena *vlena) +char * +textout(struct varlena * vlena) { - int len; - char *result; - - if (vlena == NULL) { - result = (char *) palloc(2); - result[0] = '-'; - result[1] = '\0'; - return(result); - } - len = VARSIZE(vlena) - VARHDRSZ; - result = (char *) palloc(len + 1); - memmove(result, VARDATA(vlena), len); - result[len] = '\0'; - return(result); + int len; + char *result; + + if (vlena == NULL) + { + result = (char *) palloc(2); + result[0] = '-'; + result[1] = '\0'; + return (result); + } + len = VARSIZE(vlena) - VARHDRSZ; + result = (char *) palloc(len + 1); + memmove(result, VARDATA(vlena), len); + result[len] = '\0'; + return (result); } @@ -200,25 +207,28 @@ textout(struct varlena *vlena) /* * textlen - - * returns the actual length of a text* (which may be less than - * the VARSIZE of the text*) + * returns the actual length of a text* (which may be less than + * the VARSIZE of the text*) */ #ifdef NOT_USED -int textlen (text* t) +int +textlen(text * t) { - int i = 0; - int max = VARSIZE(t) - VARHDRSZ; - char *ptr = VARDATA(t); - while (i < max && *ptr++) - i++; - return i; + int i = 0; + int max = VARSIZE(t) - VARHDRSZ; + char *ptr = VARDATA(t); + + while (i < max && *ptr++) + i++; + return i; } + #endif /* * textcat - - * takes two text* and returns a text* that is the concatentation of - * the two. + * takes two text* and returns a text* that is the concatentation of + * the two. * * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96. * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10. @@ -228,222 +238,241 @@ int textlen (text* t) * Is this OK? */ -text* -textcat(text* t1, text* t2) +text * +textcat(text * t1, text * t2) { - int len1, len2, len; - char *ptr; - text* result; + int len1, + len2, + len; + char *ptr; + text *result; - if (!PointerIsValid(t1) && !PointerIsValid(t2)) - return(NULL); + if (!PointerIsValid(t1) && !PointerIsValid(t2)) + return (NULL); - len1 = (PointerIsValid(t1)? (VARSIZE(t1) - VARHDRSZ): 0); - if (len1 < 0) len1 = 0; - len2 = (PointerIsValid(t2)? (VARSIZE(t2) - VARHDRSZ): 0); - if (len2 < 0) len2 = 0; + len1 = (PointerIsValid(t1) ? (VARSIZE(t1) - VARHDRSZ) : 0); + if (len1 < 0) + len1 = 0; + len2 = (PointerIsValid(t2) ? (VARSIZE(t2) - VARHDRSZ) : 0); + if (len2 < 0) + len2 = 0; - result = PALLOC(len = len1 + len2 + VARHDRSZ); + result = PALLOC(len = len1 + len2 + VARHDRSZ); - /* Fill data field of result string... */ - ptr = VARDATA(result); - if (PointerIsValid(t1)) memcpy(ptr, VARDATA(t1), len1); - if (PointerIsValid(t2)) memcpy(ptr + len1, VARDATA(t2), len2); + /* Fill data field of result string... */ + ptr = VARDATA(result); + if (PointerIsValid(t1)) + memcpy(ptr, VARDATA(t1), len1); + if (PointerIsValid(t2)) + memcpy(ptr + len1, VARDATA(t2), len2); - /* Set size of result string... */ - VARSIZE(result) = len; + /* Set size of result string... */ + VARSIZE(result) = len; - return(result); -} /* textcat() */ + return (result); +} /* textcat() */ /* * textpos - - * Return the position of the specified substring. - * Implements the SQL92 POSITION() function. - * Ref: A Guide To The SQL Standard, Date & Darwen, 1997 + * Return the position of the specified substring. + * Implements the SQL92 POSITION() function. + * Ref: A Guide To The SQL Standard, Date & Darwen, 1997 * - thomas 1997-07-27 */ int32 -textpos(text* t1, text* t2) +textpos(text * t1, text * t2) { - int pos; - int px, p; - int len1, len2; - char *p1, *p2; - - if (!PointerIsValid(t1) || !PointerIsValid(t2)) - return(0); - - if (VARSIZE(t2) <= 0) - return(1); - - len1 = (VARSIZE(t1) - VARHDRSZ); - len2 = (VARSIZE(t2) - VARHDRSZ); - p1 = VARDATA(t1); - p2 = VARDATA(t2); - pos = 0; - px = (len1 - len2); - for (p = 0; p <= px; p++) { - if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0)) { - pos = p + 1; - break; + int pos; + int px, + p; + int len1, + len2; + char *p1, + *p2; + + if (!PointerIsValid(t1) || !PointerIsValid(t2)) + return (0); + + if (VARSIZE(t2) <= 0) + return (1); + + len1 = (VARSIZE(t1) - VARHDRSZ); + len2 = (VARSIZE(t2) - VARHDRSZ); + p1 = VARDATA(t1); + p2 = VARDATA(t2); + pos = 0; + px = (len1 - len2); + for (p = 0; p <= px; p++) + { + if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0)) + { + pos = p + 1; + break; + }; + p1++; }; - p1++; - }; - return(pos); -} /* textpos() */ + return (pos); +} /* textpos() */ /* - * texteq - returns 1 iff arguments are equal - * textne - returns 1 iff arguments are not equal + * texteq - returns 1 iff arguments are equal + * textne - returns 1 iff arguments are not equal */ bool -texteq(struct varlena *arg1, struct varlena *arg2) +texteq(struct varlena * arg1, struct varlena * arg2) { - register int len; - register char *a1p, *a2p; - - if (arg1 == NULL || arg2 == NULL) - return((bool) NULL); - if ((len = arg1->vl_len) != arg2->vl_len) - return((bool) 0); - a1p = arg1->vl_dat; - a2p = arg2->vl_dat; - /* - * Varlenas are stored as the total size (data + size variable) - * followed by the data. - * Use VARHDRSZ instead of explicit sizeof() - thomas 1997-07-10 - */ - len -= VARHDRSZ; - while (len-- != 0) - if (*a1p++ != *a2p++) - return((bool) 0); - return((bool) 1); -} /* texteq() */ + register int len; + register char *a1p, + *a2p; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) NULL); + if ((len = arg1->vl_len) != arg2->vl_len) + return ((bool) 0); + a1p = arg1->vl_dat; + a2p = arg2->vl_dat; + + /* + * Varlenas are stored as the total size (data + size variable) + * followed by the data. Use VARHDRSZ instead of explicit sizeof() - + * thomas 1997-07-10 + */ + len -= VARHDRSZ; + while (len-- != 0) + if (*a1p++ != *a2p++) + return ((bool) 0); + return ((bool) 1); +} /* texteq() */ bool -textne(struct varlena *arg1, struct varlena *arg2) +textne(struct varlena * arg1, struct varlena * arg2) { - return((bool) !texteq(arg1, arg2)); + return ((bool) ! texteq(arg1, arg2)); } /* text_lt() * Comparison function for text strings. * Includes locale support, but must copy strings to temporary memory - * to allow null-termination for inputs to strcoll(). + * to allow null-termination for inputs to strcoll(). * XXX HACK code for textlen() indicates that there can be embedded nulls - * but it appears that most routines (incl. this one) assume not! - tgl 97/04/07 + * but it appears that most routines (incl. this one) assume not! - tgl 97/04/07 */ bool -text_lt(struct varlena *arg1, struct varlena *arg2) +text_lt(struct varlena * arg1, struct varlena * arg2) { - bool result; + bool result; #ifdef USE_LOCALE - int cval; + int cval; + #endif - int len; - unsigned char *a1p, *a2p; - - if (arg1 == NULL || arg2 == NULL) - return((bool) FALSE); - - len = (((VARSIZE(arg1) <= VARSIZE(arg2))? VARSIZE(arg1): VARSIZE(arg2))-VARHDRSZ); - + int len; + unsigned char *a1p, + *a2p; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) FALSE); + + len = (((VARSIZE(arg1) <= VARSIZE(arg2)) ? VARSIZE(arg1) : VARSIZE(arg2)) - VARHDRSZ); + #ifdef USE_LOCALE - a1p = (unsigned char *) palloc (len+1); - a2p = (unsigned char *) palloc (len+1); + a1p = (unsigned char *) palloc(len + 1); + a2p = (unsigned char *) palloc(len + 1); - memcpy(a1p, VARDATA(arg1), len); - *(a1p+len) = '\0'; - memcpy(a2p, VARDATA(arg2), len); - *(a2p+len) = '\0'; + memcpy(a1p, VARDATA(arg1), len); + *(a1p + len) = '\0'; + memcpy(a2p, VARDATA(arg2), len); + *(a2p + len) = '\0'; - cval = strcoll(a1p,a2p); - result = ((cval < 0) || ((cval == 0) && (VARSIZE(arg1) < VARSIZE(arg2)))); + cval = strcoll(a1p, a2p); + result = ((cval < 0) || ((cval == 0) && (VARSIZE(arg1) < VARSIZE(arg2)))); - pfree (a1p); - pfree (a2p); + pfree(a1p); + pfree(a2p); #else - a1p = (unsigned char *)VARDATA(arg1); - a2p = (unsigned char *)VARDATA(arg2); - - while (len != 0 && *a1p == *a2p) { - a1p++; - a2p++; - len--; - }; - - result = (len? (*a1p < *a2p): (VARSIZE(arg1) < VARSIZE(arg2))); + a1p = (unsigned char *) VARDATA(arg1); + a2p = (unsigned char *) VARDATA(arg2); + + while (len != 0 && *a1p == *a2p) + { + a1p++; + a2p++; + len--; + }; + + result = (len ? (*a1p < *a2p) : (VARSIZE(arg1) < VARSIZE(arg2))); #endif - return(result); -} /* text_lt() */ + return (result); +} /* text_lt() */ /* text_le() * Comparison function for text strings. * Includes locale support, but must copy strings to temporary memory - * to allow null-termination for inputs to strcoll(). + * to allow null-termination for inputs to strcoll(). * XXX HACK code for textlen() indicates that there can be embedded nulls - * but it appears that most routines (incl. this one) assume not! - tgl 97/04/07 + * but it appears that most routines (incl. this one) assume not! - tgl 97/04/07 */ bool -text_le(struct varlena *arg1, struct varlena *arg2) +text_le(struct varlena * arg1, struct varlena * arg2) { - bool result; + bool result; #ifdef USE_LOCALE - int cval; + int cval; + #endif - int len; - unsigned char *a1p, *a2p; - - if (arg1 == NULL || arg2 == NULL) - return((bool) 0); - - len = (((VARSIZE(arg1) <= VARSIZE(arg2))? VARSIZE(arg1): VARSIZE(arg2))-VARHDRSZ); - + int len; + unsigned char *a1p, + *a2p; + + if (arg1 == NULL || arg2 == NULL) + return ((bool) 0); + + len = (((VARSIZE(arg1) <= VARSIZE(arg2)) ? VARSIZE(arg1) : VARSIZE(arg2)) - VARHDRSZ); + #ifdef USE_LOCALE - a1p = (unsigned char *) palloc (len+1); - a2p = (unsigned char *) palloc (len+1); + a1p = (unsigned char *) palloc(len + 1); + a2p = (unsigned char *) palloc(len + 1); - memcpy(a1p, VARDATA(arg1), len); - *(a1p+len) = '\0'; - memcpy(a2p, VARDATA(arg2), len); - *(a2p+len) = '\0'; + memcpy(a1p, VARDATA(arg1), len); + *(a1p + len) = '\0'; + memcpy(a2p, VARDATA(arg2), len); + *(a2p + len) = '\0'; - cval = strcoll(a1p,a2p); - result = ((cval < 0) || ((cval == 0) && (VARSIZE(arg1) <= VARSIZE(arg2)))); + cval = strcoll(a1p, a2p); + result = ((cval < 0) || ((cval == 0) && (VARSIZE(arg1) <= VARSIZE(arg2)))); - pfree (a1p); - pfree (a2p); + pfree(a1p); + pfree(a2p); #else - a1p = (unsigned char *)VARDATA(arg1); - a2p = (unsigned char *)VARDATA(arg2); - - while (len != 0 && *a1p == *a2p) { - a1p++; - a2p++; - len--; - }; - - result = (len? (*a1p <= *a2p): (VARSIZE(arg1) <= VARSIZE(arg2))); + a1p = (unsigned char *) VARDATA(arg1); + a2p = (unsigned char *) VARDATA(arg2); + + while (len != 0 && *a1p == *a2p) + { + a1p++; + a2p++; + len--; + }; + + result = (len ? (*a1p <= *a2p) : (VARSIZE(arg1) <= VARSIZE(arg2))); #endif - return(result); -} /* text_le() */ + return (result); +} /* text_le() */ bool -text_gt(struct varlena *arg1, struct varlena *arg2) +text_gt(struct varlena * arg1, struct varlena * arg2) { - return ((bool) !text_le(arg1, arg2)); + return ((bool) ! text_le(arg1, arg2)); } bool -text_ge(struct varlena *arg1, struct varlena *arg2) +text_ge(struct varlena * arg1, struct varlena * arg2) { - return ((bool) !text_lt(arg1, arg2)); + return ((bool) ! text_lt(arg1, arg2)); } /*------------------------------------------------------------- @@ -453,13 +482,13 @@ text_ge(struct varlena *arg1, struct varlena *arg2) *------------------------------------------------------------- */ int32 -byteaGetSize(struct varlena *v) +byteaGetSize(struct varlena * v) { - register int len; - - len = v->vl_len - sizeof(v->vl_len); - - return(len); + register int len; + + len = v->vl_len - sizeof(v->vl_len); + + return (len); } /*------------------------------------------------------------- @@ -471,21 +500,22 @@ byteaGetSize(struct varlena *v) *------------------------------------------------------------- */ int32 -byteaGetByte(struct varlena *v, int32 n) +byteaGetByte(struct varlena * v, int32 n) { - int len; - int byte; - - len = byteaGetSize(v); - - if (n>=len) { - elog(WARN, "byteaGetByte: index (=%d) out of range [0..%d]", - n,len-1); - } - - byte = (unsigned char) (v->vl_dat[n]); - - return((int32) byte); + int len; + int byte; + + len = byteaGetSize(v); + + if (n >= len) + { + elog(WARN, "byteaGetByte: index (=%d) out of range [0..%d]", + n, len - 1); + } + + byte = (unsigned char) (v->vl_dat[n]); + + return ((int32) byte); } /*------------------------------------------------------------- @@ -498,22 +528,27 @@ byteaGetByte(struct varlena *v, int32 n) *------------------------------------------------------------- */ int32 -byteaGetBit(struct varlena *v, int32 n) +byteaGetBit(struct varlena * v, int32 n) { - int byteNo, bitNo; - int byte; - - byteNo = n/8; - bitNo = n%8; - - byte = byteaGetByte(v, byteNo); - - if (byte & (1<<bitNo)) { - return((int32)1); - } else { - return((int32)0); - } + int byteNo, + bitNo; + int byte; + + byteNo = n / 8; + bitNo = n % 8; + + byte = byteaGetByte(v, byteNo); + + if (byte & (1 << bitNo)) + { + return ((int32) 1); + } + else + { + return ((int32) 0); + } } + /*------------------------------------------------------------- * byteaSetByte * @@ -523,35 +558,37 @@ byteaGetBit(struct varlena *v, int32 n) *------------------------------------------------------------- */ struct varlena * -byteaSetByte(struct varlena *v, int32 n, int32 newByte) +byteaSetByte(struct varlena * v, int32 n, int32 newByte) { - int len; - struct varlena *res; - - len = byteaGetSize(v); - - if (n>=len) { - elog(WARN, - "byteaSetByte: index (=%d) out of range [0..%d]", - n, len-1); - } - - /* - * Make a copy of the original varlena. - */ - res = (struct varlena *) palloc(VARSIZE(v)); - if (res==NULL) { - elog(WARN, "byteaSetByte: Out of memory (%d bytes requested)", - VARSIZE(v)); - } - memmove((char *)res, (char *)v, VARSIZE(v)); - - /* - * Now set the byte. - */ - res->vl_dat[n] = newByte; - - return(res); + int len; + struct varlena *res; + + len = byteaGetSize(v); + + if (n >= len) + { + elog(WARN, + "byteaSetByte: index (=%d) out of range [0..%d]", + n, len - 1); + } + + /* + * Make a copy of the original varlena. + */ + res = (struct varlena *) palloc(VARSIZE(v)); + if (res == NULL) + { + elog(WARN, "byteaSetByte: Out of memory (%d bytes requested)", + VARSIZE(v)); + } + memmove((char *) res, (char *) v, VARSIZE(v)); + + /* + * Now set the byte. + */ + res->vl_dat[n] = newByte; + + return (res); } /*------------------------------------------------------------- @@ -563,39 +600,45 @@ byteaSetByte(struct varlena *v, int32 n, int32 newByte) *------------------------------------------------------------- */ struct varlena * -byteaSetBit(struct varlena *v, int32 n, int32 newBit) +byteaSetBit(struct varlena * v, int32 n, int32 newBit) { - struct varlena *res; - int oldByte, newByte; - int byteNo, bitNo; - - /* - * sanity check! - */ - if (newBit != 0 && newBit != 1) { - elog(WARN, "byteaSetByte: new bit must be 0 or 1"); - } - - /* - * get the byte where the bit we want is stored. - */ - byteNo = n / 8; - bitNo = n % 8; - oldByte = byteaGetByte(v, byteNo); - - /* - * calculate the new value for that byte - */ - if (newBit == 0) { - newByte = oldByte & (~(1<<bitNo)); - } else { - newByte = oldByte | (1<<bitNo); - } - - /* - * NOTE: 'byteaSetByte' creates a copy of 'v' & sets the byte. - */ - res = byteaSetByte(v, byteNo, newByte); - - return(res); + struct varlena *res; + int oldByte, + newByte; + int byteNo, + bitNo; + + /* + * sanity check! + */ + if (newBit != 0 && newBit != 1) + { + elog(WARN, "byteaSetByte: new bit must be 0 or 1"); + } + + /* + * get the byte where the bit we want is stored. + */ + byteNo = n / 8; + bitNo = n % 8; + oldByte = byteaGetByte(v, byteNo); + + /* + * calculate the new value for that byte + */ + if (newBit == 0) + { + newByte = oldByte & (~(1 << bitNo)); + } + else + { + newByte = oldByte | (1 << bitNo); + } + + /* + * NOTE: 'byteaSetByte' creates a copy of 'v' & sets the byte. + */ + res = byteaSetByte(v, byteNo, newByte); + + return (res); } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index aee835943e3..3edddd3c1aa 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * catcache.c-- - * System catalog cache for tuples matching a key. + * System catalog cache for tuples matching a key. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.10 1997/08/26 19:24:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.11 1997/09/07 04:52:56 momjian Exp $ * * Notes: - * XXX This needs to use exception.h to handle recovery when - * an abort occurs during DisableCache. - * + * XXX This needs to use exception.h to handle recovery when + * an abort occurs during DisableCache. + * *------------------------------------------------------------------------- */ #include <string.h> @@ -26,7 +26,7 @@ #include "miscadmin.h" #include "utils/portal.h" #include "utils/catcache.h" -#include "fmgr.h" /* for F_BOOLEQ, etc. DANGER */ +#include "fmgr.h" /* for F_BOOLEQ, etc. DANGER */ #include "utils/elog.h" #include "utils/palloc.h" #include "utils/mcxt.h" @@ -34,29 +34,31 @@ #include "catalog/pg_type.h" /* for OID of int28 type */ #include "lib/dllist.h" -static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e); -static Index CatalogCacheComputeHashIndex(struct catcache *cacheInP); -static Index CatalogCacheComputeTupleHashIndex(struct catcache *cacheInOutP, - Relation relation, HeapTuple tuple); -static void CatalogCacheInitializeCache(struct catcache *cache, - Relation relation); -static long comphash(long l, char *v); +static void CatCacheRemoveCTup(CatCache * cache, Dlelem * e); +static Index CatalogCacheComputeHashIndex(struct catcache * cacheInP); +static Index +CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, + Relation relation, HeapTuple tuple); +static void +CatalogCacheInitializeCache(struct catcache * cache, + Relation relation); +static long comphash(long l, char *v); /* ---------------- - * variables, macros and other stuff + * variables, macros and other stuff * - * note CCSIZE allocates 51 buckets .. one was already allocated in - * the catcache structure. + * note CCSIZE allocates 51 buckets .. one was already allocated in + * the catcache structure. * ---------------- */ #ifdef CACHEDEBUG -#define CACHE1_elog(a,b) elog(a,b) -#define CACHE2_elog(a,b,c) elog(a,b,c) -#define CACHE3_elog(a,b,c,d) elog(a,b,c,d) -#define CACHE4_elog(a,b,c,d,e) elog(a,b,c,d,e) -#define CACHE5_elog(a,b,c,d,e,f) elog(a,b,c,d,e,f) -#define CACHE6_elog(a,b,c,d,e,f,g) elog(a,b,c,d,e,f,g) +#define CACHE1_elog(a,b) elog(a,b) +#define CACHE2_elog(a,b,c) elog(a,b,c) +#define CACHE3_elog(a,b,c,d) elog(a,b,c,d) +#define CACHE4_elog(a,b,c,d,e) elog(a,b,c,d,e) +#define CACHE5_elog(a,b,c,d,e,f) elog(a,b,c,d,e,f) +#define CACHE6_elog(a,b,c,d,e,f,g) elog(a,b,c,d,e,f,g) #else #define CACHE1_elog(a,b) #define CACHE2_elog(a,b,c) @@ -66,209 +68,217 @@ static long comphash(long l, char *v); #define CACHE6_elog(a,b,c,d,e,f,g) #endif -CatCache *Caches = NULL; +CatCache *Caches = NULL; GlobalMemory CacheCxt; -static int DisableCache; +static int DisableCache; /* ---------------- - * EQPROC is used in CatalogCacheInitializeCache - * XXX this should be replaced by catalog lookups soon + * EQPROC is used in CatalogCacheInitializeCache + * XXX this should be replaced by catalog lookups soon * ---------------- */ -static long eqproc[] = { - F_BOOLEQ, 0l, F_CHAREQ, F_CHAR16EQ, 0l, - F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, 0l, F_TEXTEQ, - F_OIDEQ, 0l, 0l, 0l, F_OID8EQ +static long eqproc[] = { + F_BOOLEQ, 0l, F_CHAREQ, F_CHAR16EQ, 0l, + F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, 0l, F_TEXTEQ, + F_OIDEQ, 0l, 0l, 0l, F_OID8EQ }; -#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-16] +#define EQPROC(SYSTEMTYPEOID) eqproc[(SYSTEMTYPEOID)-16] /* ---------------------------------------------------------------- - * internal support functions + * internal support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * CatalogCacheInitializeCache + * CatalogCacheInitializeCache * -------------------------------- */ #ifdef CACHEDEBUG #define CatalogCacheInitializeCache_DEBUG1 \ - elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ - if (relation) \ - elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \ - else \ - elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \ - cache->cc_relname) + elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ + if (relation) \ + elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \ + else \ + elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \ + cache->cc_relname) #define CatalogCacheInitializeCache_DEBUG2 \ - if (cache->cc_key[i] > 0) { \ - elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \ - i+1, cache->cc_nkeys, cache->cc_key[i], \ - relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \ - } else { \ - elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ - i+1, cache->cc_nkeys, cache->cc_key[i]); \ - } + if (cache->cc_key[i] > 0) { \ + elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \ + i+1, cache->cc_nkeys, cache->cc_key[i], \ + relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \ + } else { \ + elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ + i+1, cache->cc_nkeys, cache->cc_key[i]); \ + } #else #define CatalogCacheInitializeCache_DEBUG1 #define CatalogCacheInitializeCache_DEBUG2 #endif static void -CatalogCacheInitializeCache(struct catcache *cache, - Relation relation) +CatalogCacheInitializeCache(struct catcache * cache, + Relation relation) { - MemoryContext oldcxt; - short didopen = 0; - short i; - TupleDesc tupdesc; - - CatalogCacheInitializeCache_DEBUG1; - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * If no relation was passed we must open it to get access to - * its fields. If one of the other caches has already opened - * it we use heap_open() instead of heap_openr() - * ---------------- - */ - if (! RelationIsValid(relation)) { - struct catcache *cp; + MemoryContext oldcxt; + short didopen = 0; + short i; + TupleDesc tupdesc; + + CatalogCacheInitializeCache_DEBUG1; + /* ---------------- - * scan the caches to see if any other cache has opened the relation + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction * ---------------- */ - for (cp = Caches; cp; cp = cp->cc_next) { - if (strncmp(cp->cc_relname, cache->cc_relname, NAMEDATALEN) == 0) { - if (cp->relationId != InvalidOid) - break; - } + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * If no relation was passed we must open it to get access to + * its fields. If one of the other caches has already opened + * it we use heap_open() instead of heap_openr() + * ---------------- + */ + if (!RelationIsValid(relation)) + { + struct catcache *cp; + + /* ---------------- + * scan the caches to see if any other cache has opened the relation + * ---------------- + */ + for (cp = Caches; cp; cp = cp->cc_next) + { + if (strncmp(cp->cc_relname, cache->cc_relname, NAMEDATALEN) == 0) + { + if (cp->relationId != InvalidOid) + break; + } + } + + /* ---------------- + * open the relation by name or by id + * ---------------- + */ + if (cp) + relation = heap_open(cp->relationId); + else + { + relation = heap_openr(cache->cc_relname); + } + + didopen = 1; } - + /* ---------------- - * open the relation by name or by id + * initialize the cache's relation id * ---------------- */ - if (cp) - relation = heap_open(cp->relationId); - else - { - relation = heap_openr(cache->cc_relname); - } - - didopen = 1; - } - - /* ---------------- - * initialize the cache's relation id - * ---------------- - */ - Assert(RelationIsValid(relation)); - cache->relationId = RelationGetRelationId(relation); - tupdesc = cache->cc_tupdesc = RelationGetTupleDescriptor(relation); - - CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %d, %d keys", - cache->relationId, cache->cc_nkeys); - - /* ---------------- - * initialize cache's key information - * ---------------- - */ - for (i = 0; i < cache->cc_nkeys; ++i) { - CatalogCacheInitializeCache_DEBUG2; - - if (cache->cc_key[i] > 0) { - - /* - * Yoiks. The implementation of the hashing code and the - * implementation of int28's are at loggerheads. The right - * thing to do is to throw out the implementation of int28's - * altogether; until that happens, we do the right thing here - * to guarantee that the hash key generator doesn't try to - * dereference an int2 by mistake. - */ - - if (tupdesc->attrs[cache->cc_key[i]-1]->atttypid == INT28OID) - cache->cc_klen[i] = sizeof (short); - else - cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i]-1]->attlen; - - cache->cc_skey[i].sk_procedure = - EQPROC(tupdesc->attrs[cache->cc_key[i]-1]->atttypid); - - fmgr_info(cache->cc_skey[i].sk_procedure, - (func_ptr *) &cache->cc_skey[i].sk_func, - (int *) &cache->cc_skey[i].sk_nargs); - - CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x", - &relation->rd_rel->relname, - i, - tupdesc->attrs[ cache->cc_key[i]-1 ]->attlen, - cache); + Assert(RelationIsValid(relation)); + cache->relationId = RelationGetRelationId(relation); + tupdesc = cache->cc_tupdesc = RelationGetTupleDescriptor(relation); + + CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %d, %d keys", + cache->relationId, cache->cc_nkeys); + + /* ---------------- + * initialize cache's key information + * ---------------- + */ + for (i = 0; i < cache->cc_nkeys; ++i) + { + CatalogCacheInitializeCache_DEBUG2; + + if (cache->cc_key[i] > 0) + { + + /* + * Yoiks. The implementation of the hashing code and the + * implementation of int28's are at loggerheads. The right + * thing to do is to throw out the implementation of int28's + * altogether; until that happens, we do the right thing here + * to guarantee that the hash key generator doesn't try to + * dereference an int2 by mistake. + */ + + if (tupdesc->attrs[cache->cc_key[i] - 1]->atttypid == INT28OID) + cache->cc_klen[i] = sizeof(short); + else + cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i] - 1]->attlen; + + cache->cc_skey[i].sk_procedure = + EQPROC(tupdesc->attrs[cache->cc_key[i] - 1]->atttypid); + + fmgr_info(cache->cc_skey[i].sk_procedure, + (func_ptr *) & cache->cc_skey[i].sk_func, + (int *) &cache->cc_skey[i].sk_nargs); + + CACHE5_elog(DEBUG, "CatalogCacheInit %16s %d %d %x", + &relation->rd_rel->relname, + i, + tupdesc->attrs[cache->cc_key[i] - 1]->attlen, + cache); + } } - } - - /* ---------------- - * close the relation if we opened it - * ---------------- - */ - if (didopen) - heap_close(relation); - - /* ---------------- - * initialize index information for the cache. this - * should only be done once per cache. - * ---------------- - */ - if (cache->cc_indname != NULL && cache->indexId == InvalidOid) + + /* ---------------- + * close the relation if we opened it + * ---------------- + */ + if (didopen) + heap_close(relation); + + /* ---------------- + * initialize index information for the cache. this + * should only be done once per cache. + * ---------------- + */ + if (cache->cc_indname != NULL && cache->indexId == InvalidOid) { - if (RelationGetRelationTupleForm(relation)->relhasindex) + if (RelationGetRelationTupleForm(relation)->relhasindex) { - /* - * If the index doesn't exist we are in trouble. - */ - relation = index_openr( cache->cc_indname); - Assert(relation); - cache->indexId = RelationGetRelationId(relation); - index_close(relation); + + /* + * If the index doesn't exist we are in trouble. + */ + relation = index_openr(cache->cc_indname); + Assert(relation); + cache->indexId = RelationGetRelationId(relation); + index_close(relation); } - else - cache->cc_indname = NULL; + else + cache->cc_indname = NULL; } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); + + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * CatalogCacheSetId + * CatalogCacheSetId * - * XXX temporary function + * XXX temporary function * -------------------------------- */ #ifdef NOT_USED void -CatalogCacheSetId(CatCache *cacheInOutP, int id) +CatalogCacheSetId(CatCache * cacheInOutP, int id) { - Assert(id == InvalidCatalogCacheId || id >= 0); - cacheInOutP->id = id; + Assert(id == InvalidCatalogCacheId || id >= 0); + cacheInOutP->id = id; } + #endif /* ---------------- * comphash -- - * Compute a hash value, somehow. + * Compute a hash value, somehow. * * XXX explain algorithm here. * @@ -279,798 +289,846 @@ CatalogCacheSetId(CatCache *cacheInOutP, int id) static long comphash(long l, register char *v) { - long i; - NameData n; - - CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v); - - switch (l) { - case 1: - case 2: - case 4: - return((long) v); - } - - if (l == NAMEDATALEN) { - /* if it's a name, make sure that the values - are null-padded. - - Note that this other fixed-length types can also have - the same typelen so this may break them - XXX - */ - namestrcpy(&n,v); - v = n.data; - } else - if (l < 0) - l = VARSIZE(v); - - i = 0; - while (l--) { - i += *v++; - } - return(i); + long i; + NameData n; + + CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v); + + switch (l) + { + case 1: + case 2: + case 4: + return ((long) v); + } + + if (l == NAMEDATALEN) + { + + /* + * if it's a name, make sure that the values are null-padded. + * + * Note that this other fixed-length types can also have the same + * typelen so this may break them - XXX + */ + namestrcpy(&n, v); + v = n.data; + } + else if (l < 0) + l = VARSIZE(v); + + i = 0; + while (l--) + { + i += *v++; + } + return (i); } /* -------------------------------- - * CatalogCacheComputeHashIndex + * CatalogCacheComputeHashIndex * -------------------------------- */ -static Index -CatalogCacheComputeHashIndex(struct catcache *cacheInP) +static Index +CatalogCacheComputeHashIndex(struct catcache * cacheInP) { - Index hashIndex; - hashIndex = 0x0; - CACHE6_elog(DEBUG,"CatalogCacheComputeHashIndex %s %d %d %d %x", - cacheInP->cc_relname, - cacheInP->cc_nkeys, - cacheInP->cc_klen[0], - cacheInP->cc_klen[1], - cacheInP); - - switch (cacheInP->cc_nkeys) { - case 4: - hashIndex ^= comphash(cacheInP->cc_klen[3], - (char*)cacheInP->cc_skey[3].sk_argument) << 9; - /* FALLTHROUGH */ - case 3: - hashIndex ^= comphash(cacheInP->cc_klen[2], - (char*)cacheInP->cc_skey[2].sk_argument) << 6; - /* FALLTHROUGH */ - case 2: - hashIndex ^= comphash(cacheInP->cc_klen[1], - (char*)cacheInP->cc_skey[1].sk_argument) << 3; - /* FALLTHROUGH */ - case 1: - hashIndex ^= comphash(cacheInP->cc_klen[0], - (char*)cacheInP->cc_skey[0].sk_argument); - break; - default: - elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); - break; - } - hashIndex %= cacheInP->cc_size; - return (hashIndex); + Index hashIndex; + + hashIndex = 0x0; + CACHE6_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %d %d %x", + cacheInP->cc_relname, + cacheInP->cc_nkeys, + cacheInP->cc_klen[0], + cacheInP->cc_klen[1], + cacheInP); + + switch (cacheInP->cc_nkeys) + { + case 4: + hashIndex ^= comphash(cacheInP->cc_klen[3], + (char *) cacheInP->cc_skey[3].sk_argument) << 9; + /* FALLTHROUGH */ + case 3: + hashIndex ^= comphash(cacheInP->cc_klen[2], + (char *) cacheInP->cc_skey[2].sk_argument) << 6; + /* FALLTHROUGH */ + case 2: + hashIndex ^= comphash(cacheInP->cc_klen[1], + (char *) cacheInP->cc_skey[1].sk_argument) << 3; + /* FALLTHROUGH */ + case 1: + hashIndex ^= comphash(cacheInP->cc_klen[0], + (char *) cacheInP->cc_skey[0].sk_argument); + break; + default: + elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); + break; + } + hashIndex %= cacheInP->cc_size; + return (hashIndex); } /* -------------------------------- - * CatalogCacheComputeTupleHashIndex + * CatalogCacheComputeTupleHashIndex * -------------------------------- */ -static Index -CatalogCacheComputeTupleHashIndex(struct catcache *cacheInOutP, - Relation relation, - HeapTuple tuple) +static Index +CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP, + Relation relation, + HeapTuple tuple) { - bool isNull = '\0'; - if (cacheInOutP->relationId == InvalidOid) - CatalogCacheInitializeCache(cacheInOutP, relation); - switch (cacheInOutP->cc_nkeys) { - case 4: - cacheInOutP->cc_skey[3].sk_argument = - (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[3], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 3: - cacheInOutP->cc_skey[2].sk_argument = - (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[2], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 2: - cacheInOutP->cc_skey[1].sk_argument = - (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[1], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - /* FALLTHROUGH */ - case 1: - cacheInOutP->cc_skey[0].sk_argument = - (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) - ? (Datum)tuple->t_oid - : (Datum)fastgetattr(tuple, - cacheInOutP->cc_key[0], - RelationGetTupleDescriptor(relation), - &isNull); - Assert(!isNull); - break; - default: - elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", - cacheInOutP->cc_nkeys - ); - break; - } - - return - CatalogCacheComputeHashIndex(cacheInOutP); + bool isNull = '\0'; + + if (cacheInOutP->relationId == InvalidOid) + CatalogCacheInitializeCache(cacheInOutP, relation); + switch (cacheInOutP->cc_nkeys) + { + case 4: + cacheInOutP->cc_skey[3].sk_argument = + (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[3], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 3: + cacheInOutP->cc_skey[2].sk_argument = + (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[2], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 2: + cacheInOutP->cc_skey[1].sk_argument = + (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[1], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + /* FALLTHROUGH */ + case 1: + cacheInOutP->cc_skey[0].sk_argument = + (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) + ? (Datum) tuple->t_oid + : (Datum) fastgetattr(tuple, + cacheInOutP->cc_key[0], + RelationGetTupleDescriptor(relation), + &isNull); + Assert(!isNull); + break; + default: + elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", + cacheInOutP->cc_nkeys + ); + break; + } + + return + CatalogCacheComputeHashIndex(cacheInOutP); } /* -------------------------------- - * CatCacheRemoveCTup + * CatCacheRemoveCTup * -------------------------------- */ static void -CatCacheRemoveCTup(CatCache *cache, Dlelem *elt) +CatCacheRemoveCTup(CatCache * cache, Dlelem * elt) { - CatCTup *ct; - CatCTup *other_ct; - Dlelem *other_elt; - - if (elt) - ct = (CatCTup*) DLE_VAL(elt); - else - return; - - other_elt = ct->ct_node; - other_ct = (CatCTup*)DLE_VAL(other_elt); - DLRemove(other_elt); - DLFreeElem(other_elt); - free(other_ct); - DLRemove(elt); - DLFreeElem(elt); - free(ct); - --cache->cc_ntup; + CatCTup *ct; + CatCTup *other_ct; + Dlelem *other_elt; + + if (elt) + ct = (CatCTup *) DLE_VAL(elt); + else + return; + + other_elt = ct->ct_node; + other_ct = (CatCTup *) DLE_VAL(other_elt); + DLRemove(other_elt); + DLFreeElem(other_elt); + free(other_ct); + DLRemove(elt); + DLFreeElem(elt); + free(ct); + --cache->cc_ntup; } /* -------------------------------- - * CatalogCacheIdInvalidate() + * CatalogCacheIdInvalidate() * - * Invalidate a tuple given a cache id. In this case the id should always - * be found (whether the cache has opened its relation or not). Of course, - * if the cache has yet to open its relation, there will be no tuples so - * no problem. + * Invalidate a tuple given a cache id. In this case the id should always + * be found (whether the cache has opened its relation or not). Of course, + * if the cache has yet to open its relation, there will be no tuples so + * no problem. * -------------------------------- */ void -CatalogCacheIdInvalidate(int cacheId, /* XXX */ - Index hashIndex, - ItemPointer pointer) +CatalogCacheIdInvalidate(int cacheId, /* XXX */ + Index hashIndex, + ItemPointer pointer) { - CatCache *ccp; - CatCTup *ct; - Dlelem *elt; - MemoryContext oldcxt; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(hashIndex < NCCBUCK); - Assert(ItemPointerIsValid(pointer)); - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); - - /* ---------------- - * switch to the cache context for our memory allocations - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * inspect every cache that could contain the tuple - * ---------------- - */ - for (ccp = Caches; ccp; ccp = ccp->cc_next) { - if (cacheId != ccp->id) - continue; + CatCache *ccp; + CatCTup *ct; + Dlelem *elt; + MemoryContext oldcxt; + /* ---------------- - * inspect the hash bucket until we find a match or exhaust + * sanity checks * ---------------- */ - for (elt = DLGetHead(ccp->cc_cache[hashIndex]); - elt; - elt = DLGetSucc(elt)) - { - ct = (CatCTup*) DLE_VAL(elt); - if (ItemPointerEquals(pointer, &ct->ct_tup->t_ctid)) - break; - } - + Assert(hashIndex < NCCBUCK); + Assert(ItemPointerIsValid(pointer)); + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); + /* ---------------- - * if we found a matching tuple, invalidate it. + * switch to the cache context for our memory allocations * ---------------- */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * inspect every cache that could contain the tuple + * ---------------- + */ + for (ccp = Caches; ccp; ccp = ccp->cc_next) + { + if (cacheId != ccp->id) + continue; + /* ---------------- + * inspect the hash bucket until we find a match or exhaust + * ---------------- + */ + for (elt = DLGetHead(ccp->cc_cache[hashIndex]); + elt; + elt = DLGetSucc(elt)) + { + ct = (CatCTup *) DLE_VAL(elt); + if (ItemPointerEquals(pointer, &ct->ct_tup->t_ctid)) + break; + } - if (elt) { - CatCacheRemoveCTup(ccp, elt); + /* ---------------- + * if we found a matching tuple, invalidate it. + * ---------------- + */ - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + if (elt) + { + CatCacheRemoveCTup(ccp, elt); + + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + } + + if (cacheId != InvalidCatalogCacheId) + break; } - - if (cacheId != InvalidCatalogCacheId) - break; - } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - /* sendpm('I', "Invalidated tuple"); */ + + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + /* sendpm('I', "Invalidated tuple"); */ } /* ---------------------------------------------------------------- - * public functions + * public functions * - * ResetSystemCache - * InitIndexedSysCache - * InitSysCache - * SearchSysCache - * RelationInvalidateCatalogCacheTuple + * ResetSystemCache + * InitIndexedSysCache + * InitSysCache + * SearchSysCache + * RelationInvalidateCatalogCacheTuple * ---------------------------------------------------------------- */ /* -------------------------------- - * ResetSystemCache + * ResetSystemCache * -------------------------------- */ void ResetSystemCache() { - MemoryContext oldcxt; - struct catcache *cache; - - /* ---------------- - * sanity checks - * ---------------- - */ - CACHE1_elog(DEBUG, "ResetSystemCache called"); - if (DisableCache) { - elog(WARN, "ResetSystemCache: Called while cache disabled"); - return; - } - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * here we purge the contents of all the caches - * - * for each system cache - * for each hash bucket - * for each tuple in hash bucket - * remove the tuple - * ---------------- - */ - for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) { - int hash; - for (hash = 0; hash < NCCBUCK; hash += 1) { - Dlelem *elt, *nextelt; - for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) { - nextelt = DLGetSucc(elt); - CatCacheRemoveCTup(cache, elt); - if (cache->cc_ntup == -1) - elog(WARN, "ResetSystemCache: cc_ntup<0 (software error)"); - } + MemoryContext oldcxt; + struct catcache *cache; + + /* ---------------- + * sanity checks + * ---------------- + */ + CACHE1_elog(DEBUG, "ResetSystemCache called"); + if (DisableCache) + { + elog(WARN, "ResetSystemCache: Called while cache disabled"); + return; + } + + /* ---------------- + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * here we purge the contents of all the caches + * + * for each system cache + * for each hash bucket + * for each tuple in hash bucket + * remove the tuple + * ---------------- + */ + for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) + { + int hash; + + for (hash = 0; hash < NCCBUCK; hash += 1) + { + Dlelem *elt, + *nextelt; + + for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) + { + nextelt = DLGetSucc(elt); + CatCacheRemoveCTup(cache, elt); + if (cache->cc_ntup == -1) + elog(WARN, "ResetSystemCache: cc_ntup<0 (software error)"); + } + } + cache->cc_ntup = 0; /* in case of WARN error above */ } - cache->cc_ntup = 0; /* in case of WARN error above */ - } - - CACHE1_elog(DEBUG, "end of ResetSystemCache call"); - - /* ---------------- - * back to the old context before we return... - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); + + CACHE1_elog(DEBUG, "end of ResetSystemCache call"); + + /* ---------------- + * back to the old context before we return... + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * InitIndexedSysCache + * InitIndexedSysCache * - * This allocates and initializes a cache for a system catalog relation. - * Actually, the cache is only partially initialized to avoid opening the - * relation. The relation will be opened and the rest of the cache - * structure initialized on the first access. + * This allocates and initializes a cache for a system catalog relation. + * Actually, the cache is only partially initialized to avoid opening the + * relation. The relation will be opened and the rest of the cache + * structure initialized on the first access. * -------------------------------- */ #ifdef CACHEDEBUG #define InitSysCache_DEBUG1 \ elog(DEBUG, "InitSysCache: rid=%d id=%d nkeys=%d size=%d\n", \ - cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ - for (i = 0; i < nkeys; i += 1) { \ - elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \ - cp->cc_key[i], cp->cc_klen[i], \ - cp->cc_skey[i].sk_flags, \ - cp->cc_skey[i].sk_attno, \ - cp->cc_skey[i].sk_procedure, \ - cp->cc_skey[i].sk_argument); \ - } + cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ + for (i = 0; i < nkeys; i += 1) { \ + elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \ + cp->cc_key[i], cp->cc_klen[i], \ + cp->cc_skey[i].sk_flags, \ + cp->cc_skey[i].sk_attno, \ + cp->cc_skey[i].sk_procedure, \ + cp->cc_skey[i].sk_argument); \ + } #else #define InitSysCache_DEBUG1 #endif -CatCache* +CatCache * InitSysCache(char *relname, - char *iname, - int id, - int nkeys, - int key[], - HeapTuple (*iScanfuncP)()) + char *iname, + int id, + int nkeys, + int key[], + HeapTuple(*iScanfuncP) ()) { - CatCache *cp; - register int i; - MemoryContext oldcxt; - - char *indname; - - indname = (iname) ? iname : NULL; - - /* ---------------- - * first switch to the cache context so our allocations - * do not vanish at the end of a transaction - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * allocate a new cache structure - * ---------------- - */ - cp = (CatCache *)palloc(sizeof(CatCache)); - memset((char*)cp, 0, sizeof(CatCache)); - - /* ---------------- - * initialize the cache buckets (each bucket is a list header) - * and the LRU tuple list - * ---------------- - */ - { - /* - * We can only do this optimization because the number of hash - * buckets never changes. Without it, we call malloc() too much. - * We could move this to dllist.c, but the way we do this is not - * dynamic/portabl, so why allow other routines to use it. - */ - Dllist *cache_begin = malloc((NCCBUCK+1)*sizeof(Dllist)); - for (i = 0; i <= NCCBUCK; ++i) { - cp->cc_cache[i] = &cache_begin[i]; - cp->cc_cache[i]->dll_head = 0; - cp->cc_cache[i]->dll_tail = 0; - } - } - - cp->cc_lrulist = DLNewList(); - - /* ---------------- - * Caches is the pointer to the head of the list of all the - * system caches. here we add the new cache to the top of the list. - * ---------------- - */ - cp->cc_next = Caches; /* list of caches (single link) */ - Caches = cp; - - /* ---------------- - * initialize the cache's relation information for the relation - * corresponding to this cache and initialize some of the the new - * cache's other internal fields. - * ---------------- - */ - cp->relationId = InvalidOid; - cp->indexId = InvalidOid; - cp->cc_relname = relname; - cp->cc_indname = indname; - cp->cc_tupdesc = (TupleDesc) NULL; - cp->id = id; - cp->cc_maxtup = MAXTUP; - cp->cc_size = NCCBUCK; - cp->cc_nkeys = nkeys; - cp->cc_iscanfunc = iScanfuncP; - - /* ---------------- - * initialize the cache's key information - * ---------------- - */ - for (i = 0; i < nkeys; ++i) { - cp->cc_key[i] = key[i]; - if (!key[i]) { - elog(FATAL, "InitSysCache: called with 0 key[%d]", i); - } - if (key[i] < 0) { - if (key[i] != ObjectIdAttributeNumber) { - elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i); - } else { - cp->cc_klen[i] = sizeof(Oid); + CatCache *cp; + register int i; + MemoryContext oldcxt; + + char *indname; + + indname = (iname) ? iname : NULL; + + /* ---------------- + * first switch to the cache context so our allocations + * do not vanish at the end of a transaction + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * allocate a new cache structure + * ---------------- + */ + cp = (CatCache *) palloc(sizeof(CatCache)); + memset((char *) cp, 0, sizeof(CatCache)); + + /* ---------------- + * initialize the cache buckets (each bucket is a list header) + * and the LRU tuple list + * ---------------- + */ + { + /* - * ScanKeyEntryData and struct skey are equivalent. It looks - * like a move was made to obsolete struct skey, but it - * didn't reach this file. Someday we should clean up this - * code and consolidate to ScanKeyEntry - mer 10 Nov 1991 + * We can only do this optimization because the number of hash + * buckets never changes. Without it, we call malloc() too much. + * We could move this to dllist.c, but the way we do this is not + * dynamic/portabl, so why allow other routines to use it. */ - ScanKeyEntryInitialize(&cp->cc_skey[i], - (bits16)0, - (AttrNumber)key[i], - (RegProcedure)F_OIDEQ, - (Datum)0); - continue; - } + Dllist *cache_begin = malloc((NCCBUCK + 1) * sizeof(Dllist)); + + for (i = 0; i <= NCCBUCK; ++i) + { + cp->cc_cache[i] = &cache_begin[i]; + cp->cc_cache[i]->dll_head = 0; + cp->cc_cache[i]->dll_tail = 0; + } + } + + cp->cc_lrulist = DLNewList(); + + /* ---------------- + * Caches is the pointer to the head of the list of all the + * system caches. here we add the new cache to the top of the list. + * ---------------- + */ + cp->cc_next = Caches; /* list of caches (single link) */ + Caches = cp; + + /* ---------------- + * initialize the cache's relation information for the relation + * corresponding to this cache and initialize some of the the new + * cache's other internal fields. + * ---------------- + */ + cp->relationId = InvalidOid; + cp->indexId = InvalidOid; + cp->cc_relname = relname; + cp->cc_indname = indname; + cp->cc_tupdesc = (TupleDesc) NULL; + cp->id = id; + cp->cc_maxtup = MAXTUP; + cp->cc_size = NCCBUCK; + cp->cc_nkeys = nkeys; + cp->cc_iscanfunc = iScanfuncP; + + /* ---------------- + * initialize the cache's key information + * ---------------- + */ + for (i = 0; i < nkeys; ++i) + { + cp->cc_key[i] = key[i]; + if (!key[i]) + { + elog(FATAL, "InitSysCache: called with 0 key[%d]", i); + } + if (key[i] < 0) + { + if (key[i] != ObjectIdAttributeNumber) + { + elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i); + } + else + { + cp->cc_klen[i] = sizeof(Oid); + + /* + * ScanKeyEntryData and struct skey are equivalent. It + * looks like a move was made to obsolete struct skey, but + * it didn't reach this file. Someday we should clean up + * this code and consolidate to ScanKeyEntry - mer 10 Nov + * 1991 + */ + ScanKeyEntryInitialize(&cp->cc_skey[i], + (bits16) 0, + (AttrNumber) key[i], + (RegProcedure) F_OIDEQ, + (Datum) 0); + continue; + } + } + + cp->cc_skey[i].sk_attno = key[i]; } - - cp->cc_skey[i].sk_attno = key[i]; - } - - /* ---------------- - * all done. new cache is initialized. print some debugging - * information, if appropriate. - * ---------------- - */ - InitSysCache_DEBUG1; - - /* ---------------- - * back to the old context before we return... - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - return(cp); + + /* ---------------- + * all done. new cache is initialized. print some debugging + * information, if appropriate. + * ---------------- + */ + InitSysCache_DEBUG1; + + /* ---------------- + * back to the old context before we return... + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + return (cp); } /* -------------------------------- - * SearchSysCache + * SearchSysCache * - * This call searches a system cache for a tuple, opening the relation - * if necessary (the first access to a particular cache). + * This call searches a system cache for a tuple, opening the relation + * if necessary (the first access to a particular cache). * -------------------------------- */ HeapTuple -SearchSysCache(struct catcache *cache, - Datum v1, - Datum v2, - Datum v3, - Datum v4) +SearchSysCache(struct catcache * cache, + Datum v1, + Datum v2, + Datum v3, + Datum v4) { - unsigned hash; - CatCTup *ct = NULL; - CatCTup *nct; - CatCTup *nct2; - Dlelem *elt; - HeapTuple ntp = 0; - Buffer buffer; - - Relation relation; - MemoryContext oldcxt; - - /* ---------------- - * sanity checks - * ---------------- - */ - if (cache->relationId == InvalidOid) - CatalogCacheInitializeCache(cache, NULL); - - /* ---------------- - * initialize the search key information - * ---------------- - */ - cache->cc_skey[0].sk_argument = v1; - cache->cc_skey[1].sk_argument = v2; - cache->cc_skey[2].sk_argument = v3; - cache->cc_skey[3].sk_argument = v4; - - /* ---------------- - * find the hash bucket in which to look for the tuple - * ---------------- - */ - hash = CatalogCacheComputeHashIndex(cache); - - /* ---------------- - * scan the hash bucket until we find a match or exhaust our tuples - * ---------------- - */ - for (elt = DLGetHead(cache->cc_cache[hash]); - elt; - elt = DLGetSucc(elt)) + unsigned hash; + CatCTup *ct = NULL; + CatCTup *nct; + CatCTup *nct2; + Dlelem *elt; + HeapTuple ntp = 0; + Buffer buffer; + + Relation relation; + MemoryContext oldcxt; + + /* ---------------- + * sanity checks + * ---------------- + */ + if (cache->relationId == InvalidOid) + CatalogCacheInitializeCache(cache, NULL); + + /* ---------------- + * initialize the search key information + * ---------------- + */ + cache->cc_skey[0].sk_argument = v1; + cache->cc_skey[1].sk_argument = v2; + cache->cc_skey[2].sk_argument = v3; + cache->cc_skey[3].sk_argument = v4; + + /* ---------------- + * find the hash bucket in which to look for the tuple + * ---------------- + */ + hash = CatalogCacheComputeHashIndex(cache); + + /* ---------------- + * scan the hash bucket until we find a match or exhaust our tuples + * ---------------- + */ + for (elt = DLGetHead(cache->cc_cache[hash]); + elt; + elt = DLGetSucc(elt)) { - ct = (CatCTup*)DLE_VAL(elt); - /* ---------------- - * see if the cached tuple matches our key. - * (should we be worried about time ranges? -cim 10/2/90) - * ---------------- - */ - if (heap_keytest(ct->ct_tup, - cache->cc_tupdesc, - cache->cc_nkeys, - cache->cc_skey)) - break; + ct = (CatCTup *) DLE_VAL(elt); + /* ---------------- + * see if the cached tuple matches our key. + * (should we be worried about time ranges? -cim 10/2/90) + * ---------------- + */ + if (heap_keytest(ct->ct_tup, + cache->cc_tupdesc, + cache->cc_nkeys, + cache->cc_skey)) + break; } - - /* ---------------- - * if we found a tuple in the cache, move it to the top of the - * lru list, and return it. - * ---------------- - */ - if (elt) { - Dlelem* old_lru_elt; - old_lru_elt = ((CatCTup*)DLE_VAL(elt))->ct_node; - DLRemove(old_lru_elt); - DLAddHead(cache->cc_lrulist, old_lru_elt); + + /* ---------------- + * if we found a tuple in the cache, move it to the top of the + * lru list, and return it. + * ---------------- + */ + if (elt) + { + Dlelem *old_lru_elt; + + old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node; + DLRemove(old_lru_elt); + DLAddHead(cache->cc_lrulist, old_lru_elt); #ifdef CACHEDEBUG + relation = heap_open(cache->relationId); + CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", + RelationGetRelationName(relation), hash); + heap_close(relation); +#endif /* CACHEDEBUG */ + + return (ct->ct_tup); + } + + /* ---------------- + * Tuple was not found in cache, so we have to try and + * retrieve it directly from the relation. If it's found, + * we add it to the cache. We must avoid recursion here, + * so we disable cache operations. If operations are + * currently disabled and we couldn't find the requested item + * in the cache, then this may be a recursive request, and we + * abort with an error. + * ---------------- + */ + + if (DisableCache) + { + elog(WARN, "SearchSysCache: Called while cache disabled"); + return ((HeapTuple) NULL); + } + + /* ---------------- + * open the relation associated with the cache + * ---------------- + */ relation = heap_open(cache->relationId); - CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", - RelationGetRelationName(relation), hash); - heap_close(relation); -#endif /* CACHEDEBUG */ - - return (ct->ct_tup); - } - - /* ---------------- - * Tuple was not found in cache, so we have to try and - * retrieve it directly from the relation. If it's found, - * we add it to the cache. We must avoid recursion here, - * so we disable cache operations. If operations are - * currently disabled and we couldn't find the requested item - * in the cache, then this may be a recursive request, and we - * abort with an error. - * ---------------- - */ - - if (DisableCache) { - elog(WARN, "SearchSysCache: Called while cache disabled"); - return((HeapTuple) NULL); - } - - /* ---------------- - * open the relation associated with the cache - * ---------------- - */ - relation = heap_open(cache->relationId); - CACHE2_elog(DEBUG, "SearchSysCache(%s)", - RelationGetRelationName(relation)); - - /* ---------------- - * DisableCache and then switch to the cache memory context. - * ---------------- - */ - DisableCache = 1; - - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * Scan the relation to find the tuple. If there's an index, and - * if this isn't bootstrap (initdb) time, use the index. - * ---------------- - */ - CACHE2_elog(DEBUG, "SearchSysCache: performing scan (override==%d)", - heapisoverride()); - - if ((RelationGetRelationTupleForm(relation))->relhasindex - && !IsBootstrapProcessingMode()) + CACHE2_elog(DEBUG, "SearchSysCache(%s)", + RelationGetRelationName(relation)); + + /* ---------------- + * DisableCache and then switch to the cache memory context. + * ---------------- + */ + DisableCache = 1; + + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * Scan the relation to find the tuple. If there's an index, and + * if this isn't bootstrap (initdb) time, use the index. + * ---------------- + */ + CACHE2_elog(DEBUG, "SearchSysCache: performing scan (override==%d)", + heapisoverride()); + + if ((RelationGetRelationTupleForm(relation))->relhasindex + && !IsBootstrapProcessingMode()) { - /* ---------- - * Switch back to old memory context so memory not freed - * in the scan function will go away at transaction end. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo(oldcxt); - Assert(cache->cc_iscanfunc); - switch(cache->cc_nkeys) + /* ---------- + * Switch back to old memory context so memory not freed + * in the scan function will go away at transaction end. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + Assert(cache->cc_iscanfunc); + switch (cache->cc_nkeys) + { + case 4: + ntp = cache->cc_iscanfunc(relation, v1, v2, v3, v4); + break; + case 3: + ntp = cache->cc_iscanfunc(relation, v1, v2, v3); + break; + case 2: + ntp = cache->cc_iscanfunc(relation, v1, v2); + break; + case 1: + ntp = cache->cc_iscanfunc(relation, v1); + break; + } + /* ---------- + * Back to Cache context. If we got a tuple copy it + * into our context. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo((MemoryContext) CacheCxt); + if (HeapTupleIsValid(ntp)) { - case 4: ntp = cache->cc_iscanfunc(relation,v1,v2,v3,v4); break; - case 3: ntp = cache->cc_iscanfunc(relation,v1,v2,v3); break; - case 2: ntp = cache->cc_iscanfunc(relation,v1,v2); break; - case 1: ntp = cache->cc_iscanfunc(relation,v1); break; + ntp = heap_copytuple(ntp); } - /* ---------- - * Back to Cache context. If we got a tuple copy it - * into our context. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo((MemoryContext)CacheCxt); - if(HeapTupleIsValid(ntp)) { - ntp = heap_copytuple(ntp); - } } - else + else { - HeapScanDesc sd; - - /* ---------- - * As above do the lookup in the callers memory - * context. - * wieck - 10/18/1996 - * ---------- - */ - MemoryContextSwitchTo(oldcxt); - - sd = heap_beginscan(relation, 0, NowTimeQual, - cache->cc_nkeys, cache->cc_skey); - - /* should this buffer be ReleaseBuffer'd? --djm 8/20/96 */ - ntp = heap_getnext(sd, 0, &buffer); - - MemoryContextSwitchTo((MemoryContext)CacheCxt); - - if (HeapTupleIsValid(ntp)) { - CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); - ntp = heap_copytuple(ntp); - } - - MemoryContextSwitchTo(oldcxt); - - heap_endscan(sd); - - MemoryContextSwitchTo((MemoryContext)CacheCxt); + HeapScanDesc sd; + + /* ---------- + * As above do the lookup in the callers memory + * context. + * wieck - 10/18/1996 + * ---------- + */ + MemoryContextSwitchTo(oldcxt); + + sd = heap_beginscan(relation, 0, NowTimeQual, + cache->cc_nkeys, cache->cc_skey); + + /* should this buffer be ReleaseBuffer'd? --djm 8/20/96 */ + ntp = heap_getnext(sd, 0, &buffer); + + MemoryContextSwitchTo((MemoryContext) CacheCxt); + + if (HeapTupleIsValid(ntp)) + { + CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); + ntp = heap_copytuple(ntp); + } + + MemoryContextSwitchTo(oldcxt); + + heap_endscan(sd); + + MemoryContextSwitchTo((MemoryContext) CacheCxt); } - - DisableCache = 0; - - /* ---------------- - * scan is complete. if tup is valid, we copy it and add the copy to - * the cache. - * ---------------- - */ - if (HeapTupleIsValid(ntp)) { + + DisableCache = 0; + /* ---------------- - * allocate a new cache tuple holder, store the pointer - * to the heap tuple there and initialize the list pointers. + * scan is complete. if tup is valid, we copy it and add the copy to + * the cache. * ---------------- */ - Dlelem *lru_elt; - - /* this is a little cumbersome here because we want the Dlelem's - in both doubly linked lists to point to one another. - That makes it easier to remove something from both the cache bucket - and the lru list at the same time */ - nct = (CatCTup*) malloc(sizeof(CatCTup)); - nct->ct_tup = ntp; - elt = DLNewElem(nct); - nct2 = (CatCTup*) malloc(sizeof(CatCTup)); - nct2->ct_tup = ntp; - lru_elt = DLNewElem(nct2); - nct2->ct_node = elt; - nct->ct_node = lru_elt; - - DLAddHead(cache->cc_lrulist, lru_elt); - DLAddHead(cache->cc_cache[hash], elt); + if (HeapTupleIsValid(ntp)) + { + /* ---------------- + * allocate a new cache tuple holder, store the pointer + * to the heap tuple there and initialize the list pointers. + * ---------------- + */ + Dlelem *lru_elt; + + /* + * this is a little cumbersome here because we want the Dlelem's + * in both doubly linked lists to point to one another. That makes + * it easier to remove something from both the cache bucket and + * the lru list at the same time + */ + nct = (CatCTup *) malloc(sizeof(CatCTup)); + nct->ct_tup = ntp; + elt = DLNewElem(nct); + nct2 = (CatCTup *) malloc(sizeof(CatCTup)); + nct2->ct_tup = ntp; + lru_elt = DLNewElem(nct2); + nct2->ct_node = elt; + nct->ct_node = lru_elt; + + DLAddHead(cache->cc_lrulist, lru_elt); + DLAddHead(cache->cc_cache[hash], elt); + + /* ---------------- + * deal with hash bucket overflow + * ---------------- + */ + if (++cache->cc_ntup > cache->cc_maxtup) + { + CatCTup *ct; + + elt = DLGetTail(cache->cc_lrulist); + ct = (CatCTup *) DLE_VAL(elt); + + if (ct != nct) + { + CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", + RelationGetRelationName(relation)); + + CatCacheRemoveCTup(cache, elt); + + } + } + + CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", + RelationGetRelationName(relation), + cache->cc_ntup, cache->cc_maxtup); + CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", + RelationGetRelationName(relation), hash); + } /* ---------------- - * deal with hash bucket overflow + * close the relation, switch back to the original memory context + * and return the tuple we found (or NULL) * ---------------- */ - if (++cache->cc_ntup > cache->cc_maxtup) { - CatCTup *ct; - elt = DLGetTail(cache->cc_lrulist); - ct = (CatCTup *) DLE_VAL(elt); - - if (ct != nct) { - CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", - RelationGetRelationName(relation)); - - CatCacheRemoveCTup(cache, elt); - - } - } - - CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", - RelationGetRelationName(relation), - cache->cc_ntup, cache->cc_maxtup); - CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", - RelationGetRelationName(relation), hash); - } - - /* ---------------- - * close the relation, switch back to the original memory context - * and return the tuple we found (or NULL) - * ---------------- - */ - heap_close(relation); - - MemoryContextSwitchTo(oldcxt); - return ntp; + heap_close(relation); + + MemoryContextSwitchTo(oldcxt); + return ntp; } /* -------------------------------- - * RelationInvalidateCatalogCacheTuple() + * RelationInvalidateCatalogCacheTuple() * - * Invalidate a tuple from a specific relation. This call determines the - * cache in question and calls CatalogCacheIdInvalidate(). It is -ok- - * if the relation cannot be found, it simply means this backend has yet - * to open it. + * Invalidate a tuple from a specific relation. This call determines the + * cache in question and calls CatalogCacheIdInvalidate(). It is -ok- + * if the relation cannot be found, it simply means this backend has yet + * to open it. * -------------------------------- */ void RelationInvalidateCatalogCacheTuple(Relation relation, - HeapTuple tuple, - void (*function)(int, Index, ItemPointer)) + HeapTuple tuple, + void (*function) (int, Index, ItemPointer)) { - struct catcache *ccp; - MemoryContext oldcxt; - Oid relationId; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - Assert(HeapTupleIsValid(tuple)); - CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called"); - - /* ---------------- - * switch to the cache memory context - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * for each cache - * if the cache contains tuples from the specified relation - * call the invalidation function on the tuples - * in the proper hash bucket - * ---------------- - */ - relationId = RelationGetRelationId(relation); - - for (ccp = Caches; ccp; ccp = ccp->cc_next) { - if (relationId != ccp->relationId) - continue; - - /* OPT inline simplification of CatalogCacheIdInvalidate */ - if (!PointerIsValid(function)) { - function = CatalogCacheIdInvalidate; + struct catcache *ccp; + MemoryContext oldcxt; + Oid relationId; + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(RelationIsValid(relation)); + Assert(HeapTupleIsValid(tuple)); + CACHE1_elog(DEBUG, "RelationInvalidateCatalogCacheTuple: called"); + + /* ---------------- + * switch to the cache memory context + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * for each cache + * if the cache contains tuples from the specified relation + * call the invalidation function on the tuples + * in the proper hash bucket + * ---------------- + */ + relationId = RelationGetRelationId(relation); + + for (ccp = Caches; ccp; ccp = ccp->cc_next) + { + if (relationId != ccp->relationId) + continue; + + /* OPT inline simplification of CatalogCacheIdInvalidate */ + if (!PointerIsValid(function)) + { + function = CatalogCacheIdInvalidate; + } + + (*function) (ccp->id, + CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), + &tuple->t_ctid); + + heap_close(relation); } - - (*function)(ccp->id, - CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), - &tuple->t_ctid); - - heap_close(relation); - } - - /* ---------------- - * return to the proper memory context - * ---------------- - */ - MemoryContextSwitchTo(oldcxt); - - /* sendpm('I', "Invalidated tuple"); */ -} + /* ---------------- + * return to the proper memory context + * ---------------- + */ + MemoryContextSwitchTo(oldcxt); + + /* sendpm('I', "Invalidated tuple"); */ +} diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c index 1d86364abda..ad174c6fdf5 100644 --- a/src/backend/utils/cache/fcache.c +++ b/src/backend/utils/cache/fcache.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fcache.c-- - * Code for the 'function cache' used in Oper and Func nodes.... + * Code for the 'function cache' used in Oper and Func nodes.... * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.4 1996/11/10 03:03:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.5 1997/09/07 04:52:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,23 +23,24 @@ #include "catalog/pg_proc.h" #include "catalog/pg_language.h" #include "catalog/pg_class.h" -#include "parser/parsetree.h" /* for getrelname() */ +#include "parser/parsetree.h" /* for getrelname() */ #include "utils/builtins.h" #include "utils/fcache.h" #include "utils/fcache2.h" #include "nodes/primnodes.h" #include "nodes/execnodes.h" #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif -static Oid GetDynamicFuncArgType(Var *arg, ExprContext *econtext); -static FunctionCachePtr init_fcache(Oid foid, - bool use_syscache, - List *argList, - ExprContext *econtext); +static Oid GetDynamicFuncArgType(Var * arg, ExprContext * econtext); +static FunctionCachePtr +init_fcache(Oid foid, + bool use_syscache, + List * argList, + ExprContext * econtext); /*----------------------------------------------------------------- * @@ -47,259 +48,269 @@ static FunctionCachePtr init_fcache(Oid foid, * * * NOTE: This function can be called when the system cache is being - * initialized. Therefore, use_syscache should ONLY be true - * when the function return type is interesting (ie: set_fcache). + * initialized. Therefore, use_syscache should ONLY be true + * when the function return type is interesting (ie: set_fcache). *----------------------------------------------------------------- */ #define FuncArgTypeIsDynamic(arg) \ - (IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber) + (IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber) -static Oid -GetDynamicFuncArgType(Var *arg, ExprContext *econtext) +static Oid +GetDynamicFuncArgType(Var * arg, ExprContext * econtext) { - char *relname; - int rtid; - HeapTuple tup; - - Assert(IsA(arg,Var)); - - rtid = ((Var*)arg)->varno; - relname = (char*)getrelname(rtid, econtext->ecxt_range_table); - - - tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(relname), - 0,0,0); - if (!tup) - elog(WARN, "Lookup failed on type tuple for class %s", - relname); - - return tup->t_oid; + char *relname; + int rtid; + HeapTuple tup; + + Assert(IsA(arg, Var)); + + rtid = ((Var *) arg)->varno; + relname = (char *) getrelname(rtid, econtext->ecxt_range_table); + + + tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(relname), + 0, 0, 0); + if (!tup) + elog(WARN, "Lookup failed on type tuple for class %s", + relname); + + return tup->t_oid; } -static FunctionCachePtr +static FunctionCachePtr init_fcache(Oid foid, - bool use_syscache, - List *argList, - ExprContext *econtext) + bool use_syscache, + List * argList, + ExprContext * econtext) { - HeapTuple procedureTuple; - HeapTuple typeTuple; - Form_pg_proc procedureStruct; - TypeTupleForm typeStruct; - FunctionCachePtr retval; - text *tmp; - int nargs; - - /* ---------------- - * get the procedure tuple corresponding to the given - * functionOid. If this fails, returnValue has been - * pre-initialized to "null" so we just return it. - * ---------------- - */ - retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); - - if (!use_syscache) - elog(WARN, "what the ????, init the fcache without the catalogs?"); - - procedureTuple = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(foid), - 0,0,0); - - if (!HeapTupleIsValid(procedureTuple)) - elog(WARN, - "init_fcache: %s %d", - "Cache lookup failed for procedure", foid); - - /* ---------------- - * get the return type from the procedure tuple - * ---------------- - */ - procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); - - /* ---------------- - * get the type tuple corresponding to the return type - * If this fails, returnValue has been pre-initialized - * to "null" so we just return it. - * ---------------- - */ - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(procedureStruct->prorettype), - 0,0,0); - - if (!HeapTupleIsValid(typeTuple)) - elog(WARN, - "init_fcache: %s %d", - "Cache lookup failed for type", - (procedureStruct)->prorettype); - - /* ---------------- - * get the type length and by-value from the type tuple and - * save the information in our one element cache. - * ---------------- - */ - typeStruct = (TypeTupleForm) GETSTRUCT(typeTuple); - - retval->typlen = (typeStruct)->typlen; - if ((typeStruct)->typrelid == InvalidOid) { - /* The return type is not a relation, so just use byval */ - retval->typbyval = (typeStruct)->typbyval ? true : false ; - } else { - /* This is a hack. We assume here that any function returning - * a relation returns it by reference. This needs to be - * fixed. + HeapTuple procedureTuple; + HeapTuple typeTuple; + Form_pg_proc procedureStruct; + TypeTupleForm typeStruct; + FunctionCachePtr retval; + text *tmp; + int nargs; + + /* ---------------- + * get the procedure tuple corresponding to the given + * functionOid. If this fails, returnValue has been + * pre-initialized to "null" so we just return it. + * ---------------- + */ + retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); + + if (!use_syscache) + elog(WARN, "what the ????, init the fcache without the catalogs?"); + + procedureTuple = SearchSysCacheTuple(PROOID, + ObjectIdGetDatum(foid), + 0, 0, 0); + + if (!HeapTupleIsValid(procedureTuple)) + elog(WARN, + "init_fcache: %s %d", + "Cache lookup failed for procedure", foid); + + /* ---------------- + * get the return type from the procedure tuple + * ---------------- + */ + procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); + + /* ---------------- + * get the type tuple corresponding to the return type + * If this fails, returnValue has been pre-initialized + * to "null" so we just return it. + * ---------------- + */ + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(procedureStruct->prorettype), + 0, 0, 0); + + if (!HeapTupleIsValid(typeTuple)) + elog(WARN, + "init_fcache: %s %d", + "Cache lookup failed for type", + (procedureStruct)->prorettype); + + /* ---------------- + * get the type length and by-value from the type tuple and + * save the information in our one element cache. + * ---------------- */ - retval->typbyval = false; - } - retval->foid = foid; - retval->language = procedureStruct->prolang; - retval->func_state = (char *)NULL; - retval->setArg = NULL; - retval->hasSetArg = false; - retval->oneResult = ! procedureStruct->proretset; - retval->istrusted = procedureStruct->proistrusted; - - /* - * If we are returning exactly one result then we have to copy - * tuples and by reference results because we have to end the execution - * before we return the results. When you do this everything allocated - * by the executor (i.e. slots and tuples) is freed. - */ - if ((retval->language == SQLlanguageId) && - (retval->oneResult) && - !(retval->typbyval)) + typeStruct = (TypeTupleForm) GETSTRUCT(typeTuple); + + retval->typlen = (typeStruct)->typlen; + if ((typeStruct)->typrelid == InvalidOid) + { + /* The return type is not a relation, so just use byval */ + retval->typbyval = (typeStruct)->typbyval ? true : false; + } + else { - Form_pg_class relationStruct; - HeapTuple relationTuple; - TupleDesc td; - TupleTableSlot *slot; - - slot = makeNode(TupleTableSlot); - slot->ttc_shouldFree = true; - slot->ttc_descIsNew = true; - slot->ttc_tupleDescriptor = (TupleDesc) NULL; - slot->ttc_buffer = InvalidBuffer; - slot->ttc_whichplan = -1; - retval->funcSlot = (Pointer)slot; - - relationTuple = (HeapTuple) - SearchSysCacheTuple(RELNAME, - PointerGetDatum(&typeStruct->typname), - 0,0,0); - - if (relationTuple) + + /* + * This is a hack. We assume here that any function returning a + * relation returns it by reference. This needs to be fixed. + */ + retval->typbyval = false; + } + retval->foid = foid; + retval->language = procedureStruct->prolang; + retval->func_state = (char *) NULL; + retval->setArg = NULL; + retval->hasSetArg = false; + retval->oneResult = !procedureStruct->proretset; + retval->istrusted = procedureStruct->proistrusted; + + /* + * If we are returning exactly one result then we have to copy tuples + * and by reference results because we have to end the execution + * before we return the results. When you do this everything + * allocated by the executor (i.e. slots and tuples) is freed. + */ + if ((retval->language == SQLlanguageId) && + (retval->oneResult) && + !(retval->typbyval)) + { + Form_pg_class relationStruct; + HeapTuple relationTuple; + TupleDesc td; + TupleTableSlot *slot; + + slot = makeNode(TupleTableSlot); + slot->ttc_shouldFree = true; + slot->ttc_descIsNew = true; + slot->ttc_tupleDescriptor = (TupleDesc) NULL; + slot->ttc_buffer = InvalidBuffer; + slot->ttc_whichplan = -1; + retval->funcSlot = (Pointer) slot; + + relationTuple = (HeapTuple) + SearchSysCacheTuple(RELNAME, + PointerGetDatum(&typeStruct->typname), + 0, 0, 0); + + if (relationTuple) { - relationStruct = (Form_pg_class)GETSTRUCT(relationTuple); - td = CreateTemplateTupleDesc(relationStruct->relnatts); + relationStruct = (Form_pg_class) GETSTRUCT(relationTuple); + td = CreateTemplateTupleDesc(relationStruct->relnatts); } - else - td = CreateTemplateTupleDesc(1); - - ((TupleTableSlot*)retval->funcSlot)->ttc_tupleDescriptor = td; + else + td = CreateTemplateTupleDesc(1); + + ((TupleTableSlot *) retval->funcSlot)->ttc_tupleDescriptor = td; } - else - retval->funcSlot = (char *)NULL; - - nargs = procedureStruct->pronargs; - retval->nargs = nargs; - - if (nargs > 0) + else + retval->funcSlot = (char *) NULL; + + nargs = procedureStruct->pronargs; + retval->nargs = nargs; + + if (nargs > 0) { - Oid *argTypes; - - retval->nullVect = (bool *)palloc((retval->nargs)*sizeof(bool)); - - if (retval->language == SQLlanguageId) + Oid *argTypes; + + retval->nullVect = (bool *) palloc((retval->nargs) * sizeof(bool)); + + if (retval->language == SQLlanguageId) { - int i; - List *oneArg; - - retval->argOidVect = - (Oid *)palloc(retval->nargs*sizeof(Oid)); - argTypes = procedureStruct->proargtypes; - memmove(retval->argOidVect, - argTypes, - (retval->nargs)*sizeof(Oid)); - - for (i=0; - argList; - i++, argList = lnext(argList)) + int i; + List *oneArg; + + retval->argOidVect = + (Oid *) palloc(retval->nargs * sizeof(Oid)); + argTypes = procedureStruct->proargtypes; + memmove(retval->argOidVect, + argTypes, + (retval->nargs) * sizeof(Oid)); + + for (i = 0; + argList; + i++, argList = lnext(argList)) { - oneArg = lfirst(argList); - if (FuncArgTypeIsDynamic(oneArg)) - retval->argOidVect[i] = GetDynamicFuncArgType((Var*)oneArg, - econtext); + oneArg = lfirst(argList); + if (FuncArgTypeIsDynamic(oneArg)) + retval->argOidVect[i] = GetDynamicFuncArgType((Var *) oneArg, + econtext); } } - else - retval->argOidVect = (Oid *)NULL; + else + retval->argOidVect = (Oid *) NULL; } - else + else { - retval->argOidVect = (Oid *)NULL; - retval->nullVect = (BoolPtr)NULL; + retval->argOidVect = (Oid *) NULL; + retval->nullVect = (BoolPtr) NULL; } - - /* - * XXX this is the first varlena in the struct. If the order - * changes for some reason this will fail. - */ - if (procedureStruct->prolang == SQLlanguageId) + + /* + * XXX this is the first varlena in the struct. If the order changes + * for some reason this will fail. + */ + if (procedureStruct->prolang == SQLlanguageId) { - retval->src = textout(&(procedureStruct->prosrc)); - retval->bin = (char *) NULL; + retval->src = textout(&(procedureStruct->prosrc)); + retval->bin = (char *) NULL; } - else + else { - - /* - * I'm not sure that we even need to do this at all. - */ - - /* - * We do for untrusted functions. - */ - - if (procedureStruct->proistrusted) - retval->bin = (char *) NULL; - else { - tmp = (text *) - SearchSysCacheGetAttribute(PROOID, - Anum_pg_proc_probin, - ObjectIdGetDatum(foid), - 0,0,0); - retval->bin = textout(tmp); - } - retval->src = (char *) NULL; + + /* + * I'm not sure that we even need to do this at all. + */ + + /* + * We do for untrusted functions. + */ + + if (procedureStruct->proistrusted) + retval->bin = (char *) NULL; + else + { + tmp = (text *) + SearchSysCacheGetAttribute(PROOID, + Anum_pg_proc_probin, + ObjectIdGetDatum(foid), + 0, 0, 0); + retval->bin = textout(tmp); + } + retval->src = (char *) NULL; } - - - - - if (retval->language != SQLlanguageId) - fmgr_info(foid, &(retval->func), &(retval->nargs)); - else - retval->func = (func_ptr)NULL; - - - return(retval); + + + + + if (retval->language != SQLlanguageId) + fmgr_info(foid, &(retval->func), &(retval->nargs)); + else + retval->func = (func_ptr) NULL; + + + return (retval); } void -setFcache(Node *node, Oid foid, List *argList, ExprContext *econtext) +setFcache(Node * node, Oid foid, List * argList, ExprContext * econtext) { - Func *fnode; - Oper *onode; - FunctionCachePtr fcache; - - fcache = init_fcache(foid, true, argList, econtext); - - if (IsA(node,Oper)) { - onode = (Oper*) node; - onode->op_fcache = fcache; - }else if (IsA(node,Func)) { - fnode = (Func*) node; - fnode->func_fcache = fcache; - }else { - elog(WARN, "init_fcache: node must be Oper or Func!"); - } + Func *fnode; + Oper *onode; + FunctionCachePtr fcache; + + fcache = init_fcache(foid, true, argList, econtext); + + if (IsA(node, Oper)) + { + onode = (Oper *) node; + onode->op_fcache = fcache; + } + else if (IsA(node, Func)) + { + fnode = (Func *) node; + fnode->func_fcache = fcache; + } + else + { + elog(WARN, "init_fcache: node must be Oper or Func!"); + } } diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 4f52e4e5f4c..4fb8a5eb6ed 100644 --- a/src/backend/utils/cache/inval.c +++ b/src/backend/utils/cache/inval.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * inval.c-- - * POSTGRES cache invalidation dispatcher code. + * POSTGRES cache invalidation dispatcher code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.4 1997/08/19 21:35:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.5 1997/09/07 04:53:01 momjian Exp $ * * Note - this code is real crufty... * @@ -17,11 +17,11 @@ #include <miscadmin.h> -#include "access/heapam.h" /* XXX to support hacks below */ +#include "access/heapam.h" /* XXX to support hacks below */ #include "access/htup.h" #include "catalog/catalog.h" #include "storage/bufpage.h" -#include "storage/buf.h" /* XXX for InvalidBuffer */ +#include "storage/buf.h" /* XXX for InvalidBuffer */ #include "storage/ipc.h" #include "storage/sinval.h" #include "utils/catcache.h" @@ -29,593 +29,615 @@ #include "utils/rel.h" #include "utils/relcache.h" #include "catalog/catname.h" /* XXX to support hacks below */ -#include "utils/syscache.h" /* XXX to support the hacks below */ +#include "utils/syscache.h" /* XXX to support the hacks below */ static InvalidationEntry InvalidationEntryAllocate(uint16 size); -static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function)()); -static LocalInvalid LocalInvalidRegister(LocalInvalid invalid, +static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()); +static LocalInvalid +LocalInvalidRegister(LocalInvalid invalid, InvalidationEntry entry); -static void getmyrelids(void); +static void getmyrelids(void); /* ---------------- - * private invalidation structures + * private invalidation structures * ---------------- */ -typedef struct CatalogInvalidationData { - Index cacheId; - Index hashIndex; - ItemPointerData pointerData; -} CatalogInvalidationData; +typedef struct CatalogInvalidationData +{ + Index cacheId; + Index hashIndex; + ItemPointerData pointerData; +} CatalogInvalidationData; -typedef struct RelationInvalidationData { - Oid relationId; - Oid objectId; -} RelationInvalidationData; +typedef struct RelationInvalidationData +{ + Oid relationId; + Oid objectId; +} RelationInvalidationData; -typedef union AnyInvalidation { - CatalogInvalidationData catalog; - RelationInvalidationData relation; -} AnyInvalidation; +typedef union AnyInvalidation +{ + CatalogInvalidationData catalog; + RelationInvalidationData relation; +} AnyInvalidation; -typedef struct InvalidationMessageData { - char kind; - AnyInvalidation any; -} InvalidationMessageData; +typedef struct InvalidationMessageData +{ + char kind; + AnyInvalidation any; +} InvalidationMessageData; -typedef InvalidationMessageData *InvalidationMessage; +typedef InvalidationMessageData *InvalidationMessage; /* ---------------- - * variables and macros + * variables and macros * ---------------- */ -static LocalInvalid Invalid = EmptyLocalInvalid; /* XXX global */ -static bool RefreshWhenInvalidate = false; +static LocalInvalid Invalid = EmptyLocalInvalid; /* XXX global */ +static bool RefreshWhenInvalidate = false; -Oid MyRelationRelationId = InvalidOid; -Oid MyAttributeRelationId = InvalidOid; -Oid MyAMRelationId = InvalidOid; -Oid MyAMOPRelationId = InvalidOid; +Oid MyRelationRelationId = InvalidOid; +Oid MyAttributeRelationId = InvalidOid; +Oid MyAMRelationId = InvalidOid; +Oid MyAMOPRelationId = InvalidOid; #define ValidateHacks() \ - if (!OidIsValid(MyRelationRelationId)) getmyrelids() + if (!OidIsValid(MyRelationRelationId)) getmyrelids() /* ---------------------------------------------------------------- - * "local" invalidation support functions + * "local" invalidation support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * InvalidationEntryAllocate-- - * Allocates an invalidation entry. + * InvalidationEntryAllocate-- + * Allocates an invalidation entry. * -------------------------------- */ -static InvalidationEntry +static InvalidationEntry InvalidationEntryAllocate(uint16 size) { - InvalidationEntryData *entryDataP; - entryDataP = (InvalidationEntryData *) - malloc(sizeof (char *) + size); /* XXX alignment */ - entryDataP->nextP = NULL; - return ((Pointer) &entryDataP->userData); + InvalidationEntryData *entryDataP; + + entryDataP = (InvalidationEntryData *) + malloc(sizeof(char *) + size); /* XXX alignment */ + entryDataP->nextP = NULL; + return ((Pointer) & entryDataP->userData); } /* -------------------------------- - * LocalInvalidRegister -- - * Returns a new local cache invalidation state containing a new entry. + * LocalInvalidRegister -- + * Returns a new local cache invalidation state containing a new entry. * -------------------------------- */ -static LocalInvalid +static LocalInvalid LocalInvalidRegister(LocalInvalid invalid, - InvalidationEntry entry) + InvalidationEntry entry) { - Assert(PointerIsValid(entry)); - - ((InvalidationUserData *)entry)->dataP[-1] = - (InvalidationUserData *)invalid; - - return (entry); + Assert(PointerIsValid(entry)); + + ((InvalidationUserData *) entry)->dataP[-1] = + (InvalidationUserData *) invalid; + + return (entry); } /* -------------------------------- - * LocalInvalidInvalidate-- - * Processes, then frees all entries in a local cache - * invalidation state. + * LocalInvalidInvalidate-- + * Processes, then frees all entries in a local cache + * invalidation state. * -------------------------------- */ static void -LocalInvalidInvalidate(LocalInvalid invalid, void (*function)()) +LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()) { - InvalidationEntryData *entryDataP; - - while (PointerIsValid(invalid)) { - entryDataP = (InvalidationEntryData *) - &((InvalidationUserData *)invalid)->dataP[-1]; - - if (PointerIsValid(function)) { - (*function)((Pointer) &entryDataP->userData); + InvalidationEntryData *entryDataP; + + while (PointerIsValid(invalid)) + { + entryDataP = (InvalidationEntryData *) + & ((InvalidationUserData *) invalid)->dataP[-1]; + + if (PointerIsValid(function)) + { + (*function) ((Pointer) & entryDataP->userData); + } + + invalid = (Pointer) entryDataP->nextP; + + /* help catch errors */ + entryDataP->nextP = (InvalidationUserData *) NULL; + + free((Pointer) entryDataP); } - - invalid = (Pointer) entryDataP->nextP; - - /* help catch errors */ - entryDataP->nextP = (InvalidationUserData *) NULL; - - free((Pointer)entryDataP); - } } /* ---------------------------------------------------------------- - * private support functions + * private support functions * ---------------------------------------------------------------- */ /* -------------------------------- - * CacheIdRegisterLocalInvalid + * CacheIdRegisterLocalInvalid * -------------------------------- */ #ifdef INVALIDDEBUG #define CacheIdRegisterLocalInvalid_DEBUG1 \ elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \ - cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \ - ItemPointerGetOffsetNumber(pointer)) + cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \ + ItemPointerGetOffsetNumber(pointer)) #else #define CacheIdRegisterLocalInvalid_DEBUG1 -#endif /* INVALIDDEBUG */ - +#endif /* INVALIDDEBUG */ + static void CacheIdRegisterLocalInvalid(Index cacheId, - Index hashIndex, - ItemPointer pointer) + Index hashIndex, + ItemPointer pointer) { - InvalidationMessage message; - - /* ---------------- - * debugging stuff - * ---------------- - */ - CacheIdRegisterLocalInvalid_DEBUG1; - - /* ---------------- - * create a message describing the system catalog tuple - * we wish to invalidate. - * ---------------- - */ - message = (InvalidationMessage) - InvalidationEntryAllocate(sizeof (InvalidationMessageData)); - - message->kind = 'c'; - message->any.catalog.cacheId = cacheId; - message->any.catalog.hashIndex = hashIndex; - - ItemPointerCopy(pointer, &message->any.catalog.pointerData); - - /* ---------------- - * Note: Invalid is a global variable - * ---------------- - */ - Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry)message); + InvalidationMessage message; + + /* ---------------- + * debugging stuff + * ---------------- + */ + CacheIdRegisterLocalInvalid_DEBUG1; + + /* ---------------- + * create a message describing the system catalog tuple + * we wish to invalidate. + * ---------------- + */ + message = (InvalidationMessage) + InvalidationEntryAllocate(sizeof(InvalidationMessageData)); + + message->kind = 'c'; + message->any.catalog.cacheId = cacheId; + message->any.catalog.hashIndex = hashIndex; + + ItemPointerCopy(pointer, &message->any.catalog.pointerData); + + /* ---------------- + * Note: Invalid is a global variable + * ---------------- + */ + Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message); } /* -------------------------------- - * RelationIdRegisterLocalInvalid + * RelationIdRegisterLocalInvalid * -------------------------------- */ static void RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId) { - InvalidationMessage message; - - /* ---------------- - * debugging stuff - * ---------------- - */ + InvalidationMessage message; + + /* ---------------- + * debugging stuff + * ---------------- + */ #ifdef INVALIDDEBUG - elog(DEBUG, "RelationRegisterLocalInvalid(%d, %d)", relationId, - objectId); -#endif /* defined(INVALIDDEBUG) */ - - /* ---------------- - * create a message describing the relation descriptor - * we wish to invalidate. - * ---------------- - */ - message = (InvalidationMessage) - InvalidationEntryAllocate(sizeof (InvalidationMessageData)); - - message->kind = 'r'; - message->any.relation.relationId = relationId; - message->any.relation.objectId = objectId; - - /* ---------------- - * Note: Invalid is a global variable - * ---------------- - */ - Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry)message); + elog(DEBUG, "RelationRegisterLocalInvalid(%d, %d)", relationId, + objectId); +#endif /* defined(INVALIDDEBUG) */ + + /* ---------------- + * create a message describing the relation descriptor + * we wish to invalidate. + * ---------------- + */ + message = (InvalidationMessage) + InvalidationEntryAllocate(sizeof(InvalidationMessageData)); + + message->kind = 'r'; + message->any.relation.relationId = relationId; + message->any.relation.objectId = objectId; + + /* ---------------- + * Note: Invalid is a global variable + * ---------------- + */ + Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message); } /* -------------------------------- - * getmyrelids + * getmyrelids * -------------------------------- */ static void getmyrelids() { - HeapTuple tuple; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(RelationRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyRelationRelationId = tuple->t_oid; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(AttributeRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyAttributeRelationId = tuple->t_oid; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(AccessMethodRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyAMRelationId = tuple->t_oid; - - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(AccessMethodOperatorRelationName), - 0,0,0); - Assert(HeapTupleIsValid(tuple)); - MyAMOPRelationId = tuple->t_oid; + HeapTuple tuple; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(RelationRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyRelationRelationId = tuple->t_oid; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(AttributeRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyAttributeRelationId = tuple->t_oid; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(AccessMethodRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyAMRelationId = tuple->t_oid; + + tuple = SearchSysCacheTuple(RELNAME, + PointerGetDatum(AccessMethodOperatorRelationName), + 0, 0, 0); + Assert(HeapTupleIsValid(tuple)); + MyAMOPRelationId = tuple->t_oid; } /* -------------------------------- - * CacheIdInvalidate + * CacheIdInvalidate * - * This routine can invalidate an tuple in a system catalog cache - * or a cached relation descriptor. You pay your money and you - * take your chances... + * This routine can invalidate an tuple in a system catalog cache + * or a cached relation descriptor. You pay your money and you + * take your chances... * -------------------------------- */ #ifdef INVALIDDEBUG #define CacheIdInvalidate_DEBUG1 \ elog(DEBUG, "CacheIdInvalidate(%d, %d, 0x%x[%d])", cacheId, hashIndex,\ - pointer, ItemPointerIsValid(pointer)) + pointer, ItemPointerIsValid(pointer)) #else #define CacheIdInvalidate_DEBUG1 -#endif /* defined(INVALIDDEBUG) */ - +#endif /* defined(INVALIDDEBUG) */ + static void CacheIdInvalidate(Index cacheId, - Index hashIndex, - ItemPointer pointer) + Index hashIndex, + ItemPointer pointer) { - /* ---------------- - * assume that if the item pointer is valid, then we are - * invalidating an item in the specified system catalog cache. - * ---------------- - */ - if (ItemPointerIsValid(pointer)) { - CatalogCacheIdInvalidate(cacheId, hashIndex, pointer); - return; - } - - CacheIdInvalidate_DEBUG1; - - ValidateHacks(); /* XXX */ - - /* ---------------- - * if the cacheId is the oid of any of the tuples in the - * following system relations, then assume we are invalidating - * a relation descriptor - * ---------------- - */ - if (cacheId == MyRelationRelationId) { - RelationIdInvalidateRelationCacheByRelationId(hashIndex); - return; - } - - if (cacheId == MyAttributeRelationId) { - RelationIdInvalidateRelationCacheByRelationId(hashIndex); - return; - } - - if (cacheId == MyAMRelationId) { - RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex); - return; - } - - if (cacheId == MyAMOPRelationId) { - RelationIdInvalidateRelationCacheByAccessMethodId(InvalidOid); - return; - } - - /* ---------------- - * Yow! the caller asked us to invalidate something else. - * ---------------- - */ - elog(FATAL, "CacheIdInvalidate: cacheId=%d relation id?", cacheId); + /* ---------------- + * assume that if the item pointer is valid, then we are + * invalidating an item in the specified system catalog cache. + * ---------------- + */ + if (ItemPointerIsValid(pointer)) + { + CatalogCacheIdInvalidate(cacheId, hashIndex, pointer); + return; + } + + CacheIdInvalidate_DEBUG1; + + ValidateHacks(); /* XXX */ + + /* ---------------- + * if the cacheId is the oid of any of the tuples in the + * following system relations, then assume we are invalidating + * a relation descriptor + * ---------------- + */ + if (cacheId == MyRelationRelationId) + { + RelationIdInvalidateRelationCacheByRelationId(hashIndex); + return; + } + + if (cacheId == MyAttributeRelationId) + { + RelationIdInvalidateRelationCacheByRelationId(hashIndex); + return; + } + + if (cacheId == MyAMRelationId) + { + RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex); + return; + } + + if (cacheId == MyAMOPRelationId) + { + RelationIdInvalidateRelationCacheByAccessMethodId(InvalidOid); + return; + } + + /* ---------------- + * Yow! the caller asked us to invalidate something else. + * ---------------- + */ + elog(FATAL, "CacheIdInvalidate: cacheId=%d relation id?", cacheId); } /* -------------------------------- - * ResetSystemCaches + * ResetSystemCaches * - * this blows away all tuples in the system catalog caches and - * all the cached relation descriptors (and closes the files too). + * this blows away all tuples in the system catalog caches and + * all the cached relation descriptors (and closes the files too). * -------------------------------- */ static void ResetSystemCaches() { - ResetSystemCache(); - RelationCacheInvalidate(false); + ResetSystemCache(); + RelationCacheInvalidate(false); } /* -------------------------------- - * InvalidationMessageRegisterSharedInvalid + * InvalidationMessageRegisterSharedInvalid * -------------------------------- */ #ifdef INVALIDDEBUG #define InvalidationMessageRegisterSharedInvalid_DEBUG1 \ elog(DEBUG,\ - "InvalidationMessageRegisterSharedInvalid(c, %d, %d, [%d, %d])",\ - message->any.catalog.cacheId,\ - message->any.catalog.hashIndex,\ - ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ - ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) + "InvalidationMessageRegisterSharedInvalid(c, %d, %d, [%d, %d])",\ + message->any.catalog.cacheId,\ + message->any.catalog.hashIndex,\ + ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ + ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) #define InvalidationMessageRegisterSharedInvalid_DEBUG2 \ - elog(DEBUG, \ - "InvalidationMessageRegisterSharedInvalid(r, %d, %d)", \ - message->any.relation.relationId, \ - message->any.relation.objectId) -#else + elog(DEBUG, \ + "InvalidationMessageRegisterSharedInvalid(r, %d, %d)", \ + message->any.relation.relationId, \ + message->any.relation.objectId) +#else #define InvalidationMessageRegisterSharedInvalid_DEBUG1 #define InvalidationMessageRegisterSharedInvalid_DEBUG2 -#endif /* INVALIDDEBUG */ - +#endif /* INVALIDDEBUG */ + static void InvalidationMessageRegisterSharedInvalid(InvalidationMessage message) { - Assert(PointerIsValid(message)); - - switch (message->kind) { - case 'c': /* cached system catalog tuple */ - InvalidationMessageRegisterSharedInvalid_DEBUG1; - - RegisterSharedInvalid(message->any.catalog.cacheId, - message->any.catalog.hashIndex, - &message->any.catalog.pointerData); - break; - - case 'r': /* cached relation descriptor */ - InvalidationMessageRegisterSharedInvalid_DEBUG2; - - RegisterSharedInvalid(message->any.relation.relationId, - message->any.relation.objectId, - (ItemPointer) NULL); - break; - - default: - elog(FATAL, - "InvalidationMessageRegisterSharedInvalid: `%c' kind", - message->kind); - } + Assert(PointerIsValid(message)); + + switch (message->kind) + { + case 'c': /* cached system catalog tuple */ + InvalidationMessageRegisterSharedInvalid_DEBUG1; + + RegisterSharedInvalid(message->any.catalog.cacheId, + message->any.catalog.hashIndex, + &message->any.catalog.pointerData); + break; + + case 'r': /* cached relation descriptor */ + InvalidationMessageRegisterSharedInvalid_DEBUG2; + + RegisterSharedInvalid(message->any.relation.relationId, + message->any.relation.objectId, + (ItemPointer) NULL); + break; + + default: + elog(FATAL, + "InvalidationMessageRegisterSharedInvalid: `%c' kind", + message->kind); + } } /* -------------------------------- - * InvalidationMessageCacheInvalidate + * InvalidationMessageCacheInvalidate * -------------------------------- */ #ifdef INVALIDDEBUG #define InvalidationMessageCacheInvalidate_DEBUG1 \ elog(DEBUG, "InvalidationMessageCacheInvalidate(c, %d, %d, [%d, %d])",\ - message->any.catalog.cacheId,\ - message->any.catalog.hashIndex,\ - ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ - ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) + message->any.catalog.cacheId,\ + message->any.catalog.hashIndex,\ + ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\ + ItemPointerGetOffsetNumber(&message->any.catalog.pointerData)) #define InvalidationMessageCacheInvalidate_DEBUG2 \ - elog(DEBUG, "InvalidationMessageCacheInvalidate(r, %d, %d)", \ - message->any.relation.relationId, \ - message->any.relation.objectId) + elog(DEBUG, "InvalidationMessageCacheInvalidate(r, %d, %d)", \ + message->any.relation.relationId, \ + message->any.relation.objectId) #else #define InvalidationMessageCacheInvalidate_DEBUG1 #define InvalidationMessageCacheInvalidate_DEBUG2 -#endif /* defined(INVALIDDEBUG) */ - +#endif /* defined(INVALIDDEBUG) */ + static void InvalidationMessageCacheInvalidate(InvalidationMessage message) { - Assert(PointerIsValid(message)); - - switch (message->kind) { - case 'c': /* cached system catalog tuple */ - InvalidationMessageCacheInvalidate_DEBUG1; - - CatalogCacheIdInvalidate(message->any.catalog.cacheId, - message->any.catalog.hashIndex, - &message->any.catalog.pointerData); - break; - - case 'r': /* cached relation descriptor */ - InvalidationMessageCacheInvalidate_DEBUG2; - - /* XXX ignore this--is this correct ??? */ - break; - - default: - elog(FATAL, "InvalidationMessageCacheInvalidate: `%c' kind", - message->kind); - } + Assert(PointerIsValid(message)); + + switch (message->kind) + { + case 'c': /* cached system catalog tuple */ + InvalidationMessageCacheInvalidate_DEBUG1; + + CatalogCacheIdInvalidate(message->any.catalog.cacheId, + message->any.catalog.hashIndex, + &message->any.catalog.pointerData); + break; + + case 'r': /* cached relation descriptor */ + InvalidationMessageCacheInvalidate_DEBUG2; + + /* XXX ignore this--is this correct ??? */ + break; + + default: + elog(FATAL, "InvalidationMessageCacheInvalidate: `%c' kind", + message->kind); + } } /* -------------------------------- - * RelationInvalidateRelationCache + * RelationInvalidateRelationCache * -------------------------------- */ static void RelationInvalidateRelationCache(Relation relation, - HeapTuple tuple, - void (*function)()) + HeapTuple tuple, + void (*function) ()) { - Oid relationId; - Oid objectId = (Oid)0; - - /* ---------------- - * get the relation object id - * ---------------- - */ - ValidateHacks(); /* XXX */ - relationId = RelationGetRelationId(relation); - - /* ---------------- - * - * ---------------- - */ - if (relationId == MyRelationRelationId) { - objectId = tuple->t_oid; - } else if (relationId == MyAttributeRelationId) { - objectId = ((AttributeTupleForm)GETSTRUCT(tuple))->attrelid; - } else if (relationId == MyAMRelationId) { - objectId = tuple->t_oid; - } else if (relationId == MyAMOPRelationId) { - ; /* objectId is unused */ - } else - return; - - /* ---------------- - * can't handle immediate relation descriptor invalidation - * ---------------- - */ - Assert(PointerIsValid(function)); - - (*function)(relationId, objectId); + Oid relationId; + Oid objectId = (Oid) 0; + + /* ---------------- + * get the relation object id + * ---------------- + */ + ValidateHacks(); /* XXX */ + relationId = RelationGetRelationId(relation); + + /* ---------------- + * + * ---------------- + */ + if (relationId == MyRelationRelationId) + { + objectId = tuple->t_oid; + } + else if (relationId == MyAttributeRelationId) + { + objectId = ((AttributeTupleForm) GETSTRUCT(tuple))->attrelid; + } + else if (relationId == MyAMRelationId) + { + objectId = tuple->t_oid; + } + else if (relationId == MyAMOPRelationId) + { + ; /* objectId is unused */ + } + else + return; + + /* ---------------- + * can't handle immediate relation descriptor invalidation + * ---------------- + */ + Assert(PointerIsValid(function)); + + (*function) (relationId, objectId); } /* * DiscardInvalid -- - * Causes the invalidated cache state to be discarded. + * Causes the invalidated cache state to be discarded. * * Note: - * This should be called as the first step in processing a transaction. - * This should be called while waiting for a query from the front end - * when other backends are active. + * This should be called as the first step in processing a transaction. + * This should be called while waiting for a query from the front end + * when other backends are active. */ void DiscardInvalid() { - /* ---------------- - * debugging stuff - * ---------------- - */ + /* ---------------- + * debugging stuff + * ---------------- + */ #ifdef INVALIDDEBUG - elog(DEBUG, "DiscardInvalid called"); -#endif /* defined(INVALIDDEBUG) */ - - InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches); + elog(DEBUG, "DiscardInvalid called"); +#endif /* defined(INVALIDDEBUG) */ + + InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches); } /* * RegisterInvalid -- - * Causes registration of invalidated state with other backends iff true. + * Causes registration of invalidated state with other backends iff true. * * Note: - * This should be called as the last step in processing a transaction. + * This should be called as the last step in processing a transaction. */ void RegisterInvalid(bool send) { - /* ---------------- - * debugging stuff - * ---------------- - */ + /* ---------------- + * debugging stuff + * ---------------- + */ #ifdef INVALIDDEBUG - elog(DEBUG, "RegisterInvalid(%d) called", send); -#endif /* defined(INVALIDDEBUG) */ - - /* ---------------- - * Note: Invalid is a global variable - * ---------------- - */ - if (send) - LocalInvalidInvalidate(Invalid, - InvalidationMessageRegisterSharedInvalid); - else - LocalInvalidInvalidate(Invalid, - InvalidationMessageCacheInvalidate); - - Invalid = EmptyLocalInvalid; + elog(DEBUG, "RegisterInvalid(%d) called", send); +#endif /* defined(INVALIDDEBUG) */ + + /* ---------------- + * Note: Invalid is a global variable + * ---------------- + */ + if (send) + LocalInvalidInvalidate(Invalid, + InvalidationMessageRegisterSharedInvalid); + else + LocalInvalidInvalidate(Invalid, + InvalidationMessageCacheInvalidate); + + Invalid = EmptyLocalInvalid; } /* * SetRefreshWhenInvalidate -- - * Causes the local caches to be immediately refreshed iff true. + * Causes the local caches to be immediately refreshed iff true. */ void SetRefreshWhenInvalidate(bool on) { #ifdef INVALIDDEBUG - elog(DEBUG, "RefreshWhenInvalidate(%d) called", on); -#endif /* defined(INVALIDDEBUG) */ - - RefreshWhenInvalidate = on; + elog(DEBUG, "RefreshWhenInvalidate(%d) called", on); +#endif /* defined(INVALIDDEBUG) */ + + RefreshWhenInvalidate = on; } /* * RelationIdInvalidateHeapTuple -- - * Causes the given tuple in a relation to be invalidated. + * Causes the given tuple in a relation to be invalidated. * * Note: - * Assumes object id is valid. - * Assumes tuple is valid. + * Assumes object id is valid. + * Assumes tuple is valid. */ #ifdef INVALIDDEBUG #define RelationInvalidateHeapTuple_DEBUG1 \ elog(DEBUG, "RelationInvalidateHeapTuple(%.16s, [%d,%d])", \ - RelationGetRelationName(relation), \ - ItemPointerGetBlockNumber(&tuple->t_ctid), \ - ItemPointerGetOffsetNumber(&tuple->t_ctid)) + RelationGetRelationName(relation), \ + ItemPointerGetBlockNumber(&tuple->t_ctid), \ + ItemPointerGetOffsetNumber(&tuple->t_ctid)) #else #define RelationInvalidateHeapTuple_DEBUG1 -#endif /* defined(INVALIDDEBUG) */ - +#endif /* defined(INVALIDDEBUG) */ + void RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple) { - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - Assert(HeapTupleIsValid(tuple)); - - if (IsBootstrapProcessingMode()) - return; - /* ---------------- - * this only works for system relations now - * ---------------- - */ - if (! IsSystemRelationName(RelationGetRelationTupleForm(relation)->relname.data)) - return; - - /* ---------------- - * debugging stuff - * ---------------- - */ - RelationInvalidateHeapTuple_DEBUG1; - - /* ---------------- - * - * ---------------- - */ - RelationInvalidateCatalogCacheTuple(relation, - tuple, - CacheIdRegisterLocalInvalid); - - RelationInvalidateRelationCache(relation, - tuple, - RelationIdRegisterLocalInvalid); - - if (RefreshWhenInvalidate) + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(RelationIsValid(relation)); + Assert(HeapTupleIsValid(tuple)); + + if (IsBootstrapProcessingMode()) + return; + /* ---------------- + * this only works for system relations now + * ---------------- + */ + if (!IsSystemRelationName(RelationGetRelationTupleForm(relation)->relname.data)) + return; + + /* ---------------- + * debugging stuff + * ---------------- + */ + RelationInvalidateHeapTuple_DEBUG1; + + /* ---------------- + * + * ---------------- + */ RelationInvalidateCatalogCacheTuple(relation, - tuple, - (void (*)()) NULL); -} + tuple, + CacheIdRegisterLocalInvalid); + RelationInvalidateRelationCache(relation, + tuple, + RelationIdRegisterLocalInvalid); + + if (RefreshWhenInvalidate) + RelationInvalidateCatalogCacheTuple(relation, + tuple, + (void (*) ()) NULL); +} diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 9de0c3fb89b..37280036970 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -1,20 +1,20 @@ /*------------------------------------------------------------------------- * * lsyscache.c-- - * Routines to access information within system caches + * Routines to access information within system caches * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.3 1997/08/19 21:35:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.4 1997/09/07 04:53:04 momjian Exp $ * * NOTES - * Eventually, the index information should go through here, too. - * - * Most of these routines call SearchSysCacheStruct() and thus simply - * (1) allocate some space for the return struct and (2) call it. - * + * Eventually, the index information should go through here, too. + * + * Most of these routines call SearchSysCacheStruct() and thus simply + * (1) allocate some space for the return struct and (2) call it. + * *------------------------------------------------------------------------- */ #include <string.h> @@ -34,99 +34,100 @@ #include "catalog/pg_operator.h" #include "catalog/pg_type.h" -/* ---------- AMOP CACHES ---------- */ +/* ---------- AMOP CACHES ---------- */ -/* +/* * op_class - - * - * Return t iff operator 'opno' is in operator class 'opclass'. - * + * + * Return t iff operator 'opno' is in operator class 'opclass'. + * */ bool op_class(Oid opno, int32 opclass, Oid amopid) { - FormData_pg_amop amoptup; - - if (SearchSysCacheStruct(AMOPOPID, - (char *) &amoptup, - ObjectIdGetDatum(opclass), - ObjectIdGetDatum(opno), - ObjectIdGetDatum(amopid), - 0)) - return(true); - else - return(false); + FormData_pg_amop amoptup; + + if (SearchSysCacheStruct(AMOPOPID, + (char *) &amoptup, + ObjectIdGetDatum(opclass), + ObjectIdGetDatum(opno), + ObjectIdGetDatum(amopid), + 0)) + return (true); + else + return (false); } -/* ---------- ATTRIBUTE CACHES ---------- */ +/* ---------- ATTRIBUTE CACHES ---------- */ -/* +/* * get_attname - - * - * Given the relation id and the attribute number, - * return the "attname" field from the attribute relation. - * + * + * Given the relation id and the attribute number, + * return the "attname" field from the attribute relation. + * */ -char* +char * get_attname(Oid relid, AttrNumber attnum) { - FormData_pg_attribute att_tup; - char *retval; - - if (SearchSysCacheStruct(ATTNUM, - (char*)&att_tup, - ObjectIdGetDatum(relid), - UInt16GetDatum(attnum), - 0,0)) { - retval = pstrdup(att_tup.attname.data); - - return(retval); - } - else - return(NULL); + FormData_pg_attribute att_tup; + char *retval; + + if (SearchSysCacheStruct(ATTNUM, + (char *) &att_tup, + ObjectIdGetDatum(relid), + UInt16GetDatum(attnum), + 0, 0)) + { + retval = pstrdup(att_tup.attname.data); + + return (retval); + } + else + return (NULL); } -/* +/* * get_attnum - - * - * Given the relation id and the attribute name, - * return the "attnum" field from the attribute relation. - * + * + * Given the relation id and the attribute name, + * return the "attnum" field from the attribute relation. + * */ AttrNumber get_attnum(Oid relid, char *attname) { - FormData_pg_attribute att_tup; - - if (SearchSysCacheStruct(ATTNAME, (char *) &att_tup, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0,0)) - return(att_tup.attnum); - else - return(InvalidAttrNumber); + FormData_pg_attribute att_tup; + + if (SearchSysCacheStruct(ATTNAME, (char *) &att_tup, + ObjectIdGetDatum(relid), + PointerGetDatum(attname), + 0, 0)) + return (att_tup.attnum); + else + return (InvalidAttrNumber); } -/* +/* * get_atttype - - * - * Given the relation OID and the attribute number with the relation, - * return the attribute type OID. - * + * + * Given the relation OID and the attribute number with the relation, + * return the attribute type OID. + * */ Oid get_atttype(Oid relid, AttrNumber attnum) { - AttributeTupleForm att_tup = (AttributeTupleForm)palloc(sizeof(*att_tup)); - - if (SearchSysCacheStruct(ATTNUM, - (char *) att_tup, - ObjectIdGetDatum(relid), - UInt16GetDatum(attnum), - 0,0)) - return(att_tup->atttypid); - else - return((Oid)NULL); + AttributeTupleForm att_tup = (AttributeTupleForm) palloc(sizeof(*att_tup)); + + if (SearchSysCacheStruct(ATTNUM, + (char *) att_tup, + ObjectIdGetDatum(relid), + UInt16GetDatum(attnum), + 0, 0)) + return (att_tup->atttypid); + else + return ((Oid) NULL); } /* This routine uses the attname instead of the attnum because it @@ -136,353 +137,366 @@ get_atttype(Oid relid, AttrNumber attnum) bool get_attisset(Oid relid, char *attname) { - HeapTuple htup; - AttrNumber attno; - AttributeTupleForm att_tup; - - attno = get_attnum(relid, attname); - - htup = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0,0); - if (!HeapTupleIsValid(htup)) - elog(WARN, "get_attisset: no attribute %.16s in relation %d", - attname, relid); - if (heap_attisnull(htup, attno)) - return(false); - else { - att_tup = (AttributeTupleForm)GETSTRUCT(htup); - return(att_tup->attisset); - } + HeapTuple htup; + AttrNumber attno; + AttributeTupleForm att_tup; + + attno = get_attnum(relid, attname); + + htup = SearchSysCacheTuple(ATTNAME, + ObjectIdGetDatum(relid), + PointerGetDatum(attname), + 0, 0); + if (!HeapTupleIsValid(htup)) + elog(WARN, "get_attisset: no attribute %.16s in relation %d", + attname, relid); + if (heap_attisnull(htup, attno)) + return (false); + else + { + att_tup = (AttributeTupleForm) GETSTRUCT(htup); + return (att_tup->attisset); + } } -/* ---------- INDEX CACHE ---------- */ +/* ---------- INDEX CACHE ---------- */ -/* watch this space... +/* watch this space... */ -/* ---------- OPERATOR CACHE ---------- */ +/* ---------- OPERATOR CACHE ---------- */ -/* +/* * get_opcode - - * - * Returns the regproc id of the routine used to implement an - * operator given the operator uid. - * + * + * Returns the regproc id of the routine used to implement an + * operator given the operator uid. + * */ RegProcedure get_opcode(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprcode); - else - return((RegProcedure)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprcode); + else + return ((RegProcedure) NULL); } /* * get_opname - - * returns the name of the operator with the given opno + * returns the name of the operator with the given opno * * Note: return the struct so that it gets copied. */ -char* +char * get_opname(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return (pstrdup(optup.oprname.data)); - else { - elog(WARN, "can't look up operator %d\n", opno); - return NULL; - } + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (pstrdup(optup.oprname.data)); + else + { + elog(WARN, "can't look up operator %d\n", opno); + return NULL; + } } -/* +/* * op_mergesortable - - * - * Returns the left and right sort operators and types corresponding to a - * mergesortable operator, or nil if the operator is not mergesortable. - * + * + * Returns the left and right sort operators and types corresponding to a + * mergesortable operator, or nil if the operator is not mergesortable. + * */ bool -op_mergesortable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp) +op_mergesortable(Oid opno, Oid ltype, Oid rtype, Oid * leftOp, Oid * rightOp) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0) && - optup.oprlsortop && - optup.oprrsortop && - optup.oprleft == ltype && - optup.oprright == rtype) { - - *leftOp = ObjectIdGetDatum(optup.oprlsortop); - *rightOp = ObjectIdGetDatum(optup.oprrsortop); - return TRUE; - } else { - return FALSE; - } + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0) && + optup.oprlsortop && + optup.oprrsortop && + optup.oprleft == ltype && + optup.oprright == rtype) + { + + *leftOp = ObjectIdGetDatum(optup.oprlsortop); + *rightOp = ObjectIdGetDatum(optup.oprrsortop); + return TRUE; + } + else + { + return FALSE; + } } -/* +/* * op_hashjoinable-- - * - * Returns the hash operator corresponding to a hashjoinable operator, + * + * Returns the hash operator corresponding to a hashjoinable operator, * or nil if the operator is not hashjoinable. - * + * */ Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0) && - optup.oprcanhash && - optup.oprleft == ltype && - optup.oprright == rtype) - return(opno); - else - return(InvalidOid); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0) && + optup.oprcanhash && + optup.oprleft == ltype && + optup.oprright == rtype) + return (opno); + else + return (InvalidOid); } -/* +/* * get_commutator - - * - * Returns the corresponding commutator of an operator. - * + * + * Returns the corresponding commutator of an operator. + * */ Oid get_commutator(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprcom); - else - return((Oid)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprcom); + else + return ((Oid) NULL); } HeapTuple get_operator_tuple(Oid opno) { - HeapTuple optup; - - if ((optup = SearchSysCacheTuple(OPROID, - ObjectIdGetDatum(opno), - 0,0,0))) - return(optup); - else - return((HeapTuple)NULL); + HeapTuple optup; + + if ((optup = SearchSysCacheTuple(OPROID, + ObjectIdGetDatum(opno), + 0, 0, 0))) + return (optup); + else + return ((HeapTuple) NULL); } -/* +/* * get_negator - - * - * Returns the corresponding negator of an operator. - * + * + * Returns the corresponding negator of an operator. + * */ Oid get_negator(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprnegate); - else - return((Oid)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprnegate); + else + return ((Oid) NULL); } -/* +/* * get_oprrest - - * - * Returns procedure id for computing selectivity of an operator. - * + * + * Returns procedure id for computing selectivity of an operator. + * */ RegProcedure get_oprrest(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprrest ); - else - return((RegProcedure) NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprrest); + else + return ((RegProcedure) NULL); } -/* +/* * get_oprjoin - - * - * Returns procedure id for computing selectivity of a join. - * + * + * Returns procedure id for computing selectivity of a join. + * */ RegProcedure get_oprjoin(Oid opno) { - FormData_pg_operator optup; - - if (SearchSysCacheStruct(OPROID, (char *) &optup, - ObjectIdGetDatum(opno), - 0,0,0)) - return(optup.oprjoin); - else - return((RegProcedure)NULL); + FormData_pg_operator optup; + + if (SearchSysCacheStruct(OPROID, (char *) &optup, + ObjectIdGetDatum(opno), + 0, 0, 0)) + return (optup.oprjoin); + else + return ((RegProcedure) NULL); } -/* ---------- RELATION CACHE ---------- */ +/* ---------- RELATION CACHE ---------- */ -/* +/* * get_relnatts - - * - * Returns the number of attributes for a given relation. - * + * + * Returns the number of attributes for a given relation. + * */ int get_relnatts(Oid relid) { - FormData_pg_class reltup; - - if (SearchSysCacheStruct(RELOID, (char *) &reltup, - ObjectIdGetDatum(relid), - 0,0,0)) - return(reltup.relnatts); - else - return(InvalidAttrNumber); + FormData_pg_class reltup; + + if (SearchSysCacheStruct(RELOID, (char *) &reltup, + ObjectIdGetDatum(relid), + 0, 0, 0)) + return (reltup.relnatts); + else + return (InvalidAttrNumber); } -/* +/* * get_rel_name - - * - * Returns the name of a given relation. - * + * + * Returns the name of a given relation. + * */ -char* +char * get_rel_name(Oid relid) { - FormData_pg_class reltup; - - if ((SearchSysCacheStruct(RELOID, - (char*)&reltup, - ObjectIdGetDatum(relid), - 0,0,0))) { - return (pstrdup(reltup.relname.data)); - } else - return(NULL); + FormData_pg_class reltup; + + if ((SearchSysCacheStruct(RELOID, + (char *) &reltup, + ObjectIdGetDatum(relid), + 0, 0, 0))) + { + return (pstrdup(reltup.relname.data)); + } + else + return (NULL); } -/* ---------- TYPE CACHE ---------- */ +/* ---------- TYPE CACHE ---------- */ -/* +/* * get_typlen - - * - * Given the type OID, return the length of the type. - * + * + * Given the type OID, return the length of the type. + * */ int16 get_typlen(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) - return(typtup.typlen); - else - return((int16)NULL); + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + return (typtup.typlen); + else + return ((int16) NULL); } -/* +/* * get_typbyval - - * - * Given the type OID, determine whether the type is returned by value or - * not. Returns 1 if by value, 0 if by reference. - * + * + * Given the type OID, determine whether the type is returned by value or + * not. Returns 1 if by value, 0 if by reference. + * */ bool get_typbyval(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) - return((bool)typtup.typbyval); - else - return(false); + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + return ((bool) typtup.typbyval); + else + return (false); } -/* +/* * get_typbyval - - * - * Given the type OID, determine whether the type is returned by value or - * not. Returns 1 if by value, 0 if by reference. - * + * + * Given the type OID, determine whether the type is returned by value or + * not. Returns 1 if by value, 0 if by reference. + * */ #ifdef NOT_USED char get_typalign(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) - return(typtup.typalign); - else - return ('i'); + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + return (typtup.typalign); + else + return ('i'); } + #endif -/* - * get_typdefault - - * - * Given the type OID, return the default value of the ADT. - * +/* + * get_typdefault - + * + * Given the type OID, return the default value of the ADT. + * */ struct varlena * get_typdefault(Oid typid) { - struct varlena *typdefault = - (struct varlena *)TypeDefaultRetrieve (typid); - return(typdefault); + struct varlena *typdefault = + (struct varlena *) TypeDefaultRetrieve(typid); + + return (typdefault); } -/* +/* * get_typtype - - * - * Given the type OID, find if it is a basic type, a named relation - * or the generic type 'relation'. - * It returns the null char if the cache lookup fails... - * + * + * Given the type OID, find if it is a basic type, a named relation + * or the generic type 'relation'. + * It returns the null char if the cache lookup fails... + * */ #ifdef NOT_USED char get_typtype(Oid typid) { - TypeTupleFormData typtup; - - if (SearchSysCacheStruct(TYPOID, (char *) &typtup, - ObjectIdGetDatum(typid), - 0,0,0)) { - return(typtup.typtype); - } else { - return('\0'); - } + TypeTupleFormData typtup; + + if (SearchSysCacheStruct(TYPOID, (char *) &typtup, + ObjectIdGetDatum(typid), + 0, 0, 0)) + { + return (typtup.typtype); + } + else + { + return ('\0'); + } } + #endif diff --git a/src/backend/utils/cache/rel.c b/src/backend/utils/cache/rel.c index 33eabad1a85..4e45138037c 100644 --- a/src/backend/utils/cache/rel.c +++ b/src/backend/utils/cache/rel.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * rel.c-- - * POSTGRES relation descriptor code. + * POSTGRES relation descriptor code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.1.1.1 1996/07/09 06:22:06 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.2 1997/09/07 04:53:07 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,57 +21,56 @@ #include "storage/fd.h" -/* - * RelationIsValid is now a macro in rel.h -cim 4/27/91 +/* + * RelationIsValid is now a macro in rel.h -cim 4/27/91 * - * Many of the RelationGet...() functions are now macros in rel.h - * -mer 3/2/92 + * Many of the RelationGet...() functions are now macros in rel.h + * -mer 3/2/92 */ /* * RelationGetIndexStrategy -- - * Returns index strategy for a relation. + * Returns index strategy for a relation. * * Note: - * Assumes relation descriptor is valid. - * Assumes relation descriptor is for an index relation. + * Assumes relation descriptor is valid. + * Assumes relation descriptor is for an index relation. */ IndexStrategy RelationGetIndexStrategy(Relation relation) { - return relation->rd_istrat; + return relation->rd_istrat; } /* * RelationSetIndexSupport -- - * Sets index strategy and support info for a relation. + * Sets index strategy and support info for a relation. * * Note: - * Assumes relation descriptor is a valid pointer to sufficient space. - * Assumes index strategy is valid. Assumes support is valid if non- - * NULL. + * Assumes relation descriptor is a valid pointer to sufficient space. + * Assumes index strategy is valid. Assumes support is valid if non- + * NULL. */ /* ---------------- - * RelationSetIndexSupport + * RelationSetIndexSupport * - * This routine saves two pointers -- one to the IndexStrategy, and - * one to the RegProcs that support the indexed access method. These - * pointers are stored in the space following the attribute data in the - * reldesc. + * This routine saves two pointers -- one to the IndexStrategy, and + * one to the RegProcs that support the indexed access method. These + * pointers are stored in the space following the attribute data in the + * reldesc. * - * NEW: the index strategy and support are now stored in real fields - * at the end of the structure - jolly + * NEW: the index strategy and support are now stored in real fields + * at the end of the structure - jolly * ---------------- */ void RelationSetIndexSupport(Relation relation, - IndexStrategy strategy, - RegProcedure *support) + IndexStrategy strategy, + RegProcedure * support) { - Assert(PointerIsValid(relation)); - Assert(IndexStrategyIsValid(strategy)); - - relation->rd_istrat = strategy; - relation->rd_support = support; -} + Assert(PointerIsValid(relation)); + Assert(IndexStrategyIsValid(strategy)); + relation->rd_istrat = strategy; + relation->rd_support = support; +} diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a54f1d81387..704d673279b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1,41 +1,41 @@ /*------------------------------------------------------------------------- * * relcache.c-- - * POSTGRES relation descriptor cache code + * POSTGRES relation descriptor cache code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.20 1997/09/01 08:04:38 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.21 1997/09/07 04:53:08 momjian Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * RelationInitialize - initialize relcache - * RelationIdCacheGetRelation - get a reldesc from the cache (id) - * RelationNameCacheGetRelation - get a reldesc from the cache (name) - * RelationIdGetRelation - get a reldesc by relation id - * RelationNameGetRelation - get a reldesc by relation name - * RelationClose - close an open relation - * RelationFlushRelation - flush relation information + * RelationInitialize - initialize relcache + * RelationIdCacheGetRelation - get a reldesc from the cache (id) + * RelationNameCacheGetRelation - get a reldesc from the cache (name) + * RelationIdGetRelation - get a reldesc by relation id + * RelationNameGetRelation - get a reldesc by relation name + * RelationClose - close an open relation + * RelationFlushRelation - flush relation information * * NOTES - * This file is in the process of being cleaned up - * before I add system attribute indexing. -cim 1/13/91 + * This file is in the process of being cleaned up + * before I add system attribute indexing. -cim 1/13/91 * - * The following code contains many undocumented hacks. Please be - * careful.... + * The following code contains many undocumented hacks. Please be + * careful.... * */ #include <sys/types.h> -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <errno.h> #include <sys/file.h> #include <fcntl.h> #include <string.h> - + #include "postgres.h" #include "miscadmin.h" @@ -51,21 +51,21 @@ #include "access/tupdesc.h" #include "access/tupmacs.h" #include "access/xact.h" - + #include "storage/buf.h" -#include "storage/fd.h" /* for SEEK_ */ +#include "storage/fd.h" /* for SEEK_ */ #include "storage/lmgr.h" #include "storage/bufmgr.h" - + #include "lib/hasht.h" - + #include "utils/memutils.h" #include "utils/mcxt.h" #include "utils/rel.h" #include "utils/relcache.h" #include "utils/hsearch.h" #include "utils/relcache.h" - + #include "catalog/catname.h" #include "catalog/catalog.h" #include "utils/syscache.h" @@ -87,1744 +87,1813 @@ #include "catalog/index.h" #include "fmgr.h" -static void RelationFlushRelation(Relation *relationPtr, - bool onlyFlushReferenceCountZero); +static void +RelationFlushRelation(Relation * relationPtr, + bool onlyFlushReferenceCountZero); static Relation RelationNameCacheGetRelation(char *relationName); -static void init_irels(void); -static void write_irels(void); +static void init_irels(void); +static void write_irels(void); /* ---------------- - * defines + * defines * ---------------- */ #define private static #define INIT_FILENAME "pg_internal.init" /* ---------------- - * externs + * externs * ---------------- */ -extern bool AMI_OVERRIDE; /* XXX style */ +extern bool AMI_OVERRIDE; /* XXX style */ extern GlobalMemory CacheCxt; /* from utils/cache/catcache.c */ /* ---------------- - * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h + * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h * ---------------- */ -FormData_pg_attribute Desc_pg_class[Natts_pg_class] = { Schema_pg_class }; -FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = { Schema_pg_attribute }; -FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = { Schema_pg_proc }; -FormData_pg_attribute Desc_pg_type[Natts_pg_type] = { Schema_pg_type }; -FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = { Schema_pg_variable }; -FormData_pg_attribute Desc_pg_log[Natts_pg_log] = { Schema_pg_log }; -FormData_pg_attribute Desc_pg_time[Natts_pg_time] = { Schema_pg_time }; +FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class}; +FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute}; +FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc}; +FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type}; +FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = {Schema_pg_variable}; +FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log}; +FormData_pg_attribute Desc_pg_time[Natts_pg_time] = {Schema_pg_time}; /* ---------------- - * global variables + * global variables * - * Relations are cached two ways, by name and by id, - * thus there are two hash tables for referencing them. + * Relations are cached two ways, by name and by id, + * thus there are two hash tables for referencing them. * ---------------- */ -HTAB *RelationNameCache; -HTAB *RelationIdCache; +HTAB *RelationNameCache; +HTAB *RelationIdCache; /* ---------------- - * RelationBuildDescInfo exists so code can be shared - * between RelationIdGetRelation() and RelationNameGetRelation() + * RelationBuildDescInfo exists so code can be shared + * between RelationIdGetRelation() and RelationNameGetRelation() * ---------------- */ -typedef struct RelationBuildDescInfo { - int infotype; /* lookup by id or by name */ +typedef struct RelationBuildDescInfo +{ + int infotype; /* lookup by id or by name */ #define INFO_RELID 1 #define INFO_RELNAME 2 - union { - Oid info_id; /* relation object id */ - char *info_name; /* relation name */ - } i; -} RelationBuildDescInfo; - -typedef struct relidcacheent { - Oid reloid; - Relation reldesc; -} RelIdCacheEnt; - -typedef struct relnamecacheent { - NameData relname; - Relation reldesc; -} RelNameCacheEnt; + union + { + Oid info_id;/* relation object id */ + char *info_name; /* relation name */ + } i; +} RelationBuildDescInfo; + +typedef struct relidcacheent +{ + Oid reloid; + Relation reldesc; +} RelIdCacheEnt; + +typedef struct relnamecacheent +{ + NameData relname; + Relation reldesc; +} RelNameCacheEnt; /* ----------------- - * macros to manipulate name cache and id cache + * macros to manipulate name cache and id cache * ----------------- */ #define RelationCacheInsert(RELATION) \ - { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ - char *relname; Oid reloid; bool found; \ - relname = (RELATION->rd_rel->relname).data; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - relname, \ - HASH_ENTER, \ - &found); \ - if (namehentry == NULL) { \ - elog(FATAL, "can't insert into relation descriptor cache"); \ - } \ - if (found && !IsBootstrapProcessingMode()) { \ - /* used to give notice -- now just keep quiet */ ; \ - } \ - namehentry->reldesc = RELATION; \ - reloid = RELATION->rd_id; \ - idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&reloid, \ - HASH_ENTER, \ - &found); \ - if (idhentry == NULL) { \ - elog(FATAL, "can't insert into relation descriptor cache"); \ - } \ - if (found && !IsBootstrapProcessingMode()) { \ - /* used to give notice -- now just keep quiet */ ; \ - } \ - idhentry->reldesc = RELATION; \ - } -#define RelationNameCacheLookup(NAME, RELATION) \ - { RelNameCacheEnt *hentry; bool found; \ - hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - (char *)NAME,HASH_FIND,&found); \ - if (hentry == NULL) { \ - elog(FATAL, "error in CACHE"); \ - } \ - if (found) { \ - RELATION = hentry->reldesc; \ - } \ - else { \ - RELATION = NULL; \ - } \ - } -#define RelationIdCacheLookup(ID, RELATION) \ - { RelIdCacheEnt *hentry; bool found; \ - hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&(ID),HASH_FIND, &found); \ - if (hentry == NULL) { \ - elog(FATAL, "error in CACHE"); \ - } \ - if (found) { \ - RELATION = hentry->reldesc; \ - } \ - else { \ - RELATION = NULL; \ - } \ - } + { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ + char *relname; Oid reloid; bool found; \ + relname = (RELATION->rd_rel->relname).data; \ + namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + relname, \ + HASH_ENTER, \ + &found); \ + if (namehentry == NULL) { \ + elog(FATAL, "can't insert into relation descriptor cache"); \ + } \ + if (found && !IsBootstrapProcessingMode()) { \ + /* used to give notice -- now just keep quiet */ ; \ + } \ + namehentry->reldesc = RELATION; \ + reloid = RELATION->rd_id; \ + idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&reloid, \ + HASH_ENTER, \ + &found); \ + if (idhentry == NULL) { \ + elog(FATAL, "can't insert into relation descriptor cache"); \ + } \ + if (found && !IsBootstrapProcessingMode()) { \ + /* used to give notice -- now just keep quiet */ ; \ + } \ + idhentry->reldesc = RELATION; \ + } +#define RelationNameCacheLookup(NAME, RELATION) \ + { RelNameCacheEnt *hentry; bool found; \ + hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + (char *)NAME,HASH_FIND,&found); \ + if (hentry == NULL) { \ + elog(FATAL, "error in CACHE"); \ + } \ + if (found) { \ + RELATION = hentry->reldesc; \ + } \ + else { \ + RELATION = NULL; \ + } \ + } +#define RelationIdCacheLookup(ID, RELATION) \ + { RelIdCacheEnt *hentry; bool found; \ + hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&(ID),HASH_FIND, &found); \ + if (hentry == NULL) { \ + elog(FATAL, "error in CACHE"); \ + } \ + if (found) { \ + RELATION = hentry->reldesc; \ + } \ + else { \ + RELATION = NULL; \ + } \ + } #define RelationCacheDelete(RELATION) \ - { RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \ - char *relname; Oid reloid; bool found; \ - relname = (RELATION->rd_rel->relname).data; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - relname, \ - HASH_REMOVE, \ - &found); \ - if (namehentry == NULL) { \ - elog(FATAL, "can't delete from relation descriptor cache"); \ - } \ - if (!found) { \ - elog(NOTICE, "trying to delete a reldesc that does not exist."); \ - } \ - reloid = RELATION->rd_id; \ - idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&reloid, \ - HASH_REMOVE, &found); \ - if (idhentry == NULL) { \ - elog(FATAL, "can't delete from relation descriptor cache"); \ - } \ - if (!found) { \ - elog(NOTICE, "trying to delete a reldesc that does not exist."); \ - } \ - } + { RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \ + char *relname; Oid reloid; bool found; \ + relname = (RELATION->rd_rel->relname).data; \ + namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + relname, \ + HASH_REMOVE, \ + &found); \ + if (namehentry == NULL) { \ + elog(FATAL, "can't delete from relation descriptor cache"); \ + } \ + if (!found) { \ + elog(NOTICE, "trying to delete a reldesc that does not exist."); \ + } \ + reloid = RELATION->rd_id; \ + idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&reloid, \ + HASH_REMOVE, &found); \ + if (idhentry == NULL) { \ + elog(FATAL, "can't delete from relation descriptor cache"); \ + } \ + if (!found) { \ + elog(NOTICE, "trying to delete a reldesc that does not exist."); \ + } \ + } /* non-export function prototypes */ -static void formrdesc(char *relationName, u_int natts, - FormData_pg_attribute att[]); +static void +formrdesc(char *relationName, u_int natts, + FormData_pg_attribute att[]); + +#if 0 /* See comments at line 1304 */ +static void RelationFlushIndexes(Relation * r, Oid accessMethodId); -#if 0 /* See comments at line 1304 */ -static void RelationFlushIndexes(Relation *r, Oid accessMethodId); #endif static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo); static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp); -static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); -static void build_tupdesc_seq(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); -static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); +static void +RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); +static void +build_tupdesc_seq(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); +static void +build_tupdesc_ind(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo); -static void IndexedAccessMethodInitialize(Relation relation); -static void AttrDefaultFetch (Relation relation); -static void RelCheckFetch (Relation relation); +static void IndexedAccessMethodInitialize(Relation relation); +static void AttrDefaultFetch(Relation relation); +static void RelCheckFetch(Relation relation); -extern void RelationBuildTriggers (Relation relation); -extern void FreeTriggerDesc (Relation relation); +extern void RelationBuildTriggers(Relation relation); +extern void FreeTriggerDesc(Relation relation); /* * newlyCreatedRelns - - * relations created during this transaction. We need to keep track of - * these. + * relations created during this transaction. We need to keep track of + * these. */ -static List *newlyCreatedRelns = NULL; +static List *newlyCreatedRelns = NULL; /* ---------------------------------------------------------------- - * RelationIdGetRelation() and RelationNameGetRelation() - * support functions + * RelationIdGetRelation() and RelationNameGetRelation() + * support functions * ---------------------------------------------------------------- */ - -#if NOT_USED /* XXX This doesn't seem to be used anywhere */ + +#if NOT_USED /* XXX This doesn't seem to be used + * anywhere */ /* -------------------------------- - * BuildDescInfoError returns a string appropriate to - * the buildinfo passed to it + * BuildDescInfoError returns a string appropriate to + * the buildinfo passed to it * -------------------------------- */ -static char * +static char * BuildDescInfoError(RelationBuildDescInfo buildinfo) { - static char errBuf[64]; - - memset(errBuf, 0, (int) sizeof(errBuf)); - switch(buildinfo.infotype) { - case INFO_RELID: - sprintf(errBuf, "(relation id %d)", buildinfo.i.info_id); - break; - case INFO_RELNAME: - sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name); - break; - } - - return errBuf; + static char errBuf[64]; + + memset(errBuf, 0, (int) sizeof(errBuf)); + switch (buildinfo.infotype) + { + case INFO_RELID: + sprintf(errBuf, "(relation id %d)", buildinfo.i.info_id); + break; + case INFO_RELNAME: + sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name); + break; + } + + return errBuf; } + #endif /* -------------------------------- - * ScanPgRelation + * ScanPgRelation * - * this is used by RelationBuildDesc to find a pg_class - * tuple matching either a relation name or a relation id - * as specified in buildinfo. + * this is used by RelationBuildDesc to find a pg_class + * tuple matching either a relation name or a relation id + * as specified in buildinfo. * -------------------------------- */ -static HeapTuple +static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo) { - /* - * If this is bootstrap time (initdb), then we can't use the system - * catalog indices, because they may not exist yet. Otherwise, we - * can, and do. - */ - - if (IsBootstrapProcessingMode()) - return (scan_pg_rel_seq(buildinfo)); - else - return (scan_pg_rel_ind(buildinfo)); + + /* + * If this is bootstrap time (initdb), then we can't use the system + * catalog indices, because they may not exist yet. Otherwise, we + * can, and do. + */ + + if (IsBootstrapProcessingMode()) + return (scan_pg_rel_seq(buildinfo)); + else + return (scan_pg_rel_ind(buildinfo)); } -static HeapTuple +static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo) { - HeapTuple pg_class_tuple; - HeapTuple return_tuple; - Relation pg_class_desc; - HeapScanDesc pg_class_scan; - ScanKeyData key; - Buffer buf; - - /* ---------------- - * form a scan key - * ---------------- - */ - switch (buildinfo.infotype) { - case INFO_RELID: - ScanKeyEntryInitialize(&key, 0, - ObjectIdAttributeNumber, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(buildinfo.i.info_id)); - break; - - case INFO_RELNAME: - ScanKeyEntryInitialize(&key, 0, - Anum_pg_class_relname, - Character16EqualRegProcedure, - NameGetDatum(buildinfo.i.info_name)); - break; - - default: - elog(WARN, "ScanPgRelation: bad buildinfo"); - return NULL; - } - - /* ---------------- - * open pg_class and fetch a tuple - * ---------------- - */ - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - RelationSetLockForRead(pg_class_desc); - pg_class_scan = - heap_beginscan(pg_class_desc, 0, NowTimeQual, 1, &key); - pg_class_tuple = heap_getnext(pg_class_scan, 0, &buf); - - /* ---------------- - * get set to return tuple - * ---------------- - */ - if (! HeapTupleIsValid(pg_class_tuple)) { - return_tuple = pg_class_tuple; - } else { - /* ------------------ - * a satanic bug used to live here: pg_class_tuple used to be - * returned here without having the corresponding buffer pinned. - * so when the buffer gets replaced, all hell breaks loose. - * this bug is discovered and killed by wei on 9/27/91. - * ------------------- + HeapTuple pg_class_tuple; + HeapTuple return_tuple; + Relation pg_class_desc; + HeapScanDesc pg_class_scan; + ScanKeyData key; + Buffer buf; + + /* ---------------- + * form a scan key + * ---------------- */ - return_tuple = (HeapTuple) palloc((Size) pg_class_tuple->t_len); - memmove((char *) return_tuple, - (char *) pg_class_tuple, - (int) pg_class_tuple->t_len); - ReleaseBuffer(buf); - } - - /* all done */ - heap_endscan(pg_class_scan); - if (!IsInitProcessingMode()) - RelationUnsetLockForRead(pg_class_desc); - heap_close(pg_class_desc); - - return return_tuple; + switch (buildinfo.infotype) + { + case INFO_RELID: + ScanKeyEntryInitialize(&key, 0, + ObjectIdAttributeNumber, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(buildinfo.i.info_id)); + break; + + case INFO_RELNAME: + ScanKeyEntryInitialize(&key, 0, + Anum_pg_class_relname, + Character16EqualRegProcedure, + NameGetDatum(buildinfo.i.info_name)); + break; + + default: + elog(WARN, "ScanPgRelation: bad buildinfo"); + return NULL; + } + + /* ---------------- + * open pg_class and fetch a tuple + * ---------------- + */ + pg_class_desc = heap_openr(RelationRelationName); + if (!IsInitProcessingMode()) + RelationSetLockForRead(pg_class_desc); + pg_class_scan = + heap_beginscan(pg_class_desc, 0, NowTimeQual, 1, &key); + pg_class_tuple = heap_getnext(pg_class_scan, 0, &buf); + + /* ---------------- + * get set to return tuple + * ---------------- + */ + if (!HeapTupleIsValid(pg_class_tuple)) + { + return_tuple = pg_class_tuple; + } + else + { + /* ------------------ + * a satanic bug used to live here: pg_class_tuple used to be + * returned here without having the corresponding buffer pinned. + * so when the buffer gets replaced, all hell breaks loose. + * this bug is discovered and killed by wei on 9/27/91. + * ------------------- + */ + return_tuple = (HeapTuple) palloc((Size) pg_class_tuple->t_len); + memmove((char *) return_tuple, + (char *) pg_class_tuple, + (int) pg_class_tuple->t_len); + ReleaseBuffer(buf); + } + + /* all done */ + heap_endscan(pg_class_scan); + if (!IsInitProcessingMode()) + RelationUnsetLockForRead(pg_class_desc); + heap_close(pg_class_desc); + + return return_tuple; } -static HeapTuple +static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo) { - Relation pg_class_desc; - HeapTuple return_tuple; - - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - RelationSetLockForRead(pg_class_desc); - - switch (buildinfo.infotype) { - case INFO_RELID: - return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id); - break; - - case INFO_RELNAME: - return_tuple = ClassNameIndexScan(pg_class_desc, - buildinfo.i.info_name); - break; - - default: - elog(WARN, "ScanPgRelation: bad buildinfo"); - /* XXX I hope this is right. It seems better than returning - * an uninitialized value */ - return_tuple = NULL; - } - - /* all done */ - if (!IsInitProcessingMode()) - RelationUnsetLockForRead(pg_class_desc); - heap_close(pg_class_desc); - - return return_tuple; + Relation pg_class_desc; + HeapTuple return_tuple; + + pg_class_desc = heap_openr(RelationRelationName); + if (!IsInitProcessingMode()) + RelationSetLockForRead(pg_class_desc); + + switch (buildinfo.infotype) + { + case INFO_RELID: + return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id); + break; + + case INFO_RELNAME: + return_tuple = ClassNameIndexScan(pg_class_desc, + buildinfo.i.info_name); + break; + + default: + elog(WARN, "ScanPgRelation: bad buildinfo"); + + /* + * XXX I hope this is right. It seems better than returning an + * uninitialized value + */ + return_tuple = NULL; + } + + /* all done */ + if (!IsInitProcessingMode()) + RelationUnsetLockForRead(pg_class_desc); + heap_close(pg_class_desc); + + return return_tuple; } /* ---------------- - * AllocateRelationDesc + * AllocateRelationDesc * - * This is used to allocate memory for a new relation descriptor - * and initialize the rd_rel field. + * This is used to allocate memory for a new relation descriptor + * and initialize the rd_rel field. * ---------------- */ -static Relation +static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp) { - Relation relation; - Size len; - Form_pg_class relationTupleForm; - - /* ---------------- - * allocate space for the relation tuple form - * ---------------- - */ - relationTupleForm = (Form_pg_class) - palloc((Size) (sizeof(FormData_pg_class))); - - memmove((char *) relationTupleForm, (char *) relp, CLASS_TUPLE_SIZE); - - /* ---------------- - * allocate space for new relation descriptor - */ - len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */ - - relation = (Relation) palloc(len); - - /* ---------------- - * clear new reldesc - * ---------------- - */ - memset((char *) relation, 0, len); - - /* initialize attribute tuple form */ - relation->rd_att = CreateTemplateTupleDesc(natts); - - /*and initialize relation tuple form */ - relation->rd_rel = relationTupleForm; - - return relation; + Relation relation; + Size len; + Form_pg_class relationTupleForm; + + /* ---------------- + * allocate space for the relation tuple form + * ---------------- + */ + relationTupleForm = (Form_pg_class) + palloc((Size) (sizeof(FormData_pg_class))); + + memmove((char *) relationTupleForm, (char *) relp, CLASS_TUPLE_SIZE); + + /* ---------------- + * allocate space for new relation descriptor + */ + len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */ + + relation = (Relation) palloc(len); + + /* ---------------- + * clear new reldesc + * ---------------- + */ + memset((char *) relation, 0, len); + + /* initialize attribute tuple form */ + relation->rd_att = CreateTemplateTupleDesc(natts); + + /* and initialize relation tuple form */ + relation->rd_rel = relationTupleForm; + + return relation; } /* -------------------------------- - * RelationBuildTupleDesc + * RelationBuildTupleDesc * - * Form the relation's tuple descriptor from information in - * the pg_attribute, pg_attrdef & pg_relcheck system cataloges. + * Form the relation's tuple descriptor from information in + * the pg_attribute, pg_attrdef & pg_relcheck system cataloges. * -------------------------------- */ static void -RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) +RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, + Relation relation, + u_int natts) { - /* - * If this is bootstrap time (initdb), then we can't use the system - * catalog indices, because they may not exist yet. Otherwise, we - * can, and do. - */ - - if (IsBootstrapProcessingMode()) - build_tupdesc_seq(buildinfo, relation, natts); - else - build_tupdesc_ind(buildinfo, relation, natts); + + /* + * If this is bootstrap time (initdb), then we can't use the system + * catalog indices, because they may not exist yet. Otherwise, we + * can, and do. + */ + + if (IsBootstrapProcessingMode()) + build_tupdesc_seq(buildinfo, relation, natts); + else + build_tupdesc_ind(buildinfo, relation, natts); } static void build_tupdesc_seq(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) + Relation relation, + u_int natts) { - HeapTuple pg_attribute_tuple; - Relation pg_attribute_desc; - HeapScanDesc pg_attribute_scan; - AttributeTupleForm attp; - ScanKeyData key; - int need; - - /* ---------------- - * form a scan key - * ---------------- - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_attribute_attrelid, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - /* ---------------- - * open pg_attribute and begin a scan - * ---------------- - */ - pg_attribute_desc = heap_openr(AttributeRelationName); - pg_attribute_scan = - heap_beginscan(pg_attribute_desc, 0, NowTimeQual, 1, &key); - - /* ---------------- - * add attribute data to relation->rd_att - * ---------------- - */ - need = natts; - - pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL); - while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) { - attp = (AttributeTupleForm) GETSTRUCT(pg_attribute_tuple); - - if (attp->attnum > 0) { - relation->rd_att->attrs[attp->attnum - 1] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - - memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]), - (char *) attp, - ATTRIBUTE_TUPLE_SIZE); - need--; + HeapTuple pg_attribute_tuple; + Relation pg_attribute_desc; + HeapScanDesc pg_attribute_scan; + AttributeTupleForm attp; + ScanKeyData key; + int need; + + /* ---------------- + * form a scan key + * ---------------- + */ + ScanKeyEntryInitialize(&key, 0, + Anum_pg_attribute_attrelid, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + /* ---------------- + * open pg_attribute and begin a scan + * ---------------- + */ + pg_attribute_desc = heap_openr(AttributeRelationName); + pg_attribute_scan = + heap_beginscan(pg_attribute_desc, 0, NowTimeQual, 1, &key); + + /* ---------------- + * add attribute data to relation->rd_att + * ---------------- + */ + need = natts; + + pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL); + while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) + { + attp = (AttributeTupleForm) GETSTRUCT(pg_attribute_tuple); + + if (attp->attnum > 0) + { + relation->rd_att->attrs[attp->attnum - 1] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]), + (char *) attp, + ATTRIBUTE_TUPLE_SIZE); + need--; + } + pg_attribute_tuple = heap_getnext(pg_attribute_scan, + 0, (Buffer *) NULL); } - pg_attribute_tuple = heap_getnext(pg_attribute_scan, - 0, (Buffer *) NULL); - } - - if (need > 0) - elog(WARN, "catalog is missing %d attribute%s for relid %d", - need, (need == 1 ? "" : "s"), relation->rd_id); - - /* ---------------- - * end the scan and close the attribute relation - * ---------------- - */ - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc); + + if (need > 0) + elog(WARN, "catalog is missing %d attribute%s for relid %d", + need, (need == 1 ? "" : "s"), relation->rd_id); + + /* ---------------- + * end the scan and close the attribute relation + * ---------------- + */ + heap_endscan(pg_attribute_scan); + heap_close(pg_attribute_desc); } static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) + Relation relation, + u_int natts) { - Relation attrel; - HeapTuple atttup; - AttributeTupleForm attp; - TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); - AttrDefault *attrdef = NULL; - int ndef = 0; - int i; - - constr->has_not_null = false; - - attrel = heap_openr(AttributeRelationName); - - for (i = 1; i <= relation->rd_rel->relnatts; i++) { - - atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i); - - if (!HeapTupleIsValid(atttup)) - elog(WARN, "cannot find attribute %d of relation %.*s", i, - NAMEDATALEN, &(relation->rd_rel->relname.data[0])); - attp = (AttributeTupleForm) GETSTRUCT(atttup); - - relation->rd_att->attrs[i - 1] = - (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); - - memmove((char *) (relation->rd_att->attrs[i - 1]), - (char *) attp, - ATTRIBUTE_TUPLE_SIZE); - - /* Update if this attribute have a constraint */ - if (attp->attnotnull) - constr->has_not_null = true; - - if (attp->atthasdef) + Relation attrel; + HeapTuple atttup; + AttributeTupleForm attp; + TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); + AttrDefault *attrdef = NULL; + int ndef = 0; + int i; + + constr->has_not_null = false; + + attrel = heap_openr(AttributeRelationName); + + for (i = 1; i <= relation->rd_rel->relnatts; i++) { - if ( attrdef == NULL ) - attrdef = (AttrDefault*) palloc (relation->rd_rel->relnatts * - sizeof (AttrDefault)); - attrdef[ndef].adnum = i; - attrdef[ndef].adbin = NULL; - attrdef[ndef].adsrc = NULL; - ndef++; + + atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i); + + if (!HeapTupleIsValid(atttup)) + elog(WARN, "cannot find attribute %d of relation %.*s", i, + NAMEDATALEN, &(relation->rd_rel->relname.data[0])); + attp = (AttributeTupleForm) GETSTRUCT(atttup); + + relation->rd_att->attrs[i - 1] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memmove((char *) (relation->rd_att->attrs[i - 1]), + (char *) attp, + ATTRIBUTE_TUPLE_SIZE); + + /* Update if this attribute have a constraint */ + if (attp->attnotnull) + constr->has_not_null = true; + + if (attp->atthasdef) + { + if (attrdef == NULL) + attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts * + sizeof(AttrDefault)); + attrdef[ndef].adnum = i; + attrdef[ndef].adbin = NULL; + attrdef[ndef].adsrc = NULL; + ndef++; + } } - } - - heap_close(attrel); - - if ( constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks ) - { - relation->rd_att->constr = constr; - - if ( ndef > 0 ) /* DEFAULTs */ - { - if ( ndef < relation->rd_rel->relnatts ) - constr->defval = (AttrDefault*) - repalloc (attrdef, ndef * sizeof (AttrDefault)); - else - constr->defval = attrdef; - constr->num_defval = ndef; - AttrDefaultFetch (relation); - } - else - constr->num_defval = 0; - - if ( relation->rd_rel->relchecks > 0 ) /* CHECKs */ + + heap_close(attrel); + + if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks) { - constr->num_check = relation->rd_rel->relchecks; - constr->check = (ConstrCheck *) palloc (constr->num_check * - sizeof (ConstrCheck)); - memset (constr->check, 0, constr->num_check * sizeof (ConstrCheck)); - RelCheckFetch (relation); + relation->rd_att->constr = constr; + + if (ndef > 0) /* DEFAULTs */ + { + if (ndef < relation->rd_rel->relnatts) + constr->defval = (AttrDefault *) + repalloc(attrdef, ndef * sizeof(AttrDefault)); + else + constr->defval = attrdef; + constr->num_defval = ndef; + AttrDefaultFetch(relation); + } + else + constr->num_defval = 0; + + if (relation->rd_rel->relchecks > 0) /* CHECKs */ + { + constr->num_check = relation->rd_rel->relchecks; + constr->check = (ConstrCheck *) palloc(constr->num_check * + sizeof(ConstrCheck)); + memset(constr->check, 0, constr->num_check * sizeof(ConstrCheck)); + RelCheckFetch(relation); + } + else + constr->num_check = 0; } else - constr->num_check = 0; - } - else - { - pfree (constr); - relation->rd_att->constr = NULL; - } - + { + pfree(constr); + relation->rd_att->constr = NULL; + } + } /* -------------------------------- - * RelationBuildRuleLock + * RelationBuildRuleLock * - * Form the relation's rewrite rules from information in - * the pg_rewrite system catalog. + * Form the relation's rewrite rules from information in + * the pg_rewrite system catalog. * -------------------------------- */ static void RelationBuildRuleLock(Relation relation) { - HeapTuple pg_rewrite_tuple; - Relation pg_rewrite_desc; - TupleDesc pg_rewrite_tupdesc; - HeapScanDesc pg_rewrite_scan; - ScanKeyData key; - RuleLock *rulelock; - int numlocks; - RewriteRule **rules; - int maxlocks; - - /* ---------------- - * form an array to hold the rewrite rules (the array is extended if - * necessary) - * ---------------- - */ - maxlocks = 4; - rules = (RewriteRule **)palloc(sizeof(RewriteRule*)*maxlocks); - numlocks = 0; - - /* ---------------- - * form a scan key - * ---------------- - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_rewrite_ev_class, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - /* ---------------- - * open pg_attribute and begin a scan - * ---------------- - */ - pg_rewrite_desc = heap_openr(RewriteRelationName); - pg_rewrite_scan = - heap_beginscan(pg_rewrite_desc, 0, NowTimeQual, 1, &key); - pg_rewrite_tupdesc = - RelationGetTupleDescriptor(pg_rewrite_desc); - - /* ---------------- - * add attribute data to relation->rd_att - * ---------------- - */ - while ((pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0, - (Buffer *) NULL)) != NULL) { - bool isnull; - char *ruleaction = NULL; - char *rule_evqual_string; - RewriteRule *rule; - - rule = (RewriteRule *)palloc(sizeof(RewriteRule)); - - rule->ruleId = pg_rewrite_tuple->t_oid; - - rule->event = - (int)heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, - &isnull) - 48; - rule->attrno = - (int)heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, - &isnull); - rule->isInstead = - !!heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, - &isnull); - - ruleaction = - heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_action, pg_rewrite_tupdesc, - &isnull); - rule_evqual_string = - heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, - &isnull); - - ruleaction = textout((struct varlena *)ruleaction); - rule_evqual_string = textout((struct varlena *)rule_evqual_string); - - rule->actions = (List*)stringToNode(ruleaction); - rule->qual = (Node*)stringToNode(rule_evqual_string); - - rules[numlocks++] = rule; - if (numlocks==maxlocks) { - maxlocks *= 2; - rules = - (RewriteRule **)repalloc(rules, sizeof(RewriteRule*)*maxlocks); + HeapTuple pg_rewrite_tuple; + Relation pg_rewrite_desc; + TupleDesc pg_rewrite_tupdesc; + HeapScanDesc pg_rewrite_scan; + ScanKeyData key; + RuleLock *rulelock; + int numlocks; + RewriteRule **rules; + int maxlocks; + + /* ---------------- + * form an array to hold the rewrite rules (the array is extended if + * necessary) + * ---------------- + */ + maxlocks = 4; + rules = (RewriteRule **) palloc(sizeof(RewriteRule *) * maxlocks); + numlocks = 0; + + /* ---------------- + * form a scan key + * ---------------- + */ + ScanKeyEntryInitialize(&key, 0, + Anum_pg_rewrite_ev_class, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + /* ---------------- + * open pg_attribute and begin a scan + * ---------------- + */ + pg_rewrite_desc = heap_openr(RewriteRelationName); + pg_rewrite_scan = + heap_beginscan(pg_rewrite_desc, 0, NowTimeQual, 1, &key); + pg_rewrite_tupdesc = + RelationGetTupleDescriptor(pg_rewrite_desc); + + /* ---------------- + * add attribute data to relation->rd_att + * ---------------- + */ + while ((pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0, + (Buffer *) NULL)) != NULL) + { + bool isnull; + char *ruleaction = NULL; + char *rule_evqual_string; + RewriteRule *rule; + + rule = (RewriteRule *) palloc(sizeof(RewriteRule)); + + rule->ruleId = pg_rewrite_tuple->t_oid; + + rule->event = + (int) heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, + &isnull) - 48; + rule->attrno = + (int) heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, + &isnull); + rule->isInstead = + !!heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, + &isnull); + + ruleaction = + heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_action, pg_rewrite_tupdesc, + &isnull); + rule_evqual_string = + heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, + &isnull); + + ruleaction = textout((struct varlena *) ruleaction); + rule_evqual_string = textout((struct varlena *) rule_evqual_string); + + rule->actions = (List *) stringToNode(ruleaction); + rule->qual = (Node *) stringToNode(rule_evqual_string); + + rules[numlocks++] = rule; + if (numlocks == maxlocks) + { + maxlocks *= 2; + rules = + (RewriteRule **) repalloc(rules, sizeof(RewriteRule *) * maxlocks); + } } - } - - /* ---------------- - * end the scan and close the attribute relation - * ---------------- - */ - heap_endscan(pg_rewrite_scan); - heap_close(pg_rewrite_desc); - - /* ---------------- - * form a RuleLock and insert into relation - * ---------------- - */ - rulelock = (RuleLock *)palloc(sizeof(RuleLock)); - rulelock->numLocks = numlocks; - rulelock->rules = rules; - - relation->rd_rules = rulelock; - return; + + /* ---------------- + * end the scan and close the attribute relation + * ---------------- + */ + heap_endscan(pg_rewrite_scan); + heap_close(pg_rewrite_desc); + + /* ---------------- + * form a RuleLock and insert into relation + * ---------------- + */ + rulelock = (RuleLock *) palloc(sizeof(RuleLock)); + rulelock->numLocks = numlocks; + rulelock->rules = rules; + + relation->rd_rules = rulelock; + return; } /* -------------------------------- - * RelationBuildDesc - * - * To build a relation descriptor, we have to allocate space, - * open the underlying unix file and initialize the following - * fields: + * RelationBuildDesc + * + * To build a relation descriptor, we have to allocate space, + * open the underlying unix file and initialize the following + * fields: * - * File rd_fd; open file descriptor - * int rd_nblocks; number of blocks in rel - * it will be set in ambeginscan() - * uint16 rd_refcnt; reference count - * Form_pg_am rd_am; AM tuple - * Form_pg_class rd_rel; RELATION tuple - * Oid rd_id; relations's object id - * Pointer lockInfo; ptr. to misc. info. - * TupleDesc rd_att; tuple desciptor + * File rd_fd; open file descriptor + * int rd_nblocks; number of blocks in rel + * it will be set in ambeginscan() + * uint16 rd_refcnt; reference count + * Form_pg_am rd_am; AM tuple + * Form_pg_class rd_rel; RELATION tuple + * Oid rd_id; relations's object id + * Pointer lockInfo; ptr. to misc. info. + * TupleDesc rd_att; tuple desciptor * - * Note: rd_ismem (rel is in-memory only) is currently unused - * by any part of the system. someday this will indicate that - * the relation lives only in the main-memory buffer pool - * -cim 2/4/91 + * Note: rd_ismem (rel is in-memory only) is currently unused + * by any part of the system. someday this will indicate that + * the relation lives only in the main-memory buffer pool + * -cim 2/4/91 * -------------------------------- */ -static Relation +static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo) { - File fd; - Relation relation; - u_int natts; - Oid relid; - Oid relam; - Form_pg_class relp; - - MemoryContext oldcxt; - - HeapTuple pg_class_tuple; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * find the tuple in pg_class corresponding to the given relation id - * ---------------- - */ - pg_class_tuple = ScanPgRelation(buildinfo); - - /* ---------------- - * if no such tuple exists, return NULL - * ---------------- - */ - if (! HeapTupleIsValid(pg_class_tuple)) { - - MemoryContextSwitchTo(oldcxt); - - return NULL; - } - - /* ---------------- - * get information from the pg_class_tuple - * ---------------- - */ - relid = pg_class_tuple->t_oid; - relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); - natts = relp->relnatts; - - /* ---------------- - * allocate storage for the relation descriptor, - * initialize relation->rd_rel and get the access method id. - * ---------------- - */ - relation = AllocateRelationDesc(natts, relp); - relam = relation->rd_rel->relam; - - /* ---------------- - * initialize the relation's relation id (relation->rd_id) - * ---------------- - */ - relation->rd_id = relid; - - /* ---------------- - * initialize relation->rd_refcnt - * ---------------- - */ - RelationSetReferenceCount(relation, 1); - - /* ---------------- - * normal relations are not nailed into the cache - * ---------------- - */ - relation->rd_isnailed = false; - - /* ---------------- - * initialize the access method information (relation->rd_am) - * ---------------- - */ - if (OidIsValid(relam)) { - relation->rd_am = (Form_pg_am) - AccessMethodObjectIdGetAccessMethodTupleForm(relam); - } - - /* ---------------- - * initialize the tuple descriptor (relation->rd_att). - * remember, rd_att is an array of attribute pointers that lives - * off the end of the relation descriptor structure so space was - * already allocated for it by AllocateRelationDesc. - * ---------------- - */ - RelationBuildTupleDesc(buildinfo, relation, natts); - - /* ---------------- - * initialize rules that affect this relation - * ---------------- - */ - if (relp->relhasrules) { - RelationBuildRuleLock(relation); - } else { - relation->rd_rules = NULL; - } - - /* Triggers */ - if ( relp->reltriggers > 0 ) - RelationBuildTriggers (relation); - else - relation->trigdesc = NULL; - - /* ---------------- - * initialize index strategy and support information for this relation - * ---------------- - */ - if (OidIsValid(relam)) { - IndexedAccessMethodInitialize(relation); - } - - /* ---------------- - * initialize the relation lock manager information - * ---------------- - */ - RelationInitLockInfo(relation); /* see lmgr.c */ - - /* ---------------- - * open the relation and assign the file descriptor returned - * by the storage manager code to rd_fd. - * ---------------- - */ - fd = smgropen(relp->relsmgr, relation); - - Assert (fd >= -1); - if (fd == -1) - elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", - &relp->relname); - - relation->rd_fd = fd; - - /* ---------------- - * insert newly created relation into proper relcaches, - * restore memory context and return the new reldesc. - * ---------------- - */ - - RelationCacheInsert(relation); - - /* ------------------- - * free the memory allocated for pg_class_tuple - * and for lock data pointed to by pg_class_tuple - * ------------------- - */ - pfree(pg_class_tuple); - - MemoryContextSwitchTo(oldcxt); - - return relation; + File fd; + Relation relation; + u_int natts; + Oid relid; + Oid relam; + Form_pg_class relp; + + MemoryContext oldcxt; + + HeapTuple pg_class_tuple; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * find the tuple in pg_class corresponding to the given relation id + * ---------------- + */ + pg_class_tuple = ScanPgRelation(buildinfo); + + /* ---------------- + * if no such tuple exists, return NULL + * ---------------- + */ + if (!HeapTupleIsValid(pg_class_tuple)) + { + + MemoryContextSwitchTo(oldcxt); + + return NULL; + } + + /* ---------------- + * get information from the pg_class_tuple + * ---------------- + */ + relid = pg_class_tuple->t_oid; + relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); + natts = relp->relnatts; + + /* ---------------- + * allocate storage for the relation descriptor, + * initialize relation->rd_rel and get the access method id. + * ---------------- + */ + relation = AllocateRelationDesc(natts, relp); + relam = relation->rd_rel->relam; + + /* ---------------- + * initialize the relation's relation id (relation->rd_id) + * ---------------- + */ + relation->rd_id = relid; + + /* ---------------- + * initialize relation->rd_refcnt + * ---------------- + */ + RelationSetReferenceCount(relation, 1); + + /* ---------------- + * normal relations are not nailed into the cache + * ---------------- + */ + relation->rd_isnailed = false; + + /* ---------------- + * initialize the access method information (relation->rd_am) + * ---------------- + */ + if (OidIsValid(relam)) + { + relation->rd_am = (Form_pg_am) + AccessMethodObjectIdGetAccessMethodTupleForm(relam); + } + + /* ---------------- + * initialize the tuple descriptor (relation->rd_att). + * remember, rd_att is an array of attribute pointers that lives + * off the end of the relation descriptor structure so space was + * already allocated for it by AllocateRelationDesc. + * ---------------- + */ + RelationBuildTupleDesc(buildinfo, relation, natts); + + /* ---------------- + * initialize rules that affect this relation + * ---------------- + */ + if (relp->relhasrules) + { + RelationBuildRuleLock(relation); + } + else + { + relation->rd_rules = NULL; + } + + /* Triggers */ + if (relp->reltriggers > 0) + RelationBuildTriggers(relation); + else + relation->trigdesc = NULL; + + /* ---------------- + * initialize index strategy and support information for this relation + * ---------------- + */ + if (OidIsValid(relam)) + { + IndexedAccessMethodInitialize(relation); + } + + /* ---------------- + * initialize the relation lock manager information + * ---------------- + */ + RelationInitLockInfo(relation); /* see lmgr.c */ + + /* ---------------- + * open the relation and assign the file descriptor returned + * by the storage manager code to rd_fd. + * ---------------- + */ + fd = smgropen(relp->relsmgr, relation); + + Assert(fd >= -1); + if (fd == -1) + elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", + &relp->relname); + + relation->rd_fd = fd; + + /* ---------------- + * insert newly created relation into proper relcaches, + * restore memory context and return the new reldesc. + * ---------------- + */ + + RelationCacheInsert(relation); + + /* ------------------- + * free the memory allocated for pg_class_tuple + * and for lock data pointed to by pg_class_tuple + * ------------------- + */ + pfree(pg_class_tuple); + + MemoryContextSwitchTo(oldcxt); + + return relation; } static void IndexedAccessMethodInitialize(Relation relation) { - IndexStrategy strategy; - RegProcedure *support; - int natts; - Size stratSize; - Size supportSize; - uint16 relamstrategies; - uint16 relamsupport; - - natts = relation->rd_rel->relnatts; - relamstrategies = relation->rd_am->amstrategies; - stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); - strategy = (IndexStrategy) palloc(stratSize); - relamsupport = relation->rd_am->amsupport; - - if (relamsupport > 0) { - supportSize = natts * (relamsupport * sizeof (RegProcedure)); - support = (RegProcedure *) palloc(supportSize); - } else { - support = (RegProcedure *) NULL; - } - - IndexSupportInitialize(strategy, support, - relation->rd_att->attrs[0]->attrelid, - relation->rd_rel->relam, - relamstrategies, relamsupport, natts); - - RelationSetIndexSupport(relation, strategy, support); + IndexStrategy strategy; + RegProcedure *support; + int natts; + Size stratSize; + Size supportSize; + uint16 relamstrategies; + uint16 relamsupport; + + natts = relation->rd_rel->relnatts; + relamstrategies = relation->rd_am->amstrategies; + stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); + strategy = (IndexStrategy) palloc(stratSize); + relamsupport = relation->rd_am->amsupport; + + if (relamsupport > 0) + { + supportSize = natts * (relamsupport * sizeof(RegProcedure)); + support = (RegProcedure *) palloc(supportSize); + } + else + { + support = (RegProcedure *) NULL; + } + + IndexSupportInitialize(strategy, support, + relation->rd_att->attrs[0]->attrelid, + relation->rd_rel->relam, + relamstrategies, relamsupport, natts); + + RelationSetIndexSupport(relation, strategy, support); } /* -------------------------------- - * formrdesc + * formrdesc * - * This is a special version of RelationBuildDesc() - * used by RelationInitialize() in initializing the - * relcache. The system relation descriptors built - * here are all nailed in the descriptor caches, for - * bootstrapping. + * This is a special version of RelationBuildDesc() + * used by RelationInitialize() in initializing the + * relcache. The system relation descriptors built + * here are all nailed in the descriptor caches, for + * bootstrapping. * -------------------------------- */ static void formrdesc(char *relationName, - u_int natts, - FormData_pg_attribute att[]) + u_int natts, + FormData_pg_attribute att[]) { - Relation relation; - Size len; - int i; - - /* ---------------- - * allocate new relation desc - * ---------------- - */ - len = sizeof (RelationData); - relation = (Relation) palloc(len); - memset((char *)relation, 0,len); - - /* ---------------- - * don't open the unix file yet.. - * ---------------- - */ - relation->rd_fd = -1; - - /* ---------------- - * initialize reference count - * ---------------- - */ - RelationSetReferenceCount(relation, 1); - - /* ---------------- - * initialize relation tuple form - * ---------------- - */ - relation->rd_rel = (Form_pg_class) - palloc((Size) (sizeof(*relation->rd_rel))); - memset(relation->rd_rel, 0, sizeof(FormData_pg_class)); - namestrcpy(&relation->rd_rel->relname, relationName); - - /* ---------------- - initialize attribute tuple form - */ - relation->rd_att = CreateTemplateTupleDesc(natts); - - /* - * For debugging purposes, it's important to distinguish between - * shared and non-shared relations, even at bootstrap time. There's - * code in the buffer manager that traces allocations that has to - * know about this. - */ - - if (IsSystemRelationName(relationName)) { - relation->rd_rel->relowner = 6; /* XXX use sym const */ - relation->rd_rel->relisshared = - IsSharedSystemRelationName(relationName); - } else { - relation->rd_rel->relowner = InvalidOid; /* XXX incorrect*/ - relation->rd_rel->relisshared = false; - } - - relation->rd_rel->relpages = 1; /* XXX */ - relation->rd_rel->reltuples = 1; /* XXX */ - relation->rd_rel->relkind = RELKIND_RELATION; - relation->rd_rel->relarch = 'n'; - relation->rd_rel->relnatts = (uint16) natts; - relation->rd_isnailed = true; - - /* ---------------- - * initialize tuple desc info - * ---------------- - */ - for (i = 0; i < natts; i++) { - relation->rd_att->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - - memset((char *)relation->rd_att->attrs[i], 0, - ATTRIBUTE_TUPLE_SIZE); - memmove((char *)relation->rd_att->attrs[i], - (char *)&att[i], - ATTRIBUTE_TUPLE_SIZE); - } - - /* ---------------- - * initialize relation id - * ---------------- - */ - relation->rd_id = relation->rd_att->attrs[0]->attrelid; - - /* ---------------- - * add new reldesc to relcache - * ---------------- - */ - RelationCacheInsert(relation); - /* - * Determining this requires a scan on pg_class, but to do the - * scan the rdesc for pg_class must already exist. Therefore - * we must do the check (and possible set) after cache insertion. - */ - relation->rd_rel->relhasindex = - CatalogHasIndex(relationName, relation->rd_id); + Relation relation; + Size len; + int i; + + /* ---------------- + * allocate new relation desc + * ---------------- + */ + len = sizeof(RelationData); + relation = (Relation) palloc(len); + memset((char *) relation, 0, len); + + /* ---------------- + * don't open the unix file yet.. + * ---------------- + */ + relation->rd_fd = -1; + + /* ---------------- + * initialize reference count + * ---------------- + */ + RelationSetReferenceCount(relation, 1); + + /* ---------------- + * initialize relation tuple form + * ---------------- + */ + relation->rd_rel = (Form_pg_class) + palloc((Size) (sizeof(*relation->rd_rel))); + memset(relation->rd_rel, 0, sizeof(FormData_pg_class)); + namestrcpy(&relation->rd_rel->relname, relationName); + + /* ---------------- + initialize attribute tuple form + */ + relation->rd_att = CreateTemplateTupleDesc(natts); + + /* + * For debugging purposes, it's important to distinguish between + * shared and non-shared relations, even at bootstrap time. There's + * code in the buffer manager that traces allocations that has to know + * about this. + */ + + if (IsSystemRelationName(relationName)) + { + relation->rd_rel->relowner = 6; /* XXX use sym const */ + relation->rd_rel->relisshared = + IsSharedSystemRelationName(relationName); + } + else + { + relation->rd_rel->relowner = InvalidOid; /* XXX incorrect */ + relation->rd_rel->relisshared = false; + } + + relation->rd_rel->relpages = 1; /* XXX */ + relation->rd_rel->reltuples = 1; /* XXX */ + relation->rd_rel->relkind = RELKIND_RELATION; + relation->rd_rel->relarch = 'n'; + relation->rd_rel->relnatts = (uint16) natts; + relation->rd_isnailed = true; + + /* ---------------- + * initialize tuple desc info + * ---------------- + */ + for (i = 0; i < natts; i++) + { + relation->rd_att->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memset((char *) relation->rd_att->attrs[i], 0, + ATTRIBUTE_TUPLE_SIZE); + memmove((char *) relation->rd_att->attrs[i], + (char *) &att[i], + ATTRIBUTE_TUPLE_SIZE); + } + + /* ---------------- + * initialize relation id + * ---------------- + */ + relation->rd_id = relation->rd_att->attrs[0]->attrelid; + + /* ---------------- + * add new reldesc to relcache + * ---------------- + */ + RelationCacheInsert(relation); + + /* + * Determining this requires a scan on pg_class, but to do the scan + * the rdesc for pg_class must already exist. Therefore we must do + * the check (and possible set) after cache insertion. + */ + relation->rd_rel->relhasindex = + CatalogHasIndex(relationName, relation->rd_id); } /* ---------------------------------------------------------------- - * Relation Descriptor Lookup Interface + * Relation Descriptor Lookup Interface * ---------------------------------------------------------------- */ /* -------------------------------- - * RelationIdCacheGetRelation + * RelationIdCacheGetRelation * - * only try to get the reldesc by looking up the cache - * do not go to the disk. this is used by BlockPrepareFile() - * and RelationIdGetRelation below. + * only try to get the reldesc by looking up the cache + * do not go to the disk. this is used by BlockPrepareFile() + * and RelationIdGetRelation below. * -------------------------------- */ Relation RelationIdCacheGetRelation(Oid relationId) { - Relation rd; - - RelationIdCacheLookup(relationId, rd); - - if (RelationIsValid(rd)) { - if (rd->rd_fd == -1) { - rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); - Assert(rd->rd_fd != -1); + Relation rd; + + RelationIdCacheLookup(relationId, rd); + + if (RelationIsValid(rd)) + { + if (rd->rd_fd == -1) + { + rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); + Assert(rd->rd_fd != -1); + } + + RelationIncrementReferenceCount(rd); + RelationSetLockForDescriptorOpen(rd); + } - - RelationIncrementReferenceCount(rd); - RelationSetLockForDescriptorOpen(rd); - - } - - return(rd); + + return (rd); } /* -------------------------------- - * RelationNameCacheGetRelation + * RelationNameCacheGetRelation * -------------------------------- */ -static Relation +static Relation RelationNameCacheGetRelation(char *relationName) { - Relation rd; - NameData name; - - /* make sure that the name key used for hash lookup is properly - null-padded */ - namestrcpy(&name, relationName); - RelationNameCacheLookup(name.data, rd); - - if (RelationIsValid(rd)) { - if (rd->rd_fd == -1) { - rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); - Assert(rd->rd_fd != -1); + Relation rd; + NameData name; + + /* + * make sure that the name key used for hash lookup is properly + * null-padded + */ + namestrcpy(&name, relationName); + RelationNameCacheLookup(name.data, rd); + + if (RelationIsValid(rd)) + { + if (rd->rd_fd == -1) + { + rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); + Assert(rd->rd_fd != -1); + } + + RelationIncrementReferenceCount(rd); + RelationSetLockForDescriptorOpen(rd); + } - - RelationIncrementReferenceCount(rd); - RelationSetLockForDescriptorOpen(rd); - - } - - return(rd); + + return (rd); } /* -------------------------------- - * RelationIdGetRelation + * RelationIdGetRelation * - * return a relation descriptor based on its id. - * return a cached value if possible + * return a relation descriptor based on its id. + * return a cached value if possible * -------------------------------- */ Relation RelationIdGetRelation(Oid relationId) { - Relation rd; - RelationBuildDescInfo buildinfo; - - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_RelationIdGetRelation); - IncrHeapAccessStat(global_RelationIdGetRelation); - - /* ---------------- - * first try and get a reldesc from the cache - * ---------------- - */ - rd = RelationIdCacheGetRelation(relationId); - if (RelationIsValid(rd)) - return rd; - - /* ---------------- - * no reldesc in the cache, so have RelationBuildDesc() - * build one and add it. - * ---------------- - */ - buildinfo.infotype = INFO_RELID; - buildinfo.i.info_id = relationId; - - rd = RelationBuildDesc(buildinfo); - return - rd; + Relation rd; + RelationBuildDescInfo buildinfo; + + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_RelationIdGetRelation); + IncrHeapAccessStat(global_RelationIdGetRelation); + + /* ---------------- + * first try and get a reldesc from the cache + * ---------------- + */ + rd = RelationIdCacheGetRelation(relationId); + if (RelationIsValid(rd)) + return rd; + + /* ---------------- + * no reldesc in the cache, so have RelationBuildDesc() + * build one and add it. + * ---------------- + */ + buildinfo.infotype = INFO_RELID; + buildinfo.i.info_id = relationId; + + rd = RelationBuildDesc(buildinfo); + return + rd; } /* -------------------------------- - * RelationNameGetRelation + * RelationNameGetRelation * - * return a relation descriptor based on its name. - * return a cached value if possible + * return a relation descriptor based on its name. + * return a cached value if possible * -------------------------------- */ Relation RelationNameGetRelation(char *relationName) { - Relation rd; - RelationBuildDescInfo buildinfo; - - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_RelationNameGetRelation); - IncrHeapAccessStat(global_RelationNameGetRelation); - - /* ---------------- - * first try and get a reldesc from the cache - * ---------------- - */ - rd = RelationNameCacheGetRelation(relationName); - if (RelationIsValid(rd)) + Relation rd; + RelationBuildDescInfo buildinfo; + + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_RelationNameGetRelation); + IncrHeapAccessStat(global_RelationNameGetRelation); + + /* ---------------- + * first try and get a reldesc from the cache + * ---------------- + */ + rd = RelationNameCacheGetRelation(relationName); + if (RelationIsValid(rd)) + return rd; + + /* ---------------- + * no reldesc in the cache, so have RelationBuildDesc() + * build one and add it. + * ---------------- + */ + buildinfo.infotype = INFO_RELNAME; + buildinfo.i.info_name = relationName; + + rd = RelationBuildDesc(buildinfo); return rd; - - /* ---------------- - * no reldesc in the cache, so have RelationBuildDesc() - * build one and add it. - * ---------------- - */ - buildinfo.infotype = INFO_RELNAME; - buildinfo.i.info_name = relationName; - - rd = RelationBuildDesc(buildinfo); - return rd; } /* ---------------- - * old "getreldesc" interface. + * old "getreldesc" interface. * ---------------- */ #ifdef NOT_USED Relation getreldesc(char *relationName) { - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_getreldesc); - IncrHeapAccessStat(global_getreldesc); - - return RelationNameGetRelation(relationName); + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_getreldesc); + IncrHeapAccessStat(global_getreldesc); + + return RelationNameGetRelation(relationName); } + #endif /* ---------------------------------------------------------------- - * cache invalidation support routines + * cache invalidation support routines * ---------------------------------------------------------------- */ /* -------------------------------- - * RelationClose - close an open relation + * RelationClose - close an open relation * -------------------------------- */ void RelationClose(Relation relation) { - /* Note: no locking manipulations needed */ - RelationDecrementReferenceCount(relation); + /* Note: no locking manipulations needed */ + RelationDecrementReferenceCount(relation); } /* -------------------------------- * RelationFlushRelation * - * Actually blows away a relation... RelationFree doesn't do - * anything anymore. + * Actually blows away a relation... RelationFree doesn't do + * anything anymore. * -------------------------------- */ static void -RelationFlushRelation(Relation *relationPtr, - bool onlyFlushReferenceCountZero) +RelationFlushRelation(Relation * relationPtr, + bool onlyFlushReferenceCountZero) { - MemoryContext oldcxt; - Relation relation = *relationPtr; - - if (relation->rd_isnailed) { - /* this is a nailed special relation for bootstraping */ - return; - } - - if (!onlyFlushReferenceCountZero || - RelationHasReferenceCountZero(relation)) { - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - RelationCacheDelete(relation); - - FreeTupleDesc (relation->rd_att); - - FreeTriggerDesc (relation); + MemoryContext oldcxt; + Relation relation = *relationPtr; -#if 0 - if (relation->rd_rules) { - int j; - for(j=0; j < relation->rd_rules->numLocks; j++) { - pfree(relation->rd_rules->rules[j]); - } - pfree(relation->rd_rules->rules); - pfree(relation->rd_rules); + if (relation->rd_isnailed) + { + /* this is a nailed special relation for bootstraping */ + return; } + + if (!onlyFlushReferenceCountZero || + RelationHasReferenceCountZero(relation)) + { + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + RelationCacheDelete(relation); + + FreeTupleDesc(relation->rd_att); + + FreeTriggerDesc(relation); + +#if 0 + if (relation->rd_rules) + { + int j; + + for (j = 0; j < relation->rd_rules->numLocks; j++) + { + pfree(relation->rd_rules->rules[j]); + } + pfree(relation->rd_rules->rules); + pfree(relation->rd_rules); + } #endif - - pfree(RelationGetLockInfo(relation)); - pfree(RelationGetRelationTupleForm(relation)); - pfree(relation); - - MemoryContextSwitchTo(oldcxt); - } + + pfree(RelationGetLockInfo(relation)); + pfree(RelationGetRelationTupleForm(relation)); + pfree(relation); + + MemoryContextSwitchTo(oldcxt); + } } /* -------------------------------- - * RelationForgetRelation - - * RelationFlushRelation + if the relation is local then get rid of - * the relation descriptor from the newly created relation list. + * RelationForgetRelation - + * RelationFlushRelation + if the relation is local then get rid of + * the relation descriptor from the newly created relation list. * -------------------------------- */ void -RelationForgetRelation (Oid rid) +RelationForgetRelation(Oid rid) { - Relation relation; - - RelationIdCacheLookup (rid, relation); - Assert ( PointerIsValid (relation) ); - - if ( relation->rd_islocal ) - { - MemoryContext oldcxt; - List *curr; - List *prev = NIL; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - foreach (curr, newlyCreatedRelns) - { - Relation reln = lfirst(curr); - - Assert ( reln != NULL && reln->rd_islocal ); - if ( reln->rd_id == rid ) - break; - prev = curr; - } - if ( curr == NIL ) - elog (FATAL, "Local relation %s not found in list", - (RelationGetRelationName(relation))->data); - if ( prev == NIL ) - newlyCreatedRelns = lnext (newlyCreatedRelns); - else - lnext (prev) = lnext (curr); - pfree (curr); - MemoryContextSwitchTo(oldcxt); - } - - RelationFlushRelation (&relation, false); + Relation relation; + + RelationIdCacheLookup(rid, relation); + Assert(PointerIsValid(relation)); + + if (relation->rd_islocal) + { + MemoryContext oldcxt; + List *curr; + List *prev = NIL; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + foreach(curr, newlyCreatedRelns) + { + Relation reln = lfirst(curr); + + Assert(reln != NULL && reln->rd_islocal); + if (reln->rd_id == rid) + break; + prev = curr; + } + if (curr == NIL) + elog(FATAL, "Local relation %s not found in list", + (RelationGetRelationName(relation))->data); + if (prev == NIL) + newlyCreatedRelns = lnext(newlyCreatedRelns); + else + lnext(prev) = lnext(curr); + pfree(curr); + MemoryContextSwitchTo(oldcxt); + } + + RelationFlushRelation(&relation, false); } /* -------------------------------- - * RelationIdInvalidateRelationCacheByRelationId + * RelationIdInvalidateRelationCacheByRelationId * -------------------------------- */ void RelationIdInvalidateRelationCacheByRelationId(Oid relationId) { - Relation relation; - - RelationIdCacheLookup(relationId, relation); - - /* - * "local" relations are invalidated by RelationPurgeLocalRelation. - * (This is to make LocalBufferSync's life easier: want the descriptor - * to hang around for a while. In fact, won't we want this for - * BufferSync also? But I'll leave it for now since I don't want to - * break anything.) - ay 3/95 - */ - if (PointerIsValid(relation) && !relation->rd_islocal) { + Relation relation; + + RelationIdCacheLookup(relationId, relation); + /* - * The boolean onlyFlushReferenceCountZero in RelationFlushReln() - * should be set to true when we are incrementing the command - * counter and to false when we are starting a new xaction. This - * can be determined by checking the current xaction status. + * "local" relations are invalidated by RelationPurgeLocalRelation. + * (This is to make LocalBufferSync's life easier: want the descriptor + * to hang around for a while. In fact, won't we want this for + * BufferSync also? But I'll leave it for now since I don't want to + * break anything.) - ay 3/95 */ - RelationFlushRelation(&relation, CurrentXactInProgress()); - } + if (PointerIsValid(relation) && !relation->rd_islocal) + { + + /* + * The boolean onlyFlushReferenceCountZero in RelationFlushReln() + * should be set to true when we are incrementing the command + * counter and to false when we are starting a new xaction. This + * can be determined by checking the current xaction status. + */ + RelationFlushRelation(&relation, CurrentXactInProgress()); + } } -#if NOT_USED /* See comments at line 1304 */ +#if NOT_USED /* See comments at line 1304 */ /* -------------------------------- - * RelationIdInvalidateRelationCacheByAccessMethodId + * RelationIdInvalidateRelationCacheByAccessMethodId * - * RelationFlushIndexes is needed for use with HashTableWalk.. + * RelationFlushIndexes is needed for use with HashTableWalk.. * -------------------------------- */ static void -RelationFlushIndexes(Relation *r, - Oid accessMethodId) +RelationFlushIndexes(Relation * r, + Oid accessMethodId) { - Relation relation = *r; - - if (!RelationIsValid(relation)) { - elog(NOTICE, "inval call to RFI"); - return; - } - - if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ - (!OidIsValid(accessMethodId) || - relation->rd_rel->relam == accessMethodId)) + Relation relation = *r; + + if (!RelationIsValid(relation)) + { + elog(NOTICE, "inval call to RFI"); + return; + } + + if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ + (!OidIsValid(accessMethodId) || + relation->rd_rel->relam == accessMethodId)) { - RelationFlushRelation(&relation, false); + RelationFlushRelation(&relation, false); } } + #endif void RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId) { -# if 0 - /* - * 25 aug 1992: mao commented out the ht walk below. it should be - * doing the right thing, in theory, but flushing reldescs for index - * relations apparently doesn't work. we want to cut 4.0.1, and i - * don't want to introduce new bugs. this code never executed before, - * so i'm turning it off for now. after the release is cut, i'll - * fix this up. - */ - - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes, - accessMethodId); -# else - return; -# endif +#if 0 + + /* + * 25 aug 1992: mao commented out the ht walk below. it should be + * doing the right thing, in theory, but flushing reldescs for index + * relations apparently doesn't work. we want to cut 4.0.1, and i + * don't want to introduce new bugs. this code never executed before, + * so i'm turning it off for now. after the release is cut, i'll fix + * this up. + */ + + HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes, + accessMethodId); +#else + return; +#endif } /* * RelationCacheInvalidate * - * Will blow away either all the cached relation descriptors or - * those that have a zero reference count. + * Will blow away either all the cached relation descriptors or + * those that have a zero reference count. * */ void RelationCacheInvalidate(bool onlyFlushReferenceCountZero) { - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, - onlyFlushReferenceCountZero); - - /* - * nailed-in reldescs will still be in the cache... - * 7 hardwired heaps + 3 hardwired indices == 10 total. - */ - if (!onlyFlushReferenceCountZero) { - Assert(RelationNameCache->hctl->nkeys == 10); - Assert(RelationIdCache->hctl->nkeys == 10); - } + HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, + onlyFlushReferenceCountZero); + + /* + * nailed-in reldescs will still be in the cache... 7 hardwired heaps + * + 3 hardwired indices == 10 total. + */ + if (!onlyFlushReferenceCountZero) + { + Assert(RelationNameCache->hctl->nkeys == 10); + Assert(RelationIdCache->hctl->nkeys == 10); + } } - + /* -------------------------------- - * RelationRegisterRelation - - * register the Relation descriptor of a newly created relation - * with the relation descriptor Cache. + * RelationRegisterRelation - + * register the Relation descriptor of a newly created relation + * with the relation descriptor Cache. * -------------------------------- */ void RelationRegisterRelation(Relation relation) { - MemoryContext oldcxt; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - if (oldcxt != (MemoryContext)CacheCxt) - elog(NOIND,"RelationRegisterRelation: WARNING: Context != CacheCxt"); - - RelationCacheInsert(relation); - - RelationInitLockInfo(relation); - - /* - * we've just created the relation. It is invisible to anyone else - * before the transaction is committed. Setting rd_islocal allows us - * to use the local buffer manager for select/insert/etc before the end - * of transaction. (We also need to keep track of relations - * created during a transaction and does the necessary clean up at - * the end of the transaction.) - ay 3/95 - */ - relation->rd_islocal = TRUE; - newlyCreatedRelns = lcons(relation, newlyCreatedRelns); - - MemoryContextSwitchTo(oldcxt); + MemoryContext oldcxt; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + if (oldcxt != (MemoryContext) CacheCxt) + elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt"); + + RelationCacheInsert(relation); + + RelationInitLockInfo(relation); + + /* + * we've just created the relation. It is invisible to anyone else + * before the transaction is committed. Setting rd_islocal allows us + * to use the local buffer manager for select/insert/etc before the + * end of transaction. (We also need to keep track of relations + * created during a transaction and does the necessary clean up at the + * end of the transaction.) - ay 3/95 + */ + relation->rd_islocal = TRUE; + newlyCreatedRelns = lcons(relation, newlyCreatedRelns); + + MemoryContextSwitchTo(oldcxt); } /* * RelationPurgeLocalRelation - - * find all the Relation descriptors marked rd_islocal and reset them. - * This should be called at the end of a transaction (commit/abort) when - * the "local" relations will become visible to others and the multi-user - * buffer pool should be used. + * find all the Relation descriptors marked rd_islocal and reset them. + * This should be called at the end of a transaction (commit/abort) when + * the "local" relations will become visible to others and the multi-user + * buffer pool should be used. */ void RelationPurgeLocalRelation(bool xactCommitted) { - MemoryContext oldcxt; - - if (newlyCreatedRelns==NULL) - return; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - while (newlyCreatedRelns) { - List *l = newlyCreatedRelns; - Relation reln = lfirst(l); - - Assert(reln!=NULL && reln->rd_islocal); - - if (!xactCommitted) { - /* - * remove the file if we abort. This is so that files for - * tables created inside a transaction block get removed. - */ - if(reln->rd_istemp) { - if(!(reln->rd_tmpunlinked)) { - smgrunlink(reln->rd_rel->relsmgr, reln); - reln->rd_tmpunlinked = TRUE; - } - } else { - smgrunlink(reln->rd_rel->relsmgr, reln); - } - } - else if ( !IsBootstrapProcessingMode () && !(reln->rd_istemp) ) - /* - * RelationFlushRelation () below will flush relation information - * from the cache. We must call smgrclose to flush relation - * information from SMGR & FMGR, too. We assume that for temp - * relations smgrunlink is already called by heap_destroyr - * and we skip smgrclose for them. - vadim 05/22/97 - */ - smgrclose(reln->rd_rel->relsmgr, reln); - - reln->rd_islocal = FALSE; + MemoryContext oldcxt; - if (!IsBootstrapProcessingMode()) - RelationFlushRelation(&reln, FALSE); - - newlyCreatedRelns = lnext(newlyCreatedRelns); - pfree(l); - } + if (newlyCreatedRelns == NULL) + return; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); - MemoryContextSwitchTo(oldcxt); + while (newlyCreatedRelns) + { + List *l = newlyCreatedRelns; + Relation reln = lfirst(l); + + Assert(reln != NULL && reln->rd_islocal); + + if (!xactCommitted) + { + + /* + * remove the file if we abort. This is so that files for + * tables created inside a transaction block get removed. + */ + if (reln->rd_istemp) + { + if (!(reln->rd_tmpunlinked)) + { + smgrunlink(reln->rd_rel->relsmgr, reln); + reln->rd_tmpunlinked = TRUE; + } + } + else + { + smgrunlink(reln->rd_rel->relsmgr, reln); + } + } + else if (!IsBootstrapProcessingMode() && !(reln->rd_istemp)) + + /* + * RelationFlushRelation () below will flush relation + * information from the cache. We must call smgrclose to flush + * relation information from SMGR & FMGR, too. We assume that + * for temp relations smgrunlink is already called by + * heap_destroyr and we skip smgrclose for them. - + * vadim 05/22/97 + */ + smgrclose(reln->rd_rel->relsmgr, reln); + + reln->rd_islocal = FALSE; + + if (!IsBootstrapProcessingMode()) + RelationFlushRelation(&reln, FALSE); + + newlyCreatedRelns = lnext(newlyCreatedRelns); + pfree(l); + } + + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * RelationInitialize + * RelationInitialize * - * This initializes the relation descriptor cache. + * This initializes the relation descriptor cache. * -------------------------------- */ -#define INITRELCACHESIZE 400 +#define INITRELCACHESIZE 400 void RelationInitialize(void) { - MemoryContext oldcxt; - HASHCTL ctl; - - /* ---------------- - * switch to cache memory context - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * create global caches - * ---------------- - */ - memset(&ctl,0, (int) sizeof(ctl)); - ctl.keysize = sizeof(NameData); - ctl.datasize = sizeof(Relation); - RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); - - ctl.keysize = sizeof(Oid); - ctl.hash = tag_hash; - RelationIdCache = hash_create(INITRELCACHESIZE, &ctl, - HASH_ELEM | HASH_FUNCTION); - - /* ---------------- - * initialize the cache with pre-made relation descriptors - * for some of the more important system relations. These - * relations should always be in the cache. - * ---------------- - */ - formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); - formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); - formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc); - formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type); - formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable); - formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log); - formrdesc(TimeRelationName, Natts_pg_time, Desc_pg_time); - - /* - * If this isn't initdb time, then we want to initialize some index - * relation descriptors, as well. The descriptors are for pg_attnumind - * (to make building relation descriptors fast) and possibly others, - * as they're added. - */ - - if (!IsBootstrapProcessingMode()) - init_irels(); - - MemoryContextSwitchTo(oldcxt); + MemoryContext oldcxt; + HASHCTL ctl; + + /* ---------------- + * switch to cache memory context + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * create global caches + * ---------------- + */ + memset(&ctl, 0, (int) sizeof(ctl)); + ctl.keysize = sizeof(NameData); + ctl.datasize = sizeof(Relation); + RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); + + ctl.keysize = sizeof(Oid); + ctl.hash = tag_hash; + RelationIdCache = hash_create(INITRELCACHESIZE, &ctl, + HASH_ELEM | HASH_FUNCTION); + + /* ---------------- + * initialize the cache with pre-made relation descriptors + * for some of the more important system relations. These + * relations should always be in the cache. + * ---------------- + */ + formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); + formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); + formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc); + formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type); + formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable); + formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log); + formrdesc(TimeRelationName, Natts_pg_time, Desc_pg_time); + + /* + * If this isn't initdb time, then we want to initialize some index + * relation descriptors, as well. The descriptors are for + * pg_attnumind (to make building relation descriptors fast) and + * possibly others, as they're added. + */ + + if (!IsBootstrapProcessingMode()) + init_irels(); + + MemoryContextSwitchTo(oldcxt); } static void -AttrDefaultFetch (Relation relation) +AttrDefaultFetch(Relation relation) { - AttrDefault *attrdef = relation->rd_att->constr->defval; - int ndef = relation->rd_att->constr->num_defval; - Relation adrel; - Relation irel; - ScanKeyData skey; - HeapTuple tuple; - Form_pg_attrdef adform; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - ItemPointer iptr; - struct varlena *val; - bool isnull; - int found; - int i; - - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - adrel = heap_openr(AttrDefaultRelationName); - irel = index_openr(AttrDefaultIndex); - sd = index_beginscan(irel, false, 1, &skey); - tuple = (HeapTuple)NULL; - - for (found = 0; ; ) - { - indexRes = index_getnext(sd, ForwardScanDirection); - if (!indexRes) - break; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (!HeapTupleIsValid(tuple)) - continue; - found++; - adform = (Form_pg_attrdef) GETSTRUCT(tuple); - for (i = 0; i < ndef; i++) - { - if ( adform->adnum != attrdef[i].adnum ) - continue; - if ( attrdef[i].adsrc != NULL ) - elog (WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_attrdef_adbin, - adrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - attrdef[i].adbin = textout (val); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_attrdef_adsrc, - adrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - attrdef[i].adsrc = textout (val); - break; - } - - if ( i >= ndef ) - elog (WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s", - adform->adnum, - NAMEDATALEN, relation->rd_rel->relname.data); - ReleaseBuffer(buffer); - } - - if ( found < ndef ) - elog (WARN, "AttrDefaultFetch: %d record not found for rel %.*s", - ndef - found, - NAMEDATALEN, relation->rd_rel->relname.data); - - index_endscan (sd); - pfree (sd); - index_close (irel); - heap_close (adrel); - + AttrDefault *attrdef = relation->rd_att->constr->defval; + int ndef = relation->rd_att->constr->num_defval; + Relation adrel; + Relation irel; + ScanKeyData skey; + HeapTuple tuple; + Form_pg_attrdef adform; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + ItemPointer iptr; + struct varlena *val; + bool isnull; + int found; + int i; + + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + adrel = heap_openr(AttrDefaultRelationName); + irel = index_openr(AttrDefaultIndex); + sd = index_beginscan(irel, false, 1, &skey); + tuple = (HeapTuple) NULL; + + for (found = 0;;) + { + indexRes = index_getnext(sd, ForwardScanDirection); + if (!indexRes) + break; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (!HeapTupleIsValid(tuple)) + continue; + found++; + adform = (Form_pg_attrdef) GETSTRUCT(tuple); + for (i = 0; i < ndef; i++) + { + if (adform->adnum != attrdef[i].adnum) + continue; + if (attrdef[i].adsrc != NULL) + elog(WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_attrdef_adbin, + adrel->rd_att, &isnull); + if (isnull) + elog(WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + attrdef[i].adbin = textout(val); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_attrdef_adsrc, + adrel->rd_att, &isnull); + if (isnull) + elog(WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + attrdef[i].adsrc = textout(val); + break; + } + + if (i >= ndef) + elog(WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s", + adform->adnum, + NAMEDATALEN, relation->rd_rel->relname.data); + ReleaseBuffer(buffer); + } + + if (found < ndef) + elog(WARN, "AttrDefaultFetch: %d record not found for rel %.*s", + ndef - found, + NAMEDATALEN, relation->rd_rel->relname.data); + + index_endscan(sd); + pfree(sd); + index_close(irel); + heap_close(adrel); + } static void -RelCheckFetch (Relation relation) +RelCheckFetch(Relation relation) { - ConstrCheck *check = relation->rd_att->constr->check; - int ncheck = relation->rd_att->constr->num_check; - Relation rcrel; - Relation irel; - ScanKeyData skey; - HeapTuple tuple; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - ItemPointer iptr; - Name rcname; - struct varlena *val; - bool isnull; - int found; - - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - rcrel = heap_openr(RelCheckRelationName); - irel = index_openr(RelCheckIndex); - sd = index_beginscan(irel, false, 1, &skey); - tuple = (HeapTuple)NULL; - - for (found = 0; ; ) - { - indexRes = index_getnext(sd, ForwardScanDirection); - if (!indexRes) - break; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(rcrel, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (!HeapTupleIsValid(tuple)) - continue; - if ( found == ncheck ) - elog (WARN, "RelCheckFetch: unexpected record found for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - - rcname = (Name) fastgetattr (tuple, - Anum_pg_relcheck_rcname, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcname IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccname = nameout (rcname); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_relcheck_rcbin, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccbin = textout (val); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_relcheck_rcsrc, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccsrc = textout (val); - found++; - - ReleaseBuffer(buffer); - } - - if ( found < ncheck ) - elog (WARN, "RelCheckFetch: %d record not found for rel %.*s", - ncheck - found, - NAMEDATALEN, relation->rd_rel->relname.data); - - index_endscan (sd); - pfree (sd); - index_close (irel); - heap_close (rcrel); - + ConstrCheck *check = relation->rd_att->constr->check; + int ncheck = relation->rd_att->constr->num_check; + Relation rcrel; + Relation irel; + ScanKeyData skey; + HeapTuple tuple; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + ItemPointer iptr; + Name rcname; + struct varlena *val; + bool isnull; + int found; + + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + rcrel = heap_openr(RelCheckRelationName); + irel = index_openr(RelCheckIndex); + sd = index_beginscan(irel, false, 1, &skey); + tuple = (HeapTuple) NULL; + + for (found = 0;;) + { + indexRes = index_getnext(sd, ForwardScanDirection); + if (!indexRes) + break; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(rcrel, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (!HeapTupleIsValid(tuple)) + continue; + if (found == ncheck) + elog(WARN, "RelCheckFetch: unexpected record found for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + + rcname = (Name) fastgetattr(tuple, + Anum_pg_relcheck_rcname, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcname IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccname = nameout(rcname); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_relcheck_rcbin, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccbin = textout(val); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_relcheck_rcsrc, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccsrc = textout(val); + found++; + + ReleaseBuffer(buffer); + } + + if (found < ncheck) + elog(WARN, "RelCheckFetch: %d record not found for rel %.*s", + ncheck - found, + NAMEDATALEN, relation->rd_rel->relname.data); + + index_endscan(sd); + pfree(sd); + index_close(irel); + heap_close(rcrel); + } /* - * init_irels(), write_irels() -- handle special-case initialization of - * index relation descriptors. + * init_irels(), write_irels() -- handle special-case initialization of + * index relation descriptors. * - * In late 1992, we started regularly having databases with more than - * a thousand classes in them. With this number of classes, it became - * critical to do indexed lookups on the system catalogs. + * In late 1992, we started regularly having databases with more than + * a thousand classes in them. With this number of classes, it became + * critical to do indexed lookups on the system catalogs. * - * Bootstrapping these lookups is very hard. We want to be able to - * use an index on pg_attribute, for example, but in order to do so, - * we must have read pg_attribute for the attributes in the index, - * which implies that we need to use the index. + * Bootstrapping these lookups is very hard. We want to be able to + * use an index on pg_attribute, for example, but in order to do so, + * we must have read pg_attribute for the attributes in the index, + * which implies that we need to use the index. * - * In order to get around the problem, we do the following: + * In order to get around the problem, we do the following: * - * + When the database system is initialized (at initdb time), we - * don't use indices on pg_attribute. We do sequential scans. + * + When the database system is initialized (at initdb time), we + * don't use indices on pg_attribute. We do sequential scans. * - * + When the backend is started up in normal mode, we load an image - * of the appropriate relation descriptors, in internal format, - * from an initialization file in the data/base/... directory. + * + When the backend is started up in normal mode, we load an image + * of the appropriate relation descriptors, in internal format, + * from an initialization file in the data/base/... directory. * - * + If the initialization file isn't there, then we create the - * relation descriptor using sequential scans and write it to - * the initialization file for use by subsequent backends. + * + If the initialization file isn't there, then we create the + * relation descriptor using sequential scans and write it to + * the initialization file for use by subsequent backends. * - * This is complicated and interferes with system changes, but - * performance is so bad that we're willing to pay the tax. + * This is complicated and interferes with system changes, but + * performance is so bad that we're willing to pay the tax. */ /* pg_attnumind, pg_classnameind, pg_classoidind */ @@ -1833,268 +1902,288 @@ RelCheckFetch (Relation relation) static void init_irels(void) { - Size len; - int nread; - File fd; - Relation irel[Num_indices_bootstrap]; - Relation ird; - Form_pg_am am; - Form_pg_class relform; - IndexStrategy strat; - RegProcedure *support; - int i; - int relno; - - if ((fd = FileNameOpenFile(INIT_FILENAME, O_RDONLY, 0600)) < 0) { - write_irels(); - return; - } - - FileSeek(fd, 0L, SEEK_SET); - - for (relno = 0; relno < Num_indices_bootstrap; relno++) { - /* first read the relation descriptor length*/ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - ird = irel[relno] = (Relation) palloc(len); - memset(ird, 0, len); - - /* then, read the Relation structure */ - if ((nread = FileRead(fd, (char*)ird, len)) != len) { - write_irels(); - return; - } - - /* the file descriptor is not yet opened */ - ird->rd_fd = -1; - - /* lock info is not initialized */ - ird->lockInfo = (char *) NULL; - - /* next, read the access method tuple form */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - am = (Form_pg_am) palloc(len); - if ((nread = FileRead(fd, (char*)am, len)) != len) { - write_irels(); - return; - } - - ird->rd_am = am; - - /* next read the relation tuple form */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - relform = (Form_pg_class) palloc(len); - if ((nread = FileRead(fd, (char*)relform, len)) != len) { - write_irels(); - return; - } - - ird->rd_rel = relform; - - /* initialize attribute tuple forms */ - ird->rd_att = CreateTemplateTupleDesc(relform->relnatts); - - /* next read all the attribute tuple form data entries */ - len = ATTRIBUTE_TUPLE_SIZE; - for (i = 0; i < relform->relnatts; i++) { - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - ird->rd_att->attrs[i] = (AttributeTupleForm) palloc(len); - - if ((nread = FileRead(fd, (char*)ird->rd_att->attrs[i], len)) != len) { + Size len; + int nread; + File fd; + Relation irel[Num_indices_bootstrap]; + Relation ird; + Form_pg_am am; + Form_pg_class relform; + IndexStrategy strat; + RegProcedure *support; + int i; + int relno; + + if ((fd = FileNameOpenFile(INIT_FILENAME, O_RDONLY, 0600)) < 0) + { write_irels(); return; - } - } - - /* next, read the index strategy map */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - strat = (IndexStrategy) palloc(len); - if ((nread = FileRead(fd, (char*)strat, len)) != len) { - write_irels(); - return; } - - /* oh, for god's sake... */ + + FileSeek(fd, 0L, SEEK_SET); + + for (relno = 0; relno < Num_indices_bootstrap; relno++) + { + /* first read the relation descriptor length */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + ird = irel[relno] = (Relation) palloc(len); + memset(ird, 0, len); + + /* then, read the Relation structure */ + if ((nread = FileRead(fd, (char *) ird, len)) != len) + { + write_irels(); + return; + } + + /* the file descriptor is not yet opened */ + ird->rd_fd = -1; + + /* lock info is not initialized */ + ird->lockInfo = (char *) NULL; + + /* next, read the access method tuple form */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + am = (Form_pg_am) palloc(len); + if ((nread = FileRead(fd, (char *) am, len)) != len) + { + write_irels(); + return; + } + + ird->rd_am = am; + + /* next read the relation tuple form */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + relform = (Form_pg_class) palloc(len); + if ((nread = FileRead(fd, (char *) relform, len)) != len) + { + write_irels(); + return; + } + + ird->rd_rel = relform; + + /* initialize attribute tuple forms */ + ird->rd_att = CreateTemplateTupleDesc(relform->relnatts); + + /* next read all the attribute tuple form data entries */ + len = ATTRIBUTE_TUPLE_SIZE; + for (i = 0; i < relform->relnatts; i++) + { + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + ird->rd_att->attrs[i] = (AttributeTupleForm) palloc(len); + + if ((nread = FileRead(fd, (char *) ird->rd_att->attrs[i], len)) != len) + { + write_irels(); + return; + } + } + + /* next, read the index strategy map */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + strat = (IndexStrategy) palloc(len); + if ((nread = FileRead(fd, (char *) strat, len)) != len) + { + write_irels(); + return; + } + + /* oh, for god's sake... */ #define SMD(i) strat[0].strategyMapData[i].entry[0] - - /* have to reinit the function pointers in the strategy maps */ - for (i = 0; i < am->amstrategies; i++) - fmgr_info(SMD(i).sk_procedure, - &(SMD(i).sk_func), &(SMD(i).sk_nargs)); - - - /* use a real field called rd_istrat instead of the - bogosity of hanging invisible fields off the end of a structure - - jolly */ - ird->rd_istrat = strat; - - /* finally, read the vector of support procedures */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - support = (RegProcedure *) palloc(len); - if ((nread = FileRead(fd, (char*)support, len)) != len) { - write_irels(); - return; - } - - /* - p += sizeof(IndexStrategy); - *((RegProcedure **) p) = support; - */ - ird->rd_support = support; - - RelationCacheInsert(ird); - } + /* have to reinit the function pointers in the strategy maps */ + for (i = 0; i < am->amstrategies; i++) + fmgr_info(SMD(i).sk_procedure, + &(SMD(i).sk_func), &(SMD(i).sk_nargs)); + + + /* + * use a real field called rd_istrat instead of the bogosity of + * hanging invisible fields off the end of a structure - jolly + */ + ird->rd_istrat = strat; + + /* finally, read the vector of support procedures */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + support = (RegProcedure *) palloc(len); + if ((nread = FileRead(fd, (char *) support, len)) != len) + { + write_irels(); + return; + } + + /* + * p += sizeof(IndexStrategy); ((RegProcedure **) p) = support; + */ + + ird->rd_support = support; + + RelationCacheInsert(ird); + } } static void write_irels(void) { - int len; - int nwritten; - File fd; - Relation irel[Num_indices_bootstrap]; - Relation ird; - Form_pg_am am; - Form_pg_class relform; - IndexStrategy strat; - RegProcedure *support; - ProcessingMode oldmode; - int i; - int relno; - RelationBuildDescInfo bi; - - fd = FileNameOpenFile(INIT_FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (fd < 0) - elog(FATAL, "cannot create init file %s", INIT_FILENAME); - - FileSeek(fd, 0L, SEEK_SET); - - /* - * Build a relation descriptor for pg_attnumind without resort to the - * descriptor cache. In order to do this, we set ProcessingMode - * to Bootstrap. The effect of this is to disable indexed relation - * searches -- a necessary step, since we're trying to instantiate - * the index relation descriptors here. - */ - - oldmode = GetProcessingMode(); - SetProcessingMode(BootstrapProcessing); - - bi.infotype = INFO_RELNAME; - bi.i.info_name = AttributeNumIndex; - irel[0] = RelationBuildDesc(bi); - irel[0]->rd_isnailed = true; - - bi.i.info_name = ClassNameIndex; - irel[1] = RelationBuildDesc(bi); - irel[1]->rd_isnailed = true; - - bi.i.info_name = ClassOidIndex; - irel[2] = RelationBuildDesc(bi); - irel[2]->rd_isnailed = true; - - SetProcessingMode(oldmode); - - /* nail the descriptor in the cache */ - for (relno = 0; relno < Num_indices_bootstrap; relno++) { - ird = irel[relno]; - - /* save the volatile fields in the relation descriptor */ - am = ird->rd_am; - ird->rd_am = (Form_pg_am) NULL; - relform = ird->rd_rel; - ird->rd_rel = (Form_pg_class) NULL; - strat = ird->rd_istrat; - support = ird->rd_support; - - /* first write the relation descriptor , excluding strategy and support */ - len = sizeof(RelationData); - - /* first, write the relation descriptor length */ - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- descriptor length"); - - /* next, write out the Relation structure */ - if ((nwritten = FileWrite(fd, (char*) ird, len)) != len) - elog(FATAL, "cannot write init file -- reldesc"); - - /* next, write the access method tuple form */ - len = sizeof(FormData_pg_am); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- am tuple form length"); - - if ((nwritten = FileWrite(fd, (char*) am, len)) != len) - elog(FATAL, "cannot write init file -- am tuple form"); - - /* next write the relation tuple form */ - len = sizeof(FormData_pg_class); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- relation tuple form length"); - - if ((nwritten = FileWrite(fd, (char*) relform, len)) != len) - elog(FATAL, "cannot write init file -- relation tuple form"); - - /* next, do all the attribute tuple form data entries */ - len = ATTRIBUTE_TUPLE_SIZE; - for (i = 0; i < relform->relnatts; i++) { - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- length of attdesc %d", i); - if ((nwritten = FileWrite(fd, (char*) ird->rd_att->attrs[i], len)) - != len) - elog(FATAL, "cannot write init file -- attdesc %d", i); + int len; + int nwritten; + File fd; + Relation irel[Num_indices_bootstrap]; + Relation ird; + Form_pg_am am; + Form_pg_class relform; + IndexStrategy strat; + RegProcedure *support; + ProcessingMode oldmode; + int i; + int relno; + RelationBuildDescInfo bi; + + fd = FileNameOpenFile(INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + elog(FATAL, "cannot create init file %s", INIT_FILENAME); + + FileSeek(fd, 0L, SEEK_SET); + + /* + * Build a relation descriptor for pg_attnumind without resort to the + * descriptor cache. In order to do this, we set ProcessingMode to + * Bootstrap. The effect of this is to disable indexed relation + * searches -- a necessary step, since we're trying to instantiate the + * index relation descriptors here. + */ + + oldmode = GetProcessingMode(); + SetProcessingMode(BootstrapProcessing); + + bi.infotype = INFO_RELNAME; + bi.i.info_name = AttributeNumIndex; + irel[0] = RelationBuildDesc(bi); + irel[0]->rd_isnailed = true; + + bi.i.info_name = ClassNameIndex; + irel[1] = RelationBuildDesc(bi); + irel[1]->rd_isnailed = true; + + bi.i.info_name = ClassOidIndex; + irel[2] = RelationBuildDesc(bi); + irel[2]->rd_isnailed = true; + + SetProcessingMode(oldmode); + + /* nail the descriptor in the cache */ + for (relno = 0; relno < Num_indices_bootstrap; relno++) + { + ird = irel[relno]; + + /* save the volatile fields in the relation descriptor */ + am = ird->rd_am; + ird->rd_am = (Form_pg_am) NULL; + relform = ird->rd_rel; + ird->rd_rel = (Form_pg_class) NULL; + strat = ird->rd_istrat; + support = ird->rd_support; + + /* + * first write the relation descriptor , excluding strategy and + * support + */ + len = sizeof(RelationData); + + /* first, write the relation descriptor length */ + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- descriptor length"); + + /* next, write out the Relation structure */ + if ((nwritten = FileWrite(fd, (char *) ird, len)) != len) + elog(FATAL, "cannot write init file -- reldesc"); + + /* next, write the access method tuple form */ + len = sizeof(FormData_pg_am); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- am tuple form length"); + + if ((nwritten = FileWrite(fd, (char *) am, len)) != len) + elog(FATAL, "cannot write init file -- am tuple form"); + + /* next write the relation tuple form */ + len = sizeof(FormData_pg_class); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- relation tuple form length"); + + if ((nwritten = FileWrite(fd, (char *) relform, len)) != len) + elog(FATAL, "cannot write init file -- relation tuple form"); + + /* next, do all the attribute tuple form data entries */ + len = ATTRIBUTE_TUPLE_SIZE; + for (i = 0; i < relform->relnatts; i++) + { + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- length of attdesc %d", i); + if ((nwritten = FileWrite(fd, (char *) ird->rd_att->attrs[i], len)) + != len) + elog(FATAL, "cannot write init file -- attdesc %d", i); + } + + /* next, write the index strategy map */ + len = AttributeNumberGetIndexStrategySize(relform->relnatts, + am->amstrategies); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- strategy map length"); + + if ((nwritten = FileWrite(fd, (char *) strat, len)) != len) + elog(FATAL, "cannot write init file -- strategy map"); + + /* finally, write the vector of support procedures */ + len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- support vector length"); + + if ((nwritten = FileWrite(fd, (char *) support, len)) != len) + elog(FATAL, "cannot write init file -- support vector"); + + /* restore volatile fields */ + ird->rd_am = am; + ird->rd_rel = relform; } - - /* next, write the index strategy map */ - len = AttributeNumberGetIndexStrategySize(relform->relnatts, - am->amstrategies); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- strategy map length"); - - if ((nwritten = FileWrite(fd, (char*) strat, len)) != len) - elog(FATAL, "cannot write init file -- strategy map"); - - /* finally, write the vector of support procedures */ - len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- support vector length"); - - if ((nwritten = FileWrite(fd, (char*) support, len)) != len) - elog(FATAL, "cannot write init file -- support vector"); - - /* restore volatile fields */ - ird->rd_am = am; - ird->rd_rel = relform; - } - - FileClose(fd); + + FileClose(fd); } diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 460e8d40af0..5f6c22b95fc 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -1,37 +1,37 @@ /*------------------------------------------------------------------------- * * syscache.c-- - * System cache management routines + * System cache management routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.4 1996/11/06 10:31:29 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.5 1997/09/07 04:53:10 momjian Exp $ * * NOTES - * These routines allow the parser/planner/executor to perform - * rapid lookups on the contents of the system catalogs. + * These routines allow the parser/planner/executor to perform + * rapid lookups on the contents of the system catalogs. * - * see catalog/syscache.h for a list of the cache id's + * see catalog/syscache.h for a list of the cache id's * *------------------------------------------------------------------------- */ #include "postgres.h" - + #include "access/heapam.h" #include "access/htup.h" #include "catalog/catname.h" #include "utils/catcache.h" #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif - + /* ---------------- - * hardwired attribute information comes from system catalog files. + * hardwired attribute information comes from system catalog files. * ---------------- */ #include "catalog/pg_am.h" @@ -51,592 +51,625 @@ #include "catalog/pg_user.h" #include "storage/large_object.h" #include "catalog/pg_listener.h" - -extern bool AMI_OVERRIDE; /* XXX style */ - + +extern bool AMI_OVERRIDE; /* XXX style */ + #include "utils/syscache.h" #include "catalog/indexing.h" - -typedef HeapTuple (*ScanFunc)(); + +typedef HeapTuple(*ScanFunc) (); /* ---------------- - * Warning: cacheinfo[] below is changed, then be sure and - * update the magic constants in syscache.h! + * Warning: cacheinfo[] below is changed, then be sure and + * update the magic constants in syscache.h! * ---------------- */ static struct cachedesc cacheinfo[] = { - { AccessMethodOperatorRelationName, /* AMOPOPID */ - 3, - { Anum_pg_amop_amopclaid, - Anum_pg_amop_amopopr, - Anum_pg_amop_amopid, - 0 }, - sizeof(FormData_pg_amop), - NULL, - (ScanFunc) NULL }, - { AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ - 3, - { Anum_pg_amop_amopid, - Anum_pg_amop_amopclaid, - Anum_pg_amop_amopstrategy, - 0 }, - sizeof(FormData_pg_amop), - NULL, - (ScanFunc) NULL }, - { AttributeRelationName, /* ATTNAME */ - 2, - { Anum_pg_attribute_attrelid, - Anum_pg_attribute_attname, - 0, - 0 }, - ATTRIBUTE_TUPLE_SIZE, - AttributeNameIndex, - (ScanFunc) AttributeNameIndexScan }, - { AttributeRelationName, /* ATTNUM */ - 2, - { Anum_pg_attribute_attrelid, - Anum_pg_attribute_attnum, - 0, - 0 }, - ATTRIBUTE_TUPLE_SIZE, - AttributeNumIndex, - (ScanFunc) AttributeNumIndexScan }, - { IndexRelationName, /* INDEXRELID */ - 1, - { Anum_pg_index_indexrelid, - 0, - 0, - 0 }, - offsetof(FormData_pg_index, indpred), - NULL, - NULL }, - { LanguageRelationName, /* LANNAME */ - 1, - { Anum_pg_language_lanname, - 0, - 0, - 0 }, - offsetof(FormData_pg_language, lancompiler), - NULL, - NULL }, - { OperatorRelationName, /* OPRNAME */ - 4, - { Anum_pg_operator_oprname, - Anum_pg_operator_oprleft, - Anum_pg_operator_oprright, - Anum_pg_operator_oprkind }, - sizeof(FormData_pg_operator), - NULL, - NULL }, - { OperatorRelationName, /* OPROID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - sizeof(FormData_pg_operator), - NULL, - (ScanFunc) NULL }, - { ProcedureRelationName, /* PRONAME */ - 3, - { Anum_pg_proc_proname, - Anum_pg_proc_pronargs, - Anum_pg_proc_proargtypes, - 0 }, - offsetof(FormData_pg_proc, prosrc), - ProcedureNameIndex, - (ScanFunc) ProcedureNameIndexScan }, - { ProcedureRelationName, /* PROOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - offsetof(FormData_pg_proc, prosrc), - ProcedureOidIndex, - (ScanFunc) ProcedureOidIndexScan }, - { RelationRelationName, /* RELNAME */ - 1, - { Anum_pg_class_relname, - 0, - 0, - 0 }, - CLASS_TUPLE_SIZE, - ClassNameIndex, - (ScanFunc) ClassNameIndexScan }, - { RelationRelationName, /* RELOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - CLASS_TUPLE_SIZE, - ClassOidIndex, - (ScanFunc) ClassOidIndexScan }, - { TypeRelationName, /* TYPNAME */ - 1, - { Anum_pg_type_typname, - 0, - 0, - 0 }, - offsetof(TypeTupleFormData,typalign)+sizeof(char), - TypeNameIndex, - TypeNameIndexScan }, - { TypeRelationName, /* TYPOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, + {AccessMethodOperatorRelationName, /* AMOPOPID */ + 3, + {Anum_pg_amop_amopclaid, + Anum_pg_amop_amopopr, + Anum_pg_amop_amopid, + 0}, + sizeof(FormData_pg_amop), + NULL, + (ScanFunc) NULL}, + {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ + 3, + {Anum_pg_amop_amopid, + Anum_pg_amop_amopclaid, + Anum_pg_amop_amopstrategy, + 0}, + sizeof(FormData_pg_amop), + NULL, + (ScanFunc) NULL}, + {AttributeRelationName, /* ATTNAME */ + 2, + {Anum_pg_attribute_attrelid, + Anum_pg_attribute_attname, + 0, + 0}, + ATTRIBUTE_TUPLE_SIZE, + AttributeNameIndex, + (ScanFunc) AttributeNameIndexScan}, + {AttributeRelationName, /* ATTNUM */ + 2, + {Anum_pg_attribute_attrelid, + Anum_pg_attribute_attnum, + 0, + 0}, + ATTRIBUTE_TUPLE_SIZE, + AttributeNumIndex, + (ScanFunc) AttributeNumIndexScan}, + {IndexRelationName, /* INDEXRELID */ + 1, + {Anum_pg_index_indexrelid, + 0, + 0, + 0}, + offsetof(FormData_pg_index, indpred), + NULL, + NULL}, + {LanguageRelationName, /* LANNAME */ + 1, + {Anum_pg_language_lanname, + 0, + 0, + 0}, + offsetof(FormData_pg_language, lancompiler), + NULL, + NULL}, + {OperatorRelationName, /* OPRNAME */ + 4, + {Anum_pg_operator_oprname, + Anum_pg_operator_oprleft, + Anum_pg_operator_oprright, + Anum_pg_operator_oprkind}, + sizeof(FormData_pg_operator), + NULL, + NULL}, + {OperatorRelationName, /* OPROID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + sizeof(FormData_pg_operator), + NULL, + (ScanFunc) NULL}, + {ProcedureRelationName, /* PRONAME */ + 3, + {Anum_pg_proc_proname, + Anum_pg_proc_pronargs, + Anum_pg_proc_proargtypes, + 0}, + offsetof(FormData_pg_proc, prosrc), + ProcedureNameIndex, + (ScanFunc) ProcedureNameIndexScan}, + {ProcedureRelationName, /* PROOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + offsetof(FormData_pg_proc, prosrc), + ProcedureOidIndex, + (ScanFunc) ProcedureOidIndexScan}, + {RelationRelationName, /* RELNAME */ + 1, + {Anum_pg_class_relname, + 0, + 0, + 0}, + CLASS_TUPLE_SIZE, + ClassNameIndex, + (ScanFunc) ClassNameIndexScan}, + {RelationRelationName, /* RELOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + CLASS_TUPLE_SIZE, + ClassOidIndex, + (ScanFunc) ClassOidIndexScan}, + {TypeRelationName, /* TYPNAME */ + 1, + {Anum_pg_type_typname, + 0, + 0, + 0}, + offsetof(TypeTupleFormData, typalign) + sizeof(char), + TypeNameIndex, + TypeNameIndexScan}, + {TypeRelationName, /* TYPOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + offsetof(TypeTupleFormData, typalign) +sizeof(char), + TypeOidIndex, + TypeOidIndexScan}, + {AccessMethodRelationName, /* AMNAME */ + 1, + {Anum_pg_am_amname, + 0, + 0, + 0}, + sizeof(FormData_pg_am), + NULL, + NULL}, + {OperatorClassRelationName, /* CLANAME */ + 1, + {Anum_pg_opclass_opcname, + 0, + 0, + 0}, + sizeof(FormData_pg_opclass), + NULL, + NULL}, + {IndexRelationName, /* INDRELIDKEY */ + 2, + {Anum_pg_index_indrelid, + Anum_pg_index_indkey, + 0, + 0}, + offsetof(FormData_pg_index, indpred), + NULL, + (ScanFunc) NULL}, + {InheritsRelationName, /* INHRELID */ + 2, + {Anum_pg_inherits_inhrel, + Anum_pg_inherits_inhseqno, + 0, 0}, - offsetof(TypeTupleFormData,typalign)+sizeof(char), - TypeOidIndex, - TypeOidIndexScan }, - { AccessMethodRelationName, /* AMNAME */ - 1, - { Anum_pg_am_amname, - 0, - 0, + sizeof(FormData_pg_inherits), + NULL, + (ScanFunc) NULL}, + {RewriteRelationName, /* RULOID */ + 1, + {ObjectIdAttributeNumber, + 0, + 0, + 0}, + offsetof(FormData_pg_rewrite, ev_qual), + NULL, + (ScanFunc) NULL}, + {AggregateRelationName, /* AGGNAME */ + 2, + {Anum_pg_aggregate_aggname, + Anum_pg_aggregate_aggbasetype, + 0, 0}, - sizeof(FormData_pg_am), - NULL, - NULL }, - { OperatorClassRelationName, /* CLANAME */ - 1, - { Anum_pg_opclass_opcname, - 0, - 0, + offsetof(FormData_pg_aggregate, agginitval1), + NULL, + (ScanFunc) NULL}, + {ListenerRelationName, /* LISTENREL */ + 2, + {Anum_pg_listener_relname, + Anum_pg_listener_pid, + 0, 0}, - sizeof(FormData_pg_opclass), - NULL, - NULL }, - { IndexRelationName, /* INDRELIDKEY */ - 2, - { Anum_pg_index_indrelid, - Anum_pg_index_indkey, - 0, + sizeof(FormData_pg_listener), + NULL, + (ScanFunc) NULL}, + {UserRelationName, /* USENAME */ + 1, + {Anum_pg_user_usename, + 0, + 0, 0}, - offsetof(FormData_pg_index, indpred), - NULL, - (ScanFunc) NULL }, - { InheritsRelationName, /* INHRELID */ - 2, - { Anum_pg_inherits_inhrel, - Anum_pg_inherits_inhseqno, - 0, + sizeof(FormData_pg_user), + NULL, + (ScanFunc) NULL}, + {UserRelationName, /* USESYSID */ + 1, + {Anum_pg_user_usesysid, + 0, + 0, + 0}, + sizeof(FormData_pg_user), + NULL, + (ScanFunc) NULL}, + {GroupRelationName, /* GRONAME */ + 1, + {Anum_pg_group_groname, + 0, + 0, + 0}, + offsetof(FormData_pg_group, grolist[0]), + NULL, + (ScanFunc) NULL}, + {GroupRelationName, /* GROSYSID */ + 1, + {Anum_pg_group_grosysid, + 0, + 0, 0}, - sizeof(FormData_pg_inherits), - NULL, - (ScanFunc) NULL }, - { RewriteRelationName, /* RULOID */ - 1, - { ObjectIdAttributeNumber, - 0, - 0, - 0 }, - offsetof(FormData_pg_rewrite, ev_qual), - NULL, - (ScanFunc) NULL }, - { AggregateRelationName, /*AGGNAME*/ - 2, - { Anum_pg_aggregate_aggname, - Anum_pg_aggregate_aggbasetype, - 0, - 0 }, - offsetof(FormData_pg_aggregate, agginitval1), - NULL, - (ScanFunc) NULL }, - { ListenerRelationName, /* LISTENREL */ - 2, - { Anum_pg_listener_relname, - Anum_pg_listener_pid, - 0, - 0 }, - sizeof(FormData_pg_listener), - NULL, - (ScanFunc) NULL }, - { UserRelationName, /* USENAME */ - 1, - { Anum_pg_user_usename, - 0, - 0, - 0 }, - sizeof(FormData_pg_user), - NULL, - (ScanFunc) NULL }, - { UserRelationName, /* USESYSID */ - 1, - { Anum_pg_user_usesysid, - 0, - 0, - 0 }, - sizeof(FormData_pg_user), - NULL, - (ScanFunc) NULL }, - { GroupRelationName, /* GRONAME */ - 1, - { Anum_pg_group_groname, - 0, - 0, - 0 }, - offsetof(FormData_pg_group, grolist[0]), - NULL, - (ScanFunc) NULL }, - { GroupRelationName, /* GROSYSID */ - 1, - { Anum_pg_group_grosysid, - 0, - 0, - 0 }, - offsetof(FormData_pg_group, grolist[0]), - NULL, - (ScanFunc) NULL }, - { RewriteRelationName, /* REWRITENAME */ - 1, - { Anum_pg_rewrite_rulename, - 0, - 0, - 0 }, - offsetof(FormData_pg_rewrite, ev_qual), - NULL, - (ScanFunc) NULL }, - { ProcedureRelationName, /* PROSRC */ - 1, - { Anum_pg_proc_prosrc, - 0, - 0, - 0 }, - offsetof(FormData_pg_proc, prosrc), - ProcedureSrcIndex, - (ScanFunc) ProcedureSrcIndexScan }, - { OperatorClassRelationName, /* CLADEFTYPE */ - 1, - { Anum_pg_opclass_opcdeftype, - 0, - 0, - 0 }, - sizeof(FormData_pg_opclass), - NULL, - (ScanFunc) NULL } + offsetof(FormData_pg_group, grolist[0]), + NULL, + (ScanFunc) NULL}, + {RewriteRelationName, /* REWRITENAME */ + 1, + {Anum_pg_rewrite_rulename, + 0, + 0, + 0}, + offsetof(FormData_pg_rewrite, ev_qual), + NULL, + (ScanFunc) NULL}, + {ProcedureRelationName, /* PROSRC */ + 1, + {Anum_pg_proc_prosrc, + 0, + 0, + 0}, + offsetof(FormData_pg_proc, prosrc), + ProcedureSrcIndex, + (ScanFunc) ProcedureSrcIndexScan}, + {OperatorClassRelationName, /* CLADEFTYPE */ + 1, + {Anum_pg_opclass_opcdeftype, + 0, + 0, + 0}, + sizeof(FormData_pg_opclass), + NULL, + (ScanFunc) NULL} }; - -static struct catcache *SysCache[lengthof(cacheinfo)]; -static int32 SysCacheSize = lengthof(cacheinfo); - - + +static struct catcache *SysCache[ + lengthof(cacheinfo)]; +static int32 SysCacheSize = lengthof(cacheinfo); + + /* * zerocaches-- * - * Make sure the SysCache structure is zero'd. + * Make sure the SysCache structure is zero'd. */ void zerocaches() { - memset((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *)); + memset((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *)); } /* * Note: - * This function was written because the initialized catalog caches - * are used to determine which caches may contain tuples which need - * to be invalidated in other backends. + * This function was written because the initialized catalog caches + * are used to determine which caches may contain tuples which need + * to be invalidated in other backends. */ void InitCatalogCache() { - int cacheId; /* XXX type */ - - if (!AMI_OVERRIDE) { - for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) { - - Assert(!PointerIsValid((Pointer)SysCache[cacheId])); - - SysCache[cacheId] = - InitSysCache(cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheId, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key, - cacheinfo[cacheId].iScanFunc); - if (!PointerIsValid((char *)SysCache[cacheId])) { - elog(WARN, - "InitCatalogCache: Can't init cache %.16s(%d)", - cacheinfo[cacheId].name, - cacheId); - } - + int cacheId; /* XXX type */ + + if (!AMI_OVERRIDE) + { + for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) + { + + Assert(!PointerIsValid((Pointer) SysCache[cacheId])); + + SysCache[cacheId] = + InitSysCache(cacheinfo[cacheId].name, + cacheinfo[cacheId].indname, + cacheId, + cacheinfo[cacheId].nkeys, + cacheinfo[cacheId].key, + cacheinfo[cacheId].iScanFunc); + if (!PointerIsValid((char *) SysCache[cacheId])) + { + elog(WARN, + "InitCatalogCache: Can't init cache %.16s(%d)", + cacheinfo[cacheId].name, + cacheId); + } + + } } - } } /* * SearchSysCacheTuple-- * - * A layer on top of SearchSysCache that does the initialization and - * key-setting for you. + * A layer on top of SearchSysCache that does the initialization and + * key-setting for you. * * Returns the tuple if one is found, NULL if not. * * XXX The tuple that is returned is NOT supposed to be pfree'd! */ HeapTuple -SearchSysCacheTuple(int cacheId, /* cache selection code */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) +SearchSysCacheTuple(int cacheId, /* cache selection code */ + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - register HeapTuple tp; - - if (cacheId < 0 || cacheId >= SysCacheSize) { - elog(WARN, "SearchSysCacheTuple: Bad cache id %d", cacheId); - return((HeapTuple) NULL); - } - - if (!AMI_OVERRIDE) { - Assert(PointerIsValid(SysCache[cacheId])); - } else { - if (!PointerIsValid(SysCache[cacheId])) { - SysCache[cacheId] = - InitSysCache(cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheId, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key, - cacheinfo[cacheId].iScanFunc); - if (!PointerIsValid(SysCache[cacheId])) { - elog(WARN, - "InitCatalogCache: Can't init cache %.16s(%d)", - cacheinfo[cacheId].name, - cacheId); - } - + register HeapTuple tp; + + if (cacheId < 0 || cacheId >= SysCacheSize) + { + elog(WARN, "SearchSysCacheTuple: Bad cache id %d", cacheId); + return ((HeapTuple) NULL); + } + + if (!AMI_OVERRIDE) + { + Assert(PointerIsValid(SysCache[cacheId])); + } + else + { + if (!PointerIsValid(SysCache[cacheId])) + { + SysCache[cacheId] = + InitSysCache(cacheinfo[cacheId].name, + cacheinfo[cacheId].indname, + cacheId, + cacheinfo[cacheId].nkeys, + cacheinfo[cacheId].key, + cacheinfo[cacheId].iScanFunc); + if (!PointerIsValid(SysCache[cacheId])) + { + elog(WARN, + "InitCatalogCache: Can't init cache %.16s(%d)", + cacheinfo[cacheId].name, + cacheId); + } + + } } - } - - tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4); - if (!HeapTupleIsValid(tp)) { + + tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4); + if (!HeapTupleIsValid(tp)) + { #ifdef CACHEDEBUG - elog(DEBUG, - "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", - (*cacheinfo[cacheId].name)->data, - cacheId, key1, key2, key3, key4); + elog(DEBUG, + "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", + (*cacheinfo[cacheId].name)->data, + cacheId, key1, key2, key3, key4); #endif - return((HeapTuple) NULL); - } - return(tp); + return ((HeapTuple) NULL); + } + return (tp); } /* * SearchSysCacheStruct-- - * Fills 's' with the information retrieved by calling SearchSysCache() - * with arguments key1...key4. Retrieves only the portion of the tuple - * which is not variable-length. + * Fills 's' with the information retrieved by calling SearchSysCache() + * with arguments key1...key4. Retrieves only the portion of the tuple + * which is not variable-length. * * NOTE: we are assuming that non-variable-length fields in the system - * catalogs will always be defined! + * catalogs will always be defined! * * Returns 1L if a tuple was found, 0L if not. */ int32 SearchSysCacheStruct(int cacheId, /* cache selection code */ - char *returnStruct, /* (preallocated!) */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) + char *returnStruct, /* (preallocated!) */ + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple tp; - - if (!PointerIsValid(returnStruct)) { - elog(WARN, "SearchSysCacheStruct: No receiving struct"); - return(0); - } - tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); - if (!HeapTupleIsValid(tp)) - return(0); - memmove(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size); - return(1); + HeapTuple tp; + + if (!PointerIsValid(returnStruct)) + { + elog(WARN, "SearchSysCacheStruct: No receiving struct"); + return (0); + } + tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); + if (!HeapTupleIsValid(tp)) + return (0); + memmove(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size); + return (1); } /* * SearchSysCacheGetAttribute-- - * Returns the attribute corresponding to 'attributeNumber' for - * a given cached tuple. + * Returns the attribute corresponding to 'attributeNumber' for + * a given cached tuple. * * XXX This re-opens a relation, so this is slower. * * [callers all assume this returns a (struct varlena *). -ay 10/94] */ -void * +void * SearchSysCacheGetAttribute(int cacheId, - AttrNumber attributeNumber, - Datum key1, - Datum key2, - Datum key3, - Datum key4) + AttrNumber attributeNumber, + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple tp; - char *cacheName; - Relation relation; - int32 attributeLength, attributeByValue; - bool isNull; - char *attributeValue; - void *returnValue; - - tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); - cacheName = cacheinfo[cacheId].name; - - if (!HeapTupleIsValid(tp)) { + HeapTuple tp; + char *cacheName; + Relation relation; + int32 attributeLength, + attributeByValue; + bool isNull; + char *attributeValue; + void *returnValue; + + tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); + cacheName = cacheinfo[cacheId].name; + + if (!HeapTupleIsValid(tp)) + { #ifdef CACHEDEBUG - elog(DEBUG, - "SearchSysCacheGetAttribute: Lookup in %s(%d) failed", - cacheName, cacheId); -#endif /* defined(CACHEDEBUG) */ - return(NULL); - } - - relation = heap_openr(cacheName); - - if (attributeNumber < 0 && - attributeNumber > FirstLowInvalidHeapAttributeNumber) { - attributeLength = heap_sysattrlen(attributeNumber); - attributeByValue = heap_sysattrbyval(attributeNumber); - } else if (attributeNumber > 0 && - attributeNumber <= relation->rd_rel->relnatts) { - attributeLength = - relation->rd_att->attrs[attributeNumber-1]->attlen; - attributeByValue = - relation->rd_att->attrs[attributeNumber-1]->attbyval; - } else { - elog(WARN, - "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", - attributeNumber, cacheName, cacheId); - return(NULL); - } - - attributeValue = heap_getattr(tp, - (Buffer) 0, - attributeNumber, - RelationGetTupleDescriptor(relation), - &isNull); - - if (isNull) { - /* - * Used to be an elog(DEBUG, ...) here and a claim that it should - * be a FATAL error, I don't think either is warranted -mer 6/9/92 - */ - return(NULL); - } - - if (attributeByValue) { - returnValue = (void *)attributeValue; - } else { - char *tmp; - int size = (attributeLength < 0) - ? VARSIZE((struct varlena *) attributeValue) /* variable length */ - : attributeLength; /* fixed length */ - - tmp = (char *) palloc(size); - memmove(tmp, attributeValue, size); - returnValue = (void *)tmp; - } - - heap_close(relation); - return(returnValue); + elog(DEBUG, + "SearchSysCacheGetAttribute: Lookup in %s(%d) failed", + cacheName, cacheId); +#endif /* defined(CACHEDEBUG) */ + return (NULL); + } + + relation = heap_openr(cacheName); + + if (attributeNumber < 0 && + attributeNumber > FirstLowInvalidHeapAttributeNumber) + { + attributeLength = heap_sysattrlen(attributeNumber); + attributeByValue = heap_sysattrbyval(attributeNumber); + } + else if (attributeNumber > 0 && + attributeNumber <= relation->rd_rel->relnatts) + { + attributeLength = + relation->rd_att->attrs[attributeNumber - 1]->attlen; + attributeByValue = + relation->rd_att->attrs[attributeNumber - 1]->attbyval; + } + else + { + elog(WARN, + "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", + attributeNumber, cacheName, cacheId); + return (NULL); + } + + attributeValue = heap_getattr(tp, + (Buffer) 0, + attributeNumber, + RelationGetTupleDescriptor(relation), + &isNull); + + if (isNull) + { + + /* + * Used to be an elog(DEBUG, ...) here and a claim that it should + * be a FATAL error, I don't think either is warranted -mer 6/9/92 + */ + return (NULL); + } + + if (attributeByValue) + { + returnValue = (void *) attributeValue; + } + else + { + char *tmp; + int size = (attributeLength < 0) + ? VARSIZE((struct varlena *) attributeValue) /* variable length */ + : attributeLength; /* fixed length */ + + tmp = (char *) palloc(size); + memmove(tmp, attributeValue, size); + returnValue = (void *) tmp; + } + + heap_close(relation); + return (returnValue); } /* * TypeDefaultRetrieve-- * - * Given a type OID, return the typdefault field associated with that - * type. The typdefault is returned as the car of a dotted pair which - * is passed to TypeDefaultRetrieve by the calling routine. + * Given a type OID, return the typdefault field associated with that + * type. The typdefault is returned as the car of a dotted pair which + * is passed to TypeDefaultRetrieve by the calling routine. * * Returns a fixnum for types which are passed by value and a ppreserve'd * vectori for types which are not. * * [identical to get_typdefault, expecting a (struct varlena *) as ret val. - * some day, either of the functions should be removed -ay 10/94] + * some day, either of the functions should be removed -ay 10/94] */ -void * +void * TypeDefaultRetrieve(Oid typId) { - HeapTuple typeTuple; - TypeTupleForm type; - int32 typByVal, typLen; - struct varlena *typDefault; - int32 dataSize; - void *returnValue; - - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(typId), - 0,0,0); - - if (!HeapTupleIsValid(typeTuple)) { -#ifdef CACHEDEBUG - elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed", - (*cacheinfo[TYPOID].name)->data, TYPOID); -#endif /* defined(CACHEDEBUG) */ - return(NULL); - } - - type = (TypeTupleForm) GETSTRUCT(typeTuple); - typByVal = type->typbyval; - typLen = type->typlen; - - typDefault = (struct varlena *) - SearchSysCacheGetAttribute(TYPOID, - Anum_pg_type_typdefault, - ObjectIdGetDatum(typId), - 0,0,0); - - if (typDefault == (struct varlena *)NULL) { + HeapTuple typeTuple; + TypeTupleForm type; + int32 typByVal, + typLen; + struct varlena *typDefault; + int32 dataSize; + void *returnValue; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(typId), + 0, 0, 0); + + if (!HeapTupleIsValid(typeTuple)) + { #ifdef CACHEDEBUG - elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault", - (*cacheinfo[TYPOID].name)->data, TYPOID); -#endif /* defined(CACHEDEBUG) */ - return (NULL); - - } - - dataSize = VARSIZE(typDefault) - VARHDRSZ; - - if (typByVal) { - int8 i8; - int16 i16; - int32 i32; - - if (dataSize == typLen) { - switch (typLen) { - case sizeof(int8): - memmove((char *) &i8, VARDATA(typDefault), sizeof(int8)); - i32 = i8; - break; - case sizeof(int16): - memmove((char *) &i16, VARDATA(typDefault), sizeof(int16)); - i32 = i16; - break; - case sizeof(int32): - memmove((char *) &i32, VARDATA(typDefault), sizeof(int32)); - break; - } - returnValue = (void *)i32; - } else { - returnValue = NULL; + elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed", + (*cacheinfo[TYPOID].name)->data, TYPOID); +#endif /* defined(CACHEDEBUG) */ + return (NULL); } - } else { - if ((typLen < 0 && dataSize < 0) || dataSize != typLen) - returnValue = NULL; - else { - returnValue = (void *)palloc(VARSIZE(typDefault)); - memmove((char *) returnValue, - (char *) typDefault, - (int) VARSIZE(typDefault)); + + type = (TypeTupleForm) GETSTRUCT(typeTuple); + typByVal = type->typbyval; + typLen = type->typlen; + + typDefault = (struct varlena *) + SearchSysCacheGetAttribute(TYPOID, + Anum_pg_type_typdefault, + ObjectIdGetDatum(typId), + 0, 0, 0); + + if (typDefault == (struct varlena *) NULL) + { +#ifdef CACHEDEBUG + elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault", + (*cacheinfo[TYPOID].name)->data, TYPOID); +#endif /* defined(CACHEDEBUG) */ + return (NULL); + } - } - - return(returnValue); -} + dataSize = VARSIZE(typDefault) - VARHDRSZ; + if (typByVal) + { + int8 i8; + int16 i16; + int32 i32; + + if (dataSize == typLen) + { + switch (typLen) + { + case sizeof(int8): + memmove((char *) &i8, VARDATA(typDefault), sizeof(int8)); + i32 = i8; + break; + case sizeof(int16): + memmove((char *) &i16, VARDATA(typDefault), sizeof(int16)); + i32 = i16; + break; + case sizeof(int32): + memmove((char *) &i32, VARDATA(typDefault), sizeof(int32)); + break; + } + returnValue = (void *) i32; + } + else + { + returnValue = NULL; + } + } + else + { + if ((typLen < 0 && dataSize < 0) || dataSize != typLen) + returnValue = NULL; + else + { + returnValue = (void *) palloc(VARSIZE(typDefault)); + memmove((char *) returnValue, + (char *) typDefault, + (int) VARSIZE(typDefault)); + } + } + + return (returnValue); +} diff --git a/src/backend/utils/error/assert.c b/src/backend/utils/error/assert.c index 4fb99ced1b9..2c46dde02b8 100644 --- a/src/backend/utils/error/assert.c +++ b/src/backend/utils/error/assert.c @@ -1,67 +1,71 @@ /*------------------------------------------------------------------------- * * assert.c-- - * Assert code. + * Assert code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/assert.c,v 1.4 1997/04/17 20:38:26 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/assert.c,v 1.5 1997/09/07 04:53:11 momjian Exp $ * * NOTE - * This should eventually work with elog(), dlog(), etc. + * This should eventually work with elog(), dlog(), etc. * *------------------------------------------------------------------------- */ #include <stdio.h> -#include "postgres.h" /* where the declaration goes */ +#include "postgres.h" /* where the declaration goes */ #include "utils/module.h" #include "utils/exc.h" int -ExceptionalCondition(char* conditionName, - Exception *exceptionP, - char* detail, - char* fileName, - int lineNumber) +ExceptionalCondition(char *conditionName, + Exception * exceptionP, + char *detail, + char *fileName, + int lineNumber) { - extern char* ExcFileName; /* XXX */ - extern Index ExcLineNumber; /* XXX */ - - ExcFileName = fileName; - ExcLineNumber = lineNumber; - - if (!PointerIsValid(conditionName) - || !PointerIsValid(fileName) - || !PointerIsValid(exceptionP)) { - fprintf(stderr, "ExceptionalCondition: bad arguments\n"); - - ExcAbort(exceptionP, - (ExcDetail)detail, - (ExcData)NULL, - (ExcMessage)NULL); - } else { - fprintf(stderr, - "%s(\"%s:%s\", File: \"%s\", Line: %d)\n", + extern char *ExcFileName;/* XXX */ + extern Index ExcLineNumber; /* XXX */ + + ExcFileName = fileName; + ExcLineNumber = lineNumber; + + if (!PointerIsValid(conditionName) + || !PointerIsValid(fileName) + || !PointerIsValid(exceptionP)) + { + fprintf(stderr, "ExceptionalCondition: bad arguments\n"); + + ExcAbort(exceptionP, + (ExcDetail) detail, + (ExcData) NULL, + (ExcMessage) NULL); + } + else + { + fprintf(stderr, + "%s(\"%s:%s\", File: \"%s\", Line: %d)\n", exceptionP->message, conditionName, detail == NULL ? "" : detail, - fileName, lineNumber); - } + fileName, lineNumber); + } #ifdef ABORT_ON_ASSERT - abort(); + abort(); #endif - /* - * XXX Depending on the Exception and tracing conditions, you will - * XXX want to stop here immediately and maybe dump core. - * XXX This may be especially true for Assert(), etc. - */ - - /* TraceDump(); dump the trace stack */ - - /* XXX FIXME: detail is lost */ - ExcRaise(exceptionP, (ExcDetail)0, (ExcData)NULL, conditionName); - return(0); + + /* + * XXX Depending on the Exception and tracing conditions, you will XXX + * want to stop here immediately and maybe dump core. XXX This may be + * especially true for Assert(), etc. + */ + + /* TraceDump(); dump the trace stack */ + + /* XXX FIXME: detail is lost */ + ExcRaise(exceptionP, (ExcDetail) 0, (ExcData) NULL, conditionName); + return (0); } diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index fae4c1adeef..e4cdc6d595b 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * elog.c-- - * error logger + * error logger * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.17 1997/08/12 22:54:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.18 1997/09/07 04:53:15 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include <fcntl.h> #ifndef O_RDONLY #include <sys/file.h> -#endif /* O_RDONLY */ +#endif /* O_RDONLY */ #include <sys/types.h> #include <stdarg.h> #include <errno.h> @@ -29,204 +29,236 @@ #include "libpq/libpq.h" #include "storage/proc.h" -static int Debugfile = -1; -static int Err_file = -1; -static int ElogDebugIndentLevel = 0; +static int Debugfile = -1; +static int Err_file = -1; +static int ElogDebugIndentLevel = 0; -extern char OutputFileName[]; +extern char OutputFileName[]; /* * elog -- - * Old error logging function. + * Old error logging function. */ void -elog(int lev, const char *fmt, ... ) +elog(int lev, const char *fmt,...) { - va_list ap; - char buf[ELOG_MAXLEN], line[ELOG_MAXLEN]; - register char *bp; - register const char *cp; - extern int errno, sys_nerr; + va_list ap; + char buf[ELOG_MAXLEN], + line[ELOG_MAXLEN]; + register char *bp; + register const char *cp; + extern int errno, + sys_nerr; + #ifndef PG_STANDALONE - extern FILE *Pfout; -#endif /* !PG_STANDALONE */ + extern FILE *Pfout; + +#endif /* !PG_STANDALONE */ #ifdef ELOG_TIMESTAMPS - time_t tim; + time_t tim; + #endif - int len; - int i = 0; - - va_start(ap, fmt); - if (lev == DEBUG && Debugfile < 0) { - return; - } - switch (lev) { - case NOIND: - i = ElogDebugIndentLevel-1; - if (i < 0) i = 0; - if (i > 30) i = i%30; - cp = "DEBUG:"; - break; - case DEBUG: - i = ElogDebugIndentLevel; - if (i < 0) i = 0; - if (i > 30) i = i%30; - cp = "DEBUG:"; - break; - case NOTICE: - cp = "NOTICE:"; - break; - case WARN: - cp = "WARN:"; - break; - default: - sprintf(line, "FATAL %d:", lev); - cp = line; - } + int len; + int i = 0; + + va_start(ap, fmt); + if (lev == DEBUG && Debugfile < 0) + { + return; + } + switch (lev) + { + case NOIND: + i = ElogDebugIndentLevel - 1; + if (i < 0) + i = 0; + if (i > 30) + i = i % 30; + cp = "DEBUG:"; + break; + case DEBUG: + i = ElogDebugIndentLevel; + if (i < 0) + i = 0; + if (i > 30) + i = i % 30; + cp = "DEBUG:"; + break; + case NOTICE: + cp = "NOTICE:"; + break; + case WARN: + cp = "WARN:"; + break; + default: + sprintf(line, "FATAL %d:", lev); + cp = line; + } #ifdef ELOG_TIMESTAMPS - time(&tim); - strcat(strcpy(buf, cp), ctime(&tim)+4); - bp = buf+strlen(buf)-6; - *bp++ = ':'; + time(&tim); + strcat(strcpy(buf, cp), ctime(&tim) + 4); + bp = buf + strlen(buf) - 6; + *bp++ = ':'; #else - strcpy(buf,cp); - bp = buf+strlen(buf); + strcpy(buf, cp); + bp = buf + strlen(buf); #endif - while (i-- >0) *bp++ = ' '; - for (cp = fmt; *cp; cp++) - if (*cp == '%' && *(cp+1) == 'm') { - if (errno < sys_nerr && errno >= 0) - strcpy(bp, strerror(errno)); - else - sprintf(bp, "error %d", errno); - bp += strlen(bp); - cp++; - } else - *bp++ = *cp; - *bp = '\0'; - vsprintf(line, buf, ap); - va_end(ap); - len = strlen(strcat(line, "\n")); - if (Debugfile > -1) - write(Debugfile, line, len); - if (lev == DEBUG || lev == NOIND) - return; - - /* - * If there's an error log file other than our channel to the - * front-end program, write to it first. This is important - * because there's a bug in the socket code on ultrix. If the - * front end has gone away (so the channel to it has been closed - * at the other end), then writing here can cause this backend - * to exit without warning -- that is, write() does an exit(). - * In this case, our only hope of finding out what's going on - * is if Err_file was set to some disk log. This is a major pain. - */ - - if (Err_file > -1 && Debugfile != Err_file) { - if (write(Err_file, line, len) < 0) { - write(open("/dev/console", O_WRONLY, 0666), line, len); - fflush(stdout); - fflush(stderr); - exitpg(lev); - } - fsync(Err_file); - } - -#ifndef PG_STANDALONE - /* Send IPC message to the front-end program */ - if (Pfout != NULL && lev > DEBUG) { - /* notices are not exactly errors, handle it differently */ - if (lev == NOTICE) - pq_putnchar("N", 1); - else - pq_putnchar("E", 1); - /* pq_putint(-101, 4);*/ /* should be query id */ - pq_putstr(line); - pq_flush(); - } -#endif /* !PG_STANDALONE */ - - if (lev == WARN) { - extern int InWarn; - ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ - if (!InWarn) { - kill(getpid(), 1); /* abort to traffic cop */ - pause(); - } - /* - * The pause(3) is just to avoid race conditions where the - * thread of control on an MP system gets past here (i.e., - * the signal is not received instantaneously). - */ - } - - if (lev == FATAL) { + while (i-- > 0) + *bp++ = ' '; + for (cp = fmt; *cp; cp++) + if (*cp == '%' && *(cp + 1) == 'm') + { + if (errno < sys_nerr && errno >= 0) + strcpy(bp, strerror(errno)); + else + sprintf(bp, "error %d", errno); + bp += strlen(bp); + cp++; + } + else + *bp++ = *cp; + *bp = '\0'; + vsprintf(line, buf, ap); + va_end(ap); + len = strlen(strcat(line, "\n")); + if (Debugfile > -1) + write(Debugfile, line, len); + if (lev == DEBUG || lev == NOIND) + return; + /* - * Assume that if we have detected the failure we can - * exit with a normal exit status. This will prevent - * the postmaster from cleaning up when it's not needed. + * If there's an error log file other than our channel to the + * front-end program, write to it first. This is important because + * there's a bug in the socket code on ultrix. If the front end has + * gone away (so the channel to it has been closed at the other end), + * then writing here can cause this backend to exit without warning -- + * that is, write() does an exit(). In this case, our only hope of + * finding out what's going on is if Err_file was set to some disk + * log. This is a major pain. */ - fflush(stdout); - fflush(stderr); - ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ - ProcReleaseLocks(); /* get rid of real locks we hold */ - exitpg(0); - } - - if (lev > FATAL) { - fflush(stdout); - fflush(stderr); - exitpg(lev); - } + + if (Err_file > -1 && Debugfile != Err_file) + { + if (write(Err_file, line, len) < 0) + { + write(open("/dev/console", O_WRONLY, 0666), line, len); + fflush(stdout); + fflush(stderr); + exitpg(lev); + } + fsync(Err_file); + } + +#ifndef PG_STANDALONE + /* Send IPC message to the front-end program */ + if (Pfout != NULL && lev > DEBUG) + { + /* notices are not exactly errors, handle it differently */ + if (lev == NOTICE) + pq_putnchar("N", 1); + else + pq_putnchar("E", 1); + /* pq_putint(-101, 4); *//* should be query id */ + pq_putstr(line); + pq_flush(); + } +#endif /* !PG_STANDALONE */ + + if (lev == WARN) + { + extern int InWarn; + + ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ + if (!InWarn) + { + kill(getpid(), 1); /* abort to traffic cop */ + pause(); + } + + /* + * The pause(3) is just to avoid race conditions where the thread + * of control on an MP system gets past here (i.e., the signal is + * not received instantaneously). + */ + } + + if (lev == FATAL) + { + + /* + * Assume that if we have detected the failure we can exit with a + * normal exit status. This will prevent the postmaster from + * cleaning up when it's not needed. + */ + fflush(stdout); + fflush(stderr); + ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ + ProcReleaseLocks(); /* get rid of real locks we hold */ + exitpg(0); + } + + if (lev > FATAL) + { + fflush(stdout); + fflush(stderr); + exitpg(lev); + } } #ifndef PG_STANDALONE int DebugFileOpen(void) { - int fd, istty; - - Err_file = Debugfile = -1; - ElogDebugIndentLevel = 0; - - if (OutputFileName[0]) { - OutputFileName[MAXPGPATH-1] = '\0'; - if ((fd = open(OutputFileName, O_CREAT|O_APPEND|O_WRONLY, - 0666)) < 0) - elog(FATAL, "DebugFileOpen: open of %s: %m", - OutputFileName); - istty = isatty(fd); - close(fd); - /* If the file is a tty and we're running under the - * postmaster, try to send stdout there as well (if it - * isn't a tty then stderr will block out stdout, so we - * may as well let stdout go wherever it was going before). + int fd, + istty; + + Err_file = Debugfile = -1; + ElogDebugIndentLevel = 0; + + if (OutputFileName[0]) + { + OutputFileName[MAXPGPATH - 1] = '\0'; + if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, + 0666)) < 0) + elog(FATAL, "DebugFileOpen: open of %s: %m", + OutputFileName); + istty = isatty(fd); + close(fd); + + /* + * If the file is a tty and we're running under the postmaster, + * try to send stdout there as well (if it isn't a tty then stderr + * will block out stdout, so we may as well let stdout go wherever + * it was going before). + */ + if (istty && + IsUnderPostmaster && + !freopen(OutputFileName, "a", stdout)) + elog(FATAL, "DebugFileOpen: %s reopen as stdout: %m", + OutputFileName); + if (!freopen(OutputFileName, "a", stderr)) + elog(FATAL, "DebugFileOpen: %s reopen as stderr: %m", + OutputFileName); + Err_file = Debugfile = fileno(stderr); + return (Debugfile); + } + + /* + * If no filename was specified, send debugging output to stderr. If + * stderr has been hosed, try to open a file. */ - if (istty && - IsUnderPostmaster && - !freopen(OutputFileName, "a", stdout)) - elog(FATAL, "DebugFileOpen: %s reopen as stdout: %m", - OutputFileName); - if (!freopen(OutputFileName, "a", stderr)) - elog(FATAL, "DebugFileOpen: %s reopen as stderr: %m", - OutputFileName); - Err_file = Debugfile = fileno(stderr); - return(Debugfile); - } - /* If no filename was specified, send debugging output to stderr. - * If stderr has been hosed, try to open a file. - */ - fd = fileno(stderr); - if (fcntl(fd, F_GETFD, 0) < 0) { - sprintf(OutputFileName, "%s/pg.errors.%d", - DataDir, (int)getpid()); - fd = open(OutputFileName, O_CREAT|O_APPEND|O_WRONLY, 0666); - } - if (fd < 0) - elog(FATAL, "DebugFileOpen: could not open debugging file"); - - Err_file = Debugfile = fd; - return(Debugfile); + fd = fileno(stderr); + if (fcntl(fd, F_GETFD, 0) < 0) + { + sprintf(OutputFileName, "%s/pg.errors.%d", + DataDir, (int) getpid()); + fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, 0666); + } + if (fd < 0) + elog(FATAL, "DebugFileOpen: could not open debugging file"); + + Err_file = Debugfile = fd; + return (Debugfile); } + #endif diff --git a/src/backend/utils/error/exc.c b/src/backend/utils/error/exc.c index 3366996fad1..fd169b94a18 100644 --- a/src/backend/utils/error/exc.c +++ b/src/backend/utils/error/exc.c @@ -1,21 +1,21 @@ /*------------------------------------------------------------------------- * * exc.c-- - * POSTGRES exception handling code. + * POSTGRES exception handling code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/exc.c,v 1.15 1997/08/19 21:35:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/exc.c,v 1.16 1997/09/07 04:53:16 momjian Exp $ * * NOTE - * XXX this code needs improvement--check for state violations and - * XXX reset after handling an exception. + * XXX this code needs improvement--check for state violations and + * XXX reset after handling an exception. * *------------------------------------------------------------------------- */ -#include <stdio.h> /* XXX use own I/O routines */ +#include <stdio.h> /* XXX use own I/O routines */ #include <errno.h> #include <string.h> @@ -24,24 +24,26 @@ #include "utils/exc.h" #include "storage/ipc.h" -static void ExcUnCaught(Exception *excP, ExcDetail detail, ExcData data, +static void +ExcUnCaught(Exception * excP, ExcDetail detail, ExcData data, ExcMessage message); -static void ExcPrint(Exception *excP, ExcDetail detail, ExcData data, - ExcMessage message); +static void +ExcPrint(Exception * excP, ExcDetail detail, ExcData data, + ExcMessage message); /* * Global Variables */ -static bool ExceptionHandlingEnabled = false; +static bool ExceptionHandlingEnabled = false; -char* ExcFileName = NULL; +char *ExcFileName = NULL; Index ExcLineNumber = 0; -ExcFrame *ExcCurFrameP = NULL; +ExcFrame *ExcCurFrameP = NULL; -static ExcProc *ExcUnCaughtP = NULL; +static ExcProc *ExcUnCaughtP = NULL; -extern char* ProgramName; +extern char *ProgramName; /* * Exported Functions @@ -49,148 +51,157 @@ extern char* ProgramName; /* * EnableExceptionHandling -- - * Enables/disables the exception handling system. + * Enables/disables the exception handling system. * * Note: - * This must be called before any exceptions occur. I.e., call this first! - * This routine will not return if an error is detected. - * This does not follow the usual Enable... protocol. - * This should be merged more closely with the error logging and tracing - * packages. + * This must be called before any exceptions occur. I.e., call this first! + * This routine will not return if an error is detected. + * This does not follow the usual Enable... protocol. + * This should be merged more closely with the error logging and tracing + * packages. * * Exceptions: - * none + * none */ /* * Excection handling should be supported by the language, thus there should * be no need to explicitly enable exception processing. * * This function should probably not be called, ever. Currently it does - * almost nothing. If there is a need for this intialization and checking. + * almost nothing. If there is a need for this intialization and checking. * then this function should be converted to the new-style Enable code and * called by all the other module Enable functions. */ void EnableExceptionHandling(bool on) { - if (on == ExceptionHandlingEnabled) { - /* XXX add logging of failed state */ - exitpg(255); - /* ExitPostgres(FatalExitStatus); */ - } - - if (on) { /* initialize */ - ; - } else { /* cleanup */ - ExcFileName = NULL; - ExcLineNumber = 0; - ExcCurFrameP = NULL; - ExcUnCaughtP = NULL; - } - - ExceptionHandlingEnabled = on; + if (on == ExceptionHandlingEnabled) + { + /* XXX add logging of failed state */ + exitpg(255); + /* ExitPostgres(FatalExitStatus); */ + } + + if (on) + { /* initialize */ + ; + } + else + { /* cleanup */ + ExcFileName = NULL; + ExcLineNumber = 0; + ExcCurFrameP = NULL; + ExcUnCaughtP = NULL; + } + + ExceptionHandlingEnabled = on; } static void -ExcPrint(Exception *excP, - ExcDetail detail, - ExcData data, - ExcMessage message) +ExcPrint(Exception * excP, + ExcDetail detail, + ExcData data, + ExcMessage message) { - extern int errno; - extern int sys_nerr; - + extern int errno; + extern int sys_nerr; + #ifdef lint - data = data; + data = data; #endif - - fflush(stdout); /* In case stderr is buffered */ - -#if 0 - if (ProgramName != NULL && *ProgramName != '\0') - fprintf(stderr, "%s: ", ProgramName); + + fflush(stdout); /* In case stderr is buffered */ + +#if 0 + if (ProgramName != NULL && *ProgramName != '\0') + fprintf(stderr, "%s: ", ProgramName); #endif - - if (message != NULL) - fprintf(stderr, "%s", message); - else if (excP->message != NULL) - fprintf(stderr, "%s", excP->message); - else + + if (message != NULL) + fprintf(stderr, "%s", message); + else if (excP->message != NULL) + fprintf(stderr, "%s", excP->message); + else #ifdef lint - fprintf(stderr, "UNNAMED EXCEPTION 0x%lx", excP); + fprintf(stderr, "UNNAMED EXCEPTION 0x%lx", excP); #else - fprintf(stderr, "UNNAMED EXCEPTION 0x%lx", (long)excP); + fprintf(stderr, "UNNAMED EXCEPTION 0x%lx", (long) excP); #endif - - fprintf(stderr, " (%ld)", detail); - - if (errno > 0 && errno < sys_nerr) - fprintf(stderr, " [%s]", strerror(errno)); - else if (errno != 0) - fprintf(stderr, " [Error %d]", errno); - - fprintf(stderr, "\n"); - - fflush(stderr); + + fprintf(stderr, " (%ld)", detail); + + if (errno > 0 && errno < sys_nerr) + fprintf(stderr, " [%s]", strerror(errno)); + else if (errno != 0) + fprintf(stderr, " [Error %d]", errno); + + fprintf(stderr, "\n"); + + fflush(stderr); } #ifdef NOT_USED -ExcProc * +ExcProc * ExcGetUnCaught(void) { - return (ExcUnCaughtP); + return (ExcUnCaughtP); } + #endif #ifdef NOT_USED -ExcProc * -ExcSetUnCaught(ExcProc *newP) +ExcProc * +ExcSetUnCaught(ExcProc * newP) { - ExcProc *oldP = ExcUnCaughtP; - - ExcUnCaughtP = newP; - - return (oldP); + ExcProc *oldP = ExcUnCaughtP; + + ExcUnCaughtP = newP; + + return (oldP); } + #endif static void -ExcUnCaught(Exception *excP, - ExcDetail detail, - ExcData data, - ExcMessage message) +ExcUnCaught(Exception * excP, + ExcDetail detail, + ExcData data, + ExcMessage message) { - ExcPrint(excP, detail, data, message); - - ExcAbort(excP, detail, data, message); + ExcPrint(excP, detail, data, message); + + ExcAbort(excP, detail, data, message); } void -ExcRaise(Exception *excP, - ExcDetail detail, - ExcData data, - ExcMessage message) +ExcRaise(Exception * excP, + ExcDetail detail, + ExcData data, + ExcMessage message) { - register ExcFrame *efp; - - efp = ExcCurFrameP; - if (efp == NULL) { - if (ExcUnCaughtP != NULL) - (*ExcUnCaughtP)(excP, detail, data, message); - - ExcUnCaught(excP, detail, data, message); - } else { - efp->id = excP; - efp->detail = detail; - efp->data = data; - efp->message = message; - - ExcCurFrameP = efp->link; - + register ExcFrame *efp; + + efp = ExcCurFrameP; + if (efp == NULL) + { + if (ExcUnCaughtP != NULL) + (*ExcUnCaughtP) (excP, detail, data, message); + + ExcUnCaught(excP, detail, data, message); + } + else + { + efp->id = excP; + efp->detail = detail; + efp->data = data; + efp->message = message; + + ExcCurFrameP = efp->link; + #if defined (JMP_BUF) - longjmp(efp->context, 1); + longjmp(efp->context, 1); #else - siglongjmp(efp->context, 1); + siglongjmp(efp->context, 1); #endif - } + } } diff --git a/src/backend/utils/error/excabort.c b/src/backend/utils/error/excabort.c index 29fd64ab7d5..3240f326496 100644 --- a/src/backend/utils/error/excabort.c +++ b/src/backend/utils/error/excabort.c @@ -1,31 +1,31 @@ /*------------------------------------------------------------------------- * * excabort.c-- - * Default exception abort code. + * Default exception abort code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/excabort.c,v 1.2 1996/11/03 06:53:32 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/excabort.c,v 1.3 1997/09/07 04:53:18 momjian Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "utils/exc.h" /* where function declarations go */ +#include "utils/exc.h" /* where function declarations go */ void -ExcAbort(const Exception *excP, - ExcDetail detail, - ExcData data, - ExcMessage message) +ExcAbort(const Exception * excP, + ExcDetail detail, + ExcData data, + ExcMessage message) { #ifdef __SABER__ - saber_stop(); + saber_stop(); #else - /* dump core */ - abort(); + /* dump core */ + abort(); #endif } diff --git a/src/backend/utils/error/excid.c b/src/backend/utils/error/excid.c index 410d7a56c88..ada9dabed70 100644 --- a/src/backend/utils/error/excid.c +++ b/src/backend/utils/error/excid.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * excid.c-- - * POSTGRES known exception identifier code. + * POSTGRES known exception identifier code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/excid.c,v 1.2 1996/11/03 06:53:35 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/excid.c,v 1.3 1997/09/07 04:53:19 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,51 +17,51 @@ #include "utils/excid.h" /***************************************************************************** - * Generic Recoverable Exceptions * + * Generic Recoverable Exceptions * *****************************************************************************/ /* * FailedAssertion -- - * Indicates an Assert(...) failed. + * Indicates an Assert(...) failed. */ -Exception FailedAssertion = { "Failed Assertion" }; +Exception FailedAssertion = {"Failed Assertion"}; /* * BadState -- - * Indicates a function call request is inconsistent with module state. + * Indicates a function call request is inconsistent with module state. */ -Exception BadState = { "Bad State for Function Call" }; +Exception BadState = {"Bad State for Function Call"}; /* * BadArg -- - * Indicates a function call argument or arguments is out-of-bounds. + * Indicates a function call argument or arguments is out-of-bounds. */ -Exception BadArg = { "Bad Argument to Function Call" }; +Exception BadArg = {"Bad Argument to Function Call"}; /***************************************************************************** - * Specific Recoverable Exceptions * + * Specific Recoverable Exceptions * *****************************************************************************/ /* * BadAllocSize -- - * Indicates that an allocation request is of unreasonable size. + * Indicates that an allocation request is of unreasonable size. */ -Exception BadAllocSize = { "Too Large Allocation Request" }; +Exception BadAllocSize = {"Too Large Allocation Request"}; /* * ExhaustedMemory -- - * Indicates an dynamic memory allocation failed. + * Indicates an dynamic memory allocation failed. */ -Exception ExhaustedMemory = { "Memory Allocation Failed" }; +Exception ExhaustedMemory = {"Memory Allocation Failed"}; /* * Unimplemented -- - * Indicates a function call request requires unimplemented code. + * Indicates a function call request requires unimplemented code. */ -Exception Unimplemented = { "Unimplemented Functionality" }; +Exception Unimplemented = {"Unimplemented Functionality"}; -Exception CatalogFailure = {"Catalog failure"}; /* XXX inconsistent */ -Exception InternalError = {"Internal Error"}; /* XXX inconsistent */ -Exception SemanticError = {"Semantic Error"}; /* XXX inconsistent */ -Exception SystemError = {"System Error"}; /* XXX inconsistent */ +Exception CatalogFailure = {"Catalog failure"}; /* XXX inconsistent */ +Exception InternalError = {"Internal Error"}; /* XXX inconsistent */ +Exception SemanticError = {"Semantic Error"}; /* XXX inconsistent */ +Exception SystemError = {"System Error"}; /* XXX inconsistent */ diff --git a/src/backend/utils/error/format.c b/src/backend/utils/error/format.c index bdbaddb402f..f996dbb8eb7 100644 --- a/src/backend/utils/error/format.c +++ b/src/backend/utils/error/format.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * format.c-- - * a wrapper around code that does what vsprintf does. + * a wrapper around code that does what vsprintf does. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/format.c,v 1.3 1997/08/12 22:54:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/format.c,v 1.4 1997/09/07 04:53:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -15,26 +15,26 @@ #include <stdarg.h> #include "c.h" -#define FormMaxSize 1024 -#define FormMinSize (FormMaxSize / 8) +#define FormMaxSize 1024 +#define FormMinSize (FormMaxSize / 8) -static char FormBuf[FormMaxSize]; +static char FormBuf[FormMaxSize]; /* ---------------- - * form + * form * ---------------- */ -char * -form(const char *fmt, ... ) +char * +form(const char *fmt,...) { - va_list args; + va_list args; - va_start(args, fmt); - - vsprintf(FormBuf, fmt, args); + va_start(args, fmt); - va_end(args); - - return (FormBuf); + vsprintf(FormBuf, fmt, args); + + va_end(args); + + return (FormBuf); } diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 079c9d0a173..0be7524290f 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * dfmgr.c-- - * Dynamic function manager code. + * Dynamic function manager code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.9 1997/09/01 08:06:17 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.10 1997/09/07 04:53:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,15 +18,15 @@ #include "postgres.h" -#include "config.h" /* for MAXPATHLEN */ -#include "fmgr.h" /* generated by Gen_fmgrtab.sh */ +#include "config.h" /* for MAXPATHLEN */ +#include "fmgr.h" /* generated by Gen_fmgrtab.sh */ #include "utils/dynamic_loader.h" #include "utils/elog.h" #include "utils/builtins.h" #include "access/heapam.h" #include "nodes/pg_list.h" -#include "port-protos.h" /* system specific function prototypes */ +#include "port-protos.h" /* system specific function prototypes */ #ifdef __ultrix #include <dl.h> #endif @@ -39,178 +39,197 @@ static DynamicFileList *file_list = (DynamicFileList *) NULL; static DynamicFileList *file_tail = (DynamicFileList *) NULL; #define NOT_EQUAL(A, B) (((A).st_ino != (B).inode) \ - || ((A).st_dev != (B).device)) + || ((A).st_dev != (B).device)) -static Oid procedureId_save = -1; -static int pronargs_save; +static Oid procedureId_save = -1; +static int pronargs_save; static func_ptr user_fn_save = (func_ptr) NULL; static func_ptr handle_load(char *filename, char *funcname); -func_ptr trigger_dynamic (char *filename, char *funcname); +func_ptr trigger_dynamic(char *filename, char *funcname); func_ptr fmgr_dynamic(Oid procedureId, int *pronargs) { - HeapTuple procedureTuple; - Form_pg_proc procedureStruct; - char *proname; - char *probinattr, *probinstring; - func_ptr user_fn; - Relation rdesc; - bool isnull; - - if (procedureId == procedureId_save) { - *pronargs = pronargs_save; - return(user_fn_save); - } - - /* - * The procedure isn't a builtin, so we'll have to do a catalog - * lookup to find its pg_proc entry. - */ - procedureTuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(procedureId), - 0,0,0); - if (!HeapTupleIsValid(procedureTuple)) { - elog(WARN, "fmgr: Cache lookup failed for procedure %d\n", - procedureId); - return((func_ptr) NULL); - } - - procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); - proname = procedureStruct->proname.data; - pronargs_save = *pronargs = procedureStruct->pronargs; - - /* - * Extract the procedure info from the pg_proc tuple. - * Since probin is varlena, do a amgetattr() on the procedure - * tuple. To do that, we need the rdesc for the procedure - * relation, so... - */ - - /* open pg_procedure */ - - rdesc = heap_openr(ProcedureRelationName); - if (!RelationIsValid(rdesc)) { - elog(WARN, "fmgr: Could not open relation %s", - ProcedureRelationName); - return((func_ptr) NULL); - } - probinattr = heap_getattr(procedureTuple, (Buffer) 0, - Anum_pg_proc_probin, - RelationGetTupleDescriptor(rdesc), &isnull); - if (!PointerIsValid(probinattr) /*|| isnull*/) { - heap_close(rdesc); - elog(WARN, "fmgr: Could not extract probin for %d from %s", - procedureId, ProcedureRelationName); - return((func_ptr) NULL); - } - probinstring = textout((struct varlena *) probinattr); - - user_fn = handle_load(probinstring, proname); - - procedureId_save = procedureId; - user_fn_save = user_fn; - - return(user_fn); + HeapTuple procedureTuple; + Form_pg_proc procedureStruct; + char *proname; + char *probinattr, + *probinstring; + func_ptr user_fn; + Relation rdesc; + bool isnull; + + if (procedureId == procedureId_save) + { + *pronargs = pronargs_save; + return (user_fn_save); + } + + /* + * The procedure isn't a builtin, so we'll have to do a catalog lookup + * to find its pg_proc entry. + */ + procedureTuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(procedureId), + 0, 0, 0); + if (!HeapTupleIsValid(procedureTuple)) + { + elog(WARN, "fmgr: Cache lookup failed for procedure %d\n", + procedureId); + return ((func_ptr) NULL); + } + + procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); + proname = procedureStruct->proname.data; + pronargs_save = *pronargs = procedureStruct->pronargs; + + /* + * Extract the procedure info from the pg_proc tuple. Since probin is + * varlena, do a amgetattr() on the procedure tuple. To do that, we + * need the rdesc for the procedure relation, so... + */ + + /* open pg_procedure */ + + rdesc = heap_openr(ProcedureRelationName); + if (!RelationIsValid(rdesc)) + { + elog(WARN, "fmgr: Could not open relation %s", + ProcedureRelationName); + return ((func_ptr) NULL); + } + probinattr = heap_getattr(procedureTuple, (Buffer) 0, + Anum_pg_proc_probin, + RelationGetTupleDescriptor(rdesc), &isnull); + if (!PointerIsValid(probinattr) /* || isnull */ ) + { + heap_close(rdesc); + elog(WARN, "fmgr: Could not extract probin for %d from %s", + procedureId, ProcedureRelationName); + return ((func_ptr) NULL); + } + probinstring = textout((struct varlena *) probinattr); + + user_fn = handle_load(probinstring, proname); + + procedureId_save = procedureId; + user_fn_save = user_fn; + + return (user_fn); } -static func_ptr +static func_ptr handle_load(char *filename, char *funcname) { - DynamicFileList *file_scanner = (DynamicFileList *) NULL; - func_ptr retval = (func_ptr) NULL; - char *load_error; - struct stat stat_buf; - - /* - * Do this because loading files may screw up the dynamic function - * manager otherwise. - */ - procedureId_save = -1; - - /* - * Scan the list of loaded FILES to see if the function - * has been loaded. - */ - - if (filename != (char *) NULL) { - for (file_scanner = file_list; - file_scanner != (DynamicFileList *) NULL - && file_scanner->filename != (char *) NULL - && strcmp(filename, file_scanner->filename) != 0; - file_scanner = file_scanner->next) - ; - if (file_scanner == (DynamicFileList *) NULL) { - if (stat(filename, &stat_buf) == -1) { - elog(WARN, "stat failed on file %s", filename); - } - - for (file_scanner = file_list; - file_scanner != (DynamicFileList *) NULL - && (NOT_EQUAL(stat_buf, *file_scanner)); - file_scanner = file_scanner->next) - ; - /* - * Same files - different paths (ie, symlink or link) - */ - if (file_scanner != (DynamicFileList *) NULL) - strcpy(file_scanner->filename, filename); - - } - } else { - file_scanner = (DynamicFileList *) NULL; - } - - /* - * File not loaded yet. - */ - - if (file_scanner == (DynamicFileList *) NULL) { - if (file_list == (DynamicFileList *) NULL) { - file_list = (DynamicFileList *) - malloc(sizeof(DynamicFileList)); - file_scanner = file_list; - } else { - file_tail->next = (DynamicFileList *) - malloc(sizeof(DynamicFileList)); - file_scanner = file_tail->next; - } - memset((char *) file_scanner, 0, sizeof(DynamicFileList)); - - strcpy(file_scanner->filename, filename); - file_scanner->device = stat_buf.st_dev; - file_scanner->inode = stat_buf.st_ino; - file_scanner->next = (DynamicFileList *) NULL; - - file_scanner->handle = pg_dlopen(filename); - if (file_scanner->handle == (void *)NULL) { - load_error = (char *) pg_dlerror(); - if (file_scanner == file_list) { - file_list = (DynamicFileList *) NULL; - } else { - file_tail->next = (DynamicFileList *) NULL; - } - - free((char *) file_scanner); - elog(WARN, "Load of file %s failed: %s", filename, load_error); - } - + DynamicFileList *file_scanner = (DynamicFileList *) NULL; + func_ptr retval = (func_ptr) NULL; + char *load_error; + struct stat stat_buf; + + /* + * Do this because loading files may screw up the dynamic function + * manager otherwise. + */ + procedureId_save = -1; + /* - * Just load the file - we are done with that so return. + * Scan the list of loaded FILES to see if the function has been + * loaded. */ - file_tail = file_scanner; - - if (funcname == (char *) NULL) - return((func_ptr) NULL); - } - - retval = (func_ptr) pg_dlsym(file_scanner->handle, funcname); - - if (retval == (func_ptr) NULL) { - elog(WARN, "Can't find function %s in file %s", funcname, filename); - } - - return(retval); + + if (filename != (char *) NULL) + { + for (file_scanner = file_list; + file_scanner != (DynamicFileList *) NULL + && file_scanner->filename != (char *) NULL + && strcmp(filename, file_scanner->filename) != 0; + file_scanner = file_scanner->next) + ; + if (file_scanner == (DynamicFileList *) NULL) + { + if (stat(filename, &stat_buf) == -1) + { + elog(WARN, "stat failed on file %s", filename); + } + + for (file_scanner = file_list; + file_scanner != (DynamicFileList *) NULL + && (NOT_EQUAL(stat_buf, *file_scanner)); + file_scanner = file_scanner->next) + ; + + /* + * Same files - different paths (ie, symlink or link) + */ + if (file_scanner != (DynamicFileList *) NULL) + strcpy(file_scanner->filename, filename); + + } + } + else + { + file_scanner = (DynamicFileList *) NULL; + } + + /* + * File not loaded yet. + */ + + if (file_scanner == (DynamicFileList *) NULL) + { + if (file_list == (DynamicFileList *) NULL) + { + file_list = (DynamicFileList *) + malloc(sizeof(DynamicFileList)); + file_scanner = file_list; + } + else + { + file_tail->next = (DynamicFileList *) + malloc(sizeof(DynamicFileList)); + file_scanner = file_tail->next; + } + memset((char *) file_scanner, 0, sizeof(DynamicFileList)); + + strcpy(file_scanner->filename, filename); + file_scanner->device = stat_buf.st_dev; + file_scanner->inode = stat_buf.st_ino; + file_scanner->next = (DynamicFileList *) NULL; + + file_scanner->handle = pg_dlopen(filename); + if (file_scanner->handle == (void *) NULL) + { + load_error = (char *) pg_dlerror(); + if (file_scanner == file_list) + { + file_list = (DynamicFileList *) NULL; + } + else + { + file_tail->next = (DynamicFileList *) NULL; + } + + free((char *) file_scanner); + elog(WARN, "Load of file %s failed: %s", filename, load_error); + } + + /* + * Just load the file - we are done with that so return. + */ + file_tail = file_scanner; + + if (funcname == (char *) NULL) + return ((func_ptr) NULL); + } + + retval = (func_ptr) pg_dlsym(file_scanner->handle, funcname); + + if (retval == (func_ptr) NULL) + { + elog(WARN, "Can't find function %s in file %s", funcname, filename); + } + + return (retval); } /* @@ -218,7 +237,7 @@ handle_load(char *filename, char *funcname) * * If the file is already loaded: * o Zero out that file's loaded space (so it doesn't screw up linking) - * o Free all space associated with that file + * o Free all space associated with that file * o Free that file's descriptor. * * Now load the file by calling handle_load with a NULL argument as the @@ -227,49 +246,61 @@ handle_load(char *filename, char *funcname) void load_file(char *filename) { - DynamicFileList *file_scanner, *p; - struct stat stat_buf; - - int done = 0; - - if (stat(filename, &stat_buf) == -1) { - elog(WARN, "stat failed on file %s", filename); - } - - if (file_list != (DynamicFileList *) NULL - && !NOT_EQUAL(stat_buf, *file_list)) { - file_scanner = file_list; - file_list = file_list->next; - pg_dlclose(file_scanner->handle); - free((char *) file_scanner); - } else if (file_list != (DynamicFileList *) NULL) { - file_scanner = file_list; - while (!done) { - if (file_scanner->next == (DynamicFileList *) NULL) { - done = 1; - } else if (!NOT_EQUAL(stat_buf, *(file_scanner->next))) { - done = 1; - } else { - file_scanner = file_scanner->next; - } - } - - if (file_scanner->next != (DynamicFileList *) NULL) { - p = file_scanner->next; - file_scanner->next = file_scanner->next->next; - pg_dlclose(file_scanner->handle); - free((char *)p); - } - } - handle_load(filename, (char *) NULL); + DynamicFileList *file_scanner, + *p; + struct stat stat_buf; + + int done = 0; + + if (stat(filename, &stat_buf) == -1) + { + elog(WARN, "stat failed on file %s", filename); + } + + if (file_list != (DynamicFileList *) NULL + && !NOT_EQUAL(stat_buf, *file_list)) + { + file_scanner = file_list; + file_list = file_list->next; + pg_dlclose(file_scanner->handle); + free((char *) file_scanner); + } + else if (file_list != (DynamicFileList *) NULL) + { + file_scanner = file_list; + while (!done) + { + if (file_scanner->next == (DynamicFileList *) NULL) + { + done = 1; + } + else if (!NOT_EQUAL(stat_buf, *(file_scanner->next))) + { + done = 1; + } + else + { + file_scanner = file_scanner->next; + } + } + + if (file_scanner->next != (DynamicFileList *) NULL) + { + p = file_scanner->next; + file_scanner->next = file_scanner->next->next; + pg_dlclose(file_scanner->handle); + free((char *) p); + } + } + handle_load(filename, (char *) NULL); } func_ptr -trigger_dynamic (char *filename, char *funcname) +trigger_dynamic(char *filename, char *funcname) { - func_ptr trigger_fn; - - trigger_fn = handle_load (filename, funcname); - - return (trigger_fn); + func_ptr trigger_fn; + + trigger_fn = handle_load(filename, funcname); + + return (trigger_fn); } diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 1da0ab18773..f7d7b29d0a6 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fmgr.c-- - * Interface routines for the table-driven function manager. + * Interface routines for the table-driven function manager. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.3 1997/08/19 21:35:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.4 1997/09/07 04:53:30 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include "postgres.h" /* these 2 files are generated by Gen_fmgrtab.sh; contain the declarations */ -#include "fmgr.h" +#include "fmgr.h" #include "utils/fmgrtab.h" #include "nodes/pg_list.h" @@ -29,173 +29,183 @@ #include "utils/elog.h" -char * +char * fmgr_c(func_ptr user_fn, - Oid func_id, - int n_arguments, - FmgrValues *values, - bool *isNull) + Oid func_id, + int n_arguments, + FmgrValues * values, + bool * isNull) { - char *returnValue = (char *) NULL; + char *returnValue = (char *) NULL; - - if (user_fn == (func_ptr) NULL) { - /* - * a NULL func_ptr denotes untrusted function (in postgres 4.2). - * Untrusted functions have very limited use and is clumsy. We - * just get rid of it. - */ - elog(WARN, "internal error: untrusted function not supported."); - } - - switch (n_arguments) { - case 0: - returnValue = (*user_fn)(); - break; - case 1: - /* NullValue() uses isNull to check if args[0] is NULL */ - returnValue = (*user_fn)(values->data[0], isNull); - break; - case 2: - returnValue = (*user_fn)(values->data[0], values->data[1]); - break; - case 3: - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2]); - break; - case 4: - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2], values->data[3]); - break; - case 5: - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2], values->data[3], - values->data[4]); - break; - case 6: - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2], values->data[3], - values->data[4], values->data[5]); - break; - case 7: - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2], values->data[3], - values->data[4], values->data[5], - values->data[6]); - break; - case 8: - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2], values->data[3], - values->data[4], values->data[5], - values->data[6], values->data[7]); - break; - case 9: - /* - * XXX Note that functions with >8 arguments can only be - * called from inside the system, not from the user level, - * since the catalogs only store 8 argument types for user - * type-checking! - */ - returnValue = (*user_fn)(values->data[0], values->data[1], - values->data[2], values->data[3], - values->data[4], values->data[5], - values->data[6], values->data[7], - values->data[8]); - break; - default: - elog(WARN, "fmgr_c: function %d: too many arguments (%d > %d)", - func_id, n_arguments, MAXFMGRARGS); - break; - } - return(returnValue); + + if (user_fn == (func_ptr) NULL) + { + + /* + * a NULL func_ptr denotes untrusted function (in postgres 4.2). + * Untrusted functions have very limited use and is clumsy. We + * just get rid of it. + */ + elog(WARN, "internal error: untrusted function not supported."); + } + + switch (n_arguments) + { + case 0: + returnValue = (*user_fn) (); + break; + case 1: + /* NullValue() uses isNull to check if args[0] is NULL */ + returnValue = (*user_fn) (values->data[0], isNull); + break; + case 2: + returnValue = (*user_fn) (values->data[0], values->data[1]); + break; + case 3: + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2]); + break; + case 4: + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2], values->data[3]); + break; + case 5: + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2], values->data[3], + values->data[4]); + break; + case 6: + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2], values->data[3], + values->data[4], values->data[5]); + break; + case 7: + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2], values->data[3], + values->data[4], values->data[5], + values->data[6]); + break; + case 8: + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2], values->data[3], + values->data[4], values->data[5], + values->data[6], values->data[7]); + break; + case 9: + + /* + * XXX Note that functions with >8 arguments can only be called + * from inside the system, not from the user level, since the + * catalogs only store 8 argument types for user type-checking! + */ + returnValue = (*user_fn) (values->data[0], values->data[1], + values->data[2], values->data[3], + values->data[4], values->data[5], + values->data[6], values->data[7], + values->data[8]); + break; + default: + elog(WARN, "fmgr_c: function %d: too many arguments (%d > %d)", + func_id, n_arguments, MAXFMGRARGS); + break; + } + return (returnValue); } void -fmgr_info(Oid procedureId, func_ptr *function, int *nargs) +fmgr_info(Oid procedureId, func_ptr * function, int *nargs) { - func_ptr user_fn = NULL; - FmgrCall *fcp; - HeapTuple procedureTuple; - FormData_pg_proc *procedureStruct; - Oid language; - - if (!(fcp = fmgr_isbuiltin(procedureId))) { - procedureTuple = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(procedureId), - 0,0,0); - if (!HeapTupleIsValid(procedureTuple)) { - elog(WARN, "fmgr_info: function %d: cache lookup failed\n", - procedureId); + func_ptr user_fn = NULL; + FmgrCall *fcp; + HeapTuple procedureTuple; + FormData_pg_proc *procedureStruct; + Oid language; + + if (!(fcp = fmgr_isbuiltin(procedureId))) + { + procedureTuple = SearchSysCacheTuple(PROOID, + ObjectIdGetDatum(procedureId), + 0, 0, 0); + if (!HeapTupleIsValid(procedureTuple)) + { + elog(WARN, "fmgr_info: function %d: cache lookup failed\n", + procedureId); + } + procedureStruct = (FormData_pg_proc *) + GETSTRUCT(procedureTuple); + if (!procedureStruct->proistrusted) + { + *function = (func_ptr) NULL; + *nargs = procedureStruct->pronargs; + return; + } + language = procedureStruct->prolang; + switch (language) + { + case INTERNALlanguageId: + user_fn = fmgr_lookupByName(procedureStruct->proname.data); + if (!user_fn) + elog(WARN, "fmgr_info: function %s: not in internal table", + procedureStruct->proname.data); + break; + case ClanguageId: + user_fn = fmgr_dynamic(procedureId, nargs); + break; + case SQLlanguageId: + user_fn = (func_ptr) NULL; + *nargs = procedureStruct->pronargs; + break; + default: + elog(WARN, "fmgr_info: function %d: unknown language %d", + procedureId, language); + } } - procedureStruct = (FormData_pg_proc *) - GETSTRUCT(procedureTuple); - if (!procedureStruct->proistrusted) { - *function = (func_ptr) NULL; - *nargs = procedureStruct->pronargs; - return; + else + { + user_fn = fcp->func; + *nargs = fcp->nargs; } - language = procedureStruct->prolang; - switch (language) { - case INTERNALlanguageId: - user_fn = fmgr_lookupByName(procedureStruct->proname.data); - if (!user_fn) - elog(WARN, "fmgr_info: function %s: not in internal table", - procedureStruct->proname.data); - break; - case ClanguageId: - user_fn = fmgr_dynamic(procedureId, nargs); - break; - case SQLlanguageId: - user_fn = (func_ptr) NULL; - *nargs = procedureStruct->pronargs; - break; - default: - elog(WARN, "fmgr_info: function %d: unknown language %d", - procedureId, language); - } - } else { - user_fn = fcp->func; - *nargs = fcp->nargs; - } - *function = user_fn; + *function = user_fn; } /* - * fmgr - return the value of a function call + * fmgr - return the value of a function call * - * If the function is a system routine, it's compiled in, so call - * it directly. + * If the function is a system routine, it's compiled in, so call + * it directly. * - * Otherwise pass it to the the appropriate 'language' function caller. + * Otherwise pass it to the the appropriate 'language' function caller. * - * Returns the return value of the invoked function if succesful, - * 0 if unsuccessful. + * Returns the return value of the invoked function if succesful, + * 0 if unsuccessful. */ -char * -fmgr(Oid procedureId, ... ) +char * +fmgr(Oid procedureId,...) { - va_list pvar; - register i; - int pronargs; - FmgrValues values; - func_ptr user_fn; - bool isNull = false; - - va_start(pvar, procedureId); - - fmgr_info(procedureId, &user_fn, &pronargs); - - if (pronargs > MAXFMGRARGS) { - elog(WARN, "fmgr: function %d: too many arguments (%d > %d)", - procedureId, pronargs, MAXFMGRARGS); - } - for (i = 0; i < pronargs; ++i) - values.data[i] = va_arg(pvar, char *); - va_end(pvar); - - /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ - return(fmgr_c(user_fn, procedureId, pronargs, &values, - &isNull)); + va_list pvar; + register i; + int pronargs; + FmgrValues values; + func_ptr user_fn; + bool isNull = false; + + va_start(pvar, procedureId); + + fmgr_info(procedureId, &user_fn, &pronargs); + + if (pronargs > MAXFMGRARGS) + { + elog(WARN, "fmgr: function %d: too many arguments (%d > %d)", + procedureId, pronargs, MAXFMGRARGS); + } + for (i = 0; i < pronargs; ++i) + values.data[i] = va_arg(pvar, char *); + va_end(pvar); + + /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ + return (fmgr_c(user_fn, procedureId, pronargs, &values, + &isNull)); } /* @@ -204,33 +214,35 @@ fmgr(Oid procedureId, ... ) * if you have all of this information you're likely to just jump through * the pointer, but it's available for use with macros in fmgr.h if you * want this routine to do sanity-checking for you. - * + * * func_ptr, func_id, n_arguments, args... */ #ifdef NOT_USED -char * -fmgr_ptr(func_ptr user_fn, Oid func_id, ...) +char * +fmgr_ptr(func_ptr user_fn, Oid func_id,...) { - va_list pvar; - register i; - int n_arguments; - FmgrValues values; - bool isNull = false; - - va_start(pvar, func_id); - n_arguments = va_arg(pvar, int); - if (n_arguments > MAXFMGRARGS) { - elog(WARN, "fmgr_ptr: function %d: too many arguments (%d > %d)", - func_id, n_arguments, MAXFMGRARGS); - } - for (i = 0; i < n_arguments; ++i) - values.data[i] = va_arg(pvar, char *); - va_end(pvar); - - /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ - return(fmgr_c(user_fn, func_id, n_arguments, &values, - &isNull)); + va_list pvar; + register i; + int n_arguments; + FmgrValues values; + bool isNull = false; + + va_start(pvar, func_id); + n_arguments = va_arg(pvar, int); + if (n_arguments > MAXFMGRARGS) + { + elog(WARN, "fmgr_ptr: function %d: too many arguments (%d > %d)", + func_id, n_arguments, MAXFMGRARGS); + } + for (i = 0; i < n_arguments; ++i) + values.data[i] = va_arg(pvar, char *); + va_end(pvar); + + /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ + return (fmgr_c(user_fn, func_id, n_arguments, &values, + &isNull)); } + #endif /* @@ -238,19 +250,19 @@ fmgr_ptr(func_ptr user_fn, Oid func_id, ...) * function pointer field to FuncIndexInfo, it will be replace by calls * to fmgr_c(). */ -char * -fmgr_array_args(Oid procedureId, int nargs, char *args[], bool *isNull) +char * +fmgr_array_args(Oid procedureId, int nargs, char *args[], bool * isNull) { - func_ptr user_fn; - int true_arguments; - - fmgr_info(procedureId, &user_fn, &true_arguments); - - /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ - return - (fmgr_c(user_fn, - procedureId, - true_arguments, - (FmgrValues*)args, - isNull)); + func_ptr user_fn; + int true_arguments; + + fmgr_info(procedureId, &user_fn, &true_arguments); + + /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ + return + (fmgr_c(user_fn, + procedureId, + true_arguments, + (FmgrValues *) args, + isNull)); } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index db209e1c338..736ca39d09f 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * dynahash.c-- - * dynamic hashing + * dynamic hashing * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.7 1997/08/12 22:54:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.8 1997/09/07 04:53:33 momjian Exp $ * *------------------------------------------------------------------------- */ /* - * + * * Dynamic hashing, after CACM April 1988 pp 446-457, by Per-Ake Larson. * Coded into C, with minor code improvements, and with hsearch(3) interface, * by ejp@ausmelb.oz, Jul 26, 1988: 13:16; @@ -35,27 +35,27 @@ * concatenation property, in probably unnecessary code 'optimisation'. * * Modified margo@postgres.berkeley.edu February 1990 - * added multiple table interface + * added multiple table interface * Modified by sullivan@postgres.berkeley.edu April 1990 - * changed ctl structure for shared memory + * changed ctl structure for shared memory */ -# include <stdio.h> -# include <sys/types.h> -# include <string.h> -# include "postgres.h" -# include "utils/dynahash.h" -# include "utils/hsearch.h" +#include <stdio.h> +#include <sys/types.h> +#include <string.h> +#include "postgres.h" +#include "utils/dynahash.h" +#include "utils/hsearch.h" #ifndef FRONTEND -# include "utils/mcxt.h" -#endif /* !FRONTEND */ -# include "utils/palloc.h" +#include "utils/mcxt.h" +#endif /* !FRONTEND */ +#include "utils/palloc.h" /* * Fast arithmetic, relying on powers of 2, * and on pre-processor concatenation property */ -# define MOD(x,y) ((x) & ((y)-1)) +#define MOD(x,y) ((x) & ((y)-1)) /* * external routines @@ -64,14 +64,14 @@ /* * Private function prototypes */ -static long *DynaHashAlloc(unsigned int size); -static void DynaHashFree(Pointer ptr); -static uint32 call_hash(HTAB *hashp, char *k, int len); -static SEG_OFFSET seg_alloc(HTAB *hashp); -static int bucket_alloc(HTAB *hashp); -static int dir_realloc(HTAB *hashp); +static long *DynaHashAlloc(unsigned int size); +static void DynaHashFree(Pointer ptr); +static uint32 call_hash(HTAB * hashp, char *k, int len); +static SEG_OFFSET seg_alloc(HTAB * hashp); +static int bucket_alloc(HTAB * hashp); +static int dir_realloc(HTAB * hashp); -typedef long * ((*dhalloc_ptr)()); +typedef long *((*dhalloc_ptr) ()); #ifndef FRONTEND /* ---------------- @@ -82,54 +82,54 @@ typedef long * ((*dhalloc_ptr)()); * garbage collector is going to corrupt them. -wei * * ??? the "cache" memory context is intended to store only - * system cache information. The user of the hashing - * routines should specify which context to use or we - * should create a separate memory context for these - * hash routines. For now I have modified this code to - * do the latter -cim 1/19/91 + * system cache information. The user of the hashing + * routines should specify which context to use or we + * should create a separate memory context for these + * hash routines. For now I have modified this code to + * do the latter -cim 1/19/91 * ---------------- */ -GlobalMemory DynaHashCxt = (GlobalMemory) NULL; +GlobalMemory DynaHashCxt = (GlobalMemory) NULL; -static long * +static long * DynaHashAlloc(unsigned int size) { - if (! DynaHashCxt) - DynaHashCxt = CreateGlobalMemory("DynaHash"); + if (!DynaHashCxt) + DynaHashCxt = CreateGlobalMemory("DynaHash"); - return (long *) - MemoryContextAlloc((MemoryContext)DynaHashCxt, size); + return (long *) + MemoryContextAlloc((MemoryContext) DynaHashCxt, size); } static void DynaHashFree(Pointer ptr) { - MemoryContextFree((MemoryContext)DynaHashCxt, ptr); + MemoryContextFree((MemoryContext) DynaHashCxt, ptr); } -#define MEM_ALLOC DynaHashAlloc -#define MEM_FREE DynaHashFree +#define MEM_ALLOC DynaHashAlloc +#define MEM_FREE DynaHashFree -#else /* FRONTEND */ +#else /* FRONTEND */ -#define MEM_ALLOC palloc -#define MEM_FREE pfree +#define MEM_ALLOC palloc +#define MEM_FREE pfree -#endif /* FRONTEND */ +#endif /* FRONTEND */ /* ---------------- * Internal routines * ---------------- */ -static int expand_table(HTAB *hashp); -static int hdefault(HTAB *hashp); -static int init_htab(HTAB *hashp, int nelem); +static int expand_table(HTAB * hashp); +static int hdefault(HTAB * hashp); +static int init_htab(HTAB * hashp, int nelem); /* * pointer access macros. Shared memory implementation cannot - * store pointers in the hash table data structures because + * store pointers in the hash table data structures because * pointer values will be different in different address spaces. * these macros convert offsets to pointers and pointers to offsets. * Shared memory need not be contiguous, but all addresses must be @@ -145,282 +145,318 @@ static int init_htab(HTAB *hashp, int nelem); #define MAKE_HASHOFFSET(hp,ptr)\ ( ((unsigned long) ptr) - ((unsigned long) (hp)->segbase) ) -# if HASH_STATISTICS -static long hash_accesses, hash_collisions, hash_expansions; -# endif +#if HASH_STATISTICS +static long hash_accesses, + hash_collisions, + hash_expansions; + +#endif /************************** CREATE ROUTINES **********************/ -HTAB * -hash_create(int nelem, HASHCTL *info, int flags) +HTAB * +hash_create(int nelem, HASHCTL * info, int flags) { - register HHDR * hctl; - HTAB * hashp; - - - hashp = (HTAB *) MEM_ALLOC((unsigned long) sizeof(HTAB)); - memset(hashp, 0, sizeof(HTAB)); - - if ( flags & HASH_FUNCTION ) { - hashp->hash = info->hash; - } else { - /* default */ - hashp->hash = string_hash; - } - - if ( flags & HASH_SHARED_MEM ) { - /* ctl structure is preallocated for shared memory tables */ - - hashp->hctl = (HHDR *) info->hctl; - hashp->segbase = (char *) info->segbase; - hashp->alloc = info->alloc; - hashp->dir = (SEG_OFFSET *)info->dir; - - /* hash table already exists, we're just attaching to it */ - if (flags & HASH_ATTACH) { - return(hashp); + register HHDR *hctl; + HTAB *hashp; + + + hashp = (HTAB *) MEM_ALLOC((unsigned long) sizeof(HTAB)); + memset(hashp, 0, sizeof(HTAB)); + + if (flags & HASH_FUNCTION) + { + hashp->hash = info->hash; + } + else + { + /* default */ + hashp->hash = string_hash; + } + + if (flags & HASH_SHARED_MEM) + { + /* ctl structure is preallocated for shared memory tables */ + + hashp->hctl = (HHDR *) info->hctl; + hashp->segbase = (char *) info->segbase; + hashp->alloc = info->alloc; + hashp->dir = (SEG_OFFSET *) info->dir; + + /* hash table already exists, we're just attaching to it */ + if (flags & HASH_ATTACH) + { + return (hashp); + } + + } + else + { + /* setup hash table defaults */ + + hashp->alloc = (dhalloc_ptr) MEM_ALLOC; + hashp->dir = NULL; + hashp->segbase = NULL; + } - - } else { - /* setup hash table defaults */ - - hashp->alloc = (dhalloc_ptr) MEM_ALLOC; - hashp->dir = NULL; - hashp->segbase = NULL; - - } - - if (! hashp->hctl) { - hashp->hctl = (HHDR *) hashp->alloc((unsigned long)sizeof(HHDR)); - if (! hashp->hctl) { - return(0); + + if (!hashp->hctl) + { + hashp->hctl = (HHDR *) hashp->alloc((unsigned long) sizeof(HHDR)); + if (!hashp->hctl) + { + return (0); + } } - } - - if ( !hdefault(hashp) ) return(0); - hctl = hashp->hctl; + + if (!hdefault(hashp)) + return (0); + hctl = hashp->hctl; #ifdef HASH_STATISTICS - hctl->accesses = hctl->collisions = 0; + hctl->accesses = hctl->collisions = 0; #endif - - if ( flags & HASH_BUCKET ) { - hctl->bsize = info->bsize; - hctl->bshift = my_log2(info->bsize); - } - if ( flags & HASH_SEGMENT ) { - hctl->ssize = info->ssize; - hctl->sshift = my_log2(info->ssize); - } - if ( flags & HASH_FFACTOR ) { - hctl->ffactor = info->ffactor; - } - - /* - * SHM hash tables have fixed maximum size (allocate - * a maximal sized directory). - */ - if ( flags & HASH_DIRSIZE ) { - hctl->max_dsize = my_log2(info->max_size); - hctl->dsize = my_log2(info->dsize); - } - /* hash table now allocates space for key and data - * but you have to say how much space to allocate - */ - if ( flags & HASH_ELEM ) { - hctl->keysize = info->keysize; - hctl->datasize = info->datasize; - } - if ( flags & HASH_ALLOC ) { - hashp->alloc = info->alloc; - } - - if ( init_htab (hashp, nelem ) ) { - hash_destroy(hashp); - return(0); - } - return(hashp); + + if (flags & HASH_BUCKET) + { + hctl->bsize = info->bsize; + hctl->bshift = my_log2(info->bsize); + } + if (flags & HASH_SEGMENT) + { + hctl->ssize = info->ssize; + hctl->sshift = my_log2(info->ssize); + } + if (flags & HASH_FFACTOR) + { + hctl->ffactor = info->ffactor; + } + + /* + * SHM hash tables have fixed maximum size (allocate a maximal sized + * directory). + */ + if (flags & HASH_DIRSIZE) + { + hctl->max_dsize = my_log2(info->max_size); + hctl->dsize = my_log2(info->dsize); + } + + /* + * hash table now allocates space for key and data but you have to say + * how much space to allocate + */ + if (flags & HASH_ELEM) + { + hctl->keysize = info->keysize; + hctl->datasize = info->datasize; + } + if (flags & HASH_ALLOC) + { + hashp->alloc = info->alloc; + } + + if (init_htab(hashp, nelem)) + { + hash_destroy(hashp); + return (0); + } + return (hashp); } /* - Allocate and initialize an HTAB structure + Allocate and initialize an HTAB structure */ static int -hdefault(HTAB *hashp) +hdefault(HTAB * hashp) { - HHDR *hctl; - - memset(hashp->hctl, 0, sizeof(HHDR)); - - hctl = hashp->hctl; - hctl->bsize = DEF_BUCKET_SIZE; - hctl->bshift = DEF_BUCKET_SHIFT; - hctl->ssize = DEF_SEGSIZE; - hctl->sshift = DEF_SEGSIZE_SHIFT; - hctl->dsize = DEF_DIRSIZE; - hctl->ffactor = DEF_FFACTOR; - hctl->nkeys = 0; - hctl->nsegs = 0; - - /* I added these MS. */ - - /* default memory allocation for hash buckets */ - hctl->keysize = sizeof(char *); - hctl->datasize = sizeof(char *); - - /* table has no fixed maximum size */ - hctl->max_dsize = NO_MAX_DSIZE; - - /* garbage collection for HASH_REMOVE */ - hctl->freeBucketIndex = INVALID_INDEX; - - return(1); + HHDR *hctl; + + memset(hashp->hctl, 0, sizeof(HHDR)); + + hctl = hashp->hctl; + hctl->bsize = DEF_BUCKET_SIZE; + hctl->bshift = DEF_BUCKET_SHIFT; + hctl->ssize = DEF_SEGSIZE; + hctl->sshift = DEF_SEGSIZE_SHIFT; + hctl->dsize = DEF_DIRSIZE; + hctl->ffactor = DEF_FFACTOR; + hctl->nkeys = 0; + hctl->nsegs = 0; + + /* I added these MS. */ + + /* default memory allocation for hash buckets */ + hctl->keysize = sizeof(char *); + hctl->datasize = sizeof(char *); + + /* table has no fixed maximum size */ + hctl->max_dsize = NO_MAX_DSIZE; + + /* garbage collection for HASH_REMOVE */ + hctl->freeBucketIndex = INVALID_INDEX; + + return (1); } static int -init_htab (HTAB *hashp, int nelem) +init_htab(HTAB * hashp, int nelem) { - register SEG_OFFSET *segp; - register int nbuckets; - register int nsegs; - int l2; - HHDR *hctl; - - hctl = hashp->hctl; - /* - * Divide number of elements by the fill factor and determine a desired - * number of buckets. Allocate space for the next greater power of - * two number of buckets - */ - nelem = (nelem - 1) / hctl->ffactor + 1; - - l2 = my_log2(nelem); - nbuckets = 1 << l2; - - hctl->max_bucket = hctl->low_mask = nbuckets - 1; - hctl->high_mask = (nbuckets << 1) - 1; - - nsegs = (nbuckets - 1) / hctl->ssize + 1; - nsegs = 1 << my_log2(nsegs); - - if ( nsegs > hctl->dsize ) { - hctl->dsize = nsegs; - } - - /* Use two low order bits of points ???? */ - /* - if ( !(hctl->mem = bit_alloc ( nbuckets )) ) return(-1); - if ( !(hctl->mod = bit_alloc ( nbuckets )) ) return(-1); - */ - - /* allocate a directory */ - if (!(hashp->dir)) { - hashp->dir = - (SEG_OFFSET *)hashp->alloc(hctl->dsize * sizeof(SEG_OFFSET)); - if (! hashp->dir) - return(-1); - } - - /* Allocate initial segments */ - for (segp = hashp->dir; hctl->nsegs < nsegs; hctl->nsegs++, segp++ ) { - *segp = seg_alloc(hashp); - if ( *segp == (SEG_OFFSET)0 ) { - hash_destroy(hashp); - return (0); + register SEG_OFFSET *segp; + register int nbuckets; + register int nsegs; + int l2; + HHDR *hctl; + + hctl = hashp->hctl; + + /* + * Divide number of elements by the fill factor and determine a + * desired number of buckets. Allocate space for the next greater + * power of two number of buckets + */ + nelem = (nelem - 1) / hctl->ffactor + 1; + + l2 = my_log2(nelem); + nbuckets = 1 << l2; + + hctl->max_bucket = hctl->low_mask = nbuckets - 1; + hctl->high_mask = (nbuckets << 1) - 1; + + nsegs = (nbuckets - 1) / hctl->ssize + 1; + nsegs = 1 << my_log2(nsegs); + + if (nsegs > hctl->dsize) + { + hctl->dsize = nsegs; + } + + /* Use two low order bits of points ???? */ + + /* + * if ( !(hctl->mem = bit_alloc ( nbuckets )) ) return(-1); if ( + * !(hctl->mod = bit_alloc ( nbuckets )) ) return(-1); + */ + + /* allocate a directory */ + if (!(hashp->dir)) + { + hashp->dir = + (SEG_OFFSET *) hashp->alloc(hctl->dsize * sizeof(SEG_OFFSET)); + if (!hashp->dir) + return (-1); + } + + /* Allocate initial segments */ + for (segp = hashp->dir; hctl->nsegs < nsegs; hctl->nsegs++, segp++) + { + *segp = seg_alloc(hashp); + if (*segp == (SEG_OFFSET) 0) + { + hash_destroy(hashp); + return (0); + } } - } - -# if HASH_DEBUG - fprintf(stderr, "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", - "init_htab:", - "TABLE POINTER ", hashp, - "BUCKET SIZE ", hctl->bsize, - "BUCKET SHIFT ", hctl->bshift, - "DIRECTORY SIZE ", hctl->dsize, - "SEGMENT SIZE ", hctl->ssize, - "SEGMENT SHIFT ", hctl->sshift, - "FILL FACTOR ", hctl->ffactor, - "MAX BUCKET ", hctl->max_bucket, - "HIGH MASK ", hctl->high_mask, - "LOW MASK ", hctl->low_mask, - "NSEGS ", hctl->nsegs, - "NKEYS ", hctl->nkeys ); -# endif - return (0); + +#if HASH_DEBUG + fprintf(stderr, "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", + "init_htab:", + "TABLE POINTER ", hashp, + "BUCKET SIZE ", hctl->bsize, + "BUCKET SHIFT ", hctl->bshift, + "DIRECTORY SIZE ", hctl->dsize, + "SEGMENT SIZE ", hctl->ssize, + "SEGMENT SHIFT ", hctl->sshift, + "FILL FACTOR ", hctl->ffactor, + "MAX BUCKET ", hctl->max_bucket, + "HIGH MASK ", hctl->high_mask, + "LOW MASK ", hctl->low_mask, + "NSEGS ", hctl->nsegs, + "NKEYS ", hctl->nkeys); +#endif + return (0); } /********************** DESTROY ROUTINES ************************/ void -hash_destroy (HTAB *hashp) +hash_destroy(HTAB * hashp) { - /* cannot destroy a shared memory hash table */ - Assert(! hashp->segbase); - - if (hashp != NULL) { - register SEG_OFFSET segNum; - SEGMENT segp; - int nsegs = hashp->hctl->nsegs; - int j; - BUCKET_INDEX *elp,p,q; - ELEMENT *curr; - - for (segNum = 0; nsegs > 0; nsegs--, segNum++) { - - segp = GET_SEG(hashp,segNum); - for (j = 0, elp = segp; j < hashp->hctl->ssize; j++, elp++) { - for ( p = *elp; p != INVALID_INDEX; p = q ){ - curr = GET_BUCKET(hashp,p); - q = curr->next; - MEM_FREE((char *) curr); + /* cannot destroy a shared memory hash table */ + Assert(!hashp->segbase); + + if (hashp != NULL) + { + register SEG_OFFSET segNum; + SEGMENT segp; + int nsegs = hashp->hctl->nsegs; + int j; + BUCKET_INDEX *elp, + p, + q; + ELEMENT *curr; + + for (segNum = 0; nsegs > 0; nsegs--, segNum++) + { + + segp = GET_SEG(hashp, segNum); + for (j = 0, elp = segp; j < hashp->hctl->ssize; j++, elp++) + { + for (p = *elp; p != INVALID_INDEX; p = q) + { + curr = GET_BUCKET(hashp, p); + q = curr->next; + MEM_FREE((char *) curr); + } + } + free((char *) segp); } - } - free((char *)segp); + MEM_FREE((char *) hashp->dir); + MEM_FREE((char *) hashp->hctl); + hash_stats("destroy", hashp); + MEM_FREE((char *) hashp); } - MEM_FREE( (char *) hashp->dir); - MEM_FREE( (char *) hashp->hctl); - hash_stats("destroy",hashp); - MEM_FREE( (char *) hashp); - } } void -hash_stats(char *where, HTAB *hashp) +hash_stats(char *where, HTAB * hashp) { -# if HASH_STATISTICS - - fprintf(stderr,"%s: this HTAB -- accesses %ld collisions %ld\n", - where,hashp->hctl->accesses,hashp->hctl->collisions); - - fprintf(stderr,"hash_stats: keys %ld keysize %ld maxp %d segmentcount %d\n", - hashp->hctl->nkeys, hashp->hctl->keysize, - hashp->hctl->max_bucket, hashp->hctl->nsegs); - fprintf(stderr,"%s: total accesses %ld total collisions %ld\n", - where, hash_accesses, hash_collisions); - fprintf(stderr,"hash_stats: total expansions %ld\n", - hash_expansions); - -# endif - +#if HASH_STATISTICS + + fprintf(stderr, "%s: this HTAB -- accesses %ld collisions %ld\n", + where, hashp->hctl->accesses, hashp->hctl->collisions); + + fprintf(stderr, "hash_stats: keys %ld keysize %ld maxp %d segmentcount %d\n", + hashp->hctl->nkeys, hashp->hctl->keysize, + hashp->hctl->max_bucket, hashp->hctl->nsegs); + fprintf(stderr, "%s: total accesses %ld total collisions %ld\n", + where, hash_accesses, hash_collisions); + fprintf(stderr, "hash_stats: total expansions %ld\n", + hash_expansions); + +#endif + } /*******************************SEARCH ROUTINES *****************************/ -static uint32 -call_hash(HTAB *hashp, char *k, int len) +static uint32 +call_hash(HTAB * hashp, char *k, int len) { - long hash_val, bucket; - HHDR *hctl; - - hctl = hashp->hctl; - hash_val = hashp->hash(k, len); - - bucket = hash_val & hctl->high_mask; - if ( bucket > hctl->max_bucket ) { - bucket = bucket & hctl->low_mask; - } - - return(bucket); + long hash_val, + bucket; + HHDR *hctl; + + hctl = hashp->hctl; + hash_val = hashp->hash(k, len); + + bucket = hash_val & hctl->high_mask; + if (bucket > hctl->max_bucket) + { + bucket = bucket & hctl->low_mask; + } + + return (bucket); } /* @@ -429,430 +465,462 @@ call_hash(HTAB *hashp, char *k, int len) * action is one of HASH_FIND/HASH_ENTER/HASH_REMOVE * * RETURNS: NULL if table is corrupted, a pointer to the element - * found/removed/entered if applicable, TRUE otherwise. - * foundPtr is TRUE if we found an element in the table - * (FALSE if we entered one). + * found/removed/entered if applicable, TRUE otherwise. + * foundPtr is TRUE if we found an element in the table + * (FALSE if we entered one). */ -long * -hash_search(HTAB *hashp, - char *keyPtr, - HASHACTION action, /* - * HASH_FIND / HASH_ENTER / HASH_REMOVE - * HASH_FIND_SAVE / HASH_REMOVE_SAVED - */ - bool *foundPtr) +long * +hash_search(HTAB * hashp, + char *keyPtr, + HASHACTION action, /* HASH_FIND / HASH_ENTER / HASH_REMOVE + * HASH_FIND_SAVE / HASH_REMOVE_SAVED */ + bool * foundPtr) { - uint32 bucket; - long segment_num; - long segment_ndx; - SEGMENT segp; - register ELEMENT *curr; - HHDR *hctl; - BUCKET_INDEX currIndex; - BUCKET_INDEX *prevIndexPtr; - char * destAddr; - static struct State { - ELEMENT *currElem; - BUCKET_INDEX currIndex; - BUCKET_INDEX *prevIndex; - } saveState; - - Assert((hashp && keyPtr)); - Assert((action == HASH_FIND) || (action == HASH_REMOVE) || (action == HASH_ENTER) || (action == HASH_FIND_SAVE) || (action == HASH_REMOVE_SAVED)); - - hctl = hashp->hctl; - -# if HASH_STATISTICS - hash_accesses++; - hashp->hctl->accesses++; -# endif - if (action == HASH_REMOVE_SAVED) - { - curr = saveState.currElem; - currIndex = saveState.currIndex; - prevIndexPtr = saveState.prevIndex; - /* - * Try to catch subsequent errors - */ - Assert(saveState.currElem && !(saveState.currElem = 0)); + uint32 bucket; + long segment_num; + long segment_ndx; + SEGMENT segp; + register ELEMENT *curr; + HHDR *hctl; + BUCKET_INDEX currIndex; + BUCKET_INDEX *prevIndexPtr; + char *destAddr; + static struct State + { + ELEMENT *currElem; + BUCKET_INDEX currIndex; + BUCKET_INDEX *prevIndex; + } saveState; + + Assert((hashp && keyPtr)); + Assert((action == HASH_FIND) || (action == HASH_REMOVE) || (action == HASH_ENTER) || (action == HASH_FIND_SAVE) || (action == HASH_REMOVE_SAVED)); + + hctl = hashp->hctl; + +#if HASH_STATISTICS + hash_accesses++; + hashp->hctl->accesses++; +#endif + if (action == HASH_REMOVE_SAVED) + { + curr = saveState.currElem; + currIndex = saveState.currIndex; + prevIndexPtr = saveState.prevIndex; + + /* + * Try to catch subsequent errors + */ + Assert(saveState.currElem && !(saveState.currElem = 0)); } - else - { - bucket = call_hash(hashp, keyPtr, hctl->keysize); - segment_num = bucket >> hctl->sshift; - segment_ndx = bucket & ( hctl->ssize - 1 ); - - segp = GET_SEG(hashp,segment_num); - - Assert(segp); - - prevIndexPtr = &segp[segment_ndx]; - currIndex = *prevIndexPtr; - /* - * Follow collision chain - */ - for (curr = NULL;currIndex != INVALID_INDEX;) { - /* coerce bucket index into a pointer */ - curr = GET_BUCKET(hashp,currIndex); - - if (! memcmp((char *)&(curr->key), keyPtr, hctl->keysize)) { - break; - } - prevIndexPtr = &(curr->next); + else + { + bucket = call_hash(hashp, keyPtr, hctl->keysize); + segment_num = bucket >> hctl->sshift; + segment_ndx = bucket & (hctl->ssize - 1); + + segp = GET_SEG(hashp, segment_num); + + Assert(segp); + + prevIndexPtr = &segp[segment_ndx]; currIndex = *prevIndexPtr; -# if HASH_STATISTICS - hash_collisions++; - hashp->hctl->collisions++; -# endif - } - } - - /* - * if we found an entry or if we weren't trying - * to insert, we're done now. - */ - *foundPtr = (bool) (currIndex != INVALID_INDEX); - switch (action) { - case HASH_ENTER: - if (currIndex != INVALID_INDEX) - return(&(curr->key)); - break; - case HASH_REMOVE: - case HASH_REMOVE_SAVED: - if (currIndex != INVALID_INDEX) { - Assert(hctl->nkeys > 0); - hctl->nkeys--; - - /* add the bucket to the freelist for this table. */ - *prevIndexPtr = curr->next; - curr->next = hctl->freeBucketIndex; - hctl->freeBucketIndex = currIndex; - - /* better hope the caller is synchronizing access to - * this element, because someone else is going to reuse - * it the next time something is added to the table - */ - return (&(curr->key)); + + /* + * Follow collision chain + */ + for (curr = NULL; currIndex != INVALID_INDEX;) + { + /* coerce bucket index into a pointer */ + curr = GET_BUCKET(hashp, currIndex); + + if (!memcmp((char *) &(curr->key), keyPtr, hctl->keysize)) + { + break; + } + prevIndexPtr = &(curr->next); + currIndex = *prevIndexPtr; +#if HASH_STATISTICS + hash_collisions++; + hashp->hctl->collisions++; +#endif + } } - return((long *) TRUE); - case HASH_FIND: - if (currIndex != INVALID_INDEX) - return(&(curr->key)); - return((long *)TRUE); - case HASH_FIND_SAVE: - if (currIndex != INVALID_INDEX) - { - saveState.currElem = curr; - saveState.prevIndex = prevIndexPtr; - saveState.currIndex = currIndex; - return(&(curr->key)); - } - return((long *)TRUE); - default: - /* can't get here */ - return (NULL); - } - - /* - If we got here, then we didn't find the element and - we have to insert it into the hash table - */ - Assert(currIndex == INVALID_INDEX); - - /* get the next free bucket */ - currIndex = hctl->freeBucketIndex; - if (currIndex == INVALID_INDEX) { - - /* no free elements. allocate another chunk of buckets */ - if (! bucket_alloc(hashp)) { - return(NULL); + + /* + * if we found an entry or if we weren't trying to insert, we're done + * now. + */ + *foundPtr = (bool) (currIndex != INVALID_INDEX); + switch (action) + { + case HASH_ENTER: + if (currIndex != INVALID_INDEX) + return (&(curr->key)); + break; + case HASH_REMOVE: + case HASH_REMOVE_SAVED: + if (currIndex != INVALID_INDEX) + { + Assert(hctl->nkeys > 0); + hctl->nkeys--; + + /* add the bucket to the freelist for this table. */ + *prevIndexPtr = curr->next; + curr->next = hctl->freeBucketIndex; + hctl->freeBucketIndex = currIndex; + + /* + * better hope the caller is synchronizing access to this + * element, because someone else is going to reuse it the next + * time something is added to the table + */ + return (&(curr->key)); + } + return ((long *) TRUE); + case HASH_FIND: + if (currIndex != INVALID_INDEX) + return (&(curr->key)); + return ((long *) TRUE); + case HASH_FIND_SAVE: + if (currIndex != INVALID_INDEX) + { + saveState.currElem = curr; + saveState.prevIndex = prevIndexPtr; + saveState.currIndex = currIndex; + return (&(curr->key)); + } + return ((long *) TRUE); + default: + /* can't get here */ + return (NULL); } + + /* + * If we got here, then we didn't find the element and we have to + * insert it into the hash table + */ + Assert(currIndex == INVALID_INDEX); + + /* get the next free bucket */ currIndex = hctl->freeBucketIndex; - } - Assert(currIndex != INVALID_INDEX); - - curr = GET_BUCKET(hashp,currIndex); - hctl->freeBucketIndex = curr->next; - - /* link into chain */ - *prevIndexPtr = currIndex; - - /* copy key and data */ - destAddr = (char *) &(curr->key); - memmove(destAddr,keyPtr,hctl->keysize); - curr->next = INVALID_INDEX; - - /* let the caller initialize the data field after - * hash_search returns. - */ - /* memmove(destAddr,keyPtr,hctl->keysize+hctl->datasize);*/ - - /* - * Check if it is time to split the segment - */ - if (++hctl->nkeys / (hctl->max_bucket+1) > hctl->ffactor) { + if (currIndex == INVALID_INDEX) + { + + /* no free elements. allocate another chunk of buckets */ + if (!bucket_alloc(hashp)) + { + return (NULL); + } + currIndex = hctl->freeBucketIndex; + } + Assert(currIndex != INVALID_INDEX); + + curr = GET_BUCKET(hashp, currIndex); + hctl->freeBucketIndex = curr->next; + + /* link into chain */ + *prevIndexPtr = currIndex; + + /* copy key and data */ + destAddr = (char *) &(curr->key); + memmove(destAddr, keyPtr, hctl->keysize); + curr->next = INVALID_INDEX; + /* - fprintf(stderr,"expanding on '%s'\n",keyPtr); - hash_stats("expanded table",hashp); - */ - if (! expand_table(hashp)) - return(NULL); - } - return (&(curr->key)); + * let the caller initialize the data field after hash_search returns. + */ + /* memmove(destAddr,keyPtr,hctl->keysize+hctl->datasize); */ + + /* + * Check if it is time to split the segment + */ + if (++hctl->nkeys / (hctl->max_bucket + 1) > hctl->ffactor) + { + + /* + * fprintf(stderr,"expanding on '%s'\n",keyPtr); + * hash_stats("expanded table",hashp); + */ + if (!expand_table(hashp)) + return (NULL); + } + return (&(curr->key)); } /* * hash_seq -- sequentially search through hash table and return - * all the elements one by one, return NULL on error and - * return TRUE in the end. + * all the elements one by one, return NULL on error and + * return TRUE in the end. * */ -long * -hash_seq(HTAB *hashp) +long * +hash_seq(HTAB * hashp) { - static uint32 curBucket = 0; - static BUCKET_INDEX curIndex; - ELEMENT *curElem; - long segment_num; - long segment_ndx; - SEGMENT segp; - HHDR *hctl; - - if (hashp == NULL) - { - /* - * reset static state - */ - curBucket = 0; - curIndex = INVALID_INDEX; - return((long *) NULL); + static uint32 curBucket = 0; + static BUCKET_INDEX curIndex; + ELEMENT *curElem; + long segment_num; + long segment_ndx; + SEGMENT segp; + HHDR *hctl; + + if (hashp == NULL) + { + + /* + * reset static state + */ + curBucket = 0; + curIndex = INVALID_INDEX; + return ((long *) NULL); } - - hctl = hashp->hctl; - while (curBucket <= hctl->max_bucket) { - if (curIndex != INVALID_INDEX) { - curElem = GET_BUCKET(hashp, curIndex); - curIndex = curElem->next; - if (curIndex == INVALID_INDEX) /* end of this bucket */ - ++curBucket; - return(&(curElem->key)); + + hctl = hashp->hctl; + while (curBucket <= hctl->max_bucket) + { + if (curIndex != INVALID_INDEX) + { + curElem = GET_BUCKET(hashp, curIndex); + curIndex = curElem->next; + if (curIndex == INVALID_INDEX) /* end of this bucket */ + ++curBucket; + return (&(curElem->key)); + } + + /* + * initialize the search within this bucket. + */ + segment_num = curBucket >> hctl->sshift; + segment_ndx = curBucket & (hctl->ssize - 1); + + /* + * first find the right segment in the table directory. + */ + segp = GET_SEG(hashp, segment_num); + if (segp == NULL) + /* this is probably an error */ + return ((long *) NULL); + + /* + * now find the right index into the segment for the first item in + * this bucket's chain. if the bucket is not empty (its entry in + * the dir is valid), we know this must correspond to a valid + * element and not a freed element because it came out of the + * directory of valid stuff. if there are elements in the bucket + * chains that point to the freelist we're in big trouble. + */ + curIndex = segp[segment_ndx]; + + if (curIndex == INVALID_INDEX) /* empty bucket */ + ++curBucket; } - - /* - * initialize the search within this bucket. - */ - segment_num = curBucket >> hctl->sshift; - segment_ndx = curBucket & ( hctl->ssize - 1 ); - - /* - * first find the right segment in the table directory. - */ - segp = GET_SEG(hashp, segment_num); - if (segp == NULL) - /* this is probably an error */ - return((long *) NULL); - - /* - * now find the right index into the segment for the first - * item in this bucket's chain. if the bucket is not empty - * (its entry in the dir is valid), we know this must - * correspond to a valid element and not a freed element - * because it came out of the directory of valid stuff. if - * there are elements in the bucket chains that point to the - * freelist we're in big trouble. - */ - curIndex = segp[segment_ndx]; - - if (curIndex == INVALID_INDEX) /* empty bucket */ - ++curBucket; - } - - return((long *) TRUE); /* out of buckets */ + + return ((long *) TRUE); /* out of buckets */ } /********************************* UTILITIES ************************/ static int -expand_table(HTAB *hashp) +expand_table(HTAB * hashp) { - HHDR *hctl; - SEGMENT old_seg,new_seg; - long old_bucket, new_bucket; - long new_segnum, new_segndx; - long old_segnum, old_segndx; - ELEMENT *chain; - BUCKET_INDEX *old,*newbi; - register BUCKET_INDEX chainIndex,nextIndex; - + HHDR *hctl; + SEGMENT old_seg, + new_seg; + long old_bucket, + new_bucket; + long new_segnum, + new_segndx; + long old_segnum, + old_segndx; + ELEMENT *chain; + BUCKET_INDEX *old, + *newbi; + register BUCKET_INDEX chainIndex, + nextIndex; + #ifdef HASH_STATISTICS - hash_expansions++; + hash_expansions++; #endif - - hctl = hashp->hctl; - new_bucket = ++hctl->max_bucket; - old_bucket = (hctl->max_bucket & hctl->low_mask); - - new_segnum = new_bucket >> hctl->sshift; - new_segndx = MOD ( new_bucket, hctl->ssize ); - - if ( new_segnum >= hctl->nsegs ) { - - /* Allocate new segment if necessary */ - if (new_segnum >= hctl->dsize) { - dir_realloc(hashp); + + hctl = hashp->hctl; + new_bucket = ++hctl->max_bucket; + old_bucket = (hctl->max_bucket & hctl->low_mask); + + new_segnum = new_bucket >> hctl->sshift; + new_segndx = MOD(new_bucket, hctl->ssize); + + if (new_segnum >= hctl->nsegs) + { + + /* Allocate new segment if necessary */ + if (new_segnum >= hctl->dsize) + { + dir_realloc(hashp); + } + if (!(hashp->dir[new_segnum] = seg_alloc(hashp))) + { + return (0); + } + hctl->nsegs++; } - if (! (hashp->dir[new_segnum] = seg_alloc(hashp))) { - return (0); + + + if (new_bucket > hctl->high_mask) + { + /* Starting a new doubling */ + hctl->low_mask = hctl->high_mask; + hctl->high_mask = new_bucket | hctl->low_mask; } - hctl->nsegs++; - } - - - if ( new_bucket > hctl->high_mask ) { - /* Starting a new doubling */ - hctl->low_mask = hctl->high_mask; - hctl->high_mask = new_bucket | hctl->low_mask; - } - - /* - * Relocate records to the new bucket - */ - old_segnum = old_bucket >> hctl->sshift; - old_segndx = MOD(old_bucket, hctl->ssize); - - old_seg = GET_SEG(hashp,old_segnum); - new_seg = GET_SEG(hashp,new_segnum); - - old = &old_seg[old_segndx]; - newbi = &new_seg[new_segndx]; - for (chainIndex = *old; - chainIndex != INVALID_INDEX; - chainIndex = nextIndex){ - - chain = GET_BUCKET(hashp,chainIndex); - nextIndex = chain->next; - if ( call_hash(hashp, - (char *)&(chain->key), - hctl->keysize) == old_bucket ) { - *old = chainIndex; - old = &chain->next; - } else { - *newbi = chainIndex; - newbi = &chain->next; + + /* + * Relocate records to the new bucket + */ + old_segnum = old_bucket >> hctl->sshift; + old_segndx = MOD(old_bucket, hctl->ssize); + + old_seg = GET_SEG(hashp, old_segnum); + new_seg = GET_SEG(hashp, new_segnum); + + old = &old_seg[old_segndx]; + newbi = &new_seg[new_segndx]; + for (chainIndex = *old; + chainIndex != INVALID_INDEX; + chainIndex = nextIndex) + { + + chain = GET_BUCKET(hashp, chainIndex); + nextIndex = chain->next; + if (call_hash(hashp, + (char *) &(chain->key), + hctl->keysize) == old_bucket) + { + *old = chainIndex; + old = &chain->next; + } + else + { + *newbi = chainIndex; + newbi = &chain->next; + } + chain->next = INVALID_INDEX; } - chain->next = INVALID_INDEX; - } - return (1); + return (1); } static int -dir_realloc(HTAB *hashp) +dir_realloc(HTAB * hashp) { - register char *p; - char **p_ptr; - long old_dirsize; - long new_dirsize; - - - if (hashp->hctl->max_dsize != NO_MAX_DSIZE) + register char *p; + char **p_ptr; + long old_dirsize; + long new_dirsize; + + + if (hashp->hctl->max_dsize != NO_MAX_DSIZE) + return (0); + + /* Reallocate directory */ + old_dirsize = hashp->hctl->dsize * sizeof(SEGMENT *); + new_dirsize = old_dirsize << 1; + + p_ptr = (char **) hashp->dir; + p = (char *) hashp->alloc((unsigned long) new_dirsize); + if (p != NULL) + { + memmove(p, *p_ptr, old_dirsize); + memset(*p_ptr + old_dirsize, 0, new_dirsize - old_dirsize); + free((char *) *p_ptr); + *p_ptr = p; + hashp->hctl->dsize = new_dirsize; + return (1); + } return (0); - - /* Reallocate directory */ - old_dirsize = hashp->hctl->dsize * sizeof ( SEGMENT * ); - new_dirsize = old_dirsize << 1; - - p_ptr = (char **) hashp->dir; - p = (char *) hashp->alloc((unsigned long) new_dirsize ); - if (p != NULL) { - memmove(p, *p_ptr, old_dirsize ); - memset ( *p_ptr + old_dirsize, 0, new_dirsize-old_dirsize ); - free( (char *)*p_ptr); - *p_ptr = p; - hashp->hctl->dsize = new_dirsize; - return(1); - } - return (0); - + } -static SEG_OFFSET +static SEG_OFFSET seg_alloc(HTAB * hashp) { - SEGMENT segp; - SEG_OFFSET segOffset; - - - segp = (SEGMENT) hashp->alloc((unsigned long) - sizeof(SEGMENT)*hashp->hctl->ssize); - - if (! segp) { - return(0); - } - - memset((char *)segp, 0, - (long) sizeof(SEGMENT)*hashp->hctl->ssize); - - segOffset = MAKE_HASHOFFSET(hashp,segp); - return(segOffset); + SEGMENT segp; + SEG_OFFSET segOffset; + + + segp = (SEGMENT) hashp->alloc((unsigned long) + sizeof(SEGMENT) * hashp->hctl->ssize); + + if (!segp) + { + return (0); + } + + memset((char *) segp, 0, + (long) sizeof(SEGMENT) * hashp->hctl->ssize); + + segOffset = MAKE_HASHOFFSET(hashp, segp); + return (segOffset); } /* * allocate some new buckets and link them into the free list */ static int -bucket_alloc(HTAB *hashp) +bucket_alloc(HTAB * hashp) { - int i; - ELEMENT *tmpBucket; - long bucketSize; - BUCKET_INDEX tmpIndex,lastIndex; - - bucketSize = - sizeof(BUCKET_INDEX) + hashp->hctl->keysize + hashp->hctl->datasize; - - /* make sure its aligned correctly */ - bucketSize += sizeof(long *) - (bucketSize % sizeof(long *)); - - /* tmpIndex is the shmem offset into the first bucket of - * the array. - */ - tmpBucket = (ELEMENT *) - hashp->alloc((unsigned long) BUCKET_ALLOC_INCR*bucketSize); - - if (! tmpBucket) { - return(0); - } - - tmpIndex = MAKE_HASHOFFSET(hashp,tmpBucket); - - /* set the freebucket list to point to the first bucket */ - lastIndex = hashp->hctl->freeBucketIndex; - hashp->hctl->freeBucketIndex = tmpIndex; - - /* initialize each bucket to point to the one behind it */ - for (i=0;i<(BUCKET_ALLOC_INCR-1);i++) { - tmpBucket = GET_BUCKET(hashp,tmpIndex); - tmpIndex += bucketSize; - tmpBucket->next = tmpIndex; - } - - /* the last bucket points to the old freelist head (which is - * probably invalid or we wouldnt be here) - */ - tmpBucket->next = lastIndex; - - return(1); + int i; + ELEMENT *tmpBucket; + long bucketSize; + BUCKET_INDEX tmpIndex, + lastIndex; + + bucketSize = + sizeof(BUCKET_INDEX) + hashp->hctl->keysize + hashp->hctl->datasize; + + /* make sure its aligned correctly */ + bucketSize += sizeof(long *) - (bucketSize % sizeof(long *)); + + /* + * tmpIndex is the shmem offset into the first bucket of the array. + */ + tmpBucket = (ELEMENT *) + hashp->alloc((unsigned long) BUCKET_ALLOC_INCR * bucketSize); + + if (!tmpBucket) + { + return (0); + } + + tmpIndex = MAKE_HASHOFFSET(hashp, tmpBucket); + + /* set the freebucket list to point to the first bucket */ + lastIndex = hashp->hctl->freeBucketIndex; + hashp->hctl->freeBucketIndex = tmpIndex; + + /* initialize each bucket to point to the one behind it */ + for (i = 0; i < (BUCKET_ALLOC_INCR - 1); i++) + { + tmpBucket = GET_BUCKET(hashp, tmpIndex); + tmpIndex += bucketSize; + tmpBucket->next = tmpIndex; + } + + /* + * the last bucket points to the old freelist head (which is probably + * invalid or we wouldnt be here) + */ + tmpBucket->next = lastIndex; + + return (1); } /* calculate the log base 2 of num */ int my_log2(long num) { - int i = 1; - int limit; - - for ( i = 0, limit = 1; limit < num; limit = 2 * limit, i++ ); - return (i); + int i = 1; + int limit; + + for (i = 0, limit = 1; limit < num; limit = 2 * limit, i++); + return (i); } diff --git a/src/backend/utils/hash/hashfn.c b/src/backend/utils/hash/hashfn.c index 3b2f0ec19a9..f7b8f3fde6e 100644 --- a/src/backend/utils/hash/hashfn.c +++ b/src/backend/utils/hash/hashfn.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * hashfn.c-- - * + * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/hash/hashfn.c,v 1.3 1997/08/19 21:35:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/hash/hashfn.c,v 1.4 1997/09/07 04:53:38 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -24,96 +24,97 @@ long string_hash(char *key, int keysize) { - int h; - register unsigned char *k = (unsigned char *) key; - - h = 0; - /* - * Convert string to integer - */ - while (*k) - h = h * PRIME1 ^ (*k++ - ' '); - h %= PRIME2; - - return (h); + int h; + register unsigned char *k = (unsigned char *) key; + + h = 0; + + /* + * Convert string to integer + */ + while (*k) + h = h * PRIME1 ^ (*k++ - ' '); + h %= PRIME2; + + return (h); } long tag_hash(int *key, int keysize) { - register long h = 0; - - /* - * Convert tag to integer; Use four byte chunks in a "jump table" - * to go a little faster. Currently the maximum keysize is 16 - * (mar 17 1992) I have put in cases for up to 24. Bigger than - * this will resort to the old behavior of the for loop. (see the - * default case). - */ - switch (keysize) + register long h = 0; + + /* + * Convert tag to integer; Use four byte chunks in a "jump table" to + * go a little faster. Currently the maximum keysize is 16 (mar 17 + * 1992) I have put in cases for up to 24. Bigger than this will + * resort to the old behavior of the for loop. (see the default case). + */ + switch (keysize) { - case 6*sizeof(int): - h = h * PRIME1 ^ (*key); - key++; - /* fall through */ - - case 5*sizeof(int): - h = h * PRIME1 ^ (*key); - key++; - /* fall through */ - - case 4*sizeof(int): - h = h * PRIME1 ^ (*key); - key++; - /* fall through */ - - case 3*sizeof(int): - h = h * PRIME1 ^ (*key); - key++; - /* fall through */ - - case 2*sizeof(int): - h = h * PRIME1 ^ (*key); - key++; - /* fall through */ - + case 6 * sizeof(int): + h = h * PRIME1 ^ (*key); + key++; + /* fall through */ + + case 5 * sizeof(int): + h = h * PRIME1 ^ (*key); + key++; + /* fall through */ + + case 4 * sizeof(int): + h = h * PRIME1 ^ (*key); + key++; + /* fall through */ + + case 3 * sizeof(int): + h = h * PRIME1 ^ (*key); + key++; + /* fall through */ + + case 2 * sizeof(int): + h = h * PRIME1 ^ (*key); + key++; + /* fall through */ + case sizeof(int): - h = h * PRIME1 ^ (*key); - key++; - break; - - default: - for(; keysize > (sizeof(int)-1); keysize -= sizeof(int), key++) h = h * PRIME1 ^ (*key); - /* - * now let's grab the last few bytes of the tag if the tag - * has (size % 4) != 0 (which it sometimes will on a sun3). - */ - if (keysize) + key++; + break; + + default: + for (; keysize > (sizeof(int) - 1); keysize -= sizeof(int), key++) + h = h * PRIME1 ^ (*key); + + /* + * now let's grab the last few bytes of the tag if the tag has + * (size % 4) != 0 (which it sometimes will on a sun3). + */ + if (keysize) { - char *keytmp = (char *)key; - - switch (keysize) + char *keytmp = (char *) key; + + switch (keysize) { case 3: - h = h * PRIME1 ^ (*keytmp); - keytmp++; - /* fall through */ + h = h * PRIME1 ^ (*keytmp); + keytmp++; + /* fall through */ case 2: - h = h * PRIME1 ^ (*keytmp); - keytmp++; - /* fall through */ + h = h * PRIME1 ^ (*keytmp); + keytmp++; + /* fall through */ case 1: - h = h * PRIME1 ^ (*keytmp); - break; + h = h * PRIME1 ^ (*keytmp); + break; } } - break; + break; } - - h %= PRIME2; - return (h); + + h %= PRIME2; + return (h); } /* @@ -129,31 +130,42 @@ tag_hash(int *key, int keysize) long disk_hash(char *key) { - register int n = 0; - register char *str = key; - register int len = strlen(key); - register int loop; - -#define HASHC n = *str++ + 65599 * n - - if (len > 0) { - loop = (len + 8 - 1) >> 3; - - switch(len & (8 - 1)) { - case 0: do { /* All fall throughs */ - HASHC; - case 7: HASHC; - case 6: HASHC; - case 5: HASHC; - case 4: HASHC; - case 3: HASHC; - case 2: HASHC; - case 1: HASHC; - } while (--loop); + register int n = 0; + register char *str = key; + register int len = strlen(key); + register int loop; + +#define HASHC n = *str++ + 65599 * n + + if (len > 0) + { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) + { + case 0: + do + { /* All fall throughs */ + HASHC; + case 7: + HASHC; + case 6: + HASHC; + case 5: + HASHC; + case 4: + HASHC; + case 3: + HASHC; + case 2: + HASHC; + case 1: + HASHC; + } while (--loop); + } + } - - } - return(n); + return (n); } -#endif +#endif diff --git a/src/backend/utils/init/enbl.c b/src/backend/utils/init/enbl.c index 995ab9d9567..dfcf295e34c 100644 --- a/src/backend/utils/init/enbl.c +++ b/src/backend/utils/init/enbl.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * enbl.c-- - * POSTGRES module enable and disable support code. + * POSTGRES module enable and disable support code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/enbl.c,v 1.1.1.1 1996/07/09 06:22:08 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/enbl.c,v 1.2 1997/09/07 04:53:42 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,15 +16,15 @@ /* * BypassEnable -- - * False iff enable/disable processing is required given on and "*countP." + * False iff enable/disable processing is required given on and "*countP." * * Note: - * As a side-effect, *countP is modified. It should be 0 initially. + * As a side-effect, *countP is modified. It should be 0 initially. * * Exceptions: - * BadState if called with pointer to value 0 and false. - * BadArg if "countP" is invalid pointer. - * BadArg if on is invalid. + * BadState if called with pointer to value 0 and false. + * BadArg if "countP" is invalid pointer. + * BadArg if on is invalid. */ bool BypassEnable(int *enableCountInOutP, bool on) @@ -32,14 +32,15 @@ BypassEnable(int *enableCountInOutP, bool on) AssertArg(PointerIsValid(enableCountInOutP)); AssertArg(BoolIsValid(on)); - if (on) { + if (on) + { *enableCountInOutP += 1; - return ((bool)(*enableCountInOutP >= 2)); + return ((bool) (*enableCountInOutP >= 2)); } AssertState(*enableCountInOutP >= 1); *enableCountInOutP -= 1; - return ((bool)(*enableCountInOutP >= 1)); + return ((bool) (*enableCountInOutP >= 1)); } diff --git a/src/backend/utils/init/findbe.c b/src/backend/utils/init/findbe.c index 8718e3f91d6..5e6aa7412a6 100644 --- a/src/backend/utils/init/findbe.c +++ b/src/backend/utils/init/findbe.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/findbe.c,v 1.5 1997/08/27 03:48:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/findbe.c,v 1.6 1997/09/07 04:53:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,213 +19,230 @@ #include <unistd.h> #include "postgres.h" -#include "miscadmin.h" /* for DebugLvl */ +#include "miscadmin.h" /* for DebugLvl */ -#ifndef S_IRUSR /* XXX [TRH] should be in a header */ -# define S_IRUSR S_IREAD -# define S_IWUSR S_IWRITE -# define S_IXUSR S_IEXEC -# define S_IRGRP ((S_IRUSR)>>3) -# define S_IWGRP ((S_IWUSR)>>3) -# define S_IXGRP ((S_IXUSR)>>3) -# define S_IROTH ((S_IRUSR)>>6) -# define S_IWOTH ((S_IWUSR)>>6) -# define S_IXOTH ((S_IXUSR)>>6) +#ifndef S_IRUSR /* XXX [TRH] should be in a header */ +#define S_IRUSR S_IREAD +#define S_IWUSR S_IWRITE +#define S_IXUSR S_IEXEC +#define S_IRGRP ((S_IRUSR)>>3) +#define S_IWGRP ((S_IWUSR)>>3) +#define S_IXGRP ((S_IXUSR)>>3) +#define S_IROTH ((S_IRUSR)>>6) +#define S_IWOTH ((S_IWUSR)>>6) +#define S_IXOTH ((S_IXUSR)>>6) #endif /* * ValidateBackend -- validate "path" as a POSTGRES executable file * * returns 0 if the file is found and no error is encountered. - * -1 if the regular file "path" does not exist or cannot be executed. - * -2 if the file is otherwise valid but cannot be read. + * -1 if the regular file "path" does not exist or cannot be executed. + * -2 if the file is otherwise valid but cannot be read. */ int ValidateBackend(char *path) { - struct stat buf; - uid_t euid; - struct group *gp; - struct passwd *pwp; - int i; - int is_r = 0; - int is_x = 0; - int in_grp = 0; - - /* - * Ensure that the file exists and is a regular file. - * - * XXX if you have a broken system where stat() looks at the symlink - * instead of the underlying file, you lose. - */ - if (strlen(path) >= MAXPGPATH) { - if (DebugLvl > 1) - fprintf(stderr, "ValidateBackend: pathname \"%s\" is too long\n", - path); - return(-1); - } + struct stat buf; + uid_t euid; + struct group *gp; + struct passwd *pwp; + int i; + int is_r = 0; + int is_x = 0; + int in_grp = 0; - if (stat(path, &buf) < 0) { - if (DebugLvl > 1) - fprintf(stderr, "ValidateBackend: can't stat \"%s\"\n", - path); - return(-1); - } - if (!(buf.st_mode & S_IFREG)) { - if (DebugLvl > 1) - fprintf(stderr, "ValidateBackend: \"%s\" is not a regular file\n", - path); - return(-1); - } - - /* - * Ensure that we are using an authorized backend. - * - * XXX I'm open to suggestions here. I would like to enforce ownership - * of backends by user "postgres" but people seem to like to run - * as users other than "postgres"... - */ - - /* - * Ensure that the file is both executable and readable (required for - * dynamic loading). - * - * We use the effective uid here because the backend will not have - * executed setuid() by the time it calls this routine. - */ - euid = geteuid(); - if (euid == buf.st_uid) { - is_r = buf.st_mode & S_IRUSR; - is_x = buf.st_mode & S_IXUSR; - if (DebugLvl > 1 && !(is_r && is_x)) - fprintf(stderr, "ValidateBackend: \"%s\" is not user read/execute\n", - path); - return(is_x ? (is_r ? 0 : -2) : -1); - } - pwp = getpwuid(euid); - if (pwp) { - if (pwp->pw_gid == buf.st_gid) { - ++in_grp; - } else if (pwp->pw_name && - (gp = getgrgid(buf.st_gid))) { - for (i = 0; gp->gr_mem[i]; ++i) { - if (!strcmp(gp->gr_mem[i], pwp->pw_name)) { - ++in_grp; - break; - } - } + /* + * Ensure that the file exists and is a regular file. + * + * XXX if you have a broken system where stat() looks at the symlink + * instead of the underlying file, you lose. + */ + if (strlen(path) >= MAXPGPATH) + { + if (DebugLvl > 1) + fprintf(stderr, "ValidateBackend: pathname \"%s\" is too long\n", + path); + return (-1); } - if (in_grp) { - is_r = buf.st_mode & S_IRGRP; - is_x = buf.st_mode & S_IXGRP; - if (DebugLvl > 1 && !(is_r && is_x)) - fprintf(stderr, "ValidateBackend: \"%s\" is not group read/execute\n", - path); - return(is_x ? (is_r ? 0 : -2) : -1); + + if (stat(path, &buf) < 0) + { + if (DebugLvl > 1) + fprintf(stderr, "ValidateBackend: can't stat \"%s\"\n", + path); + return (-1); } - } - is_r = buf.st_mode & S_IROTH; - is_x = buf.st_mode & S_IXOTH; - if (DebugLvl > 1 && !(is_r && is_x)) - fprintf(stderr, "ValidateBackend: \"%s\" is not other read/execute\n", - path); - return(is_x ? (is_r ? 0 : -2) : -1); + if (!(buf.st_mode & S_IFREG)) + { + if (DebugLvl > 1) + fprintf(stderr, "ValidateBackend: \"%s\" is not a regular file\n", + path); + return (-1); + } + + /* + * Ensure that we are using an authorized backend. + * + * XXX I'm open to suggestions here. I would like to enforce ownership + * of backends by user "postgres" but people seem to like to run as + * users other than "postgres"... + */ + + /* + * Ensure that the file is both executable and readable (required for + * dynamic loading). + * + * We use the effective uid here because the backend will not have + * executed setuid() by the time it calls this routine. + */ + euid = geteuid(); + if (euid == buf.st_uid) + { + is_r = buf.st_mode & S_IRUSR; + is_x = buf.st_mode & S_IXUSR; + if (DebugLvl > 1 && !(is_r && is_x)) + fprintf(stderr, "ValidateBackend: \"%s\" is not user read/execute\n", + path); + return (is_x ? (is_r ? 0 : -2) : -1); + } + pwp = getpwuid(euid); + if (pwp) + { + if (pwp->pw_gid == buf.st_gid) + { + ++in_grp; + } + else if (pwp->pw_name && + (gp = getgrgid(buf.st_gid))) + { + for (i = 0; gp->gr_mem[i]; ++i) + { + if (!strcmp(gp->gr_mem[i], pwp->pw_name)) + { + ++in_grp; + break; + } + } + } + if (in_grp) + { + is_r = buf.st_mode & S_IRGRP; + is_x = buf.st_mode & S_IXGRP; + if (DebugLvl > 1 && !(is_r && is_x)) + fprintf(stderr, "ValidateBackend: \"%s\" is not group read/execute\n", + path); + return (is_x ? (is_r ? 0 : -2) : -1); + } + } + is_r = buf.st_mode & S_IROTH; + is_x = buf.st_mode & S_IXOTH; + if (DebugLvl > 1 && !(is_r && is_x)) + fprintf(stderr, "ValidateBackend: \"%s\" is not other read/execute\n", + path); + return (is_x ? (is_r ? 0 : -2) : -1); } /* * FindBackend -- find an absolute path to a valid backend executable * * The reason we have to work so hard to find an absolute path is that - * we need to feed the backend server the location of its actual + * we need to feed the backend server the location of its actual * executable file -- otherwise, we can't do dynamic loading. */ int FindBackend(char *backend, char *argv0) { - char buf[MAXPGPATH + 2]; - char *p; - char *path, *startp, *endp; - int pathlen; - - /* - * for the postmaster: - * First try: use the backend that's located in the same directory - * as the postmaster, if it was invoked with an explicit path. - * Presumably the user used an explicit path because it wasn't in - * PATH, and we don't want to use incompatible executables. - * - * This has the neat property that it works for installed binaries, - * old source trees (obj/support/post{master,gres}) and new marc - * source trees (obj/post{master,gres}) because they all put the - * two binaries in the same place. - * - * for the backend server: - * First try: if we're given some kind of path, use it (making sure - * that a relative path is made absolute before returning it). - */ - if (argv0 && (p = strrchr(argv0, '/')) && *++p) { - if (*argv0 == '/' || !getcwd(buf, MAXPGPATH)) - buf[0] = '\0'; - else - strcat(buf, "/"); - strcat(buf, argv0); - p = strrchr(buf, '/'); - strcpy(++p, "postgres"); - if (!ValidateBackend(buf)) { - strncpy(backend, buf, MAXPGPATH); - if (DebugLvl) - fprintf(stderr, "FindBackend: found \"%s\" using argv[0]\n", - backend); - return(0); + char buf[MAXPGPATH + 2]; + char *p; + char *path, + *startp, + *endp; + int pathlen; + + /* + * for the postmaster: First try: use the backend that's located in + * the same directory as the postmaster, if it was invoked with an + * explicit path. Presumably the user used an explicit path because it + * wasn't in PATH, and we don't want to use incompatible executables. + * + * This has the neat property that it works for installed binaries, old + * source trees (obj/support/post{master,gres}) and new marc source + * trees (obj/post{master,gres}) because they all put the two binaries + * in the same place. + * + * for the backend server: First try: if we're given some kind of path, + * use it (making sure that a relative path is made absolute before + * returning it). + */ + if (argv0 && (p = strrchr(argv0, '/')) && *++p) + { + if (*argv0 == '/' || !getcwd(buf, MAXPGPATH)) + buf[0] = '\0'; + else + strcat(buf, "/"); + strcat(buf, argv0); + p = strrchr(buf, '/'); + strcpy(++p, "postgres"); + if (!ValidateBackend(buf)) + { + strncpy(backend, buf, MAXPGPATH); + if (DebugLvl) + fprintf(stderr, "FindBackend: found \"%s\" using argv[0]\n", + backend); + return (0); + } + fprintf(stderr, "FindBackend: invalid backend \"%s\"\n", + buf); + return (-1); } - fprintf(stderr, "FindBackend: invalid backend \"%s\"\n", - buf); - return(-1); - } - - /* - * Second try: since no explicit path was supplied, the user must - * have been relying on PATH. We'll use the same PATH. - */ - if ((p = getenv("PATH")) && *p) { - if (DebugLvl) - fprintf(stderr, "FindBackend: searching PATH ...\n"); - pathlen = strlen(p); - path = malloc(pathlen + 1); - strcpy(path, p); - for (startp = path, endp = strchr(path, ':'); - startp && *startp; - startp = endp + 1, endp = strchr(startp, ':')) { - if (startp == endp) /* it's a "::" */ - continue; - if (endp) - *endp = '\0'; - if (*startp == '/' || !getcwd(buf, MAXPGPATH)) - buf[0] = '\0'; - strcat(buf, startp); - strcat(buf, "/postgres"); - switch (ValidateBackend(buf)) { - case 0: /* found ok */ - strncpy(backend, buf, MAXPGPATH); + + /* + * Second try: since no explicit path was supplied, the user must have + * been relying on PATH. We'll use the same PATH. + */ + if ((p = getenv("PATH")) && *p) + { if (DebugLvl) - fprintf(stderr, "FindBackend: found \"%s\" using PATH\n", - backend); - free(path); - return(0); - case -1: /* wasn't even a candidate, keep looking */ - break; - case -2: /* found but disqualified */ - fprintf(stderr, "FindBackend: could not read backend \"%s\"\n", - buf); + fprintf(stderr, "FindBackend: searching PATH ...\n"); + pathlen = strlen(p); + path = malloc(pathlen + 1); + strcpy(path, p); + for (startp = path, endp = strchr(path, ':'); + startp && *startp; + startp = endp + 1, endp = strchr(startp, ':')) + { + if (startp == endp) /* it's a "::" */ + continue; + if (endp) + *endp = '\0'; + if (*startp == '/' || !getcwd(buf, MAXPGPATH)) + buf[0] = '\0'; + strcat(buf, startp); + strcat(buf, "/postgres"); + switch (ValidateBackend(buf)) + { + case 0: /* found ok */ + strncpy(backend, buf, MAXPGPATH); + if (DebugLvl) + fprintf(stderr, "FindBackend: found \"%s\" using PATH\n", + backend); + free(path); + return (0); + case -1: /* wasn't even a candidate, keep looking */ + break; + case -2: /* found but disqualified */ + fprintf(stderr, "FindBackend: could not read backend \"%s\"\n", + buf); + free(path); + return (-1); + } + if (!endp) /* last one */ + break; + } free(path); - return(-1); - } - if (!endp) /* last one */ - break; } - free(path); - } - fprintf(stderr, "FindBackend: could not find a backend to execute...\n"); - return(-1); + fprintf(stderr, "FindBackend: could not find a backend to execute...\n"); + return (-1); } diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 053bcbb8775..2ed0c83e0b2 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * globals.c-- - * global variable declarations + * global variable declarations * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.10 1997/08/14 16:11:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.11 1997/09/07 04:53:48 momjian Exp $ * * NOTES - * Globals used all over the place should be declared here and not - * in other modules. + * Globals used all over the place should be declared here and not + * in other modules. * *------------------------------------------------------------------------- */ @@ -24,7 +24,7 @@ #include <unistd.h> #include "postgres.h" -#include "miscadmin.h" /* where the declarations go */ +#include "miscadmin.h" /* where the declarations go */ #include <storage/backendid.h> #include "access/heapam.h" @@ -36,83 +36,86 @@ #include "catalog/catname.h" -int Portfd = -1; -int Noversion = 0; -int Quiet = 1; +int Portfd = -1; +int Noversion = 0; +int Quiet = 1; -int MasterPid; -char *DataDir; - /* The PGDATA directory user says to use, or defaults to via environment - variable. NULL if no option given and no environment variable set +int MasterPid; +char *DataDir; + + /* + * The PGDATA directory user says to use, or defaults to via environment + * variable. NULL if no option given and no environment variable set */ -Relation reldesc; /* current relation descriptor */ - -char OutputFileName[MAXPGPATH] = ""; +Relation reldesc; /* current relation descriptor */ + +char OutputFileName[MAXPGPATH] = ""; -BackendId MyBackendId; -BackendTag MyBackendTag; +BackendId MyBackendId; +BackendTag MyBackendTag; -char *UserName = NULL; -char *DatabaseName = NULL; -char *DatabasePath = NULL; +char *UserName = NULL; +char *DatabaseName = NULL; +char *DatabasePath = NULL; -bool MyDatabaseIdIsInitialized = false; -Oid MyDatabaseId = InvalidOid; -bool TransactionInitWasProcessed = false; +bool MyDatabaseIdIsInitialized = false; +Oid MyDatabaseId = InvalidOid; +bool TransactionInitWasProcessed = false; -bool IsUnderPostmaster = false; -bool IsPostmaster = false; +bool IsUnderPostmaster = false; +bool IsPostmaster = false; -short DebugLvl = 0; +short DebugLvl = 0; -int DateStyle = USE_POSTGRES_DATES; -bool EuroDates = false; -bool HasCTZSet = false; -bool CDayLight = false; -int CTimeZone = 0; -char CTZName[MAXTZLEN+1] = ""; +int DateStyle = USE_POSTGRES_DATES; +bool EuroDates = false; +bool HasCTZSet = false; +bool CDayLight = false; +int CTimeZone = 0; +char CTZName[MAXTZLEN + 1] = ""; -char DateFormat[20] = "%d-%m-%Y"; /* mjl: sizes! or better malloc? XXX */ -char FloatFormat[20] = "%f"; +char DateFormat[20] = "%d-%m-%Y"; /* mjl: sizes! or better + * malloc? XXX */ +char FloatFormat[20] = "%f"; -int fsyncOff = 0; -int SortMem = 512; +int fsyncOff = 0; +int SortMem = 512; -char *IndexedCatalogNames[] = { - AttributeRelationName, - ProcedureRelationName, - TypeRelationName, - RelationRelationName, - 0 +char *IndexedCatalogNames[] = { + AttributeRelationName, + ProcedureRelationName, + TypeRelationName, + RelationRelationName, + 0 }; /* ---------------- * we just do a linear search now so there's no requirement that the list - * be ordered. The list is so small it shouldn't make much difference. + * be ordered. The list is so small it shouldn't make much difference. * make sure the list is null-terminated - * - jolly 8/19/95 - * + * - jolly 8/19/95 + * * OLD COMMENT - * WARNING WARNING WARNING WARNING WARNING WARNING + * WARNING WARNING WARNING WARNING WARNING WARNING * - * keep SharedSystemRelationNames[] in SORTED order! A binary search - * is done on it in catalog.c! + * keep SharedSystemRelationNames[] in SORTED order! A binary search + * is done on it in catalog.c! * - * XXX this is a serious hack which should be fixed -cim 1/26/90 + * XXX this is a serious hack which should be fixed -cim 1/26/90 * ---------------- */ -char *SharedSystemRelationNames[] = { - DatabaseRelationName, - DefaultsRelationName, - DemonRelationName, - GroupRelationName, - HostsRelationName, - LogRelationName, - MagicRelationName, - ServerRelationName, - TimeRelationName, - UserRelationName, - VariableRelationName, - 0 +char *SharedSystemRelationNames[] = { + DatabaseRelationName, + DefaultsRelationName, + DemonRelationName, + GroupRelationName, + HostsRelationName, + LogRelationName, + MagicRelationName, + ServerRelationName, + TimeRelationName, + UserRelationName, + VariableRelationName, + 0 }; diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 2fe002bd914..71efb80d120 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -1,55 +1,55 @@ /*------------------------------------------------------------------------- * * miscinit.c-- - * miscellanious initialization support stuff + * miscellanious initialization support stuff * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.6 1997/08/19 21:35:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.7 1997/09/07 04:53:49 momjian Exp $ * *------------------------------------------------------------------------- */ #include <string.h> -#include <sys/param.h> /* for MAXPATHLEN */ +#include <sys/param.h> /* for MAXPATHLEN */ #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <stdio.h> #include <unistd.h> -#include <grp.h> /* for getgrgid */ -#include <pwd.h> /* for getpwuid */ +#include <grp.h> /* for getgrgid */ +#include <pwd.h> /* for getpwuid */ #include "postgres.h" -#include "utils/portal.h" /* for EnablePortalManager, etc. */ -#include "utils/exc.h" /* for EnableExceptionHandling, etc. */ -#include "utils/mcxt.h" /* for EnableMemoryContext, etc. */ +#include "utils/portal.h" /* for EnablePortalManager, etc. */ +#include "utils/exc.h" /* for EnableExceptionHandling, etc. */ +#include "utils/mcxt.h" /* for EnableMemoryContext, etc. */ #include "utils/elog.h" #include "utils/builtins.h" -#include "miscadmin.h" /* where the declarations go */ +#include "miscadmin.h" /* where the declarations go */ #include "catalog/catname.h" #include "catalog/pg_user.h" #include "catalog/pg_proc.h" #include "utils/syscache.h" -#include "storage/fd.h" /* for O_ */ +#include "storage/fd.h" /* for O_ */ /* * EnableAbortEnvVarName -- - * Enables system abort iff set to a non-empty string in environment. + * Enables system abort iff set to a non-empty string in environment. */ #define EnableAbortEnvVarName "POSTGRESABORT" -extern char *getenv(const char *name); /* XXX STDLIB */ +extern char *getenv(const char *name); /* XXX STDLIB */ -/* from globals.c */ -extern char *DatabaseName; -extern char *UserName; -extern char *DatabasePath; +/* from globals.c */ +extern char *DatabaseName; +extern char *UserName; +extern char *DatabasePath; /* @@ -59,282 +59,286 @@ extern char *DatabasePath; #define USE_ENVIRONMENT /* ---------------------------------------------------------------- - * some of the 19 ways to leave postgres + * some of the 19 ways to leave postgres * ---------------------------------------------------------------- */ /* * ExitPostgres -- - * Exit POSTGRES with a status code. + * Exit POSTGRES with a status code. * * Note: - * This function never returns. - * ... + * This function never returns. + * ... * * Side effects: - * ... + * ... * * Exceptions: - * none + * none */ void ExitPostgres(ExitStatus status) { #ifdef __SABER__ - saber_stop(); + saber_stop(); #endif - exitpg(status); + exitpg(status); } /* * AbortPostgres -- - * Abort POSTGRES dumping core. + * Abort POSTGRES dumping core. * * Note: - * This function never returns. - * ... + * This function never returns. + * ... * * Side effects: - * Core is dumped iff EnableAbortEnvVarName is set to a non-empty string. - * ... + * Core is dumped iff EnableAbortEnvVarName is set to a non-empty string. + * ... * * Exceptions: - * none + * none */ #ifdef NOT_USED void AbortPostgres() { - char *abortValue = getenv(EnableAbortEnvVarName); - + char *abortValue = getenv(EnableAbortEnvVarName); + #ifdef __SABER__ - saber_stop(); + saber_stop(); #endif - - if (PointerIsValid(abortValue) && abortValue[0] != '\0') - abort(); - else - exitpg(FatalExitStatus); + + if (PointerIsValid(abortValue) && abortValue[0] != '\0') + abort(); + else + exitpg(FatalExitStatus); } + #endif /* ---------------- - * StatusBackendExit + * StatusBackendExit * ---------------- */ void StatusBackendExit(int status) { - /* someday, do some real cleanup and then call the LISP exit */ - /* someday, call StatusPostmasterExit if running without postmaster */ - exitpg(status); + /* someday, do some real cleanup and then call the LISP exit */ + /* someday, call StatusPostmasterExit if running without postmaster */ + exitpg(status); } /* ---------------- - * StatusPostmasterExit + * StatusPostmasterExit * ---------------- */ void StatusPostmasterExit(int status) { - /* someday, do some real cleanup and then call the LISP exit */ - exitpg(status); + /* someday, do some real cleanup and then call the LISP exit */ + exitpg(status); } /* ---------------------------------------------------------------- - * processing mode support stuff (used to be in pmod.c) + * processing mode support stuff (used to be in pmod.c) * ---------------------------------------------------------------- */ -static ProcessingMode Mode = NoProcessing; +static ProcessingMode Mode = NoProcessing; /* * IsNoProcessingMode -- - * True iff processing mode is NoProcessing. + * True iff processing mode is NoProcessing. */ bool IsNoProcessingMode() { - return ((bool)(Mode == NoProcessing)); + return ((bool) (Mode == NoProcessing)); } /* * IsBootstrapProcessingMode -- - * True iff processing mode is BootstrapProcessing. + * True iff processing mode is BootstrapProcessing. */ bool IsBootstrapProcessingMode() { - return ((bool)(Mode == BootstrapProcessing)); + return ((bool) (Mode == BootstrapProcessing)); } /* * IsInitProcessingMode -- - * True iff processing mode is InitProcessing. + * True iff processing mode is InitProcessing. */ bool IsInitProcessingMode() { - return ((bool)(Mode == InitProcessing)); + return ((bool) (Mode == InitProcessing)); } /* * IsNormalProcessingMode -- - * True iff processing mode is NormalProcessing. + * True iff processing mode is NormalProcessing. */ bool IsNormalProcessingMode() { - return ((bool)(Mode == NormalProcessing)); + return ((bool) (Mode == NormalProcessing)); } /* * SetProcessingMode -- - * Sets mode of processing as specified. + * Sets mode of processing as specified. * * Exceptions: - * BadArg if called with invalid mode. + * BadArg if called with invalid mode. * * Note: - * Mode is NoProcessing before the first time this is called. + * Mode is NoProcessing before the first time this is called. */ void SetProcessingMode(ProcessingMode mode) { - AssertArg(mode == NoProcessing || mode == BootstrapProcessing || - mode == InitProcessing || mode == NormalProcessing); - - Mode = mode; + AssertArg(mode == NoProcessing || mode == BootstrapProcessing || + mode == InitProcessing || mode == NormalProcessing); + + Mode = mode; } ProcessingMode GetProcessingMode() { - return (Mode); + return (Mode); } /* ---------------------------------------------------------------- - * database path / name support stuff + * database path / name support stuff * ---------------------------------------------------------------- */ /* * GetDatabasePath -- - * Returns path to database. + * Returns path to database. * */ -char* +char * GetDatabasePath() { - return DatabasePath; + return DatabasePath; } /* * GetDatabaseName -- - * Returns name of database. + * Returns name of database. */ -char* +char * GetDatabaseName() { - return DatabaseName; + return DatabaseName; } void SetDatabasePath(char *path) { - /* use malloc since this is done before memory contexts are set up */ - if (DatabasePath) - free(DatabasePath); - DatabasePath = malloc(strlen(path)+1); - strcpy(DatabasePath, path); + /* use malloc since this is done before memory contexts are set up */ + if (DatabasePath) + free(DatabasePath); + DatabasePath = malloc(strlen(path) + 1); + strcpy(DatabasePath, path); } void SetDatabaseName(char *name) { - if (DatabaseName) - free (DatabaseName); - DatabaseName = malloc(strlen(name)+1); - strcpy(DatabaseName, name); + if (DatabaseName) + free(DatabaseName); + DatabaseName = malloc(strlen(name) + 1); + strcpy(DatabaseName, name); } /* ---------------- - * GetPgUserName and SetPgUserName + * GetPgUserName and SetPgUserName * - * SetPgUserName must be called before InitPostgres, since the setuid() - * is done there. + * SetPgUserName must be called before InitPostgres, since the setuid() + * is done there. * - * Replace GetPgUserName() with a lower-case version - * to allow use in new case-insensitive SQL (referenced - * in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26 + * Replace GetPgUserName() with a lower-case version + * to allow use in new case-insensitive SQL (referenced + * in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26 * ---------------- */ -char* +char * getpgusername() { - return UserName; + return UserName; } void SetPgUserName() { #ifndef NO_SECURITY - char *p; - struct passwd *pw; - - if (IsUnderPostmaster) { - /* use the (possibly) authenticated name that's provided */ - if (!(p = getenv("PG_USER"))) - elog(FATAL, "SetPgUserName: PG_USER environment variable unset"); - } else { - /* setuid() has not yet been done, see above comment */ - if (!(pw = getpwuid(geteuid()))) - elog(FATAL, "SetPgUserName: no entry in passwd file"); - p = pw->pw_name; - } - if (UserName) - free(UserName); - UserName = malloc(strlen(p)+1); - strcpy(UserName, p); -#endif /* NO_SECURITY */ + char *p; + struct passwd *pw; + + if (IsUnderPostmaster) + { + /* use the (possibly) authenticated name that's provided */ + if (!(p = getenv("PG_USER"))) + elog(FATAL, "SetPgUserName: PG_USER environment variable unset"); + } + else + { + /* setuid() has not yet been done, see above comment */ + if (!(pw = getpwuid(geteuid()))) + elog(FATAL, "SetPgUserName: no entry in passwd file"); + p = pw->pw_name; + } + if (UserName) + free(UserName); + UserName = malloc(strlen(p) + 1); + strcpy(UserName, p); +#endif /* NO_SECURITY */ } /* ---------------------------------------------------------------- - * GetUserId and SetUserId + * GetUserId and SetUserId * ---------------------------------------------------------------- */ -static Oid UserId = InvalidOid; +static Oid UserId = InvalidOid; Oid GetUserId() { - Assert(OidIsValid(UserId)); - return(UserId); + Assert(OidIsValid(UserId)); + return (UserId); } void SetUserId() { - HeapTuple userTup; - char *userName; - - Assert(!OidIsValid(UserId)); /* only once */ - - /* - * Don't do scans if we're bootstrapping, none of the system - * catalogs exist yet, and they should be owned by postgres - * anyway. - */ - if (IsBootstrapProcessingMode()) { - UserId = geteuid(); - return; - } - - userName = GetPgUserName(); - userTup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName), - 0,0,0); - if (!HeapTupleIsValid(userTup)) - elog(FATAL, "SetUserId: user \"%s\" is not in \"%s\"", - userName, - UserRelationName); - UserId = (Oid) ((Form_pg_user) GETSTRUCT(userTup))->usesysid; + HeapTuple userTup; + char *userName; + + Assert(!OidIsValid(UserId));/* only once */ + + /* + * Don't do scans if we're bootstrapping, none of the system catalogs + * exist yet, and they should be owned by postgres anyway. + */ + if (IsBootstrapProcessingMode()) + { + UserId = geteuid(); + return; + } + + userName = GetPgUserName(); + userTup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName), + 0, 0, 0); + if (!HeapTupleIsValid(userTup)) + elog(FATAL, "SetUserId: user \"%s\" is not in \"%s\"", + userName, + UserRelationName); + UserId = (Oid) ((Form_pg_user) GETSTRUCT(userTup))->usesysid; } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index fb21e51a492..5a8a1a83d4d 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -1,28 +1,28 @@ /*------------------------------------------------------------------------- * * postinit.c-- - * postgres initialization utilities + * postgres initialization utilities * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.12 1997/08/27 03:48:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.13 1997/09/07 04:53:50 momjian Exp $ * * NOTES - * InitPostgres() is the function called from PostgresMain - * which does all non-trival initialization, mainly by calling - * all the other initialization functions. InitPostgres() - * is only used within the "postgres" backend and so that routine - * is in tcop/postgres.c InitPostgres() is needed in cinterface.a - * because things like the bootstrap backend program need it. Hence - * you find that in this file... + * InitPostgres() is the function called from PostgresMain + * which does all non-trival initialization, mainly by calling + * all the other initialization functions. InitPostgres() + * is only used within the "postgres" backend and so that routine + * is in tcop/postgres.c InitPostgres() is needed in cinterface.a + * because things like the bootstrap backend program need it. Hence + * you find that in this file... * - * If you feel the need to add more initialization code, it should be - * done in InitPostgres() or someplace lower. Do not start - * putting stuff in PostgresMain - if you do then someone - * will have to clean it up later, and it's not going to be me! - * -cim 10/3/90 + * If you feel the need to add more initialization code, it should be + * done in InitPostgres() or someplace lower. Do not start + * putting stuff in PostgresMain - if you do then someone + * will have to clean it up later, and it's not going to be me! + * -cim 10/3/90 * *------------------------------------------------------------------------- */ @@ -47,22 +47,22 @@ #include "access/heapam.h" #include "access/xact.h" #include "storage/bufmgr.h" -#include "access/transam.h" /* XXX dependency problem */ +#include "access/transam.h" /* XXX dependency problem */ #include "utils/tqual.h" #include "utils/syscache.h" -#include "storage/bufpage.h" /* for page layout, for InitMyDatabaseId() */ +#include "storage/bufpage.h" /* for page layout, for InitMyDatabaseId() */ #include "storage/sinval.h" #include "storage/sinvaladt.h" #include "storage/lmgr.h" -#include "miscadmin.h" /* for global decls */ -#include "utils/portal.h" /* for EnablePortalManager, etc. */ +#include "miscadmin.h" /* for global decls */ +#include "utils/portal.h" /* for EnablePortalManager, etc. */ -#include "utils/exc.h" /* for EnableExceptionHandling, etc. */ -#include "fmgr.h" /* for EnableDynamicFunctionManager, etc. */ +#include "utils/exc.h" /* for EnableExceptionHandling, etc. */ +#include "fmgr.h" /* for EnableDynamicFunctionManager, etc. */ #include "utils/elog.h" #include "utils/palloc.h" -#include "utils/mcxt.h" /* for EnableMemoryContext, etc. */ +#include "utils/mcxt.h" /* for EnableMemoryContext, etc. */ #include "catalog/catname.h" #include "catalog/pg_database.h" @@ -70,584 +70,612 @@ #include "port-protos.h" #include "libpq/libpq-be.h" -static void InitCommunication(void); -static void InitMyDatabaseId(void); -static void InitStdio(void); -static void InitUserid(void); +static void InitCommunication(void); +static void InitMyDatabaseId(void); +static void InitStdio(void); +static void InitUserid(void); -static IPCKey PostgresIpcKey; +static IPCKey PostgresIpcKey; /* ---------------------------------------------------------------- - * InitPostgres support + * InitPostgres support * ---------------------------------------------------------------- */ /* -------------------------------- - * InitMyDatabaseId() -- Find and record the OID of the database we are - * to open. + * InitMyDatabaseId() -- Find and record the OID of the database we are + * to open. * - * The database's oid forms half of the unique key for the system - * caches and lock tables. We therefore want it initialized before - * we open any relations, since opening relations puts things in the - * cache. To get around this problem, this code opens and scans the - * pg_database relation by hand. + * The database's oid forms half of the unique key for the system + * caches and lock tables. We therefore want it initialized before + * we open any relations, since opening relations puts things in the + * cache. To get around this problem, this code opens and scans the + * pg_database relation by hand. * - * This algorithm relies on the fact that first attribute in the - * pg_database relation schema is the database name. It also knows - * about the internal format of tuples on disk and the length of - * the datname attribute. It knows the location of the pg_database - * file. + * This algorithm relies on the fact that first attribute in the + * pg_database relation schema is the database name. It also knows + * about the internal format of tuples on disk and the length of + * the datname attribute. It knows the location of the pg_database + * file. * - * This code is called from InitDatabase(), after we chdir() to the - * database directory but before we open any relations. + * This code is called from InitDatabase(), after we chdir() to the + * database directory but before we open any relations. * -------------------------------- */ static void InitMyDatabaseId() { - int dbfd; - int fileflags; - int nbytes; - int max, i; - HeapTuple tup; - Page pg; - PageHeader ph; - char *dbfname; - Form_pg_database tup_db; - - /* - * At bootstrap time, we don't need to check the oid of the database - * in use, since we're not using shared memory. This is lucky, since - * the database may not be in the tables yet. - */ - - if (IsBootstrapProcessingMode()) { - LockDisable(true); - return; - } - - dbfname = (char *) palloc(strlen(DataDir) + strlen("pg_database") + 2); - sprintf(dbfname, "%s%cpg_database", DataDir, SEP_CHAR); - fileflags = O_RDONLY; - - if ((dbfd = open(dbfname, O_RDONLY, 0)) < 0) - elog(FATAL, "Cannot open %s", dbfname); - - pfree(dbfname); - - /* ---------------- - * read and examine every page in pg_database - * - * Raw I/O! Read those tuples the hard way! Yow! - * - * Why don't we use the access methods or move this code - * someplace else? This is really pg_database schema dependent - * code. Perhaps it should go in lib/catalog/pg_database? - * -cim 10/3/90 - * - * mao replies 4 apr 91: yeah, maybe this should be moved to - * lib/catalog. however, we CANNOT use the access methods since - * those use the buffer cache, which uses the relation cache, which - * requires that the dbid be set, which is what we're trying to do - * here. - * ---------------- - */ - pg = (Page) palloc(BLCKSZ); - ph = (PageHeader) pg; - - while ((nbytes = read(dbfd, pg, BLCKSZ)) == BLCKSZ) { - max = PageGetMaxOffsetNumber(pg); - - /* look at each tuple on the page */ - for (i = 0; i <= max; i++) { - int offset; - - /* if it's a freed tuple, ignore it */ - if (!(ph->pd_linp[i].lp_flags & LP_USED)) - continue; - - /* get a pointer to the tuple itself */ - offset = (int) ph->pd_linp[i].lp_off; - tup = (HeapTuple) (((char *) pg) + offset); - - /* - * if the tuple has been deleted (the database was destroyed), - * skip this tuple. XXX warning, will robinson: violation of - * transaction semantics happens right here. we should check - * to be sure that the xact that deleted this tuple actually - * committed. only way to do this at init time is to paw over - * the log relation by hand, too. let's be optimistic. - * - * XXX This is an evil type cast. tup->t_xmax is char[5] while - * TransactionId is struct * { char data[5] }. It works but - * if data is ever moved and no longer the first field this - * will be broken!! -mer 11 Nov 1991. - */ - if (TransactionIdIsValid((TransactionId)tup->t_xmax)) - continue; - - /* - * Okay, see if this is the one we want. - * XXX 1 july 91: mao and mer discover that tuples now squash - * t_bits. Why is this? - * - * 24 july 92: mer realizes that the t_bits field is only - * used in the event of null values. If no - * fields are null we reduce the header size - * by doing the squash. t_hoff tells you exactly - * how big the header actually is. use the PC - * means of getting at sys cat attrs. - */ - tup_db = (Form_pg_database)GETSTRUCT(tup); - - if (strncmp(GetDatabaseName(), - &(tup_db->datname.data[0]), - 16) == 0) - { - MyDatabaseId = tup->t_oid; - goto done; - } - } - } - - done: - close(dbfd); - pfree(pg); - - if (!OidIsValid(MyDatabaseId)) - elog(FATAL, - "Database %s does not exist in %s", - GetDatabaseName(), - DatabaseRelationName); + int dbfd; + int fileflags; + int nbytes; + int max, + i; + HeapTuple tup; + Page pg; + PageHeader ph; + char *dbfname; + Form_pg_database tup_db; + + /* + * At bootstrap time, we don't need to check the oid of the database + * in use, since we're not using shared memory. This is lucky, since + * the database may not be in the tables yet. + */ + + if (IsBootstrapProcessingMode()) + { + LockDisable(true); + return; + } + + dbfname = (char *) palloc(strlen(DataDir) + strlen("pg_database") + 2); + sprintf(dbfname, "%s%cpg_database", DataDir, SEP_CHAR); + fileflags = O_RDONLY; + + if ((dbfd = open(dbfname, O_RDONLY, 0)) < 0) + elog(FATAL, "Cannot open %s", dbfname); + + pfree(dbfname); + + /* ---------------- + * read and examine every page in pg_database + * + * Raw I/O! Read those tuples the hard way! Yow! + * + * Why don't we use the access methods or move this code + * someplace else? This is really pg_database schema dependent + * code. Perhaps it should go in lib/catalog/pg_database? + * -cim 10/3/90 + * + * mao replies 4 apr 91: yeah, maybe this should be moved to + * lib/catalog. however, we CANNOT use the access methods since + * those use the buffer cache, which uses the relation cache, which + * requires that the dbid be set, which is what we're trying to do + * here. + * ---------------- + */ + pg = (Page) palloc(BLCKSZ); + ph = (PageHeader) pg; + + while ((nbytes = read(dbfd, pg, BLCKSZ)) == BLCKSZ) + { + max = PageGetMaxOffsetNumber(pg); + + /* look at each tuple on the page */ + for (i = 0; i <= max; i++) + { + int offset; + + /* if it's a freed tuple, ignore it */ + if (!(ph->pd_linp[i].lp_flags & LP_USED)) + continue; + + /* get a pointer to the tuple itself */ + offset = (int) ph->pd_linp[i].lp_off; + tup = (HeapTuple) (((char *) pg) + offset); + + /* + * if the tuple has been deleted (the database was destroyed), + * skip this tuple. XXX warning, will robinson: violation of + * transaction semantics happens right here. we should check + * to be sure that the xact that deleted this tuple actually + * committed. only way to do this at init time is to paw over + * the log relation by hand, too. let's be optimistic. + * + * XXX This is an evil type cast. tup->t_xmax is char[5] while + * TransactionId is struct * { char data[5] }. It works but + * if data is ever moved and no longer the first field this + * will be broken!! -mer 11 Nov 1991. + */ + if (TransactionIdIsValid((TransactionId) tup->t_xmax)) + continue; + + /* + * Okay, see if this is the one we want. XXX 1 july 91: mao + * and mer discover that tuples now squash t_bits. Why is + * this? + * + * 24 july 92: mer realizes that the t_bits field is only used + * in the event of null values. If no fields are null we + * reduce the header size by doing the squash. t_hoff tells + * you exactly how big the header actually is. use the PC + * means of getting at sys cat attrs. + */ + tup_db = (Form_pg_database) GETSTRUCT(tup); + + if (strncmp(GetDatabaseName(), + &(tup_db->datname.data[0]), + 16) == 0) + { + MyDatabaseId = tup->t_oid; + goto done; + } + } + } + +done: + close(dbfd); + pfree(pg); + + if (!OidIsValid(MyDatabaseId)) + elog(FATAL, + "Database %s does not exist in %s", + GetDatabaseName(), + DatabaseRelationName); } /* * DoChdirAndInitDatabaseNameAndPath -- - * Set current directory to the database directory for the database - * named <name>. - * Also set global variables DatabasePath and DatabaseName to those - * values. Also check for proper version of database system and - * database. Exit program via elog() if anything doesn't check out. + * Set current directory to the database directory for the database + * named <name>. + * Also set global variables DatabasePath and DatabaseName to those + * values. Also check for proper version of database system and + * database. Exit program via elog() if anything doesn't check out. * * Arguments: - * Path and name are invalid if it invalid as a string. - * Path is "badly formated" if it is not a string containing a path - * to a writable directory. - * Name is "badly formated" if it contains more than 16 characters or if - * it is a bad file name (e.g., it contains a '/' or an 8-bit character). + * Path and name are invalid if it invalid as a string. + * Path is "badly formated" if it is not a string containing a path + * to a writable directory. + * Name is "badly formated" if it contains more than 16 characters or if + * it is a bad file name (e.g., it contains a '/' or an 8-bit character). * * Exceptions: - * BadState if called more than once. - * BadArg if both path and name are "badly formated" or invalid. - * BadArg if path and name are both "inconsistent" and valid. + * BadState if called more than once. + * BadArg if both path and name are "badly formated" or invalid. + * BadArg if path and name are both "inconsistent" and valid. * - * This routine is inappropriate in bootstrap mode, since the directories - * and version files need not exist yet if we're in bootstrap mode. + * This routine is inappropriate in bootstrap mode, since the directories + * and version files need not exist yet if we're in bootstrap mode. */ static void -DoChdirAndInitDatabaseNameAndPath(char *name) { - char *reason; - /* Failure reason returned by some function. NULL if no failure */ - int fd; - char errormsg[1000]; - - if ((fd = open(DataDir, O_RDONLY,0)) == -1) - sprintf(errormsg, "Database system does not exist. " - "PGDATA directory '%s' not found. Normally, you " - "create a database system by running initdb.", - DataDir); - else { - char myPath[MAXPGPATH]; /* DatabasePath points here! */ - - close(fd); - if (strlen(DataDir) + strlen(name) + 10 > sizeof(myPath)) - sprintf(errormsg, "Internal error in postinit.c: database " - "pathname exceeds maximum allowable length."); - else { - sprintf(myPath, "%s/base/%s", DataDir, name); - - if ((fd = open(myPath, O_RDONLY,0)) == -1) - sprintf(errormsg, - "Database '%s' does not exist. " - "(We know this because the directory '%s' " - "does not exist). You can create a database " - "with the SQL command CREATE DATABASE. To see " - "what databases exist, look at the subdirectories " - "of '%s/base/'.", - name, myPath, DataDir); - else { - close(fd); - ValidatePgVersion(DataDir, &reason); - if (reason != NULL) - sprintf(errormsg, - "InitPostgres could not validate that the database " - "system version is compatible with this level of " - "Postgres. You may need to run initdb to create " - "a new database system. %s", - reason); - else { - ValidatePgVersion(myPath, &reason); - if (reason != NULL) - sprintf(errormsg, - "InitPostgres could not validate that the " - "database version is compatible with this level " - "of Postgres, even though the database system " - "as a whole appears to be at a compatible level. " - "You may need to recreate the database with SQL " - "commands DROP DATABASE and CREATE DATABASE. " - "%s", - reason); - else { - /* The directories and PG_VERSION files are in order.*/ - int rc; /* return code from some function we call */ - - SetDatabasePath(myPath); - SetDatabaseName(name); - rc = chdir(myPath); - if (rc < 0) - sprintf(errormsg, - "InitPostgres unable to change " - "current directory to '%s', errno = %s (%d).", - myPath, strerror(errno), errno); - else errormsg[0] = '\0'; - } - } - } - } - } - if (errormsg[0] != '\0') - elog(FATAL, errormsg); - /* Above does not return */ +DoChdirAndInitDatabaseNameAndPath(char *name) +{ + char *reason; + + /* Failure reason returned by some function. NULL if no failure */ + int fd; + char errormsg[1000]; + + if ((fd = open(DataDir, O_RDONLY, 0)) == -1) + sprintf(errormsg, "Database system does not exist. " + "PGDATA directory '%s' not found. Normally, you " + "create a database system by running initdb.", + DataDir); + else + { + char myPath[MAXPGPATH]; /* DatabasePath points + * here! */ + + close(fd); + if (strlen(DataDir) + strlen(name) + 10 > sizeof(myPath)) + sprintf(errormsg, "Internal error in postinit.c: database " + "pathname exceeds maximum allowable length."); + else + { + sprintf(myPath, "%s/base/%s", DataDir, name); + + if ((fd = open(myPath, O_RDONLY, 0)) == -1) + sprintf(errormsg, + "Database '%s' does not exist. " + "(We know this because the directory '%s' " + "does not exist). You can create a database " + "with the SQL command CREATE DATABASE. To see " + "what databases exist, look at the subdirectories " + "of '%s/base/'.", + name, myPath, DataDir); + else + { + close(fd); + ValidatePgVersion(DataDir, &reason); + if (reason != NULL) + sprintf(errormsg, + "InitPostgres could not validate that the database " + "system version is compatible with this level of " + "Postgres. You may need to run initdb to create " + "a new database system. %s", + reason); + else + { + ValidatePgVersion(myPath, &reason); + if (reason != NULL) + sprintf(errormsg, + "InitPostgres could not validate that the " + "database version is compatible with this level " + "of Postgres, even though the database system " + "as a whole appears to be at a compatible level. " + "You may need to recreate the database with SQL " + "commands DROP DATABASE and CREATE DATABASE. " + "%s", + reason); + else + { + + /* + * The directories and PG_VERSION files are in + * order. + */ + int rc; /* return code from some + * function we call */ + + SetDatabasePath(myPath); + SetDatabaseName(name); + rc = chdir(myPath); + if (rc < 0) + sprintf(errormsg, + "InitPostgres unable to change " + "current directory to '%s', errno = %s (%d).", + myPath, strerror(errno), errno); + else + errormsg[0] = '\0'; + } + } + } + } + } + if (errormsg[0] != '\0') + elog(FATAL, errormsg); + /* Above does not return */ } /* -------------------------------- - * InitUserid + * InitUserid * - * initializes crap associated with the user id. + * initializes crap associated with the user id. * -------------------------------- */ static void InitUserid() { - setuid(geteuid()); - SetUserId(); + setuid(geteuid()); + SetUserId(); } /* -------------------------------- - * InitCommunication + * InitCommunication * - * This routine initializes stuff needed for ipc, locking, etc. - * it should be called something more informative. + * This routine initializes stuff needed for ipc, locking, etc. + * it should be called something more informative. * * Note: - * This does not set MyBackendId. MyBackendTag is set, however. + * This does not set MyBackendId. MyBackendTag is set, however. * -------------------------------- */ static void InitCommunication() { - char *postid; - char *postport; - IPCKey key = 0; - - /* ---------------- - * try and get the backend tag from POSTID - * ---------------- - */ - MyBackendId = -1; - - postid = getenv("POSTID"); - if (!PointerIsValid(postid)) { - MyBackendTag = -1; - } else { - MyBackendTag = atoi(postid); - Assert(MyBackendTag >= 0); - } - - /* ---------------- - * try and get the ipc key from POSTPORT - * ---------------- - */ - postport = getenv("POSTPORT"); - - if (PointerIsValid(postport)) { - SystemPortAddress address = atoi(postport); - - if (address == 0) - elog(FATAL, "InitCommunication: invalid POSTPORT"); - - if (MyBackendTag == -1) - elog(FATAL, "InitCommunication: missing POSTID"); - - key = SystemPortAddressCreateIPCKey(address); - - /* - * Enable this if you are trying to force the backend to run as if it - * is running under the postmaster. - * - * This goto forces Postgres to attach to shared memory instead of - * using malloc'ed memory (which is the normal behavior if run - * directly). - * - * To enable emulation, run the following shell commands (in addition - * to enabling this goto) - * - * % setenv POSTID 1 - * % setenv POSTPORT 4321 - * % postmaster & - * % kill -9 %1 - * - * Upon doing this, Postmaster will have allocated the shared memory - * resources that Postgres will attach to if you enable - * EMULATE_UNDER_POSTMASTER. - * - * This comment may well age with time - it is current as of - * 8 January 1990 - * - * Greg - */ - + char *postid; + char *postport; + IPCKey key = 0; + + /* ---------------- + * try and get the backend tag from POSTID + * ---------------- + */ + MyBackendId = -1; + + postid = getenv("POSTID"); + if (!PointerIsValid(postid)) + { + MyBackendTag = -1; + } + else + { + MyBackendTag = atoi(postid); + Assert(MyBackendTag >= 0); + } + + /* ---------------- + * try and get the ipc key from POSTPORT + * ---------------- + */ + postport = getenv("POSTPORT"); + + if (PointerIsValid(postport)) + { + SystemPortAddress address = atoi(postport); + + if (address == 0) + elog(FATAL, "InitCommunication: invalid POSTPORT"); + + if (MyBackendTag == -1) + elog(FATAL, "InitCommunication: missing POSTID"); + + key = SystemPortAddressCreateIPCKey(address); + + /* + * Enable this if you are trying to force the backend to run as if + * it is running under the postmaster. + * + * This goto forces Postgres to attach to shared memory instead of + * using malloc'ed memory (which is the normal behavior if run + * directly). + * + * To enable emulation, run the following shell commands (in addition + * to enabling this goto) + * + * % setenv POSTID 1 % setenv POSTPORT 4321 % postmaster & % kill -9 + * %1 + * + * Upon doing this, Postmaster will have allocated the shared memory + * resources that Postgres will attach to if you enable + * EMULATE_UNDER_POSTMASTER. + * + * This comment may well age with time - it is current as of 8 + * January 1990 + * + * Greg + */ + #ifdef EMULATE_UNDER_POSTMASTER - - goto forcesharedmemory; - + + goto forcesharedmemory; + #endif - - } else if (IsUnderPostmaster) { - elog(FATAL, - "InitCommunication: under postmaster and POSTPORT not set"); - } else { - /* ---------------- - * assume we're running a postgres backend by itself with - * no front end or postmaster. - * ---------------- - */ - if (MyBackendTag == -1) { - MyBackendTag = 1; - } - - key = PrivateIPCKey; - } - - /* ---------------- - * initialize shared memory and semaphores appropriately. - * ---------------- - */ + + } + else if (IsUnderPostmaster) + { + elog(FATAL, + "InitCommunication: under postmaster and POSTPORT not set"); + } + else + { + /* ---------------- + * assume we're running a postgres backend by itself with + * no front end or postmaster. + * ---------------- + */ + if (MyBackendTag == -1) + { + MyBackendTag = 1; + } + + key = PrivateIPCKey; + } + + /* ---------------- + * initialize shared memory and semaphores appropriately. + * ---------------- + */ #ifdef EMULATE_UNDER_POSTMASTER - - forcesharedmemory: - + +forcesharedmemory: + #endif - - PostgresIpcKey = key; - AttachSharedMemoryAndSemaphores(key); + + PostgresIpcKey = key; + AttachSharedMemoryAndSemaphores(key); } /* -------------------------------- - * InitStdio + * InitStdio * - * this routine consists of a bunch of code fragments - * that used to be randomly scattered through cinit(). - * they all seem to do stuff associated with io. + * this routine consists of a bunch of code fragments + * that used to be randomly scattered through cinit(). + * they all seem to do stuff associated with io. * -------------------------------- */ static void InitStdio() { - DebugFileOpen(); + DebugFileOpen(); } /* -------------------------------- * InitPostgres -- - * Initialize POSTGRES. + * Initialize POSTGRES. * * Note: - * Be very careful with the order of calls in the InitPostgres function. + * Be very careful with the order of calls in the InitPostgres function. * -------------------------------- */ -bool PostgresIsInitialized = false; -extern int NBuffers; +bool PostgresIsInitialized = false; +extern int NBuffers; /* - * this global is used by wei for testing his code, but must be declared - * here rather than in postgres.c so that it's defined for cinterface.a - * applications. + * this global is used by wei for testing his code, but must be declared + * here rather than in postgres.c so that it's defined for cinterface.a + * applications. */ -/*int testFlag = 0;*/ -int lockingOff = 0; +/*int testFlag = 0;*/ +int lockingOff = 0; /* */ void -InitPostgres(char *name) /* database name */ +InitPostgres(char *name) /* database name */ { - bool bootstrap; /* true if BootstrapProcessing */ - - /* ---------------- - * see if we're running in BootstrapProcessing mode - * ---------------- - */ - bootstrap = IsBootstrapProcessingMode(); - - /* ---------------- - * turn on the exception handler. Note: we cannot use elog, Assert, - * AssertState, etc. until after exception handling is on. - * ---------------- - */ - EnableExceptionHandling(true); - - /* ---------------- - * A stupid check to make sure we don't call this more than once. - * But things like ReinitPostgres() get around this by just diddling - * the PostgresIsInitialized flag. - * ---------------- - */ - AssertState(!PostgresIsInitialized); - - /* ---------------- - * Memory system initialization. - * (we may call palloc after EnableMemoryContext()) - * - * Note EnableMemoryContext() must happen before EnablePortalManager(). - * ---------------- - */ - EnableMemoryContext(true); /* initializes the "top context" */ - EnablePortalManager(true); /* memory for portal/transaction stuff */ - - /* ---------------- - * initialize the backend local portal stack used by - * internal PQ function calls. see src/lib/libpq/be-dumpdata.c - * This is different from the "portal manager" so this goes here. - * -cim 2/12/91 - * ---------------- - */ - be_portalinit(); - - /* ---------------- - * attach to shared memory and semaphores, and initialize our - * input/output/debugging file descriptors. - * ---------------- - */ - InitCommunication(); - InitStdio(); - - /* - * initialize the local buffer manager - */ - InitLocalBuffer(); - - if (!TransactionFlushEnabled()) - on_exitpg(FlushBufferPool, (caddr_t) NULL); - - if (bootstrap) { - SetDatabasePath("."); - SetDatabaseName(name); - } else { - DoChdirAndInitDatabaseNameAndPath(name); - } - - /* ******************************** - * code after this point assumes we are in the proper directory! - * ******************************** - */ - - /* ---------------- - * initialize the database id used for system caches and lock tables - * ---------------- - */ - InitMyDatabaseId(); - - smgrinit(); - - /* ---------------- - * initialize the transaction system and the relation descriptor - * cache. Note we have to make certain the lock manager is off while - * we do this. - * ---------------- - */ - AmiTransactionOverride(IsBootstrapProcessingMode()); - LockDisable(true); - - /* - * Part of the initialization processing done here sets a read - * lock on pg_log. Since locking is disabled the set doesn't have - * intended effect of locking out writers, but this is ok, since - * we only lock it to examine AMI transaction status, and this is - * never written after initdb is done. -mer 15 June 1992 - */ - RelationInitialize(); /* pre-allocated reldescs created here */ - InitializeTransactionSystem(); /* pg_log,etc init/crash recovery here */ - - LockDisable(false); - - /* ---------------- - * anyone knows what this does? something having to do with - * system catalog cache invalidation in the case of multiple - * backends, I think -cim 10/3/90 - * Sets up MyBackendId a unique backend identifier. - * ---------------- - */ - InitSharedInvalidationState(); - - /* ---------------- - * Set up a per backend process in shared memory. Must be done after - * InitSharedInvalidationState() as it relies on MyBackendId being - * initialized already. XXX -mer 11 Aug 1991 - * ---------------- - */ - InitProcess(PostgresIpcKey); - - if (MyBackendId > MaxBackendId || MyBackendId <= 0) { - elog(FATAL, "cinit2: bad backend id %d (%d)", - MyBackendTag, - MyBackendId); - } - - /* ---------------- - * initialize the access methods. - * ---------------- - */ - initam(); - - /* ---------------- - * initialize all the system catalog caches. - * ---------------- - */ - zerocaches(); - InitCatalogCache(); - - /* ---------------- - * set ourselves to the proper user id and figure out our postgres - * user id. If we ever add security so that we check for valid - * postgres users, we might do it here. - * ---------------- - */ - InitUserid(); - - /* ---------------- - * ok, all done, now let's make sure we don't do it again. - * ---------------- - */ - PostgresIsInitialized = true; -/* on_exitpg(DestroyLocalRelList, (caddr_t) NULL); */ - - /* ---------------- - * Done with "InitPostgres", now change to NormalProcessing unless - * we're in BootstrapProcessing mode. - * ---------------- - */ - if (!bootstrap) - SetProcessingMode(NormalProcessing); -/* if (testFlag || lockingOff) */ - if (lockingOff) - LockDisable(true); -} + bool bootstrap; /* true if BootstrapProcessing */ + + /* ---------------- + * see if we're running in BootstrapProcessing mode + * ---------------- + */ + bootstrap = IsBootstrapProcessingMode(); + + /* ---------------- + * turn on the exception handler. Note: we cannot use elog, Assert, + * AssertState, etc. until after exception handling is on. + * ---------------- + */ + EnableExceptionHandling(true); + + /* ---------------- + * A stupid check to make sure we don't call this more than once. + * But things like ReinitPostgres() get around this by just diddling + * the PostgresIsInitialized flag. + * ---------------- + */ + AssertState(!PostgresIsInitialized); + + /* ---------------- + * Memory system initialization. + * (we may call palloc after EnableMemoryContext()) + * + * Note EnableMemoryContext() must happen before EnablePortalManager(). + * ---------------- + */ + EnableMemoryContext(true); /* initializes the "top context" */ + EnablePortalManager(true); /* memory for portal/transaction stuff */ + + /* ---------------- + * initialize the backend local portal stack used by + * internal PQ function calls. see src/lib/libpq/be-dumpdata.c + * This is different from the "portal manager" so this goes here. + * -cim 2/12/91 + * ---------------- + */ + be_portalinit(); + + /* ---------------- + * attach to shared memory and semaphores, and initialize our + * input/output/debugging file descriptors. + * ---------------- + */ + InitCommunication(); + InitStdio(); + + /* + * initialize the local buffer manager + */ + InitLocalBuffer(); + if (!TransactionFlushEnabled()) + on_exitpg(FlushBufferPool, (caddr_t) NULL); + if (bootstrap) + { + SetDatabasePath("."); + SetDatabaseName(name); + } + else + { + DoChdirAndInitDatabaseNameAndPath(name); + } + + /* + * ******************************** code after this point assumes we + * are in the proper directory! ******************************** + * + */ + + /* ---------------- + * initialize the database id used for system caches and lock tables + * ---------------- + */ + InitMyDatabaseId(); + + smgrinit(); + + /* ---------------- + * initialize the transaction system and the relation descriptor + * cache. Note we have to make certain the lock manager is off while + * we do this. + * ---------------- + */ + AmiTransactionOverride(IsBootstrapProcessingMode()); + LockDisable(true); + + /* + * Part of the initialization processing done here sets a read lock on + * pg_log. Since locking is disabled the set doesn't have intended + * effect of locking out writers, but this is ok, since we only lock + * it to examine AMI transaction status, and this is never written + * after initdb is done. -mer 15 June 1992 + */ + RelationInitialize(); /* pre-allocated reldescs created here */ + InitializeTransactionSystem(); /* pg_log,etc init/crash recovery + * here */ + + LockDisable(false); + + /* ---------------- + * anyone knows what this does? something having to do with + * system catalog cache invalidation in the case of multiple + * backends, I think -cim 10/3/90 + * Sets up MyBackendId a unique backend identifier. + * ---------------- + */ + InitSharedInvalidationState(); + + /* ---------------- + * Set up a per backend process in shared memory. Must be done after + * InitSharedInvalidationState() as it relies on MyBackendId being + * initialized already. XXX -mer 11 Aug 1991 + * ---------------- + */ + InitProcess(PostgresIpcKey); + + if (MyBackendId > MaxBackendId || MyBackendId <= 0) + { + elog(FATAL, "cinit2: bad backend id %d (%d)", + MyBackendTag, + MyBackendId); + } + + /* ---------------- + * initialize the access methods. + * ---------------- + */ + initam(); + + /* ---------------- + * initialize all the system catalog caches. + * ---------------- + */ + zerocaches(); + InitCatalogCache(); + + /* ---------------- + * set ourselves to the proper user id and figure out our postgres + * user id. If we ever add security so that we check for valid + * postgres users, we might do it here. + * ---------------- + */ + InitUserid(); + + /* ---------------- + * ok, all done, now let's make sure we don't do it again. + * ---------------- + */ + PostgresIsInitialized = true; +/* on_exitpg(DestroyLocalRelList, (caddr_t) NULL); */ + + /* ---------------- + * Done with "InitPostgres", now change to NormalProcessing unless + * we're in BootstrapProcessing mode. + * ---------------- + */ + if (!bootstrap) + SetProcessingMode(NormalProcessing); +/* if (testFlag || lockingOff) */ + if (lockingOff) + LockDisable(true); +} diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c index b939c2c05e1..57a9950dea3 100644 --- a/src/backend/utils/misc/superuser.c +++ b/src/backend/utils/misc/superuser.c @@ -2,16 +2,16 @@ * * superuser.c-- * - * The superuser() function. Determines if user has superuser privilege. + * The superuser() function. Determines if user has superuser privilege. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.2 1996/11/03 23:46:28 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.3 1997/09/07 04:53:52 momjian Exp $ * * DESCRIPTION - * See superuser(). + * See superuser(). *------------------------------------------------------------------------- */ @@ -20,20 +20,18 @@ #include <catalog/pg_user.h> bool -superuser(void) { +superuser(void) +{ /*-------------------------------------------------------------------------- - The Postgres user running this command has Postgres superuser - privileges. + The Postgres user running this command has Postgres superuser + privileges. --------------------------------------------------------------------------*/ - extern char *UserName; /* defined in global.c */ + extern char *UserName; /* defined in global.c */ - HeapTuple utup; + HeapTuple utup; - utup = SearchSysCacheTuple(USENAME, PointerGetDatum(UserName), - 0,0,0); - Assert(utup != NULL); - return ((Form_pg_user)GETSTRUCT(utup))->usesuper; + utup = SearchSysCacheTuple(USENAME, PointerGetDatum(UserName), + 0, 0, 0); + Assert(utup != NULL); + return ((Form_pg_user) GETSTRUCT(utup))->usesuper; } - - - diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 8e0482de38c..c07fb1bd587 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -1,33 +1,34 @@ /*------------------------------------------------------------------------- * * aset.c-- - * Allocation set definitions. + * Allocation set definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.5 1997/08/19 21:35:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.6 1997/09/07 04:54:01 momjian Exp $ * * NOTE - * XXX This is a preliminary implementation which lacks fail-fast - * XXX validity checking of arguments. + * XXX This is a preliminary implementation which lacks fail-fast + * XXX validity checking of arguments. * *------------------------------------------------------------------------- */ #include <stdio.h> #include "postgres.h" -#include "utils/excid.h" /* for ExhaustedMemory */ -#include "utils/memutils.h" /* where funnction declarations go */ +#include "utils/excid.h" /* for ExhaustedMemory */ +#include "utils/memutils.h" /* where funnction declarations go */ #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif -static void AllocPointerDump(AllocPointer pointer); -static int AllocSetIterate(AllocSet set, - void (*function)(AllocPointer pointer)); +static void AllocPointerDump(AllocPointer pointer); +static int +AllocSetIterate(AllocSet set, + void (*function) (AllocPointer pointer)); #undef AllocSetReset #undef malloc @@ -39,12 +40,13 @@ static int AllocSetIterate(AllocSet set, /* * AllocElem -- - * Allocation element. + * Allocation element. */ -typedef struct AllocElemData { - OrderedElemData elemData; /* elem in AllocSet */ - Size size; -} AllocElemData; +typedef struct AllocElemData +{ + OrderedElemData elemData; /* elem in AllocSet */ + Size size; +} AllocElemData; typedef AllocElemData *AllocElem; @@ -55,21 +57,21 @@ typedef AllocElemData *AllocElem; /* * AllocPointerGetAllocElem -- - * Returns allocation (internal) elem given (external) pointer. + * Returns allocation (internal) elem given (external) pointer. */ -#define AllocPointerGetAllocElem(pointer) (&((AllocElem)(pointer))[-1]) +#define AllocPointerGetAllocElem(pointer) (&((AllocElem)(pointer))[-1]) /* * AllocElemGetAllocPointer -- - * Returns allocation (external) pointer given (internal) elem. + * Returns allocation (external) pointer given (internal) elem. */ -#define AllocElemGetAllocPointer(alloc) ((AllocPointer)&(alloc)[1]) +#define AllocElemGetAllocPointer(alloc) ((AllocPointer)&(alloc)[1]) /* * AllocElemIsValid -- - * True iff alloc is valid. + * True iff alloc is valid. */ -#define AllocElemIsValid(alloc) PointerIsValid(alloc) +#define AllocElemIsValid(alloc) PointerIsValid(alloc) /* non-export function prototypes */ static AllocPointer AllocSetGetFirst(AllocSet set); @@ -79,242 +81,250 @@ static AllocPointer AllocPointerGetNext(AllocPointer pointer); * Public routines */ -/* - * AllocPointerIsValid(pointer) - * AllocSetIsValid(set) +/* + * AllocPointerIsValid(pointer) + * AllocSetIsValid(set) * - * .. are now macros in aset.h -cim 4/27/91 + * .. are now macros in aset.h -cim 4/27/91 */ /* * AllocSetInit -- - * Initializes given allocation set. + * Initializes given allocation set. * * Note: - * The semantics of the mode are explained above. Limit is ignored - * for dynamic and static modes. + * The semantics of the mode are explained above. Limit is ignored + * for dynamic and static modes. * * Exceptions: - * BadArg if set is invalid pointer. - * BadArg if mode is invalid. + * BadArg if set is invalid pointer. + * BadArg if mode is invalid. */ void AllocSetInit(AllocSet set, AllocMode mode, Size limit) { - AssertArg(PointerIsValid(set)); - AssertArg((int)DynamicAllocMode <= (int)mode); - AssertArg((int)mode <= (int)BoundedAllocMode); - - /* - * XXX mode is currently ignored and treated as DynamicAllocMode. - * XXX limit is also ignored. This affects this whole file. - */ - - OrderedSetInit(&set->setData, offsetof(AllocElemData, elemData)); + AssertArg(PointerIsValid(set)); + AssertArg((int) DynamicAllocMode <= (int) mode); + AssertArg((int) mode <= (int) BoundedAllocMode); + + /* + * XXX mode is currently ignored and treated as DynamicAllocMode. XXX + * limit is also ignored. This affects this whole file. + */ + + OrderedSetInit(&set->setData, offsetof(AllocElemData, elemData)); } /* * AllocSetReset -- - * Frees memory which is allocated in the given set. + * Frees memory which is allocated in the given set. * * Exceptions: - * BadArg if set is invalid. + * BadArg if set is invalid. */ void AllocSetReset(AllocSet set) { - AllocPointer pointer; - - AssertArg(AllocSetIsValid(set)); - - while (AllocPointerIsValid(pointer = AllocSetGetFirst(set))) { - AllocSetFree(set, pointer); - } + AllocPointer pointer; + + AssertArg(AllocSetIsValid(set)); + + while (AllocPointerIsValid(pointer = AllocSetGetFirst(set))) + { + AllocSetFree(set, pointer); + } } #ifdef NOT_USED void AllocSetReset_debug(char *file, int line, AllocSet set) { - AllocPointer pointer; - - AssertArg(AllocSetIsValid(set)); - - while (AllocPointerIsValid(pointer = AllocSetGetFirst(set))) { - AllocSetFree(set, pointer); - } + AllocPointer pointer; + + AssertArg(AllocSetIsValid(set)); + + while (AllocPointerIsValid(pointer = AllocSetGetFirst(set))) + { + AllocSetFree(set, pointer); + } } + #endif /* * AllocSetContains -- - * True iff allocation set contains given allocation element. + * True iff allocation set contains given allocation element. * * Exceptions: - * BadArg if set is invalid. - * BadArg if pointer is invalid. + * BadArg if set is invalid. + * BadArg if pointer is invalid. */ bool AllocSetContains(AllocSet set, AllocPointer pointer) { - AssertArg(AllocSetIsValid(set)); - AssertArg(AllocPointerIsValid(pointer)); - - return (OrderedSetContains(&set->setData, - &AllocPointerGetAllocElem(pointer)->elemData)); + AssertArg(AllocSetIsValid(set)); + AssertArg(AllocPointerIsValid(pointer)); + + return (OrderedSetContains(&set->setData, + &AllocPointerGetAllocElem(pointer)->elemData)); } /* * AllocSetAlloc -- - * Returns pointer to allocated memory of given size; memory is added - * to the set. + * Returns pointer to allocated memory of given size; memory is added + * to the set. * * Exceptions: - * BadArg if set is invalid. - * MemoryExhausted if allocation fails. + * BadArg if set is invalid. + * MemoryExhausted if allocation fails. */ AllocPointer AllocSetAlloc(AllocSet set, Size size) { - AllocElem alloc; - - AssertArg(AllocSetIsValid(set)); - - /* allocate */ - alloc = (AllocElem)malloc(sizeof (*alloc) + size); - - if (!PointerIsValid(alloc)) { - elog (FATAL, "palloc failure: memory exhausted"); - } - - /* add to allocation list */ - OrderedElemPushInto(&alloc->elemData, &set->setData); - - /* set size */ - alloc->size = size; - - return (AllocElemGetAllocPointer(alloc)); + AllocElem alloc; + + AssertArg(AllocSetIsValid(set)); + + /* allocate */ + alloc = (AllocElem) malloc(sizeof(*alloc) + size); + + if (!PointerIsValid(alloc)) + { + elog(FATAL, "palloc failure: memory exhausted"); + } + + /* add to allocation list */ + OrderedElemPushInto(&alloc->elemData, &set->setData); + + /* set size */ + alloc->size = size; + + return (AllocElemGetAllocPointer(alloc)); } /* * AllocSetFree -- - * Frees allocated memory; memory is removed from the set. + * Frees allocated memory; memory is removed from the set. * * Exceptions: - * BadArg if set is invalid. - * BadArg if pointer is invalid. - * BadArg if pointer is not member of set. + * BadArg if set is invalid. + * BadArg if pointer is invalid. + * BadArg if pointer is not member of set. */ void AllocSetFree(AllocSet set, AllocPointer pointer) { - AllocElem alloc; - - /* AssertArg(AllocSetIsValid(set)); */ - /* AssertArg(AllocPointerIsValid(pointer)); */ - AssertArg(AllocSetContains(set, pointer)); - - alloc = AllocPointerGetAllocElem(pointer); - - /* remove from allocation set */ - OrderedElemPop(&alloc->elemData); - - /* free storage */ - free(alloc); + AllocElem alloc; + + /* AssertArg(AllocSetIsValid(set)); */ + /* AssertArg(AllocPointerIsValid(pointer)); */ + AssertArg(AllocSetContains(set, pointer)); + + alloc = AllocPointerGetAllocElem(pointer); + + /* remove from allocation set */ + OrderedElemPop(&alloc->elemData); + + /* free storage */ + free(alloc); } /* * AllocSetRealloc -- - * Returns new pointer to allocated memory of given size; this memory - * is added to the set. Memory associated with given pointer is copied - * into the new memory, and the old memory is freed. + * Returns new pointer to allocated memory of given size; this memory + * is added to the set. Memory associated with given pointer is copied + * into the new memory, and the old memory is freed. * * Exceptions: - * BadArg if set is invalid. - * BadArg if pointer is invalid. - * BadArg if pointer is not member of set. - * MemoryExhausted if allocation fails. + * BadArg if set is invalid. + * BadArg if pointer is invalid. + * BadArg if pointer is not member of set. + * MemoryExhausted if allocation fails. */ AllocPointer AllocSetRealloc(AllocSet set, AllocPointer pointer, Size size) { - AllocPointer newPointer; - AllocElem alloc; - - /* AssertArg(AllocSetIsValid(set)); */ - /* AssertArg(AllocPointerIsValid(pointer)); */ - AssertArg(AllocSetContains(set, pointer)); - - /* - * Calling realloc(3) directly is not be possible (unless we use - * our own hacked version of malloc) since we must keep the - * allocations in the allocation set. - */ - - alloc = AllocPointerGetAllocElem(pointer); - - /* allocate new pointer */ - newPointer = AllocSetAlloc(set, size); - - /* fill new memory */ - memmove(newPointer, pointer, (alloc->size < size) ? alloc->size : size); - - /* free old pointer */ - AllocSetFree(set, pointer); - - return (newPointer); + AllocPointer newPointer; + AllocElem alloc; + + /* AssertArg(AllocSetIsValid(set)); */ + /* AssertArg(AllocPointerIsValid(pointer)); */ + AssertArg(AllocSetContains(set, pointer)); + + /* + * Calling realloc(3) directly is not be possible (unless we use our + * own hacked version of malloc) since we must keep the allocations in + * the allocation set. + */ + + alloc = AllocPointerGetAllocElem(pointer); + + /* allocate new pointer */ + newPointer = AllocSetAlloc(set, size); + + /* fill new memory */ + memmove(newPointer, pointer, (alloc->size < size) ? alloc->size : size); + + /* free old pointer */ + AllocSetFree(set, pointer); + + return (newPointer); } /* * AllocSetIterate -- - * Returns size of set. Iterates through set elements calling function - * (if valid) on each. + * Returns size of set. Iterates through set elements calling function + * (if valid) on each. * * Note: - * This was written as an aid to debugging. It is intended for - * debugging use only. + * This was written as an aid to debugging. It is intended for + * debugging use only. * * Exceptions: - * BadArg if set is invalid. + * BadArg if set is invalid. */ static int AllocSetIterate(AllocSet set, - void (*function)(AllocPointer pointer)) + void (*function) (AllocPointer pointer)) { - int count = 0; - AllocPointer pointer; - - AssertArg(AllocSetIsValid(set)); - - for (pointer = AllocSetGetFirst(set); - AllocPointerIsValid(pointer); - pointer = AllocPointerGetNext(pointer)) { - - if (PointerIsValid(function)) { - (*function)(pointer); + int count = 0; + AllocPointer pointer; + + AssertArg(AllocSetIsValid(set)); + + for (pointer = AllocSetGetFirst(set); + AllocPointerIsValid(pointer); + pointer = AllocPointerGetNext(pointer)) + { + + if (PointerIsValid(function)) + { + (*function) (pointer); + } + count += 1; } - count += 1; - } - - return (count); + + return (count); } #ifdef NOT_USED int AllocSetCount(AllocSet set) { - int count = 0; - AllocPointer pointer; - - AssertArg(AllocSetIsValid(set)); - - for (pointer = AllocSetGetFirst(set); - AllocPointerIsValid(pointer); - pointer = AllocPointerGetNext(pointer)) { - count++; - } - return count; + int count = 0; + AllocPointer pointer; + + AssertArg(AllocSetIsValid(set)); + + for (pointer = AllocSetGetFirst(set); + AllocPointerIsValid(pointer); + pointer = AllocPointerGetNext(pointer)) + { + count++; + } + return count; } + #endif /* @@ -323,45 +333,47 @@ AllocSetCount(AllocSet set) /* * AllocSetGetFirst -- - * Returns "first" allocation pointer in a set. + * Returns "first" allocation pointer in a set. * * Note: - * Assumes set is valid. + * Assumes set is valid. */ -static AllocPointer +static AllocPointer AllocSetGetFirst(AllocSet set) { - AllocElem alloc; - - alloc = (AllocElem)OrderedSetGetHead(&set->setData); - - if (!AllocElemIsValid(alloc)) { - return (NULL); - } - - return (AllocElemGetAllocPointer(alloc)); + AllocElem alloc; + + alloc = (AllocElem) OrderedSetGetHead(&set->setData); + + if (!AllocElemIsValid(alloc)) + { + return (NULL); + } + + return (AllocElemGetAllocPointer(alloc)); } /* * AllocPointerGetNext -- - * Returns "successor" allocation pointer. + * Returns "successor" allocation pointer. * * Note: - * Assumes pointer is valid. + * Assumes pointer is valid. */ -static AllocPointer +static AllocPointer AllocPointerGetNext(AllocPointer pointer) { - AllocElem alloc; - - alloc = (AllocElem) - OrderedElemGetSuccessor(&AllocPointerGetAllocElem(pointer)->elemData); - - if (!AllocElemIsValid(alloc)) { - return (NULL); - } - - return (AllocElemGetAllocPointer(alloc)); + AllocElem alloc; + + alloc = (AllocElem) + OrderedElemGetSuccessor(&AllocPointerGetAllocElem(pointer)->elemData); + + if (!AllocElemIsValid(alloc)) + { + return (NULL); + } + + return (AllocElemGetAllocPointer(alloc)); } @@ -371,22 +383,23 @@ AllocPointerGetNext(AllocPointer pointer) /* * XXX AllocPointerDump -- - * Displays allocated pointer. + * Displays allocated pointer. */ static void AllocPointerDump(AllocPointer pointer) { - printf("\t%-10ld@ %0#lx\n", ((long*)pointer)[-1], (long)pointer); /* XXX */ + printf("\t%-10ld@ %0#lx\n", ((long *) pointer)[-1], (long) pointer); /* XXX */ } /* * AllocSetDump -- - * Displays allocated set. + * Displays allocated set. */ void AllocSetDump(AllocSet set) { - int count; - count = AllocSetIterate(set, AllocPointerDump); - printf("\ttotal %d allocations\n", count); + int count; + + count = AllocSetIterate(set, AllocPointerDump); + printf("\ttotal %d allocations\n", count); } diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index df2eb480817..dbd1b6e19f6 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * mcxt.c-- - * POSTGRES memory context code. + * POSTGRES memory context code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.3 1997/08/19 21:35:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.4 1997/09/07 04:54:08 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* XXX for printf debugging */ +#include <stdio.h> /* XXX for printf debugging */ #include "postgres.h" @@ -35,90 +35,93 @@ /* * Global State */ -static int MemoryContextEnableCount = 0; +static int MemoryContextEnableCount = 0; + #define MemoryContextEnabled (MemoryContextEnableCount > 0) -static OrderedSetData ActiveGlobalMemorySetData; /* uninitialized */ +static OrderedSetData ActiveGlobalMemorySetData; /* uninitialized */ + #define ActiveGlobalMemorySet (&ActiveGlobalMemorySetData) /* * description of allocated memory representation goes here */ -#define PSIZE(PTR) (*((int32 *)(PTR) - 1)) +#define PSIZE(PTR) (*((int32 *)(PTR) - 1)) #define PSIZEALL(PTR) (*((int32 *)(PTR) - 1) + sizeof (int32)) #define PSIZESKIP(PTR) ((char *)((int32 *)(PTR) + 1)) #define PSIZEFIND(PTR) ((char *)((int32 *)(PTR) - 1)) -#define PSIZESPACE(LEN) ((LEN) + sizeof (int32)) +#define PSIZESPACE(LEN) ((LEN) + sizeof (int32)) /* * AllocSizeIsValid -- - * True iff 0 < size and size <= MaxAllocSize. + * True iff 0 < size and size <= MaxAllocSize. */ -#define AllocSizeIsValid(size) (0 < (size) && (size) <= MaxAllocSize) +#define AllocSizeIsValid(size) (0 < (size) && (size) <= MaxAllocSize) /***************************************************************************** - * GLOBAL MEMORY * + * GLOBAL MEMORY * *****************************************************************************/ /* * CurrentMemoryContext -- - * Memory context for general global allocations. + * Memory context for general global allocations. */ MemoryContext CurrentMemoryContext = NULL; /***************************************************************************** - * PRIVATE DEFINITIONS * + * PRIVATE DEFINITIONS * *****************************************************************************/ -static Pointer GlobalMemoryAlloc(GlobalMemory this, Size size); -static void GlobalMemoryFree(GlobalMemory this, Pointer pointer); -static Pointer GlobalMemoryRealloc(GlobalMemory this, Pointer pointer, - Size size); -static char *GlobalMemoryGetName(GlobalMemory this); -static void GlobalMemoryDump(GlobalMemory this); +static Pointer GlobalMemoryAlloc(GlobalMemory this, Size size); +static void GlobalMemoryFree(GlobalMemory this, Pointer pointer); +static Pointer +GlobalMemoryRealloc(GlobalMemory this, Pointer pointer, + Size size); +static char *GlobalMemoryGetName(GlobalMemory this); +static void GlobalMemoryDump(GlobalMemory this); + #ifdef NOT_USED -static void DumpGlobalMemories(void); +static void DumpGlobalMemories(void); + #endif /* * Global Memory Methods */ -static struct MemoryContextMethodsData GlobalContextMethodsData = { - GlobalMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ - GlobalMemoryFree, /* void (*)(this, Pointer) pfree */ - GlobalMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */ - GlobalMemoryGetName, /* char* (*)(this) getName */ - GlobalMemoryDump /* void (*)(this) dump */ +static struct MemoryContextMethodsData GlobalContextMethodsData = { + GlobalMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ + GlobalMemoryFree, /* void (*)(this, Pointer) pfree */ + GlobalMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */ + GlobalMemoryGetName, /* char* (*)(this) getName */ + GlobalMemoryDump /* void (*)(this) dump */ }; /* * Note: - * TopGlobalMemory is handled specially because of bootstrapping. + * TopGlobalMemory is handled specially because of bootstrapping. */ /* extern bool EqualGlobalMemory(); */ static struct GlobalMemory TopGlobalMemoryData = { - T_GlobalMemory, /* NodeTag tag */ - &GlobalContextMethodsData, /* ContextMethods method */ - { { 0 } }, /* uninitialized - * OrderedSetData allocSetD - */ - "TopGlobal", /* char* name */ - { 0 } /* uninitialized OrderedElemData elemD */ + T_GlobalMemory, /* NodeTag tag */ + &GlobalContextMethodsData, /* ContextMethods method */ + {{0}}, /* uninitialized OrderedSetData allocSetD */ + "TopGlobal", /* char* name */ + {0} /* uninitialized OrderedElemData elemD */ }; /* * TopMemoryContext -- - * Memory context for general global allocations. + * Memory context for general global allocations. * * Note: - * Don't use this memory context for random allocations. If you - * allocate something here, you are expected to clean it up when - * appropriate. + * Don't use this memory context for random allocations. If you + * allocate something here, you are expected to clean it up when + * appropriate. */ -MemoryContext TopMemoryContext = (MemoryContext)&TopGlobalMemoryData; +MemoryContext TopMemoryContext = (MemoryContext) & TopGlobalMemoryData; @@ -129,213 +132,223 @@ MemoryContext TopMemoryContext = (MemoryContext)&TopGlobalMemoryData; /* * EnableMemoryContext -- - * Enables/disables memory management and global contexts. + * Enables/disables memory management and global contexts. * * Note: - * This must be called before creating contexts or allocating memory. - * This must be called before other contexts are created. + * This must be called before creating contexts or allocating memory. + * This must be called before other contexts are created. * * Exceptions: - * BadArg if on is invalid. - * BadState if on is false when disabled. + * BadArg if on is invalid. + * BadState if on is false when disabled. */ void EnableMemoryContext(bool on) { - static bool processing = false; - - AssertState(!processing); - AssertArg(BoolIsValid(on)); - - if (BypassEnable(&MemoryContextEnableCount, on)) { - return; - } - - processing = true; - - if (on) { /* initialize */ - /* initialize TopGlobalMemoryData.setData */ - AllocSetInit(&TopGlobalMemoryData.setData, DynamicAllocMode, - (Size)0); - - /* make TopGlobalMemoryData member of ActiveGlobalMemorySet */ - OrderedSetInit(ActiveGlobalMemorySet, - offsetof(struct GlobalMemory, elemData)); - OrderedElemPushInto(&TopGlobalMemoryData.elemData, - ActiveGlobalMemorySet); - - /* initialize CurrentMemoryContext */ - CurrentMemoryContext = TopMemoryContext; - - } else { /* cleanup */ - GlobalMemory context; - - /* walk the list of allocations */ - while (PointerIsValid(context = (GlobalMemory) - OrderedSetGetHead(ActiveGlobalMemorySet))) { - - if (context == &TopGlobalMemoryData) { - /* don't free it and clean it last */ - OrderedElemPop(&TopGlobalMemoryData.elemData); - } else { - GlobalMemoryDestroy(context); - } - /* what is needed for the top? */ + static bool processing = false; + + AssertState(!processing); + AssertArg(BoolIsValid(on)); + + if (BypassEnable(&MemoryContextEnableCount, on)) + { + return; } - - /* - * Freeing memory here should be safe as this is called - * only after all modules which allocate in TopMemoryContext - * have been disabled. - */ - - /* step through remaining allocations and log */ - /* AllocSetStep(...); */ - - /* deallocate whatever is left */ - AllocSetReset(&TopGlobalMemoryData.setData); - } - - processing = false; + + processing = true; + + if (on) + { /* initialize */ + /* initialize TopGlobalMemoryData.setData */ + AllocSetInit(&TopGlobalMemoryData.setData, DynamicAllocMode, + (Size) 0); + + /* make TopGlobalMemoryData member of ActiveGlobalMemorySet */ + OrderedSetInit(ActiveGlobalMemorySet, + offsetof(struct GlobalMemory, elemData)); + OrderedElemPushInto(&TopGlobalMemoryData.elemData, + ActiveGlobalMemorySet); + + /* initialize CurrentMemoryContext */ + CurrentMemoryContext = TopMemoryContext; + + } + else + { /* cleanup */ + GlobalMemory context; + + /* walk the list of allocations */ + while (PointerIsValid(context = (GlobalMemory) + OrderedSetGetHead(ActiveGlobalMemorySet))) + { + + if (context == &TopGlobalMemoryData) + { + /* don't free it and clean it last */ + OrderedElemPop(&TopGlobalMemoryData.elemData); + } + else + { + GlobalMemoryDestroy(context); + } + /* what is needed for the top? */ + } + + /* + * Freeing memory here should be safe as this is called only after + * all modules which allocate in TopMemoryContext have been + * disabled. + */ + + /* step through remaining allocations and log */ + /* AllocSetStep(...); */ + + /* deallocate whatever is left */ + AllocSetReset(&TopGlobalMemoryData.setData); + } + + processing = false; } /* * MemoryContextAlloc -- - * Returns pointer to aligned allocated memory in the given context. + * Returns pointer to aligned allocated memory in the given context. * * Note: - * none + * none * * Exceptions: - * BadState if called before InitMemoryManager. - * BadArg if context is invalid or if size is 0. - * BadAllocSize if size is larger than MaxAllocSize. + * BadState if called before InitMemoryManager. + * BadArg if context is invalid or if size is 0. + * BadAllocSize if size is larger than MaxAllocSize. */ Pointer MemoryContextAlloc(MemoryContext context, Size size) { - AssertState(MemoryContextEnabled); - AssertArg(MemoryContextIsValid(context)); - - LogTrap(!AllocSizeIsValid(size), BadAllocSize, - ("size=%d [0x%x]", size, size)); - - return (context->method->alloc(context, size)); + AssertState(MemoryContextEnabled); + AssertArg(MemoryContextIsValid(context)); + + LogTrap(!AllocSizeIsValid(size), BadAllocSize, + ("size=%d [0x%x]", size, size)); + + return (context->method->alloc(context, size)); } /* * MemoryContextFree -- - * Frees allocated memory referenced by pointer in the given context. + * Frees allocated memory referenced by pointer in the given context. * * Note: - * none + * none * * Exceptions: - * ??? - * BadArgumentsErr if firstTime is true for subsequent calls. + * ??? + * BadArgumentsErr if firstTime is true for subsequent calls. */ void MemoryContextFree(MemoryContext context, Pointer pointer) { - AssertState(MemoryContextEnabled); - AssertArg(MemoryContextIsValid(context)); - AssertArg(PointerIsValid(pointer)); - - context->method->free_p(context, pointer); + AssertState(MemoryContextEnabled); + AssertArg(MemoryContextIsValid(context)); + AssertArg(PointerIsValid(pointer)); + + context->method->free_p(context, pointer); } /* * MemoryContextRelloc -- - * Returns pointer to aligned allocated memory in the given context. + * Returns pointer to aligned allocated memory in the given context. * * Note: - * none + * none * * Exceptions: - * ??? - * BadArgumentsErr if firstTime is true for subsequent calls. + * ??? + * BadArgumentsErr if firstTime is true for subsequent calls. */ Pointer MemoryContextRealloc(MemoryContext context, - Pointer pointer, - Size size) + Pointer pointer, + Size size) { - AssertState(MemoryContextEnabled); - AssertArg(MemoryContextIsValid(context)); - AssertArg(PointerIsValid(pointer)); - - LogTrap(!AllocSizeIsValid(size), BadAllocSize, - ("size=%d [0x%x]", size, size)); - - return (context->method->realloc(context, pointer, size)); + AssertState(MemoryContextEnabled); + AssertArg(MemoryContextIsValid(context)); + AssertArg(PointerIsValid(pointer)); + + LogTrap(!AllocSizeIsValid(size), BadAllocSize, + ("size=%d [0x%x]", size, size)); + + return (context->method->realloc(context, pointer, size)); } /* * MemoryContextGetName -- - * Returns pointer to aligned allocated memory in the given context. + * Returns pointer to aligned allocated memory in the given context. * * Note: - * none + * none * * Exceptions: - * ??? - * BadArgumentsErr if firstTime is true for subsequent calls. + * ??? + * BadArgumentsErr if firstTime is true for subsequent calls. */ #ifdef NOT_USED -char* +char * MemoryContextGetName(MemoryContext context) { - AssertState(MemoryContextEnabled); - AssertArg(MemoryContextIsValid(context)); - - return (context->method->getName(context)); + AssertState(MemoryContextEnabled); + AssertArg(MemoryContextIsValid(context)); + + return (context->method->getName(context)); } + #endif /* * PointerGetAllocSize -- - * Returns size of aligned allocated memory given pointer to it. + * Returns size of aligned allocated memory given pointer to it. * * Note: - * none + * none * * Exceptions: - * ??? - * BadArgumentsErr if firstTime is true for subsequent calls. + * ??? + * BadArgumentsErr if firstTime is true for subsequent calls. */ #ifdef NOT_USED Size PointerGetAllocSize(Pointer pointer) { - AssertState(MemoryContextEnabled); - AssertArg(PointerIsValid(pointer)); - - return (PSIZE(pointer)); + AssertState(MemoryContextEnabled); + AssertArg(PointerIsValid(pointer)); + + return (PSIZE(pointer)); } + #endif /* * MemoryContextSwitchTo -- - * Returns the current context; installs the given context. + * Returns the current context; installs the given context. * * Note: - * none + * none * * Exceptions: - * BadState if called when disabled. - * BadArg if context is invalid. + * BadState if called when disabled. + * BadArg if context is invalid. */ MemoryContext MemoryContextSwitchTo(MemoryContext context) { - MemoryContext old; - - AssertState(MemoryContextEnabled); - AssertArg(MemoryContextIsValid(context)); - - old = CurrentMemoryContext; - CurrentMemoryContext = context; - return (old); + MemoryContext old; + + AssertState(MemoryContextEnabled); + AssertArg(MemoryContextIsValid(context)); + + old = CurrentMemoryContext; + CurrentMemoryContext = context; + return (old); } /* @@ -343,174 +356,178 @@ MemoryContextSwitchTo(MemoryContext context) */ /* * CreateGlobalMemory -- - * Returns new global memory context. + * Returns new global memory context. * * Note: - * Assumes name is static. + * Assumes name is static. * * Exceptions: - * BadState if called when disabled. - * BadState if called outside TopMemoryContext (TopGlobalMemory). - * BadArg if name is invalid. + * BadState if called when disabled. + * BadState if called outside TopMemoryContext (TopGlobalMemory). + * BadArg if name is invalid. */ GlobalMemory -CreateGlobalMemory(char *name) /* XXX MemoryContextName */ +CreateGlobalMemory(char *name) /* XXX MemoryContextName */ { - GlobalMemory context; - MemoryContext savecxt; - - AssertState(MemoryContextEnabled); - - savecxt = MemoryContextSwitchTo(TopMemoryContext); - - context = (GlobalMemory)newNode(sizeof(struct GlobalMemory), T_GlobalMemory); - context->method = &GlobalContextMethodsData; - context->name = name; /* assumes name is static */ - AllocSetInit(&context->setData, DynamicAllocMode, (Size)0); - - /* link the context */ - OrderedElemPushInto(&context->elemData, ActiveGlobalMemorySet); - - MemoryContextSwitchTo(savecxt); - return (context); + GlobalMemory context; + MemoryContext savecxt; + + AssertState(MemoryContextEnabled); + + savecxt = MemoryContextSwitchTo(TopMemoryContext); + + context = (GlobalMemory) newNode(sizeof(struct GlobalMemory), T_GlobalMemory); + context->method = &GlobalContextMethodsData; + context->name = name; /* assumes name is static */ + AllocSetInit(&context->setData, DynamicAllocMode, (Size) 0); + + /* link the context */ + OrderedElemPushInto(&context->elemData, ActiveGlobalMemorySet); + + MemoryContextSwitchTo(savecxt); + return (context); } /* * GlobalMemoryDestroy -- - * Destroys given global memory context. + * Destroys given global memory context. * * Exceptions: - * BadState if called when disabled. - * BadState if called outside TopMemoryContext (TopGlobalMemory). - * BadArg if context is invalid GlobalMemory. - * BadArg if context is TopMemoryContext (TopGlobalMemory). + * BadState if called when disabled. + * BadState if called outside TopMemoryContext (TopGlobalMemory). + * BadArg if context is invalid GlobalMemory. + * BadArg if context is TopMemoryContext (TopGlobalMemory). */ void GlobalMemoryDestroy(GlobalMemory context) { - AssertState(MemoryContextEnabled); - AssertArg(IsA(context,GlobalMemory)); - AssertArg(context != &TopGlobalMemoryData); - - AllocSetReset(&context->setData); - - /* unlink and delete the context */ - OrderedElemPop(&context->elemData); - MemoryContextFree(TopMemoryContext, (Pointer)context); + AssertState(MemoryContextEnabled); + AssertArg(IsA(context, GlobalMemory)); + AssertArg(context != &TopGlobalMemoryData); + + AllocSetReset(&context->setData); + + /* unlink and delete the context */ + OrderedElemPop(&context->elemData); + MemoryContextFree(TopMemoryContext, (Pointer) context); } /***************************************************************************** - * PRIVATE * + * PRIVATE * *****************************************************************************/ /* * GlobalMemoryAlloc -- - * Returns pointer to aligned space in the global context. + * Returns pointer to aligned space in the global context. * * Exceptions: - * ExhaustedMemory if allocation fails. + * ExhaustedMemory if allocation fails. */ -static Pointer +static Pointer GlobalMemoryAlloc(GlobalMemory this, Size size) { - return (AllocSetAlloc(&this->setData, size)); + return (AllocSetAlloc(&this->setData, size)); } /* * GlobalMemoryFree -- - * Frees allocated memory in the global context. + * Frees allocated memory in the global context. * * Exceptions: - * BadContextErr if current context is not the global context. - * BadArgumentsErr if pointer is invalid. + * BadContextErr if current context is not the global context. + * BadArgumentsErr if pointer is invalid. */ static void GlobalMemoryFree(GlobalMemory this, - Pointer pointer) + Pointer pointer) { - AllocSetFree(&this->setData, pointer); + AllocSetFree(&this->setData, pointer); } /* * GlobalMemoryRealloc -- - * Returns pointer to aligned space in the global context. + * Returns pointer to aligned space in the global context. * * Note: - * Memory associated with the pointer is freed before return. + * Memory associated with the pointer is freed before return. * * Exceptions: - * BadContextErr if current context is not the global context. - * BadArgumentsErr if pointer is invalid. - * NoMoreMemoryErr if allocation fails. + * BadContextErr if current context is not the global context. + * BadArgumentsErr if pointer is invalid. + * NoMoreMemoryErr if allocation fails. */ -static Pointer +static Pointer GlobalMemoryRealloc(GlobalMemory this, - Pointer pointer, - Size size) + Pointer pointer, + Size size) { - return (AllocSetRealloc(&this->setData, pointer, size)); + return (AllocSetRealloc(&this->setData, pointer, size)); } /* * GlobalMemoryGetName -- - * Returns name string for context. + * Returns name string for context. * * Exceptions: - * ??? + * ??? */ -static char* +static char * GlobalMemoryGetName(GlobalMemory this) { - return (this->name); + return (this->name); } /* * GlobalMemoryDump -- - * Dumps global memory context for debugging. + * Dumps global memory context for debugging. * * Exceptions: - * ??? + * ??? */ static void GlobalMemoryDump(GlobalMemory this) { - GlobalMemory context; - - printf("--\n%s:\n", GlobalMemoryGetName(this)); - - context = (GlobalMemory)OrderedElemGetPredecessor(&this->elemData); - if (PointerIsValid(context)) { - printf("\tpredecessor=%s\n", GlobalMemoryGetName(context)); - } - - context = (GlobalMemory)OrderedElemGetSuccessor(&this->elemData); - if (PointerIsValid(context)) { - printf("\tsucessor=%s\n", GlobalMemoryGetName(context)); - } - - AllocSetDump(&this->setData); /* XXX is this right interface */ + GlobalMemory context; + + printf("--\n%s:\n", GlobalMemoryGetName(this)); + + context = (GlobalMemory) OrderedElemGetPredecessor(&this->elemData); + if (PointerIsValid(context)) + { + printf("\tpredecessor=%s\n", GlobalMemoryGetName(context)); + } + + context = (GlobalMemory) OrderedElemGetSuccessor(&this->elemData); + if (PointerIsValid(context)) + { + printf("\tsucessor=%s\n", GlobalMemoryGetName(context)); + } + + AllocSetDump(&this->setData); /* XXX is this right interface */ } /* * DumpGlobalMemories -- - * Dumps all global memory contexts for debugging. + * Dumps all global memory contexts for debugging. * * Exceptions: - * ??? + * ??? */ #ifdef NOT_USED static void DumpGlobalMemories() { - GlobalMemory context; - - context = (GlobalMemory)OrderedSetGetHead(&ActiveGlobalMemorySetData); - - while (PointerIsValid(context)) { - GlobalMemoryDump(context); - - context = (GlobalMemory)OrderedElemGetSuccessor( - &context->elemData); - } + GlobalMemory context; + + context = (GlobalMemory) OrderedSetGetHead(&ActiveGlobalMemorySetData); + + while (PointerIsValid(context)) + { + GlobalMemoryDump(context); + + context = (GlobalMemory) OrderedElemGetSuccessor( + &context->elemData); + } } + #endif diff --git a/src/backend/utils/mmgr/oset.c b/src/backend/utils/mmgr/oset.c index 6b42ee45d72..758b701ff55 100644 --- a/src/backend/utils/mmgr/oset.c +++ b/src/backend/utils/mmgr/oset.c @@ -1,39 +1,39 @@ /*------------------------------------------------------------------------- * * oset.c-- - * Fixed format ordered set definitions. + * Fixed format ordered set definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/oset.c,v 1.3 1997/08/24 23:07:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/oset.c,v 1.4 1997/09/07 04:54:11 momjian Exp $ * * NOTE - * XXX This is a preliminary implementation which lacks fail-fast - * XXX validity checking of arguments. + * XXX This is a preliminary implementation which lacks fail-fast + * XXX validity checking of arguments. * *------------------------------------------------------------------------- */ #include "c.h" -#include "utils/memutils.h" /* where declarations of this file goes */ +#include "utils/memutils.h" /* where declarations of this file goes */ -static Pointer OrderedElemGetBase(OrderedElem elem); -static void OrderedElemPush(OrderedElem elem); -static void OrderedElemPushHead(OrderedElem elem); +static Pointer OrderedElemGetBase(OrderedElem elem); +static void OrderedElemPush(OrderedElem elem); +static void OrderedElemPushHead(OrderedElem elem); /* * OrderedElemGetBase -- - * Returns base of enclosing structure. + * Returns base of enclosing structure. */ -static Pointer +static Pointer OrderedElemGetBase(OrderedElem elem) { - if (elem == (OrderedElem) NULL) - return (Pointer) NULL; - - return ((Pointer)((char*)(elem) - (elem)->set->offset)); + if (elem == (OrderedElem) NULL) + return (Pointer) NULL; + + return ((Pointer) ((char *) (elem) - (elem)->set->offset)); } /* @@ -42,20 +42,20 @@ OrderedElemGetBase(OrderedElem elem) void OrderedSetInit(OrderedSet set, Offset offset) { - set->head = (OrderedElem)&set->dummy; - set->dummy = NULL; - set->tail = (OrderedElem)&set->head; - set->offset = offset; + set->head = (OrderedElem) & set->dummy; + set->dummy = NULL; + set->tail = (OrderedElem) & set->head; + set->offset = offset; } /* * OrderedSetContains -- - * True iff ordered set contains given element. + * True iff ordered set contains given element. */ bool OrderedSetContains(OrderedSet set, OrderedElem elem) { - return ((bool)(elem->set == set && (elem->next || elem->prev))); + return ((bool) (elem->set == set && (elem->next || elem->prev))); } /* @@ -64,13 +64,14 @@ OrderedSetContains(OrderedSet set, OrderedElem elem) Pointer OrderedSetGetHead(OrderedSet set) { - register OrderedElem elem; - - elem = set->head; - if (elem->next) { - return (OrderedElemGetBase(elem)); - } - return (NULL); + register OrderedElem elem; + + elem = set->head; + if (elem->next) + { + return (OrderedElemGetBase(elem)); + } + return (NULL); } /* @@ -80,14 +81,16 @@ OrderedSetGetHead(OrderedSet set) Pointer OrderedSetGetTail(OrderedSet set) { - register OrderedElem elem; - - elem = set->tail; - if (elem->prev) { - return (OrderedElemGetBase(elem)); - } - return (NULL); + register OrderedElem elem; + + elem = set->tail; + if (elem->prev) + { + return (OrderedElemGetBase(elem)); + } + return (NULL); } + #endif /* @@ -96,11 +99,12 @@ OrderedSetGetTail(OrderedSet set) Pointer OrderedElemGetPredecessor(OrderedElem elem) { - elem = elem->prev; - if (elem->prev) { - return (OrderedElemGetBase(elem)); - } - return (NULL); + elem = elem->prev; + if (elem->prev) + { + return (OrderedElemGetBase(elem)); + } + return (NULL); } /* @@ -109,24 +113,25 @@ OrderedElemGetPredecessor(OrderedElem elem) Pointer OrderedElemGetSuccessor(OrderedElem elem) { - elem = elem->next; - if (elem->next) { - return (OrderedElemGetBase(elem)); - } - return (NULL); + elem = elem->next; + if (elem->next) + { + return (OrderedElemGetBase(elem)); + } + return (NULL); } /* * OrderedElemPop -- */ -void +void OrderedElemPop(OrderedElem elem) { - elem->next->prev = elem->prev; - elem->prev->next = elem->next; - /* assignments used only for error detection */ - elem->next = NULL; - elem->prev = NULL; + elem->next->prev = elem->prev; + elem->prev->next = elem->next; + /* assignments used only for error detection */ + elem->next = NULL; + elem->prev = NULL; } /* @@ -135,11 +140,11 @@ OrderedElemPop(OrderedElem elem) void OrderedElemPushInto(OrderedElem elem, OrderedSet set) { - elem->set = set; - /* mark as unattached */ - elem->next = NULL; - elem->prev = NULL; - OrderedElemPush(elem); + elem->set = set; + /* mark as unattached */ + elem->next = NULL; + elem->prev = NULL; + OrderedElemPush(elem); } /* @@ -148,7 +153,7 @@ OrderedElemPushInto(OrderedElem elem, OrderedSet set) static void OrderedElemPush(OrderedElem elem) { - OrderedElemPushHead(elem); + OrderedElemPushHead(elem); } /* @@ -157,9 +162,8 @@ OrderedElemPush(OrderedElem elem) static void OrderedElemPushHead(OrderedElem elem) { - elem->next = elem->set->head; - elem->prev = (OrderedElem)&elem->set->head; - elem->next->prev = elem; - elem->prev->next = elem; + elem->next = elem->set->head; + elem->prev = (OrderedElem) & elem->set->head; + elem->next->prev = elem; + elem->prev->next = elem; } - diff --git a/src/backend/utils/mmgr/palloc.c b/src/backend/utils/mmgr/palloc.c index 8830a21f40a..f644706c911 100644 --- a/src/backend/utils/mmgr/palloc.c +++ b/src/backend/utils/mmgr/palloc.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * palloc.c-- - * POSTGRES memory allocator code. + * POSTGRES memory allocator code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/palloc.c,v 1.3 1996/11/26 03:19:12 bryanh Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/palloc.c,v 1.4 1997/09/07 04:54:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -25,7 +25,7 @@ #include "utils/palloc.h" /* ---------------------------------------------------------------- - * User library functions + * User library functions * ---------------------------------------------------------------- */ @@ -36,84 +36,84 @@ #undef malloc #undef free -/* define PALLOC_IS_MALLOC if you want palloc to go straight to the +/* define PALLOC_IS_MALLOC if you want palloc to go straight to the raw malloc, without concern for the extra bookkeeping needed to ensure garbage is collected at the end of transactions - jolly 1/12/94 */ /* * palloc -- - * Returns pointer to aligned memory of specified size. + * Returns pointer to aligned memory of specified size. * * Exceptions: - * BadArgument if size < 1 or size >= MaxAllocSize. - * ExhaustedMemory if allocation fails. - * NonallocatedPointer if pointer was not returned by palloc or repalloc - * or may have been freed already. + * BadArgument if size < 1 or size >= MaxAllocSize. + * ExhaustedMemory if allocation fails. + * NonallocatedPointer if pointer was not returned by palloc or repalloc + * or may have been freed already. * * pfree -- - * Frees memory associated with pointer returned from palloc or repalloc. + * Frees memory associated with pointer returned from palloc or repalloc. * * Exceptions: - * BadArgument if pointer is invalid. - * FreeInWrongContext if pointer was allocated in a different "context." - * NonallocatedPointer if pointer was not returned by palloc or repalloc - * or may have been subsequently freed. + * BadArgument if pointer is invalid. + * FreeInWrongContext if pointer was allocated in a different "context." + * NonallocatedPointer if pointer was not returned by palloc or repalloc + * or may have been subsequently freed. */ -void* +void * palloc(Size size) { #ifdef PALLOC_IS_MALLOC - return malloc(size); + return malloc(size); #else - return (MemoryContextAlloc(CurrentMemoryContext, size)); -#endif /* PALLOC_IS_MALLOC */ + return (MemoryContextAlloc(CurrentMemoryContext, size)); +#endif /* PALLOC_IS_MALLOC */ } void pfree(void *pointer) -{ +{ #ifdef PALLOC_IS_MALLOC - free(pointer); + free(pointer); #else - MemoryContextFree(CurrentMemoryContext, pointer); -#endif /* PALLOC_IS_MALLOC */ + MemoryContextFree(CurrentMemoryContext, pointer); +#endif /* PALLOC_IS_MALLOC */ } /* * repalloc -- - * Returns pointer to aligned memory of specified size. + * Returns pointer to aligned memory of specified size. * * Side effects: - * The returned memory is first filled with the contents of *pointer - * up to the minimum of size and psize(pointer). Pointer is freed. + * The returned memory is first filled with the contents of *pointer + * up to the minimum of size and psize(pointer). Pointer is freed. * * Exceptions: - * BadArgument if pointer is invalid or size < 1 or size >= MaxAllocSize. - * ExhaustedMemory if allocation fails. - * NonallocatedPointer if pointer was not returned by palloc or repalloc - * or may have been freed already. + * BadArgument if pointer is invalid or size < 1 or size >= MaxAllocSize. + * ExhaustedMemory if allocation fails. + * NonallocatedPointer if pointer was not returned by palloc or repalloc + * or may have been freed already. */ -void * +void * repalloc(void *pointer, Size size) { #ifdef PALLOC_IS_MALLOC - return realloc(pointer, size); + return realloc(pointer, size); #else - return (MemoryContextRealloc(CurrentMemoryContext, pointer, size)); + return (MemoryContextRealloc(CurrentMemoryContext, pointer, size)); #endif } -/* pstrdup - allocates space for and copies a string - just like strdup except it uses palloc instead of malloc */ -char* -pstrdup(char* string) +/* pstrdup + allocates space for and copies a string + just like strdup except it uses palloc instead of malloc */ +char * +pstrdup(char *string) { - char *nstr; + char *nstr; - nstr = (char *)palloc(strlen(string)+1); - strcpy(nstr, string); + nstr = (char *) palloc(strlen(string) + 1); + strcpy(nstr, string); - return nstr; + return nstr; } diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 7f1674d88db..595153b0ce6 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -1,86 +1,86 @@ /*------------------------------------------------------------------------- * * portalmem.c-- - * backend portal memory context management stuff + * backend portal memory context management stuff * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.5 1997/08/19 21:36:04 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.6 1997/09/07 04:54:13 momjian Exp $ * *------------------------------------------------------------------------- */ /* * NOTES - * Do not confuse "Portal" with "PortalEntry" (or "PortalBuffer"). - * When a PQexec() routine is run, the resulting tuples - * find their way into a "PortalEntry". The contents of the resulting - * "PortalEntry" can then be inspected by other PQxxx functions. - * - * A "Portal" is a structure used to keep track of queries of the - * form: - * retrieve portal FOO ( blah... ) where blah... - * - * When the backend sees a "retrieve portal" query, it allocates - * a "PortalD" structure, plans the query and then stores the query - * in the portal without executing it. Later, when the backend - * sees a - * fetch 1 into FOO - * - * the system looks up the portal named "FOO" in the portal table, - * gets the planned query and then calls the executor with a feature of - * '(EXEC_FOR 1). The executor then runs the query and returns a single - * tuple. The problem is that we have to hold onto the state of the - * portal query until we see a "close p". This means we have to be - * careful about memory management. - * - * Having said all that, here is what a PortalD currently looks like: + * Do not confuse "Portal" with "PortalEntry" (or "PortalBuffer"). + * When a PQexec() routine is run, the resulting tuples + * find their way into a "PortalEntry". The contents of the resulting + * "PortalEntry" can then be inspected by other PQxxx functions. + * + * A "Portal" is a structure used to keep track of queries of the + * form: + * retrieve portal FOO ( blah... ) where blah... + * + * When the backend sees a "retrieve portal" query, it allocates + * a "PortalD" structure, plans the query and then stores the query + * in the portal without executing it. Later, when the backend + * sees a + * fetch 1 into FOO + * + * the system looks up the portal named "FOO" in the portal table, + * gets the planned query and then calls the executor with a feature of + * '(EXEC_FOR 1). The executor then runs the query and returns a single + * tuple. The problem is that we have to hold onto the state of the + * portal query until we see a "close p". This means we have to be + * careful about memory management. + * + * Having said all that, here is what a PortalD currently looks like: * * struct PortalD { - * char* name; - * classObj(PortalVariableMemory) variable; - * classObj(PortalHeapMemory) heap; - * List queryDesc; - * EState state; - * void (*cleanup) ARGS((Portal portal)); + * char* name; + * classObj(PortalVariableMemory) variable; + * classObj(PortalHeapMemory) heap; + * List queryDesc; + * EState state; + * void (*cleanup) ARGS((Portal portal)); * }; * - * I hope this makes things clearer to whoever reads this -cim 2/22/91 + * I hope this makes things clearer to whoever reads this -cim 2/22/91 * - * Here is an old comment taken from nodes/memnodes.h + * Here is an old comment taken from nodes/memnodes.h * * MemoryContext -- - * A logical context in which memory allocations occur. + * A logical context in which memory allocations occur. * * The types of memory contexts can be thought of as members of the * following inheritance hierarchy with properties summarized below. * - * Node - * | - * MemoryContext___ - * / \ - * GlobalMemory PortalMemoryContext - * / \ - * PortalVariableMemory PortalHeapMemory + * Node + * | + * MemoryContext___ + * / \ + * GlobalMemory PortalMemoryContext + * / \ + * PortalVariableMemory PortalHeapMemory * - * Flushed at Flushed at Checkpoints - * Transaction Portal - * Commit Close + * Flushed at Flushed at Checkpoints + * Transaction Portal + * Commit Close * - * GlobalMemory n n n - * PortalVariableMemory n y n - * PortalHeapMemory y y y * + * GlobalMemory n n n + * PortalVariableMemory n y n + * PortalHeapMemory y y y * * */ -#include <stdio.h> /* for sprintf() */ -#include <string.h> /* for strlen, strncpy */ +#include <stdio.h> /* for sprintf() */ +#include <string.h> /* for strlen, strncpy */ #include "postgres.h" #include "lib/hasht.h" #include "utils/module.h" -#include "utils/excid.h" /* for Unimplemented */ +#include "utils/excid.h" /* for Unimplemented */ #include "utils/mcxt.h" #include "utils/hsearch.h" @@ -91,324 +91,330 @@ #include "utils/portal.h" -static void CollectNamedPortals(Portal *portalP, int destroy); -static Portal PortalHeapMemoryGetPortal(PortalHeapMemory context); +static void CollectNamedPortals(Portal * portalP, int destroy); +static Portal PortalHeapMemoryGetPortal(PortalHeapMemory context); static PortalVariableMemory PortalHeapMemoryGetVariableMemory(PortalHeapMemory context); -static void PortalResetHeapMemory(Portal portal); -static Portal PortalVariableMemoryGetPortal(PortalVariableMemory context); +static void PortalResetHeapMemory(Portal portal); +static Portal PortalVariableMemoryGetPortal(PortalVariableMemory context); /* ---------------- - * ALLOCFREE_ERROR_ABORT - * define this if you want a core dump when you try to - * free memory already freed -cim 2/9/91 + * ALLOCFREE_ERROR_ABORT + * define this if you want a core dump when you try to + * free memory already freed -cim 2/9/91 * ---------------- */ #undef ALLOCFREE_ERROR_ABORT /* ---------------- - * Global state + * Global state * ---------------- */ -static int PortalManagerEnableCount = 0; -#define MAX_PORTALNAME_LEN 64 /* XXX LONGALIGNable value */ +static int PortalManagerEnableCount = 0; -typedef struct portalhashent { - char portalname[MAX_PORTALNAME_LEN]; - Portal portal; -} PortalHashEnt; +#define MAX_PORTALNAME_LEN 64 /* XXX LONGALIGNable value */ + +typedef struct portalhashent +{ + char portalname[MAX_PORTALNAME_LEN]; + Portal portal; +} PortalHashEnt; #define PortalManagerEnabled (PortalManagerEnableCount >= 1) -static HTAB *PortalHashTable = NULL; +static HTAB *PortalHashTable = NULL; + #define PortalHashTableLookup(NAME, PORTAL) \ - { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ - memset(key, 0, MAX_PORTALNAME_LEN); \ - sprintf(key, "%s", NAME); \ - hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ - key, HASH_FIND, &found); \ - if (hentry == NULL) \ - elog(FATAL, "error in PortalHashTable"); \ - if (found) \ - PORTAL = hentry->portal; \ - else \ - PORTAL = NULL; \ - } + { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ + memset(key, 0, MAX_PORTALNAME_LEN); \ + sprintf(key, "%s", NAME); \ + hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ + key, HASH_FIND, &found); \ + if (hentry == NULL) \ + elog(FATAL, "error in PortalHashTable"); \ + if (found) \ + PORTAL = hentry->portal; \ + else \ + PORTAL = NULL; \ + } #define PortalHashTableInsert(PORTAL) \ - { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ - memset(key, 0, MAX_PORTALNAME_LEN); \ - sprintf(key, "%s", PORTAL->name); \ - hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ - key, HASH_ENTER, &found); \ - if (hentry == NULL) \ - elog(FATAL, "error in PortalHashTable"); \ - if (found) \ - elog(NOTICE, "trying to insert a portal name that exists."); \ - hentry->portal = PORTAL; \ - } + { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ + memset(key, 0, MAX_PORTALNAME_LEN); \ + sprintf(key, "%s", PORTAL->name); \ + hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ + key, HASH_ENTER, &found); \ + if (hentry == NULL) \ + elog(FATAL, "error in PortalHashTable"); \ + if (found) \ + elog(NOTICE, "trying to insert a portal name that exists."); \ + hentry->portal = PORTAL; \ + } #define PortalHashTableDelete(PORTAL) \ - { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ - memset(key, 0, MAX_PORTALNAME_LEN); \ - sprintf(key, "%s", PORTAL->name); \ - hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ - key, HASH_REMOVE, &found); \ - if (hentry == NULL) \ - elog(FATAL, "error in PortalHashTable"); \ - if (!found) \ - elog(NOTICE, "trying to delete portal name that does not exist."); \ - } - -static GlobalMemory PortalMemory = NULL; + { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ + memset(key, 0, MAX_PORTALNAME_LEN); \ + sprintf(key, "%s", PORTAL->name); \ + hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ + key, HASH_REMOVE, &found); \ + if (hentry == NULL) \ + elog(FATAL, "error in PortalHashTable"); \ + if (!found) \ + elog(NOTICE, "trying to delete portal name that does not exist."); \ + } + +static GlobalMemory PortalMemory = NULL; static char PortalMemoryName[] = "Portal"; -static Portal BlankPortal = NULL; +static Portal BlankPortal = NULL; /* ---------------- - * Internal class definitions + * Internal class definitions * ---------------- */ -typedef struct HeapMemoryBlockData { - AllocSetData setData; - FixedItemData itemData; -} HeapMemoryBlockData; +typedef struct HeapMemoryBlockData +{ + AllocSetData setData; + FixedItemData itemData; +} HeapMemoryBlockData; -typedef HeapMemoryBlockData *HeapMemoryBlock; +typedef HeapMemoryBlockData *HeapMemoryBlock; #define HEAPMEMBLOCK(context) \ - ((HeapMemoryBlock)(context)->block) + ((HeapMemoryBlock)(context)->block) /* ---------------------------------------------------------------- - * Variable and heap memory methods + * Variable and heap memory methods * ---------------------------------------------------------------- */ /* ---------------- - * PortalVariableMemoryAlloc + * PortalVariableMemoryAlloc * ---------------- */ -static Pointer +static Pointer PortalVariableMemoryAlloc(PortalVariableMemory this, - Size size) + Size size) { - return (AllocSetAlloc(&this->setData, size)); + return (AllocSetAlloc(&this->setData, size)); } /* ---------------- - * PortalVariableMemoryFree + * PortalVariableMemoryFree * ---------------- */ static void PortalVariableMemoryFree(PortalVariableMemory this, - Pointer pointer) + Pointer pointer) { - AllocSetFree(&this->setData, pointer); + AllocSetFree(&this->setData, pointer); } /* ---------------- - * PortalVariableMemoryRealloc + * PortalVariableMemoryRealloc * ---------------- */ -static Pointer +static Pointer PortalVariableMemoryRealloc(PortalVariableMemory this, - Pointer pointer, - Size size) + Pointer pointer, + Size size) { - return (AllocSetRealloc(&this->setData, pointer, size)); + return (AllocSetRealloc(&this->setData, pointer, size)); } /* ---------------- - * PortalVariableMemoryGetName + * PortalVariableMemoryGetName * ---------------- */ -static char* +static char * PortalVariableMemoryGetName(PortalVariableMemory this) { - return (form("%s-var", PortalVariableMemoryGetPortal(this)->name)); + return (form("%s-var", PortalVariableMemoryGetPortal(this)->name)); } /* ---------------- - * PortalVariableMemoryDump + * PortalVariableMemoryDump * ---------------- */ static void PortalVariableMemoryDump(PortalVariableMemory this) { - printf("--\n%s:\n", PortalVariableMemoryGetName(this)); - - AllocSetDump(&this->setData); /* XXX is this the right interface */ + printf("--\n%s:\n", PortalVariableMemoryGetName(this)); + + AllocSetDump(&this->setData); /* XXX is this the right interface */ } /* ---------------- - * PortalHeapMemoryAlloc + * PortalHeapMemoryAlloc * ---------------- */ -static Pointer +static Pointer PortalHeapMemoryAlloc(PortalHeapMemory this, - Size size) + Size size) { - HeapMemoryBlock block = HEAPMEMBLOCK(this); - - AssertState(PointerIsValid(block)); - - return (AllocSetAlloc(&block->setData, size)); + HeapMemoryBlock block = HEAPMEMBLOCK(this); + + AssertState(PointerIsValid(block)); + + return (AllocSetAlloc(&block->setData, size)); } /* ---------------- - * PortalHeapMemoryFree + * PortalHeapMemoryFree * ---------------- */ static void PortalHeapMemoryFree(PortalHeapMemory this, - Pointer pointer) -{ - HeapMemoryBlock block = HEAPMEMBLOCK(this); - - AssertState(PointerIsValid(block)); - - if (AllocSetContains(&block->setData, pointer)) - AllocSetFree(&block->setData, pointer); - else { - elog(NOTICE, - "PortalHeapMemoryFree: 0x%x not in alloc set!", - pointer); + Pointer pointer) +{ + HeapMemoryBlock block = HEAPMEMBLOCK(this); + + AssertState(PointerIsValid(block)); + + if (AllocSetContains(&block->setData, pointer)) + AllocSetFree(&block->setData, pointer); + else + { + elog(NOTICE, + "PortalHeapMemoryFree: 0x%x not in alloc set!", + pointer); #ifdef ALLOCFREE_ERROR_ABORT - Assert(AllocSetContains(&block->setData, pointer)); -#endif /* ALLOCFREE_ERROR_ABORT*/ - } + Assert(AllocSetContains(&block->setData, pointer)); +#endif /* ALLOCFREE_ERROR_ABORT */ + } } /* ---------------- - * PortalHeapMemoryRealloc + * PortalHeapMemoryRealloc * ---------------- */ -static Pointer +static Pointer PortalHeapMemoryRealloc(PortalHeapMemory this, - Pointer pointer, - Size size) + Pointer pointer, + Size size) { - HeapMemoryBlock block = HEAPMEMBLOCK(this); - - AssertState(PointerIsValid(block)); - - return (AllocSetRealloc(&block->setData, pointer, size)); + HeapMemoryBlock block = HEAPMEMBLOCK(this); + + AssertState(PointerIsValid(block)); + + return (AllocSetRealloc(&block->setData, pointer, size)); } /* ---------------- - * PortalHeapMemoryGetName + * PortalHeapMemoryGetName * ---------------- */ -static char* +static char * PortalHeapMemoryGetName(PortalHeapMemory this) { - return (form("%s-heap", PortalHeapMemoryGetPortal(this)->name)); + return (form("%s-heap", PortalHeapMemoryGetPortal(this)->name)); } /* ---------------- - * PortalHeapMemoryDump + * PortalHeapMemoryDump * ---------------- */ static void PortalHeapMemoryDump(PortalHeapMemory this) { - HeapMemoryBlock block; - - printf("--\n%s:\n", PortalHeapMemoryGetName(this)); - - /* XXX is this the right interface */ - if (PointerIsValid(this->block)) - AllocSetDump(&HEAPMEMBLOCK(this)->setData); - - /* dump the stack too */ - for (block = (HeapMemoryBlock)FixedStackGetTop(&this->stackData); - PointerIsValid(block); - block = (HeapMemoryBlock) - FixedStackGetNext(&this->stackData, (Pointer)block)) { - - printf("--\n"); - AllocSetDump(&block->setData); - } + HeapMemoryBlock block; + + printf("--\n%s:\n", PortalHeapMemoryGetName(this)); + + /* XXX is this the right interface */ + if (PointerIsValid(this->block)) + AllocSetDump(&HEAPMEMBLOCK(this)->setData); + + /* dump the stack too */ + for (block = (HeapMemoryBlock) FixedStackGetTop(&this->stackData); + PointerIsValid(block); + block = (HeapMemoryBlock) + FixedStackGetNext(&this->stackData, (Pointer) block)) + { + + printf("--\n"); + AllocSetDump(&block->setData); + } } /* ---------------------------------------------------------------- - * variable / heap context method tables + * variable / heap context method tables * ---------------------------------------------------------------- */ -static struct MemoryContextMethodsData PortalVariableContextMethodsData = { - PortalVariableMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ - PortalVariableMemoryFree, /* void (*)(this, Pointer) pfree */ - PortalVariableMemoryRealloc,/* Pointer (*)(this, Pointer) repalloc */ - PortalVariableMemoryGetName,/* char* (*)(this) getName */ - PortalVariableMemoryDump /* void (*)(this) dump */ +static struct MemoryContextMethodsData PortalVariableContextMethodsData = { + PortalVariableMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ + PortalVariableMemoryFree, /* void (*)(this, Pointer) pfree */ + PortalVariableMemoryRealloc,/* Pointer (*)(this, Pointer) repalloc */ + PortalVariableMemoryGetName,/* char* (*)(this) getName */ + PortalVariableMemoryDump /* void (*)(this) dump */ }; -static struct MemoryContextMethodsData PortalHeapContextMethodsData = { - PortalHeapMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ - PortalHeapMemoryFree, /* void (*)(this, Pointer) pfree */ - PortalHeapMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */ - PortalHeapMemoryGetName, /* char* (*)(this) getName */ - PortalHeapMemoryDump /* void (*)(this) dump */ +static struct MemoryContextMethodsData PortalHeapContextMethodsData = { + PortalHeapMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ + PortalHeapMemoryFree, /* void (*)(this, Pointer) pfree */ + PortalHeapMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */ + PortalHeapMemoryGetName, /* char* (*)(this) getName */ + PortalHeapMemoryDump /* void (*)(this) dump */ }; /* ---------------------------------------------------------------- - * private internal support routines + * private internal support routines * ---------------------------------------------------------------- */ /* ---------------- - * CreateNewBlankPortal + * CreateNewBlankPortal * ---------------- */ static void CreateNewBlankPortal() { - Portal portal; - - AssertState(!PortalIsValid(BlankPortal)); - - /* - * make new portal structure - */ - portal = (Portal) - MemoryContextAlloc((MemoryContext)PortalMemory, sizeof *portal); - - /* - * initialize portal variable context - */ - NodeSetTag((Node*)&portal->variable, T_PortalVariableMemory); - AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size)0); - portal->variable.method = &PortalVariableContextMethodsData; - - /* - * initialize portal heap context - */ - NodeSetTag((Node*)&portal->heap, T_PortalHeapMemory); - portal->heap.block = NULL; - FixedStackInit(&portal->heap.stackData, - offsetof (HeapMemoryBlockData, itemData)); - portal->heap.method = &PortalHeapContextMethodsData; - - /* - * set bogus portal name - */ - portal->name = "** Blank Portal **"; - - /* initialize portal query */ - portal->queryDesc = NULL; - portal->attinfo = NULL; - portal->state = NULL; - portal->cleanup = NULL; - - /* - * install blank portal - */ - BlankPortal = portal; + Portal portal; + + AssertState(!PortalIsValid(BlankPortal)); + + /* + * make new portal structure + */ + portal = (Portal) + MemoryContextAlloc((MemoryContext) PortalMemory, sizeof *portal); + + /* + * initialize portal variable context + */ + NodeSetTag((Node *) & portal->variable, T_PortalVariableMemory); + AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size) 0); + portal->variable.method = &PortalVariableContextMethodsData; + + /* + * initialize portal heap context + */ + NodeSetTag((Node *) & portal->heap, T_PortalHeapMemory); + portal->heap.block = NULL; + FixedStackInit(&portal->heap.stackData, + offsetof(HeapMemoryBlockData, itemData)); + portal->heap.method = &PortalHeapContextMethodsData; + + /* + * set bogus portal name + */ + portal->name = "** Blank Portal **"; + + /* initialize portal query */ + portal->queryDesc = NULL; + portal->attinfo = NULL; + portal->state = NULL; + portal->cleanup = NULL; + + /* + * install blank portal + */ + BlankPortal = portal; } bool PortalNameIsSpecial(char *pname) { - if (strcmp(pname, VACPNAME) == 0) - return true; - return false; + if (strcmp(pname, VACPNAME) == 0) + return true; + return false; } /* @@ -420,572 +426,586 @@ PortalNameIsSpecial(char *pname) * and screws up the sequential walk of the table). -mer 17 Aug 1992 */ static void -CollectNamedPortals(Portal *portalP, int destroy) -{ - static Portal *portalList = (Portal *)NULL; - static int listIndex = 0; - static int maxIndex = 9; - - if (portalList == (Portal *)NULL) - portalList = (Portal *)malloc(10*sizeof(Portal)); - - if (destroy != 0) +CollectNamedPortals(Portal * portalP, int destroy) +{ + static Portal *portalList = (Portal *) NULL; + static int listIndex = 0; + static int maxIndex = 9; + + if (portalList == (Portal *) NULL) + portalList = (Portal *) malloc(10 * sizeof(Portal)); + + if (destroy != 0) { - int i; - - for (i = 0; i < listIndex; i++) - PortalDestroy(&portalList[i]); - listIndex = 0; + int i; + + for (i = 0; i < listIndex; i++) + PortalDestroy(&portalList[i]); + listIndex = 0; } - else + else { - Assert(portalP); - Assert(*portalP); - - /* - * Don't delete special portals, up to portal creator to do this - */ - if (PortalNameIsSpecial((*portalP)->name)) - return; - - portalList[listIndex] = *portalP; - listIndex++; - if (listIndex == maxIndex) + Assert(portalP); + Assert(*portalP); + + /* + * Don't delete special portals, up to portal creator to do this + */ + if (PortalNameIsSpecial((*portalP)->name)) + return; + + portalList[listIndex] = *portalP; + listIndex++; + if (listIndex == maxIndex) { - portalList = (Portal *) - realloc(portalList, (maxIndex+11)*sizeof(Portal)); - maxIndex += 10; + portalList = (Portal *) + realloc(portalList, (maxIndex + 11) * sizeof(Portal)); + maxIndex += 10; } } - return; + return; } void AtEOXact_portals() { - HashTableWalk(PortalHashTable, CollectNamedPortals, 0); - CollectNamedPortals(NULL, 1); + HashTableWalk(PortalHashTable, CollectNamedPortals, 0); + CollectNamedPortals(NULL, 1); } /* ---------------- - * PortalDump + * PortalDump * ---------------- */ #ifdef NOT_USED static void -PortalDump(Portal *thisP) +PortalDump(Portal * thisP) { - /* XXX state/argument checking here */ - - PortalVariableMemoryDump(PortalGetVariableMemory(*thisP)); - PortalHeapMemoryDump(PortalGetHeapMemory(*thisP)); + /* XXX state/argument checking here */ + + PortalVariableMemoryDump(PortalGetVariableMemory(*thisP)); + PortalHeapMemoryDump(PortalGetHeapMemory(*thisP)); } + #endif /* ---------------- - * DumpPortals + * DumpPortals * ---------------- */ #ifdef NOT_USED static void DumpPortals() { - /* XXX state checking here */ - - HashTableWalk(PortalHashTable, PortalDump, 0); + /* XXX state checking here */ + + HashTableWalk(PortalHashTable, PortalDump, 0); } + #endif - + /* ---------------------------------------------------------------- - * public portal interface functions + * public portal interface functions * ---------------------------------------------------------------- */ /* * EnablePortalManager -- - * Enables/disables the portal management module. + * Enables/disables the portal management module. */ void EnablePortalManager(bool on) { - static bool processing = false; - HASHCTL ctl; - - AssertState(!processing); - AssertArg(BoolIsValid(on)); - - if (BypassEnable(&PortalManagerEnableCount, on)) - return; - - processing = true; - - if (on) { /* initialize */ - EnableMemoryContext(true); - - PortalMemory = CreateGlobalMemory(PortalMemoryName); - - ctl.keysize = MAX_PORTALNAME_LEN; - ctl.datasize = sizeof(Portal); - - /* use PORTALS_PER_USER, defined in utils/portal.h - * as a guess of how many hash table entries to create, initially - */ - PortalHashTable = hash_create(PORTALS_PER_USER * 3, &ctl, HASH_ELEM); - - CreateNewBlankPortal(); - - } else { /* cleanup */ - if (PortalIsValid(BlankPortal)) { - PortalDestroy(&BlankPortal); - MemoryContextFree((MemoryContext)PortalMemory, - (Pointer)BlankPortal); - BlankPortal = NULL; + static bool processing = false; + HASHCTL ctl; + + AssertState(!processing); + AssertArg(BoolIsValid(on)); + + if (BypassEnable(&PortalManagerEnableCount, on)) + return; + + processing = true; + + if (on) + { /* initialize */ + EnableMemoryContext(true); + + PortalMemory = CreateGlobalMemory(PortalMemoryName); + + ctl.keysize = MAX_PORTALNAME_LEN; + ctl.datasize = sizeof(Portal); + + /* + * use PORTALS_PER_USER, defined in utils/portal.h as a guess of + * how many hash table entries to create, initially + */ + PortalHashTable = hash_create(PORTALS_PER_USER * 3, &ctl, HASH_ELEM); + + CreateNewBlankPortal(); + } - /* - * Each portal must free its non-memory resources specially. - */ - HashTableWalk(PortalHashTable, PortalDestroy, 0); - hash_destroy(PortalHashTable); - PortalHashTable = NULL; - - GlobalMemoryDestroy(PortalMemory); - PortalMemory = NULL; - - EnableMemoryContext(true); - } - - processing = false; + else + { /* cleanup */ + if (PortalIsValid(BlankPortal)) + { + PortalDestroy(&BlankPortal); + MemoryContextFree((MemoryContext) PortalMemory, + (Pointer) BlankPortal); + BlankPortal = NULL; + } + + /* + * Each portal must free its non-memory resources specially. + */ + HashTableWalk(PortalHashTable, PortalDestroy, 0); + hash_destroy(PortalHashTable); + PortalHashTable = NULL; + + GlobalMemoryDestroy(PortalMemory); + PortalMemory = NULL; + + EnableMemoryContext(true); + } + + processing = false; } /* * GetPortalByName -- - * Returns a portal given a portal name; returns blank portal given + * Returns a portal given a portal name; returns blank portal given * NULL; returns invalid portal if portal not found. * * Exceptions: - * BadState if called when disabled. + * BadState if called when disabled. */ Portal GetPortalByName(char *name) { - Portal portal; - - AssertState(PortalManagerEnabled); - - if (PointerIsValid(name)) { - PortalHashTableLookup(name, portal); - } - else { - if (!PortalIsValid(BlankPortal)) - CreateNewBlankPortal(); - portal = BlankPortal; - } - - return (portal); + Portal portal; + + AssertState(PortalManagerEnabled); + + if (PointerIsValid(name)) + { + PortalHashTableLookup(name, portal); + } + else + { + if (!PortalIsValid(BlankPortal)) + CreateNewBlankPortal(); + portal = BlankPortal; + } + + return (portal); } /* * BlankPortalAssignName -- - * Returns former blank portal as portal with given name. + * Returns former blank portal as portal with given name. * * Side effect: - * All references to the former blank portal become incorrect. + * All references to the former blank portal become incorrect. * * Exceptions: - * BadState if called when disabled. - * BadState if called without an intervening call to GetPortalByName(NULL). - * BadArg if portal name is invalid. - * "WARN" if portal name is in use. + * BadState if called when disabled. + * BadState if called without an intervening call to GetPortalByName(NULL). + * BadArg if portal name is invalid. + * "WARN" if portal name is in use. */ Portal -BlankPortalAssignName(char *name) /* XXX PortalName */ -{ - Portal portal; - uint16 length; - - AssertState(PortalManagerEnabled); - AssertState(PortalIsValid(BlankPortal)); - AssertArg(PointerIsValid(name)); /* XXX PortalName */ - - portal = GetPortalByName(name); - if (PortalIsValid(portal)) { - elog(NOTICE, "BlankPortalAssignName: portal %s already exists", name); +BlankPortalAssignName(char *name) /* XXX PortalName */ +{ + Portal portal; + uint16 length; + + AssertState(PortalManagerEnabled); + AssertState(PortalIsValid(BlankPortal)); + AssertArg(PointerIsValid(name)); /* XXX PortalName */ + + portal = GetPortalByName(name); + if (PortalIsValid(portal)) + { + elog(NOTICE, "BlankPortalAssignName: portal %s already exists", name); + return (portal); + } + + /* + * remove blank portal + */ + portal = BlankPortal; + BlankPortal = NULL; + + /* + * initialize portal name + */ + length = 1 + strlen(name); + portal->name = (char *) + MemoryContextAlloc((MemoryContext) & portal->variable, length); + + strncpy(portal->name, name, length); + + /* + * put portal in table + */ + PortalHashTableInsert(portal); + return (portal); - } - - /* - * remove blank portal - */ - portal = BlankPortal; - BlankPortal = NULL; - - /* - * initialize portal name - */ - length = 1 + strlen(name); - portal->name = (char*) - MemoryContextAlloc((MemoryContext)&portal->variable, length); - - strncpy(portal->name, name, length); - - /* - * put portal in table - */ - PortalHashTableInsert(portal); - - return (portal); } /* * PortalSetQuery -- - * Attaches a "query" to portal. + * Attaches a "query" to portal. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. - * BadArg if queryDesc is "invalid." - * BadArg if state is "invalid." + * BadState if called when disabled. + * BadArg if portal is invalid. + * BadArg if queryDesc is "invalid." + * BadArg if state is "invalid." */ void PortalSetQuery(Portal portal, - QueryDesc *queryDesc, - TupleDesc attinfo, - EState *state, - void (*cleanup)(Portal portal)) + QueryDesc * queryDesc, + TupleDesc attinfo, + EState * state, + void (*cleanup) (Portal portal)) { - AssertState(PortalManagerEnabled); - AssertArg(PortalIsValid(portal)); - AssertArg(IsA((Node*)state,EState)); - - portal->queryDesc = queryDesc; - portal->state = state; - portal->attinfo = attinfo; - portal->cleanup = cleanup; + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + AssertArg(IsA((Node *) state, EState)); + + portal->queryDesc = queryDesc; + portal->state = state; + portal->attinfo = attinfo; + portal->cleanup = cleanup; } /* * PortalGetQueryDesc -- - * Returns query attached to portal. + * Returns query attached to portal. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. + * BadState if called when disabled. + * BadArg if portal is invalid. */ -QueryDesc * +QueryDesc * PortalGetQueryDesc(Portal portal) { - AssertState(PortalManagerEnabled); - AssertArg(PortalIsValid(portal)); - - return (portal->queryDesc); + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + + return (portal->queryDesc); } /* * PortalGetState -- - * Returns state attached to portal. + * Returns state attached to portal. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. + * BadState if called when disabled. + * BadArg if portal is invalid. */ -EState * +EState * PortalGetState(Portal portal) { - AssertState(PortalManagerEnabled); - AssertArg(PortalIsValid(portal)); - - return (portal->state); + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + + return (portal->state); } /* * CreatePortal -- - * Returns a new portal given a name. + * Returns a new portal given a name. * * Note: - * This is expected to be of very limited usability. See instead, + * This is expected to be of very limited usability. See instead, * BlankPortalAssignName. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal name is invalid. - * "WARN" if portal name is in use. + * BadState if called when disabled. + * BadArg if portal name is invalid. + * "WARN" if portal name is in use. */ Portal -CreatePortal(char *name) /* XXX PortalName */ -{ - Portal portal; - uint16 length; - - AssertState(PortalManagerEnabled); - AssertArg(PointerIsValid(name)); /* XXX PortalName */ - - portal = GetPortalByName(name); - if (PortalIsValid(portal)) { - elog(NOTICE, "CreatePortal: portal %s already exists", name); +CreatePortal(char *name) /* XXX PortalName */ +{ + Portal portal; + uint16 length; + + AssertState(PortalManagerEnabled); + AssertArg(PointerIsValid(name)); /* XXX PortalName */ + + portal = GetPortalByName(name); + if (PortalIsValid(portal)) + { + elog(NOTICE, "CreatePortal: portal %s already exists", name); + return (portal); + } + + /* make new portal structure */ + portal = (Portal) + MemoryContextAlloc((MemoryContext) PortalMemory, sizeof *portal); + + /* initialize portal variable context */ + NodeSetTag((Node *) & portal->variable, T_PortalVariableMemory); + AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size) 0); + portal->variable.method = &PortalVariableContextMethodsData; + + /* initialize portal heap context */ + NodeSetTag((Node *) & portal->heap, T_PortalHeapMemory); + portal->heap.block = NULL; + FixedStackInit(&portal->heap.stackData, + offsetof(HeapMemoryBlockData, itemData)); + portal->heap.method = &PortalHeapContextMethodsData; + + /* initialize portal name */ + length = 1 + strlen(name); + portal->name = (char *) + MemoryContextAlloc((MemoryContext) & portal->variable, length); + strncpy(portal->name, name, length); + + /* initialize portal query */ + portal->queryDesc = NULL; + portal->attinfo = NULL; + portal->state = NULL; + portal->cleanup = NULL; + + /* put portal in table */ + PortalHashTableInsert(portal); + + /* Trap(PointerIsValid(name), Unimplemented); */ return (portal); - } - - /* make new portal structure */ - portal = (Portal) - MemoryContextAlloc((MemoryContext)PortalMemory, sizeof *portal); - - /* initialize portal variable context */ - NodeSetTag((Node*)&portal->variable, T_PortalVariableMemory); - AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size)0); - portal->variable.method = &PortalVariableContextMethodsData; - - /* initialize portal heap context */ - NodeSetTag((Node*)&portal->heap, T_PortalHeapMemory); - portal->heap.block = NULL; - FixedStackInit(&portal->heap.stackData, - offsetof (HeapMemoryBlockData, itemData)); - portal->heap.method = &PortalHeapContextMethodsData; - - /* initialize portal name */ - length = 1 + strlen(name); - portal->name = (char*) - MemoryContextAlloc((MemoryContext)&portal->variable, length); - strncpy(portal->name, name, length); - - /* initialize portal query */ - portal->queryDesc = NULL; - portal->attinfo = NULL; - portal->state = NULL; - portal->cleanup = NULL; - - /* put portal in table */ - PortalHashTableInsert(portal); - - /* Trap(PointerIsValid(name), Unimplemented); */ - return (portal); } /* * PortalDestroy -- - * Destroys portal. + * Destroys portal. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. + * BadState if called when disabled. + * BadArg if portal is invalid. */ void -PortalDestroy(Portal *portalP) -{ - Portal portal = *portalP; - - AssertState(PortalManagerEnabled); - AssertArg(PortalIsValid(portal)); - - /* remove portal from table if not blank portal */ - if (portal != BlankPortal) - PortalHashTableDelete(portal); - - /* reset portal */ - if (PointerIsValid(portal->cleanup)) - (*portal->cleanup)(portal); - - PortalResetHeapMemory(portal); - MemoryContextFree((MemoryContext)&portal->variable, - (Pointer)portal->name); - AllocSetReset(&portal->variable.setData); /* XXX log */ - - if (portal != BlankPortal) - MemoryContextFree((MemoryContext)PortalMemory, (Pointer)portal); +PortalDestroy(Portal * portalP) +{ + Portal portal = *portalP; + + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + + /* remove portal from table if not blank portal */ + if (portal != BlankPortal) + PortalHashTableDelete(portal); + + /* reset portal */ + if (PointerIsValid(portal->cleanup)) + (*portal->cleanup) (portal); + + PortalResetHeapMemory(portal); + MemoryContextFree((MemoryContext) & portal->variable, + (Pointer) portal->name); + AllocSetReset(&portal->variable.setData); /* XXX log */ + + if (portal != BlankPortal) + MemoryContextFree((MemoryContext) PortalMemory, (Pointer) portal); } /* ---------------- - * PortalResetHeapMemory -- - * Resets portal's heap memory context. + * PortalResetHeapMemory -- + * Resets portal's heap memory context. * * Someday, Reset, Start, and End can be optimized by keeping a global * portal module stack of free HeapMemoryBlock's. This will make Start * and End be fast. * * Exceptions: - * BadState if called when disabled. - * BadState if called when not in PortalHeapMemory context. - * BadArg if mode is invalid. + * BadState if called when disabled. + * BadState if called when not in PortalHeapMemory context. + * BadArg if mode is invalid. * ---------------- */ static void PortalResetHeapMemory(Portal portal) { - PortalHeapMemory context; - MemoryContext currentContext; - - context = PortalGetHeapMemory(portal); - - if (PointerIsValid(context->block)) { - /* save present context */ - currentContext = MemoryContextSwitchTo((MemoryContext)context); - - do { - EndPortalAllocMode(); - } while (PointerIsValid(context->block)); - - /* restore context */ - MemoryContextSwitchTo(currentContext); - } + PortalHeapMemory context; + MemoryContext currentContext; + + context = PortalGetHeapMemory(portal); + + if (PointerIsValid(context->block)) + { + /* save present context */ + currentContext = MemoryContextSwitchTo((MemoryContext) context); + + do + { + EndPortalAllocMode(); + } while (PointerIsValid(context->block)); + + /* restore context */ + MemoryContextSwitchTo(currentContext); + } } /* * StartPortalAllocMode -- - * Starts a new block of portal heap allocation using mode and limit; - * the current block is disabled until EndPortalAllocMode is called. + * Starts a new block of portal heap allocation using mode and limit; + * the current block is disabled until EndPortalAllocMode is called. * * Note: - * Note blocks may be stacked and restored arbitarily. - * The semantics of mode and limit are described in aset.h. + * Note blocks may be stacked and restored arbitarily. + * The semantics of mode and limit are described in aset.h. * * Exceptions: - * BadState if called when disabled. - * BadState if called when not in PortalHeapMemory context. - * BadArg if mode is invalid. + * BadState if called when disabled. + * BadState if called when not in PortalHeapMemory context. + * BadArg if mode is invalid. */ void StartPortalAllocMode(AllocMode mode, Size limit) { - PortalHeapMemory context; - - AssertState(PortalManagerEnabled); - AssertState(IsA(CurrentMemoryContext,PortalHeapMemory)); - /* AssertArg(AllocModeIsValid); */ - - context = (PortalHeapMemory)CurrentMemoryContext; - - /* stack current mode */ - if (PointerIsValid(context->block)) - FixedStackPush(&context->stackData, context->block); - - /* allocate and initialize new block */ - context->block = - MemoryContextAlloc( - (MemoryContext)PortalHeapMemoryGetVariableMemory(context), - sizeof (HeapMemoryBlockData) ); - - /* XXX careful, context->block has never been stacked => bad state */ - - AllocSetInit(&HEAPMEMBLOCK(context)->setData, mode, limit); + PortalHeapMemory context; + + AssertState(PortalManagerEnabled); + AssertState(IsA(CurrentMemoryContext, PortalHeapMemory)); + /* AssertArg(AllocModeIsValid); */ + + context = (PortalHeapMemory) CurrentMemoryContext; + + /* stack current mode */ + if (PointerIsValid(context->block)) + FixedStackPush(&context->stackData, context->block); + + /* allocate and initialize new block */ + context->block = + MemoryContextAlloc( + (MemoryContext) PortalHeapMemoryGetVariableMemory(context), + sizeof(HeapMemoryBlockData)); + + /* XXX careful, context->block has never been stacked => bad state */ + + AllocSetInit(&HEAPMEMBLOCK(context)->setData, mode, limit); } /* * EndPortalAllocMode -- - * Ends current block of portal heap allocation; previous block is - * reenabled. + * Ends current block of portal heap allocation; previous block is + * reenabled. * * Note: - * Note blocks may be stacked and restored arbitarily. + * Note blocks may be stacked and restored arbitarily. * * Exceptions: - * BadState if called when disabled. - * BadState if called when not in PortalHeapMemory context. + * BadState if called when disabled. + * BadState if called when not in PortalHeapMemory context. */ void EndPortalAllocMode() { - PortalHeapMemory context; - - AssertState(PortalManagerEnabled); - AssertState(IsA(CurrentMemoryContext,PortalHeapMemory)); - - context = (PortalHeapMemory)CurrentMemoryContext; - AssertState(PointerIsValid(context->block)); /* XXX Trap(...) */ - - /* free current mode */ - AllocSetReset(&HEAPMEMBLOCK(context)->setData); - MemoryContextFree((MemoryContext)PortalHeapMemoryGetVariableMemory(context), - context->block); - - /* restore previous mode */ - context->block = FixedStackPop(&context->stackData); + PortalHeapMemory context; + + AssertState(PortalManagerEnabled); + AssertState(IsA(CurrentMemoryContext, PortalHeapMemory)); + + context = (PortalHeapMemory) CurrentMemoryContext; + AssertState(PointerIsValid(context->block)); /* XXX Trap(...) */ + + /* free current mode */ + AllocSetReset(&HEAPMEMBLOCK(context)->setData); + MemoryContextFree((MemoryContext) PortalHeapMemoryGetVariableMemory(context), + context->block); + + /* restore previous mode */ + context->block = FixedStackPop(&context->stackData); } /* * PortalGetVariableMemory -- - * Returns variable memory context for a given portal. + * Returns variable memory context for a given portal. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. + * BadState if called when disabled. + * BadArg if portal is invalid. */ PortalVariableMemory PortalGetVariableMemory(Portal portal) { - return (&portal->variable); + return (&portal->variable); } /* * PortalGetHeapMemory -- - * Returns heap memory context for a given portal. + * Returns heap memory context for a given portal. * * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. + * BadState if called when disabled. + * BadArg if portal is invalid. */ PortalHeapMemory PortalGetHeapMemory(Portal portal) { - return (&portal->heap); + return (&portal->heap); } /* * PortalVariableMemoryGetPortal -- - * Returns portal containing given variable memory context. + * Returns portal containing given variable memory context. * * Exceptions: - * BadState if called when disabled. - * BadArg if context is invalid. + * BadState if called when disabled. + * BadArg if context is invalid. */ -static Portal +static Portal PortalVariableMemoryGetPortal(PortalVariableMemory context) { - return ((Portal)((char *)context - offsetof (PortalD, variable))); + return ((Portal) ((char *) context - offsetof(PortalD, variable))); } /* * PortalHeapMemoryGetPortal -- - * Returns portal containing given heap memory context. + * Returns portal containing given heap memory context. * * Exceptions: - * BadState if called when disabled. - * BadArg if context is invalid. + * BadState if called when disabled. + * BadArg if context is invalid. */ -static Portal +static Portal PortalHeapMemoryGetPortal(PortalHeapMemory context) { - return ((Portal)((char *)context - offsetof (PortalD, heap))); + return ((Portal) ((char *) context - offsetof(PortalD, heap))); } /* * PortalVariableMemoryGetHeapMemory -- - * Returns heap memory context associated with given variable memory. + * Returns heap memory context associated with given variable memory. * * Exceptions: - * BadState if called when disabled. - * BadArg if context is invalid. + * BadState if called when disabled. + * BadArg if context is invalid. */ #ifdef NOT_USED PortalHeapMemory PortalVariableMemoryGetHeapMemory(PortalVariableMemory context) { - return ((PortalHeapMemory)((char *)context - - offsetof (PortalD, variable) - + offsetof (PortalD, heap))); + return ((PortalHeapMemory) ((char *) context + - offsetof(PortalD, variable) + + offsetof(PortalD, heap))); } + #endif /* * PortalHeapMemoryGetVariableMemory -- - * Returns variable memory context associated with given heap memory. + * Returns variable memory context associated with given heap memory. * * Exceptions: - * BadState if called when disabled. - * BadArg if context is invalid. + * BadState if called when disabled. + * BadArg if context is invalid. */ -static PortalVariableMemory +static PortalVariableMemory PortalHeapMemoryGetVariableMemory(PortalHeapMemory context) { - return ((PortalVariableMemory)((char *)context - - offsetof (PortalD, heap) - + offsetof (PortalD, variable))); + return ((PortalVariableMemory) ((char *) context + - offsetof(PortalD, heap) + + offsetof(PortalD, variable))); } - diff --git a/src/backend/utils/sort/lselect.c b/src/backend/utils/sort/lselect.c index 6797bd40ca0..bc6948292b3 100644 --- a/src/backend/utils/sort/lselect.c +++ b/src/backend/utils/sort/lselect.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * lselect.c-- - * leftist tree selection algorithm (linked priority queue--Knuth, Vol.3, - * pp.150-52) + * leftist tree selection algorithm (linked priority queue--Knuth, Vol.3, + * pp.150-52) * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.5 1997/08/12 22:55:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.6 1997/09/07 04:54:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -26,295 +26,340 @@ #include "utils/psort.h" #include "utils/lselect.h" -#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP) +#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP) /* - * USEMEM - record use of memory - * FREEMEM - record freeing of memory + * USEMEM - record use of memory + * FREEMEM - record freeing of memory */ -#define USEMEM(context,AMT) context->sortMem -= (AMT) -#define FREEMEM(context,AMT) context->sortMem += (AMT) +#define USEMEM(context,AMT) context->sortMem -= (AMT) +#define FREEMEM(context,AMT) context->sortMem += (AMT) /* - * lmerge - merges two leftist trees into one + * lmerge - merges two leftist trees into one * - * Note: - * Enforcing the rule that pt->lt_dist >= qt->lt_dist may - * simplifify much of the code. Removing recursion will not - * speed up code significantly. + * Note: + * Enforcing the rule that pt->lt_dist >= qt->lt_dist may + * simplifify much of the code. Removing recursion will not + * speed up code significantly. */ struct leftist * -lmerge(struct leftist *pt, struct leftist *qt, LeftistContext context) +lmerge(struct leftist * pt, struct leftist * qt, LeftistContext context) { - register struct leftist *root, *majorLeftist, *minorLeftist; - int dist; - - if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context)) { - root = pt; - majorLeftist = qt; - } else { - root = qt; - majorLeftist = pt; - } - if (root->lt_left == NULL) - root->lt_left = majorLeftist; - else { - if ((minorLeftist = root->lt_right) != NULL) - majorLeftist = lmerge(majorLeftist, minorLeftist, context); - if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist) { - root->lt_dist = 1 + dist; - root->lt_right = root->lt_left; - root->lt_left = majorLeftist; - } else { - root->lt_dist = 1 + majorLeftist->lt_dist; - root->lt_right = majorLeftist; + register struct leftist *root, + *majorLeftist, + *minorLeftist; + int dist; + + if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context)) + { + root = pt; + majorLeftist = qt; + } + else + { + root = qt; + majorLeftist = pt; } - } - return(root); + if (root->lt_left == NULL) + root->lt_left = majorLeftist; + else + { + if ((minorLeftist = root->lt_right) != NULL) + majorLeftist = lmerge(majorLeftist, minorLeftist, context); + if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist) + { + root->lt_dist = 1 + dist; + root->lt_right = root->lt_left; + root->lt_left = majorLeftist; + } + else + { + root->lt_dist = 1 + majorLeftist->lt_dist; + root->lt_right = majorLeftist; + } + } + return (root); } static struct leftist * -linsert(struct leftist *root, struct leftist *new1, LeftistContext context) +linsert(struct leftist * root, struct leftist * new1, LeftistContext context) { - register struct leftist *left, *right; - - if (! tuplecmp(root->lt_tuple, new1->lt_tuple, context)) { - new1->lt_left = root; - return(new1); - } - left = root->lt_left; - right = root->lt_right; - if (right == NULL) { - if (left == NULL) - root->lt_left = new1; - else { - root->lt_right = new1; - root->lt_dist = 2; + register struct leftist *left, + *right; + + if (!tuplecmp(root->lt_tuple, new1->lt_tuple, context)) + { + new1->lt_left = root; + return (new1); + } + left = root->lt_left; + right = root->lt_right; + if (right == NULL) + { + if (left == NULL) + root->lt_left = new1; + else + { + root->lt_right = new1; + root->lt_dist = 2; + } + return (root); + } + right = linsert(right, new1, context); + if (right->lt_dist < left->lt_dist) + { + root->lt_dist = 1 + left->lt_dist; + root->lt_left = right; + root->lt_right = left; + } + else + { + root->lt_dist = 1 + right->lt_dist; + root->lt_right = right; } - return(root); - } - right = linsert(right, new1, context); - if (right->lt_dist < left->lt_dist) { - root->lt_dist = 1 + left->lt_dist; - root->lt_left = right; - root->lt_right = left; - } else { - root->lt_dist = 1 + right->lt_dist; - root->lt_right = right; - } - return(root); + return (root); } /* - * gettuple - returns tuple at top of tree (Tuples) + * gettuple - returns tuple at top of tree (Tuples) * - * Returns: - * tuple at top of tree, NULL if failed ALLOC() - * *devnum is set to the devnum of tuple returned - * *treep is set to the new tree + * Returns: + * tuple at top of tree, NULL if failed ALLOC() + * *devnum is set to the devnum of tuple returned + * *treep is set to the new tree * - * Note: - * *treep must not be NULL - * NULL is currently never returned BUG + * Note: + * *treep must not be NULL + * NULL is currently never returned BUG */ HeapTuple -gettuple(struct leftist **treep, - short *devnum, /* device from which tuple came */ - LeftistContext context) +gettuple(struct leftist ** treep, + short *devnum, /* device from which tuple came */ + LeftistContext context) { - register struct leftist *tp; - HeapTuple tup; - - tp = *treep; - tup = tp->lt_tuple; - *devnum = tp->lt_devnum; - if (tp->lt_dist == 1) /* lt_left == NULL */ - *treep = tp->lt_left; - else - *treep = lmerge(tp->lt_left, tp->lt_right, context); - - FREEMEM(context,sizeof (struct leftist)); - FREE(tp); - return(tup); + register struct leftist *tp; + HeapTuple tup; + + tp = *treep; + tup = tp->lt_tuple; + *devnum = tp->lt_devnum; + if (tp->lt_dist == 1) /* lt_left == NULL */ + *treep = tp->lt_left; + else + *treep = lmerge(tp->lt_left, tp->lt_right, context); + + FREEMEM(context, sizeof(struct leftist)); + FREE(tp); + return (tup); } /* - * puttuple - inserts new tuple into tree + * puttuple - inserts new tuple into tree * - * Returns: - * NULL iff failed ALLOC() + * Returns: + * NULL iff failed ALLOC() * - * Note: - * Currently never returns NULL BUG + * Note: + * Currently never returns NULL BUG */ void -puttuple(struct leftist **treep, - HeapTuple newtuple, - short devnum, - LeftistContext context) +puttuple(struct leftist ** treep, + HeapTuple newtuple, + short devnum, + LeftistContext context) { - register struct leftist *new1; - register struct leftist *tp; - - new1 = (struct leftist *) palloc((unsigned) sizeof (struct leftist)); - USEMEM(context,sizeof (struct leftist)); - new1->lt_dist = 1; - new1->lt_devnum = devnum; - new1->lt_tuple = newtuple; - new1->lt_left = NULL; - new1->lt_right = NULL; - if ((tp = *treep) == NULL) - *treep = new1; - else - *treep = linsert(tp, new1, context); - return; + register struct leftist *new1; + register struct leftist *tp; + + new1 = (struct leftist *) palloc((unsigned) sizeof(struct leftist)); + USEMEM(context, sizeof(struct leftist)); + new1->lt_dist = 1; + new1->lt_devnum = devnum; + new1->lt_tuple = newtuple; + new1->lt_left = NULL; + new1->lt_right = NULL; + if ((tp = *treep) == NULL) + *treep = new1; + else + *treep = linsert(tp, new1, context); + return; } /* - * tuplecmp - Compares two tuples with respect CmpList + * tuplecmp - Compares two tuples with respect CmpList * - * Returns: - * 1 if left < right ;0 otherwise - * Assumtions: + * Returns: + * 1 if left < right ;0 otherwise + * Assumtions: */ int tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context) { - register char *lattr, *rattr; - int nkey = 0; - int result = 0; - bool isnull; - - if (ltup == (HeapTuple)NULL) - return(0); - if (rtup == (HeapTuple)NULL) - return(1); - while (nkey < context->nKeys && !result) { - lattr = heap_getattr(ltup, InvalidBuffer, - context->scanKeys[nkey].sk_attno, - context->tupDesc, &isnull); - if (isnull) - return(0); - rattr = heap_getattr(rtup, InvalidBuffer, - context->scanKeys[nkey].sk_attno, - context->tupDesc, - &isnull); - if (isnull) - return(1); - if (context->scanKeys[nkey].sk_flags & SK_COMMUTE) { - if (!(result = - (long) (*context->scanKeys[nkey].sk_func) (rattr, lattr))) - result = - -(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr); - } else if (!(result = - (long) (*context->scanKeys[nkey].sk_func) (lattr, rattr))) - result = - -(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr); - nkey++; - } - return (result == 1); + register char *lattr, + *rattr; + int nkey = 0; + int result = 0; + bool isnull; + + if (ltup == (HeapTuple) NULL) + return (0); + if (rtup == (HeapTuple) NULL) + return (1); + while (nkey < context->nKeys && !result) + { + lattr = heap_getattr(ltup, InvalidBuffer, + context->scanKeys[nkey].sk_attno, + context->tupDesc, &isnull); + if (isnull) + return (0); + rattr = heap_getattr(rtup, InvalidBuffer, + context->scanKeys[nkey].sk_attno, + context->tupDesc, + &isnull); + if (isnull) + return (1); + if (context->scanKeys[nkey].sk_flags & SK_COMMUTE) + { + if (!(result = + (long) (*context->scanKeys[nkey].sk_func) (rattr, lattr))) + result = + -(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr); + } + else if (!(result = + (long) (*context->scanKeys[nkey].sk_func) (lattr, rattr))) + result = + -(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr); + nkey++; + } + return (result == 1); } #ifdef EBUG void -checktree(struct leftist *tree, LeftistContext context) +checktree(struct leftist * tree, LeftistContext context) { - int lnodes; - int rnodes; - - if (tree == NULL) { - puts("Null tree."); - return; - } - lnodes = checktreer(tree->lt_left, 1, context); - rnodes = checktreer(tree->lt_right, 1, context); - if (lnodes < 0) { - lnodes = -lnodes; - puts("0:\tBad left side."); - } - if (rnodes < 0) { - rnodes = -rnodes; - puts("0:\tBad right side."); - } - if (lnodes == 0) { - if (rnodes != 0) - puts("0:\tLeft and right reversed."); - if (tree->lt_dist != 1) - puts("0:\tDistance incorrect."); - } else if (rnodes == 0) { - if (tree->lt_dist != 1) - puts("0:\tDistance incorrect."); - } else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) { - puts("0:\tLeft and right reversed."); - if (tree->lt_dist != 1 + tree->lt_left->lt_dist) - puts("0:\tDistance incorrect."); - } else if (tree->lt_dist != 1+ tree->lt_right->lt_dist) - puts("0:\tDistance incorrect."); - if (lnodes > 0) - if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) - printf("%d:\tLeft child < parent.\n"); - if (rnodes > 0) - if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) - printf("%d:\tRight child < parent.\n"); - printf("Tree has %d nodes\n", 1 + lnodes + rnodes); + int lnodes; + int rnodes; + + if (tree == NULL) + { + puts("Null tree."); + return; + } + lnodes = checktreer(tree->lt_left, 1, context); + rnodes = checktreer(tree->lt_right, 1, context); + if (lnodes < 0) + { + lnodes = -lnodes; + puts("0:\tBad left side."); + } + if (rnodes < 0) + { + rnodes = -rnodes; + puts("0:\tBad right side."); + } + if (lnodes == 0) + { + if (rnodes != 0) + puts("0:\tLeft and right reversed."); + if (tree->lt_dist != 1) + puts("0:\tDistance incorrect."); + } + else if (rnodes == 0) + { + if (tree->lt_dist != 1) + puts("0:\tDistance incorrect."); + } + else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) + { + puts("0:\tLeft and right reversed."); + if (tree->lt_dist != 1 + tree->lt_left->lt_dist) + puts("0:\tDistance incorrect."); + } + else if (tree->lt_dist != 1 + tree->lt_right->lt_dist) + puts("0:\tDistance incorrect."); + if (lnodes > 0) + if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) + printf("%d:\tLeft child < parent.\n"); + if (rnodes > 0) + if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) + printf("%d:\tRight child < parent.\n"); + printf("Tree has %d nodes\n", 1 + lnodes + rnodes); } int -checktreer(struct leftist *tree, int level, LeftistContext context) +checktreer(struct leftist * tree, int level, LeftistContext context) { - int lnodes, rnodes; - int error = 0; - - if (tree == NULL) - return(0); - lnodes = checktreer(tree->lt_left, level + 1, context); - rnodes = checktreer(tree->lt_right, level + 1, context); - if (lnodes < 0) { - error = 1; - lnodes = -lnodes; - printf("%d:\tBad left side.\n", level); - } - if (rnodes < 0) { - error = 1; - rnodes = -rnodes; - printf("%d:\tBad right side.\n", level); - } - if (lnodes == 0) { - if (rnodes != 0) { - error = 1; - printf("%d:\tLeft and right reversed.\n", level); + int lnodes, + rnodes; + int error = 0; + + if (tree == NULL) + return (0); + lnodes = checktreer(tree->lt_left, level + 1, context); + rnodes = checktreer(tree->lt_right, level + 1, context); + if (lnodes < 0) + { + error = 1; + lnodes = -lnodes; + printf("%d:\tBad left side.\n", level); } - if (tree->lt_dist != 1) { - error = 1; - printf("%d:\tDistance incorrect.\n", level); + if (rnodes < 0) + { + error = 1; + rnodes = -rnodes; + printf("%d:\tBad right side.\n", level); } - } else if (rnodes == 0) { - if (tree->lt_dist != 1) { - error = 1; - printf("%d:\tDistance incorrect.\n", level); - } - } else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) { - error = 1; - printf("%d:\tLeft and right reversed.\n", level); - if (tree->lt_dist != 1 + tree->lt_left->lt_dist) - printf("%d:\tDistance incorrect.\n", level); - } else if (tree->lt_dist != 1+ tree->lt_right->lt_dist) { - error = 1; - printf("%d:\tDistance incorrect.\n", level); - } - if (lnodes > 0) - if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) { - error = 1; - printf("%d:\tLeft child < parent.\n"); + if (lnodes == 0) + { + if (rnodes != 0) + { + error = 1; + printf("%d:\tLeft and right reversed.\n", level); + } + if (tree->lt_dist != 1) + { + error = 1; + printf("%d:\tDistance incorrect.\n", level); + } } - if (rnodes > 0) - if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) { - error = 1; - printf("%d:\tRight child < parent.\n"); + else if (rnodes == 0) + { + if (tree->lt_dist != 1) + { + error = 1; + printf("%d:\tDistance incorrect.\n", level); + } } - if (error) - return(-1 + -lnodes + -rnodes); - return(1 + lnodes + rnodes); + else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) + { + error = 1; + printf("%d:\tLeft and right reversed.\n", level); + if (tree->lt_dist != 1 + tree->lt_left->lt_dist) + printf("%d:\tDistance incorrect.\n", level); + } + else if (tree->lt_dist != 1 + tree->lt_right->lt_dist) + { + error = 1; + printf("%d:\tDistance incorrect.\n", level); + } + if (lnodes > 0) + if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) + { + error = 1; + printf("%d:\tLeft child < parent.\n"); + } + if (rnodes > 0) + if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) + { + error = 1; + printf("%d:\tRight child < parent.\n"); + } + if (error) + return (-1 + -lnodes + -rnodes); + return (1 + lnodes + rnodes); } + #endif diff --git a/src/backend/utils/sort/psort.c b/src/backend/utils/sort/psort.c index 12486166268..00cbfbacba5 100644 --- a/src/backend/utils/sort/psort.c +++ b/src/backend/utils/sort/psort.c @@ -1,36 +1,36 @@ /*------------------------------------------------------------------------- * * psort.c-- - * Polyphase merge sort. + * Polyphase merge sort. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.18 1997/09/05 00:09:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.19 1997/09/07 04:54:17 momjian Exp $ * * NOTES - * Sorts the first relation into the second relation. + * Sorts the first relation into the second relation. * - * The old psort.c's routines formed a temporary relation from the merged + * The old psort.c's routines formed a temporary relation from the merged * sort files. This version keeps the files around instead of generating the * relation from them, and provides interface functions to the file so that * you can grab tuples, mark a position in the file, restore a position in the * file. You must now explicitly call an interface function to end the sort, * psort_end, when you are done. - * Now most of the global variables are stuck in the Sort nodes, and + * Now most of the global variables are stuck in the Sort nodes, and * accessed from there (they are passed to all the psort routines) so that * each sort running has its own separate state. This is facilitated by having * the Sort nodes passed in to all the interface functions. - * The one global variable that all the sorts still share is SortMemory. - * You should now be allowed to run two or more psorts concurrently, + * The one global variable that all the sorts still share is SortMemory. + * You should now be allowed to run two or more psorts concurrently, * so long as the memory they eat up is not greater than SORTMEM, the initial - * value of SortMemory. -Rex 2.15.1995 + * value of SortMemory. -Rex 2.15.1995 * - * Use the tape-splitting method (Knuth, Vol. III, pp281-86) in the future. + * Use the tape-splitting method (Knuth, Vol. III, pp281-86) in the future. * - * Arguments? Variables? - * MAXMERGE, MAXTAPES + * Arguments? Variables? + * MAXMERGE, MAXTAPES *------------------------------------------------------------------------- */ #include <stdio.h> @@ -46,11 +46,11 @@ #include "access/htup.h" #include "access/relscan.h" #include "access/skey.h" -#include "utils/tqual.h" /* for NowTimeQual */ +#include "utils/tqual.h" /* for NowTimeQual */ #include "storage/buf.h" -#include "storage/bufmgr.h" /* for BLCKSZ */ -#include "utils/portal.h" /* for {Start,End}PortalAllocMode */ +#include "storage/bufmgr.h" /* for BLCKSZ */ +#include "utils/portal.h" /* for {Start,End}PortalAllocMode */ #include "utils/elog.h" #include "utils/rel.h" @@ -64,47 +64,47 @@ #include "miscadmin.h" #include "storage/fd.h" -static bool createrun(Sort *node, FILE *file, bool *empty); -static void destroytape(FILE *file); -static void dumptuples(FILE *file, Sort *node); -static FILE *gettape(void); -static void initialrun(Sort *node, bool *empty); -static void inittapes(Sort *node); -static void merge(Sort *node, struct tape *dest); -static FILE *mergeruns(Sort *node); +static bool createrun(Sort * node, FILE * file, bool * empty); +static void destroytape(FILE * file); +static void dumptuples(FILE * file, Sort * node); +static FILE *gettape(void); +static void initialrun(Sort * node, bool * empty); +static void inittapes(Sort * node); +static void merge(Sort * node, struct tape * dest); +static FILE *mergeruns(Sort * node); static HeapTuple tuplecopy(HeapTuple tup); -#define TEMPDIR "./" +#define TEMPDIR "./" -static long shortzero = 0; /* used to delimit runs */ +static long shortzero = 0; /* used to delimit runs */ /* * old psort global variables * * (These are the global variables from the old psort. They are still used, - * but are now accessed from Sort nodes using the PS macro. Note that while - * these variables will be accessed by PS(node)->whatever, they will still - * be called by their original names within the comments! -Rex 2.10.1995) + * but are now accessed from Sort nodes using the PS macro. Note that while + * these variables will be accessed by PS(node)->whatever, they will still + * be called by their original names within the comments! -Rex 2.10.1995) * - * LeftistContextData treeContext; + * LeftistContextData treeContext; * - * static int TapeRange; number of tapes - 1 (T) - * static int Level; (l) - * static int TotalDummy; summation of tp_dummy - * static struct tape *Tape; + * static int TapeRange; number of tapes - 1 (T) + * static int Level; (l) + * static int TotalDummy; summation of tp_dummy + * static struct tape *Tape; * - * static int BytesRead; to keep track of # of IO - * static int BytesWritten; + * static int BytesRead; to keep track of # of IO + * static int BytesWritten; * - * struct leftist *Tuples; current tuples in memory + * struct leftist *Tuples; current tuples in memory * - * FILE *psort_grab_file; this holds tuples grabbed - * from merged sort runs - * long psort_current; current file position - * long psort_saved; file position saved for - * mark and restore + * FILE *psort_grab_file; this holds tuples grabbed + * from merged sort runs + * long psort_current; current file position + * long psort_saved; file position saved for + * mark and restore */ /* @@ -113,730 +113,777 @@ static long shortzero = 0; /* used to delimit runs */ #define PS(N) ((Psortstate *)N->psortstate) /* - * psort_begin - polyphase merge sort entry point. Sorts the subplan - * into a temporary file psort_grab_file. After - * this is called, calling the interface function - * psort_grabtuple iteratively will get you the sorted - * tuples. psort_end then finishes the sort off, after - * all the tuples have been grabbed. + * psort_begin - polyphase merge sort entry point. Sorts the subplan + * into a temporary file psort_grab_file. After + * this is called, calling the interface function + * psort_grabtuple iteratively will get you the sorted + * tuples. psort_end then finishes the sort off, after + * all the tuples have been grabbed. * - * Allocates and initializes sort node's psort state. + * Allocates and initializes sort node's psort state. */ bool -psort_begin(Sort *node, int nkeys, ScanKey key) +psort_begin(Sort * node, int nkeys, ScanKey key) { - bool empty; /* to answer: is child node empty? */ - - node->psortstate = (struct Psortstate *)palloc(sizeof(struct Psortstate)); - if (node->psortstate == NULL) - return false; - - AssertArg(nkeys >= 1); - AssertArg(key[0].sk_attno != 0); - AssertArg(key[0].sk_procedure != 0); - - PS(node)->BytesRead = 0; - PS(node)->BytesWritten = 0; - PS(node)->treeContext.tupDesc = - ExecGetTupType(outerPlan((Plan *)node)); - PS(node)->treeContext.nKeys = nkeys; - PS(node)->treeContext.scanKeys = key; - PS(node)->treeContext.sortMem = SortMem * 1024; - - PS(node)->Tuples = NULL; - PS(node)->tupcount = 0; - - PS(node)->using_tape_files = false; - PS(node)->memtuples = NULL; - - initialrun(node, &empty); - - if (empty) - return false; - - if (PS(node)->using_tape_files) - PS(node)->psort_grab_file = mergeruns(node); - - PS(node)->psort_current = 0; - PS(node)->psort_saved = 0; - - return true; + bool empty; /* to answer: is child node empty? */ + + node->psortstate = (struct Psortstate *) palloc(sizeof(struct Psortstate)); + if (node->psortstate == NULL) + return false; + + AssertArg(nkeys >= 1); + AssertArg(key[0].sk_attno != 0); + AssertArg(key[0].sk_procedure != 0); + + PS(node)->BytesRead = 0; + PS(node)->BytesWritten = 0; + PS(node)->treeContext.tupDesc = + ExecGetTupType(outerPlan((Plan *) node)); + PS(node)->treeContext.nKeys = nkeys; + PS(node)->treeContext.scanKeys = key; + PS(node)->treeContext.sortMem = SortMem * 1024; + + PS(node)->Tuples = NULL; + PS(node)->tupcount = 0; + + PS(node)->using_tape_files = false; + PS(node)->memtuples = NULL; + + initialrun(node, &empty); + + if (empty) + return false; + + if (PS(node)->using_tape_files) + PS(node)->psort_grab_file = mergeruns(node); + + PS(node)->psort_current = 0; + PS(node)->psort_saved = 0; + + return true; } /* - * inittapes - initializes the tapes - * - (polyphase merge Alg.D(D1)--Knuth, Vol.3, p.270) - * Returns: - * number of allocated tapes + * inittapes - initializes the tapes + * - (polyphase merge Alg.D(D1)--Knuth, Vol.3, p.270) + * Returns: + * number of allocated tapes */ static void -inittapes(Sort *node) +inittapes(Sort * node) { - register int i; - register struct tape *tp; - - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); - - /* - ASSERT(ntapes >= 3 && ntapes <= MAXTAPES, - "inittapes: Invalid number of tapes to initialize.\n"); - */ - - tp = PS(node)->Tape; - for (i = 0; i < MAXTAPES && (tp->tp_file = gettape()) != NULL; i++) { - tp->tp_dummy = 1; - tp->tp_fib = 1; - tp->tp_prev = tp - 1; - tp++; - } - PS(node)->TapeRange = --tp - PS(node)->Tape; - tp->tp_dummy = 0; - tp->tp_fib = 0; - PS(node)->Tape[0].tp_prev = tp; - - if (PS(node)->TapeRange <= 1) - elog(WARN, "inittapes: Could only allocate %d < 3 tapes\n", - PS(node)->TapeRange + 1); - - PS(node)->Level = 1; - PS(node)->TotalDummy = PS(node)->TapeRange; - - PS(node)->using_tape_files = true; + register int i; + register struct tape *tp; + + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); + + /* + * ASSERT(ntapes >= 3 && ntapes <= MAXTAPES, "inittapes: Invalid + * number of tapes to initialize.\n"); + */ + + tp = PS(node)->Tape; + for (i = 0; i < MAXTAPES && (tp->tp_file = gettape()) != NULL; i++) + { + tp->tp_dummy = 1; + tp->tp_fib = 1; + tp->tp_prev = tp - 1; + tp++; + } + PS(node)->TapeRange = --tp - PS(node)->Tape; + tp->tp_dummy = 0; + tp->tp_fib = 0; + PS(node)->Tape[0].tp_prev = tp; + + if (PS(node)->TapeRange <= 1) + elog(WARN, "inittapes: Could only allocate %d < 3 tapes\n", + PS(node)->TapeRange + 1); + + PS(node)->Level = 1; + PS(node)->TotalDummy = PS(node)->TapeRange; + + PS(node)->using_tape_files = true; } /* - * PUTTUP - writes the next tuple - * ENDRUN - mark end of run - * GETLEN - reads the length of the next tuple - * ALLOCTUP - returns space for the new tuple - * SETTUPLEN - stores the length into the tuple - * GETTUP - reads the tuple + * PUTTUP - writes the next tuple + * ENDRUN - mark end of run + * GETLEN - reads the length of the next tuple + * ALLOCTUP - returns space for the new tuple + * SETTUPLEN - stores the length into the tuple + * GETTUP - reads the tuple * - * Note: - * LEN field must be a short; FP is a stream + * Note: + * LEN field must be a short; FP is a stream */ -#define PUTTUP(NODE, TUP, FP) do {\ - ((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \ - fwrite((char *)TUP, (TUP)->t_len, 1, FP);} while (0) -#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP) -#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP) -#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN)) -#define GETTUP(NODE, TUP, LEN, FP) do {\ - IncrProcessed(); \ - ((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (shortzero); \ - fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP);} \ - while (0) -#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN - - /* - * USEMEM - record use of memory - * FREEMEM - record freeing of memory - * FULLMEM - 1 iff a tuple will fit - */ - -#define USEMEM(NODE,AMT) PS(node)->treeContext.sortMem -= (AMT) -#define FREEMEM(NODE,AMT) PS(node)->treeContext.sortMem += (AMT) -#define LACKMEM(NODE) (PS(node)->treeContext.sortMem <= MAXBLCKSZ) /* not accurate */ -#define TRACEMEM(FUNC) -#define TRACEOUT(FUNC, TUP) +#define PUTTUP(NODE, TUP, FP) do {\ + ((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \ + fwrite((char *)TUP, (TUP)->t_len, 1, FP);} while (0) +#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP) +#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP) +#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN)) +#define GETTUP(NODE, TUP, LEN, FP) do {\ + IncrProcessed(); \ + ((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (shortzero); \ + fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP);} \ + while (0) +#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN + + /* + * USEMEM - record use of memory FREEMEM - record + * freeing of memory FULLMEM - 1 iff a tuple will fit + */ + +#define USEMEM(NODE,AMT) PS(node)->treeContext.sortMem -= (AMT) +#define FREEMEM(NODE,AMT) PS(node)->treeContext.sortMem += (AMT) +#define LACKMEM(NODE) (PS(node)->treeContext.sortMem <= MAXBLCKSZ) /* not accurate */ +#define TRACEMEM(FUNC) +#define TRACEOUT(FUNC, TUP) /* - * initialrun - distributes tuples from the relation - * - (replacement selection(R2-R3)--Knuth, Vol.3, p.257) - * - (polyphase merge Alg.D(D2-D4)--Knuth, Vol.3, p.271) + * initialrun - distributes tuples from the relation + * - (replacement selection(R2-R3)--Knuth, Vol.3, p.257) + * - (polyphase merge Alg.D(D2-D4)--Knuth, Vol.3, p.271) * - * Explaination: - * Tuples are distributed to the tapes as in Algorithm D. - * A "tuple" with t_size == 0 is used to mark the end of a run. + * Explaination: + * Tuples are distributed to the tapes as in Algorithm D. + * A "tuple" with t_size == 0 is used to mark the end of a run. * - * Note: - * The replacement selection algorithm has been modified - * to go from R1 directly to R3 skipping R2 the first time. + * Note: + * The replacement selection algorithm has been modified + * to go from R1 directly to R3 skipping R2 the first time. * - * Maybe should use closer(rdesc) before return - * Perhaps should adjust the number of tapes if less than n. - * used--v. likely to have problems in mergeruns(). - * Must know if should open/close files before each - * call to psort()? If should--messy?? + * Maybe should use closer(rdesc) before return + * Perhaps should adjust the number of tapes if less than n. + * used--v. likely to have problems in mergeruns(). + * Must know if should open/close files before each + * call to psort()? If should--messy?? * - * Possible optimization: - * put the first xxx runs in quickly--problem here since - * I (perhaps prematurely) combined the 2 algorithms. - * Also, perhaps allocate tapes when needed. Split into 2 funcs. + * Possible optimization: + * put the first xxx runs in quickly--problem here since + * I (perhaps prematurely) combined the 2 algorithms. + * Also, perhaps allocate tapes when needed. Split into 2 funcs. */ static void -initialrun(Sort *node, bool *empty) +initialrun(Sort * node, bool * empty) { - /* register struct tuple *tup; */ - register struct tape *tp; - int baseruns; /* D:(a) */ - int extrapasses; /* EOF */ - - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); - - tp = PS(node)->Tape; - - if ((bool)createrun(node, NULL, empty) != false) { - if (! PS(node)->using_tape_files) - inittapes(node); - extrapasses = 0; - } - else { - /* if empty or rows fit in memory, we never access tape stuff */ - if (*empty || ! PS(node)->using_tape_files) - return; - if (! PS(node)->using_tape_files) - inittapes(node); - extrapasses = 1 + (PS(node)->Tuples != NULL); /* (T != N) ? 2 : 1 */ - } - - for ( ; ; ) { - tp->tp_dummy--; - PS(node)->TotalDummy--; - if (tp->tp_dummy < (tp + 1)->tp_dummy) - tp++; - else if (tp->tp_dummy != 0) - tp = PS(node)->Tape; - else { - PS(node)->Level++; - baseruns = PS(node)->Tape[0].tp_fib; - for (tp = PS(node)->Tape; - tp - PS(node)->Tape < PS(node)->TapeRange; tp++) { - PS(node)->TotalDummy += - (tp->tp_dummy = baseruns - + (tp + 1)->tp_fib - - tp->tp_fib); - tp->tp_fib = baseruns - + (tp + 1)->tp_fib; - } - tp = PS(node)->Tape; /* D4 */ - } /* D3 */ - if (extrapasses) - if (--extrapasses) { - dumptuples(tp->tp_file, node); - ENDRUN(tp->tp_file); - continue; - } else - break; - - if ((bool)createrun(node, tp->tp_file, empty) == false) - extrapasses = 1 + (PS(node)->Tuples != NULL); - /* D2 */ - } - for (tp = PS(node)->Tape + PS(node)->TapeRange; tp >= PS(node)->Tape; tp--) - rewind(tp->tp_file); /* D. */ + /* register struct tuple *tup; */ + register struct tape *tp; + int baseruns; /* D:(a) */ + int extrapasses;/* EOF */ + + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); + + tp = PS(node)->Tape; + + if ((bool) createrun(node, NULL, empty) != false) + { + if (!PS(node)->using_tape_files) + inittapes(node); + extrapasses = 0; + } + else + { + /* if empty or rows fit in memory, we never access tape stuff */ + if (*empty || !PS(node)->using_tape_files) + return; + if (!PS(node)->using_tape_files) + inittapes(node); + extrapasses = 1 + (PS(node)->Tuples != NULL); /* (T != N) ? 2 : 1 */ + } + + for (;;) + { + tp->tp_dummy--; + PS(node)->TotalDummy--; + if (tp->tp_dummy < (tp + 1)->tp_dummy) + tp++; + else if (tp->tp_dummy != 0) + tp = PS(node)->Tape; + else + { + PS(node)->Level++; + baseruns = PS(node)->Tape[0].tp_fib; + for (tp = PS(node)->Tape; + tp - PS(node)->Tape < PS(node)->TapeRange; tp++) + { + PS(node)->TotalDummy += + (tp->tp_dummy = baseruns + + (tp + 1)->tp_fib + - tp->tp_fib); + tp->tp_fib = baseruns + + (tp + 1)->tp_fib; + } + tp = PS(node)->Tape;/* D4 */ + } /* D3 */ + if (extrapasses) + if (--extrapasses) + { + dumptuples(tp->tp_file, node); + ENDRUN(tp->tp_file); + continue; + } + else + break; + + if ((bool) createrun(node, tp->tp_file, empty) == false) + extrapasses = 1 + (PS(node)->Tuples != NULL); + /* D2 */ + } + for (tp = PS(node)->Tape + PS(node)->TapeRange; tp >= PS(node)->Tape; tp--) + rewind(tp->tp_file); /* D. */ } /* - * createrun - places the next run on file, grabbing the tuples by - * executing the subplan passed in + * createrun - places the next run on file, grabbing the tuples by + * executing the subplan passed in * - * Uses: - * Tuples, which should contain any tuples for this run + * Uses: + * Tuples, which should contain any tuples for this run * - * Returns: - * FALSE iff process through end of relation - * Tuples contains the tuples for the following run upon exit + * Returns: + * FALSE iff process through end of relation + * Tuples contains the tuples for the following run upon exit */ -static bool -createrun(Sort *node, FILE *file, bool *empty) +static bool +createrun(Sort * node, FILE * file, bool * empty) { - register HeapTuple lasttuple; - register HeapTuple tup; - struct leftist *nextrun; - bool foundeor; - short junk; - - int cr_tuples = 0; /* Count tuples grabbed from plannode */ - TupleTableSlot *cr_slot; - - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); - - lasttuple = NULL; - nextrun = NULL; - foundeor = false; - for ( ; ; ) { - while (LACKMEM(node) && PS(node)->Tuples != NULL) { - if (lasttuple != NULL) { - FREEMEM(node,lasttuple->t_len); - FREE(lasttuple); - TRACEMEM(createrun); - } - lasttuple = tup = gettuple(&PS(node)->Tuples, &junk, - &PS(node)->treeContext); - if (! PS(node)->using_tape_files) { - inittapes(node); - if (! file) - file = PS(node)->Tape->tp_file; /* was NULL */ - } - PUTTUP(node, tup, file); - TRACEOUT(createrun, tup); - } - if (LACKMEM(node)) - break; + register HeapTuple lasttuple; + register HeapTuple tup; + struct leftist *nextrun; + bool foundeor; + short junk; - /* About to call ExecProcNode, it can mess up the state if it - * eventually calls another Sort node. So must stow it away here for - * the meantime. -Rex 2.2.1995 - */ + int cr_tuples = 0; /* Count tuples grabbed from + * plannode */ + TupleTableSlot *cr_slot; - cr_slot = ExecProcNode(outerPlan((Plan *)node), (Plan *)node); + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); + + lasttuple = NULL; + nextrun = NULL; + foundeor = false; + for (;;) + { + while (LACKMEM(node) && PS(node)->Tuples != NULL) + { + if (lasttuple != NULL) + { + FREEMEM(node, lasttuple->t_len); + FREE(lasttuple); + TRACEMEM(createrun); + } + lasttuple = tup = gettuple(&PS(node)->Tuples, &junk, + &PS(node)->treeContext); + if (!PS(node)->using_tape_files) + { + inittapes(node); + if (!file) + file = PS(node)->Tape->tp_file; /* was NULL */ + } + PUTTUP(node, tup, file); + TRACEOUT(createrun, tup); + } + if (LACKMEM(node)) + break; + + /* + * About to call ExecProcNode, it can mess up the state if it + * eventually calls another Sort node. So must stow it away here + * for the meantime. -Rex + * 2.2.1995 + */ + + cr_slot = ExecProcNode(outerPlan((Plan *) node), (Plan *) node); + + if (TupIsNull(cr_slot)) + { + foundeor = true; + break; + } + else + { + tup = tuplecopy(cr_slot->val); + ExecClearTuple(cr_slot); + PS(node)->tupcount++; + cr_tuples++; + } - if (TupIsNull(cr_slot)) { - foundeor = true; - break; + IncrProcessed(); + USEMEM(node, tup->t_len); + TRACEMEM(createrun); + if (lasttuple != NULL && tuplecmp(tup, lasttuple, + &PS(node)->treeContext)) + puttuple(&nextrun, tup, 0, &PS(node)->treeContext); + else + puttuple(&PS(node)->Tuples, tup, 0, &PS(node)->treeContext); } - else { - tup = tuplecopy(cr_slot->val); - ExecClearTuple(cr_slot); - PS(node)->tupcount++; - cr_tuples++; + if (lasttuple != NULL) + { + FREEMEM(node, lasttuple->t_len); + FREE(lasttuple); + TRACEMEM(createrun); } + dumptuples(file, node); + if (PS(node)->using_tape_files) + ENDRUN(file); + /* delimit the end of the run */ + PS(node)->Tuples = nextrun; - IncrProcessed(); - USEMEM(node,tup->t_len); - TRACEMEM(createrun); - if (lasttuple != NULL && tuplecmp(tup, lasttuple, - &PS(node)->treeContext)) - puttuple(&nextrun, tup, 0, &PS(node)->treeContext); - else - puttuple(&PS(node)->Tuples, tup, 0, &PS(node)->treeContext); - } - if (lasttuple != NULL) { - FREEMEM(node,lasttuple->t_len); - FREE(lasttuple); - TRACEMEM(createrun); - } - dumptuples(file, node); - if (PS(node)->using_tape_files) - ENDRUN(file); - /* delimit the end of the run */ - PS(node)->Tuples = nextrun; - - /* if we did not see any tuples, mark empty */ - *empty = (cr_tuples > 0) ? false : true; - - return((bool)! foundeor); /* XXX - works iff bool is {0,1} */ + /* if we did not see any tuples, mark empty */ + *empty = (cr_tuples > 0) ? false : true; + + return ((bool) ! foundeor); /* XXX - works iff bool is {0,1} */ } /* - * tuplecopy - see also tuple.c:palloctup() + * tuplecopy - see also tuple.c:palloctup() * - * This should eventually go there under that name? And this will - * then use palloc directly (see version -r1.2). + * This should eventually go there under that name? And this will + * then use palloc directly (see version -r1.2). */ -static HeapTuple +static HeapTuple tuplecopy(HeapTuple tup) { - HeapTuple rettup; - - if (!HeapTupleIsValid(tup)) { - return(NULL); /* just in case */ - } - rettup = (HeapTuple)palloc(tup->t_len); - memmove((char *)rettup, (char *)tup, tup->t_len); /* XXX */ - return(rettup); + HeapTuple rettup; + + if (!HeapTupleIsValid(tup)) + { + return (NULL); /* just in case */ + } + rettup = (HeapTuple) palloc(tup->t_len); + memmove((char *) rettup, (char *) tup, tup->t_len); /* XXX */ + return (rettup); } /* - * mergeruns - merges all runs from input tapes - * (polyphase merge Alg.D(D6)--Knuth, Vol.3, p271) + * mergeruns - merges all runs from input tapes + * (polyphase merge Alg.D(D6)--Knuth, Vol.3, p271) * - * Returns: - * file of tuples in order + * Returns: + * file of tuples in order */ -static FILE * -mergeruns(Sort *node) +static FILE * +mergeruns(Sort * node) { - register struct tape *tp; + register struct tape *tp; - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); - Assert(PS(node)->using_tape_files == true); + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); + Assert(PS(node)->using_tape_files == true); - tp = PS(node)->Tape + PS(node)->TapeRange; - merge(node, tp); - rewind(tp->tp_file); - while (--PS(node)->Level != 0) { - tp = tp->tp_prev; - rewind(tp->tp_file); - /* resettape(tp->tp_file); -not sufficient */ + tp = PS(node)->Tape + PS(node)->TapeRange; merge(node, tp); rewind(tp->tp_file); - } - return(tp->tp_file); + while (--PS(node)->Level != 0) + { + tp = tp->tp_prev; + rewind(tp->tp_file); + /* resettape(tp->tp_file); -not sufficient */ + merge(node, tp); + rewind(tp->tp_file); + } + return (tp->tp_file); } /* - * merge - handles a single merge of the tape - * (polyphase merge Alg.D(D5)--Knuth, Vol.3, p271) + * merge - handles a single merge of the tape + * (polyphase merge Alg.D(D5)--Knuth, Vol.3, p271) */ static void -merge(Sort *node, struct tape *dest) +merge(Sort * node, struct tape * dest) { - register HeapTuple tup; - register struct tape *lasttp; /* (TAPE[P]) */ - register struct tape *tp; - struct leftist *tuples; - FILE *destfile; - int times; /* runs left to merge */ - int outdummy; /* complete dummy runs */ - short fromtape; - long tuplen; - - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); - Assert(PS(node)->using_tape_files == true); - - lasttp = dest->tp_prev; - times = lasttp->tp_fib; - for (tp = lasttp ; tp != dest; tp = tp->tp_prev) - tp->tp_fib -= times; - tp->tp_fib += times; - /* Tape[].tp_fib (A[]) is set to proper exit values */ - - if (PS(node)->TotalDummy < PS(node)->TapeRange)/* no complete dummy runs */ - outdummy = 0; - else { - outdummy = PS(node)->TotalDummy; /* a large positive number */ - for (tp = lasttp; tp != dest; tp = tp->tp_prev) - if (outdummy > tp->tp_dummy) - outdummy = tp->tp_dummy; + register HeapTuple tup; + register struct tape *lasttp; /* (TAPE[P]) */ + register struct tape *tp; + struct leftist *tuples; + FILE *destfile; + int times; /* runs left to merge */ + int outdummy; /* complete dummy runs */ + short fromtape; + long tuplen; + + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); + Assert(PS(node)->using_tape_files == true); + + lasttp = dest->tp_prev; + times = lasttp->tp_fib; for (tp = lasttp; tp != dest; tp = tp->tp_prev) - tp->tp_dummy -= outdummy; - tp->tp_dummy += outdummy; - PS(node)->TotalDummy -= outdummy * PS(node)->TapeRange; - /* do not add the outdummy runs yet */ - times -= outdummy; - } - destfile = dest->tp_file; - while (times-- != 0) { /* merge one run */ - tuples = NULL; - if (PS(node)->TotalDummy == 0) - for (tp = dest->tp_prev; tp != dest; tp = tp->tp_prev) { - GETLEN(tuplen, tp->tp_file); - tup = ALLOCTUP(tuplen); - USEMEM(node,tuplen); - TRACEMEM(merge); - SETTUPLEN(tup, tuplen); - GETTUP(node, tup, tuplen, tp->tp_file); - puttuple(&tuples, tup, tp - PS(node)->Tape, - &PS(node)->treeContext); - } - else { - for (tp = dest->tp_prev; tp != dest; tp = tp->tp_prev) { - if (tp->tp_dummy != 0) { - tp->tp_dummy--; - PS(node)->TotalDummy--; - } else { - GETLEN(tuplen, tp->tp_file); - tup = ALLOCTUP(tuplen); - USEMEM(node,tuplen); - TRACEMEM(merge); - SETTUPLEN(tup, tuplen); - GETTUP(node, tup, tuplen, tp->tp_file); - puttuple(&tuples, tup, tp - PS(node)->Tape, - &PS(node)->treeContext); + tp->tp_fib -= times; + tp->tp_fib += times; + /* Tape[].tp_fib (A[]) is set to proper exit values */ + + if (PS(node)->TotalDummy < PS(node)->TapeRange) /* no complete dummy + * runs */ + outdummy = 0; + else + { + outdummy = PS(node)->TotalDummy; /* a large positive number */ + for (tp = lasttp; tp != dest; tp = tp->tp_prev) + if (outdummy > tp->tp_dummy) + outdummy = tp->tp_dummy; + for (tp = lasttp; tp != dest; tp = tp->tp_prev) + tp->tp_dummy -= outdummy; + tp->tp_dummy += outdummy; + PS(node)->TotalDummy -= outdummy * PS(node)->TapeRange; + /* do not add the outdummy runs yet */ + times -= outdummy; + } + destfile = dest->tp_file; + while (times-- != 0) + { /* merge one run */ + tuples = NULL; + if (PS(node)->TotalDummy == 0) + for (tp = dest->tp_prev; tp != dest; tp = tp->tp_prev) + { + GETLEN(tuplen, tp->tp_file); + tup = ALLOCTUP(tuplen); + USEMEM(node, tuplen); + TRACEMEM(merge); + SETTUPLEN(tup, tuplen); + GETTUP(node, tup, tuplen, tp->tp_file); + puttuple(&tuples, tup, tp - PS(node)->Tape, + &PS(node)->treeContext); + } + else + { + for (tp = dest->tp_prev; tp != dest; tp = tp->tp_prev) + { + if (tp->tp_dummy != 0) + { + tp->tp_dummy--; + PS(node)->TotalDummy--; + } + else + { + GETLEN(tuplen, tp->tp_file); + tup = ALLOCTUP(tuplen); + USEMEM(node, tuplen); + TRACEMEM(merge); + SETTUPLEN(tup, tuplen); + GETTUP(node, tup, tuplen, tp->tp_file); + puttuple(&tuples, tup, tp - PS(node)->Tape, + &PS(node)->treeContext); + } + } + } + while (tuples != NULL) + { + /* possible optimization by using count in tuples */ + tup = gettuple(&tuples, &fromtape, &PS(node)->treeContext); + PUTTUP(node, tup, destfile); + FREEMEM(node, tup->t_len); + FREE(tup); + TRACEMEM(merge); + GETLEN(tuplen, PS(node)->Tape[fromtape].tp_file); + if (tuplen == 0) + ; + else + { + tup = ALLOCTUP(tuplen); + USEMEM(node, tuplen); + TRACEMEM(merge); + SETTUPLEN(tup, tuplen); + GETTUP(node, tup, tuplen, PS(node)->Tape[fromtape].tp_file); + puttuple(&tuples, tup, fromtape, &PS(node)->treeContext); + } } - } + ENDRUN(destfile); } - while (tuples != NULL) { - /* possible optimization by using count in tuples */ - tup = gettuple(&tuples, &fromtape, &PS(node)->treeContext); - PUTTUP(node, tup, destfile); - FREEMEM(node,tup->t_len); - FREE(tup); - TRACEMEM(merge); - GETLEN(tuplen, PS(node)->Tape[fromtape].tp_file); - if (tuplen == 0) - ; - else { - tup = ALLOCTUP(tuplen); - USEMEM(node,tuplen); - TRACEMEM(merge); - SETTUPLEN(tup, tuplen); - GETTUP(node, tup, tuplen, PS(node)->Tape[fromtape].tp_file); - puttuple(&tuples, tup, fromtape, &PS(node)->treeContext); - } - } - ENDRUN(destfile); - } - PS(node)->TotalDummy += outdummy; + PS(node)->TotalDummy += outdummy; } /* * dumptuples - stores all the tuples in tree into file */ static void -dumptuples(FILE *file, Sort *node) +dumptuples(FILE * file, Sort * node) { - register struct leftist *tp; - register struct leftist *newp; - struct leftist **treep = &PS(node)->Tuples; - LeftistContext context = &PS(node)->treeContext; - HeapTuple tup; - int memtupindex = 0; - - if (! PS(node)->using_tape_files && PS(node)->tupcount) { - Assert(PS(node)->memtuples == NULL); - PS(node)->memtuples = palloc(PS(node)->tupcount * sizeof(HeapTuple)); - } - - tp = *treep; - while (tp != NULL) { - tup = tp->lt_tuple; - if (tp->lt_dist == 1) /* lt_right == NULL */ - newp = tp->lt_left; - else - newp = lmerge(tp->lt_left, tp->lt_right, context); - FREEMEM(node,sizeof (struct leftist)); - FREE(tp); - if (PS(node)->using_tape_files) { - PUTTUP(node, tup, file); - FREEMEM(node,tup->t_len); - FREE(tup); + register struct leftist *tp; + register struct leftist *newp; + struct leftist **treep = &PS(node)->Tuples; + LeftistContext context = &PS(node)->treeContext; + HeapTuple tup; + int memtupindex = 0; + + if (!PS(node)->using_tape_files && PS(node)->tupcount) + { + Assert(PS(node)->memtuples == NULL); + PS(node)->memtuples = palloc(PS(node)->tupcount * sizeof(HeapTuple)); } - else - PS(node)->memtuples[memtupindex++] = tup; - tp = newp; - } - *treep = NULL; + tp = *treep; + while (tp != NULL) + { + tup = tp->lt_tuple; + if (tp->lt_dist == 1) /* lt_right == NULL */ + newp = tp->lt_left; + else + newp = lmerge(tp->lt_left, tp->lt_right, context); + FREEMEM(node, sizeof(struct leftist)); + FREE(tp); + if (PS(node)->using_tape_files) + { + PUTTUP(node, tup, file); + FREEMEM(node, tup->t_len); + FREE(tup); + } + else + PS(node)->memtuples[memtupindex++] = tup; + + tp = newp; + } + *treep = NULL; } /* - * psort_grabtuple - gets a tuple from the sorted file and returns it. - * If there are no tuples left, returns NULL. - * Should not call psort_end unless this has returned - * a NULL indicating the last tuple has been processed. + * psort_grabtuple - gets a tuple from the sorted file and returns it. + * If there are no tuples left, returns NULL. + * Should not call psort_end unless this has returned + * a NULL indicating the last tuple has been processed. */ HeapTuple -psort_grabtuple(Sort *node) +psort_grabtuple(Sort * node) { - register HeapTuple tup; - long tuplen; - - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); - - if (PS(node)->using_tape_files == true) { - if (!feof(PS(node)->psort_grab_file)) { - if (GETLEN(tuplen, PS(node)->psort_grab_file) && tuplen != 0) { - tup = (HeapTuple)palloc((unsigned)tuplen); - SETTUPLEN(tup, tuplen); - GETTUP(node, tup, tuplen, PS(node)->psort_grab_file); - - /* Update current merged sort file position */ - PS(node)->psort_current += tuplen; - - return tup; - } - else - return NULL; - } - else - return NULL; - } - else { - if (PS(node)->psort_current < PS(node)->tupcount) - return PS(node)->memtuples[PS(node)->psort_current++]; - else - return NULL; - } + register HeapTuple tup; + long tuplen; + + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); + + if (PS(node)->using_tape_files == true) + { + if (!feof(PS(node)->psort_grab_file)) + { + if (GETLEN(tuplen, PS(node)->psort_grab_file) && tuplen != 0) + { + tup = (HeapTuple) palloc((unsigned) tuplen); + SETTUPLEN(tup, tuplen); + GETTUP(node, tup, tuplen, PS(node)->psort_grab_file); + + /* Update current merged sort file position */ + PS(node)->psort_current += tuplen; + + return tup; + } + else + return NULL; + } + else + return NULL; + } + else + { + if (PS(node)->psort_current < PS(node)->tupcount) + return PS(node)->memtuples[PS(node)->psort_current++]; + else + return NULL; + } } /* - * psort_markpos - saves current position in the merged sort file + * psort_markpos - saves current position in the merged sort file */ void -psort_markpos(Sort *node) +psort_markpos(Sort * node) { - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); - PS(node)->psort_saved = PS(node)->psort_current; + PS(node)->psort_saved = PS(node)->psort_current; } /* - * psort_restorepos- restores current position in merged sort file to - * last saved position + * psort_restorepos- restores current position in merged sort file to + * last saved position */ void -psort_restorepos(Sort *node) +psort_restorepos(Sort * node) { - Assert(node != (Sort *) NULL); - Assert(PS(node) != (Psortstate *) NULL); + Assert(node != (Sort *) NULL); + Assert(PS(node) != (Psortstate *) NULL); - if (PS(node)->using_tape_files == true) - fseek(PS(node)->psort_grab_file, PS(node)->psort_saved, SEEK_SET); - PS(node)->psort_current = PS(node)->psort_saved; + if (PS(node)->using_tape_files == true) + fseek(PS(node)->psort_grab_file, PS(node)->psort_saved, SEEK_SET); + PS(node)->psort_current = PS(node)->psort_saved; } /* - * psort_end - unlinks the tape files, and cleans up. Should not be - * called unless psort_grabtuple has returned a NULL. + * psort_end - unlinks the tape files, and cleans up. Should not be + * called unless psort_grabtuple has returned a NULL. */ void -psort_end(Sort *node) +psort_end(Sort * node) { - register struct tape *tp; - - if (!node->cleaned) { - Assert(node != (Sort *) NULL); -/* Assert(PS(node) != (Psortstate *) NULL); */ - - /* - * I'm changing this because if we are sorting a relation - * with no tuples, psortstate is NULL. - */ - if (PS(node) != (Psortstate *) NULL) { - if (PS(node)->using_tape_files == true) - for (tp = PS(node)->Tape + PS(node)->TapeRange; tp >= PS(node)->Tape; tp--) - destroytape(tp->tp_file); - else if (PS(node)->memtuples) - pfree(PS(node)->memtuples); - - NDirectFileRead += - (int)ceil((double)PS(node)->BytesRead / BLCKSZ); - NDirectFileWrite += - (int)ceil((double)PS(node)->BytesWritten / BLCKSZ); - - pfree((void *)node->psortstate); - - node->cleaned = TRUE; + register struct tape *tp; + + if (!node->cleaned) + { + Assert(node != (Sort *) NULL); +/* Assert(PS(node) != (Psortstate *) NULL); */ + + /* + * I'm changing this because if we are sorting a relation with no + * tuples, psortstate is NULL. + */ + if (PS(node) != (Psortstate *) NULL) + { + if (PS(node)->using_tape_files == true) + for (tp = PS(node)->Tape + PS(node)->TapeRange; tp >= PS(node)->Tape; tp--) + destroytape(tp->tp_file); + else if (PS(node)->memtuples) + pfree(PS(node)->memtuples); + + NDirectFileRead += + (int) ceil((double) PS(node)->BytesRead / BLCKSZ); + NDirectFileWrite += + (int) ceil((double) PS(node)->BytesWritten / BLCKSZ); + + pfree((void *) node->psortstate); + + node->cleaned = TRUE; + } } - } } /* - * gettape - handles access temporary files in polyphase merging + * gettape - handles access temporary files in polyphase merging * - * Optimizations: - * If guarenteed that only one sort running/process, - * can simplify the file generation--and need not store the - * name for later unlink. + * Optimizations: + * If guarenteed that only one sort running/process, + * can simplify the file generation--and need not store the + * name for later unlink. */ -struct tapelst { - char *tl_name; - int tl_fd; - struct tapelst *tl_next; +struct tapelst +{ + char *tl_name; + int tl_fd; + struct tapelst *tl_next; }; -static struct tapelst *Tapes = NULL; +static struct tapelst *Tapes = NULL; /* - * gettape - returns an open stream for writing/reading + * gettape - returns an open stream for writing/reading * - * Returns: - * Open stream for writing/reading. - * NULL if unable to open temporary file. + * Returns: + * Open stream for writing/reading. + * NULL if unable to open temporary file. */ -static FILE * +static FILE * gettape() { - register struct tapelst *tp; - FILE *file; - static int tapeinit = 0; - char *mktemp(); - static unsigned int uniqueFileId = 0; - extern int errno; - char uniqueName[MAXPGPATH]; - - tp = (struct tapelst *)palloc((unsigned)sizeof (struct tapelst)); - - sprintf(uniqueName, "%spg_psort.%d.%d", TEMPDIR, (int)getpid(), uniqueFileId); - uniqueFileId++; - - tapeinit = 1; - - tp->tl_name = palloc((unsigned)sizeof(uniqueName)); - - /* - * now, copy template with final null into palloc'd space - */ - - memmove(tp->tl_name, uniqueName, strlen(uniqueName)); - - - file = AllocateFile(tp->tl_name, "w+"); - if (file == NULL) - elog(WARN,"Open: %s in %s line %d, %s", tp->tl_name, - __FILE__, __LINE__, strerror(errno)); - - tp->tl_fd = fileno(file); - tp->tl_next = Tapes; - Tapes = tp; - return(file); + register struct tapelst *tp; + FILE *file; + static int tapeinit = 0; + char *mktemp(); + static unsigned int uniqueFileId = 0; + extern int errno; + char uniqueName[MAXPGPATH]; + + tp = (struct tapelst *) palloc((unsigned) sizeof(struct tapelst)); + + sprintf(uniqueName, "%spg_psort.%d.%d", TEMPDIR, (int) getpid(), uniqueFileId); + uniqueFileId++; + + tapeinit = 1; + + tp->tl_name = palloc((unsigned) sizeof(uniqueName)); + + /* + * now, copy template with final null into palloc'd space + */ + + memmove(tp->tl_name, uniqueName, strlen(uniqueName)); + + + file = AllocateFile(tp->tl_name, "w+"); + if (file == NULL) + elog(WARN, "Open: %s in %s line %d, %s", tp->tl_name, + __FILE__, __LINE__, strerror(errno)); + + tp->tl_fd = fileno(file); + tp->tl_next = Tapes; + Tapes = tp; + return (file); } /* - * resettape - resets the tape to size 0 + * resettape - resets the tape to size 0 */ #ifdef NOT_USED static void -resettape(FILE *file) +resettape(FILE * file) { - register struct tapelst *tp; - register int fd; - - Assert(PointerIsValid(file)); - - fd = fileno(file); - for (tp = Tapes; tp != NULL && tp->tl_fd != fd; tp = tp->tl_next) - ; - if (tp == NULL) - elog(WARN, "resettape: tape not found"); - - file = freopen(tp->tl_name, "w+", file); - if (file == NULL) { - elog(FATAL, "could not freopen temporary file"); - } + register struct tapelst *tp; + register int fd; + + Assert(PointerIsValid(file)); + + fd = fileno(file); + for (tp = Tapes; tp != NULL && tp->tl_fd != fd; tp = tp->tl_next) + ; + if (tp == NULL) + elog(WARN, "resettape: tape not found"); + + file = freopen(tp->tl_name, "w+", file); + if (file == NULL) + { + elog(FATAL, "could not freopen temporary file"); + } } + #endif /* - * distroytape - unlinks the tape + * distroytape - unlinks the tape * - * Efficiency note: - * More efficient to destroy more recently allocated tapes first. + * Efficiency note: + * More efficient to destroy more recently allocated tapes first. * - * Possible bugs: - * Exits instead of returning status, if given invalid tape. + * Possible bugs: + * Exits instead of returning status, if given invalid tape. */ static void -destroytape(FILE *file) +destroytape(FILE * file) { - register struct tapelst *tp, *tq; - register int fd; - - if ((tp = Tapes) == NULL) - elog(FATAL, "destroytape: tape not found"); - - if ((fd = fileno(file)) == tp->tl_fd) { - Tapes = tp->tl_next; - FreeFile(file); - unlink(tp->tl_name); - FREE(tp->tl_name); - FREE(tp); - } else - for ( ; ; ) { - if (tp->tl_next == NULL) + register struct tapelst *tp, + *tq; + register int fd; + + if ((tp = Tapes) == NULL) elog(FATAL, "destroytape: tape not found"); - if (tp->tl_next->tl_fd == fd) { + + if ((fd = fileno(file)) == tp->tl_fd) + { + Tapes = tp->tl_next; FreeFile(file); - tq = tp->tl_next; - tp->tl_next = tq->tl_next; - unlink(tq->tl_name); - FREE((tq->tl_name)); - FREE(tq); - break; - } - tp = tp->tl_next; + unlink(tp->tl_name); + FREE(tp->tl_name); + FREE(tp); } + else + for (;;) + { + if (tp->tl_next == NULL) + elog(FATAL, "destroytape: tape not found"); + if (tp->tl_next->tl_fd == fd) + { + FreeFile(file); + tq = tp->tl_next; + tp->tl_next = tq->tl_next; + unlink(tq->tl_name); + FREE((tq->tl_name)); + FREE(tq); + break; + } + tp = tp->tl_next; + } } diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index 1fcf3679fe4..2a85ecd712b 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * tqual.c-- - * POSTGRES time qualification code. + * POSTGRES time qualification code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.4 1997/08/29 09:04:54 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.5 1997/09/07 04:54:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,23 +29,23 @@ static AbsoluteTime TimeQualGetEndTime(TimeQual qual); static AbsoluteTime TimeQualGetSnapshotTime(TimeQual qual); static AbsoluteTime TimeQualGetStartTime(TimeQual qual); -static bool TimeQualIncludesNow(TimeQual qual); -static bool TimeQualIndicatesDisableValidityChecking(TimeQual qual); -static bool TimeQualIsLegal(TimeQual qual); -static bool TimeQualIsRanged(TimeQual qual); -static bool TimeQualIsSnapshot(TimeQual qual); -static bool TimeQualIsValid(TimeQual qual); +static bool TimeQualIncludesNow(TimeQual qual); +static bool TimeQualIndicatesDisableValidityChecking(TimeQual qual); +static bool TimeQualIsLegal(TimeQual qual); +static bool TimeQualIsRanged(TimeQual qual); +static bool TimeQualIsSnapshot(TimeQual qual); +static bool TimeQualIsValid(TimeQual qual); /* * TimeQualMode -- - * Mode indicator for treatment of time qualifications. + * Mode indicator for treatment of time qualifications. */ typedef uint16 TimeQualMode; -#define TimeQualAt 0x1 +#define TimeQualAt 0x1 #define TimeQualNewer 0x2 #define TimeQualOlder 0x4 -#define TimeQualAll 0x8 +#define TimeQualAll 0x8 #define TimeQualMask 0xf @@ -53,820 +53,903 @@ typedef uint16 TimeQualMode; #define TimeQualRange (TimeQualNewer | TimeQualOlder) #define TimeQualAllAt (TimeQualAt | TimeQualAll) -typedef struct TimeQualData { - AbsoluteTime start; - AbsoluteTime end; - TimeQualMode mode; -} TimeQualData; +typedef struct TimeQualData +{ + AbsoluteTime start; + AbsoluteTime end; + TimeQualMode mode; +} TimeQualData; -typedef TimeQualData *InternalTimeQual; +typedef TimeQualData *InternalTimeQual; -static TimeQualData SelfTimeQualData; -TimeQual SelfTimeQual = (Pointer)&SelfTimeQualData; +static TimeQualData SelfTimeQualData; +TimeQual SelfTimeQual = (Pointer) & SelfTimeQualData; extern bool PostgresIsInitialized; /* * XXX Transaction system override hacks start here */ -#ifndef GOODAMI +#ifndef GOODAMI -static TransactionId HeapSpecialTransactionId = InvalidTransactionId; -static CommandId HeapSpecialCommandId = FirstCommandId; +static TransactionId HeapSpecialTransactionId = InvalidTransactionId; +static CommandId HeapSpecialCommandId = FirstCommandId; void setheapoverride(bool on) { - if (on) { - TransactionIdStore(GetCurrentTransactionId(), - &HeapSpecialTransactionId); - HeapSpecialCommandId = GetCurrentCommandId(); - } else { - HeapSpecialTransactionId = InvalidTransactionId; - } + if (on) + { + TransactionIdStore(GetCurrentTransactionId(), + &HeapSpecialTransactionId); + HeapSpecialCommandId = GetCurrentCommandId(); + } + else + { + HeapSpecialTransactionId = InvalidTransactionId; + } } /* static */ bool heapisoverride() { - if (!TransactionIdIsValid(HeapSpecialTransactionId)) { - return (false); - } - - if (!TransactionIdEquals(GetCurrentTransactionId(), - HeapSpecialTransactionId) || - GetCurrentCommandId() != HeapSpecialCommandId) { - HeapSpecialTransactionId = InvalidTransactionId; - - return (false); - } - return (true); + if (!TransactionIdIsValid(HeapSpecialTransactionId)) + { + return (false); + } + + if (!TransactionIdEquals(GetCurrentTransactionId(), + HeapSpecialTransactionId) || + GetCurrentCommandId() != HeapSpecialCommandId) + { + HeapSpecialTransactionId = InvalidTransactionId; + + return (false); + } + return (true); } -#endif /* !defined(GOODAMI) */ +#endif /* !defined(GOODAMI) */ /* * XXX Transaction system override hacks end here */ -static bool HeapTupleSatisfiesItself(HeapTuple tuple); -static bool HeapTupleSatisfiesNow(HeapTuple tuple); -static bool HeapTupleSatisfiesSnapshotInternalTimeQual(HeapTuple tuple, - InternalTimeQual qual); -static bool HeapTupleSatisfiesUpperBoundedInternalTimeQual(HeapTuple tuple, - InternalTimeQual qual); -static bool HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple, - InternalTimeQual qual); +static bool HeapTupleSatisfiesItself(HeapTuple tuple); +static bool HeapTupleSatisfiesNow(HeapTuple tuple); +static bool +HeapTupleSatisfiesSnapshotInternalTimeQual(HeapTuple tuple, + InternalTimeQual qual); +static bool +HeapTupleSatisfiesUpperBoundedInternalTimeQual(HeapTuple tuple, + InternalTimeQual qual); +static bool +HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple, + InternalTimeQual qual); + - /* * TimeQualIsValid -- - * True iff time qualification is valid. + * True iff time qualification is valid. */ -static bool +static bool TimeQualIsValid(TimeQual qual) { - bool hasStartTime; - - if (!PointerIsValid(qual) || qual == SelfTimeQual) { + bool hasStartTime; + + if (!PointerIsValid(qual) || qual == SelfTimeQual) + { + return (true); + } + + if (((InternalTimeQual) qual)->mode & ~TimeQualMask) + { + return (false); + } + + if (((InternalTimeQual) qual)->mode & TimeQualAt) + { + return (AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual) qual)->start)); + } + + hasStartTime = false; + + if (((InternalTimeQual) qual)->mode & TimeQualNewer) + { + if (!AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual) qual)->start)) + { + return (false); + } + hasStartTime = true; + } + + if (((InternalTimeQual) qual)->mode & TimeQualOlder) + { + if (!AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual) qual)->end)) + { + return (false); + } + if (hasStartTime) + { + return ((bool) ! AbsoluteTimeIsBefore( + ((InternalTimeQual) qual)->end, + ((InternalTimeQual) qual)->start)); + } + } return (true); - } - - if (((InternalTimeQual)qual)->mode & ~TimeQualMask) { - return (false); - } - - if (((InternalTimeQual)qual)->mode & TimeQualAt) { - return (AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual)qual)->start)); - } - - hasStartTime = false; - - if (((InternalTimeQual)qual)->mode & TimeQualNewer) { - if (!AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual)qual)->start)) { - return (false); - } - hasStartTime = true; - } - - if (((InternalTimeQual)qual)->mode & TimeQualOlder) { - if (!AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual)qual)->end)) { - return (false); - } - if (hasStartTime) { - return ((bool)!AbsoluteTimeIsBefore( - ((InternalTimeQual)qual)->end, - ((InternalTimeQual)qual)->start)); - } - } - return (true); } /* * TimeQualIsLegal -- - * True iff time qualification is legal. - * I.e., true iff time qualification does not intersects the future, - * relative to the transaction start time. + * True iff time qualification is legal. + * I.e., true iff time qualification does not intersects the future, + * relative to the transaction start time. * * Note: - * Assumes time qualification is valid. + * Assumes time qualification is valid. */ -static bool +static bool TimeQualIsLegal(TimeQual qual) { - Assert(TimeQualIsValid(qual)); - - if (qual == NowTimeQual || qual == SelfTimeQual) { + Assert(TimeQualIsValid(qual)); + + if (qual == NowTimeQual || qual == SelfTimeQual) + { + return (true); + } + + /* TimeQualAt */ + if (((InternalTimeQual) qual)->mode & TimeQualAt) + { + AbsoluteTime a, + b; + + a = ((InternalTimeQual) qual)->start; + b = GetCurrentTransactionStartTime(); + + if (AbsoluteTimeIsAfter(a, b)) + return (false); + else + return (true); + } + + /* TimeQualOlder or TimeQualRange */ + if (((InternalTimeQual) qual)->mode & TimeQualOlder) + { + AbsoluteTime a, + b; + + a = ((InternalTimeQual) qual)->end; + b = GetCurrentTransactionStartTime(); + + if (AbsoluteTimeIsAfter(a, b)) + return (false); + else + return (true); + } + + /* TimeQualNewer */ + if (((InternalTimeQual) qual)->mode & TimeQualNewer) + { + AbsoluteTime a, + b; + + a = ((InternalTimeQual) qual)->start; + b = GetCurrentTransactionStartTime(); + + if (AbsoluteTimeIsAfter(a, b)) + return (false); + else + return (true); + } + + /* TimeQualEvery */ return (true); - } - - /* TimeQualAt */ - if (((InternalTimeQual)qual)->mode & TimeQualAt) { - AbsoluteTime a, b; - - a = ((InternalTimeQual)qual)->start; - b = GetCurrentTransactionStartTime(); - - if (AbsoluteTimeIsAfter(a, b)) - return (false); - else - return (true); - } - - /* TimeQualOlder or TimeQualRange */ - if (((InternalTimeQual)qual)->mode & TimeQualOlder) { - AbsoluteTime a, b; - - a = ((InternalTimeQual)qual)->end; - b = GetCurrentTransactionStartTime(); - - if (AbsoluteTimeIsAfter(a, b)) - return (false); - else - return (true); - } - - /* TimeQualNewer */ - if (((InternalTimeQual)qual)->mode & TimeQualNewer) { - AbsoluteTime a, b; - - a = ((InternalTimeQual)qual)->start; - b = GetCurrentTransactionStartTime(); - - if (AbsoluteTimeIsAfter(a, b)) - return (false); - else - return (true); - } - - /* TimeQualEvery */ - return (true); } /* * TimeQualIncludesNow -- - * True iff time qualification includes "now." + * True iff time qualification includes "now." * * Note: - * Assumes time qualification is valid. + * Assumes time qualification is valid. */ -static bool +static bool TimeQualIncludesNow(TimeQual qual) { - Assert(TimeQualIsValid(qual)); - - if (qual == NowTimeQual || qual == SelfTimeQual) { + Assert(TimeQualIsValid(qual)); + + if (qual == NowTimeQual || qual == SelfTimeQual) + { + return (true); + } + + if (((InternalTimeQual) qual)->mode & TimeQualAt) + { + return (false); + } + if (((InternalTimeQual) qual)->mode & TimeQualOlder && + !AbsoluteTimeIsAfter( + ((InternalTimeQual) qual)->end, + GetCurrentTransactionStartTime())) + { + + return (false); + } return (true); - } - - if (((InternalTimeQual)qual)->mode & TimeQualAt) { - return (false); - } - if (((InternalTimeQual)qual)->mode & TimeQualOlder && - !AbsoluteTimeIsAfter( - ((InternalTimeQual)qual)->end, - GetCurrentTransactionStartTime())) { - - return (false); - } - return (true); } /* * TimeQualIncludesPast -- - * True iff time qualification includes some time in the past. + * True iff time qualification includes some time in the past. * * Note: - * Assumes time qualification is valid. - * XXX may not be needed? + * Assumes time qualification is valid. + * XXX may not be needed? */ #ifdef NOT_USED bool TimeQualIncludesPast(TimeQual qual) { - Assert(TimeQualIsValid(qual)); - - if (qual == NowTimeQual || qual == SelfTimeQual) { - return (false); - } - - /* otherwise, must check archive (setting locks as appropriate) */ - return (true); + Assert(TimeQualIsValid(qual)); + + if (qual == NowTimeQual || qual == SelfTimeQual) + { + return (false); + } + + /* otherwise, must check archive (setting locks as appropriate) */ + return (true); } + #endif /* * TimeQualIsSnapshot -- - * True iff time qualification is a snapshot qualification. + * True iff time qualification is a snapshot qualification. * * Note: - * Assumes time qualification is valid. + * Assumes time qualification is valid. */ -static bool +static bool TimeQualIsSnapshot(TimeQual qual) { - Assert(TimeQualIsValid(qual)); - - if (qual == NowTimeQual || qual == SelfTimeQual) { - return (false); - } - - return ((bool)!!(((InternalTimeQual)qual)->mode & TimeQualAt)); + Assert(TimeQualIsValid(qual)); + + if (qual == NowTimeQual || qual == SelfTimeQual) + { + return (false); + } + + return ((bool) ! !(((InternalTimeQual) qual)->mode & TimeQualAt)); } /* * TimeQualIsRanged -- - * True iff time qualification is a ranged qualification. + * True iff time qualification is a ranged qualification. * * Note: - * Assumes time qualification is valid. + * Assumes time qualification is valid. */ -static bool +static bool TimeQualIsRanged(TimeQual qual) { - Assert(TimeQualIsValid(qual)); - - if (qual == NowTimeQual || qual == SelfTimeQual) { - return (false); - } - - return ((bool)!(((InternalTimeQual)qual)->mode & TimeQualAt)); + Assert(TimeQualIsValid(qual)); + + if (qual == NowTimeQual || qual == SelfTimeQual) + { + return (false); + } + + return ((bool) ! (((InternalTimeQual) qual)->mode & TimeQualAt)); } /* * TimeQualIndicatesDisableValidityChecking -- - * True iff time qualification indicates validity checking should be - * disabled. + * True iff time qualification indicates validity checking should be + * disabled. * * Note: - * XXX This should not be implemented since this does not make sense. + * XXX This should not be implemented since this does not make sense. */ -static bool +static bool TimeQualIndicatesDisableValidityChecking(TimeQual qual) { - Assert (TimeQualIsValid(qual)); - - if (qual == NowTimeQual || qual == SelfTimeQual) { + Assert(TimeQualIsValid(qual)); + + if (qual == NowTimeQual || qual == SelfTimeQual) + { + return (false); + } + + if (((InternalTimeQual) qual)->mode & TimeQualAll) + { + return (true); + } return (false); - } - - if (((InternalTimeQual)qual)->mode & TimeQualAll) { - return (true); - } - return (false); } /* * TimeQualGetSnapshotTime -- - * Returns time for a snapshot time qual. + * Returns time for a snapshot time qual. * * Note: - * Assumes time qual is valid snapshot time qual. + * Assumes time qual is valid snapshot time qual. */ -static AbsoluteTime +static AbsoluteTime TimeQualGetSnapshotTime(TimeQual qual) { - Assert(TimeQualIsSnapshot(qual)); - - return (((InternalTimeQual)qual)->start); + Assert(TimeQualIsSnapshot(qual)); + + return (((InternalTimeQual) qual)->start); } /* * TimeQualGetStartTime -- - * Returns start time for a ranged time qual. + * Returns start time for a ranged time qual. * * Note: - * Assumes time qual is valid ranged time qual. + * Assumes time qual is valid ranged time qual. */ -static AbsoluteTime +static AbsoluteTime TimeQualGetStartTime(TimeQual qual) { - Assert(TimeQualIsRanged(qual)); - - return (((InternalTimeQual)qual)->start); + Assert(TimeQualIsRanged(qual)); + + return (((InternalTimeQual) qual)->start); } /* * TimeQualGetEndTime -- - * Returns end time for a ranged time qual. + * Returns end time for a ranged time qual. * * Note: - * Assumes time qual is valid ranged time qual. + * Assumes time qual is valid ranged time qual. */ -static AbsoluteTime +static AbsoluteTime TimeQualGetEndTime(TimeQual qual) { - Assert(TimeQualIsRanged(qual)); - - return (((InternalTimeQual)qual)->end); + Assert(TimeQualIsRanged(qual)); + + return (((InternalTimeQual) qual)->end); } /* * TimeFormSnapshotTimeQual -- - * Returns snapshot time qual for a time. + * Returns snapshot time qual for a time. * * Note: - * Assumes time is valid. + * Assumes time is valid. */ TimeQual TimeFormSnapshotTimeQual(AbsoluteTime time) { - InternalTimeQual qual; - - Assert(AbsoluteTimeIsBackwardCompatiblyValid(time)); - - qual = (InternalTimeQual)palloc(sizeof *qual); - - qual->start = time; - qual->end = INVALID_ABSTIME; - qual->mode = TimeQualAt; - - return ((TimeQual)qual); + InternalTimeQual qual; + + Assert(AbsoluteTimeIsBackwardCompatiblyValid(time)); + + qual = (InternalTimeQual) palloc(sizeof *qual); + + qual->start = time; + qual->end = INVALID_ABSTIME; + qual->mode = TimeQualAt; + + return ((TimeQual) qual); } /* * TimeFormRangedTimeQual -- - * Returns ranged time qual for a pair of times. + * Returns ranged time qual for a pair of times. * * Note: - * If start time is invalid, it is regarded as the epoch. - * If end time is invalid, it is regarded as "now." - * Assumes start time is before (or the same as) end time. + * If start time is invalid, it is regarded as the epoch. + * If end time is invalid, it is regarded as "now." + * Assumes start time is before (or the same as) end time. */ TimeQual TimeFormRangedTimeQual(AbsoluteTime startTime, - AbsoluteTime endTime) + AbsoluteTime endTime) { - InternalTimeQual qual; - - qual = (InternalTimeQual)palloc(sizeof *qual); - - qual->start = startTime; - qual->end = endTime; - qual->mode = TimeQualEvery; - - if (AbsoluteTimeIsBackwardCompatiblyValid(startTime)) { - qual->mode |= TimeQualNewer; - } - if (AbsoluteTimeIsBackwardCompatiblyValid(endTime)) { - qual->mode |= TimeQualOlder; - } - - return ((TimeQual)qual); + InternalTimeQual qual; + + qual = (InternalTimeQual) palloc(sizeof *qual); + + qual->start = startTime; + qual->end = endTime; + qual->mode = TimeQualEvery; + + if (AbsoluteTimeIsBackwardCompatiblyValid(startTime)) + { + qual->mode |= TimeQualNewer; + } + if (AbsoluteTimeIsBackwardCompatiblyValid(endTime)) + { + qual->mode |= TimeQualOlder; + } + + return ((TimeQual) qual); } /* * HeapTupleSatisfiesTimeQual -- - * True iff heap tuple satsifies a time qual. + * True iff heap tuple satsifies a time qual. * * Note: - * Assumes heap tuple is valid. - * Assumes time qual is valid. - * XXX Many of the checks may be simplified and still remain correct. - * XXX Partial answers to the checks may be cached in an ItemId. + * Assumes heap tuple is valid. + * Assumes time qual is valid. + * XXX Many of the checks may be simplified and still remain correct. + * XXX Partial answers to the checks may be cached in an ItemId. */ bool HeapTupleSatisfiesTimeQual(HeapTuple tuple, TimeQual qual) { -/* extern TransactionId AmiTransactionId; */ - - Assert(HeapTupleIsValid(tuple)); - Assert(TimeQualIsValid(qual)); - - if (TransactionIdEquals(tuple->t_xmax, AmiTransactionId)) - return(false); - - if (qual == SelfTimeQual || heapisoverride()) { - return (HeapTupleSatisfiesItself(tuple)); - } - - if (qual == NowTimeQual) { - return (HeapTupleSatisfiesNow(tuple)); - } - - if (!TimeQualIsLegal(qual)) { - elog(WARN, "HeapTupleSatisfiesTimeQual: illegal time qual"); - } - - if (TimeQualIndicatesDisableValidityChecking(qual)) { - elog(WARN, "HeapTupleSatisfiesTimeQual: no disabled validity checking (yet)"); - } - - if (TimeQualIsSnapshot(qual)) { - return (HeapTupleSatisfiesSnapshotInternalTimeQual(tuple, - (InternalTimeQual)qual)); - } - - if (TimeQualIncludesNow(qual)) { - return (HeapTupleSatisfiesUpperUnboundedInternalTimeQual(tuple, - (InternalTimeQual)qual)); - } - - return (HeapTupleSatisfiesUpperBoundedInternalTimeQual(tuple, - (InternalTimeQual)qual)); +/* extern TransactionId AmiTransactionId; */ + + Assert(HeapTupleIsValid(tuple)); + Assert(TimeQualIsValid(qual)); + + if (TransactionIdEquals(tuple->t_xmax, AmiTransactionId)) + return (false); + + if (qual == SelfTimeQual || heapisoverride()) + { + return (HeapTupleSatisfiesItself(tuple)); + } + + if (qual == NowTimeQual) + { + return (HeapTupleSatisfiesNow(tuple)); + } + + if (!TimeQualIsLegal(qual)) + { + elog(WARN, "HeapTupleSatisfiesTimeQual: illegal time qual"); + } + + if (TimeQualIndicatesDisableValidityChecking(qual)) + { + elog(WARN, "HeapTupleSatisfiesTimeQual: no disabled validity checking (yet)"); + } + + if (TimeQualIsSnapshot(qual)) + { + return (HeapTupleSatisfiesSnapshotInternalTimeQual(tuple, + (InternalTimeQual) qual)); + } + + if (TimeQualIncludesNow(qual)) + { + return (HeapTupleSatisfiesUpperUnboundedInternalTimeQual(tuple, + (InternalTimeQual) qual)); + } + + return (HeapTupleSatisfiesUpperBoundedInternalTimeQual(tuple, + (InternalTimeQual) qual)); } /* * HeapTupleSatisfiesItself -- - * True iff heap tuple is valid for "itself." - * "{it}self" means valid as of everything that's happened - * in the current transaction, _including_ the current command. + * True iff heap tuple is valid for "itself." + * "{it}self" means valid as of everything that's happened + * in the current transaction, _including_ the current command. * * Note: - * Assumes heap tuple is valid. + * Assumes heap tuple is valid. */ /* * The satisfaction of "itself" requires the following: * - * ((Xmin == my-transaction && the row was updated by the current transaction, and - * (Xmax is null it was not deleted - * [|| Xmax != my-transaction)]) [or it was deleted by another transaction] + * ((Xmin == my-transaction && the row was updated by the current transaction, and + * (Xmax is null it was not deleted + * [|| Xmax != my-transaction)]) [or it was deleted by another transaction] * || * - * (Xmin is committed && the row was modified by a committed transaction, and - * (Xmax is null || the row has not been deleted, or - * (Xmax != my-transaction && the row was deleted by another transaction - * Xmax is not committed))) that has not been committed + * (Xmin is committed && the row was modified by a committed transaction, and + * (Xmax is null || the row has not been deleted, or + * (Xmax != my-transaction && the row was deleted by another transaction + * Xmax is not committed))) that has not been committed */ -static bool +static bool HeapTupleSatisfiesItself(HeapTuple tuple) { - /* - * XXX Several evil casts are made in this routine. Casting XID to be - * TransactionId works only because TransactionId->data is the first - * (and only) field of the structure. - */ - if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) { - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) && - !TransactionIdIsValid((TransactionId)tuple->t_xmax)) { - return (true); - } - - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) { - return (false); - } - - tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); - } - /* the tuple was inserted validly */ - - if (AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) { - return (false); - } - - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) { - return (true); - } - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) { - return (false); - } - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) { - return (true); - } - - /* by here, deleting transaction has committed */ - tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); + /* + * XXX Several evil casts are made in this routine. Casting XID to be + * TransactionId works only because TransactionId->data is the first + * (and only) field of the structure. + */ + if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) + { + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmin) && + !TransactionIdIsValid((TransactionId) tuple->t_xmax)) + { + return (true); + } + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmin)) + { + return (false); + } + + tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); + } + /* the tuple was inserted validly */ - return (false); + if (AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) + { + return (false); + } + + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax)) + { + return (true); + } + + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmax)) + { + return (false); + } + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmax)) + { + return (true); + } + + /* by here, deleting transaction has committed */ + tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); + + return (false); } /* * HeapTupleSatisfiesNow -- - * True iff heap tuple is valid "now." - * "now" means valid including everything that's happened - * in the current transaction _up to, but not including,_ - * the current command. + * True iff heap tuple is valid "now." + * "now" means valid including everything that's happened + * in the current transaction _up to, but not including,_ + * the current command. * * Note: - * Assumes heap tuple is valid. + * Assumes heap tuple is valid. */ /* * The satisfaction of "now" requires the following: * - * ((Xmin == my-transaction && changed by the current transaction - * Cmin != my-command && but not by this command, and - * (Xmax is null || the row has not been deleted, or - * (Xmax == my-transaction && it was deleted by the current transaction - * Cmax != my-command))) but not by this command, - * || or + * ((Xmin == my-transaction && changed by the current transaction + * Cmin != my-command && but not by this command, and + * (Xmax is null || the row has not been deleted, or + * (Xmax == my-transaction && it was deleted by the current transaction + * Cmax != my-command))) but not by this command, + * || or * - * (Xmin is committed && the row was modified by a committed transaction, and - * (Xmax is null || the row has not been deleted, or - * (Xmax == my-transaction && the row is being deleted by this command, or - * Cmax == my-command) || - * (Xmax is not committed && the row was deleted by another transaction - * Xmax != my-transaction)))) that has not been committed + * (Xmin is committed && the row was modified by a committed transaction, and + * (Xmax is null || the row has not been deleted, or + * (Xmax == my-transaction && the row is being deleted by this command, or + * Cmax == my-command) || + * (Xmax is not committed && the row was deleted by another transaction + * Xmax != my-transaction)))) that has not been committed * * XXX - * CommandId stuff didn't work properly if one used SQL-functions in - * UPDATE/INSERT(fromSELECT)/DELETE scans: SQL-funcs call - * CommandCounterIncrement and made tuples changed/inserted by - * current command visible to command itself (so we had multiple - * update of updated tuples, etc). - vadim 08/29/97 - * - * mao says 17 march 1993: the tests in this routine are correct; - * if you think they're not, you're wrong, and you should think - * about it again. i know, it happened to me. we don't need to - * check commit time against the start time of this transaction - * because 2ph locking protects us from doing the wrong thing. - * if you mess around here, you'll break serializability. the only - * problem with this code is that it does the wrong thing for system - * catalog updates, because the catalogs aren't subject to 2ph, so - * the serializability guarantees we provide don't extend to xacts - * that do catalog accesses. this is unfortunate, but not critical. + * CommandId stuff didn't work properly if one used SQL-functions in + * UPDATE/INSERT(fromSELECT)/DELETE scans: SQL-funcs call + * CommandCounterIncrement and made tuples changed/inserted by + * current command visible to command itself (so we had multiple + * update of updated tuples, etc). - vadim 08/29/97 + * + * mao says 17 march 1993: the tests in this routine are correct; + * if you think they're not, you're wrong, and you should think + * about it again. i know, it happened to me. we don't need to + * check commit time against the start time of this transaction + * because 2ph locking protects us from doing the wrong thing. + * if you mess around here, you'll break serializability. the only + * problem with this code is that it does the wrong thing for system + * catalog updates, because the catalogs aren't subject to 2ph, so + * the serializability guarantees we provide don't extend to xacts + * that do catalog accesses. this is unfortunate, but not critical. */ -static bool +static bool HeapTupleSatisfiesNow(HeapTuple tuple) { - if (AMI_OVERRIDE) - return true; - /* - * If the transaction system isn't yet initialized, then we assume - * that transactions committed. We only look at system catalogs - * during startup, so this is less awful than it seems, but it's - * still pretty awful. - */ - - if (!PostgresIsInitialized) - return ((bool)(TransactionIdIsValid((TransactionId)tuple->t_xmin) && - !TransactionIdIsValid((TransactionId)tuple->t_xmax))); - - /* - * XXX Several evil casts are made in this routine. Casting XID to be - * TransactionId works only because TransactionId->data is the first - * (and only) field of the structure. - */ - if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) { - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) - && CommandIdGEScanCommandId(tuple->t_cmin)) { - - return (false); - } - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) - && !CommandIdGEScanCommandId(tuple->t_cmin)) { - - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) { - return (true); - } - - Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)); - - if (CommandIdGEScanCommandId(tuple->t_cmax)) { - return (true); - } - } - + if (AMI_OVERRIDE) + return true; + /* - * this call is VERY expensive - requires a log table lookup. + * If the transaction system isn't yet initialized, then we assume + * that transactions committed. We only look at system catalogs + * during startup, so this is less awful than it seems, but it's still + * pretty awful. */ - - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) { - return (false); - } - /* - * the transaction has been committed--store the commit time _now_ - * instead of waiting for a vacuum so we avoid the expensive call - * next time. + if (!PostgresIsInitialized) + return ((bool) (TransactionIdIsValid((TransactionId) tuple->t_xmin) && + !TransactionIdIsValid((TransactionId) tuple->t_xmax))); + + /* + * XXX Several evil casts are made in this routine. Casting XID to be + * TransactionId works only because TransactionId->data is the first + * (and only) field of the structure. */ - tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); - } - - /* by here, the inserting transaction has committed */ - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) { - return (true); - } - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) { - return (false); - } + if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) + { + + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmin) + && CommandIdGEScanCommandId(tuple->t_cmin)) + { + + return (false); + } + + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmin) + && !CommandIdGEScanCommandId(tuple->t_cmin)) + { + + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax)) + { + return (true); + } + + Assert(TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmax)); + + if (CommandIdGEScanCommandId(tuple->t_cmax)) + { + return (true); + } + } + + /* + * this call is VERY expensive - requires a log table lookup. + */ + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmin)) + { + return (false); + } + + /* + * the transaction has been committed--store the commit time _now_ + * instead of waiting for a vacuum so we avoid the expensive call + * next time. + */ + tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); + } - if (AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) { - return (false); - } + /* by here, the inserting transaction has committed */ + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax)) + { + return (true); + } - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) { - return (true); - } + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmax)) + { + return (false); + } + + if (AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) + { + return (false); + } - /* xmax transaction committed, but no tmax set. so set it. */ - tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmax)) + { + return (true); + } + + /* xmax transaction committed, but no tmax set. so set it. */ + tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); - return (false); + return (false); } /* * HeapTupleSatisfiesSnapshotInternalTimeQual -- - * True iff heap tuple is valid at the snapshot time qualification. + * True iff heap tuple is valid at the snapshot time qualification. * * Note: - * Assumes heap tuple is valid. - * Assumes internal time qualification is valid snapshot qualification. + * Assumes heap tuple is valid. + * Assumes internal time qualification is valid snapshot qualification. */ /* * The satisfaction of Rel[T] requires the following: * * (Xmin is committed && Tmin <= T && - * (Xmax is null || (Xmax is not committed && Xmax != my-transaction) || - * Tmax >= T)) + * (Xmax is null || (Xmax is not committed && Xmax != my-transaction) || + * Tmax >= T)) */ -static bool +static bool HeapTupleSatisfiesSnapshotInternalTimeQual(HeapTuple tuple, - InternalTimeQual qual) + InternalTimeQual qual) { - /* - * XXX Several evil casts are made in this routine. Casting XID to be - * TransactionId works only because TransactionId->data is the first - * (and only) field of the structure. - */ - if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) { - - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) { - return (false); - } - - tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); - } - - if (AbsoluteTimeIsBefore(TimeQualGetSnapshotTime((TimeQual)qual), tuple->t_tmin)) { - return (false); - } - /* the tuple was inserted validly before the snapshot time */ - - if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) { - - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax) || - !TransactionIdDidCommit((TransactionId)tuple->t_xmax)) { - - return (true); - } - - tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); - } - - return ((bool) - AbsoluteTimeIsAfter(tuple->t_tmax, - TimeQualGetSnapshotTime((TimeQual)qual))); + + /* + * XXX Several evil casts are made in this routine. Casting XID to be + * TransactionId works only because TransactionId->data is the first + * (and only) field of the structure. + */ + if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) + { + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmin)) + { + return (false); + } + + tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); + } + + if (AbsoluteTimeIsBefore(TimeQualGetSnapshotTime((TimeQual) qual), tuple->t_tmin)) + { + return (false); + } + /* the tuple was inserted validly before the snapshot time */ + + if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) + { + + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax) || + !TransactionIdDidCommit((TransactionId) tuple->t_xmax)) + { + + return (true); + } + + tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); + } + + return ((bool) + AbsoluteTimeIsAfter(tuple->t_tmax, + TimeQualGetSnapshotTime((TimeQual) qual))); } /* * HeapTupleSatisfiesUpperBoundedInternalTimeQual -- - * True iff heap tuple is valid within a upper bounded time qualification. + * True iff heap tuple is valid within a upper bounded time qualification. * * Note: - * Assumes heap tuple is valid. - * Assumes time qualification is valid ranged qualification with fixed - * upper bound. + * Assumes heap tuple is valid. + * Assumes time qualification is valid ranged qualification with fixed + * upper bound. */ /* * The satisfaction of [T1,T2] requires the following: * * (Xmin is committed && Tmin <= T2 && - * (Xmax is null || (Xmax is not committed && Xmax != my-transaction) || - * T1 is null || Tmax >= T1)) + * (Xmax is null || (Xmax is not committed && Xmax != my-transaction) || + * T1 is null || Tmax >= T1)) */ -static bool +static bool HeapTupleSatisfiesUpperBoundedInternalTimeQual(HeapTuple tuple, - InternalTimeQual qual) + InternalTimeQual qual) { - /* - * XXX Several evil casts are made in this routine. Casting XID to be - * TransactionId works only because TransactionId->data is the first - * (and only) field of the structure. - */ - if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) { - - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) { - return (false); - } - - tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); - } - - if (AbsoluteTimeIsBefore(TimeQualGetEndTime((TimeQual)qual), tuple->t_tmin)) { - return (false); - } - /* the tuple was inserted validly before the range end */ - - if (!AbsoluteTimeIsBackwardCompatiblyValid(TimeQualGetStartTime((TimeQual)qual))) { - return (true); - } - - if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) { - - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax) || - !TransactionIdDidCommit((TransactionId)tuple->t_xmax)) { - - return (true); - } - - tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); - } - - return ((bool)AbsoluteTimeIsAfter(tuple->t_tmax, - TimeQualGetStartTime((TimeQual)qual))); + + /* + * XXX Several evil casts are made in this routine. Casting XID to be + * TransactionId works only because TransactionId->data is the first + * (and only) field of the structure. + */ + if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) + { + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmin)) + { + return (false); + } + + tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); + } + + if (AbsoluteTimeIsBefore(TimeQualGetEndTime((TimeQual) qual), tuple->t_tmin)) + { + return (false); + } + /* the tuple was inserted validly before the range end */ + + if (!AbsoluteTimeIsBackwardCompatiblyValid(TimeQualGetStartTime((TimeQual) qual))) + { + return (true); + } + + if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) + { + + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax) || + !TransactionIdDidCommit((TransactionId) tuple->t_xmax)) + { + + return (true); + } + + tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); + } + + return ((bool) AbsoluteTimeIsAfter(tuple->t_tmax, + TimeQualGetStartTime((TimeQual) qual))); } /* * HeapTupleSatisfiesUpperUnboundedInternalTimeQual -- - * True iff heap tuple is valid within a upper bounded time qualification. + * True iff heap tuple is valid within a upper bounded time qualification. * * Note: - * Assumes heap tuple is valid. - * Assumes time qualification is valid ranged qualification with no - * upper bound. + * Assumes heap tuple is valid. + * Assumes time qualification is valid ranged qualification with no + * upper bound. */ /* * The satisfaction of [T1,] requires the following: * * ((Xmin == my-transaction && Cmin != my-command && - * (Xmax is null || (Xmax == my-transaction && Cmax != my-command))) + * (Xmax is null || (Xmax == my-transaction && Cmax != my-command))) * || * * (Xmin is committed && - * (Xmax is null || (Xmax == my-transaction && Cmax == my-command) || - * (Xmax is not committed && Xmax != my-transaction) || - * T1 is null || Tmax >= T1))) + * (Xmax is null || (Xmax == my-transaction && Cmax == my-command) || + * (Xmax is not committed && Xmax != my-transaction) || + * T1 is null || Tmax >= T1))) */ -static bool +static bool HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple, - InternalTimeQual qual) + InternalTimeQual qual) { - if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) { - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) && - CommandIdGEScanCommandId(tuple->t_cmin)) { - - return (false); - } - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) && - !CommandIdGEScanCommandId(tuple->t_cmin)) { - - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) { + if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) + { + + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmin) && + CommandIdGEScanCommandId(tuple->t_cmin)) + { + + return (false); + } + + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmin) && + !CommandIdGEScanCommandId(tuple->t_cmin)) + { + + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax)) + { + return (true); + } + + Assert(TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmax)); + + return ((bool) ! CommandIdGEScanCommandId(tuple->t_cmax)); + } + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmin)) + { + return (false); + } + + tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); + } + /* the tuple was inserted validly */ + + if (!AbsoluteTimeIsBackwardCompatiblyValid(TimeQualGetStartTime((TimeQual) qual))) + { return (true); - } - - Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)); - - return ((bool) !CommandIdGEScanCommandId(tuple->t_cmax)); - } - - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) { - return (false); - } - - tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin); - } - /* the tuple was inserted validly */ - - if (!AbsoluteTimeIsBackwardCompatiblyValid(TimeQualGetStartTime((TimeQual)qual))) { - return (true); - } - - if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) { - - if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) { - return (true); - } - - if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) { - return (CommandIdGEScanCommandId(tuple->t_cmin)); - /* it looks like error ^^^^ */ - } - - if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) { - return (true); - } - - tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); - } - - return ((bool)AbsoluteTimeIsAfter(tuple->t_tmax, - TimeQualGetStartTime((TimeQual)qual))); + } + + if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) + { + + if (!TransactionIdIsValid((TransactionId) tuple->t_xmax)) + { + return (true); + } + + if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_xmax)) + { + return (CommandIdGEScanCommandId(tuple->t_cmin)); + /* it looks like error ^^^^ */ + } + + if (!TransactionIdDidCommit((TransactionId) tuple->t_xmax)) + { + return (true); + } + + tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax); + } + + return ((bool) AbsoluteTimeIsAfter(tuple->t_tmax, + TimeQualGetStartTime((TimeQual) qual))); } |