/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 Copyright (C) Picosoft s.r.l. 1995-2002

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
static char rcsid[] = "$Id: sortrel.cpp 5.1 2000/11/20 10:43:56 picoSoft Exp $";
# include "sqlpars.h"
# include "serchidx.h" 
# include "trace.h"

void
SqlParser::EvalOrder (StmtRel **allArray, StmtRel **buildArray,
                      StmtRel **bestArray, int idx, int relNum,
                      int &maxVal, int &maxLen)
{
   Condition *c;
   register int i, j;
   int val = 0;
   int len = 0;

   if (idx < relNum) {
      for (i = 0; i < relNum; i++) {
         buildArray[idx] = allArray[i];
         for (j = 0 ; j < idx; j++)
            if (buildArray[idx] == buildArray[j])
               break;
         if (j == idx)
            EvalOrder(allArray, buildArray, bestArray, idx + 1, relNum,
                      maxVal, maxLen);
      }
   } else {
      ConditionList &vc = WhereStack.GetValidCond();

      for (i = 0, len = 0; i < relNum && i == len; i++) {
         for (c = vc.GetFirst(); c != 0; c = vc.GetNext()) {
            if (c->left && c->right) {
               if (i == 0) {
                  len = i + 1;
                  if (c->left->getAttr()->getParent() ==
                                buildArray[i]->getRel() &&
                                c->right->getAttr()->getParent() == 0) {
                     if (c->left->getAttr()->IsIndexPart (1))
                        val = relNum - i + 1;
                     else
                        val = relNum - i;
                  } else if (c->right->getAttr()->getParent() ==
                                        buildArray[i]->getRel() &&
                                        c->left->getAttr()->getParent() == 0) {
                     if (c->right->getAttr()->IsIndexPart (1))
                        val = relNum - i + 1;
                     else
                        val = relNum - i;
                  }
               } else {
                  if (c->left->getAttr()->getParent() == 
                               buildArray[i]->getRel()) {
                     for (j = 0; j < i; j++) {
                        if (c->right->getAttr()->getParent() ==
                                      buildArray[j]->getRel()) {
                           len = i + 1;
                           if (c->left->getAttr()->IsIndexPart (1))
                              val += relNum - i + 1;
                           else
                              val += relNum - i;
                           break;
                        }
                     }
                  } else if (c->right->getAttr()->getParent() ==
                                        buildArray[i]->getRel()) {
                     for (j = 0; j < i; j++) {
                        if (c->left->getAttr()->getParent() ==
                                      buildArray[j]->getRel()) {
                           len = i + 1;
                           if (c->right->getAttr()->IsIndexPart (1))
                              val += relNum - i + 1;
                           else
                              val += relNum - i;
                           break;
                        }
                     }
                  }
               }
            }
         }
      }
      if (len >= maxLen && val > maxVal) {
         for (i = 0; i < relNum; i++)
            bestArray[i] = buildArray[i];
         maxLen = len;
         maxVal = val;
      }
   }
}

void
SqlParser::SortRelation (StmtRelList &rl)
{

   StmtRel *r;
   register int i, j;
   int maxLen;
   int maxVal;
   int relNum = (int)(rl.GetItemNum());
   ConditionList &vc = WhereStack.GetValidCond();

   if (relNum == 1)
      return;
   StmtRel **allArray = new StmtRel *[relNum];
   StmtRel **buildArray = new StmtRel *[relNum];
   StmtRel **bestArray = new StmtRel *[relNum];


   for (i = 0, r = rl.GetFirst(); r != 0; r = rl.DeleteCurrent(), i++)
      allArray[i] = r;

   maxVal = 0;
   maxLen = 0;
   EvalOrder (allArray, buildArray, bestArray, 0, relNum, maxVal, maxLen);

   if (maxLen < relNum) {
      for (i = 0; i < relNum; i++) {
         for (j = 0; j < maxLen; j++)
            if (bestArray[j] == allArray[i])
               break;
         if (j == maxLen)
            bestArray[maxLen++] = allArray[i];
      }
   }

   for (i = 0; i < relNum; i++)
      rl.AddItem (bestArray[i]);

   delete buildArray;
   delete bestArray;
   delete allArray;
   
   if (Trace.isSet)
      for (r = rl.GetFirst(), i = 0; r != 0; r = rl.GetNext(), i++)
         Trace.Write ("--->SortRel[%d] maxLen=%d, maxVal=%d tab=%s\n",
                       i, maxLen, maxVal, r->getRel()->getName().gets());
}

