/*
_____       _    _    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.

*/
# ifndef stmtattr_h
# define stmtattr_h "$Id: stmtattr.h 5.1 2000/05/16 14:18:55 picoSoft Exp Marco $"

# include "pstring.h"
# include "plist.h"
# include "piteratr.h"
# include "attribut.h"
# include "odbcdate.h"
# include "blob.h"

class StmtRel;
class Condition;
class SearchIndex;
class SqlParser;

class StmtAttr : public PObject
{
friend class Condition;
friend class SearchIndex;
   PCLASS(StmtAttr, PObject)
   PString   Name;
   Attribute &Attr;
   char * Buffer;
   StmtRel * StmtParent;
   SearchIndex *   IndexPnt;
   PBool     LocalAttr;
   PBool     Null;
   toknum    aggregate;
   const DataBase &DB;
   void init(toknum bi, PBool la);
   friend PBool StringCompare (char *, int, toknum, char *, int, 
                               unsigned char *, unsigned char fill = ' ');
   friend PBool NumberCompare (StmtAttr * c1, toknum op, StmtAttr * c2);
   void CharToPackedOrdered (const char *in);
   char * PackedOrderedToChar (char *a, int size, int right);
   friend int TimeStampDiff (StmtAttr *a1, StmtAttr *a2);
   BlobField *bField;
   void allocBlobField();
public:
   void setBlobBlkNum (unsigned long blkNum);
   unsigned long getBlobBlkNum ();
public:
   StmtAttr (const DataBase &d, Attribute &a, StmtRel * sr, const PString *newName) :
             DB(d), Attr(a), StmtParent(sr) {
                             init (NULL_, PFalse);
                             if (newName)
                                Name = *newName;
                             else
                                Name = Attr.getName();
                          }
                          
   StmtAttr (StmtAttr &sa, const PString & n, StmtRel * sr, toknum bi = NULL_) :
             DB(sa.DB), Attr(*(sa.getAttr())), StmtParent(sr) {
                             init (bi, PFalse);
                             if (n.size() == 0)
                                Name = Attr.getName();
                             else
                                Name = n;
                             Buffer = sa.Buffer;
                           }
                           
   StmtAttr (StmtAttr &sa) :
             DB(sa.DB), Attr (*(new Attribute (*sa.getAttr()))),
             StmtParent (0) {
                               init (NULL_, PTrue);
                               Name = Attr.getName();
                               FromAttr(sa);
                           }
                           
   StmtAttr (const DataBase &d, const PString &s, StmtRel *sr) :
             DB(d), Attr (*(new Attribute (s, 0))),
             StmtParent (sr) {
                               init (NULL_, PTrue);
                               Name = Attr.getName();
                           }
   StmtAttr (const DataBase &d, const Token &t, toknum bi = NULL_) :
             DB(d), Attr(*(new Attribute(t))),
             StmtParent(0) {
                              init (bi, PTrue);
                              Name = Attr.getName();
                              FromToken (t);
                           }
                           
   StmtAttr (const DataBase &d, Attribute &a) :
             DB(d), Attr(*(new Attribute(a))),
             StmtParent(0) {
                              init (NULL_, PTrue);
                              Name = Attr.getName();
                           }                           
   ~StmtAttr ();
   PString & getName () { return Name; }
   void setName (const PString & n) { Name = n; }
   Attribute * getAttr() {if (this != 0)
                             return  &Attr;
                          else
                             return 0; }
   const DataBase  & getDB() { return DB; }                             
   void SetIndex (SearchIndex * i) { IndexPnt = i; }
   SearchIndex * GetIndex () { return IndexPnt; }
   void setAggregate (toknum bi) { aggregate = bi; }
   void allocBuffer();
   void deleteBuffer() {
      if (StmtParent == 0 && Buffer != (char *)0) {
         delete Buffer;
         Buffer = 0;
      }
   }
   //sj PBool IsExpression () { return Expression; }
   void setBuffer ();
   char * GetBuffer () { return Buffer; }
   PBool isAggregate () { return aggregate != NULL_; }
   toknum getAggregate () { return aggregate; }
   // void CalcBuiltIn (unsigned long l, StmtAttr *a);
   void Aggregate (unsigned long l, StmtAttr *a);
   StmtRel * GetStmtParent() { return StmtParent; }
   void SetStmtParent(StmtRel *sr) { StmtParent = sr; }
   PBool isNull();
   void setNull(PBool onoff) { Null=onoff; }
   void setNullBuffer();
   void setHighValueBuffer ();
   PBool Compare (StmtAttr *, toknum op, PBool checkOnly);
   int IndexCompare (StmtAttr *a);
   Error ToDouble (double & out, long & len);
   Error ToChar (char ** out, long & len);
   Error ToFloat (float & out, long & len);
   Error ToLong (long & out, long & len);
   Error ToULong (unsigned long & out, long & len);
   Error ToShort (short & out, long & len);
   Error ToUShort (unsigned short & out, long & len);
   Error ToTsChar (char **out, long & len);
   Error ToTimeStamp (TIMESTAMP_STRUCT *ts, long & len);
   PBool TimeStampCompare (StmtAttr *sa, toknum op);
   PBool couldBeTimeStamp () {
      if (Attr.getDateType() == T_TIMESTAMP)
         return PTrue;
      else {
         const char *fmt;
         if (Attr.GetType() == T_CSTRING &&
              StmtParent == 0 &&
              (fmt = isStringTimeStamp(Buffer, Attr.GetLen()))) {
            Attr.setDateFmt (fmt);
            return PTrue;
         } else
            return PFalse;
      }
   }
   Error FromTimeStamp (const TIMESTAMP_STRUCT *ts);
   Error FromTokenTs(const Token &t);
   Error FromDouble (double n);
   Error FromToken(const Token &t);
   Error FromAttr (StmtAttr &a);
   Error FromString (const char *s);
   Error setBlob (unsigned char * buf, unsigned long len) {
      Error Return = SQL_SUCCESS;
      if (bField != 0)
         bField->setBlob (buf, len);
      else
         Return = SQL_ERROR;
      return Return;
   }
   void setBlobField (BlobField *f) {
      bField = f;
   }
   BlobField * getBlob() {
      return bField;
   }
};

PLIST(StmtAttr);
PITERATOR(StmtAttr);

void CalcAggregate (toknum bi, double prec, double &calc,
                    unsigned long count);

# endif
