1: # include   "../ingres.h"
   2: # include   "../aux.h"
   3: # include   "../symbol.h"
   4: # include   "../tree.h"
   5: # include   "../pipes.h"
   6: # include   "qrymod.h"
   7: 
   8: /*
   9: **  UTIL.C -- qrymod support routines
  10: **
  11: **	This module contains a set of support routines for use
  12: **	by the query modification routines.
  13: **
  14: **	Defined Constants:
  15: **		none
  16: **
  17: **	Defines:
  18: **		trimqlend() -- trim QLEND node off of qualification.
  19: **		appqual() -- append qualification to tree.
  20: **		ferror() -- issue fatal error
  21: **		lsetbit() -- set bit in large set.
  22: **		mergevar() -- merge variables to link terms
  23: **		makezero() -- make a zero node
  24: **
  25: **	Required By:
  26: **		almost all
  27: **
  28: **	Trace Flags:
  29: **		00 -> 19
  30: **
  31: **	History:
  32: **		2/14/79 -- version 6.2/0 release.
  33: */
  34: /*
  35: **  TRIMQLEND -- trim QLEND node off of qualification
  36: **
  37: **	The QLEND node, and possible the AND node preceeding it,
  38: **	are trimmed off.  The result of this routine should be
  39: **	a very ordinary tree like you might see in some textbook.
  40: **
  41: **	A fast not on the algorithm: the pointer 't' points to the
  42: **	current node (the one which we are checking for a QLEND).
  43: **	's' points to 't's parent, and 'r' points to 's's parent;
  44: **	'r' is NULL at the top of the tree.
  45: **
  46: **	This routine works correctly on trees with no QLEND in
  47: **	the first place, returning the original tree.
  48: **
  49: **	If there is a QLEND, it must be on the far right branch
  50: **	of the tree, that is, the tree must be INGRES-canonical.
  51: **
  52: **	Parameters:
  53: **		qual -- the qualification to be trimmed.
  54: **
  55: **	Returns:
  56: **		A pointer to the new qualification.
  57: **		NULL if the qualification was null once the
  58: **			QLEND is stripped.
  59: **
  60: **	Side Effects:
  61: **		The tree pointed to by 'qual' may be modified.
  62: **
  63: **	Called By:
  64: **		protect()
  65: **		appqual()
  66: **		maybe others.
  67: **
  68: **	Trace Flags:
  69: **		none
  70: **
  71: **	Syserrs:
  72: **		none
  73: */
  74: 
  75: QTREE *
  76: trimqlend(qual)
  77: QTREE   *qual;
  78: {
  79:     register QTREE  *t;
  80:     register QTREE  *s;
  81:     register QTREE  *r;
  82: 
  83:     t = qual;
  84: 
  85:     /* check for the simple null qualification case */
  86:     if (t == NULL || t->sym.type == QLEND)
  87:         return (NULL);
  88: 
  89:     /* scan tree for QLEND node */
  90:     for (r = NULL, s = t; (t = t->right) != NULL; r = s, s = t)
  91:     {
  92:         if (t->sym.type == QLEND)
  93:         {
  94:             /* trim of QLEND and AND node */
  95:             if (r == NULL)
  96:             {
  97:                 /* only one AND -- return its operand */
  98:                 return (s->left);
  99:             }
 100: 
 101:             r->right = s->left;
 102:             break;
 103:         }
 104:     }
 105: 
 106:     /* return tree with final AND node and QLEND node pruned */
 107:     return (qual);
 108: }
 109: /*
 110: **  APPQUAL -- append qualification to tree
 111: **
 112: **	The qualification is conjoined to the qualificaion of the
 113: **	tree which is passed.
 114: **
 115: **	Parameters:
 116: **		qual -- a pointer to the qualification to be appended.
 117: **		root -- a pointer to the tree to be appended to.
 118: **
 119: **	Returns:
 120: **		none
 121: **
 122: **	Side Effects:
 123: **		Both 'qual' ad 'root' may be modified.  Note that
 124: **			'qual' is linked into 'root', and must be
 125: **			retained.
 126: **
 127: **	Requires:
 128: **		tree() -- to create a new AND node.
 129: **
 130: **	Called By:
 131: **		view
 132: **		protect
 133: **		integrity
 134: **
 135: **	Trace Flags:
 136: **		13
 137: */
 138: 
 139: appqual(qual, root)
 140: QTREE   *qual;
 141: QTREE   *root;
 142: {
 143:     register QTREE  *p;
 144:     register QTREE  *r;
 145: 
 146:     r = root;
 147: #	ifdef xQTR3
 148:     if (r == NULL)
 149:         syserr("appqual: NULL root");
 150: #	endif
 151: 
 152:     /*
 153: 	**  Find node before QLEND node
 154: 	**	p points the node we are examining, r points to
 155: 	**	it's parent.
 156: 	*/
 157: 
 158:     while ((p = r->right) != NULL && p->sym.type != QLEND)
 159:     {
 160: #		ifdef xQTR3
 161:         if (p->sym.type != AND)
 162:             syserr("appqual: node %d", p->sym.type);
 163: #		endif
 164:         r = p;
 165:     }
 166: 
 167:     /* link in qualification */
 168:     r->right = qual;
 169: }
 170: /*
 171: **  FERROR -- issue fatal error message and abort query
 172: **
 173: **	This call is almost exactly like 'error' (which is called),
 174: **	but never returns: the return is done by 'reset'.  Also, the
 175: **	R_up pipe is flushed.
 176: **
 177: **	Parameters:
 178: **		errno -- the error number.
 179: **		qmode -- the query mode to pass as $0, -1 if none.
 180: **		vn -- the varno of the relation name to pass as
 181: **			$1, -1 if none.
 182: **		p1 to p5 -- the parameters $2 through $6
 183: **
 184: **	Returns:
 185: **		non-local (via reset())
 186: **
 187: **	Side Effects:
 188: **		The error message is generated.
 189: **
 190: **	Defines:
 191: **		ferror
 192: **		Qmdname -- the names of the various Qmodes.
 193: **
 194: **	Requires:
 195: **		error
 196: **		reset
 197: **		Pipe
 198: **		rdpipe
 199: **		wrpipe
 200: **		Nullsync -- send null query on error -- defined
 201: **			in main.c
 202: **		nullsync -- routine to do same -- defined in
 203: **			issue.c.
 204: **
 205: **	Called By:
 206: **		MANY
 207: **
 208: **	Trace Flags:
 209: **		none
 210: **
 211: **	Diagnostics:
 212: **		none of it's own.
 213: **
 214: **	Syserrs:
 215: **		none
 216: */
 217: 
 218: extern struct pipfrmt   Pipe;
 219: char    *Qmdname[] =
 220: {
 221:     "[ERROR]",  /* 0 = mdRETTERM */
 222:     "RETRIEVE", /* 1 = mdRETR */
 223:     "APPEND",   /* 2 = mdAPP */
 224:     "REPLACE",  /* 3 = mdREPL */
 225:     "DELETE",   /* 4 = mdDEL */
 226:     "",     /* 5 = mdCOPY */
 227:     "",     /* 6 = mdCREATE */
 228:     "",     /* 7 = mdDESTROY */
 229:     "",     /* 8 = mdHELP */
 230:     "",     /* 9 = mdINDEX */
 231:     "",     /* 10 = mdMODIFY */
 232:     "",     /* 11 = mdPRINT */
 233:     "",     /* 12 = mdRANGE */
 234:     "",     /* 13 = mdSAVE */
 235:     "DEFINE",   /* 14 = mdDEFINE */
 236:     "RET_UNIQUE",   /* 15 = mdRET_UNI */
 237:     "",     /* 16 = mdVIEW */
 238:     "",     /* 17 = mdUPDATE */
 239:     "",     /* 18 = mdRESETREL */
 240:     "",     /* 19 = mdERIC */
 241:     "",     /* 20 = mdNETQRY */
 242:     "",     /* 21 = mdMOVEREL */
 243:     "",     /* 22 = mdPROT */
 244:     "",     /* 23 = mdINTEG */
 245:     "",     /* 24 = mdDCREATE */
 246: };
 247: 
 248: 
 249: ferror(errno, qmode, vn, p1, p2, p3, p4, p5, p6)
 250: int errno;
 251: int qmode;
 252: int vn;
 253: char    *p1, *p2, *p3, *p4, *p5, *p6;
 254: {
 255:     register char   *x1;
 256:     register char   *x2;
 257:     char        xbuf[MAXNAME + 1];
 258:     register int    i;
 259:     extern char *trim_relname();
 260:     extern int  Nullsync;
 261:     struct retcode  *rc, *nullsync();
 262: 
 263:     /* flush the upward read pipe */
 264:     rdpipe(P_SYNC, &Pipe, R_up);
 265: 
 266:     /* set up qmode and varno parameters */
 267:     x1 = x2 = "";
 268:     i = qmode;
 269:     if (i >= 0)
 270:         x1 = Qmdname[i];
 271:     i = vn;
 272:     if (i >= 0)
 273:         smove(trim_relname(Rangev[i].relid), x2 = xbuf);
 274: 
 275:     /* issue the error message */
 276:     error(errno, x1, x2, p1, p2, p3, p4, p5, p6, 0);
 277: 
 278:     /* issue null query if running Equel */
 279:     if (Nullsync)
 280:         rc = nullsync();
 281:     else
 282:         rc = NULL;
 283: 
 284:     /* sync to above */
 285:     wrpipe(P_PRIME, &Pipe, 0, 0, 0);
 286:     if (rc != NULL)
 287:         wrpipe(P_NORM, &Pipe, W_up, rc, sizeof *rc);
 288:     wrpipe(P_END, &Pipe, W_up);
 289: 
 290:     /* return to main loop for next query */
 291:     reset();
 292: }
 293: /*
 294: **  XERROR -- interface from need() to ferror()
 295: **
 296: **	Parameters:
 297: **		err -- the error number.
 298: **
 299: **	Returns:
 300: **		never
 301: **
 302: **	Side Effects:
 303: **		see ferror
 304: */
 305: 
 306: xerror(err)
 307: int err;
 308: {
 309:     ferror(err, -1, -1, 0);
 310: }
 311: /*
 312: **  LSETBIT -- set a bit in a domain set
 313: **
 314: **	Parameters:
 315: **		bitno -- the bit number to set (0 -> 127)
 316: **		xset -- the set to set it in.
 317: **
 318: **	Returns:
 319: **		none
 320: **
 321: **	Side Effects:
 322: **		none
 323: **
 324: **	Called By:
 325: **		makedset()
 326: **
 327: **	History:
 328: **		8/21/78 (eric) -- written.
 329: */
 330: 
 331: lsetbit(bitno, xset)
 332: int bitno;
 333: int xset[8];
 334: {
 335:     register int    b;
 336:     register int    n;
 337:     register int    *x;
 338: 
 339:     x = xset;
 340: 
 341:     b = bitno;
 342:     n = b >> LOG2WORDSIZE;
 343:     b &= WORDSIZE - 1;
 344: 
 345:     x[n] |= 1 << b;
 346: }
 347: /*
 348: **  MERGEVAR -- merge variable numbers to link terms
 349: **
 350: **	One specified variable gets mapped into another, effectively
 351: **	merging those two variables.  This is used for protection
 352: **	and integrity, since the constraint read from the tree
 353: **	must coincide with one of the variables in the query tree.
 354: **
 355: **	Parameters:
 356: **		va -- the variable which will dissappear.
 357: **		vb -- the variable which 'va' gets mapped into.
 358: **		root -- the root of the tree to map.
 359: **
 360: **	Returns:
 361: **		none
 362: **
 363: **	Side Effects:
 364: **		The tree pointed at by 'root' gets VAR and RESDOM
 365: **			nodes mapped.
 366: **		Range table entry for 'va' is deallocated.
 367: **		The 'Remap' vector gets reset and left in an
 368: **			undefined state.
 369: **
 370: **	Requires:
 371: **		clrrange -- to clear the 'Remap' vector (called with
 372: **			a FALSE parameter, so 'Rangev' is not cleared).
 373: **		mapvars -- to do the actual mapping.
 374: **		Remap -- to define the mapping for mapvars().
 375: **		Rangev -- to check consistency and to clear the entry
 376: **			for variable 'va'.
 377: **
 378: **	Called By:
 379: **		protect.c
 380: **		integrity.c
 381: **
 382: **	Trace Flags:
 383: **		16
 384: **
 385: **	Diagnostics:
 386: **		none
 387: **
 388: **	Syserrs:
 389: **		mergevar: range %d %d
 390: **			Either 'va' or 'vb' was out of range.
 391: **		mergevar: incon %s %s
 392: **			The variables for 'va' and 'vb' must range
 393: **			over the same relation.  The strings are the
 394: **			relation names if this does not hold.
 395: **		mergevar: undef %d %d
 396: **			The variables 'va' and 'vb' must both
 397: **			be defined.
 398: */
 399: 
 400: mergevar(va, vb, root)
 401: int va;
 402: int vb;
 403: QTREE   *root;
 404: {
 405:     register int    a;
 406:     register int    b;
 407: 
 408:     a = va;
 409:     b = vb;
 410: 
 411: #	ifdef xQTR1
 412:     if (tTf(16, 0))
 413:     {
 414:         printf("\nmergevar(%d->%d)", a, b);
 415:         treepr(root, NULL);
 416:     }
 417: #	endif
 418: 
 419:     /*
 420: 	**  Insure that 'va' and 'vb' are consistant, that is,
 421: 	**  that they both are in range, are defined, and range over
 422: 	**  the same relation.
 423: 	*/
 424: 
 425:     if (a < 0 || b < 0 || a >= MAXVAR + 1 || b >= MAXVAR + 1)
 426:         syserr("mergevar: range %d %d", a, b);
 427:     if (!Rangev[a].rused || !Rangev[b].rused)
 428:         syserr("mergevar: undef %d %d", a, b);
 429:     if (!bequal(Rangev[a].relid, Rangev[b].relid, MAXNAME) ||
 430:         !bequal(Rangev[a].rowner, Rangev[b].rowner, 2))
 431:         syserr("mergevar: incon %.14s %.14s", Rangev[a].relid,
 432:             Rangev[b].relid);
 433: 
 434:     /*
 435: 	**  To do the actual mapping, we will set up 'Remap' and
 436: 	**  call 'mapvars()'.  This is because I am too lazy to
 437: 	**  do it myself.
 438: 	*/
 439: 
 440:     clrrange(FALSE);
 441:     Remap[a] = b;
 442:     mapvars(root);
 443: 
 444:     /* delete a from the range table */
 445:     Rangev[a].rused = FALSE;
 446: }
 447: /*
 448: **  MAKEZERO -- make a node with value 'zero'
 449: **
 450: **	A node is created with value representing the zero value
 451: **	for the specified type, that is, 0 for integers, 0.0 for
 452: **	floats, and the blank string for chars.
 453: **
 454: **	Parameters:
 455: **		typ -- the node type.
 456: **
 457: **	Returns:
 458: **		a pointer to the zero node.
 459: **
 460: **	Side Effects:
 461: **		space is grabbed from Qbuf
 462: **
 463: **	Requires:
 464: **		Qbuf -- for space.
 465: **		need() -- to get that space.
 466: **
 467: **	History:
 468: **		11/21/78 (eric) -- written.
 469: */
 470: 
 471: QTREE *
 472: makezero(typ)
 473: int typ;
 474: {
 475:     register int        l;
 476:     register struct symbol  *s;
 477:     int         symbuf[(sizeof *s + 4) / sizeof l];
 478:     char            *need();
 479: 
 480:     s = (struct symbol *) &symbuf;
 481:     s->type = typ;
 482: 
 483:     switch (typ)
 484:     {
 485:       case INT:
 486:         s->len = l = 2;
 487:         i2deref(s->value) = 0;
 488:         break;
 489: 
 490:       case FLOAT:
 491:         s->len = l = 4;
 492:         f4deref(s->value) = 0.0;
 493:         break;
 494: 
 495:       case CHAR:
 496:         s->len = l = 2;
 497:         i2deref(s->value) = 0x2020; /* (two spaces) */
 498:         break;
 499: 
 500:       default:
 501:         syserr("makezero: typ %d", typ);
 502:     }
 503: 
 504:     /* duplicate the node into Qbuf */
 505:     l += sizeof *s;
 506:     s = (struct symbol *) need(Qbuf, l);
 507:     bmove(&symbuf, s, l);
 508:     return ((QTREE *) s);
 509: }

Defined functions

makezero defined in line 471; used 2 times
xerror defined in line 306; used 2 times

Defined variables

Qmdname defined in line 219; used 2 times
Last modified: 1995-02-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3437
Valid CSS Valid XHTML 1.0 Strict