groupby.k
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:20k
源码类别:

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  * groupby.c  -   'group by' transformation  
  3.  *
  4.  * This file is a part of GNU SQL Server
  5.  *
  6.  * Copyright (c) 1996, 1997, Free Software Foundation, Inc
  7.  * Developed at the Institute of System Programming
  8.  * This file is written by Michael Kimelman.
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  *
  24.  * Contacts: gss@ispras.ru
  25.  *
  26.  */
  27. /* $Id: groupby.k,v 1.248 1997/04/24 18:41:28 kml Exp $ */
  28. #include "cycler.h"
  29. #include "opt.h"
  30. #include "cnf.h"
  31. #include "tree_gen.h"
  32. #include "tassert.h"
  33. #include <assert.h>
  34. /*
  35.   step in - save from in stack 
  36.   check where for correctness
  37.   save group_by list
  38.   check having and selection (if there are any aggregate function appliable
  39.                               to this level)
  40.   if MGoperation requred, create 3 lists (selection list for inner scan,
  41.   upper query scan column list and list of MAKEGROUP operation - 
  42.   [col0, col1, Avg(col2), Max(col2)... ] )
  43.     
  44.   from: 
  45.     DR- store context in stack and put 'selection' behind 'having';
  46.     RL - clear stack, generate 2-level query with makegroup (if needed) and replace
  47.          selection to the original place;
  48.   where,having,selection:
  49.     LD - set subtree_code;
  50.     DR - clear subtree_code
  51.   group by: move subtree to inner selection list & create sort list 
  52.   Aggregate functions: 
  53.     LD - set flag af+ ;
  54.     DR - clear flag af-, and replace node by colptr of tmp table
  55.   colptr - check for availability (!single column in having) and if af+ check for
  56.   one level columns in agr_func. columns from group by replaced by new colptrs
  57. */
  58. #define COL_N(c) XLNG_TRN(c,0)
  59. typedef struct {
  60.   enum token   query_code;
  61.   enum token   subtree_code;
  62.   i4_t          is_col_in_selection;
  63.   i4_t          one_row_groups;
  64.   TXTREF       sort_list; 
  65.   TXTREF       scol_list;
  66.   TXTREF       from;
  67.   TXTREF       selection;
  68.   TXTREF       into;      /* specially for SELECT statement */
  69.   TXTREF       where;
  70.   TXTREF       group_by;
  71.   TXTREF       having;
  72. } query_level_t;
  73.  
  74. DECL_STACK(gb,query_level_t); /* ';' added to make indent & emacs happy */
  75. /* the following two routines was wriiten to use from debugger */
  76.      
  77. static void
  78.      debug_frame(query_level_t *t)
  79. {
  80. #define F         fprintf
  81. #define E         STDERR
  82. #define BRANCH(v) F(E,"n%s:",#v)
  83.   BRANCH(subtree_code);        F(E,"%sn",NAME(t->subtree_code)); 
  84.   BRANCH(is_col_in_selection); F(E,"%dn",t->is_col_in_selection);
  85.   BRANCH(one_row_groups     ); F(E,"%dn",t->one_row_groups     );
  86.   BRANCH(sort_list);           debug_trn(t->sort_list);
  87.   BRANCH(scol_list);           debug_trn(t->scol_list);
  88.   BRANCH(from);                debug_trn(t->from);
  89.   BRANCH(selection);           debug_trn(t->selection);
  90.   BRANCH(where);               debug_trn(t->where);
  91.   BRANCH(group_by);            debug_trn(t->group_by);
  92.   BRANCH(having);              debug_trn(t->having);
  93. #undef F
  94. #undef E
  95. #undef BRANCH
  96. }
  97. void
  98. debug_gb_stack(i4_t i)
  99. {
  100.   i4_t depth;
  101.   query_level_t *st_frame;
  102.   
  103.   for(depth=0;depth < st_depth(gb_stack) && depth < i ;depth++)
  104.     {
  105.       fprintf(STDERR,
  106.               "---------------------------%d-%d-%d-%d-------------n",
  107.               depth,depth,depth,depth);
  108.       st_frame=SPTR(gb,depth);
  109.       debug_frame(st_frame);
  110.     }
  111. }
  112. static query_level_t *
  113. find_frame(TXTREF colptr)
  114. {
  115.   i4_t depth;
  116.   query_level_t *st_frame;
  117.   TXTREF scan = TNULL,ctblptr,t;
  118.   switch(CODE_TRN(colptr))
  119.     {
  120.     case COLPTR:
  121.       t = OBJ_DESC(colptr);
  122.       TASSERT(CODE_TRN(t)==SCOLUMN,colptr);
  123.       scan = COL_TBL(t); /* pointer to scan */
  124.       break;
  125.     case TBLPTR:
  126.       scan = TABL_DESC(colptr);
  127.       break;
  128.     default:
  129.       debug_trn(colptr);
  130.       yyfatal("Unexpected node in find_frame");
  131.     }
  132.   TASSERT(CODE_TRN(scan)==SCAN,colptr);
  133.   for(depth=0;depth < st_depth(gb_stack);depth++)
  134.     {
  135.       st_frame=SPTR(gb,depth);
  136.       for( ctblptr = DOWN_TRN(st_frame->from);
  137.            ctblptr;
  138.    ctblptr = RIGHT_TRN(ctblptr))
  139.         if (TABL_DESC(ctblptr) == scan)
  140.   return st_frame;
  141.     }
  142.   debug_trn(colptr);
  143.   yyfatal("Can't find given column in the frame list...");
  144.   return NULL;
  145. }
  146. static int
  147. is_unique(TXTREF clist)
  148. {
  149.   TXTREF tbl;
  150.   TXTREF ind,col,scan;
  151.   
  152.   TASSERT (CODE_TRN(clist)==COLPTR,clist);
  153.   /*     scan    scolumn  colptr */
  154.   scan = COL_TBL(OBJ_DESC(clist));
  155.   tbl  = COR_TBL(scan);
  156.   switch(CODE_TRN(tbl))
  157.     {
  158.     case TABLE:
  159.       ind=IND_INFO(tbl);
  160.       break;
  161.     case TMPTABLE:
  162.     case SCAN:
  163.     default:
  164.       return 0;
  165.     }
  166.   
  167.   while(ind)
  168.     {
  169.       if (CODE_TRN(ind)==UNIQUE || CODE_TRN(ind)==PRIMARY)
  170.         {
  171.           TXTREF clm;
  172.           TASSERT(ARITY_TRN(ind) > 0 && DOWN_TRN(ind) != TNULL, ind);
  173.           for (clm = DOWN_TRN(ind); clm ; clm = RIGHT_TRN(clm))
  174.             {
  175.               i4_t    id = COL_NO(OBJ_DESC(clm));
  176.               for (col = clist; col ; col = RIGHT_TRN(col))
  177.                 {
  178.                   TXTREF scol = OBJ_DESC(col);
  179.                   if ( COL_NO(scol) == id && COL_TBL(scol) == scan )
  180.                     break;
  181.                 }
  182.               if (!col) /* if not found */
  183.                 break;
  184.             }
  185.           if (!clm) /* unique key found for given list */
  186.             return 1;
  187.         }
  188.       ind = RIGHT_TRN(ind);
  189.     }
  190.   return 0;
  191. }
  192. #define FOR(link_name,cnt) if(!frame->link_name) 
  193.   frame->link_name = gen_node(NOOP); 
  194.   for(cnt=0,cptr=DOWN_TRN(frame->link_name);cptr;cptr=RIGHT_TRN(cptr),cnt++)
  195. #define CHECK_ERROR(msg) if(!cptr) { 
  196.   /*debug_trn(colptr);*/ yyfatal(msg); return TNULL;}
  197. static TXTREF 
  198. replace_function (TXTREF func  ,query_level_t *frame  ) 
  199. {
  200.   TXTREF cptr;
  201.   i4_t    counter,cno,dummy_cntr,count_all=0;
  202.   
  203.   TASSERT(Is_Function(func),func);
  204.   if (TstF_TRN(func,DISTINCT_F) && is_unique(DOWN_TRN(func)))
  205.     {
  206.       ClrF_TRN(func,DISTINCT_F);
  207.       if (CODE_TRN(func)==COUNT)
  208.         {
  209.           free_tree(DOWN_TRN(func));
  210.           ARITY_TRN(func) = 0;
  211.           DOWN_TRN(func) = TNULL;
  212.         }
  213.     }
  214.   
  215.   cptr = DOWN_TRN(func);
  216.   if (frame->one_row_groups==1) /* if we have a fictive selctions */
  217.     {
  218.       if (CODE_TRN(func)==COUNT)
  219.         cptr = #(Const "1" Int[10,0] Int[10,0] ) ;
  220.       else
  221.         cptr = DOWN_TRN(func);
  222.       free_node(func);
  223.       return cptr;
  224.     }
  225.   if(!cptr)
  226.     {
  227.       /* It looks to be 'count(*)' */
  228.       TASSERT(CODE_TRN(func)==COUNT && !TstF_TRN(func,DISTINCT_F),func);
  229.       if(!frame->group_by)
  230.         frame->group_by = gen_node(NOOP);
  231.       count_all = 1;
  232.       counter = 0;
  233.     }
  234.   else
  235.     {
  236.       FOR(group_by,counter)
  237. if(trn_equal_p(cptr,DOWN_TRN(func)))
  238.   break;
  239.       if(!cptr)
  240. {
  241.           TASSERT(RIGHT_TRN(DOWN_TRN(func))==TNULL,func);
  242.   add_child(frame->group_by,DOWN_TRN(func));
  243.           SetF_TRN(DOWN_TRN(func),EXACT_F);
  244. }
  245.     }
  246.   FOR(sort_list,cno)
  247.     if(CODE_TRN(cptr)==CODE_TRN(func) && MASK_TRN(cptr)==MASK_TRN(func) &&
  248.        ( count_all == 1 || COL_N(DOWN_TRN(cptr))==counter) )
  249.       break;
  250.   if(!cptr)
  251.     {
  252.       DOWN_TRN(func) = #(Col <counter> ) ;
  253.       RIGHT_TRN(func) = TNULL;
  254.       ARITY_TRN(func) = 1;
  255.       add_child(frame->sort_list,func);
  256.       cno++;
  257.     }
  258.   FOR(scol_list,dummy_cntr)
  259.     if(COL_NO(cptr)==cno /* || dummy_cntr==cno */ )
  260.       break;
  261.   if(!cptr)
  262.     {
  263.       char nm[100];
  264.       sprintf(nm,"%s_%d",NAME(CODE_TRN(func)),counter);
  265.       cptr =  #(SColumn <ltr_rec(nm)> <dummy_cntr> <OPRN_TYPE(func)> ) ;
  266.       add_child(frame->scol_list,cptr);
  267.       cno++;
  268.     }
  269.   return #(ColPtr <cptr> ) ;
  270. }
  271. static TXTREF 
  272. replace_clmn     (TXTREF colptr,query_level_t *frame) 
  273. {
  274.   TXTREF cptr;
  275.   i4_t    counter,cno;
  276.   char   msg[100],cn[100];
  277.   if (frame->one_row_groups==1) /* if we have a fictive grouping */
  278.     return colptr;
  279.   cptr = COR_TBL(COL_TBL(OBJ_DESC(colptr)));
  280.   sprintf(cn,"%s", STRING(COL_NAME(OBJ_DESC(colptr))));
  281.   sprintf(msg,"column '%s' isn't in `group by' clause",cn);
  282.   
  283.   FOR(group_by,counter) /* check column in group by list - selection clause
  284.    of inner query */
  285.     if(trn_equal_p(cptr,colptr))
  286.       break;
  287.   
  288.   CHECK_ERROR(msg);
  289.   if (TstF_TRN(cptr,EXACT_F))
  290.     yyfatal(msg);
  291.   FOR(sort_list,cno)    /* find reference to this column in sort list */
  292.     if(CODE_TRN(cptr)==COL && COL_N(cptr)==counter)
  293.       break;
  294.   CHECK_ERROR(msg);
  295.   FOR(scol_list,counter) /* find column of sorted scan */
  296.     if(COL_NO(cptr)==cno /* || counter==cno */ )
  297.       break;
  298.   CHECK_ERROR("Internal error: sort list and scan column list mismatch");
  299.   OBJ_DESC(colptr)=cptr;
  300.   return colptr;
  301. }
  302. static void
  303. process_gb_clmn  (TXTREF group_by,query_level_t *frame) 
  304. {
  305.   i4_t     counter;
  306.   TXTREF  cptr;
  307.   /* add new node in sort list and add column in scol_list */
  308.   TASSERT(CODE_TRN(group_by) == GROUP,group_by);
  309.   if (ARITY_TRN(frame->from)==1 && is_unique(DOWN_TRN(group_by)))  
  310.     { /* if we'll got just 1 row after selection */
  311.       frame->one_row_groups=1; /* if we have a fictive grouping */
  312.       return;
  313.     }
  314.   
  315.   FOR(group_by,counter)
  316.     {
  317.       TXTREF newscol,col=OBJ_DESC(cptr);
  318.       TASSERT(CODE_TRN(col)==SCOLUMN,group_by);
  319.       
  320.       COPY_NODE(SCOLUMN,col,newscol);
  321.       COL_TBL(newscol)=TNULL;
  322.       COL_NO(newscol)=counter;
  323.       COL_DEFAULT(newscol) = copy_tree(COL_DEFAULT(newscol));
  324.       
  325.       col = #(Col <counter>);
  326.       
  327.       if (!frame->scol_list)
  328.         frame->scol_list = gen_node(NOOP);
  329.       if (!frame->sort_list)
  330.         frame->sort_list = gen_node(NOOP);
  331.       
  332.       add_child(frame->scol_list,newscol);
  333.       add_child(frame->sort_list,col);
  334.     }
  335. }
  336. /*
  337.  * the extract_regular_query forms reqular query from query
  338.  * with group by when group by condition leds to only one row
  339.  * groups
  340.  */
  341. static TXTREF 
  342. extract_regular_query   (TXTREF query,query_level_t *frame)
  343. {
  344.   TXTREF Op[4];
  345.   i4_t    kitty_lcc; /* it looks to be need by (Run "..." ) */
  346.   TASSERT(frame->sort_list==TNULL,query);
  347.   Op[0] = query;
  348.   free_tree(frame->group_by);  /* erase fictive group list */
  349.   if (!frame->having)
  350.     Op[1] = frame->where;
  351.   else if (!frame->where)
  352.     {
  353.       Op[1] = frame->having;
  354.       CODE_TRN(Op[1]) = WHERE;
  355.     }
  356.   else
  357.     {
  358.       TASSERT(frame->having && frame->where,query);
  359.       Op[1] = #(Where { /* join condition in where & having */
  360.                  (Run "nested_assotiative"  
  361.                    (And {
  362.                      (DOWN (C_code "frame->where "))
  363.                      (DOWN (C_code "frame->having"))
  364.                    })
  365.                  )
  366.                });
  367.       free_node(frame->where);
  368.       free_node(frame->having);
  369.     }
  370.    
  371. # (Op:0 {
  372.      (C_code "frame->from" )
  373.      (C_code "frame->selection")
  374.      (Op:1)
  375.   }) ;
  376.     
  377.   return query;
  378. }
  379. static TXTREF 
  380. make_groupped_tbl       (TXTREF query,query_level_t *frame) 
  381. {
  382.   TXTREF t,s, iq, cptr;
  383.   i4_t    i,j;
  384.   enum token q_code;
  385.   
  386.   q_code = CODE_TRN(query);
  387.   TASSERT( q_code == QUERY ||
  388.            q_code == SELECT ||
  389.            q_code == SUBQUERY, query);
  390.   TASSERT( DOWN_TRN(query) == frame->from, query);
  391.   
  392.   TASSERT(frame->one_row_groups!=1,query);/*we don't have fictive grouping*/
  393.     
  394.   if (ARITY_TRN(frame->group_by)==0)  /* select count(*) from ..... */
  395.     {
  396.       TXTREF scan = TABL_DESC(DOWN_TRN(frame->from));
  397.       if (COR_COLUMNS(scan) == TNULL) /* if (select count(*) from table) */
  398.         add_column(scan,COL_NAME(TBL_COLS(COR_TBL(scan))));
  399.       DOWN_TRN(frame->group_by) = #(ColPtr (C_code "COR_COLUMNS(scan)"));
  400.       ARITY_TRN(frame->group_by) =1;
  401.     }
  402.   CODE_TRN(frame->group_by) = SELECTION;
  403.   FOR(group_by,i)
  404.     {
  405.       TASSERT(CODE_TRN(cptr)==COLPTR,cptr);
  406.       ClrF_TRN(cptr,EXACT_F);
  407.     }
  408.   if(frame->having)
  409.     CODE_TRN(frame->having) = WHERE;
  410.   iq =  
  411. #    (Query {  
  412.        (C_code "frame->from" )
  413.        (C_code "frame->group_by")
  414.        (C_code "frame->where")   
  415.      } )
  416.     ;
  417.   /* 'iq' points to inner query now */
  418.   t = DOWN_TRN(frame->group_by);
  419.   s = #(MakeGroup [] <make_scan(t,iq)> );
  420.   {
  421.     TXTREF t2,t1,v = gen_vect(ARITY_TRN(frame->scol_list));
  422.     TASSERT(ARITY_TRN(frame->scol_list) == ARITY_TRN(frame->sort_list),
  423.             frame->sort_list);
  424.     for(j=0,t1 = DOWN_TRN(frame->sort_list);t1;t1=t2,j++)
  425.       {
  426.         t2 = RIGHT_TRN(t1);
  427.         RIGHT_TRN(t1) = TNULL;
  428.         VOP(v,j).txtp = t1;
  429.       }
  430.     XVEC_TRN(s,0) = v;
  431.     free_node(frame->sort_list);
  432.     frame->sort_list = TNULL;
  433.   }
  434.   
  435.   t = gen_node(TMPTABLE);
  436.   VIEW_QUERY(t) = s;
  437.   add_info(t);
  438.   
  439.   {
  440.     char str[100];
  441.     s = #(Scan "" <-1> <t> );
  442.     add_info(s);                    /* Scan     */
  443.     sprintf(str,"gb_scan_%s_%s_%d",STRING(TBL_FNAME(t)),
  444.             STRING(TBL_NAME(t)),COR_NO(s));
  445.     COR_NAME(s) = ltr_rec(str);
  446.   }
  447.   for(i=0,t=DOWN_TRN(frame->scol_list);t;i++,t = RIGHT_TRN(t))
  448.     {
  449.       TXTREF t1;
  450.       
  451.       TASSERT(CODE_TRN(t) == SCOLUMN,t);
  452.       
  453.       COPY_NODE(COLUMN,t,t1);
  454.       COL_TBL(t1) = COR_TBL(s);
  455.       COL_TBL(t) = s;
  456.       COL_DEFAULT(t1) = copy_tree(COL_DEFAULT(t1));
  457.       
  458.       TASSERT(CODE_TRN(t1) == COLUMN,t1);
  459.       add_info(t1);  /* add tmptable column */
  460.       TASSERT(CODE_TRN(t1) == COLUMN,t1);
  461.     }
  462.   COR_COLUMNS(s) = DOWN_TRN(frame->scol_list);
  463.   t = COR_TBL(s);
  464.   TASSERT(TBL_NCOLS(t) == i,t);
  465.   TASSERT(ARITY_TRN(frame->scol_list) == i,frame->scol_list);
  466.   free_node(frame->scol_list);
  467.   frame->scol_list = TNULL;
  468.   SetF_TRN(t,CHECKED_F);
  469.   
  470.   {
  471.     TXTREF Op[1];
  472.     Op[0] = query;
  473. #   (Op:0 {
  474.       (From { (TblPtr (C_code "s")  ) } )
  475.       (C_code "frame->selection")
  476.       (C_code "frame->having")
  477.     } )
  478.       ;
  479.   }
  480.   if(TstF_TRN(query,HAVING_F))
  481.     {
  482.       SetF_TRN(query,WHERE_F);
  483.       ClrF_TRN(query,HAVING_F);
  484.     }
  485.   ClrF_TRN(query,GROUP_F);
  486.     
  487.   return query;
  488. }
  489. static void
  490. fix_into_subtree(TXTREF select,query_level_t *frame)
  491. {
  492.   TXTREF p,s;
  493. #define T(n) *node_type(n)
  494.   
  495.   TASSERT(frame->query_code==SELECT,select); 
  496.   
  497.   for ( p = DOWN_TRN(frame->into),s = DOWN_TRN(frame->selection);
  498.         p && s;
  499.         p = RIGHT_TRN(p), s = RIGHT_TRN(s))
  500.     {
  501.       TASSERT(CODE_TRN(p)==PARMPTR,frame->into);
  502.       if ( (T(p)).code == SQLType_0 )
  503.         T(p) = T(s);
  504.       else if (!is_casted(T(s),T(p)))
  505.         {
  506.           file_pos = LOCATION_TRN(p);
  507.           lperror("Parameter '%s' and selected expressions types mismatch",
  508.                   STRING(PAR_NAME(OBJ_DESC(p))));
  509.         }
  510.       adjust_parameter(p,s);
  511.           
  512.     }
  513.   if (p||s)
  514.     yyerror("there are different number of elements in 'selection' "
  515.             "and 'into' lists of SELECT statement");
  516.   /*  into      selection from     SELECT  */
  517.   p = RIGHT_TRN(s=RIGHT_TRN(DOWN_TRN(select)));
  518.   if (p && CODE_TRN(p)==INTO)
  519.     {
  520.       RIGHT_TRN(s) = RIGHT_TRN(p);
  521.       ARITY_TRN(select) --;
  522.     }
  523.   free_tree(frame->into);
  524. #undef T
  525. }
  526. #(Rule:static "upd_query"
  527.   (Query {
  528.     (From { (TblPtr (Scan:0)) })
  529.     --
  530.   } )  
  531.   "CODE_TRN(COR_TBL(Op[0]))==TABLE"
  532.   {}
  533. )
  534. static TXTREF
  535. skip_node(TXTREF n)
  536. {
  537.   free_tree(n);
  538.   return gen_node(NOOP);
  539. }
  540. #define LD (flag==CYCLER_LD)
  541. #define DR (flag==CYCLER_DR)
  542. #define RL (flag==CYCLER_RL)
  543. #define SUBTREE(branch)     
  544. if (gb_stack)           
  545. {    
  546.   cf=SPTR(gb,0);   
  547.   cf->subtree_code = (LD) ? CODE_TRN(node) : UNKNOWN ;   
  548.   if(LD) cf->branch = node;   
  549. }
  550. #define CLEAR(v) bzero(&v,sizeof(v))
  551. TXTREF 
  552. group_by_proc(TXTREF node,i4_t flag)
  553. {
  554.   
  555.   query_level_t *cf = NULL;
  556.   static i4_t            inside_function = 0;
  557.   static query_level_t *func_frame      = NULL;
  558. #if 0
  559.   fprintf(STDERR,"group_by:%s:%s:n:",NAME(CODE_TRN(node)),
  560.           (LD?"LD":(DR?"DR":(RL?"RL":"**"))));
  561. #endif
  562.   
  563.   switch(CODE_TRN(node))
  564.     {
  565.     case SELECT:
  566.     case QUERY:
  567.     case SUBQUERY:
  568.       if(LD)
  569. {
  570.   query_level_t frame;
  571.   CLEAR(frame);
  572.           frame.query_code = CODE_TRN(node);
  573.   PUSHS(gb,frame);
  574. }
  575.       else if(DR)
  576. {
  577.   query_level_t frame;
  578.           i4_t           distinct = TstF_TRN(node,DISTINCT_F);
  579.   POPS(gb,frame);
  580.   if(frame.scol_list == TNULL)
  581.             {
  582.               i4_t is_simple = 0;
  583.               if (frame.one_row_groups==1) /* if we have a fictive grouping */
  584.                 node = extract_regular_query(node,&frame);
  585.               rule_upd_query(&is_simple,node);
  586.               if (!is_simple)
  587.                 SetF_TRN(node,RO_F);
  588.             }
  589.           else
  590.             {
  591.               /* here we need to construct 2-level query with 
  592.                * makegroup operation
  593.                */
  594.               if (distinct)
  595.                 ClrF_TRN(node,DISTINCT_F);
  596.               node = make_groupped_tbl (node,&frame);
  597.               if (distinct)
  598.                 SetF_TRN(node,DISTINCT_F);
  599.               SetF_TRN(node,RO_F);
  600.             }
  601.           if (CODE_TRN(node) == SELECT)
  602.             fix_into_subtree(node,&frame);
  603. }
  604.       break;
  605.     case INTO:
  606.       SUBTREE(into);
  607.       if(gb_stack)
  608.         {
  609.           TASSERT(cf->query_code==SELECT,node);
  610.         }
  611.       break;
  612.     case FROM:
  613.       SUBTREE(from);
  614.       break;
  615.     case WHERE:
  616.       SUBTREE(where);
  617.       break;
  618.     case GROUP:
  619.       SUBTREE(group_by);
  620.       if(DR)
  621.         process_gb_clmn(node,cf);
  622.       break;
  623.     case HAVING:
  624.       SUBTREE(having);
  625.       break;
  626.     case SELECTION:   /* these subtrees must be processed after */
  627.     case RESULT:      /* group by and having                    */
  628.       if (RL)
  629.         {
  630.           extern TXTREF transformer __P((TXTREF in, i4_t f));
  631.           flag = CYCLER_LD;    /* left-2-down pass simulation */
  632.           SUBTREE(selection);
  633.           DOWN_TRN(node) = transformer(DOWN_TRN(node),0);
  634.           flag = CYCLER_RL;    /* recover pass info */
  635.           SUBTREE(selection);
  636.         }
  637.       else
  638.         cycler_skip_subtree = 1;
  639.       break;
  640.     case TBLPTR:
  641.       if (gb_stack && DR)
  642.         {
  643.           TXTREF tbl;
  644.           cf = find_frame(node);
  645.           tbl = COR_TBL(TABL_DESC(node));
  646.           /* do something smart */
  647.         }
  648.       break;
  649.     case COLPTR:
  650.       if (DR && gb_stack)
  651. {
  652.   cf = find_frame(node);
  653.   if (inside_function)
  654.     {
  655.       if (func_frame == NULL)
  656. func_frame = cf;
  657.       else if (func_frame !=  cf)
  658. yyerror("Aggregate function applied to incorrect expression");
  659.     }
  660.   else
  661.     {
  662.       switch(cf->subtree_code)
  663. {
  664. case FROM:
  665.                   file_pos = LOCATION_TRN(node);
  666.   yyfatal("using of columns isn't allowed in 'from' clause");
  667. case WHERE: /* do nothing - it's already ok */
  668.   break;
  669. case GROUP: /* we'll process them later */
  670.   break;
  671. case SELECTION:
  672. case RESULT:
  673.   if (cf->group_by==TNULL)
  674.     {
  675.       cf->is_col_in_selection = 1;
  676.       break;
  677.     }
  678. case HAVING:
  679.   node = replace_clmn(node,cf);
  680.   break;
  681. default:
  682.   yyfatal("Internal error: "
  683.                           "Column found in unexpected clause of query ");
  684. }
  685.     }
  686. }
  687.       break;
  688.     default: 
  689.       if (Is_Function(node))
  690. {
  691.           if(!gb_stack)
  692.             {
  693.               yyerror("illegal usage of aggregate function not in SELECT frame");
  694.               return skip_node(node);
  695.             }
  696.   if (LD)
  697.     {
  698.       assert(inside_function==0);
  699.       inside_function = 1;
  700.       func_frame = NULL;
  701.     }
  702.   else if (DR)
  703.     {
  704.       inside_function = 0;
  705.               if(!func_frame)
  706.                 func_frame = SPTR(gb,0);
  707.       switch(func_frame->subtree_code)
  708.         {
  709.                 case WHERE: 
  710.                   yyerror("illegal usage of aggregate function in "
  711.                           "WHERE clause");
  712.                   return skip_node(node);
  713.                   break;
  714.                 case SELECTION:
  715.                   if (func_frame->is_col_in_selection)
  716.                     {
  717.                       if (func_frame->is_col_in_selection==1)
  718.                         yyerror("Illegal usage both aggregate function"
  719.                                 " and columns in SELECT");
  720.                       func_frame->is_col_in_selection++;
  721.                       return skip_node(node);
  722.                     }
  723.                   break;
  724.                 default: break;
  725.                 }
  726.       node = replace_function(node,func_frame);
  727.       func_frame = NULL;
  728.     }
  729.         }
  730.     }
  731.   return node;
  732. }