home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / parser / gram.y < prev    next >
Encoding:
Lex Description  |  1993-05-02  |  52.5 KB  |  2,191 lines

  1. %{
  2. #define YYDEBUG 1
  3. /**********************************************************************
  4.  
  5.   $Header: /private/postgres/src/parser/RCS/gram.y,v 4.16 1992/08/26 21:09:57 mer Exp $
  6.  
  7.   POSTGRES YACC rules/actions
  8.   
  9.   Conventions used in coding this YACC file:
  10.  
  11.   CAPITALS are used to represent terminal symbols.
  12.   non-capitals are used to represent non-terminals.
  13.  
  14.  **********************************************************************/
  15.  
  16. #include <strings.h>
  17. #include <ctype.h>
  18.  
  19. #include "tmp/c.h"
  20. #include "catalogutils.h"
  21. #include "catalog/catname.h"
  22. #include "catalog/pg_log.h"
  23. #include "catalog/pg_magic.h"
  24. #include "catalog/pg_time.h"
  25. #include "catalog/pg_variable.h"
  26. #include "access/heapam.h"
  27. #include "utils/log.h"
  28. #include "utils/palloc.h"
  29. #include "nodes/pg_lisp.h"
  30. /* XXX ORDER DEPENDENCY */
  31. /* Yes, it's order dependant, but parse_query.h must be included a*f*t*e*r
  32.    nodes/primnodes.h */
  33. #include "nodes/primnodes.h"
  34. #include "parse_query.h"
  35. #include "nodes/primnodes.a.h"
  36. #include "rules/params.h"
  37. #include "utils/lsyscache.h"
  38. extern LispValue new_filestr();
  39. extern LispValue parser_typecast();
  40. extern LispValue make_targetlist_expr();
  41. extern List MakeList();
  42. extern List FlattenRelationList();
  43. extern List ParseAgg();
  44. extern LispValue make_array_ref();
  45.  
  46. #define ELEMENT     yyval = nappend1( LispNil , yyvsp[-0] )
  47.  
  48. #define INC_LIST     yyval = nappend1( yyvsp[-2] , yyvsp[-0] ) /* $1,$3 */
  49.  
  50. #define NULLTREE    yyval = LispNil ; 
  51. #define LAST(lv)        lispCons ( lv , LispNil )
  52.  
  53. #define INC_NUM_LEVELS(x)    { if (NumLevels < x ) NumLevels = x; }
  54. #define KW(keyword)        lispAtom(CppAsString(keyword))
  55.  
  56. #define ADD_TO_RT(rt_entry)     p_rtable = nappend1(p_rtable,rt_entry) 
  57.  
  58. #define YYSTYPE LispValue
  59. extern YYSTYPE parsetree;
  60.  
  61. LispValue NewOrCurrentIsReally = (LispValue)NULL;
  62. bool ResdomNoIsAttrNo = false;
  63. extern YYSTYPE parser_ppreserve();
  64.  
  65. static YYSTYPE temp;
  66.  
  67. int NumLevels = 0;
  68.  
  69. YYSTYPE yylval;
  70.  
  71. YYSTYPE p_target,
  72.         p_qual,
  73.         p_root,
  74.         p_priority,
  75.         p_ruleinfo;
  76. YYSTYPE           p_rtable,
  77.                p_target_resnos;
  78.  
  79. static int p_numlevels,p_last_resno;
  80. Relation parser_current_rel = NULL;
  81. static bool QueryIsRule = false;
  82.  
  83. bool Input_is_string = false;
  84. bool Input_is_integer = false;
  85. bool Typecast_ok = true;
  86. %}
  87.  
  88. /* Commands */
  89.  
  90. %token  ABORT_TRANS ADD_ATTR APPEND ATTACH_AS BEGIN_TRANS CLOSE
  91.         CLUSTER COPY CREATE DEFINE DELETE DESTROY END_TRANS EXECUTE
  92.         FETCH MERGE MOVE PURGE REMOVE RENAME REPLACE RETRIEVE
  93.  
  94. /* Keywords */
  95.  
  96. %token  ALL ALWAYS AFTER AND ARCHIVE ARCH_STORE ARG ASCENDING BACKWARD BEFORE
  97.     BINARY BY DEMAND DESCENDING EMPTY FORWARD FROM HEAVY INTERSECT INTO
  98.     IN INDEX INDEXABLE INHERITS INPUTPROC IS KEY LEFTOUTER LIGHT STORE
  99.     MERGE NEVER NEWVERSION NONE NONULLS NOT PNULL ON ONCE OR OUTPUTPROC
  100.         PORTAL PRIORITY QUEL RIGHTOUTER RULE SCONST SETOF SORT TO TRANSACTION
  101.         UNION UNIQUE USING WHERE WITH FUNCTION OPERATOR P_TYPE
  102.  
  103.  
  104. /* Special keywords */
  105.  
  106. %token  IDENT SCONST ICONST Op CCONST FCONST
  107.  
  108. /* add tokens here */
  109.  
  110. %token       INHERITANCE VERSION CURRENT NEW THEN DO INSTEAD VIEW
  111.         REWRITE P_TUPLE TYPECAST P_FUNCTION C_FUNCTION C_FN
  112.         POSTQUEL RELATION RETURNS INTOTEMP LOAD CREATEDB DESTROYDB
  113.         STDIN STDOUT VACUUM PARALLEL AGGREGATE NOTIFY LISTEN 
  114.                 IPORTAL ISNULL NOTNULL
  115.                 
  116.  
  117. /* precedence */
  118. %left    OR
  119. %left    AND
  120. %right    NOT
  121. %right     '='
  122. %nonassoc Op
  123. %nonassoc NOTNULL
  124. %nonassoc ISNULL
  125. %left      '+' '-'
  126. %left      '*' '/'
  127. %left    '|'        /* this is the relation union op, not logical or */
  128. %right  ';' ':'        /* Unary Operators      */
  129. %nonassoc  '<' '>'
  130. %right   UMINUS
  131. %left    '.'
  132. %left      '[' ']' 
  133. %nonassoc TYPECAST
  134. %nonassoc REDUCE
  135. %token PARAM AS
  136. %%
  137.  
  138. queryblock:
  139.     query 
  140.         { parser_init(param_type_info, pfunc_num_args); }
  141.     queryblock
  142.         { parsetree = lispCons ( $1 , parsetree ) ; }
  143.     | query
  144.         { 
  145.             parsetree = lispCons($1,LispNil) ; 
  146.             parser_init(param_type_info, pfunc_num_args);
  147.         }
  148.     ;
  149. query:
  150.     stmt
  151.     | PARALLEL ICONST stmt
  152.         {
  153.             $$ = nappend1($3, $2);
  154.         }
  155.     ;
  156.  
  157. stmt :
  158.       AttributeAddStmt
  159.     | ATTACH_AS attach_args /* what are the args ? */
  160.     | AggregateStmt
  161.     | ClosePortalStmt
  162.     | ClusterStmt
  163.     | CopyStmt
  164.     | CreateStmt
  165.     | DefineStmt
  166.     | DestroyStmt
  167.     | FetchStmt
  168.     | IndexStmt
  169.     | MergeStmt
  170.     | MoveStmt
  171.         | ListenStmt
  172.     | ProcedureStmt
  173.     | PurgeStmt            
  174.     | RemoveOperatorStmt
  175.     | RemoveStmt
  176.     | RenameStmt
  177.     | OptimizableStmt    
  178.     | RuleStmt            
  179.     | TransactionStmt
  180.       | ViewStmt
  181.     | LoadStmt
  182.     | CreatedbStmt
  183.     | DestroydbStmt
  184.     | VacuumStmt
  185.     ;
  186.  
  187.  
  188.  /**********************************************************************
  189.  
  190.     QUERY :
  191.         addattr ( attr1 = type1 .. attrn = typen ) to <relname>
  192.     TREE :
  193.         (ADD_ATTR <relname> (attr1 type1) . . (attrn typen) )
  194.  
  195.   **********************************************************************/
  196. AttributeAddStmt:
  197.       ADD_ATTR '(' var_defs ')' TO relation_name
  198.         {
  199.              $$ = lispCons( $6 , $3);
  200.              $$ = lispCons( KW(addattr) , $$);
  201.         }
  202.     ;
  203.  
  204.  /**********************************************************************
  205.     
  206.     QUERY :
  207.         close <optname>
  208.     TREE :
  209.         (CLOSE <portalname>)
  210.  
  211.    **********************************************************************/
  212. ClosePortalStmt:
  213.       CLOSE opt_id    
  214.         {  $$ = MakeList ( KW(close), $2, -1 ); }
  215.  
  216.     ;
  217.  
  218.  /**********************************************************************
  219.     
  220.     QUERY :
  221.         cluster <relation> on <indexname> [using <operator>]
  222.     TREE:
  223.         XXX ??? unimplemented as of 1/8/89
  224.  
  225.   **********************************************************************/
  226. ClusterStmt:
  227.       CLUSTER relation_name ON index_name OptUseOp
  228.           { elog(WARN,"cluster statement unimplemented in version 2"); }
  229.     ;
  230.  
  231.  /**********************************************************************
  232.  
  233.     QUERY :
  234.         COPY [BINARY] [NONULLS] <relname> FROM/TO 
  235.         <filename> [USING <maprelname>]
  236.  
  237.     TREE:
  238.         ( COPY ("relname" [BINARY] [NONULLS] )
  239.                ( FROM/TO "filename")
  240.                ( USING "maprelname")
  241.  
  242.   **********************************************************************/
  243.  
  244. CopyStmt:
  245.       COPY copy_type copy_null 
  246.       relation_name copy_dirn copy_file_name copy_map
  247.     
  248.         {
  249.             LispValue temp;
  250.             $$ = lispCons( KW(copy), LispNil);
  251.             $4 = lispCons($4,LispNil);
  252.             $4 = nappend1($4,$2);
  253.             $4 = nappend1($4,$3);
  254.             $$ = nappend1($$,$4);
  255.             $$ = nappend1($$,lispCons ($5,lispCons($6,LispNil)));
  256.             if(! lispNullp($7))
  257.               $7 = lispCons($7,LispNil);
  258.             $$ = nappend1($$, lispCons(KW(using), $7));
  259.             temp = $$;
  260.             while(temp != LispNil && CDR(temp) != LispNil )
  261.               temp = CDR(temp);
  262.             CDR(temp) = LispNil;
  263.         }
  264.     ;
  265.  
  266. copy_dirn:      
  267.       TO 
  268.         { $$ = KW(to); }
  269.     | FROM
  270.         { $$ = KW(from); }
  271.     ;
  272.  
  273. copy_map:
  274.     /*EMPTY*/                { NULLTREE }
  275.     | Using map_rel_name            { $$ = $2 ; }
  276.     ;
  277.  
  278. copy_null:
  279.     /*EMPTY*/                { NULLTREE }
  280.     | Nonulls
  281.     ;
  282.  
  283. copy_type:
  284.     /*EMPTY*/                { NULLTREE }
  285.     | BINARY                { $$ = KW(binary); }
  286.     ;
  287.  
  288. /* create a relation */
  289. CreateStmt:
  290.       CREATE relation_name '(' opt_var_defs ')' 
  291.       OptKeyPhrase OptInherit OptIndexable OptArchiveType
  292.       OptLocation OptArchiveLocation
  293.         {
  294.  
  295.              LispValue temp = LispNil;
  296.  
  297.              $11 = lispCons ($11, LispNil);
  298.              $10 = lispCons ($10, $11);
  299.              $9 = lispCons ( $9, $10);
  300.              $8 = lispCons ( $8, $9 );
  301.              $7 = lispCons ( $7, $8 );
  302.              $6 = lispCons ( $6, $7 );
  303.              
  304.              $2 = lispCons ( $2, LispNil );
  305.              $$ = lispCons ( KW(create), $2 );
  306.              
  307.              $$ = nappend1 ( $$, $6 );
  308.              temp = $$;
  309.  
  310.              while (CDR(temp) != LispNil) 
  311.                temp = CDR(temp);
  312.  
  313.              CDR(temp) = $4;
  314.         }
  315.     | CREATE OptDeltaDirn NEWVERSION relation_name FROM 
  316.           relation_name_version
  317.         {   
  318.             $$ = MakeList ( $2, $4, $6,-1 );
  319.         }
  320.     ;
  321. relation_name_version:
  322.       relation_name
  323.     | relation_name '[' date ']'    { $$ = MakeList( $1, $3, -1); }
  324.     ;
  325.  
  326. OptDeltaDirn:
  327.       /*EMPTY*/        { $$ = KW(forward);}
  328.     | FORWARD        { $$ = KW(forward); }
  329.     | BACKWARD        { $$ = KW(backward); }
  330.     ;
  331.  
  332. OptIndexable:
  333.     /*EMPTY*/
  334.         { NULLTREE }
  335.     | Indexable dom_name_list
  336.         { $$ = lispCons ( $1 , $2 ); }
  337.     ;
  338.  
  339. dom_name_list:        name_list;
  340.  
  341. OptArchiveType:
  342.     /*EMPTY*/                { NULLTREE }
  343.     | ARCHIVE '=' archive_type        
  344.         { $$ = lispCons (KW(archive) , $3); }
  345.     ;
  346.  
  347. archive_type:      
  348.     HEAVY    { $$ = KW(heavy); }
  349.     | LIGHT { $$ = KW(light); }
  350.     | NONE  { $$ = KW(none); }
  351.     ;
  352.  
  353. OptLocation:
  354.     /*EMPTY*/                { NULLTREE }
  355.     | STORE '=' Sconst
  356.         {
  357.             int which;
  358.  
  359.             which = smgrin(LISPVALUE_STRING($3));
  360.             $$ = lispCons(KW(store), lispInteger(which));
  361.         }
  362.     ;
  363.  
  364. OptArchiveLocation:
  365.     /*EMPTY*/                { NULLTREE }
  366.     | ARCH_STORE '=' Sconst
  367.         {
  368.             int which;
  369.  
  370.             which = smgrin(LISPVALUE_STRING($3));
  371.             $$ = lispCons(KW(arch_store), lispInteger(which));
  372.         }
  373.     ;
  374.  
  375. OptInherit:
  376.       /*EMPTY */                { NULLTREE }
  377.     | INHERITS '(' relation_name_list ')'    
  378.         { 
  379.             $$ = lispCons ( KW(inherits), $3 ) ; 
  380.         }
  381.     ;
  382.  
  383.  
  384. OptKeyPhrase :
  385.       /* NULL */                { NULLTREE }
  386.     | Key '(' key_list ')'            
  387.         { 
  388.             $$ = MakeList ( $1, $3, -1 );
  389.         }
  390.     ;
  391.  
  392. key_list:
  393.       key                    { ELEMENT ; }
  394.     | key_list ',' key            { INC_LIST ;  }
  395.     ;
  396.  
  397. key:
  398.       attr_name OptUseOp
  399.         {
  400.           $$ = lispCons($1,lispCons($2,LispNil)) ;
  401.         }
  402.     ;
  403.  
  404.  /**********************************************************************
  405.  
  406.        QUERY :
  407.         define (type,operator)
  408.     TREE :
  409.  
  410.   **********************************************************************/
  411. DefineStmt:
  412.       DEFINE def_type def_rest
  413.         {
  414.            $2 = lispCons ($2 , $3 ); 
  415.            $$ = lispCons (KW(define) , $2 ); 
  416.         }
  417.     ;
  418.  
  419. def_rest:
  420.       def_name definition opt_def_args
  421.         {
  422.            if ( $3 != LispNil ) 
  423.             $2 = nappend1 ($2, $3 );
  424.            $$ = lispCons ($1 , $2 );
  425.         }
  426.     ;
  427.  
  428. def_type:   Operator | Type    ;
  429.  
  430. def_name:  Id | Op
  431.       | '+'   { $$ = lispString("+"); }
  432.       | '-'   { $$ = lispString("-"); }
  433.       | '*'   { $$ = lispString("*"); }
  434.       | '/'   { $$ = lispString("/"); }
  435.       | '<'   { $$ = lispString("<"); }
  436.       | '>'   { $$ = lispString(">"); }
  437.       | '='   { $$ = lispString("="); }
  438.       ;
  439.  
  440. opt_def_args:    /* Because "define procedure .." */
  441.       ARG IS '(' def_name_list ')'
  442.         { $$ = lispCons (KW(arg), $4); }
  443.     | /*EMPTY*/
  444.         { NULLTREE }
  445.     ;
  446.  
  447. def_name_list:        name_list;    
  448.  
  449. def_arg:
  450.       Id
  451.     | Op
  452.     | NumConst
  453.           | Sconst
  454.     | SETOF Id        { $$ = lispCons(KW(setof), $2); }
  455.     ;
  456.  
  457. definition:
  458.       '(' def_list ')'
  459.         { $$ = $2; }
  460.     ;
  461.  
  462. def_elem:
  463.       def_name '=' def_arg
  464.         { $$ = lispCons($1, lispCons($3, LispNil)); }
  465.     | def_name
  466.         { $$ = lispCons($1, LispNil); }
  467.     ;
  468.  
  469. def_list:
  470.       def_elem            { ELEMENT ; }
  471.     | def_list ',' def_elem        { INC_LIST ;  }
  472.     ;
  473.  
  474.  /**********************************************************************
  475.     
  476.     destroy <relname1> [, <relname2> .. <relnameN> ]
  477.         ( DESTROY "relname1" ["relname2" .. "relnameN"] )
  478.  
  479.   **********************************************************************/
  480.  
  481. DestroyStmt:
  482.       DESTROY relation_name_list        
  483.         { $$ = lispCons( KW(destroy) ,$2) ; }
  484.     ;
  485.  
  486.  /**********************************************************************
  487.  
  488.     QUERY:
  489.         fetch [forward | backward] [number | all ] [ in <portalname> ]
  490.     TREE:
  491.         (FETCH <portalname> <dirn> <number> )
  492.  
  493.   **********************************************************************/
  494. FetchStmt:
  495.       FETCH opt_direction fetch_how_many opt_portal_name
  496.         {
  497.             $$ = MakeList ( KW(fetch), $4, $2, $3, -1 );
  498.             }
  499.     ;
  500.  
  501. fetch_how_many:
  502.     /*EMPTY, default is all*/
  503.         { $$ = KW(all) ; }
  504.     | NumConst
  505.     | ALL
  506.         { $$ = KW(all) ; }
  507.     ;
  508.  
  509.  /**********************************************************************
  510.     QUERY:
  511.         move [<dirn>] [<whereto>] [<portalname>]
  512.     TREE:
  513.         ( MOVE ["portalname"] <dirn> (TO <whereto> |
  514.   **********************************************************************/
  515.  
  516. MoveStmt:
  517.       MOVE opt_direction opt_move_where opt_portal_name
  518.         { 
  519.             $$ = MakeList ( KW(move), $4, $2, $3, -1 );
  520.         }
  521.     ;
  522.  
  523. opt_direction:
  524.     /*EMPTY, by default forward */        { $$ = KW(forward); }
  525.     | FORWARD
  526.         { $$ = KW(forward); }
  527.     | BACKWARD
  528.         { $$ = KW(backward); }
  529.     ;
  530.  
  531. opt_move_where: 
  532.     /*EMPTY*/                { NULLTREE }
  533.     | NumConst                /* $$ = $1 */
  534.     | TO NumConst                
  535.         { $$ = MakeList ( KW(to), $2, -1 ); }
  536.     | TO record_qual            
  537.         { $$ = lispString("record quals unimplemented") ; }
  538.     ;
  539.  
  540. opt_portal_name:
  541.     /*EMPTY*/                { NULLTREE }
  542.     | IN name                { $$ = $2;}
  543.     ;
  544.  
  545.  
  546.  
  547.  /************************************************************
  548.  
  549.     define index:
  550.     
  551.     define [archive] index <indexname> on <relname>
  552.       using <access> "(" (<col> with <op>)+ ")" with
  553.       <target_list>
  554.  
  555.   ************************************************************/
  556.  
  557.  
  558. IndexStmt:
  559.       DEFINE opt_archive Index index_name ON relation_name
  560.         Using access_method '(' index_params ')' with_clause where_clause
  561.         {
  562.             /* should check that access_method is valid,
  563.                etc ... but doesn't */
  564.  
  565.             $$ = MakeList ( $6,$4,$8,$10,$12,$13,-1 );
  566.             $$ = lispCons(KW(index),$$);
  567.             $$ = lispCons(KW(define),$$);
  568.         }
  569.     ;
  570.  
  571.  /************************************************************
  572.     QUERY:
  573.         merge <rel1> into <rel2>
  574.     TREE:
  575.         ( MERGE <rel1> <rel2> )
  576.  
  577.     XXX - unsupported in version 3 (outside of parser)
  578.  
  579.   ************************************************************/
  580. MergeStmt:
  581.     MERGE relation_expr INTO relation_name
  582.         { 
  583.             $$ = MakeList ( $1, $2, $4, -1 );
  584.             elog(WARN, "merge is unsupported in version 4");
  585.         }
  586.     ;
  587.  
  588.  /************************************************************
  589.     QUERY:
  590.                 define function <fname>
  591.                        (language = <lang>, returntype = <typename> 
  592.                         [, arch_pct = <percentage | pre-defined>]
  593.                         [, disk_pct = <percentage | pre-defined>]
  594.                         [, byte_pct = <percentage | pre-defined>]
  595.                         [, perbyte_cpu = <int | pre-defined>]
  596.                         [, percall_cpu = <int | pre-defined>]
  597.                         [, iscachable])
  598.                         [arg is (<type-1> { , <type-n>})]
  599.                         as <filename or code in language as appropriate>
  600.  
  601.   ************************************************************/
  602.  
  603. ProcedureStmt:
  604.  
  605.       DEFINE FUNCTION def_rest AS SCONST
  606.                 {
  607.             $$ = lispCons($5, LispNil);
  608.             $$ = lispCons($3, $$);
  609.             $$ = lispCons(KW(function), $$);
  610.             $$ = lispCons(KW(define), $$);
  611.         };
  612. AggregateStmt:
  613.  
  614.     DEFINE AGGREGATE def_rest 
  615.     {
  616.         $$ = lispCons( KW(aggregate), $3);
  617.         $$ = lispCons( KW(define), $$);
  618.     }
  619.     ;
  620.  
  621.  /**********************************************************************
  622.  
  623.     Purge:
  624.  
  625.     purge <relname> [before <date>] [after <date>]
  626.       or
  627.     purge <relname>  [after<date>][before <date>] 
  628.     
  629.         (PURGE "relname" ((BEFORE date)(AFTER date)))
  630.  
  631.   **********************************************************************/
  632.  
  633. PurgeStmt:
  634.       PURGE relation_name purge_quals
  635.         { 
  636.           $$ = lispCons ( $3, LispNil );
  637.           $$ = lispCons ( $2, $$ );
  638.           $$ = lispCons ( KW(purge), $$ );
  639.         }
  640.     ;
  641.  
  642. purge_quals:
  643.     /*EMPTY*/
  644.         {$$=lispList();}
  645.     | before_clause
  646.         { $$ = lispCons ( $1, LispNil ); }
  647.     | after_clause
  648.         { $$ = lispCons ( $1, LispNil ); }
  649.     | before_clause after_clause
  650.         { $$ = MakeList ( $1, $2 , -1 ); }
  651.     | after_clause before_clause
  652.         { $$ = MakeList ( $2, $1, -1 ); }
  653.     ;
  654.  
  655. before_clause:    BEFORE date        { $$ = MakeList ( KW(before),$2,-1); }
  656. after_clause:    AFTER date        { $$ = MakeList ( KW(after),$2,-1 ); }
  657.  
  658.  /**********************************************************************
  659.  
  660.     Remove:
  661.  
  662.     remove function <funcname>
  663.         (REMOVE FUNCTION "funcname")
  664.     remove operator <opname>
  665.         (REMOVE OPERATOR ("opname" leftoperand_typ rightoperand_typ))
  666.     remove type <typename>
  667.         (REMOVE TYPE "typename")
  668.     remove rewrite rule <rulename>
  669.         (REMOVE REWRITE RULE "rulename")
  670.     remove tuple rule <rulename>
  671.         (REMOVE RULE "rulename")
  672.  
  673.   **********************************************************************/
  674.  
  675. RemoveStmt:
  676.     REMOVE remove_type name
  677.         {
  678.             $$ = MakeList ( KW(remove), $2, $3 , -1 ); 
  679.         }
  680.     ;
  681.  
  682. remove_type:
  683.       Function | Aggregate | Type | Index | RuleType | VIEW ;
  684.  
  685. RuleType:
  686.      newruleTag RULE
  687.         { 
  688.             /*
  689.              * the rule type can be either
  690.              * P_TYPE or REWRITE
  691.              */
  692.             $$ = CAR($1);
  693.         }
  694.     ;  
  695. RemoveOperatorStmt:
  696.       REMOVE Operator Op '(' remove_operator ')'
  697.         {
  698.             $$  = lispCons($3, $5);
  699.             $$  = lispCons($2, lispCons($$, LispNil));
  700.             $$  = lispCons( KW(remove) , $$);
  701.         }
  702.         | REMOVE Operator MathOp '(' remove_operator ')'
  703.                 {
  704.                     $$  = lispCons($3, $5);
  705.                     $$  = lispCons($2, lispCons($$, LispNil));
  706.                     $$  = lispCons( KW(remove) , $$);
  707.                 }
  708.         ;
  709. MathOp:
  710.     | '+'   { $$ = lispString("+"); }
  711.     | '-'   { $$ = lispString("-"); }
  712.     | '*'   { $$ = lispString("*"); }
  713.     | '/'   { $$ = lispString("/"); }
  714.     | '<'   { $$ = lispString("<"); }
  715.     | '>'   { $$ = lispString(">"); }
  716.     | '='   { $$ = lispString("="); }
  717.     ;
  718.  
  719. remove_operator:
  720.       name
  721.         { $$ = lispCons($1, LispNil); }
  722.     | name ',' name
  723.         { $$ = MakeList ( $1, $3, -1 ); }
  724.     ;
  725.  
  726.  /**********************************************************************
  727.      
  728.     rename <attrname1> in <relname> to <attrname2>
  729.         ( RENAME "ATTRIBUTE" "relname" "attname1" "attname2" )
  730.     rename <relname1> to <relname2>
  731.         ( RENAME "RELATION" "relname1" "relname2" )
  732.     
  733.   **********************************************************************/
  734.  
  735. RenameStmt :
  736.       RENAME attr_name IN relation_name TO attr_name
  737.         { 
  738.             $$ = MakeList ( KW(rename), lispString("ATTRIBUTE"),
  739.                     $4, $2, $6, -1 );
  740.         }
  741.     | RENAME relation_name TO relation_name
  742.                 {
  743.             $$ = MakeList ( KW(rename), lispString("RELATION"),
  744.                     $2, $4, -1 );
  745.         }
  746.     ;
  747.  
  748.  
  749.  /* ADD : Define Rewrite Rule , Define Tuple Rule 
  750.           Define Rule <old rules >
  751.   */
  752.  
  753. opt_support:
  754.       '[' NumConst ',' NumConst ']'
  755.         {
  756.             $$ = lispCons ( $2, $4 );
  757.         }
  758.     | /* EMPTY */
  759.         {
  760.             $$ = lispCons ( lispFloat(1.0), lispFloat(0.0) );
  761.         }
  762.      ;
  763.  
  764. RuleStmt:
  765.     DEFINE newruleTag RULE name opt_support IS
  766.         {
  767.             p_ruleinfo = lispCons(lispInteger(0),LispNil);
  768.             p_priority = lispInteger(0) ;
  769.         }
  770.     RuleBody
  771.         {
  772.             if ( CAtom(CAR($2))==P_TUPLE) {
  773.             /* XXX - do the bogus fix to get param nodes
  774.                      to replace varnodes that have current 
  775.                  in them */
  776.             /*==== XXX
  777.              * LET THE TUPLE-LEVEL RULE MANAGER DO
  778.              * THE SUBSTITUTION....
  779.             SubstituteParamForNewOrCurrent ( $8 );
  780.              *====
  781.              */
  782.             $$ = lispCons ( $8, lispCons ( p_rtable, NULL )); 
  783.             $$ = lispCons ( $4, $$ ); 
  784.             if (null(CDR($2))) {
  785.                 List t;
  786.                 t = lispCons(LispNil, LispNil);
  787.                 t = lispCons(KW(rule), t);
  788.                 $$ = lispCons(t, $$);
  789.             } else {
  790.                 List t;
  791.                 t = lispCons(CADR($2), LispNil); 
  792.                 t = lispCons(KW(rule), t); 
  793.                 $$ = lispCons(t, $$); 
  794.             }
  795.             $$ = lispCons ( CAR($2), $$ );
  796.             $$ = lispCons ( KW(define), $$ ); 
  797.             } else {
  798.             $$ = nappend1 ( $8, $5 );
  799.             $$ = lispCons ( $4, $$ );
  800.             $$ = lispCons ( KW(rule), $$ );    
  801.             $$ = lispCons ( CAR($2), $$ ); 
  802.             $$ = lispCons ( KW(define), $$ );
  803.             }
  804.         }
  805.     ;
  806.  
  807. /*-------------------------
  808.  * We currently support the following rule tags:
  809.  *
  810.  * 'tuple' i.e. a rule implemented with the tuple level rule system
  811.  * 'rewrite' i.e. a rule implemented with the rewrite system
  812.  * 'relation tuple' a rule implemented with the tuple level rule
  813.  *        system, but which is forced to use a relation
  814.  *        level lock (even if we could have used the
  815.  *        more efficient tuple-level rule lock).
  816.  *        This option is used for debugging...
  817.  * 'tuple tuple' i.e. it must be implemented with a tuple level
  818.  *        lock.
  819.  *
  820.  *  25 feb 1991:  stonebraker is objectifying our terminology.  as a
  821.  *          result, 'tuples' no longer exist.  they've been replaced
  822.  *          by 'instances'.  we still use the old terminology inside
  823.  *          the system, but the visible interface has been changed.
  824.  */
  825. newruleTag: P_TUPLE 
  826.         { $$ = lispCons(KW(instance), LispNil); }
  827.     | REWRITE 
  828.         { $$ = lispCons(KW(rewrite), LispNil); }
  829.     | RELATION P_TUPLE
  830.         {
  831.             $$ = lispCons(KW(relation), LispNil);
  832.             $$ = lispCons(KW(instance), $$);
  833.         }
  834.     | P_TUPLE P_TUPLE
  835.         {
  836.             $$ = lispCons(KW(instance), LispNil);
  837.             $$ = lispCons(KW(instance), $$);
  838.         }
  839.     | /* EMPTY */
  840.         { $$ = lispCons(KW(instance), LispNil); }
  841.     ;
  842.  
  843. OptStmtList:
  844.       Id
  845.         { 
  846.           if ( ! strcmp(CString($1),"nothing") ) {
  847.             $$ = LispNil;
  848.           } else
  849.             elog(WARN,"bad rule action %s", CString($1));
  850.         }
  851.     | OptimizableStmt
  852.         { $$ = lispCons ( $1, LispNil ); }
  853.     | '[' OptStmtBlock ']'
  854.         { $$ = $2; }
  855.         ;
  856.  
  857. OptStmtBlock:
  858.       OptimizableStmt 
  859.         { ELEMENT ;}
  860.        | OptStmtBlock
  861.                {
  862.                   p_last_resno = 1;
  863.                   p_target_resnos = LispNil;
  864.           p_target = LispNil;
  865.                }
  866.          OptimizableStmt
  867.                { $$ = nappend1($1, $3); }
  868.  
  869.     ;
  870.  
  871. RuleBody: 
  872.     ON event TO 
  873.     event_object 
  874.     { 
  875.         /* XXX - figure out how to add a from_clause into this
  876.                  rule thing properly.  Spyros/Greg's bogus
  877.              fix really breaks things, so I had to axe it. */
  878.  
  879.         NewOrCurrentIsReally = $4;
  880.        /*
  881.         * NOTE: 'CURRENT' must always have a varno
  882.         * equal to 1 and 'NEW' equal to 2.
  883.         */
  884.         ADD_TO_RT ( MakeRangeTableEntry ( (Name)CString(CAR($4)), 
  885.                          LispNil,
  886.                          (Name)"*CURRENT*" ) );
  887.         ADD_TO_RT ( MakeRangeTableEntry ( (Name)CString(CAR($4)), 
  888.                          LispNil,
  889.                          (Name)"*NEW*" ));
  890.         QueryIsRule = true;
  891.     } 
  892.     where_clause
  893.     DO opt_instead 
  894.     OptStmtList
  895.     {
  896.         $$ = MakeList ( $2, $4, $6, $8, $9, -1 );
  897.         /* modify the rangetable entry for "current" and "new" */
  898.     }
  899.     ;
  900.  
  901. event_object: 
  902.     relation_name '.' attr_name
  903.         { $$ = MakeList ( $1, $3, -1 ); }
  904.     | relation_name
  905.         { $$ = lispCons ( $1, LispNil ); }
  906.       ;
  907. event:
  908.       RETRIEVE | REPLACE | DELETE | APPEND ;
  909.  
  910. opt_instead:
  911.       INSTEAD                { $$ = lispInteger((int)true); }
  912.     | /* EMPTY */            { $$ = lispInteger((int)false); }
  913.     ;
  914.  
  915.  
  916. /* NOTIFY <relation_name>  can appear both in rule bodies and
  917.   as a query-level command */
  918. NotifyStmt: NOTIFY relation_name 
  919.             {
  920.         LispValue root;
  921.         int x = 0;
  922.             
  923.         elog(WARN,
  924.              "notify is turned off for 4.0.1 - see the release notes");
  925.         if((x=RangeTablePosn(CString($2),LispNil)) == 0 )
  926.           ADD_TO_RT (MakeRangeTableEntry ((Name)CString($2),
  927.                           LispNil,
  928.                           (Name)CString($2)));
  929.             
  930.         if (x==0)
  931.           x = RangeTablePosn(CString($2),LispNil);
  932.         
  933.         parser_current_rel = heap_openr(VarnoGetRelname(x));
  934.         if (parser_current_rel == NULL)
  935.           elog(WARN,"notify: relation %s doesn't exist",CString($2));
  936.         else
  937.           heap_close(parser_current_rel);
  938.  
  939.         root = MakeRoot(1,
  940.                 KW(notify),
  941.                 lispInteger(x), /* result relation */
  942.                 p_rtable, /* range table */
  943.                 p_priority, /* priority */
  944.                 p_ruleinfo, /* rule info */
  945.                 LispNil, /* unique flag */
  946.                 LispNil, /* sort clause */
  947.                 LispNil); /* target list */
  948.         $$ = lispCons ( root , LispNil );
  949.         $$ = nappend1 ( $$ , LispNil ); /*  */
  950.         $$ = nappend1 ( $$ , LispNil ); /*  */
  951.         }
  952. ;
  953.  
  954. ListenStmt: LISTEN relation_name 
  955.             {
  956.         elog(WARN,
  957.              "listen is turned off for 4.0.1 - see the release notes");
  958.         parser_current_rel = heap_openr(CString($2));
  959.         if (parser_current_rel == NULL)
  960.           elog(WARN,"listen: relation %s doesn't exist",$2);
  961.         else
  962.           heap_close(parser_current_rel);
  963.  
  964.         $$ = MakeList(KW(listen),$2,-1);
  965.         }
  966. ;
  967.  
  968.  /**************************************************
  969.  
  970.     Transactions:
  971.  
  972.     abort transaction
  973.         (ABORT)
  974.     begin transaction
  975.         (BEGIN)
  976.     end transaction
  977.         (END)
  978.     
  979.   **************************************************/
  980. TransactionStmt:
  981.       ABORT_TRANS TRANSACTION
  982.         { $$ = lispCons ( KW(abort), LispNil ) ; } 
  983.     | BEGIN_TRANS TRANSACTION
  984.         { $$ = lispCons ( KW(begin), LispNil ) ; } 
  985.     | END_TRANS TRANSACTION
  986.         { $$ = lispCons ( KW(end), LispNil ) ; } 
  987.     | ABORT_TRANS
  988.         { $$ = lispCons ( KW(abort), LispNil ) ; } 
  989.     | BEGIN_TRANS
  990.         { $$ = lispCons ( KW(begin), LispNil ) ; } 
  991.     | END_TRANS
  992.         { $$ = lispCons ( KW(end), LispNil ) ; } 
  993.     ;
  994.  
  995.  /**************************************************
  996.  
  997.     View Stmt  
  998.     define view <viewname> '('target-list ')' [where <quals> ]
  999.  
  1000.    **************************************************/
  1001.  
  1002. ViewStmt:
  1003.     DEFINE VIEW name 
  1004.     RetrieveSubStmt
  1005.         { 
  1006.             $3 = lispCons ( $3 , $4 );
  1007.             $2 = lispCons ( KW(view) , $3 );
  1008.             $$ = lispCons ( KW(define) , $2 );
  1009.         }
  1010.     ;
  1011.  
  1012.  /**************************************************
  1013.  
  1014.         Load Stmt
  1015.         load "filename"
  1016.  
  1017.    **************************************************/
  1018.  
  1019. LoadStmt:
  1020.         LOAD file_name
  1021.                 {  $$ = MakeList ( KW(load), $2, -1 ); }
  1022.         ;
  1023.  
  1024.  /**************************************************
  1025.  
  1026.         Createdb Stmt
  1027.         createdb dbname
  1028.  
  1029.    **************************************************/
  1030.  
  1031. CreatedbStmt:
  1032.         CREATEDB database_name
  1033.                 {  $$ = MakeList ( KW(createdb), $2, -1 ); }
  1034.         ;
  1035.  
  1036.  /**************************************************
  1037.  
  1038.         Destroydb Stmt
  1039.         destroydb dbname
  1040.  
  1041.    **************************************************/
  1042.  
  1043. DestroydbStmt:
  1044.         DESTROYDB database_name
  1045.                 {  $$ = MakeList ( KW(destroydb), $2, -1 ); }
  1046.         ;
  1047.  
  1048.  /**************************************************
  1049.  
  1050.         Vacuum Stmt
  1051.     vacuum
  1052.  
  1053.    **************************************************/
  1054.  
  1055. VacuumStmt:
  1056.     VACUUM
  1057.         { $$ = MakeList(KW(vacuum), -1); }
  1058.     ;
  1059.  
  1060.  /**********************************************************************
  1061.   **********************************************************************
  1062.  
  1063.     Optimizable Stmts:
  1064.  
  1065.     one of the five queries processed by the planner
  1066.  
  1067.     [ultimately] produces query-trees as specified
  1068.     in the query-spec document in ~postgres/ref
  1069.  
  1070.   **********************************************************************
  1071.   **********************************************************************/
  1072.  
  1073.  
  1074. OptimizableStmt:    
  1075.       RetrieveStmt
  1076.     | ExecuteStmt
  1077.     | ReplaceStmt
  1078.     | AppendStmt
  1079.         | NotifyStmt
  1080.         | DeleteStmt            /* by default all are $$=$1 */
  1081.     ;
  1082.  
  1083.  /**************************************************
  1084.  
  1085.    AppendStmt
  1086.    - an optimizable statement, produces a querytree
  1087.    as per query spec
  1088.  
  1089.   **************************************************/
  1090.  
  1091. AppendStmt:
  1092.         APPEND
  1093.                 { SkipForwardToFromList(); }
  1094.           from_clause
  1095.           opt_star relation_name
  1096.                 {
  1097.                    int x = 0;
  1098.                    if((x=RangeTablePosn(CString($5),LispNil)) == 0)
  1099.              ADD_TO_RT( MakeRangeTableEntry((Name)CString($5),
  1100.                             LispNil,
  1101.                             (Name)CString($5)));
  1102.                   if (x==0)
  1103.                     x = RangeTablePosn(CString($5),LispNil);
  1104.                   parser_current_rel = heap_openr(VarnoGetRelname(x));
  1105.                   if (parser_current_rel == NULL)
  1106.                         elog(WARN,"invalid relation name");
  1107.                   ResdomNoIsAttrNo = true;
  1108.                 }
  1109.           '(' res_target_list ')'
  1110.           where_clause
  1111.                 {
  1112.                         LispValue root;
  1113.             LispValue command;
  1114.                         int x = RangeTablePosn(CString($5),LispNil);
  1115.  
  1116.             if ( $4 == LispNil )
  1117.               command = KW(append);
  1118.             else
  1119.               command = lispCons( lispInteger('*'),KW(append));
  1120.  
  1121.                         root = MakeRoot(1, command , lispInteger(x),
  1122.                                         p_rtable,
  1123.                                         p_priority, p_ruleinfo,
  1124.                     LispNil,LispNil,$8);
  1125.                         $$ = lispCons ( root , LispNil );
  1126.                         $$ = nappend1 ( $$ , $8 ); /* (eq p_target $8) */
  1127.                         $$ = nappend1 ( $$ , $10 ); /* (eq p_qual $10 */
  1128.                         ResdomNoIsAttrNo = false;
  1129.             heap_close(parser_current_rel);
  1130.                 }
  1131.         ;
  1132.  
  1133.  
  1134.  
  1135.  /**************************************************
  1136.  
  1137.    DeleteStmt
  1138.    - produces a querytree that looks like
  1139.    that in the query spec
  1140.  
  1141.   **************************************************/
  1142.    
  1143. DeleteStmt:
  1144.           DELETE
  1145.                 { SkipForwardToFromList(); }
  1146.           from_clause
  1147.           opt_star var_name
  1148.                 {
  1149.             int x = 0;
  1150.             
  1151.             if((x=RangeTablePosn(CString($5),LispNil)) == 0 )
  1152.                       ADD_TO_RT (MakeRangeTableEntry ((Name)CString($5),
  1153.                               LispNil,
  1154.                               (Name)CString($5)));
  1155.             
  1156.             if (x==0)
  1157.               x = RangeTablePosn(CString($5),LispNil);
  1158.             
  1159.             parser_current_rel = heap_openr(VarnoGetRelname(x));
  1160.             if (parser_current_rel == NULL)
  1161.               elog(WARN,"invalid relation name");
  1162.             else
  1163.               heap_close(parser_current_rel);
  1164.             /* ResdomNoIsAttrNo = true;  */
  1165.         }
  1166.           where_clause
  1167.                 {
  1168.             LispValue root = LispNil;
  1169.             LispValue command = LispNil;
  1170.             int x = 0;
  1171.  
  1172.             x= RangeTablePosn(CString($5),LispNil);
  1173.             if (x == 0)
  1174.               ADD_TO_RT(MakeRangeTableEntry ((Name)CString ($5),
  1175.                              LispNil,
  1176.                              (Name)CString($5)));
  1177.             if ( $4 == LispNil )
  1178.               command = KW(delete);
  1179.             else
  1180.               command = lispCons( lispInteger('*'),KW(delete));
  1181.             
  1182.             root = MakeRoot(1,command,
  1183.                     lispInteger ( x ) ,
  1184.                     p_rtable, p_priority, p_ruleinfo,
  1185.                     LispNil,LispNil,LispNil);
  1186.             $$ = lispCons ( root , LispNil );
  1187.  
  1188.             /* check that var_name is in the relation */
  1189.  
  1190.             $$ = nappend1 ( $$ , LispNil );     /* no target list */
  1191.             $$ = nappend1 ( $$ , $7 );         /* (eq p_qual $7 */
  1192.                 }
  1193.         ;
  1194.  
  1195.  /**************************************************
  1196.    
  1197.    ExecuteStmt
  1198.    - produces a querytree that looks like that
  1199.    in the queryspec
  1200.  
  1201.   **************************************************/
  1202.  
  1203. ExecuteStmt:
  1204.       EXECUTE opt_star opt_portal '(' res_target_list ')'
  1205.             from_clause with_clause where_clause
  1206.         { 
  1207.             $$ = KW(execute);
  1208.               elog(WARN, "execute does not work in Version 1");
  1209.         }
  1210.     ;
  1211.  
  1212.  /**********************************************************************
  1213.  
  1214.     Replace:
  1215.  
  1216.     - as per qtree specs
  1217.  
  1218.   **********************************************************************/
  1219.  
  1220. ReplaceStmt:
  1221.      REPLACE 
  1222.                 { SkipForwardToFromList(); }
  1223.         from_clause
  1224.         opt_star relation_name
  1225.                 {
  1226.                    int x = 0;
  1227.                    if((x=RangeTablePosn(CString($5),LispNil) ) == 0 )
  1228.              ADD_TO_RT( MakeRangeTableEntry ((Name)CString($5),
  1229.                              LispNil,
  1230.                              (Name)CString($5)));
  1231.                   if (x==0)
  1232.                     x = RangeTablePosn(CString($5),LispNil);
  1233.                   parser_current_rel = heap_openr(VarnoGetRelname(x));
  1234.                   if (parser_current_rel == NULL)
  1235.                         elog(WARN,"invalid relation name");
  1236.                   ResdomNoIsAttrNo = true; }
  1237.         '(' res_target_list ')' where_clause
  1238.                 {
  1239.                     LispValue root;
  1240.             LispValue command = LispNil;
  1241.                     int result = RangeTablePosn(CString($5),LispNil);
  1242.                     if (result < 1)
  1243.                       elog(WARN,"parser internal error , bogus relation");
  1244.             if ( $4 == LispNil )
  1245.               command = KW(replace);
  1246.             else
  1247.               command = lispCons( lispInteger('*'),KW(replace));
  1248.  
  1249.                     root = MakeRoot(1, command , lispInteger(result),
  1250.                                     p_rtable,
  1251.                                     p_priority, p_ruleinfo,
  1252.                     LispNil,LispNil,$8);
  1253.  
  1254.                     $$ = lispCons( root , LispNil );
  1255.                     $$ = nappend1 ( $$ , $8 );          /* (eq p_target $6) */
  1256.                     $$ = nappend1 ( $$ , $10 );         /* (eq p_qual $9) */
  1257.                     ResdomNoIsAttrNo = false;
  1258.             heap_close(parser_current_rel);
  1259.                 }
  1260.         ;
  1261.  
  1262.  
  1263.          
  1264.  /************************************************************
  1265.  
  1266.     Retrieve:
  1267.  
  1268.     ( ( <NumLevels> RETRIEVE <result> <rtable> <priority>
  1269.         <RuleInfo> )
  1270.       (targetlist)
  1271.       (qualification) )
  1272.  
  1273.   ************************************************************/
  1274.  
  1275. RetrieveStmt:
  1276.     RETRIEVE 
  1277.     RetrieveSubStmt
  1278.         { $$ = $2 ; }
  1279.     ;
  1280.  
  1281. RetrieveSubStmt:
  1282.       { SkipForwardToFromList(); }
  1283.       from_clause 
  1284.       result opt_unique 
  1285.       '(' res_target_list ')'
  1286.        where_clause ret_opt2 
  1287.           {
  1288.         /* XXX - what to do with opt_unique, from_clause
  1289.          */    
  1290.             LispValue root;
  1291.             LispValue command;
  1292.  
  1293.             command = KW(retrieve);
  1294.  
  1295.             root = MakeRoot(NumLevels,command, $3, p_rtable,
  1296.                     p_priority, p_ruleinfo,$4,$9,$6);
  1297.             
  1298.  
  1299.             $$ = lispCons( root , LispNil );
  1300.             $$ = nappend1 ( $$ , $6 );
  1301.             $$ = nappend1 ( $$ , $8 );
  1302.         }
  1303.  
  1304.  /**************************************************
  1305.  
  1306.     Retrieve result:
  1307.     into <relname>
  1308.         (INTO "relname");
  1309.     portal <portname>
  1310.         (PORTAL "portname")
  1311.     NULL
  1312.         nil
  1313.  
  1314.   **************************************************/
  1315. result:
  1316.       INTO relation_name
  1317.         {
  1318.             $2=lispCons($2 , LispNil );
  1319.             /* should check for archive level */
  1320.             $$=lispCons(KW(into), $2);
  1321.         }
  1322.     | opt_portal
  1323.         /* takes care of the null case too */
  1324.     ;
  1325.  
  1326. opt_unique:
  1327.     /*EMPTY*/
  1328.         { NULLTREE }
  1329.     | UNIQUE
  1330.         { $$ = KW(unique); }
  1331.     ;
  1332.  
  1333. ret_opt2: 
  1334.     /*EMPTY*/
  1335.         { NULLTREE }
  1336.     | Sort BY sortby_list
  1337.         { $$ = $3 ; }
  1338.     ;
  1339.  
  1340. sortby_list:
  1341.       sortby                { ELEMENT ; }
  1342.     | sortby_list ',' sortby        { INC_LIST ;  }
  1343.     ;
  1344.  
  1345. sortby:
  1346.       Id OptUseOp
  1347.         { $$ = lispCons ( $1, lispCons ($2, LispNil )) ; }
  1348.     | attr OptUseOp
  1349.                 { /* i had to do this since a bug in yacc wouldn't catch */
  1350.                   /* this syntax error - ron choi 4/11/91 */
  1351.                   yyerror("syntax error: use \"sort by attribute_name\"");
  1352.                 }
  1353.  
  1354.     ;
  1355.  
  1356.  
  1357.  
  1358. opt_archive:
  1359.         { NULLTREE }
  1360.     | ARCHIVE 
  1361.         { $$ = KW(archive); }
  1362.     ;
  1363.  
  1364. index_params:
  1365.       index_list                /* $$=$1 */
  1366.     | func_index                { ELEMENT ; }
  1367.     ;
  1368. index_list:
  1369.       index_list ',' index_elem        { INC_LIST ;  }
  1370.     | index_elem                { ELEMENT ; }
  1371.     ;
  1372.  
  1373. func_index:
  1374.       ind_function opt_class
  1375.         { $$ = nappend1(LispNil,$1); nappend1($$,$2); }
  1376.       ;
  1377.  
  1378. ind_function:
  1379.       name '(' name_list ')' 
  1380.         { $$ = nappend1(LispNil,$1); rplacd($$,$3); }
  1381.       ;
  1382.  
  1383. index_elem:
  1384.       attr_name opt_class
  1385.         { $$ = nappend1(LispNil,$1); nappend1($$,$2);}
  1386.     ;
  1387. opt_class:
  1388.       /* empty */                { NULLTREE; }
  1389.     | class
  1390.     | With class
  1391.         {$$=$2;}
  1392.     ;
  1393.  
  1394. /*
  1395.  *  jimmy bell-style recursive queries aren't supported in the
  1396.  *  current system.
  1397.  */
  1398.  
  1399. opt_star:
  1400.     /*EMPTY*/        { NULLTREE }
  1401.       ;
  1402.  
  1403. relation_name_list:    name_list ;
  1404.  
  1405. name_list: 
  1406.       name                 { ELEMENT ; }
  1407.     | name_list ',' name        { INC_LIST ;  }
  1408.     ;    
  1409.  
  1410.  /**********************************************************************
  1411.    
  1412.    clauses common to all Optimizable Stmts:
  1413.        from_clause     -
  1414.            where_clause     -
  1415.     
  1416.   **********************************************************************/
  1417. with_clause:
  1418.     /* NULL */                { NULLTREE }
  1419.     | With '(' param_list ')'        { $$ = MakeList ( $1,$3,-1 ); }
  1420.     ;
  1421.  
  1422. param_list:         
  1423.       param_list ',' param            { INC_LIST ;  }
  1424.     | param                    { ELEMENT ; }
  1425.     ;
  1426.  
  1427. param:             
  1428.       Id '=' string 
  1429.         { $$ = MakeList ( $1, $3, -1 ); }
  1430.     ;
  1431.  
  1432. from_clause:
  1433.      FROM from_list             
  1434.         { 
  1435.             $$ = $2 ; 
  1436.             SkipBackToTlist();
  1437.             yychar = -1;
  1438.             /* goto yynewstate; */
  1439.         }
  1440.     | /*empty*/                { NULLTREE ; }
  1441.     ;
  1442.  
  1443. from_list:
  1444.       from_list ',' from_val         { INC_LIST ;  }
  1445.     | from_val                { ELEMENT ; }
  1446.     ;
  1447.  
  1448. from_val:
  1449.       var_list IN relation_expr
  1450.         {
  1451.             extern List MakeFromClause ();
  1452.             $$ = MakeFromClause ( $1, $3 );
  1453.         }    
  1454.     ;
  1455. var_list:
  1456.       var_list ',' var_name            { INC_LIST ;  }
  1457.     | var_name                { ELEMENT ; }
  1458.     ;
  1459.  
  1460. where_clause:
  1461.     /* empty - no qualifiers */
  1462.             { NULLTREE } 
  1463.     | WHERE a_expr
  1464.         {
  1465.         if (CInteger(CAR($2)) != BOOLOID)
  1466.             elog(WARN,
  1467.              "where clause must return type bool, not %s",
  1468.              tname(get_id_type(CInteger(CAR($2)))));
  1469.         p_qual = $$ = CDR($2);
  1470.         }
  1471.     ;
  1472.  
  1473. opt_portal:
  1474.       /* common to retrieve, execute */
  1475.     /*EMPTY*/
  1476.         { NULLTREE }
  1477.         | IPORTAL name 
  1478.         {
  1479.             /*
  1480.              *  15 august 1991 -- since 3.0 postgres does locking
  1481.              *  right, we discovered that portals were violating
  1482.              *  locking protocol.  portal locks cannot span xacts.
  1483.              *  as a short-term fix, we installed the check here. 
  1484.              *                -- mao
  1485.              */
  1486.             if (!IsTransactionBlock())
  1487.             elog(WARN, "Named portals may only be used in begin/end transaction blocks.");
  1488.  
  1489.             $$ = MakeList ( KW(iportal), $2, -1 ); 
  1490.         }
  1491.     | PORTAL name 
  1492.         {
  1493.             /*
  1494.              *  15 august 1991 -- since 3.0 postgres does locking
  1495.              *  right, we discovered that portals were violating
  1496.              *  locking protocol.  portal locks cannot span xacts.
  1497.              *  as a short-term fix, we installed the check here. 
  1498.              *                -- mao
  1499.              */
  1500.             if (!IsTransactionBlock())
  1501.             elog(WARN, "Named portals may only be used in begin/end transaction blocks.");
  1502.  
  1503.             $$ = MakeList ( KW(portal), $2, -1 ); 
  1504.         }
  1505.     ;
  1506.  
  1507. OptUseOp:
  1508.       /*EMPTY*/            { NULLTREE }
  1509.     | USING Op            { $$ = $2; }
  1510.     | USING '<'            { $$ = lispString("<"); }
  1511.     | USING '>'            { $$ = lispString(">"); }
  1512.     ;
  1513.  
  1514. relation_expr:
  1515.       relation_name
  1516.           { 
  1517.             /* normal relations */
  1518.             $$ = lispCons ( MakeList ( $1, LispNil , LispNil , -1 ),
  1519.                    LispNil );
  1520.         }
  1521.     | relation_expr '|' relation_expr %prec '='
  1522.         { 
  1523.             /* union'ed relations */
  1524.             elog ( DEBUG, "now consing the union'ed relations");
  1525.             $$ = append ( $1, $3 );
  1526.         }
  1527.     | relation_name '*'          %prec '='
  1528.         { 
  1529.             /* inheiritance query */
  1530.             $$ = lispCons ( MakeList ( $1, LispNil, 
  1531.                           lispString("*"), -1) ,
  1532.                    LispNil );
  1533.         }
  1534.     | relation_name time_range 
  1535.         { 
  1536.             /* time-qualified query */
  1537.             $$ = lispCons ( MakeList ( $1, $2, LispNil , -1 ) ,
  1538.                     LispNil );
  1539.         }
  1540.     | '(' relation_expr ')'
  1541.         { 
  1542.             elog( DEBUG, "now reducing by parentheses");
  1543.             $$ = $2; 
  1544.         }
  1545.     ;
  1546.  
  1547.       
  1548. time_range:
  1549.       '[' opt_range_start ',' opt_range_end ']'
  1550.             { 
  1551.             $$ = MakeList ( $2, $4, lispInteger(1), -1 );
  1552.         }
  1553.     | '[' date ']'
  1554.         { 
  1555.             $$ = MakeList ( $2 , LispNil, lispInteger(0), -1 );
  1556.         }
  1557.         ;
  1558.  
  1559. opt_range_start:
  1560.       /* no date, default to nil */
  1561.         { $$ = lispString("epoch"); }
  1562.     | date
  1563.     ;
  1564.  
  1565. opt_range_end:
  1566.       /* no date, default to nil */
  1567.         { $$ = lispString("now"); }
  1568.     | date
  1569.     ;
  1570.  
  1571. record_qual:
  1572.     /*EMPTY*/
  1573.         { NULLTREE }
  1574.     ;
  1575.  
  1576. /*
  1577.  *  Array bounds -- support for arrays in the current system is poor.
  1578.  *  We'd like to support multi-dimensional arrays, arrays with lower
  1579.  *  bounds at values other than 1, ..., but we don't.  The only thing
  1580.  *  that's real in the Array nodes we return below is arrayhigh,
  1581.  *  which is the upper bound of the array.
  1582.  */
  1583.  
  1584. opt_array_bounds:
  1585.         '[' ']'
  1586.         { 
  1587.             $$ = (LispValue) MakeArray((ObjectId) 0, 0, false, 0,
  1588.                         -1, /* -1 means var length */
  1589.                     0);
  1590.         }
  1591.     | '[' Iconst ']'
  1592.         {
  1593.             $$ = (LispValue) MakeArray((ObjectId) 0, 0, false, 0,
  1594.                         CInteger($2), 0);
  1595.         }
  1596.     | /* EMPTY */                { NULLTREE }
  1597.     ;
  1598.  
  1599. Typename:
  1600.         name opt_array_bounds            { $$ = lispCons($1,$2); }
  1601.     ;
  1602.  
  1603. var_def:     
  1604.       Id '=' Typename
  1605.         { 
  1606.             ObjectId typrelid;
  1607.  
  1608.             /* for 4.0, attributes cannot have complex types */
  1609.             typrelid = get_typrelid(type(CString(CAR($3))));
  1610.             if (typrelid != InvalidObjectId) {
  1611.             elog(NOTICE, "cannot create attribute of type %s",
  1612.                      CString(CAR($3)));
  1613.             elog(WARN, "use functions to get complex objects");
  1614.             }
  1615.  
  1616.             $$ = MakeList($1,$3,-1);
  1617.         }
  1618.     ;
  1619.  
  1620. var_defs:
  1621.       var_defs ',' var_def        { INC_LIST ;  }
  1622.     | var_def            { ELEMENT ; }
  1623.     ;
  1624.  
  1625. opt_var_defs: 
  1626.       var_defs
  1627.     | {NULLTREE} ;
  1628.  
  1629. agg_where_clause:
  1630.     /* empty list */  {NULLTREE; }
  1631.     | WHERE a_expr 
  1632.         {
  1633.         if (CInteger(CAR($2)) != BOOLOID)
  1634.             elog(WARN,
  1635.              "where clause must return type bool, not %s",
  1636.              tname(get_id_type(CInteger(CAR($2)))));
  1637.         $$ = CDR($2);
  1638.         }
  1639.     ;
  1640.  
  1641.  /* 
  1642.   * expression grammar, still needs some cleanup
  1643.   */
  1644.  
  1645. a_expr:
  1646.       attr opt_indirection
  1647.            {
  1648.         List temp;
  1649.  
  1650.         temp = HandleNestedDots($1);
  1651.         if ($2 == LispNil)
  1652.             $$ = temp;
  1653.         else
  1654.             $$ = make_array_ref(temp, $2);
  1655.         Typecast_ok = false;
  1656.        }
  1657.     | AexprConst        
  1658.     | '-' a_expr %prec UMINUS
  1659.           { $$ = make_op(lispString("-"), LispNil, $2, 'l');
  1660.           Typecast_ok = false; }
  1661.     | a_expr '+' a_expr
  1662.         { $$ = make_op (lispString("+"), $1, $3, 'b' ) ;
  1663.           Typecast_ok = false; }
  1664.     | a_expr '-' a_expr
  1665.         { $$ = make_op (lispString("-"), $1, $3, 'b' ) ;
  1666.           Typecast_ok = false; }
  1667.     | a_expr '/' a_expr
  1668.         { $$ = make_op (lispString("/"), $1, $3, 'b' ) ;
  1669.           Typecast_ok = false; }
  1670.     | a_expr '*' a_expr
  1671.         { $$ = make_op (lispString("*"), $1, $3, 'b' ) ;
  1672.           Typecast_ok = false; }
  1673.     | a_expr '<' a_expr
  1674.         { $$ = make_op (lispString("<"), $1, $3, 'b' ) ;
  1675.           Typecast_ok = false; }
  1676.     | a_expr '>' a_expr
  1677.         { $$ = make_op (lispString(">"), $1, $3, 'b' ) ;
  1678.           Typecast_ok = false; }
  1679.     | a_expr '=' a_expr
  1680.         { $$ = make_op (lispString("="), $1, $3, 'b' ) ;
  1681.           Typecast_ok = false; }
  1682.     | ':' a_expr
  1683.         { $$ = make_op (lispString(":"), LispNil, $2, 'l' ) ;
  1684.         Typecast_ok = false; }
  1685.     | ';' a_expr
  1686.         { $$ = make_op (lispString(";"), LispNil, $2, 'l' ) ;
  1687.         Typecast_ok = false; }
  1688.     | '|' a_expr
  1689.         { $$ = make_op (lispString("|"), LispNil, $2, 'l' ) ;
  1690.         Typecast_ok = false; }
  1691.     | AexprConst TYPECAST Typename
  1692.         { 
  1693.             extern LispValue parser_typecast();
  1694.             $$ = parser_typecast ( $1, $3 );
  1695.             Typecast_ok = false; /* it's already typecasted */
  1696.                      /* don't do it again. */ }
  1697.     | '(' a_expr ')'
  1698.         {$$ = $2;}
  1699.     | a_expr Op a_expr
  1700.         { $$ = make_op ( $2, $1 , $3, 'b' );
  1701.           Typecast_ok = false; }
  1702.     | Op a_expr
  1703.           { $$ = make_op ( $1, LispNil, $2, 'l');
  1704.           Typecast_ok = false; }
  1705.     | a_expr Op
  1706.           { $$ = make_op ( $2, $1, LispNil, 'r');
  1707.           Typecast_ok = false; }
  1708.     | relation_name
  1709.         { $$ = lispCons ( KW(relation), $1 );
  1710.                   INC_NUM_LEVELS(1);
  1711.           Typecast_ok = false; }
  1712.     | name '(' ')'
  1713.         {
  1714.             extern List ParseFunc();
  1715.             $$ = ParseFunc ( CString ( $1 ), LispNil );
  1716.             Typecast_ok = false;
  1717.         }
  1718.     | name '(' expr_list ')'
  1719.         {
  1720.             extern List ParseFunc();
  1721.             $$ = ParseFunc ( CString ( $1 ), $3 );
  1722.             Typecast_ok = false; }
  1723.      | a_expr ISNULL
  1724.              {
  1725.                  extern List ParseFunc();
  1726.                  yyval =  nappend1( LispNil, $1);
  1727.                  $$ = ParseFunc( "NullValue", yyval );
  1728.                  Typecast_ok = false; }
  1729.     | a_expr NOTNULL
  1730.         {
  1731.             extern List ParseFunc();
  1732.              yyval =  nappend1( LispNil, $1);
  1733.              $$ = ParseFunc( "NonNullValue", yyval );
  1734.              Typecast_ok = false;
  1735.         }
  1736.     | a_expr AND a_expr
  1737.         {
  1738.         if (CInteger(CAR($1)) != BOOLOID)
  1739.             elog(WARN,
  1740.              "left-hand side of AND is type '%s', not bool",
  1741.              tname(get_id_type(CInteger(CAR($1)))));
  1742.         if (CInteger(CAR($3)) != BOOLOID)
  1743.             elog(WARN,
  1744.              "right-hand side of AND is type '%s', not bool",
  1745.              tname(get_id_type(CInteger(CAR($3)))));
  1746.  
  1747.         $$ = lispCons(lispInteger(BOOLOID),
  1748.                   MakeList (lispInteger(AND),
  1749.                     CDR($1), CDR($3), -1));
  1750.         }
  1751.     | a_expr OR a_expr
  1752.         {
  1753.         if (CInteger(CAR($1)) != BOOLOID)
  1754.             elog(WARN,
  1755.              "left-hand side of OR is type '%s', not bool",
  1756.              tname(get_id_type(CInteger(CAR($1)))));
  1757.         if (CInteger(CAR($3)) != BOOLOID)
  1758.             elog(WARN,
  1759.              "right-hand side of OR is type '%s', not bool",
  1760.              tname(get_id_type(CInteger(CAR($3)))));
  1761.  
  1762.         $$ = lispCons(lispInteger(BOOLOID),
  1763.                   MakeList (lispInteger(OR),
  1764.                     CDR($1), CDR($3), -1));
  1765.         }
  1766.     | NOT a_expr
  1767.         {
  1768.         if (CInteger(CAR($2)) != BOOLOID)
  1769.             elog(WARN,
  1770.              "argument to NOT is type '%s', not bool",
  1771.              tname(get_id_type(CInteger(CAR($2)))));
  1772.  
  1773.         $$ = lispCons(lispInteger(BOOLOID),
  1774.                   MakeList (lispInteger(NOT),
  1775.                     CDR($2), -1));
  1776.         }
  1777.     ;
  1778.  
  1779. /* we support only single-dim arrays in the current system */
  1780. opt_indirection:
  1781.       '[' a_expr ']'        {
  1782.         if (CInteger(CAR($2)) != INT4OID)
  1783.             elog(WARN, "array index expressions must be int4's");
  1784.         $$ = $2;
  1785.         }
  1786.     | /* EMPTY */            { NULLTREE }
  1787.     ;
  1788.  
  1789. expr_list: a_expr            { ELEMENT ; }
  1790.     |  expr_list ',' a_expr        { INC_LIST ; }
  1791.     ;
  1792. attr:
  1793.           relation_name '.' attrs
  1794.                 {
  1795.             INC_NUM_LEVELS(1);
  1796.             $$ = lispCons($1,$3);
  1797.         }
  1798.  
  1799.     | ParamNo '.' attrs
  1800.             {
  1801.         INC_NUM_LEVELS(1);
  1802.         $$ = lispCons($1,$3);
  1803.         }
  1804.     ;
  1805.  
  1806. attrs:
  1807.         attr_name                       { $$ = lispCons($1, LispNil); }
  1808.       | attrs '.' attr_name             { $$ = nappend1($1, $3);}
  1809.  
  1810. agg_res_target_el:
  1811.        attr
  1812.       {
  1813.            LispValue varnode, temp;
  1814.            Resdom resnode;
  1815.            int type_id, type_len;
  1816.  
  1817.            temp = HandleNestedDots($1);
  1818.  
  1819.             type_id = CInteger(CAR(temp));
  1820.  
  1821.         if (ISCOMPLEX(type_id))
  1822.             elog(WARN,
  1823.              "Cannot use complex type %s as atomic value in target list",
  1824.              tname(get_id_type(type_id)));
  1825.  
  1826.             type_len = tlen(get_id_type(type_id));
  1827.             resnode = MakeResdom ( (AttributeNumber)1,
  1828.                      (ObjectId)type_id, ISCOMPLEX(type_id),
  1829.                      (Size)type_len,
  1830.                      (Name)CString(CAR(last ($1) )),
  1831.                      (Index)0 , (OperatorTupleForm)0 ,
  1832.                      0 );
  1833.             varnode = CDR(temp);
  1834.  
  1835.             $$ = lispCons((LispValue)resnode, lispCons(varnode,LispNil));
  1836.      }
  1837.  
  1838. agg:
  1839.     name  '{' agg_res_target_el agg_where_clause '}'
  1840.     {
  1841.          LispValue query2;
  1842.          LispValue varnode = $3;
  1843.          $3 = lispCons($3, LispNil);
  1844.          query2 = MakeRoot(1, KW(retrieve), LispNil,
  1845.          p_rtable, p_priority, p_ruleinfo, LispNil,
  1846.          LispNil,$3);
  1847.         
  1848.          query2 = lispCons (query2, LispNil);
  1849.          query2 = nappend1 (query2, $3);
  1850.          query2 = nappend1 (query2, $4);
  1851.          /* query2 now retrieves the subquery within the
  1852.           * agg brackets.
  1853.           * this will be the agg node's outer child.
  1854.           */
  1855.  
  1856.           $$ = ParseAgg(CString($1), query2, varnode);
  1857.  
  1858.           /*paramlist = search_quals($4, aggnode);*/
  1859.           /*$$ = nappend1($$, $4);*/
  1860.           /* (rettype, "agg",aggname, query, tlist, -1) */
  1861.     }
  1862.  
  1863. res_target_list:
  1864.       res_target_list ',' res_target_el    
  1865.         { p_target = nappend1(p_target,$3); $$ = p_target; }
  1866.     | res_target_el             
  1867.         { p_target = lispCons ($1,LispNil); $$ = p_target;}
  1868.     | relation_name '.' ALL
  1869.         {
  1870.             LispValue temp = p_target;
  1871.             INC_NUM_LEVELS(1);
  1872.             if(temp == LispNil )
  1873.               p_target = ExpandAll((Name)CString($1), &p_last_resno);
  1874.             else {
  1875.               while (temp != LispNil && CDR(temp) != LispNil)
  1876.                 temp = CDR(temp);
  1877.               CDR(temp) = ExpandAll( (Name)CString($1), &p_last_resno);
  1878.             }
  1879.             $$ = p_target;
  1880.         }
  1881.     | res_target_list ',' relation_name '.' ALL
  1882.         {
  1883.             LispValue temp = p_target;
  1884.             if (ResdomNoIsAttrNo == true) {
  1885.               elog(WARN,"all doesn't make any sense here");
  1886.               return(1);
  1887.             }
  1888.             INC_NUM_LEVELS(1);
  1889.             if(temp == LispNil )
  1890.               p_target = ExpandAll((Name)CString($3), &p_last_resno);
  1891.             else {
  1892.               while(temp != LispNil && CDR(temp) != LispNil )
  1893.                 temp = CDR(temp);
  1894.               CDR(temp) = ExpandAll( (Name)CString($3), &p_last_resno);
  1895.             }
  1896.             $$ = p_target;
  1897.         }
  1898.     ;
  1899.  
  1900. res_target_el:
  1901.         Id '=' agg
  1902.     {
  1903.          int type_id;
  1904.          int resdomno,  type_len;
  1905.          List temp = LispNil;
  1906.  
  1907.          type_id = CInteger(CAR($3));
  1908.  
  1909.          if (ISCOMPLEX(type_id))
  1910.         elog(WARN,
  1911.            "Cannot assign complex type to variable %s in target list",
  1912.            CString($1));
  1913.  
  1914.          type_len = tlen(get_id_type(type_id));
  1915.          resdomno = p_last_resno++;
  1916.          temp = lispCons ((LispValue)MakeResdom((AttributeNumber)resdomno,
  1917.                      (ObjectId)type_id,
  1918.                      ISCOMPLEX(type_id),
  1919.                      (Size)type_len,
  1920.                      (Name)CString($1),
  1921.                      (Index)0, (OperatorTupleForm)0, 0) 
  1922.                   , lispCons(CDR($3), LispNil) );
  1923.         $$ = temp;
  1924.     }
  1925.  
  1926.     | Id '=' a_expr
  1927.       {
  1928.         if ($3 != LispNil && ISCOMPLEX(CInteger(CAR($3))))
  1929.             elog(WARN, "Cannot assign complex type to variable %s in target list", CString($1));
  1930.         $$ = make_targetlist_expr ($1,$3);
  1931.        } 
  1932.     | attr opt_indirection
  1933.              {
  1934.          LispValue varnode, temp;
  1935.          Resdom resnode;
  1936.          int type_id, type_len;
  1937.  
  1938.          temp = HandleNestedDots($1);
  1939.  
  1940.          if ($2 != LispNil)
  1941.              temp = make_array_ref(temp, $2);
  1942.  
  1943.          type_id = CInteger(CAR(temp));
  1944.          if (ISCOMPLEX(type_id))
  1945.              elog(WARN, "Cannot use complex type %s as atomic value in target list",
  1946.               tname(get_id_type(type_id)));
  1947.          type_len = tlen(get_id_type(type_id));
  1948.          resnode = MakeResdom ( (AttributeNumber)p_last_resno++ ,
  1949.                     (ObjectId)type_id, ISCOMPLEX(type_id),
  1950.                         (Size)type_len, 
  1951.                     (Name)CString(CAR(last ($1) )),
  1952.                     (Index)0 , (OperatorTupleForm)0,
  1953.                     0 );
  1954.          varnode = CDR(temp);
  1955.          $$=lispCons((LispValue)resnode, lispCons(varnode,LispNil));
  1956.         }
  1957.     ;         
  1958.  
  1959. opt_id:
  1960.     /*EMPTY*/        { NULLTREE }
  1961.     | Id
  1962.     ;
  1963.  
  1964. relation_name:
  1965.     SpecialRuleRelation
  1966.     | Id
  1967.       {
  1968.         /* disallow refs to magic system tables */
  1969.         if (strncmp(CString($1), Name_pg_log, 16) == 0
  1970.             || strncmp(CString($1), Name_pg_variable, 16) == 0
  1971.             || strncmp(CString($1), Name_pg_time, 16) == 0
  1972.             || strncmp(CString($1), Name_pg_magic, 16) == 0)
  1973.             elog(WARN, "%s cannot be accessed by users", CString($1));
  1974.         else
  1975.             $$ = $1;
  1976.       }
  1977.     ;
  1978.  
  1979. database_name:    Id    /*$$=$1*/;
  1980. access_method:         Id         /*$$=$1*/;
  1981. attr_name:         Id        /*$$=$1*/;
  1982. class:             Id        /*$$=$1*/;
  1983. index_name:         Id        /*$$=$1*/;
  1984. map_rel_name:        Id        /*$$=$1*/;
  1985. var_name:        Id        /*$$=$1*/;
  1986. name:            Id        /*$$-$1*/;
  1987. string:         Id        /*$$=$1 Sconst ?*/;
  1988.  
  1989. date:            Sconst        /*$$=$1*/;
  1990. file_name:        SCONST        {$$ = new_filestr($1); };
  1991. copy_file_name:
  1992.           SCONST        {$$ = new_filestr($1); };
  1993.     | STDIN                { $$ = lispString(CppAsString(stdin)); }
  1994.     | STDOUT            { $$ = lispString(CppAsString(stdout)); }
  1995.  /* adt_const:        Sconst        /*$$=$1*/;
  1996. attach_args:        Sconst        /*$$=$1*/;
  1997.             /* XXX should be converted by fmgr? */
  1998. AexprConst:
  1999.       Iconst            { $$ = make_const ( $1 ) ; 
  2000.                       Input_is_integer = true; }
  2001.     | FCONST            { $$ = make_const ( $1 ) ; }
  2002.     | CCONST            { $$ = make_const ( $1 ) ; }
  2003.     | Sconst             { $$ = make_const ( $1 ) ; 
  2004.                       Input_is_string = true; }
  2005.     | ParamNo            {
  2006.         $$ = lispCons(lispInteger(get_paramtype((Param)$1)),
  2007.                   $1 /* , -1 (kai: lispCons takes only 2 pars)) */);
  2008.         }
  2009.     | Pnull                 { $$ = LispNil; 
  2010.                       Typecast_ok = false; }
  2011.     ;
  2012.  
  2013. ParamNo: PARAM                {
  2014.         ObjectId toid;
  2015.         int paramno;
  2016.         
  2017.         paramno = CInteger($1);
  2018.         toid = param_type(paramno);
  2019.         if (!ObjectIdIsValid(toid)) {
  2020.         elog(WARN, "Parameter '$%d' is out of range",
  2021.              paramno);
  2022.         }
  2023.         $$ = (LispValue) MakeParam(PARAM_NUM, (AttributeNumber) paramno,
  2024.                        (Name)"<unnamed>", (ObjectId)toid,
  2025.                        (List) NULL);
  2026.       }
  2027.     ;
  2028.  
  2029. NumConst:
  2030.       Iconst            /*$$ = $1 */
  2031.     | FCONST             { $$ = yylval; }
  2032.     ;
  2033.  
  2034. Iconst:     ICONST            { $$ = yylval; }
  2035. Sconst:        SCONST            { $$ = yylval; }
  2036.  
  2037. Id:
  2038.     IDENT           { $$ = yylval; }
  2039.     ;
  2040.  
  2041. SpecialRuleRelation:
  2042.     CURRENT
  2043.         { 
  2044.             if (QueryIsRule)
  2045.               $$ = lispString("*CURRENT*");
  2046.             else 
  2047.               elog(WARN,"\"current\" used in non-rule query");
  2048.         }
  2049.     | NEW
  2050.         { 
  2051.             if (QueryIsRule)
  2052.               $$ = lispString("*NEW*");
  2053.             else 
  2054.               elog(WARN,"NEW used in non-rule query"); 
  2055.             
  2056.         }
  2057.     ;
  2058.  
  2059. Function:        FUNCTION    { $$ = yylval ; } ;
  2060. Aggregate:        AGGREGATE    { $$ = yylval ; } ;
  2061. Index:            INDEX        { $$ = yylval ; } ;
  2062. Indexable:        INDEXABLE    { $$ = yylval ; } ;
  2063. Key:            KEY        { $$ = yylval ; } ;
  2064. Nonulls:        NONULLS        { $$ = yylval ; } ;
  2065. Operator:        OPERATOR    { $$ = yylval ; } ;
  2066. Sort:            SORT        { $$ = yylval ; } ;
  2067. Type:            P_TYPE        { $$ = yylval ; } ;
  2068. Using:            USING        { $$ = yylval ; } ;
  2069. With:            WITH        { $$ = yylval ; } ;
  2070. Pnull:            PNULL        { $$ = yylval ; } ;
  2071.  
  2072. %%
  2073. parser_init(typev, nargs)
  2074.     ObjectId *typev;
  2075.     int nargs;
  2076. {
  2077.     NumLevels = 0;
  2078.     p_target = LispNil;
  2079.     p_qual = LispNil;
  2080.     p_root = LispNil;
  2081.     p_priority = lispInteger(0);
  2082.     p_ruleinfo = LispNil;
  2083.     p_rtable = LispNil;
  2084.     p_last_resno = 1;
  2085.     p_numlevels = 0;
  2086.     p_target_resnos = LispNil;
  2087.     ResdomNoIsAttrNo = false;
  2088.     QueryIsRule = false;
  2089.     Input_is_string = false;
  2090.     Input_is_integer = false;
  2091.     Typecast_ok = true;
  2092.  
  2093.     param_type_init(typev, nargs);
  2094. }
  2095.  
  2096.  
  2097. LispValue
  2098. make_targetlist_expr ( name , expr )
  2099.      LispValue name;
  2100.      LispValue expr;
  2101. {
  2102.     extern bool ResdomNoIsAttrNo;
  2103.     extern Relation parser_current_rel;
  2104.     int type_id,type_len, attrtype, attrlen;
  2105.     int resdomno;
  2106.     Relation rd;
  2107.  
  2108.     if(ResdomNoIsAttrNo && (expr == LispNil) && !Typecast_ok){
  2109.        /* expr is NULL, and the query is append or replace */
  2110.        /* append, replace work only on one relation,
  2111.           so multiple occurence of same resdomno is bogus */
  2112.        rd = parser_current_rel;
  2113.        Assert(rd != NULL);
  2114.        resdomno = varattno(rd,CString(name));
  2115.        attrtype = att_typeid(rd,resdomno);
  2116.        attrlen = tlen(get_id_type(attrtype));
  2117.        expr = lispCons( lispInteger(attrtype), (LispValue)
  2118.                 MakeConst((ObjectId) attrtype, (Size) attrlen, (Datum) LispNil, (bool)1, (bool) 0 /* ignored */));
  2119.        Input_is_string = false;
  2120.        Input_is_integer = false;
  2121.        Typecast_ok = true;
  2122.        if( lispAssoc( lispInteger(resdomno),p_target_resnos)
  2123.           != -1 ) {
  2124.            elog(WARN,"two or more occurence of same attr");
  2125.        } else {
  2126.            p_target_resnos = lispCons( lispInteger(resdomno),
  2127.                                      p_target_resnos);
  2128.        }
  2129.        return  ( lispCons ((LispValue)MakeResdom ((AttributeNumber)resdomno,
  2130.                        (ObjectId) attrtype,
  2131.                        ISCOMPLEX(attrtype),
  2132.                        (Size)attrlen ,
  2133.                        (Name)CString(name),
  2134.                        (Index) 0 ,
  2135.                        (OperatorTupleForm) 0 , 0 ) ,
  2136.                              lispCons((LispValue)CDR(expr),LispNil)) );
  2137.      }
  2138.  
  2139.     type_id = CInteger(CAR(expr));
  2140.     type_len = tlen(get_id_type(type_id));
  2141.     if (ResdomNoIsAttrNo) { /* append or replace query */
  2142.     /* append, replace work only on one relation,
  2143.        so multiple occurence of same resdomno is bogus */
  2144.     rd = parser_current_rel;
  2145.     Assert(rd != NULL);
  2146.     resdomno = varattno(rd,CString(name));
  2147.     attrtype = att_typeid(rd,resdomno);
  2148.     attrlen = tlen(get_id_type(attrtype)); 
  2149.  
  2150.     if(Input_is_string && Typecast_ok){
  2151.               Datum val;
  2152.               if (CInteger(CAR(expr)) == typeid(type("unknown"))){
  2153.                 val = textout((struct varlena *)get_constvalue((Const)CDR(expr)));
  2154.               }else{
  2155.                 val = get_constvalue((Const)CDR(expr));
  2156.               }
  2157.               CDR(expr) = (LispValue) MakeConst(attrtype, attrlen,
  2158.       (Datum)fmgr(typeid_get_retinfunc(attrtype),val,get_typelem(attrtype)),
  2159.                 false, true /*??? Maybe correct-- 80% chance */);
  2160.     } else if((Typecast_ok) && (attrtype != type_id)){
  2161.               CDR(expr) = (LispValue) 
  2162.             parser_typecast2 ( expr, get_id_type((long)attrtype));
  2163.     } else 
  2164.          if (attrtype != type_id)
  2165.         elog(WARN, "unequal type in tlist : %s \n", CString(name));
  2166.     Input_is_string = false;
  2167.     Input_is_integer = false;
  2168.         Typecast_ok = true;
  2169.  
  2170.     if( lispAssoc( lispInteger(resdomno),p_target_resnos) 
  2171.        != -1 ) {
  2172.         elog(WARN,"two or more occurence of same attr");
  2173.     } else {
  2174.         p_target_resnos = lispCons( lispInteger(resdomno),
  2175.                        p_target_resnos);
  2176.     }
  2177.     } else {
  2178.     resdomno = p_last_resno++;
  2179.     attrtype = type_id;
  2180.     attrlen = type_len;
  2181.     }
  2182.     return  ( lispCons ((LispValue)MakeResdom ((AttributeNumber)resdomno,
  2183.                     (ObjectId)  attrtype,
  2184.                     ISCOMPLEX(attrtype),
  2185.                     (Size)  attrlen , 
  2186.                     (Name)  CString(name), (Index)0 ,
  2187.                     (OperatorTupleForm)0 , 0 ) ,
  2188.                   lispCons(CDR(expr),LispNil)) );
  2189.     
  2190. }
  2191.