home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / commands / define.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  19.2 KB  |  695 lines

  1. /* ----------------------------------------------------------------
  2.  * define.c --
  3.  *    POSTGRES define (function | type | operator) utility code.
  4.  *
  5.  * NOTES:
  6.  *    These things must be defined and committed in the following order:
  7.  *        input/output, recv/send procedures
  8.  *        type
  9.  *        operators
  10.  * ----------------------------------------------------------------
  11.  */
  12.  
  13. #include <strings.h>    /* XXX style */
  14. #include <ctype.h>
  15. #include <math.h>
  16.  
  17. #include "tmp/postgres.h"
  18.  
  19. RcsId("$Header: /private/postgres/src/commands/RCS/define.c,v 1.52 1992/08/19 19:37:41 mer Exp $");
  20.  
  21. #include "access/ftup.h"
  22. #include "access/heapam.h"
  23. #include "access/htup.h"
  24. #include "access/tqual.h"
  25. #include "catalog/catname.h"
  26. #include "catalog/syscache.h"
  27. #include "manip.h"
  28. #include "nodes/pg_lisp.h"
  29. #include "parser/parse.h"    /* for ARG */
  30. #include "utils/fmgr.h"        /* for fmgr */
  31. #include "utils/builtins.h"    /* prototype for textin() */
  32. #include "utils/log.h"
  33.  
  34. #include "commands/defrem.h"
  35. #include "planner/xfunc.h"
  36.  
  37. #include "tcop/dest.h"
  38.  
  39. /* ----------------
  40.  *    external functions
  41.  * ----------------
  42.  */
  43. extern    ObjectId TypeDefine();
  44. extern    void     ProcedureDefine();
  45. extern    void     OperatorDefine();
  46. extern  void     AggregateDefine();
  47.  
  48. /* ----------------
  49.  *    this is used by the DefineXXX functions below.
  50.  * ----------------
  51.  */
  52. extern
  53. String        /* XXX Datum */
  54. FetchDefault ARGS((
  55.     String    string,
  56.     String    standard
  57. ));
  58.  
  59. /* ----------------------------------------------------------------
  60.  *        Define Function / Operator / Type
  61.  * ----------------------------------------------------------------
  62.  */
  63.  
  64. /* --------------------------------
  65.  *    DefineFunction
  66.  * --------------------------------
  67.  */
  68. void
  69. DefineFunction(nameargsexe, dest)
  70.     LispValue    nameargsexe;
  71.     CommandDest dest;
  72. {
  73.     Name    name = (Name) CString(CAR(CAR(nameargsexe)));
  74.     LispValue   parameters = CDR(CAR(nameargsexe));
  75.     LispValue    entry;
  76.     String    languageName, fileName, sourceCode;
  77.     char        *c;
  78.     String    returnTypeName;
  79.     char        blankstring[2];
  80.     bool    canCache;
  81.     bool        trusted = true;
  82.     String      trusted_str;
  83.     LispValue    argList;
  84.     int32       byte_pct, perbyte_cpu, percall_cpu, outin_ratio;
  85.     String      perbyte_str, percall_str;
  86.     int         count;
  87.     char        *ptr;
  88.     bool    returnsSet;
  89.  
  90.     /* ----------------
  91.      * Note:
  92.      * XXX    Checking of "name" validity (16 characters?) is needed.
  93.      * ----------------
  94.      */
  95.     AssertArg(NameIsValid(name));
  96.  
  97.     /* figure out the language */
  98.     entry = DefineListRemoveRequiredAssignment(¶meters, "language");
  99.     languageName = DefineEntryGetString(entry);
  100.     /* lowercase-ise the language */
  101.     for (c = languageName; *c != '\0'; c++)
  102.       *c = tolower(*c);
  103.  
  104.     if (!strcmp(languageName, "postquel") && !strcmp(languageName, "c"))
  105.       elog(WARN, "DefineFunction: Specified language not supported");    
  106.  
  107.     /* ----------------
  108.      * handle "returntype = X".  The function could return a singleton
  109.      * value or a set of values.  Figure out which.
  110.      * ----------------
  111.      */
  112.     entry = DefineListRemoveRequiredAssignment(¶meters, "returntype");
  113.     if (IsA(CADR(entry),LispList)) {
  114.     returnTypeName = LISPVALUE_STRING(CDR(CADR(entry)));
  115.     returnsSet = true;
  116.     } else {
  117.     returnTypeName = CString(CADR(entry));
  118.     returnsSet = false;
  119.     }
  120.  
  121.     /* Next attributes only definable for C functions */
  122.     if (!strcmp(languageName, "c"))
  123.      {
  124.      /* ----------------
  125.       * handle "[ iscachable ]": figure out if Postquel functions are
  126.       * cacheable automagically?
  127.       * ----------------
  128.       */
  129.  
  130.      entry = DefineListRemoveOptionalIndicator(¶meters, "iscachable");
  131.      canCache = (bool)!null(entry);
  132.     
  133.      /*
  134.       * handle trusted/untrusted.  defaults to trusted for now; when
  135.       * i finish real support it'll default untrusted.  -dpassage
  136.       */
  137.  
  138.      entry = DefineListRemoveOptionalAssignment(¶meters, "trusted");
  139.      if (null(entry)) 
  140.          trusted = true;
  141.      else 
  142.          trusted = ((DefineEntryGetString(entry)[0]) == 't');
  143.  
  144.      /*
  145.       ** handle expensive function parameters
  146.       */
  147.      entry = DefineListRemoveOptionalAssignment(¶meters, "byte_pct");
  148.      if (null(entry)) byte_pct = BYTE_PCT;
  149.      else byte_pct = DefineEntryGetInteger(entry);
  150.  
  151.      entry = DefineListRemoveOptionalAssignment(¶meters, "perbyte_cpu");
  152.      if (null(entry)) perbyte_cpu = PERBYTE_CPU;
  153.      else 
  154.       {
  155.           perbyte_str = DefineEntryGetString(entry);
  156.           if (!sscanf(perbyte_str, "%d", &perbyte_cpu))
  157.            {
  158.            for (count = 0, ptr = perbyte_str; *ptr != '\0'; ptr++)
  159.              if (*ptr == '!') count++;
  160.            perbyte_cpu = (int) pow(10.0, (double)count);
  161.            }
  162.       }
  163.  
  164.      entry = DefineListRemoveOptionalAssignment(¶meters, "percall_cpu");
  165.      if (null(entry)) percall_cpu = PERCALL_CPU;
  166.      else 
  167.       {
  168.           percall_str = DefineEntryGetString(entry);
  169.           if (!sscanf(percall_str, "%d", &percall_cpu))
  170.            {
  171.            for (count = 0, ptr = percall_str; *ptr != '\0'; ptr++)
  172.              if (*ptr == '!') count++;
  173.            percall_cpu = (int) pow(10.0, (double)count);
  174.            }
  175.       }
  176.  
  177.  
  178.      entry = DefineListRemoveOptionalAssignment(¶meters, "outin_ratio");
  179.      if (null(entry)) outin_ratio = OUTIN_RATIO;
  180.      else outin_ratio = DefineEntryGetInteger(entry);
  181.  
  182.      }
  183.     else
  184.      {
  185.      /* postquel function */
  186.      canCache = false;
  187.  
  188.      /* query optimizer groks postquel, these are meaningless */
  189.      perbyte_cpu = percall_cpu = 0;
  190.      byte_pct = outin_ratio = 100;
  191.      }
  192.  
  193.     /* ----------------
  194.      * handle "[ arg is (...) ]"
  195.      * XXX fix optional arg handling below
  196.      * ----------------
  197.      */
  198.     argList = LispRemoveMatchingSymbol(¶meters, ARG);
  199.      
  200.     if (!null(argList)) {
  201.     LispValue    rest;
  202.          
  203.     /*
  204.      * first discard symbol 'arg from list
  205.      */
  206.     argList = CDR(argList);
  207.     AssertArg(length(argList) > 0);
  208.          
  209.     foreach (rest, argList) {
  210.         if (!lispStringp(CAR(rest))) {
  211.         elog(WARN, "DefineFunction: arg type = ?");
  212.         }
  213.     }
  214.     }
  215.      
  216.     /* ----------------
  217.      *    there should be nothing more
  218.      * ----------------
  219.      */
  220.     DefineListAssertEmpty(parameters);
  221.      
  222.  
  223.     /* set up the sourcecode and filename strings */
  224.     blankstring[0] = '-';
  225.     blankstring[1] = '\0';
  226.     if (!strcmp(languageName, "c"))
  227.      {
  228.      sourceCode = blankstring;
  229.      fileName = CString(CADR(nameargsexe));
  230.      }
  231.     else
  232.      {
  233.      sourceCode = CString(CADR(nameargsexe));
  234.      fileName = blankstring;
  235.      }
  236.  
  237.     /* C is stored uppercase in pg_language */
  238.     if (!strcmp(languageName, "c"))
  239.       *languageName = 'C';
  240.  
  241.     /* ----------------
  242.      *    now have ProcedureDefine do all the work..
  243.      * ----------------
  244.      */
  245.     ProcedureDefine(name,
  246.             returnsSet,
  247.             returnTypeName,
  248.             languageName,
  249.             sourceCode,
  250.             fileName,
  251.             canCache,
  252.             trusted,
  253.             byte_pct, perbyte_cpu, percall_cpu, 
  254.             outin_ratio,
  255.             argList,
  256.             dest);
  257. }
  258.  
  259. /* --------------------------------
  260.  *    DefineOperator
  261.  *
  262.  *    this function extracts all the information from the
  263.  *    parameter list generated by the parser and then has
  264.  *    OperatorDefine() do all the actual work.
  265.  * --------------------------------
  266.  */
  267. void
  268. DefineOperator(name, parameters)
  269.     Name    name;
  270.     LispValue    parameters;
  271. {
  272.     LispValue    entry;
  273.     Name     functionName;         /* function for operator */
  274.     Name     typeName1;         /* first type name */
  275.     Name     typeName2;         /* optional second type name */
  276.     uint16     precedence;         /* operator precedence */
  277.     bool    canHash;         /* operator hashes */
  278.     bool    isLeftAssociative;     /* operator is left associative */
  279.     Name     commutatorName;         /* optional commutator operator name */
  280.     Name     negatorName;         /* optional negator operator name */
  281.     Name     restrictionName;    /* optional restrict. sel. procedure */
  282.     Name     joinName;         /* optional join sel. procedure name */
  283.     Name     sortName1;         /* optional first sort operator */
  284.     Name     sortName2;         /* optional second sort operator */
  285.     NameData    oprName;        /* operator name */
  286.     
  287.     /* ----------------
  288.      *    sanity checks
  289.      *
  290.      * XXX    Checking of operator "name" validity
  291.      *        (16 characters?) is needed.
  292.      * ----------------
  293.      */
  294.     AssertArg(NameIsValid(name));
  295.     AssertArg(listp(parameters));
  296.  
  297.     bzero(&oprName, sizeof(NameData));
  298.     strncpy(&(oprName.data[0]), name, 16);
  299.     /* ----------------
  300.      * handle "arg1 = typname"
  301.      *    
  302.      * XXX ( ... arg1 = typname [ , arg2 = typname ] ... )
  303.      * XXX is undocumented in the reference manual source as of 89/8/22.
  304.      * ----------------
  305.      */
  306.     entry = DefineListRemoveRequiredAssignment(¶meters, "arg1");
  307.     typeName1 = DefineEntryGetName(entry);
  308.     
  309.     /* ----------------
  310.      * handle "[ arg2 = typname ]"
  311.      * ----------------
  312.      */
  313.     entry = DefineListRemoveOptionalAssignment(¶meters, "arg2");
  314.     typeName2 = NULL;
  315.     if (!null(entry)) {
  316.     typeName2 = DefineEntryGetName(entry);
  317.     }
  318.     
  319.     /* ----------------
  320.      * handle "procedure = proname"
  321.      * ----------------
  322.      */
  323.     entry = DefineListRemoveRequiredAssignment(¶meters, "procedure");
  324.     functionName = DefineEntryGetName(entry);
  325.     
  326.     /* ----------------
  327.      * handle "[ precedence = number ]"
  328.      * ----------------
  329.      */
  330.     entry = DefineListRemoveOptionalAssignment(¶meters, "precedence");
  331.     if (null(entry)) {
  332.     precedence = 0;        /* FetchDefault? */
  333.     } else {
  334.     precedence = DefineEntryGetInteger(entry);
  335.     }
  336.     
  337.     /* ----------------
  338.      * handle "[ associativity = (left|right|none|any) ]"
  339.      *    
  340.      * XXX Associativity code below must be fixed when the catalogs and
  341.      * XXX the planner/executor support proper associativity semantics.
  342.      * ----------------
  343.      */
  344.     entry = DefineListRemoveOptionalAssignment(¶meters, "associativity");
  345.     if (null(entry)) {
  346.     isLeftAssociative = true;    /* XXX FetchDefault */
  347.     } else {
  348.     String    string;
  349.     
  350.     string = DefineEntryGetString(entry);
  351.     if (StringEquals(string, "right")) {
  352.         isLeftAssociative = false;
  353.     } else if (!StringEquals(string, "left") &&
  354.            !StringEquals(string, "none") &&
  355.            !StringEquals(string, "any")) {
  356.         elog(WARN, "Define: precedence = what?");
  357.     } else {
  358.         isLeftAssociative = true;
  359.     }
  360.     }
  361.     
  362.     /* ----------------
  363.      * handle "[ commutator = oprname ]"
  364.      * ----------------
  365.      */
  366.     entry = DefineListRemoveOptionalAssignment(¶meters, "commutator");
  367.     commutatorName = NULL;
  368.     if (!null(entry)) {
  369.     commutatorName = DefineEntryGetName(entry);
  370.     }
  371.     
  372.     /* ----------------
  373.      * handle "[ negator = oprname ]"
  374.      * ----------------
  375.      */
  376.     entry = DefineListRemoveOptionalAssignment(¶meters, "negator");
  377.     negatorName = NULL;
  378.     if (!null(entry)) {
  379.     negatorName = DefineEntryGetName(entry);
  380.     }
  381.     
  382.     /* ----------------
  383.      * handle "[ restrict = proname ]"
  384.      * ----------------
  385.      */
  386.     entry = DefineListRemoveOptionalAssignment(¶meters, "restrict");
  387.     restrictionName = NULL;
  388.     if (!null(entry)) {
  389.     restrictionName = DefineEntryGetName(entry);
  390.     }
  391.     
  392.     /* ----------------
  393.      * handle "[ join = proname ]"
  394.      * ----------------
  395.      */
  396.     entry = DefineListRemoveOptionalAssignment(¶meters, "join");
  397.     joinName = NULL;
  398.     if (!null(entry)) {
  399.     joinName = DefineEntryGetName(entry);
  400.     }
  401.     
  402.     /* ----------------
  403.      * handle "[ hashes ]"
  404.      * ----------------
  405.      */
  406.     entry = DefineListRemoveOptionalIndicator(¶meters, "hashes");
  407.     canHash = (bool)!null(entry);
  408.     
  409.     /* ----------------
  410.      * handle "[ sort1 = oprname ]"
  411.      *    
  412.      * XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... )
  413.      * XXX is undocumented in the reference manual source as of 89/8/22.
  414.      * ----------------
  415.      */
  416.     entry = DefineListRemoveOptionalAssignment(¶meters, "sort1");
  417.     sortName1 = NULL;
  418.     if (!null(entry)) {
  419.     sortName1 = DefineEntryGetName(entry);
  420.     }
  421.     
  422.     /* ----------------
  423.      * handle "[ sort2 = oprname ]"
  424.      * ----------------
  425.      */
  426.     entry = DefineListRemoveOptionalAssignment(¶meters, "sort2");
  427.     sortName2 = NULL;
  428.     if (!null(entry)) {
  429.     sortName2 = DefineEntryGetName(entry);
  430.     }
  431.  
  432.     /* ----------------
  433.      *    there should be nothing more..
  434.      * ----------------
  435.      */
  436.     DefineListAssertEmpty(parameters);
  437.  
  438.     /* ----------------
  439.      *    now have OperatorDefine do all the work..
  440.      * ----------------
  441.      */
  442.     OperatorDefine(&oprName,        /* operator name */
  443.            typeName1,        /* first type name */
  444.            typeName2,        /* optional second type name */
  445.            functionName,    /* function for operator */
  446.            precedence,        /* operator precedence */
  447.            isLeftAssociative,    /* operator is left associative */
  448.            commutatorName,    /* optional commutator operator name */
  449.            negatorName,        /* optional negator operator name */
  450.            restrictionName,    /* optional restrict. sel. procedure */
  451.            joinName,        /* optional join sel. procedure name */
  452.            canHash,        /* operator hashes */
  453.            sortName1,        /* optional first sort operator */
  454.            sortName2);        /* optional second sort operator */
  455. }
  456.  
  457. /* -------------------
  458.  *  DefineAggregate
  459.  * ------------------
  460.  */
  461. void
  462. DefineAggregate(name, parameters)
  463.     Name name;
  464.     LispValue parameters;
  465. {
  466.     Name   stepfunc1Name, stepfunc2Name, finalfuncName;
  467.     String primStr, secStr;
  468.     struct varlena *primVal, *secVal;
  469.     LispValue entry;
  470.  
  471.   /* sanity checks...name validity */
  472.  
  473.   AssertArg(NameIsValid(name));
  474.   AssertArg(listp(parameters));
  475.  
  476.   /* handle "stepfunc = proname" */
  477.   entry = DefineListRemoveRequiredAssignment(¶meters, "sfunc1");
  478.   stepfunc1Name = DefineEntryGetName(entry);
  479.    
  480.    /* handle "countfunc = proname " */
  481.   entry = DefineListRemoveRequiredAssignment(¶meters, "sfunc2");
  482.   stepfunc2Name = DefineEntryGetName(entry);
  483.  
  484.   /* handle "finalfunc = proname */
  485.   entry = DefineListRemoveRequiredAssignment(¶meters, "finalfunc");
  486.   finalfuncName = DefineEntryGetName(entry);
  487.  
  488.   /* -----------------
  489.    * handle first initial condition
  490.    */
  491.   entry = DefineListRemoveRequiredAssignment(¶meters, "initcond1");
  492.   primStr = DefineEntryGetString(entry);
  493.   primVal = textin(primStr);
  494.  
  495.   /* -------------------
  496.    * handle second initial condition
  497.    */
  498.   entry = DefineListRemoveRequiredAssignment(¶meters, "initcond2");
  499.   secStr = DefineEntryGetString(entry);
  500.   secVal = textin(secStr);
  501.  
  502.   DefineListAssertEmpty(parameters);
  503.  
  504.   AggregateDefine(name,          /* aggregate name */
  505.           stepfunc1Name,    /* first step function name */
  506.           stepfunc2Name,    /* second step function name */
  507.           finalfuncName,    /* final function name */
  508.           primVal,    /* first initial condition */
  509.           secVal);    /* second initial condition */
  510. }
  511.  
  512. /* --------------------------------
  513.  *    DefineType
  514.  * --------------------------------
  515.  */
  516. void
  517. DefineType(name, parameters)
  518.     Name    name;
  519.     LispValue    parameters;
  520. {
  521.     LispValue    entry;
  522.     int16    internalLength;        /* int2 */
  523.     int16    externalLength;        /* int2 */
  524.     Name    elemName;
  525.     Name    inputName;
  526.     Name    outputName;
  527.     Name    sendName;
  528.     Name    receiveName;
  529.     char*    defaultValue;        /* Datum */
  530.     bool    byValue;        /* Boolean */
  531.     char    delimiter;
  532.     char    shadow_type[16];
  533.     
  534.     /* ----------------
  535.      *    sanity checks
  536.      *
  537.      * XXX    Checking of operator "name" validity
  538.      *        (16 characters?) is needed.
  539.      * ----------------
  540.      */
  541.     AssertArg(NameIsValid(name));
  542.     AssertArg(listp(parameters));
  543.  
  544.     /*
  545.      * Type names can only be 15 characters long, so that the shadow type
  546.      * can be created using the 16th character as necessary.
  547.      */
  548.  
  549.     if (strlen(name) > 15)
  550.     {
  551.     elog(WARN, "DefineType: Names can only be 15 characters long or less");
  552.     }
  553.     
  554.     /* ----------------
  555.      * handle "internallength = (number | variable)"
  556.      * ----------------
  557.      */
  558.     entry = DefineListRemoveRequiredAssignment(¶meters,
  559.                            "internallength");
  560.     internalLength = DefineEntryGetLength(entry);
  561.  
  562.     /* ----------------
  563.      * handle "[ externallength = (number | variable) ]"
  564.      * ----------------
  565.      */
  566.     entry = DefineListRemoveOptionalAssignment(¶meters,
  567.                            "externallength");
  568.     externalLength = 0;        /* FetchDefault? */
  569.     if (!null(entry)) {
  570.     externalLength = DefineEntryGetLength(entry);
  571.     }
  572.     
  573.     /* ----------------
  574.      * handle "input = procedure"
  575.      * ----------------
  576.      */
  577.     entry = DefineListRemoveRequiredAssignment(¶meters, "input");
  578.     inputName = DefineEntryGetName(entry);
  579.     
  580.     /* ----------------
  581.      * handle "output = procedure"
  582.      * ----------------
  583.      */
  584.     entry = DefineListRemoveRequiredAssignment(¶meters, "output");
  585.     outputName = DefineEntryGetName(entry);
  586.     
  587.     /* ----------------
  588.      * handle "[ send = procedure ]"
  589.      * ----------------
  590.      */
  591.     entry = DefineListRemoveOptionalAssignment(¶meters, "send");
  592.     sendName = NULL;
  593.     if (!null(entry)) {
  594.     sendName = DefineEntryGetName(entry);
  595.     }
  596.     
  597.  
  598.     /*
  599.      * ----------------
  600.      * handle "[ delimiter = delim]"
  601.      * ----------------
  602.      */
  603.  
  604.     entry = DefineListRemoveOptionalAssignment(¶meters, "delimiter");
  605.     delimiter = ',';
  606.     if (!null(entry)) {
  607.     char *p = (char *) DefineEntryGetName(entry);
  608.     delimiter = p[0];
  609.     }
  610.  
  611.     /* ----------------
  612.      * handle "[ receive = procedure ]"
  613.      * ----------------
  614.      */
  615.     entry = DefineListRemoveOptionalAssignment(¶meters, "receive");
  616.     receiveName = NULL;
  617.     if (!null(entry)) {
  618.     receiveName = DefineEntryGetName(entry);
  619.     }
  620.     
  621.     /*
  622.      * ----------------
  623.      * handle "[ element = type]"
  624.      * ----------------
  625.      */
  626.  
  627.     entry = DefineListRemoveOptionalAssignment(¶meters, "element");
  628.     elemName = NULL;
  629.     if (!null(entry)) {
  630.     elemName = DefineEntryGetName(entry);
  631.     }
  632.  
  633.     /* ----------------
  634.      * handle "[ default = `...' ]"
  635.      * ----------------
  636.      */
  637.     entry = DefineListRemoveOptionalAssignment(¶meters, "default");
  638.     defaultValue = NULL;
  639.     if (!null(entry)) {
  640.     defaultValue = DefineEntryGetString(entry);
  641.     }
  642.     
  643.     /* ----------------
  644.      * handle "[ passedbyvalue ]"
  645.      * ----------------
  646.      */
  647.     entry = DefineListRemoveOptionalIndicator(¶meters, "passedbyvalue");
  648.     byValue = (bool)!null(entry);
  649.     
  650.     /* ----------------
  651.      *    there should be nothing more..
  652.      * ----------------
  653.      */
  654.     DefineListAssertEmpty(parameters);
  655.  
  656.     /* ----------------
  657.      *    now have TypeDefine do all the real work.
  658.      * ----------------
  659.      */
  660.     (void) TypeDefine(name,        /* type name */
  661.               InvalidObjectId,  /* relation oid (n/a here) */
  662.               internalLength,    /* internal size */
  663.               externalLength,    /* external size */
  664.               'b',        /* type-type (base type) */
  665.               delimiter,    /* array element delimiter */
  666.               inputName,    /* input procedure */
  667.               outputName,    /* output procedure */
  668.               sendName,        /* send procedure */
  669.               receiveName,    /* recieve procedure */
  670.               elemName,        /* element type name */
  671.               defaultValue,    /* default type value */
  672.               byValue);        /* passed by value */
  673.     /*
  674.      * ----------------
  675.      *  When we create a true type (as opposed to a complex type)
  676.      *  we need to have an shadow array entry for it in pg type as well.
  677.      * ----------------
  678.      */
  679.     sprintf(shadow_type, "_%s", name);
  680.  
  681.     (void) TypeDefine(shadow_type,        /* type name */
  682.               InvalidObjectId,  /* relation oid (n/a here) */
  683.               -1,        /* internal size */
  684.               -1,        /* external size */
  685.               'b',        /* type-type (base type) */
  686.               ',',        /* array element delimiter */
  687.               "array_in",    /* input procedure */
  688.               "array_out",    /* output procedure */
  689.               "array_out",    /* send procedure */
  690.               "array_in",    /* recieve procedure */
  691.               name,         /* element type name */
  692.               defaultValue,    /* default type value */
  693.               false);        /* never passed by value */
  694. }
  695.