findsymbol(struct header *hd, int fd, struct sym *s) { register int i, j; struct sym next; if (startsymbol(hd, fd)) return (-1); for (i = hd->ssize; i--; ) { j = read(fd, &next, sizeof(next)); if (j != sizeof(next)) { if (j) printf("symbol table error %d,%d,%d\n", hd->ssize, i, j); return (-1); } if (bequal(next.symname, s->symname, sizeof(next.symname))) { s->type = next.type; s->value = next.value; return (0); } } return (1); }
static void parse_msg(const char *bytes, size_t len, struct user *user, int kq) { static char chanhdr[] = "GOTROOMMSG "; static char usrhdr[] = "GOTUSERMSG "; static size_t ftrlen = sizeof(CRLF)-1; struct user *u; struct msg *m; size_t offset, hlen, rlen, size; char *buf, *hdr, *cp; if (len == 0) { cmderr(user, MNORECIP, kq); return; } if ((cp = memchr(bytes, ' ', len)) == NULL) { cmderr(user, MNOSPACE, kq); return; } rlen = cp-bytes; if (bytes[0] == '#') { hdr = chanhdr; hlen = sizeof(chanhdr)-1; offset = 0; } else { hdr = usrhdr; hlen = sizeof(usrhdr)-1; offset = rlen+1; } size = hlen + (user->namelen+1) + (len-offset) + ftrlen; m = malloc_or_die(sizeof(*m) + size); buf = (char *)(m+1); bcopy(hdr, buf, hlen); buf += hlen; bcopy(user->name, buf, user->namelen); buf += user->namelen; *buf++ = ' '; bcopy(bytes+offset, buf, len-offset); bcopy(CRLF, buf+len-offset, ftrlen); m->bytes = (char *)(m+1); m->len = size; m->refcnt = 0; if (bytes[0] == '#') { struct channel *c; struct list *up; for (short i = 0; i < user->nchans; i++) { c = user->joined_chans[i]; if (bequal(c->name, c->len, bytes, rlen)) { LIST_FOREACH_ELT(up, &c->users, struct user, u) writeto(u, m, kq); ok(user, kq); return; } } cmderr(user, CHNJOINED, kq); free_msg(m); } else if ((u = table_get(users, bytes, rlen)) == NULL) {
/* ** MERGEVAR -- merge variable numbers to link terms ** ** One specified variable gets mapped into another, effectively ** merging those two variables. This is used for protection ** and integrity, since the constraint read from the tree ** must coincide with one of the variables in the query tree. ** ** Parameters: ** va -- the variable which will dissappear. ** vb -- the variable which 'va' gets mapped into. ** root -- the root of the tree to map. ** ** Returns: ** none ** ** Side Effects: ** The tree pointed at by 'root' gets VAR and RESDOM ** nodes mapped. ** Range table entry for 'va' is deallocated. ** The 'Qt.qt_remap' vector gets reset and left in an ** undefined state. ** ** Trace Flags: ** 72 */ void mergevar(register int a, register int b, qtree_t *root) { register int i; #ifdef xQTR1 if (tTf(72, 0)) { printf("\nmergevar(%d->%d)", a, b); treepr(root); } #endif /* ** Insure that 'a' and 'b' are consistant, that is, ** that they both are in range, are defined, and range over ** the same relation. */ if (a < 0 || b < 0 || a >= MAX_VARS + 1 || b >= MAX_VARS + 1) syserr("mergevar: range %d %d", a, b); if (Qt.qt_rangev[a].rngvdesc == NULL || Qt.qt_rangev[b].rngvdesc == NULL) syserr("mergevar: undef %d %d", a, b); if (!bequal(Qt.qt_rangev[a].rngvdesc->d_r.r_id, Qt.qt_rangev[b].rngvdesc->d_r.r_id, MAX_NAME_SIZE) || !bequal(Qt.qt_rangev[a].rngvdesc->d_r.r_owner, Qt.qt_rangev[b].rngvdesc->d_r.r_owner, 2)) { syserr("mergevar: incon %.14s %.14s", Qt.qt_rangev[a].rngvdesc->d_r.r_id, Qt.qt_rangev[b].rngvdesc->d_r.r_id); } /* ** To do the actual mapping, we will set up 'Qt.qt_remap' and ** call 'mapvars()'. This is because I am too lazy to ** do it myself. */ for (i = 0; i < MAX_RANGES; i++) Qt.qt_remap[i] = i; Qt.qt_remap[a] = b; mapvars(root); /* delete a from the range table */ declare(a, NULL); }
/** This is an implementation of the Boyer-Moore Search. * It uses the delta1 only with the fast/slow loops. * It searches for the string 'str' starting at the current buffer location. * If sensitive is 0, then the match is case insensitive. * The point is left at the byte after the search str. * @param buff The buffer to search in. * @param str The string to search for. * @param sensitive Should the search be case sensitive? * @return 1 if string found, 0 if not. */ int bm_search(struct buff *buff, const char *str, int sensitive) { int delta[NUMASCII], len, i, shift; len = strlen(str) - 1; /* Init the delta table to str length. For each char in the * str, store the offset from the str start in the delta * table. If we are in case insensitive mode - lower case the * match string and mark both the upper case version and the * lower case version of the match string chars in the delta * array. */ for (i = 0; i < NUMASCII; ++i) delta[i] = len ? len : 1; if (sensitive) for (i = 0; i <= len; ++i) delta[(uint8_t)str[i]] = len - i; else for (i = 0; i <= len; ++i) { delta[toupper(str[i])] = len - i; delta[tolower(str[i])] = len - i; } /* search forward*/ while (!bisend(buff)) { /* fast loop - delta will be 0 if matched */ while (!bisend(buff) && delta[buffint()]) bmove(buff, delta[buffint()]); /* slow loop */ for (i = len; bequal(buff, str[i], sensitive); bmove(buff, -1), --i) if (i == 0) { bmove(buff, len + 1); return 1; } /* compute shift. shift must be forward! */ if (i + delta[buffint()] > len) shift = delta[buffint()]; else shift = len - i + 1; bmove(buff, shift); } return 0; }
int icompare(char *ax, char *bx, char frmt, char frml) { register ANYTYPE *a, *b; register int length; ANYTYPE atemp, btemp; length = frml & I1MASK; if (frmt == CHAR_CONST) return (scompare(ax, length, bx, length)); a = &atemp; b = &btemp; bmove(ax, (char *) a, length); bmove(bx, (char *) b, length); if (bequal((char *) a, (char *) b, length)) return (0); switch (frmt) { case INT_CONST: switch (length) { case 1: return (a->i1type - b->i1type); case 2: return (a->i2type - b->i2type); case 4: return (a->i4type > b->i4type ? 1 : -1); } break; case FLOAT_CONST: if (frml == 4) { if ( a->f4type > b->f4type ) return ( 1 ); else return ( -1 ); } else { if ( a->f8type > b->f8type ) return ( 1 ); else return ( -1 ); } break; } syserr("compare: t=%d,l=%d", frmt, frml); /*NOTREACHED*/ return(-1); }
/** This is an implementation of the Boyer-Moore Search that searches backwards. * It uses the delta1 only with the fast/slow loops. * It searches for the string 'str' starting at the current buffer location. * If sensitive is 0, then the match is case insensitive. * The point is left at the start of the search str. * @param buff The buffer to search in. * @param str The string to search backwards for. * @param sensitive Should the search be case sensitive? * @return 1 if string found, 0 if not. */ int bm_rsearch(struct buff *buff, const char *str, int sensitive) { int delta[NUMASCII], len, i, shift; len = strlen(str) - 1; /* Init the delta table to str length. For each char in the * str, store the negative offset from the str start in the * delta table. */ for (i = 0; i < NUMASCII; ++i) delta[i] = len ? -len : -1; if (sensitive) for (i = len; i >= 0; --i) delta[(uint8_t)str[i]] = -i; else for (i = len; i >= 0; --i) { delta[toupper(str[i])] = -i; delta[tolower(str[i])] = -i; } /* reverse search */ bmove(buff, -len); while (!bisstart(buff)) { /* fast loop - delta will be 0 if matched */ while (delta[buffint()] && !bisstart(buff)) bmove(buff, delta[buffint()]); /* slow loop */ for (i = 0; i <= len && bequal(buff, str[i], sensitive); ++i, bmove1(buff)) ; if (i > len) { /* we matched! */ bmove(buff, -len - 1); return 1; } /* compute shift. shift must be backward! */ shift = delta[buffint()] + i < 0 ? delta[buffint()] : -i - 1; bmove(buff, shift); } return 0; }
static void parse_part(const char *bytes, size_t len, struct user *u, int kq) { if (*bytes != '#') { cmderr(u, CHSHARP, kq); return; } if (illegal_name(bytes, len, u, kq, CHEMTPY, CHILLEGAL)) return; for (short i = 0; i < u->nchans; i++) { struct channel *c = u->joined_chans[i]; if (bequal(c->name, c->len, bytes, len)) { rmuser(u, c); u->joined_chans[i] = u->joined_chans[--u->nchans]; ok(u, kq); return; } } cmderr(u, CHNJOINED, kq); }
/* ** STRATEGY ** ** Attempts to limit access scan to less than the entire De.ov_source ** relation by finding a key which can be used for associative ** access to the De.ov_source reln or an index thereon. The key is ** constructed from domain-value specifications found in the ** clauses of the qualification list using sub-routine findsimp ** in findsimp.c and other subroutines in file key.c */ int strategy(void) { register int i, allexact; acc_param_t sourceparm, indexparm; index_t itup, rtup; key_t lowikey[MAX_2ND_KEYS+1], highikey[MAX_2ND_KEYS+1]; key_t lowbkey[MAX_2ND_KEYS+1], highbkey[MAX_2ND_KEYS+1]; register desc_t *d; extern desc_t Inddes; char *tp; long l_lid[MAXLID], h_lid[MAXLID]; int keytype; long page, l, t; int lidsize; locator_t tidloc; keytype = allexact = 0; #ifdef xOTR1 if (tTf(70, 0)) printf("STRATEGY\tSource=%.12s\tNewq = %d\n", De.ov_source ? De.ov_source->d_r.r_id : "(none)", De.de_newq); #endif while (De.de_newq) /* if De.de_newq=TRUE then compute a new strategy */ /* NOTE: This while loop is executed only once */ { De.ov_scanr = De.ov_source; if (!De.ov_scanr) return (1); /* return immediately if there is no source relation */ De.ov_fmode = NOKEY; /* assume a find mode with no key */ if (!De.ov_qlist) break; /* if no qualification then you must scan entire rel */ /* ** Here we check for the special condition ** of a where clause consisting only of a tid. */ if (tid_only_test()) return(1); /* copy structure of source relation into sourceparm */ paramd(De.ov_source, &sourceparm); /* if source is unkeyed and has no sec index then give up */ if (sourceparm.mode == NOKEY && De.ov_source->d_r.r_indexed <= 0 && !De.ov_source->d_r.r_dim) break; /* find all simple clauses if any */ if (!findsimps()) break; /* break if there are no simple clauses */ /* Four steps are now performed to try and find a key. ** First if the relation is hashed then an exact key is search for ** ** Second if there are secondary indices, then a search is made ** for an exact key. If that fails then a check is made for ** a range key. The result of the rangekey check is saved. ** ** A step to check for possible use of Btrees is made here, ** although in actuality, an exact btreekey search is used ** after an exact range key search but before a range key search. ** A BTree range search is used only as a last alternative ** to a no key search. ** ** Third if the relation is an ISAM a check is made for ** an exact key or a range key. ** ** Fourth if there is a secondary index, then if step two ** found a key, that key is used. ** ** Lastly, give up and scan the entire relation */ /* step one. Try to find exact key on primary */ if (exactkey(&sourceparm, De.ov_lkey_struct)) { De.ov_fmode = EXACTKEY; break; } /* step two. If there is an index, try to find an exactkey on one of them */ if (De.ov_source->d_r.r_indexed > 0) { opencatalog("indices", OR_READ); ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_id, IRELIDP); ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_owner, IOWNERP); if ((i = find(&Inddes, EXACTKEY, &De.ov_lotid, &De.ov_hitid, (char *)&itup)) != 0) syserr("strategy:find indices %d", i); while (!(i = get(&Inddes, &De.ov_lotid, &De.ov_hitid, (char *)&itup, NXTTUP))) { #ifdef xOTR1 if (tTf(70, 3)) printup(&Inddes, (char *)&itup); #endif if (!bequal(itup.i_relname, De.ov_source->d_r.r_id, MAX_NAME_SIZE) || !bequal(itup.i_owner, De.ov_source->d_r.r_owner, 2)) continue; parami(&itup, &indexparm); if (exactkey(&indexparm, De.ov_lkey_struct)) { De.ov_fmode = EXACTKEY; d = openindex(itup.i_index); /* temp check for 6.0 index */ if ((int) d->d_r.r_indexed == -1) ov_err(BADSECINDX); De.ov_scanr = d; break; } if (De.ov_fmode == LRANGEKEY) continue; /* a range key on a s.i. has already been found */ if ((allexact = rangekey(&indexparm, lowikey, highikey)) != 0) { bmove((char *)&itup, (char *)&rtup, sizeof(itup)); /* save tuple */ De.ov_fmode = LRANGEKEY; } } if (i < 0) syserr("stragery:bad get from index-rel %d", i); /* If an exactkey on a secondary index was found, look no more. */ if (De.ov_fmode == EXACTKEY) break; } /* attempt to use Btree in aiding search */ if ((i = btreekey(lowbkey, highbkey)) != 0) { if (i > 0) De.ov_fmode = BTREEKEY; else if (De.ov_fmode != LRANGEKEY) { /* use range key search over btree range search */ keytype = i; De.ov_fmode = BTREERANGE; } } /* step three. Look for a range key on primary */ if ((i = rangekey(&sourceparm, De.ov_lkey_struct, De.ov_hkey_struct)) != 0) { if (i < 0) De.ov_fmode = EXACTKEY; else if (De.ov_fmode == BTREEKEY) { /* use exact btree search over range search */ bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey)); bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey)); } else De.ov_fmode = LRANGEKEY; break; } if (De.ov_fmode == BTREEKEY) { bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey)); bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey)); break; } /* last step. If a secondary index range key was found, use it */ if (De.ov_fmode == LRANGEKEY) { if (allexact < 0) De.ov_fmode = EXACTKEY; d = openindex(rtup.i_index); /* temp check for 6.0 index */ if ((int) d->d_r.r_indexed == -1) ov_err(BADSECINDX); De.ov_scanr = d; bmove((char *)lowikey, (char *)De.ov_lkey_struct, sizeof(lowikey)); bmove((char *)highikey, (char *)De.ov_hkey_struct, sizeof(highikey)); break; } /* nothing will work. give up! */ break; } /* check for De.de_newq = FALSE and no source relation */ if (!De.ov_scanr) return (1); /* ** At this point the strategy is determined. ** ** If De.ov_fmode is EXACTKEY then De.ov_lkey_struct contains ** the pointers to the keys. ** ** If De.ov_fmode is LRANGEKEY then De.ov_lkey_struct contains ** the pointers to the low keys and De.ov_hkey_struct ** contains pointers to the high keys. ** ** If De.ov_fmode is BTREEKEY then De.ov_lkey_struct contains ** pointers to the key lid. ** ** If De.ov_fmode is BTREERANGE then lowbkey contains pointers ** to the low key lid and highbkey contains pointers to the ** high key lid. ** ** If De.ov_fmode is NOKEY, then a full scan will be performed */ #ifdef xOTR1 if (tTf(70, -1)) printf("De.ov_fmode= %d\n",De.ov_fmode); #endif if (De.ov_fmode == BTREERANGE) { /* requires special type of search to limit tid scan */ for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) { l_lid[i] = 0; h_lid[i] = 0; } lidsize = LIDSIZE * De.ov_scanr->d_r.r_dim; /* get low lids */ if (keytype == -1 || keytype == -3) { tp = De.ov_keyl + De.ov_scanr->d_r.r_width - lidsize; bmove(l_lid, tp, lidsize); setallkey(lowbkey, De.ov_keyl); bmove(tp, l_lid, lidsize); } /* get high lids */ if (keytype == -2 || keytype == -3) { tp = De.ov_keyh + De.ov_scanr->d_r.r_width - lidsize; bmove(h_lid, tp, lidsize); setallkey(highbkey, De.ov_keyh); bmove(tp, h_lid, lidsize); } setglobalint(BTREE_FD_NAME, De.ov_scanr->d_btreefd); /* scan through lids to fill in unprovided lids and to check ** for lids that are too big */ page = RT; for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) { if (l_lid[i] <= 0) l_lid[i] = 1; l = last_lid(page) - 1; if (h_lid[i] < 0) return(0); if (!h_lid[i] || h_lid[i] > l) h_lid[i] = l; if ((t = get_tid(page, h_lid[i], &tidloc)) < 0) syserr("bad gettid in strategy, lid = %ld\n", h_lid[i]); page = t; } /* check whether lo > hi */ for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) if (l_lid[i] < h_lid[i]) break; else if (l_lid[i] > h_lid[i]) return(0); #ifdef xOTR1 if (tTf(70,0)) for (i = 0 ; i < De.ov_scanr->d_r.r_dim; ++i) printf("hi = %ld, lo = %ld\n", h_lid[i], l_lid[i]); #endif /* find the smallest and largest possible tids of the lids ** within the provided range */ btreerange(De.ov_scanr, l_lid, h_lid, &De.ov_lotid, &De.ov_hitid); } else { /* set up the key tuples */ if (De.ov_fmode != NOKEY) { if (setallkey(De.ov_lkey_struct, De.ov_keyl)) return (0); /* query false. There is a simple ** clause which can never be satisfied. ** These simple clauses can be choosey! */ } if ((i = find(De.ov_scanr, De.ov_fmode, &De.ov_lotid, &De.ov_hitid, De.ov_keyl)) != 0) syserr("strategy:find1 %.12s, %d", De.ov_scanr->d_r.r_id, i); if (De.ov_fmode == LRANGEKEY) { setallkey(De.ov_hkey_struct, De.ov_keyh); if ((i = find(De.ov_scanr, HRANGEKEY, &De.ov_lotid, &De.ov_hitid, De.ov_keyh)) != 0) syserr("strategy:find2 %.12s, %d", De.ov_scanr->d_r.r_id, i); } } #ifdef xOTR1 if (tTf(70, 1)) { printf("Lo"); dumptid(&De.ov_lotid); printf("Hi"); dumptid(&De.ov_hitid); } #endif return (1); }
int copy(int pc, paramv_t *pv) { extern char *Usercode; extern int Noupdt; register int i, pid; register char *cp; int stat; int op; #ifdef xZTR1 if (tTf(30,1)) { printf("entered copy\n"); prvect(pc, pv); } #endif Duptuple = 0; Truncount = 0; Tupcount = 0; Baddoms = 0; Relname = pv[0].pv_val.pv_str; Into = (pv[pc-2].pv_val.pv_str[0] == 'i'); Filename = pv[pc-1].pv_val.pv_str; /* relation must exist and not be a system relation */ /* in addition a copy "from" can't be done if the user */ /* doesn't own the relation */ /* and furthermore it can't have an index */ i = 0; /* assume all is well */ if ((op = openr(&Des, OR_WRITE, Relname)) != 0) { if (op == AMOPNVIEW_ERR) i = NOCPVIEW; else { if (op < 0) syserr("COPY: openr 1 (%.14s) %d", Relname, op); else /* non-existant relation */ i = NOEXIST; } } else { if (Into) { if ((Des.d_r.r_status & S_PROTALL) && (Des.d_r.r_status & S_PROTRET) && !bequal(Usercode, Des.d_r.r_owner, USERCODE_SIZE)) i = RELPROTECT; } else { /* extra checking if this is a copy "from" */ /* must be owned by the user */ if (!bequal(Usercode, Des.d_r.r_owner, USERCODE_SIZE)) i = NOTOWNER; else /* must be updateable */ if ((Des.d_r.r_status & S_NOUPDT) && Noupdt) i = NOUPDT; else /* must not be indexed */ if (Des.d_r.r_indexed > 0) i = DESTINDEX; } } if (i) { closer(&Des); return (error(i, Relname, 0)); /* relation doesn't exist for this user */ } /* check that file name begins with a "/" */ cp = Filename; while (*cp == ' ') cp++; if (*cp != '/') { closer(&Des); return (error(FULLPATH, Filename, 0)); } /* fill map structures with transfer information */ if ((i = mapfill(&pv[1])) != 0) { closer(&Des); return (i); /* error in user semantics */ } /* fork a child process which will run as the real user */ /* that child will complete the copy and exit */ if (pipe(Piped)) syserr("copy:can't make pipe"); if ((pid = fork()) < 0) syserr("copy:can't fork"); if (pid) { /* the ingres parent */ close(Piped[1]); ruboff(0); /* interrupts off */ stat = fullwait(pid, "copy"); if (read(Piped[0], &Des.d_addc, 4) != 4) syserr("copy:can't read pipe"); close(Piped[0]); closer(&Des); /* close the rel */ rubon(); /* if stat is != 0 then add on 5800 for error */ if (stat) stat += 5800; return (stat); /* done */ } /* the child. change to run as the real user */ if (signal(SIGINT, SIG_IGN) != SIG_IGN) { signal(SIGINT, copydone); /* clean up on rubout */ } setuid(getuid()); setgid(getgid()); if (Into) { /* from relation into file */ if ((File_iop = fopen(Filename, "w")) == NULL) /* create file for user */ i = nferror(NOFILECRT, Filename, 0); /* cant create file */ else { if (Lockrel) /* set a shared lock on relation*/ setrll(A_SLP, &Des.d_tid, M_SHARE); i = rel_file(); } } else { /* from UNIX file into relation */ if ((File_iop = fopen(Filename, "r")) == NULL) i = nferror(NOFILEOPN, Filename, 0); /* cant open user file */ else { if (Lockrel) /* set an exclusive lock on relat*/ setrll(A_SLP, &Des.d_tid, M_EXCL); i = file_rel(); if (Duptuple) nferror(DUPTUPS, locv(Duptuple), 0); /* warning only */ if (Baddoms) nferror(BADDOMS, locv(Baddoms), 0); /* warning only */ } } copydone(i); return(0); }
/* ** Mapfill fills the Map structure with the list ** of user supplied attributes. It then reads ** the list of relation attributes and checks ** for matching attribute names. ** ** if an error occures then mapfill returns -1 ** else it returns 0 ** ** Mapfill performs special processing on ** dummy domains. ** ** If no user attributes are given, then "given"=FALSE ** and each attribute in the relation is set up to be ** copied in the formats and order in which they ** exist in the relation */ int mapfill(paramv_t *aptr) { register paramv_t *ap; register struct map *mp; register int i; char *fp; extern desc_t Attdes; attr_t att; struct tup_id tid, limtid; int given, cnt; Mapcount = 0; mp = Map; ap = aptr; /* Gather list of user supplied attributes */ while (*(ap->pv_val.pv_str) != '\0') { /* check for overflow */ if (Mapcount == MAXMAP) return (error(TOOMANYATTR, 0)); /* more than MAXMAP specifiers */ mp->paramname = (ap->pv_val).pv_str; /* save pointer to user supplied name */ pmove(((ap++)->pv_val).pv_str, mp->name, MAX_NAME_SIZE, ' '); fp = ((ap++)->pv_val).pv_str; /* fp points to format string */ mp->used = 0; mp->rlen = 0; /* zero in case this is a dummy domain */ mp->roffset = 0; mp->fdelim = 0; /* check domain type in *fp */ switch (*fp++) { case 'c': i = CHAR_CONST; if ((mp->fdelim = zcheck(fp)) == 0) return (-1); /* bad delimitor */ break; case 'f': i = FLOAT_CONST; break; case 'i': i = INT_CONST; break; case DUMMY: i = DUMMY; if ((mp->fdelim = zcheck(fp)) == 0) return (-1); break; default: return (error(BADATTRTYPE, mp->paramname, --fp, 0)); } mp->ftype = i; /* convert format length to binary */ mp->flen = atoi(fp); if (mp->flen < 0 || mp->flen > 511 || (mp->ftype == FLOAT_CONST && mp->flen != 4 && mp->flen != 8) || (mp->ftype == INT_CONST && mp->flen != 1 && mp->flen != 2 && mp->flen != 4)) { return (error(BADATTRLEN, mp->paramname, --fp, 0)); /* bad length for attribute */ } /* process dummy domain if any */ if (Into && mp->ftype == DUMMY && mp->flen) { if ((fp = dumvalue(mp->paramname)) == 0) return (5807); /* bad dummy name */ mp->rtype = *fp; /* use first char of string */ } /* check for format of type "c0delim" on copy "into" */ if (Into && mp->flen == 0 && mp->fdelim != Delimitor) { fp = mp->fdelim; /* is there room for a dummy domain? */ mp++; if (++Mapcount == MAXMAP) return (error(TOOMANYATTR, 0)); /* no room */ /* create a dummy entry */ mp->ftype = DUMMY; mp->flen = 1; mp->rtype = *fp; mp->roffset = mp->rlen = 0; } mp++; Mapcount++; } /* if no atributes were given, set flag */ if (Mapcount) given = TRUE; else given = FALSE; /* open attribute relation and prepare for scan */ opencatalog("attribute", OR_READ); ingres_setkey(&Attdes, &att, Des.d_r.r_id, ATTRELID); ingres_setkey(&Attdes, &att, Des.d_r.r_owner, ATTOWNER); if (find(&Attdes, EXACTKEY, &tid, &limtid, &att)) syserr("find error for att-rel"); /* scan Map for each relation attribute */ while ((i = get(&Attdes, &tid, &limtid, &att, 1)) == 0) { if (!bequal(&Des, &att, MAX_NAME_SIZE+2)) continue; /* if no user attributes were supplied, fake an entry */ if (!given) { Mapcount++; mp = &Map[att.a_id -1]; mp->rtype = mp->ftype = att.a_fmt; mp->rlen = mp->flen = att.a_len & I1MASK; mp->roffset = att.a_off; mp->used = 1; mp->paramname = mp->name; /* point to name */ bmove(att.a_name, mp->name, MAX_NAME_SIZE); /* copy name */ continue; } mp = Map; /* check each user domain for match with relation domain */ for (i = Mapcount; i--; mp++) { if (mp->ftype == DUMMY) continue; /* ignore dummy */ if (!bequal(mp->name, att.a_name, 12)) continue; mp->rtype = att.a_fmt; mp->rlen = att.a_len & I1MASK; mp->roffset = att.a_off; mp->used++; /* check for special case of C0 in a copy "into" */ if (Into && (mp->flen == 0) && mp->ftype == CHAR_CONST) { switch (mp->rtype) { case CHAR_CONST: mp->flen = mp->rlen; break; case INT_CONST: switch (mp->rlen) { case 1: mp->flen = Out_arg.i1width; break; case 2: mp->flen = Out_arg.i2width; break; case 4: mp->flen = Out_arg.i4width; } break; case FLOAT_CONST: if (mp->rlen == 4) mp->flen = Out_arg.f4width; else mp->flen = Out_arg.f8width; } } /* if this is a copy "from" then break otherwise continue. In a copy "into" an attribute might be copied more than once */ if (!Into) break; } } if (i < 0) syserr("bad get from att-rel %d", i); /* check that all user domains have been identified */ cnt = 0; mp = Map; for (i = Mapcount; i--; mp++) { cnt += mp->flen; if (mp->ftype == DUMMY) continue; if (!mp->used) { if ( Into && bequal(mp->name,"tid ",12) ) { mp->flen = 4; mp->rtype = INT_CONST; mp->rlen = 4; mp->roffset = -1; mp->used++; } else return (error(ATTRNOEXIST, mp->paramname, Relname, 0)); /* unrecognizable domain name */ } } /* check that copy into doesn't exceed buffer size */ if (Into && cnt > BUFSIZ) return (error(FILETOOWIDE, 0)); /* cnt too large */ return (0); }
strategy() { register int i, allexact; struct accessparam sourceparam, indexparam; struct index itup, rtup; struct key lowikey[MAXKEYS+1], highikey[MAXKEYS+1]; register struct descriptor *d; extern struct descriptor Inddes; struct descriptor *openindex(); # ifdef xOTR1 if (tTf(31, 0)) printf("STRATEGY\tSource=%.12s\tNewq = %d\n", Source ? Source->relid : "(none)", Newq); # endif while (Newq) /* if Newq=TRUE then compute a new strategy */ /* NOTE: This while loop is executed only once */ { Scanr = Source; if (!Scanr) return (1); /* return immediately if there is no source relation */ Fmode = NOKEY; /* assume a find mode with no key */ if (!Qlist) break; /* if no qualification then you must scan entire rel */ /* copy structure of source relation into sourceparam */ paramd(Source, &sourceparam); /* if source is unkeyed and has no sec index then give up */ if (sourceparam.mode == NOKEY && Source->relindxd <= 0) break; /* find all simple clauses if any */ if (!findsimps()) break; /* break if there are no simple clauses */ /* Four steps are now performed to try and find a key. ** First if the relation is hashed then an exact key is search for ** ** Second if there are secondary indexes, then a search is made ** for an exact key. If that fails then a check is made for ** a range key. The result of the rangekey check is saved. ** ** Third if the relation is an ISAM a check is made for ** an exact key or a range key. ** ** Fourth if there is a secondary index, then if step two ** found a key, that key is used. ** ** Lastly, give up and scan the entire relation */ /* step one. Try to find exact key on primary */ if (exactkey(&sourceparam, &Lkey_struct)) { Fmode = EXACTKEY; break; } /* step two. If there is an index, try to find an exactkey on one of them */ if (Source->relindxd) { opencatalog("indexes", 0); setkey(&Inddes, &itup, Source->relid, IRELIDP); setkey(&Inddes, &itup, Source->relowner, IOWNERP); if (i = find(&Inddes, EXACTKEY, &Lotid, &Hitid, &itup)) syserr("strategy:find indexes %d", i); while (!(i = get(&Inddes, &Lotid, &Hitid, &itup, NXTTUP))) { # ifdef xOTR1 if (tTf(31, 3)) printup(&Inddes, &itup); # endif if (!bequal(itup.irelidp, Source->relid, MAXNAME) || !bequal(itup.iownerp, Source->relowner, 2)) continue; parami(&itup, &indexparam); if (exactkey(&indexparam, &Lkey_struct)) { Fmode = EXACTKEY; d = openindex(itup.irelidi); /* temp check for 6.0 index */ if (d->relindxd == -1) ov_err(BADSECINDX); Scanr = d; break; } if (Fmode == LRANGEKEY) continue; /* a range key on a s.i. has already been found */ if (allexact = rangekey(&indexparam, &lowikey, &highikey)) { bmove(&itup, &rtup, sizeof itup); /* save tuple */ Fmode = LRANGEKEY; } } if (i < 0) syserr("stragery:bad get from index-rel %d", i); /* If an exactkey on a secondary index was found, look no more. */ if (Fmode == EXACTKEY) break; } /* step three. Look for a range key on primary */ if (i = rangekey(&sourceparam, &Lkey_struct, &Hkey_struct)) { if (i < 0) Fmode = EXACTKEY; else Fmode = LRANGEKEY; break; } /* last step. If a secondary index range key was found, use it */ if (Fmode == LRANGEKEY) { if (allexact < 0) Fmode = EXACTKEY; d = openindex(rtup.irelidi); /* temp check for 6.0 index */ if (d->relindxd == -1) ov_err(BADSECINDX); Scanr = d; bmove(&lowikey, &Lkey_struct, sizeof lowikey); bmove(&highikey, &Hkey_struct, sizeof highikey); break; } /* nothing will work. give up! */ break; } /* check for Newq = FALSE and no source relation */ if (!Scanr) return (1); /* ** At this point the strategy is determined. ** ** If Fmode is EXACTKEY then Lkey_struct contains ** the pointers to the keys. ** ** If Fmode is LRANGEKEY then Lkey_struct contains ** the pointers to the low keys and Hkey_struct ** contains pointers to the high keys. ** ** If Fmode is NOKEY, then a full scan will be performed */ # ifdef xOTR1 if (tTf(31, -1)) printf("Fmode= %d\n",Fmode); # endif /* set up the key tuples */ if (Fmode != NOKEY) { if (setallkey(&Lkey_struct, Keyl)) return (0); /* query false. There is a simple ** clause which can never be satisfied. ** These simple clauses can be choosey! */ } if (i = find(Scanr, Fmode, &Lotid, &Hitid, Keyl)) syserr("strategy:find1 %.12s, %d", Scanr->relid, i); if (Fmode == LRANGEKEY) { setallkey(&Hkey_struct, Keyh); if (i = find(Scanr, HRANGEKEY, &Lotid, &Hitid, Keyh)) syserr("strategy:find2 %.12s, %d", Scanr->relid, i); } # ifdef xOTR1 if (tTf(31, 1)) { printf("Lo"); dumptid(&Lotid); printf("Hi"); dumptid(&Hitid); } # endif return (1); }
int isttyname(register char *n) { return (strcmp(n, "console") == 0 || bequal(n, "tty", 3)); }
int d_prot(int pc, paramv_t *pv) { protect_t protup; struct tup_id protid; protect_t prokey; protect_t proxtup; char ubuf[MAX_LINE_SIZE + 1]; register int i; short ix; register qtree_t *t; qtree_t *root; register char *p; relation_t reltup; relation_t relkey; struct tup_id reltid; int relstat; int all_pro; /* ** Fill in the protection tuple with the information ** from the parser, validating as we go. ** ** Also, determine if we have a PERMIT xx to ALL ** with no further qualification case. The variable ** 'all_pro' is set to reflect this. */ clr_tuple(&Prodes, (char *) &protup); all_pro = TRUE; /* read operation set */ if (pv->pv_type != PV_INT) syserr("d_prot: opset"); protup.p_opset = pv->pv_val.pv_int; if ((protup.p_opset & PRO_RETR) != 0) protup.p_opset |= PRO_TEST | PRO_AGGR; pv++; /* read relation name */ if (pv->pv_type != PV_STR) syserr("d_prot: relid"); pmove(pv->pv_val.pv_str, protup.p_rel, MAX_NAME_SIZE, ' '); pv++; /* read relation owner */ if (pv->pv_type != PV_STR) syserr("d_prot: relid"); bmove(pv->pv_val.pv_str, protup.p_owner, sizeof(protup.p_owner)); pv++; /* read user name */ if (pv->pv_type != PV_STR) syserr("d_prot: user"); if (strcmp(pv->pv_val.pv_str, "all") == 0) bmove(" ", protup.p_user, sizeof(protup.p_user)); else { /* look up user in 'users' file */ if (getnuser(pv->pv_val.pv_str, ubuf)) qmerror(BADUSRNAME, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); for (p = ubuf; *p != ':' && *p != 0; p++) continue; bmove(++p, protup.p_user, sizeof(protup.p_user)); /* XXX - agc assumes only 2 chars */ if (p[0] == ':' || p[1] == ':' || p[2] != ':') syserr("d_prot: users %s", ubuf); all_pro = FALSE; } pv++; /* read terminal id */ if (pv->pv_type != PV_STR) { syserr("d_prot: user"); } if (strcmp(pv->pv_val.pv_str, "all") == 0) { pmove("", protup.p_term, sizeof(protup.p_term), ' '); } else { pmove(pv->pv_val.pv_str, protup.p_term, sizeof(protup.p_term), ' '); if (!isttyname(pv->pv_val.pv_str)) qmerror(BADTERM, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); all_pro = FALSE; } pv++; /* read starting time of day */ if (pv->pv_type != PV_INT) syserr("d_prot: btod"); protup.p_tbegin = pv->pv_val.pv_int; if (pv->pv_val.pv_int > 0) all_pro = FALSE; pv++; /* read ending time of day */ if (pv->pv_type != PV_INT) syserr("d_prot: etod"); protup.p_tend = pv->pv_val.pv_int; if (pv->pv_val.pv_int < 24 * 60 - 1) all_pro = FALSE; pv++; /* read beginning day of week */ if (pv->pv_type != PV_STR) syserr("d_prot: bdow"); i = cvt_dow(pv->pv_val.pv_str); if (i < 0) qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); /* bad dow */ protup.p_dbegin = i; if (i > 0) all_pro = FALSE; pv++; /* read ending day of week */ if (pv->pv_type != PV_STR) syserr("d_prot: edow"); i = cvt_dow(pv->pv_val.pv_str); if (i < 0) qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); /* bad dow */ protup.p_dend = i; if (i < 6) all_pro = FALSE; pv++; /* ** Check for valid tree: ** There must be a tree defined, and all variables ** referenced must be owned by the current user; this ** is because you could otherwise get at data by ** mentioning it in a permit statement; see protect.c ** for a better explanation of this. */ if (pv->pv_type != PV_QTREE) syserr("d_prot: tree"); root = (qtree_t *) pv->pv_val.pv_qtree; pv++; for (i = 0; i < MAX_VARS + 1; i++) { if (Qt.qt_rangev[i].rngvdesc == NULL) continue; if (!bequal(Qt.qt_rangev[i].rngvdesc->d_r.r_owner, Usercode, USERCODE_SIZE)) qmerror(OWNEDNOT, -1, i, 0); } /* test for dba */ if (!bequal(Usercode, Admin.ad_h.adm_owner, USERCODE_SIZE)) qmerror(NOTDBA, -1, Qt.qt_resvar, 0); /* get domain reference set from target list */ /* (also, find the TREE node) */ t = root->left; if (t->sym.type == TREE) { for (i = 0; i < 8; i++) protup.p_domset[i] = -1; } else { for (i = 0; i < 8; i++) protup.p_domset[i] = 0; for (; t->sym.type != TREE; t = t->left) { if (t->right->sym.type != VAR || t->sym.type != RESDOM || t->right->sym.value.sym_var.varno != Qt.qt_resvar) syserr("d_prot: garbage tree"); lsetbit(t->right->sym.value.sym_var.attno, protup.p_domset); } all_pro = FALSE; } /* trim off the target list, since it isn't used again */ root->left = t; /* ** Check out the target relation. ** We first save the varno of the relation which is ** getting the permit stuff. Also, we check to see ** that the relation mentioned is a base relation, ** and not a view, since that tuple would never do ** anything anyway. Finally, we clear the Qt.qt_resvar ** so that it does not get output to the tree catalog. ** This would result in a 'syserr' when we tried to ** read it. */ protup.p_result = Qt.qt_resvar; #ifdef xQTR3 if (Qt.qt_resvar < 0) syserr("d_prot: Rv %d", Qt.qt_resvar); #endif if (BITISSET(S_VIEW, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_status)) qmerror(NOTREALREL, -1, Qt.qt_resvar, 0); /* is a view */ /* clear the (unused) Qt.qt_qmode */ #ifdef xQTR3 if (Qt.qt_qmode != mdPROT) syserr("d_prot: Qt.qt_qmode %d", Qt.qt_qmode); #endif Qt.qt_qmode = -1; /* ** Check for PERMIT xx to ALL case. ** The r_status bits will be adjusted as necessary ** to reflect these special cases. ** ** This is actually a little tricky, since we cannot ** afford to turn off any permissions. If we already ** have some form of PERMIT xx to ALL access, we must ** leave it. */ relstat = Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_status; if (all_pro && (protup.p_opset & PRO_RETR) != 0) { if (protup.p_opset == -1) relstat &= ~S_PROTALL; else { relstat &= ~S_PROTRET; if ((protup.p_opset & ~(PRO_RETR|PRO_AGGR|PRO_TEST)) != 0) { /* some special case: still insert prot tuple */ all_pro = FALSE; } } } else all_pro = FALSE; /* see if we are adding any tuples */ if (!all_pro) relstat |= S_PROTUPS; /* ** Change relstat field in relation catalog if changed */ if (relstat != Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_status) { opencatalog("relation", OR_WRITE); ingres_setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_id, RELID); ingres_setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_owner, RELOWNER); i = getequal(&Reldes, &relkey, &reltup, &reltid); if (i != 0) syserr("d_prot: geteq %d", i); reltup.r_status = relstat; i = replace(&Reldes, &reltid, &reltup, FALSE); if (i != 0) syserr("d_prot: repl %d", i); if (noclose(&Reldes) != 0) syserr("d_prot: noclose(rel)"); } Qt.qt_resvar = -1; if (!all_pro) { /* ** Output the created tuple to the protection catalog ** after making other internal adjustments and deter- ** mining a unique sequence number (with the protect ** catalog locked). */ if (root->right->sym.type != QLEND) protup.p_tree = puttree(root, protup.p_rel, protup.p_owner, mdPROT); else protup.p_tree = -1; /* compute unique permission id */ opencatalog("protect", OR_WRITE); setrll(A_SLP, &Prodes.d_tid, M_EXCL); ingres_setkey(&Prodes, &prokey, protup.p_rel, PRORELID); ingres_setkey(&Prodes, &prokey, protup.p_owner, PRORELOWN); for (ix = 2; ; ix++) { ingres_setkey(&Prodes, &prokey, &ix, PROPERMID); i = getequal(&Prodes, &prokey, &proxtup, &protid); if (i < 0) syserr("d_prot: geteq"); else if (i > 0) break; } protup.p_perm = ix; /* do actual insert */ i = insert(&Prodes, &protid, &protup, FALSE); if (i < 0) syserr("d_prot: insert"); if (noclose(&Prodes) != 0) syserr("d_prot: noclose(pro)"); /* clear the lock */ unlrl(&Prodes.d_tid); } return(0); }
int indexx(int pc, paramv_t *pv) { register int i; int j; register struct dom *dom; register paramv_t *p; char *primary, *indx; int ndoms, newpc; struct tup_id tid, hitid; struct tup_id xtid; paramv_t newpv[MAX_2ND_KEYS * 2 + 4]; char primtup[MAX_TUP_SIZE], systup[MAX_TUP_SIZE]; desc_t desc, pridesc; extern desc_t Reldes; extern desc_t Attdes; extern desc_t Inddes; relation_t relkey, reltup; attr_t attkey, atttup; index_t indtup; struct dom domain[MAX_2ND_KEYS]; primary = pv[0].pv_val.pv_str; indx = pv[1].pv_val.pv_str; #ifdef xZTR1 if (tTf(33, -1)) printf("index: (pri %s ind %s)\n", primary, indx); #endif i = openr(&pridesc, OR_READ, primary); if (i == AMOPNVIEW_ERR) return (error(NOINDVIEW, primary, 0)); if (i > 0) return (error(NOPRIMREL, primary, 0)); if (i < 0) syserr("INDEX : openr (%.14s) %d", primary, i); if (!bequal(pridesc.d_r.r_owner, Usercode, USERCODE_SIZE)) { i = NOTOWNED; } else if (pridesc.d_r.r_status & S_CATALOG) { i = NOINDXSYSREL; } else if (pridesc.d_r.r_indexed == SECINDEX) { i = ALREADYINDX; } if (i) { closer(&pridesc); return (error(i, primary, 0)); } /* ** GATHER INFO. ON DOMAINS */ opencatalog("attribute", OR_WRITE); ingres_setkey(&Attdes, &attkey, primary, ATTRELID); ingres_setkey(&Attdes, &attkey, pridesc.d_r.r_owner, ATTOWNER); pc -= 2; p = &pv[2]; dom = domain; for (i = 0; i < pc; i++) { if (i >= MAX_2ND_KEYS) { closer(&pridesc); return (error(TOOMUCHDOMS, (p->pv_val).pv_str, primary, 0)); /* too many keys */ } ingres_setkey(&Attdes, &attkey, (p->pv_val).pv_str, ATTNAME); j = getequal(&Attdes, &attkey, &atttup, &tid); if (j < 0) syserr("INDEX: geteq att %d", j); if (j) { closer(&pridesc); return (error(NODOM, (p->pv_val).pv_str, 0)); /* key not in relation */ } if (pridesc.d_r.r_dim > 0 && atttup.a_id == pridesc.d_r.r_attrc) { /* attempting to use lid field as part of index */ closer(&pridesc); return(error(NOINDXLID, primary, (p->pv_val).pv_str, 0)); } dom->id = atttup.a_id; dom->off = atttup.a_off; dom->frml = atttup.a_len & I1MASK; dom->frm[0] = atttup.a_fmt; p++; dom++; } ndoms = i; noclose(&Attdes); /* ** The "order" of the steps have been altered to improve ** recovery possibilities */ /* ** STEP 1 & 2: CREATE INDEX RELATION. */ newpv[0].pv_val.pv_str = "0202"; newpv[1].pv_val.pv_str = indx; newpc = 2; p = &pv[2]; dom = domain; for (i = 0; i < pc; i++) { newpv[newpc++].pv_val.pv_str = (p->pv_val).pv_str; itoa(dom->frml, &dom->frm[1]); newpv[newpc++].pv_val.pv_str = dom->frm; dom++; p++; } newpv[newpc++].pv_val.pv_str = "tidp"; newpv[newpc++].pv_val.pv_str = "i4"; newpv[newpc].pv_type = PV_EOF; if (create(newpc, newpv)) { closer(&pridesc); return (-1); } /* This is done for concurrency reasons */ if (noclose(&Reldes)) syserr("index: noclose"); /* ** STEP 5: FILL UP THE SECONDARY INDEX FILE ITSELF */ if (Lockrel) { /* set a shared relation lock */ setrll(A_SLP, &pridesc.d_tid, M_SHARE); } if ((i = openr(&desc, OR_WRITE, indx)) != 0) syserr("INDEX: openr %.14s %d", indx, i); find(&pridesc, NOKEY, &tid, &hitid, (void *) NULL); while ((i = get(&pridesc, &tid, &hitid, primtup, TRUE)) == 0) { dom = domain; for (i = j = 0; j < ndoms; j++) { #ifdef BIG_ENDIAN if (dom->frm[0] != 'c') i = ((i-1)|(dom->frml-1))+1; #endif bmove(&primtup[dom->off], &systup[i], dom->frml); i += dom->frml; dom++; } #ifdef BIG_ENDIAN i = ((i-1)|3)+1; #endif /* move in pointer */ bmove(&tid, &systup[i], sizeof(tid)); if ((j = insert(&desc, &xtid, systup, TRUE)) < 0) { syserr("INDEX: insert %.14s %d", indx, j); } } if (i < 0) { syserr("INDEX: get %.14s %d", primary, i); } closer(&pridesc); closer(&desc); /* ** STEP 3: ENTRIES TO INDEX-REL */ /* mv in primary name */ pmove(primary, indtup.i_relname, MAX_NAME_SIZE, ' '); /* primary owner */ bmove(pridesc.d_r.r_owner, indtup.i_owner, sizeof(pridesc.d_r.r_owner)); /* index name */ pmove(indx, indtup.i_index, MAX_NAME_SIZE, ' '); indtup.i_indrelspec = M_HEAP; for (i = 0; i < MAX_2ND_KEYS; i++) { indtup.i_dom[i] = (i < ndoms) ? domain[i].id : 0; } opencatalog("indices", OR_WRITE); if ((i = insert(&Inddes, &tid, (char *) &indtup, TRUE)) < 0) syserr("INDEX: insert ix %d", i); /* ** STEP 4: TURN BIT ON IN PRIMARY RELATION TO SHOW IT IS BEING INDEXED */ opencatalog("relation", OR_WRITE); ingres_setkey(&Reldes, &relkey, primary, RELID); ingres_setkey(&Reldes, &relkey, pridesc.d_r.r_owner, RELOWNER); if ((i = getequal(&Reldes, &relkey, &reltup, &tid)) != 0) syserr("INDEX: geteq rel %d", i); reltup.r_indexed = SECBASE; if ((i = replace(&Reldes, &tid, &reltup, TRUE)) < 0) syserr("INDEX: replace rel %d", i); if (Lockrel) unlrl(&pridesc.d_tid); /* release relation lock */ return (0); }