home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / parser / catalogutils.c next >
Encoding:
C/C++ Source or Header  |  1993-02-11  |  21.3 KB  |  927 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    catalogutils.c
  4.  *    
  5.  *   NOTES
  6.  *
  7.  *   IDENTIFICATION
  8.  *    $Header: /private/postgres/src/parser/RCS/catalogutils.c,v 1.45 1992/07/29 17:06:40 mer Exp $
  9.  * ----------------------------------------------------------------
  10.  */
  11. #include "tmp/postgres.h"
  12.  
  13. RcsId("$Header: /private/postgres/src/parser/RCS/catalogutils.c,v 1.45 1992/07/29 17:06:40 mer Exp $");
  14.  
  15. #include "tmp/simplelists.h"
  16. #include "tmp/datum.h"
  17.  
  18. #include "utils/log.h"
  19. #include "utils/fmgr.h"
  20.  
  21. #include "nodes/pg_lisp.h"
  22. #include "catalog/syscache.h"
  23.  
  24. #include "exceptions.h"
  25. #include "catalogutils.h"
  26. #include "catalog/pg_inherits.h"
  27.  
  28. #include "access/skey.h"
  29. #include "access/relscan.h"
  30. #include "access/tupdesc.h"
  31. #include "access/htup.h"
  32. #include "access/heapam.h"
  33.  
  34. #include "storage/buf.h"
  35.  
  36. struct {
  37.     char *field;
  38.     int code;
  39. } special_attr[] =
  40.            {
  41.            { "ctid", SelfItemPointerAttributeNumber },
  42.            { "lock", RuleLockAttributeNumber },
  43.            { "oid", ObjectIdAttributeNumber },
  44.            { "xmin", MinTransactionIdAttributeNumber },
  45.            { "cmin", MinCommandIdAttributeNumber },
  46.            { "xmax", MaxTransactionIdAttributeNumber },
  47.            { "cmax", MaxCommandIdAttributeNumber },
  48.            { "chain", ChainItemPointerAttributeNumber },
  49.            { "anchor", AnchorItemPointerAttributeNumber },
  50.            { "tmin", MinAbsoluteTimeAttributeNumber },
  51.            { "tmax", MaxAbsoluteTimeAttributeNumber },
  52.            { "vtype", VersionTypeAttributeNumber }
  53.            };
  54.  
  55. #define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
  56.   
  57. static String attnum_type[SPECIALS] = {
  58.     "tid",
  59.     "lock",
  60.     "oid",
  61.     "xid",
  62.     "cid",
  63.     "xid",
  64.     "cid",
  65.     "tid",
  66.     "tid",
  67.     "abstime",
  68.     "abstime",
  69.     "char"
  70.   };
  71.  
  72. struct tuple *SearchSysCache();
  73.  
  74. #define    MAXFARGS 8        /* max # args to a c or postquel function */
  75.  
  76. extern    ObjectId    **argtype_inherit();
  77. extern    ObjectId    **genxprod();
  78. extern    OID        typeid_get_relid();
  79.  
  80. /*
  81.  *  This structure is used to explore the inheritance hierarchy above
  82.  *  nodes in the type tree in order to disambiguate among polymorphic
  83.  *  functions.
  84.  */
  85.  
  86. typedef struct _InhPaths {
  87.     int        nsupers;    /* number of superclasses */
  88.     ObjectId    self;        /* this class */
  89.     ObjectId    *supervec;    /* vector of superclasses */
  90. } InhPaths;
  91.  
  92. /* return a Type structure, given an typid */
  93. Type
  94. get_id_type(id)
  95. long id;
  96. {
  97.     HeapTuple tup;
  98.  
  99.     if (!(tup = SearchSysCacheTuple(TYPOID, id))) {
  100.     elog ( WARN, "type id lookup of %d failed", id);
  101.     return(NULL);
  102.     }
  103.     return((Type) tup);
  104. }
  105.  
  106. /* return a Type structure, given type name */
  107. Type
  108. type(s)
  109. char *s;
  110. {
  111.     HeapTuple tup;
  112.  
  113.     if (s == NULL) {
  114.     elog ( WARN , "type(): Null type" );
  115.     }
  116.  
  117.     if (!(tup = SearchSysCacheTuple(TYPNAME, s))) {
  118.     elog (WARN , "type name lookup of %s failed", s);
  119.     }
  120.     return((Type) tup);
  121. }
  122.  
  123. /* given attribute id, return type of that attribute */
  124. /* XXX Special case for pseudo-attributes is a hack */
  125. OID
  126. att_typeid(rd, attid)
  127. Relation rd;
  128. int attid;
  129. {
  130.  
  131.     if (attid < 0) {
  132.     return(typeid(type(attnum_type[-attid-1])));
  133.     }
  134.     /* -1 because varattno (where attid comes from) returns one
  135.        more than index */
  136.     return(rd->rd_att.data[attid-1]->atttypid);
  137. }
  138.  
  139. /* given type, return the type OID */
  140. OID
  141. typeid(tp)
  142. Type tp;
  143. {
  144.     if (tp == NULL) {
  145.     elog ( WARN , "typeid() called with NULL type struct");
  146.     }
  147.     return(tp->t_oid);
  148. }
  149.  
  150. /* given type (as type struct), return the length of type */
  151. int16
  152. tlen(t)
  153. Type t;
  154. {
  155.     TypeTupleForm    typ;
  156.  
  157.     typ = (TypeTupleForm)GETSTRUCT(t);
  158.     return(typ->typlen);
  159. }
  160.  
  161. /* given type (as type struct), return the value of its 'byval' attribute.*/
  162. bool
  163. tbyval(t)
  164. Type t;
  165. {
  166.     TypeTupleForm    typ;
  167.  
  168.     typ = (TypeTupleForm)GETSTRUCT(t);
  169.     return(typ->typbyval);
  170. }
  171.  
  172. /* given type (as type struct), return the name of type */
  173. Name
  174. tname(t)
  175. Type t;
  176. {
  177.     TypeTupleForm    typ;
  178.  
  179.     typ = (TypeTupleForm)GETSTRUCT(t);
  180.     return((Name)&(typ->typname));
  181. }
  182.  
  183. /* given type (as type struct), return wether type is passed by value */
  184. int
  185. tbyvalue(t)
  186. Type t;
  187. {
  188.     TypeTupleForm typ;
  189.  
  190.     typ = (TypeTupleForm) GETSTRUCT(t);
  191.     return(typ->typbyval);
  192. }
  193.  
  194. /* given operator, return the operator OID */
  195. OID
  196. oprid(op)
  197. Operator op;
  198. {
  199.     return(op->t_oid);
  200. }
  201.  
  202. /* Given operator, types of arg1, and arg2, return oper struct */
  203. Operator
  204. oper(op, arg1, arg2)
  205. char *op;
  206. int arg1, arg2;    /* typeids */
  207. {
  208.     HeapTuple tup;
  209.  
  210.     /*
  211.     if (!OpCache) {
  212.     init_op_cache();
  213.     }
  214.     */
  215.     if (!(tup = SearchSysCacheTuple(OPRNAME, op, arg1, arg2, (char *) 'b'))) {
  216.     op_error(op, arg1, arg2);
  217.     return(NULL);
  218.     }
  219.     return((Operator) tup);
  220. }
  221. /* Find default type for right arg of binary operator */
  222. Operator
  223. oper_default(op, arg1)
  224. char *op;
  225. int arg1;       /* typeid */
  226. {
  227.     HeapTuple tup;
  228.  
  229.     /* see if there is only one type available for right arg. of binary op. */
  230.     tup = (HeapTuple) FindDefaultType(op, arg1);
  231.     if(!tup){  /* this could mean a) there is no operator named op.
  232.                                 b) there are more than one possible right arg */
  233.        if (!(tup = SearchSysCacheTuple(OPRNAME, op, arg1, arg1, (char *) 'b')))
  234.        {
  235.           /* there's no reasonable default type for the right argument */
  236.           return(NULL);
  237.        }
  238.     }
  239.  
  240.     return((Operator) tup);
  241. }
  242.  
  243. /* Given unary right-side operator (operator on right), return oper struct */
  244. Operator
  245. right_oper(op, arg)
  246. char *op;
  247. int arg; /* type id */
  248. {
  249.     HeapTuple tup;
  250.  
  251.     /*
  252.     if (!OpCache) {
  253.     init_op_cache();
  254.     }
  255.     */
  256.     if (!(tup = SearchSysCacheTuple(OPRNAME, op, arg, 0, (char *) 'r'))) {
  257.     elog ( WARN ,
  258.           "Can't find right op: %s for type %d", op, arg );
  259.     return(NULL);
  260.     }
  261.     return((Operator) tup);
  262. }
  263.  
  264. /* Given unary left-side operator (operator on left), return oper struct */
  265. Operator
  266. left_oper(op, arg)
  267.      char *op;
  268.      int arg; /* type id */
  269. {
  270.     HeapTuple tup;
  271.     
  272.     if (!(tup = SearchSysCacheTuple(OPRNAME, op, 0, arg, (char *) 'l'))) {
  273.         elog (WARN ,
  274.             "Can't find left op: %s for type %s",
  275.             op, tname(get_id_type(arg)));
  276.         return(NULL);
  277.     }
  278.     return ((Operator) tup);
  279. }
  280.  
  281. /* given range variable, return id of variable */
  282.    
  283. int
  284. varattno ( rd , a)
  285.      Relation rd;
  286.      char *a;
  287. {
  288.     int i;
  289.     
  290.     for (i = 0; i < rd->rd_rel->relnatts; i++) {
  291.         if (!strcmp(&rd->rd_att.data[i]->attname, a)) {
  292.             return(i+1);
  293.         }
  294.     }
  295.     for (i = 0; i < SPECIALS; i++) {
  296.         if (!strcmp(special_attr[i].field, a)) {
  297.             return(special_attr[i].code);
  298.         }
  299.     }
  300.  
  301.     elog(WARN,"Relation %s does not have attribute %s\n", 
  302.          RelationGetRelationName(rd), a );
  303.     return(-1);
  304. }
  305. /* given range variable, return id of variable */
  306.    
  307. int
  308. nf_varattno ( rd , a)
  309.      Relation rd;
  310.      char *a;
  311. {
  312.     int i;
  313.     
  314.     for (i = 0; i < rd->rd_rel->relnatts; i++) {
  315.         if (!strcmp(&rd->rd_att.data[i]->attname, a)) {
  316.             return(i+1);
  317.         }
  318.     }
  319.     for (i = 0; i < SPECIALS; i++) {
  320.         if (!strcmp(special_attr[i].field, a)) {
  321.             return(special_attr[i].code);
  322.         }
  323.     }
  324.     return InvalidAttributeNumber;
  325. }
  326. /*-------------
  327.  * given an attribute number and a relation, return its relation name
  328.  */
  329. Name
  330. getAttrName(rd, attrno)
  331. Relation rd;
  332. int attrno;
  333. {
  334.     Name name;
  335.     int i;
  336.  
  337.     if (attrno<0) {
  338.     for (i = 0; i < SPECIALS; i++) {
  339.         if (special_attr[i].code == attrno) {
  340.             name = (Name) special_attr[i].field;
  341.             return(name);
  342.         }
  343.     }
  344.     elog(WARN, "Illegal attr no %d for relation %s\n",
  345.         attrno, RelationGetRelationName(rd));
  346.     } else if (attrno >=1 && attrno<= RelationGetNumberOfAttributes(rd)) {
  347.     name = &(rd->rd_att.data[attrno-1]->attname);
  348.     return(name);
  349.     } else {
  350.     elog(WARN, "Illegal attr no %d for relation %s\n",
  351.         attrno, RelationGetRelationName(rd));
  352.     }
  353.  
  354.     /*
  355.      * Shouldn't get here, but we want lint to be happy...
  356.      */
  357.  
  358.     return(NULL);
  359. }
  360.  
  361. /* given range variable, return id of variable */
  362. RangeTablePosn ( rangevar , options )
  363.      char *rangevar;
  364.      List options;
  365. {
  366.     int index = 1;
  367.     extern LispValue p_rtable;
  368.     LispValue temp = p_rtable;
  369.     int inherit = 0;
  370.     int timerange = 0;
  371.  
  372.     index = 1;
  373.     temp = p_rtable;
  374.     while ( ! lispNullp (temp )) {
  375.         LispValue refvalue = ( CAR ( CAR (temp )));
  376.         if ( IsA (refvalue,LispStr)) {
  377.         if ( (! strcmp ( CString ( refvalue ),
  378.                 rangevar ) ) &&
  379.             (inherit == inherit) &&
  380.             (timerange == timerange))
  381.           return (index );
  382.         } else {
  383.         List i;
  384.         foreach ( i , refvalue ) {
  385.             Name actual_ref = (Name)CString(CAR(i));
  386.             if ( !strcmp ( actual_ref , rangevar ) &&
  387.              inherit == inherit &&
  388.              timerange == timerange )
  389.               return ( index );
  390.         }
  391.         }
  392.         temp = CDR(temp);
  393.         index++;
  394.     }
  395.         return(0);
  396. }
  397.  
  398. /* given range variable, return id of variable */
  399. List
  400. RangeTablePositions ( rangevar , options )
  401.      char *rangevar;
  402.      List options;
  403. {
  404.     int index = 1;
  405.     extern LispValue p_rtable;
  406.     LispValue temp = p_rtable;
  407.     List list_of_positions = NULL;
  408.     int inherit = 0;
  409.     int timerange = 0;
  410.     
  411.     index = 1;
  412.     temp = p_rtable;
  413.  
  414.     while ( ! lispNullp (temp )) {
  415.     LispValue refvalue = CAR ( CAR ( temp ));
  416.     if ( IsA (refvalue,LispStr)) {
  417.         if ( (! strcmp ( CString ( refvalue ),
  418.                 rangevar ) ) &&
  419.         (inherit == inherit) &&
  420.         (timerange == timerange)) {
  421.         
  422.         list_of_positions = lispCons ( lispInteger ( index ),
  423.                           list_of_positions );
  424.         } 
  425.     } else {
  426.         List i;
  427.         foreach ( i , refvalue ) {
  428.         Name actual_ref = (Name)CString(CAR(i));
  429.         if ( !strcmp ( actual_ref , rangevar ) &&
  430.             inherit == inherit &&
  431.             timerange == timerange ) {
  432.             
  433.         list_of_positions = lispCons ( lispInteger ( index ),
  434.                           list_of_positions );
  435.         }
  436.         }
  437.     }
  438.     temp = CDR(temp);
  439.     index++;
  440.     }
  441.  
  442.     return(list_of_positions);
  443. }
  444.  
  445. /* Given a typename and value, returns the ascii form of the value */
  446.  
  447. char *
  448. outstr(typename, value)
  449. char *typename;    /* Name of type of value */
  450. char *value;    /* Could be of any type */
  451. {
  452.     TypeTupleForm tp;
  453.     OID op;
  454.  
  455.     tp = (TypeTupleForm ) GETSTRUCT(type(typename));
  456.     op = tp->typoutput;
  457.     return((char *) fmgr(op, value));
  458. }
  459.  
  460. /* Given a Type and a string, return the internal form of that string */
  461. char *
  462. instr2(tp, string)
  463. Type tp;
  464. char *string;
  465. {
  466.     return(instr1((TypeTupleForm ) GETSTRUCT(tp), string));
  467. }
  468.  
  469. /* Given a type structure and a string, returns the internal form of
  470.    that string */
  471. char *
  472. instr1(tp, string)
  473. TypeTupleForm tp;
  474. char *string;
  475. {
  476.     OID op;
  477.     OID typelem;
  478.     
  479.     op = tp->typinput;
  480.     typelem = tp->typelem; /* XXX - used for array_in */
  481.     return((char *) fmgr(op, string, typelem));
  482. }
  483.  
  484. /* Given a typename and string, returns the internal form of that string */
  485. char *
  486. instr(typename, string)
  487. char *typename;    /* Name of type to turn string into */
  488. char *string;
  489. {
  490.     TypeTupleForm tp;
  491.  
  492.     tp = (TypeTupleForm) GETSTRUCT(type(typename));
  493.     return(instr1(tp, string));
  494. }
  495.  
  496. OID
  497. funcid_get_rettype ( funcid)
  498.      OID funcid;
  499. {
  500.     HeapTuple func_tuple = NULL;
  501.     OID funcrettype = (OID)0;
  502.  
  503.     func_tuple = SearchSysCacheTuple(PROOID,funcid,0,0,0);
  504.  
  505.     if ( !HeapTupleIsValid ( func_tuple )) 
  506.     elog (WARN, "function  %d does not exist", funcid);
  507.     
  508.     funcrettype = (OID)
  509.       ((struct proc *)GETSTRUCT(func_tuple))->prorettype ;
  510.  
  511.     return (funcrettype);
  512. }
  513.  
  514. ObjectId *
  515. funcname_get_funcargtypes ( function_name )
  516.      char *function_name;
  517. {
  518.     HeapTuple func_tuple = NULL;
  519.     ObjectId *oid_array = NULL;
  520.     struct proc *foo;
  521.     func_tuple = SearchSysCacheTuple(PRONAME,function_name,0,0,0);
  522.  
  523.     if ( !HeapTupleIsValid ( func_tuple )) 
  524.     elog (WARN, "function named %s does not exist", function_name);
  525.     
  526.     foo = (struct proc *)GETSTRUCT(func_tuple);
  527.     oid_array = foo->proargtypes.data;
  528.     return (oid_array);
  529. }
  530.  
  531. bool
  532. func_get_detail(funcname, nargs, oid_array, funcid, rettype, retset)
  533.     char *funcname;
  534.     int nargs;
  535.     ObjectId *oid_array;
  536.     ObjectId *funcid;            /* return value */
  537.     ObjectId *rettype;            /* return value */
  538.     bool *retset;            /* return value */
  539. {
  540.     ObjectId *fargs;
  541.     ObjectId **oid_vector;
  542.     HeapTuple ftup;
  543.     Form_pg_proc pform;
  544.  
  545.     /* find the named function in the system catalogs */
  546.     ftup = SearchSysCacheTuple(PRONAME, funcname, 0, 0, 0);
  547.  
  548.     if (!HeapTupleIsValid(ftup))
  549.     return (false);
  550.  
  551.     /*
  552.      *  If the function exists, we need to check the argument types
  553.      *  passed in by the user.  If they don't match, then we need to
  554.      *  check the user's arg types against superclasses of the arguments
  555.      *  to this function.
  556.      */
  557.  
  558.     pform = (Form_pg_proc)GETSTRUCT(ftup);
  559.     if (pform->pronargs != nargs) {
  560.     elog(NOTICE, "argument count mismatch: %s takes %d, %d supplied",
  561.              funcname, pform->pronargs, nargs);
  562.     return (false);
  563.     }
  564.  
  565.     /* typecheck arguments */
  566.     fargs = pform->proargtypes.data;
  567.     if (*fargs != InvalidObjectId && *oid_array != InvalidObjectId) {
  568.     if (bcmp(fargs, oid_array, 8 * sizeof(ObjectId)) != 0) {
  569.         oid_vector = argtype_inherit(nargs, oid_array);
  570.         while (**oid_vector != InvalidObjectId) {
  571.         oid_array = *oid_vector++;
  572.         if (bcmp(fargs, oid_array, 8 * sizeof(ObjectId)) == 0)
  573.             goto okay;
  574.         }
  575.         if (**oid_vector == InvalidObjectId)
  576.         elog(NOTICE, "type mismatch in invocation of function %s",
  577.                  funcname);
  578.         return (false);
  579.     }
  580.     }
  581.  
  582. okay:
  583.     /* by here, we have a match */
  584.     *funcid = ftup->t_oid;
  585.     *rettype = (ObjectId) pform->prorettype;
  586.     *retset = (ObjectId) pform->proretset;
  587.  
  588.     return (true);
  589. }
  590.  
  591. /*
  592.  *  argtype_inherit() -- Construct an argtype vector reflecting the
  593.  *             inheritance properties of the supplied argv.
  594.  *
  595.  *    This function is used to disambiguate among functions with the
  596.  *    same name but different signatures.  It takes an array of eight
  597.  *    type ids.  For each type id in the array that's a complex type
  598.  *    (a class), it walks up the inheritance tree, finding all
  599.  *    superclasses of that type.  A vector of new ObjectId type arrays
  600.  *    is returned to the caller, reflecting the structure of the
  601.  *    inheritance tree above the supplied arguments.
  602.  *
  603.  *    The order of this vector is as follows:  all superclasses of the
  604.  *    rightmost complex class are explored first.  The exploration
  605.  *    continues from right to left.  This policy means that we favor
  606.  *    keeping the leftmost argument type as low in the inheritance tree
  607.  *    as possible.  This is intentional; it is exactly what we need to
  608.  *    do for method dispatch.  The last type array we return is all
  609.  *    zeroes.  This will match any functions for which return types are
  610.  *    not defined.  There are lots of these (mostly builtins) in the
  611.  *    catalogs.
  612.  */
  613.  
  614. ObjectId **
  615. argtype_inherit(nargs, oid_array)
  616.     int nargs;
  617.     ObjectId *oid_array;
  618. {
  619.     ObjectId relid;
  620.     int i;
  621.     InhPaths arginh[MAXFARGS];
  622.  
  623.     for (i = 0; i < MAXFARGS; i++) {
  624.     if (i < nargs) {
  625.         arginh[i].self = oid_array[i];
  626.         if ((relid = typeid_get_relid(oid_array[i])) != InvalidObjectId) {
  627.         arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
  628.         } else {
  629.         arginh[i].nsupers = 0;
  630.         arginh[i].supervec = (ObjectId *) NULL;
  631.         }
  632.     } else {
  633.         arginh[i].self = InvalidObjectId;
  634.         arginh[i].nsupers = 0;
  635.         arginh[i].supervec = (ObjectId *) NULL;
  636.     }
  637.     }
  638.  
  639.     /* return an ordered cross-product of the classes involved */
  640.     return (genxprod(arginh));
  641. }
  642.  
  643. typedef struct _SuperQE {
  644.     SLNode    sqe_node;
  645.     ObjectId    sqe_relid;
  646. } SuperQE;
  647.  
  648. int
  649. findsupers(relid, supervec)
  650.     ObjectId relid;
  651.     ObjectId **supervec;
  652. {
  653.     ObjectId *relidvec;
  654.     Relation inhrel;
  655.     HeapScanDesc inhscan;
  656.     ScanKeyData skey;
  657.     HeapTuple inhtup;
  658.     TupleDescriptor inhtupdesc;
  659.     int nvisited;
  660.     SuperQE *qentry, *vnode;
  661.     SLList visited, queue;
  662.     Relation rd;
  663.     Buffer buf;
  664.     Datum d;
  665.     bool newrelid;
  666.     char isNull;
  667.  
  668.     nvisited = 0;
  669.     SLNewList(&queue, 0);
  670.     SLNewList(&visited, 0);
  671.  
  672.     inhrel = heap_openr(Name_pg_inherits);
  673.     RelationSetLockForRead(inhrel);
  674.     inhtupdesc = RelationGetTupleDescriptor(inhrel);
  675.  
  676.     /*
  677.      *  Use queue to do a breadth-first traversal of the inheritance
  678.      *  graph from the relid supplied up to the root.
  679.      */
  680.     do {
  681.     ScanKeyEntryInitialize(&skey.data[0], 0x0, Anum_pg_inherits_inhrel,
  682.                    ObjectIdEqualRegProcedure,
  683.                    ObjectIdGetDatum(relid));
  684.  
  685.     inhscan = heap_beginscan(inhrel, 0, NowTimeQual, 1, &skey);
  686.  
  687.     while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf))) {
  688.         qentry = (SuperQE *) palloc(sizeof(SuperQE));
  689.  
  690.         d = (Datum) fastgetattr(inhtup, Anum_pg_inherits_inhparent,
  691.                     inhtupdesc, &isNull);
  692.         qentry->sqe_relid = DatumGetObjectId(d);
  693.  
  694.         /* put this one on the queue */
  695.         SLNewNode(&(qentry->sqe_node));
  696.         SLAddTail(&queue, &(qentry->sqe_node));
  697.  
  698.         ReleaseBuffer(buf);
  699.     }
  700.  
  701.     heap_endscan(inhscan);
  702.  
  703.     /* pull next unvisited relid off the queue */
  704.     do {
  705.         qentry = (SuperQE *) SLRemHead(&queue);
  706.         if (qentry == (SuperQE *) NULL)
  707.         break;
  708.  
  709.         relid = qentry->sqe_relid;
  710.         newrelid = true;
  711.  
  712.         for (vnode = (SuperQE *) SLGetHead(&visited);
  713.          vnode != (SuperQE *) NULL;
  714.          vnode = (SuperQE *) SLGetSucc(&(vnode->sqe_node))) {
  715.         if (qentry->sqe_relid == vnode->sqe_relid) {
  716.             newrelid = false;
  717.             break;
  718.         }
  719.         }
  720.     } while (!newrelid);
  721.  
  722.     if (qentry != (SuperQE *) NULL) {
  723.  
  724.         /* save the type id, rather than the relation id */
  725.         if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
  726.         elog(WARN, "relid %d does not exist", qentry->sqe_relid);
  727.         qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)));
  728.         heap_close(rd);
  729.  
  730.         SLAddTail(&visited, &(qentry->sqe_node));
  731.         nvisited++;
  732.     }
  733.     } while (qentry != (SuperQE *) NULL);
  734.  
  735.     RelationUnsetLockForRead(inhrel);
  736.     heap_close(inhrel);
  737.  
  738.     if (nvisited > 0) {
  739.     relidvec = (ObjectId *) palloc(nvisited * sizeof(ObjectId));
  740.     *supervec = relidvec;
  741.     for (vnode = (SuperQE *) SLGetHead(&visited);
  742.          vnode != (SuperQE *) NULL;
  743.          vnode = (SuperQE *) SLGetSucc(&(vnode->sqe_node))) {
  744.         *relidvec++ = vnode->sqe_relid;
  745.     }
  746.     } else {
  747.     *supervec = (ObjectId *) NULL;
  748.     }
  749.  
  750.     return (nvisited);
  751. }
  752.  
  753. ObjectId **
  754. genxprod(arginh)
  755.     InhPaths *arginh;
  756. {
  757.     int nanswers;
  758.     ObjectId **result, **iter;
  759.     ObjectId *oneres;
  760.     int i, j;
  761.     int cur[MAXFARGS];
  762.  
  763.     nanswers = 1;
  764.     for (i = 0; i < MAXFARGS; i++) {
  765.     nanswers *= (arginh[i].nsupers + 1);
  766.     cur[i] = 0;
  767.     }
  768.  
  769.     iter = result = (ObjectId **) palloc(sizeof(ObjectId *) * nanswers);
  770.  
  771.     /* compute the cross product from right to left */
  772.     for (;;) {
  773.     oneres = (ObjectId *) palloc(MAXFARGS * sizeof(ObjectId));
  774.  
  775.     for (i = MAXFARGS - 1; i >= 0 && cur[i] == arginh[i].nsupers; i--)
  776.         continue;
  777.  
  778.     /* if we're done, do wildcard vector and return */
  779.     if (i < 0) {
  780.         bzero(oneres, MAXFARGS * sizeof(ObjectId));
  781.         *iter = oneres;
  782.         return (result);
  783.     }
  784.  
  785.     /* no, increment this column and zero the ones after it */
  786.     cur[i] = cur[i] + 1;
  787.     for (j = MAXFARGS - 1; j > i; j--)
  788.         cur[j] = 0;
  789.  
  790.     for (i = 0; i < MAXFARGS; i++) {
  791.         if (cur[i] == 0)
  792.         oneres[i] = arginh[i].self;
  793.         else
  794.         oneres[i] = arginh[i].supervec[cur[i] - 1];
  795.     }
  796.  
  797.     *iter++ = oneres;
  798.     }
  799.     /* NOTREACHED */
  800. }
  801.  
  802. ObjectId *
  803. funcid_get_funcargtypes ( funcid )
  804.      ObjectId funcid;
  805. {
  806.     HeapTuple func_tuple = NULL;
  807.     ObjectId *oid_array = NULL;
  808.     struct proc *foo;
  809.     func_tuple = SearchSysCacheTuple(PROOID,funcid,0,0,0);
  810.  
  811.     if ( !HeapTupleIsValid ( func_tuple )) 
  812.     elog (WARN, "function %d does not exist", funcid);
  813.     
  814.     foo = (struct proc *)GETSTRUCT(func_tuple);
  815.     oid_array = foo->proargtypes.data;
  816.     return (oid_array);
  817. }
  818.  
  819. /* Given a type id, returns the in-conversion function of the type */
  820. OID
  821. typeid_get_retinfunc(type_id)
  822.         int type_id;
  823. {
  824.         HeapTuple     typeTuple;
  825.         TypeTupleForm   type;
  826.         OID             infunc;
  827.         typeTuple = SearchSysCacheTuple(TYPOID, (char *) type_id,
  828.                   (char *) NULL, (char *) NULL, (char *) NULL);
  829.     if ( !HeapTupleIsValid ( typeTuple ))
  830.         elog(WARN,
  831.          "typeid_get_retinfunc: Invalid type - oid = %d",
  832.          type_id);
  833.  
  834.         type = (TypeTupleForm) GETSTRUCT(typeTuple);
  835.         infunc = type->typinput;
  836.         return(infunc);
  837. }
  838.  
  839. OID
  840. typeid_get_relid(type_id)
  841.         int type_id;
  842. {
  843.         HeapTuple     typeTuple;
  844.         TypeTupleForm   type;
  845.         OID             infunc;
  846.         typeTuple = SearchSysCacheTuple(TYPOID, (char *) type_id,
  847.                   (char *) NULL, (char *) NULL, (char *) NULL);
  848.     if ( !HeapTupleIsValid ( typeTuple ))
  849.         elog(WARN, "typeid_get_relid: Invalid type - oid = %d ", type_id);
  850.  
  851.         type = (TypeTupleForm) GETSTRUCT(typeTuple);
  852.         infunc = type->typrelid;
  853.         return(infunc);
  854. }
  855.  
  856. OID
  857. get_typrelid(typ)
  858.     TypeTupleForm typ;
  859. {
  860.     Form_pg_type typtup;
  861.  
  862.     typtup = (Form_pg_type) GETSTRUCT(typ);
  863.  
  864.     return (typtup->typrelid);
  865. }
  866.  
  867. OID
  868. get_typelem(type_id)
  869.  
  870. OID type_id;
  871.  
  872. {
  873.     HeapTuple     typeTuple;
  874.     TypeTupleForm   type;
  875.  
  876.     if (!(typeTuple = SearchSysCacheTuple(TYPOID, type_id, NULL, NULL, NULL))) {
  877.         elog (WARN , "type name lookup of %d failed", type_id);
  878.     }
  879.     type = (TypeTupleForm) GETSTRUCT(typeTuple);
  880.  
  881.     return (type->typelem);
  882. }
  883.  
  884. char
  885. FindDelimiter(typename)
  886. char *typename;
  887. {
  888.     char delim;
  889.     HeapTuple     typeTuple;
  890.     TypeTupleForm   type;
  891.  
  892.  
  893.     if (!(typeTuple = SearchSysCacheTuple(TYPNAME, typename))) {
  894.         elog (WARN , "type name lookup of %s failed", typename);
  895.     }
  896.     type = (TypeTupleForm) GETSTRUCT(typeTuple);
  897.  
  898.     delim = type->typdelim;
  899.     return (delim);
  900. }
  901.  
  902. /*
  903.  * Give a somewhat useful error message when the operator for two types
  904.  * is not found.
  905.  */
  906.  
  907. op_error(op, arg1, arg2)
  908.  
  909. char *op;
  910. int arg1, arg2;
  911.  
  912. {
  913.     Type tp, get_id_type();
  914.     char p1[16], p2[16];
  915.  
  916.     tp = get_id_type(arg1);
  917.     strncpy(p1, tname(tp), 16);
  918.  
  919.     tp = get_id_type(arg2);
  920.     strncpy(p2, tname(tp), 16);
  921.  
  922.     elog(NOTICE, "there is no operator %s for types %s and %s", op, p1, p2);
  923.     elog(NOTICE, "You will either have to retype this query using an");
  924.     elog(NOTICE, "explicit cast, or you will have to define the operator");
  925.     elog(WARN, "%s for %s and %s using DEFINE OPERATOR", op, p1, p2);
  926. }
  927.