/*
_____       _    _    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 sqlpars_h
# define sqlpars_h "$Id: sqlpars.h 5.2 2000/11/20 10:17:48 picoSoft Exp Marco $"

# include "lex.h"
# include "database.h"
# include "token.h"
# include "dberror.h"
# include "conditn.h"
# include "stmtrel.h" 
# include "stmtrlvw.h" 
# include "stmtattr.h"
# include "cfield.h"
# include "where.h"
# include "express.h"
 
typedef struct s_token
{
   char * word;
   toknum token;
} fix_token;

class ODBCString;
class Join;
 
class SqlParser : public PObject
{
   PCLASS(SqlParser, PObject)
friend class Join;
friend class DataBase;
   toknum        Command;
   StmtRelList   FromList;
   StmtRelViewList ViewList;
   ExpressionList Selected;
   StmtAttrList  Fields;
   CFieldList    Params;
   int nParams;
   OrderItemCopyList OrderList;
   PBool isSortDesc;
   OrderItemCopyList *GroupList;
   Where         WhereStack;
   Where         HavingStack;
   StmtAttrList  Info;
   CFieldList    BindFields;
   DataBase *DB;
   PBool Parsed;
   PBool forUpdate;
   PString explicitJoin;

   StmtRel LocalView;
   StmtRel &View;
   StmtRel *GroupByView;
   SqlParser *insertQuery;
   SqlParser *subQueryOf;
   StmtRel *pUpdStmtRel;
   SqlParserList unions;
   unsigned long Processed;
   unsigned long MaxRows;
   unsigned long Limit;
   unsigned long Offset;
   unsigned long Fetched;
   unsigned long rowSetSize;
   enum eDirection {
      NEXT,
      PREV,
      FIRST,
      LAST
   } Direction;
   time_t currentTimestamp;
   char *sqlCmd;
   PString cursorName;
   
   Attribute *AttrDefinition (Lex &l,  Token *t);
   Error CreateTable (Lex &l);
   Error ExecCreateTable ();
   Error primaryKey (AttributeList &al, Lex &l, PStringList &pk);
   Error CreateRelation (Lex &l, Token *t, PStringList &pk);
   Error CreateIndex (Lex &l, PBool unique);
   Error ExecCreateIndex ();
   Error DropTable (Lex &l);
   Error ExecDropTable ();
   Error DropIndex (Lex &l);
   Error ExecDropIndex ();
   Error DropView (Lex &l);
   Error ExecDropView ();
   Error Select (Lex &l);
   Error ExecSelect ();
   Error Insert (Lex &l);
   Error ExecInsert ();
   Error Update (Lex &l);
   Error ExecUpdate ();
   Error Delete (Lex &l);
   Error ExecDelete ();
   Error Create (Lex &l);
   Error CreateView (Lex &l);
   Error ExecCreateView ();
   Error doCreateView (PBool checkOption);
   Error AlterTable (Lex &l);
   Error AlterTableAdd (Lex &l, StmtRel *sr);
   Error AlterTableDrop (Lex &l, StmtRel *sr);
   Error AlterTableRename (Lex &l, StmtRel *sr);
   Error ExecAlterTableRename ();
   Error ExecAlterTableDrop ();
   Error ExecAlterTableAdd ();

   Error SelectNotForUpdate (Token * t, Lex &l, PBool Distinct);
   Error SelectForUpdate (Token *t, Lex &l, PBool Distinct);
   Error From (Lex &l, PBool viewAllowed);
   void substViewFrom (TokenList &tl, Lex &l);
   void substViewSelect (TokenList &tl, Lex &l);
   void substViewWhere (TokenList &tl, Lex &l);
   Error OrderGroupBy (Lex &l, OrderItemCopyList &list);
   StmtRel * getRelation (Token *t, Lex &l);
   AttrView *getViewField (const PString &name, const PString &table, const PString &alias);
   void parseUserName (Token *t, Lex &l, PString &field, PString &table, PString *alias);
   Error AddAllField ();
   void AddAllExpr ();
   Error AddField (PString & name, PString & table, PString & alias);
   Error BuildWhere (Token *t, Lex &l);  
   Error BuildHaving (Token *t, Lex &l); 
   Error  BuildJoin (Lex &l, PString &cond, StmtRel *left, StmtRel *right);
   StmtAttr * GetFieldByName(Lex &, PString &);
   void   PutKeyToken (Lex &l);
   toknum FindResKey (char * str);
   Error  ProcessAll (int);
   Error  SingleProcess (int order, enum eDirection dir = NEXT);
   Error  UpdateBuffer (Relation *r);
   Error  InsertBuffer (Relation *r);
   Error  InsertBuffer (StmtAttrList &dst, StmtAttrList &src);
                                 
   void   SelfSetAttrColumns();
   void   SelfSetAttrTables();
   void   SelfSetAttrSpecCol();
   void   SelfSetAttrStatist();
   void   SelfSetTypeInfo();
   void   SelfSetAttrPrimaryKeys();
   void   SelfSetAttrForeignKeys();
   void   SelfSetAttrProcedures();
   void   SelfSetAttrProcedureColumns();
   void   SelfSetAttrTablePrivileges();
   void   SelfSetAttrColumnPrivileges();
   Error  PrintTable(Relation &rl, const ODBCString &ColumnName,
                     short &order);
   Error  PrintView(RelView &rv, const ODBCString &ColumnName,
                     short &order);
   Error  PrintSpecCol(Attribute *a);
   Error  PrintStatistic(Attribute *ra, IndexPart *ip);
   Error  PrintFirstStatistic(Relation *rl);
   Error  PrintColumn(Attribute *a, const PString *name = 0);
   Error  PrintTypeInfo(short fSqlType);
   Error  PrintPrimaryKeys(Attribute *ra, IndexPart *ip);
   void EvalOrder (StmtRel **allArray, StmtRel **buildArray,
                   StmtRel **bestArray, int idx, int relNum,
                   int &maxVal, int &maxLen);
   void SortRelation (StmtRelList &rl);
   Error verifyGroup (Expression *ex);
   Error verifyGroup (StmtAttr *sa);
   StmtRel *getFrom (const PString &name);
   Attribute * getType (int n);
public:
   SqlParser (DataBase *db, SqlParser *sqo = 0, StmtRel *uv = 0);
   ~SqlParser ();
   DataBase * GetDB (void) { return DB; }
   void Clear ();
   void ClearExec ();
   void Unbind ();
   void ResetParams ();
   CField *NewParam ();
   StmtAttr * GetTableName (const PString & name, PString & table,
                            StmtRel **sr, toknum bi = NULL_);
   StmtAttr * GetViewName (const PString & name, PString & table,
                           StmtRel **sr, toknum bi);
   PBool RedBefore (StmtRel *former, StmtRel *latter);
   Error Parse (char *line, long len);
   Error ChecksBeforeExec ();
   Error Exec ();
   Error Fetch (enum eDirection dir = NEXT, unsigned long numElem = 0);
   Error ExtendedFetch (int dir, unsigned long *pcrow,
                        unsigned short *rgfRowStatus);
   Error GetData (unsigned short icol, AttrCType fCType, char *rgbValue, 
                  long cbValueMax, long *pcbValue);
   Error Bind (unsigned short icol, AttrCType fCType, char *rgbValue, 
               long cbValueMax, long *pcbValue);
   Error ParamData (void **dataPtr);
   Error PutData (void *dataPtr, long len);
   Error GetColLength (unsigned short icol, long &len);
   Error GetLength (unsigned short icol, long &len);
   Error GetColName (unsigned short icol, PString &rgbDesc);
   Error GetColType (unsigned short icol, long &type,
                     SignType &s, DateTime &d);
   Error GetUpdatable (unsigned short icol, long &upd);
   Error GetIsChar (unsigned short icol, long &ischr);
   Error GetColPrecision (unsigned short icol, long &precision);
   Error GetColDisplaySize (unsigned short icol, long &disp);
   Error GetColScale (unsigned short icol, long &scale);
   Error GetColSign (unsigned short icol, long &scale);
   Error GetColNum (long &num);
   Error GetRowCount (long &num);
   Error GetNumParams (short &num);
   Error SetParam (int ipar, AttrCType fCType, int fSqlType,
                   long precision, char *rgbValue, long * pcbValue);
   Error DescribeParam (unsigned short ipar, short *fSqlType,
                        unsigned long *precision,short *scale,short *nullable);
   const PString &getCursorName () { return cursorName; }
   void setCursorName (const char *cn, int len) {
      if (len < 0)
         cursorName.puts (cn);
      else
         cursorName.puts (cn, len);
      cursorName.toUpper();
   }
   unsigned long GetMaxRows() { return MaxRows; }
   void SetMaxRows(unsigned long m) { MaxRows = m; }
   unsigned long getRowSetSize() { return rowSetSize; }
   void setRowSetSize(unsigned long m) { rowSetSize = m; }
   unsigned long GetFetched() { return Fetched; }
   time_t getCurrentTimestamp();

   Error Columns (char *szTableQualifier, short cbTableQualifier,
                  char *szTableOwner,     short cbTableOwner,
              char *szTableName,      short cbTableName,
              char *szColumnName,     short cbColumnName);
                   
   Error Tables  (char *szTableQualifier, short cbTableQualifier,
                  char *szTableOwner,     short cbTableOwner,
              char *szTableName,      short cbTableName,
              char *szTableType,      short cbTableType);

   Error SpecialColumns (unsigned short fColType, char *szTableQualifier,
                     short cbTableQualifier,  char *szTableOwner,
                     short cbTableOwner,      char *szTableName,
                     short cbTableName,
                     unsigned short fScope,   unsigned short fNullable);

   Error Statistics (char *szTableQualifier, short cbTableQualifier,
                     char *szTableOwner,     short cbTableOwner,
                     char *szTableName,      short cbTableName,
                 unsigned short fUnique,   unsigned short fAccuracy);
   Error PrimaryKeys (char *szTableQualifier, short cbTableQualifier,
                      char *szTableOwner,     short cbTableOwner,
                      char *szTableName,      short cbTableName);
   Error EmptyResult ();
   Error ForeignKeys (char *szPkTableQualifier, short cbPkTableQualifier,
                      char *szPkTableOwner,     short cbPkTableOwner,
                      char *szPkTableName,      short cbPkTableName,
                      char *szFkTableQualifier, short cbFkTableQualifier,
                      char *szFkTableOwner,     short cbFkTableOwner,
                      char *szFkTableName,      short cbFkTableName);
   Error Procedures (char *szProcQualifier, short cbProcQualifier,
                     char *szProcOwner,     short cbProcOwner,
                     char *__szProcName,    short __cbProcName);
   Error ProcedureColumns (char *szProcQualifier, short cbProcQualifier,
                           char *szProcOwner,     short cbProcOwner,
                           char *__szProcName,    short __cbProcName,
                           char *szColumnName,    short cbColumnName);
   Error TablePrivileges (char *szProcQualifier, short cbProcQualifier,
                          char *szProcOwner,     short cbProcOwner,
                          char *__szProcName,    short __cbProcName);
   Error ColumnPrivileges (char *szProcQualifier, short cbProcQualifier,
                           char *szProcOwner,     short cbProcOwner,
                           char *__szProcName,    short __cbProcName,
                           char *szColumnName,    short cbColumnName);

   Error  TypeInfo(short fSqlType);

   void DelError () {
      if (subQueryOf)
         subQueryOf->DelError ();
      else                     
         ::DelError (0, 0, this);
   }
   void   PrintError (ErrNum e, const PString & submess, int syserr = 0) {
      if (subQueryOf)
         subQueryOf->PrintError (e, "(subquery)" + submess, syserr);
      else
         ::PrintError (0, 0, this, e, submess, syserr);
   }
   double nextVal(StmtAttr *sa);
};

# endif
