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

*/
# include "sqlpars.h"
# include "trace.h"
static char rcsid[] = "$Id: parscat.cpp 5.1 2001/09/24 13:34:30 picoSoft Exp Marco $";
extern int Int2OdbcType (int t, SignType s, DateTime d);
extern const char * Int2OdbcTypeStr (int t, SignType s, DateTime d);
extern int Like (char *, char *, int, int);
extern "C" {
# include <string.h>
# include <ctype.h>
# ifdef MSDOS
# include <windows.h>
# define strcpy lstrcpy
# define strlen lstrlen
# endif
}
# define MAX_SQL_CHAR 255
# define MAX_SQL_LONGVARCHAR 32767

union cast {
   char chr [sizeof(double)];
   short sht;
   long lng;
   double dbl;
   float flt;
};


class ODBCString
{
   char *data;
   int dim;
public:
   ODBCString (const char *s, short len) {
      char *pnt;
      if (s == 0) {
         data = 0;
         dim = 0;
      } else if (len < 0) {
         dim = strlen (s);
         data = pnt = new char[dim + 1];
         for ( ; *s; s++,pnt++)
            *pnt = toupper(*s);
         *pnt = 0;
      } else {
         data = pnt = new char[len + 1];
         for (dim = 0; *s && dim < len; dim++, s++, pnt++)
            *pnt = toupper(*s);
         *pnt = 0;
      }
   }
   ~ODBCString () { if (data) delete data; }
   operator char *() const { return data; }
   short size() const { return dim; }
   PBool IsNotNull () const { return data != 0; }
   PBool IsEmpty () const { if (data && dim == 0)
                              return PTrue;
                           else
                              return PFalse;
                         }
};

inline PBool IsEmptyString (char *s, short len)
{
   if (s && (len == 0 || *s == '\0'))
      return PTrue;
   else
      return PFalse;
}

Error
SqlParser::TypeInfo  (short fSqlType)
{
   Error Return = SQL_SUCCESS;
   StmtAttr *sa;
   OrderItem oi;

   Clear();

   SelfSetTypeInfo();

// Si deve aggiungere DB agli attributi !!!

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   if ((sa = Fields.GetAt(1)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetFirst()) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   View.SetRel(Fields, *DB);
   View.BufferStmtRelAlloc();
   // View.DefineIndex(OrderList, 1, PTrue);
   View.DefineOrderBy(OrderList, PTrue);

   if ((Return = View.Create ()) == SQL_SUCCESS) {
      View.Clear();
      if (fSqlType == SQL_ALL_TYPES) {
         Return = PrintTypeInfo(SQL_CHAR);
         Return = PrintTypeInfo(SQL_VARCHAR);
         Return = PrintTypeInfo(SQL_LONGVARCHAR);
         // Return = PrintTypeInfo(SQL_NUMERIC);
         Return = PrintTypeInfo(SQL_DECIMAL);
         Return = PrintTypeInfo(SQL_INTEGER);
         Return = PrintTypeInfo(SQL_SMALLINT);
         Return = PrintTypeInfo(SQL_FLOAT);
         Return = PrintTypeInfo(SQL_REAL);
         Return = PrintTypeInfo(SQL_DOUBLE);
         Return = PrintTypeInfo(SQL_TIMESTAMP);
         Return = PrintTypeInfo(SQL_LONGVARBINARY);
      } else
         Return = PrintTypeInfo(fSqlType);
      if (Return == SQL_SUCCESS)
         View.StartNext ();
   }
   return Return;
}

void
SqlParser::SelfSetTypeInfo()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TYPE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "DATA_TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PRECISION", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "LITERAL_PREFIX", &View);
   sa->getAttr()->setType (T_CSTRING, 10, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "LITERAL_SUFFIX", &View);
   sa->getAttr()->setType (T_CSTRING, 10, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "CREATE_PARAMS", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NULLABLE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "CASE_SENSITIVE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "SEARCHABLE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "UNSIGNED_ATTRIBUTE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "MONEY", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "AUTO_INCREMENT", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "LOCAL_TYPE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "MINIMUM_SCALE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "MAXIMUM_SCALE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);
}

Error
SqlParser::PrintTypeInfo (short fSqlType)
{
   StmtAttr *sa;
   Error Return = SQL_SUCCESS;
   union cast val;

   if ((sa = View.GetFieldAt(1)) != 0) {
      sa->setNullBuffer();
      val.sht = fSqlType;
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   switch (fSqlType) {
   case SQL_CHAR:
   case SQL_VARCHAR:
   case SQL_LONGVARCHAR:
      if ((sa = View.GetFirstField()) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_VARCHAR)
            strcpy(sa->GetBuffer(), "VARCHAR");
         else if (fSqlType == SQL_LONGVARCHAR)
            strcpy(sa->GetBuffer(), "LONGVARCHAR");
         else
            strcpy(sa->GetBuffer(), "CHAR");
      }
      if ((sa = View.GetFieldAt(2)) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_LONGVARCHAR)
            val.lng = MAX_SQL_LONGVARCHAR;
         else
            val.lng = MAX_SQL_CHAR;
         memcpy (sa->GetBuffer(), val.chr, sizeof(long));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "'");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "'");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "length");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_NULLABLE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 1;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_SEARCHABLE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_VARCHAR)
            strcpy(sa->GetBuffer(), "VARCHAR");
         else if (fSqlType == SQL_LONGVARCHAR)
            strcpy(sa->GetBuffer(), "LONGVARCHAR");
         else
            strcpy(sa->GetBuffer(), "CHAR");
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      View.Write ();
      break;
   case SQL_NUMERIC:
   case SQL_DECIMAL:
   case SQL_INTEGER:
   case SQL_SMALLINT:
   case SQL_FLOAT:
   case SQL_REAL:
   case SQL_DOUBLE:
      if ((sa = View.GetFirstField()) != 0) {
         sa->setNullBuffer();

         if (fSqlType == SQL_INTEGER)
            strcpy(sa->GetBuffer(), "INTEGER");
         else if (fSqlType == SQL_SMALLINT)
            strcpy(sa->GetBuffer(), "SMALLINT");
         else if (fSqlType == SQL_REAL)
            strcpy(sa->GetBuffer(), "REAL");
         else if (fSqlType == SQL_DOUBLE || fSqlType == SQL_FLOAT)
            strcpy(sa->GetBuffer(), "DOUBLE");
         else if (fSqlType == SQL_NUMERIC || fSqlType == SQL_DECIMAL)
            strcpy(sa->GetBuffer(), "NUMERIC");
      }
      if ((sa = View.GetFieldAt(2)) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_INTEGER)
            val.lng = 9;
         else if (fSqlType == SQL_SMALLINT)
            val.lng = 4;
         else if (fSqlType == SQL_REAL)
            val.lng = 7;
         else if (fSqlType == SQL_DOUBLE || fSqlType == SQL_FLOAT)
            val.lng = 15;
         else if (fSqlType == SQL_NUMERIC || fSqlType == SQL_DECIMAL)
            val.lng = 18;
         memcpy (sa->GetBuffer(), val.chr, sizeof(long));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_INTEGER)
            val.sht = SQL_NULLABLE;
         else if (fSqlType == SQL_SMALLINT)
            val.sht = SQL_NULLABLE;
         else if (fSqlType == SQL_REAL)
            val.sht = SQL_NO_NULLS;
         else if (fSqlType == SQL_DOUBLE || fSqlType == SQL_FLOAT)
            val.sht = SQL_NO_NULLS;
         else if (fSqlType == SQL_NUMERIC || fSqlType == SQL_DECIMAL)
            val.sht = SQL_NO_NULLS;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_ALL_EXCEPT_LIKE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
/*
         if (fSqlType == SQL_INTEGER)
            strcpy(sa->GetBuffer(), "INTEGER");
         else if (fSqlType == SQL_SMALLINT)
            strcpy(sa->GetBuffer(), "SMALLINT");
         else if (fSqlType == SQL_REAL)
            strcpy(sa->GetBuffer(), "REAL");
         else if (fSqlType == SQL_DOUBLE || fSqlType == SQL_FLOAT)
            strcpy(sa->GetBuffer(), "DOUBLE");
         else if (fSqlType == SQL_NUMERIC || fSqlType == SQL_DECIMAL)
            strcpy(sa->GetBuffer(), "NUMERIC");
*/
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_INTEGER ||
             fSqlType == SQL_SMALLINT)
            val.sht = 0;
         else if (fSqlType == SQL_NUMERIC || fSqlType == SQL_DECIMAL)
            val.sht = 0;
         else
            val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         if (fSqlType == SQL_INTEGER ||
             fSqlType == SQL_SMALLINT)
            val.sht = 0;
         else if (fSqlType == SQL_NUMERIC || fSqlType == SQL_DECIMAL)
            val.sht = 18;
         else
            val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      View.Write();
      break;
   case SQL_TIMESTAMP:
      if ((sa = View.GetFirstField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "TIMESTAMP");
      }
      if ((sa = View.GetFieldAt(2)) != 0) {
         union cast val;
         sa->setNullBuffer();
         val.lng = TIMESTAMPPREC;
         memcpy (sa->GetBuffer(), val.chr, sizeof(long));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "'");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "'");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_NULLABLE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_ALL_EXCEPT_LIKE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      View.Write ();
      break;
   case SQL_LONGVARBINARY:
      if ((sa = View.GetFirstField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "BLOB");
      }
      if ((sa = View.GetFieldAt(2)) != 0) {
         sa->setNullBuffer();
         val.lng = NULLLONG;
         memcpy (sa->GetBuffer(), val.chr, sizeof(long));
      }
      if ((sa = View.GetNextField()) != 0)
         sa->setNullBuffer();

      if ((sa = View.GetNextField()) != 0)
         sa->setNullBuffer();

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         strcpy(sa->GetBuffer(), "");
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_NULLABLE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = SQL_UNSEARCHABLE;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = 0;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }

      if ((sa = View.GetNextField()) != 0) {
         sa->setNullBuffer();
         val.sht = NULLSHORT;
         memcpy (sa->GetBuffer(), val.chr, sizeof(short));
      }
      View.Write ();
      break;
   default:
      break;
   }
   return Return;
}

Error
SqlParser::PrintColumn(Attribute *a, const PString *name)
{
   StmtAttr *loc;
   Error Return = SQL_SUCCESS;
   int i = 0;
   const char * tipo;
   union cast val;

   for (loc = View.GetFirstField(), i = 0; loc != 0;
        loc = View.GetNextField(), i++) {
      if (i > 2)
         loc->setNullBuffer();
      switch(i) {
      case 3:  // COLUMN_NAME
         if (name)
            memcpy (loc->GetBuffer(), name->gets(), name->size());
         else
            memcpy (loc->GetBuffer(), a->getName().gets(), (int)a->getName().size());
         break;
      case 4:  // DATA_TYPE
         val.sht = Int2OdbcType (a->GetType(), a->GetSign(), a->getDateType());
         if (val.sht == SQL_CHAR && a->getFldSize() > MAX_SQL_CHAR)
            val.sht = SQL_LONGVARCHAR;
         memcpy (loc->GetBuffer(), val.chr, sizeof(short));
         break;
      case 5:  // TYPE_NAME
         tipo =  Int2OdbcTypeStr (a->GetType(), a->GetSign(), a->getDateType());
         memcpy (loc->GetBuffer(), tipo, strlen(tipo));
         break;
      case 6:  // PRECISION
         if (a->getDateType() == T_TIMESTAMP)
            val.lng = TIMESTAMPPREC;
         else
            val.lng  = a->GetLen();
         memcpy (loc->GetBuffer(), val.chr, sizeof(long));
         break;
      case 7:  // LENGTH
         if (a->getDateType() == T_TIMESTAMP)
            val.lng = sizeof(TIMESTAMP_STRUCT);
         else
            if (a->GetDecimal() > 0)
               val.lng = a->GetLen() + 2;
            else
               val.lng = a->GetLen();
         memcpy (loc->GetBuffer(), val.chr, sizeof(long));
         break;
      case 8:  // SCALE
         val.sht = a->GetDecimal();
         memcpy (loc->GetBuffer(), val.chr, sizeof(short));
         break;
      case 9:  // RADIX
         if (a->GetType() != T_CSTRING) {
            val.sht = 10;
            memcpy (loc->GetBuffer(), val.chr, sizeof(short));
         }
         break;
      case 10: // NULLABLE
         val.sht = SQL_NULLABLE;   // Da vedere
         memcpy (loc->GetBuffer(), val.chr, sizeof(short));
         break;
      case 11: // REMARKS
//         memcpy(loc->Buffer, "Descrizione della colonna", 25);
         break;
      default:
         break;
      }
   }
   return Return;
}

Error
SqlParser::PrintTable(Relation &rl, const ODBCString &ColumnName,
                      short &order)
{
   Attribute *a;
   Error Return = SQL_SUCCESS;

   order = 0;
   for (a = rl.getVisAttrs().GetFirst(); a != 0;
        a = rl.getVisAttrs().GetNext()) {
      if (ColumnName.IsNotNull()) {
         if (ColumnName.IsEmpty ())
            continue;
         if (! Like (a->getName().gets(), (char *)ColumnName,
                     a->getName().size(), ColumnName.size()))
            continue;
      }
      Return = PrintColumn(a);
      order++;
      if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
         break;
//    View->FillBuffer(Info);
      Return = View.Write();
      if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
         break;
   }
   return Return;
}

Error
SqlParser::PrintView(RelView &rv, const ODBCString &ColumnName,
                      short &order)
{
   Error Return = SQL_SUCCESS;
   AttrViewIterator avi(rv.getFields());

   order = 0;
   for (avi.reset(); *avi; avi++) {
      if (ColumnName.IsNotNull()) {
         if (ColumnName.IsEmpty ())
            continue;
         if (! Like ((*avi)->getName().gets(), (char *)ColumnName,
                     (*avi)->getName().size(), ColumnName.size()))
            continue;
      }
      Return = PrintColumn((*avi)->getAttr(), &(*avi)->getName());
      order++;
      if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
         break;
//    View->FillBuffer(Info);
      Return = View.Write();
      if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
         break;
   }
   return Return;
}

void
SqlParser::SelfSetAttrColumns()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "DATA_TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TYPE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PRECISION", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "LENGTH", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "SCALE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "RADIX", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NULLABLE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "REMARKS", &View);
   sa->getAttr()->setType (T_CSTRING, 30, 0);
   Info.AddItem (sa);

   sa = new StmtAttr  (*DB, "order", &View); // ultimo per ordinamento
   sa->getAttr()->setType (T_SHORT, 0, 0);
   Info.AddItem(sa);
}

Error
SqlParser::Columns (char *szTableQualifier, short cbTableQualifier,
                    char *szTableOwner,     short cbTableOwner,
                char *__szTableName,      short __cbTableName,
                char *__szColumnName,     short __cbColumnName)
{
   Error Return = SQL_SUCCESS;
   Relation *r;
   RelView *rv;
   RelObject *ro;
   StmtAttr *order, *sa;
   OrderItem oi;
   int i = 0;
   ODBCString ColumnName(__szColumnName, __cbColumnName);
   ODBCString TableName(__szTableName, __cbTableName);
   union cast val;

   Clear();

   SelfSetAttrColumns();

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   for (i = 0, sa = Fields.GetFirst(); sa != 0 && i < 3; sa = Fields.GetNext(), i++) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }

   View.SetRel(Fields, *DB);

   order = View.GetFieldAt(Info.GetItemNum() - 1);
   View.getRel()->SetInvis (order->getAttr());
/*
   order = new StmtAttr  ("order", &View);
   AuxFields.AddItem (order);
   order->getAttr()->setType (T_SHORT, 0, 0);
   View.AddField (order);
*/
//sj   View.getRel()->AllAttrs.AddItem (order);
   oi.sa = order;
   oi.desc = PFalse;
   OrderList.AddItem (oi);

   View.BufferStmtRelAlloc();
   // View.DefineIndex(OrderList, 1, PTrue);
   View.DefineOrderBy(OrderList, PTrue);

   if ((Return = View.Create ()) == SQL_SUCCESS) {
      View.Clear();

      if ((sa = View.GetFirstField()) != 0){ // TABLE_QUALIFIER
         sa->setNullBuffer();
         /*
         GetPrivateProfileString(DB->Nome.gets(), "DataDirectory",
           "", szDbDir, sizeof(szDbDir), "ODBC.INI");
         memcpy (sa->GetBuffer(), szDbDir, strlen(szDbDir));
         */
      }
      if ((sa = View.GetNextField()) != 0){ // TABLE_OWNER
         sa->setNullBuffer();
         // da settare
      }
      if ((sa = View.GetNextField()) != 0) { // TABLE_NAME
         for (RelObjectIterator roi(DB->getRelBases()); *roi; roi++) {
            if ((*roi)->Exists()) {
               if (TableName.IsNotNull()) {
                  if (TableName.IsEmpty())
                     continue;
                  if (! Like ((*roi)->getName().gets(), (char *)TableName,
                              (*roi)->getName().size(), TableName.size()))
                     continue;
               }
               if ((*roi)->IsA(RelBase::Class)) {
                  if (r = DB->GetRelation ((*roi)->getName(), this)) {
                     sa->setNullBuffer(); // sempre TABLE_NAME
                     strncpy(sa->GetBuffer(), r->getName().gets(), sa->getAttr()->GetLen());
                     Return = PrintTable(*r, ColumnName, val.sht);
                     memcpy (order->GetBuffer(), val.chr, sizeof(short));
                     if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
                        break;
                  } else
                     Return = SQL_ERROR;
               }
            } // else View O^O
         }
         for (RelObjectIterator rvi(DB->getRelViews()); *rvi; rvi++) {
            if ((*rvi)->Exists()) {
               if (TableName.IsNotNull()) {
                  if (TableName.IsEmpty())
                     continue;
                  if (! Like ((*rvi)->getName().gets(), (char *)TableName,
                              (*rvi)->getName().size(), TableName.size()))
                     continue;
               }
               if (rv = DB->GetRelView ((*rvi)->getName())) {
                  sa->setNullBuffer(); // sempre TABLE_NAME
                  strncpy(sa->GetBuffer(), rv->getName().gets(), sa->getAttr()->GetLen());
                  Return = PrintView(*rv, ColumnName, val.sht);
                  memcpy (order->GetBuffer(), val.chr, sizeof(short));
                  if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
                     break;
               } else
                  Return = SQL_ERROR;
            }
         }
         RelObjectIterator bvi(DB->getBaseViews());
         while ((ro = *bvi)) {
            bvi++; // Perche' l'elemento puo' essere cancellato dala lista!!
            if (ro->Exists()) {
               if (TableName.IsNotNull()) {
                  if (TableName.IsEmpty())
                     continue;
                  if (! Like (ro->getName().gets(), (char *)TableName,
                              ro->getName().size(), TableName.size()))
                     continue;
               }
               if (rv = DB->GetRelView (ro->getName())) {
                  sa->setNullBuffer(); // sempre TABLE_NAME
                  strncpy(sa->GetBuffer(), rv->getName().gets(), sa->getAttr()->GetLen());
                  Return = PrintView(*rv, ColumnName, val.sht);
                  memcpy (order->GetBuffer(), val.chr, sizeof(short));
                  if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
                     break;
               } else
                  Return = SQL_ERROR;
            }
         }
      }
      if (Return == SQL_SUCCESS)
         View.StartNext ();
   } else {
      ClearExec ();
      PrintError (E_GENERAL_ERROR_001, "Temporary file creation failed",
                   View.getStatus());
      Return = SQL_ERROR;
   }
   return Return;
}


void
SqlParser::SelfSetAttrTables()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_TYPE", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "REMARKS", &View);
   sa->getAttr()->setType (T_CSTRING, 30, 0);
   Info.AddItem (sa);
}

Error
SqlParser::Tables (char *szTableQualifier, short cbTableQualifier,
                   char *szTableOwner,     short cbTableOwner,
                   char *__szTableName,    short __cbTableName,
                   char *__szTableType,    short __cbTableType)
{
   Error Return = SQL_SUCCESS;
   StmtAttr *sa;
   OrderItem oi;
   register int i = 0;
   PBool infoTable = PFalse;
   PBool infoView = PFalse;
   ODBCString TableName(__szTableName,__cbTableName);
   ODBCString TableType(__szTableType,__cbTableType);

   if (szTableQualifier != 0 &&
       (cbTableQualifier > 0 ||
       cbTableQualifier == SQL_NTS && szTableQualifier[0] != '\0')) {
      PrintError (E_GENERAL_ERROR_C00, "");
      return SQL_ERROR;
   }
   if (szTableOwner != 0 &&
       (cbTableOwner > 0 ||
        cbTableOwner == SQL_NTS && szTableOwner[0] != '\0')) {
      PrintError (E_GENERAL_ERROR_C00, "");
      return SQL_ERROR;
   }
   if (TableType.IsNotNull() == PFalse || strcmp((char*)TableType, "%") == 0)
      infoTable = infoView = PTrue;
   else {
      if (strstr ((char*)TableType, "TABLE"))
         infoTable = PTrue;
      if (strstr ((char*)TableType, "VIEW"))
         infoView = PTrue;
   }
   Clear();

   SelfSetAttrTables();

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   if ((sa = Fields.GetLast()) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   for (i = 0, sa = Fields.GetFirst(); sa != 0 && i < 3;
                                       sa = Fields.GetNext(), i++) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   View.SetRel(Fields, *DB);
   View.BufferStmtRelAlloc();
   View.DefineOrderBy(OrderList, PTrue);
   if ((Return = View.Create ()) == SQL_SUCCESS) {
      if (infoTable || infoView) {
         View.Clear();

         if ((sa = View.GetFieldAt(0)) != 0){ // TABLE_QUALIFIER
            sa->setNullBuffer();
         }
         if ((sa = View.GetFieldAt(1)) != 0){ // TABLE_OWNER
            sa->setNullBuffer();
         }
         if (TableName.IsEmpty()) {
            if (infoTable) {
               if ((sa = View.GetFieldAt(2)) != 0) // TABLE_NAME
                  sa->setNullBuffer();
               if ((sa = View.GetFieldAt(3)) != 0) // TABLE_TYPE
                  sa->setNullBuffer();
                  memcpy(sa->GetBuffer(), "TABLE", 5);
               if ((sa = View.GetFieldAt(4)) != 0) // REMARKS
                  sa->setNullBuffer();
               Return = View.Write();
            }
            if (infoView && Return == SQL_SUCCESS) {
               if ((sa = View.GetFieldAt(2)) != 0) // TABLE_NAME
                  sa->setNullBuffer();
               if ((sa = View.GetFieldAt(3)) != 0) // TABLE_TYPE
                  sa->setNullBuffer();
                  memcpy(sa->GetBuffer(), "VIEW", 5);
               if ((sa = View.GetFieldAt(4)) != 0) // REMARKS
                  sa->setNullBuffer();
               Return = View.Write();
            }
         } else {
            if (infoTable) {
               for (RelObjectIterator roi(DB->getRelBases()); *roi; roi++) {
                  if ((*roi)->Exists()) {
                     if (TableName.IsNotNull()) {
                        if (!Like((*roi)->getName().gets(), (char *)TableName,
                                  (*roi)->getName().size(), TableName.size()))
                        continue;
                     }
                     if ((sa = View.GetFieldAt(2)) != 0) { // TABLE_NAME
                        sa->setNullBuffer();
                        memcpy(sa->GetBuffer(), (*roi)->getName().gets(),
                                           (int)(*roi)->getName().size());
                     }
                     if ((sa = View.GetFieldAt(3)) != 0) {// TABLE_TYPE
                        sa->setNullBuffer();
                        memcpy(sa->GetBuffer(), "TABLE", 5);
                     }
                     if ((sa = View.GetFieldAt(4)) != 0) // REMARKS
                        sa->setNullBuffer();
                     Return = View.Write();
                     if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
                        break;
                  }
               }
            }
            if (infoView) {
               for (RelObjectIterator roi(DB->getRelViews()); *roi; roi++) {
                  if ((*roi)->Exists()) {
                     if (TableName.IsNotNull()) {
                        if (!Like((*roi)->getName().gets(), (char *)TableName,
                                  (*roi)->getName().size(), TableName.size()))
                           continue;
                     }
                     if ((sa = View.GetFieldAt(2)) != 0) { // TABLE_NAME
                        sa->setNullBuffer();
                        memcpy(sa->GetBuffer(), (*roi)->getName().gets(),
                                           (int)(*roi)->getName().size());
                     }
                     if ((sa = View.GetFieldAt(3)) != 0) {// TABLE_TYPE
                        sa->setNullBuffer();
                        memcpy(sa->GetBuffer(), "VIEW", 5);
                     }
                     if ((sa = View.GetFieldAt(4)) != 0) // REMARKS
                        sa->setNullBuffer();
                     Return = View.Write();
                     if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
                        break;
                  }
               }
               for (RelObjectIterator bvi(DB->getBaseViews()); *bvi; bvi++) {
                  if ((*bvi)->Exists()) {
                     if (TableName.IsNotNull()) {
                        if (!Like((*bvi)->getName().gets(), (char *)TableName,
                                  (*bvi)->getName().size(), TableName.size()))
                           continue;
                     }
                     if ((sa = View.GetFieldAt(2)) != 0) { // TABLE_NAME
                        sa->setNullBuffer();
                        memcpy(sa->GetBuffer(), (*bvi)->getName().gets(),
                                           (int)(*bvi)->getName().size());
                     }
                     if ((sa = View.GetFieldAt(3)) != 0) {// TABLE_TYPE
                        sa->setNullBuffer();
                        memcpy(sa->GetBuffer(), "VIEW", 5);
                     }
                     if ((sa = View.GetFieldAt(4)) != 0) // REMARKS
                        sa->setNullBuffer();
                     Return = View.Write();
                     if ( Return != SQL_SUCCESS && Return != SQL_SUCCESS_WITH_INFO)
                        break;
                  }
               }
            }
         }
         if (Return == SQL_SUCCESS)
            View.StartNext ();
      }
   } else {
      ClearExec ();
      PrintError (E_GENERAL_ERROR_001, "Temporary file creation failed", Return);
      Return = SQL_ERROR;
   }
   return Return;
}

void
SqlParser::SelfSetAttrSpecCol()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "SCOPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "DATA_TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TYPE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PRECISION", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "LENGTH", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "SCALE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PSEUDO_COLUMN", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);
}

Error
SqlParser::PrintSpecCol (Attribute *ra)
{
   StmtAttr *sa;
   union cast val;

   if ((sa = View.GetFirstField()) != 0){ // 0 SCOPE
     sa->setNullBuffer();
     val.sht = SQL_SCOPE_CURROW;
     memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0){ // 1 COLUMN_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(), ra->getName().gets(), sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0){ // 2 DATA_TYPE
     sa->setNullBuffer();
     val.sht = Int2OdbcType (ra->GetType(), ra->GetSign(), ra->getDateType());
     memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0){ // 3 TYPE_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(), Int2OdbcTypeStr (ra->GetType(), ra->GetSign(), ra->getDateType()),
                          sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0){ // 4 PRECISION
     sa->setNullBuffer();
     if (ra->getDateType() == T_TIMESTAMP)
        val.lng = TIMESTAMPPREC;
     else
        val.lng = ra->GetLen();
     memcpy (sa->GetBuffer(), val.chr, sizeof(long));
   }
   if ((sa = View.GetNextField()) != 0){ // 5 LENGTH
      sa->setNullBuffer();
      switch (Int2OdbcType (ra->GetType(), ra->GetSign(), ra->getDateType())) {
      case SQL_DECIMAL:
      case SQL_NUMERIC:
         val.lng = ra->GetLen() + 2;
         break;
      case SQL_SMALLINT:
         val.lng = 2;
         break;
      case SQL_INTEGER:
      case SQL_REAL:
         val.lng = 4;
         break;
      case SQL_DOUBLE:
      case SQL_FLOAT:
         val.lng = 8;
         break;
      case SQL_TIMESTAMP:
         val.lng = sizeof(TIMESTAMP_STRUCT);
         break;
      default:
         val.lng = ra->GetLen();
         break;
      }
      memcpy (sa->GetBuffer(), val.chr, sizeof(long));
   }
   if ((sa = View.GetNextField()) != 0){ // 6 SCALE
     sa->setNullBuffer();
     val.sht = ra->GetDecimal();
     memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0){ // 7 PSEUDO_COLUMN
     sa->setNullBuffer();
     val.sht = SQL_PC_NOT_PSEUDO;
     memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   return SQL_SUCCESS;
}

Error
SqlParser::SpecialColumns (unsigned short fColType, char *szTableQualifier,
                        short cbTableQualifier,  char *szTableOwner,
                        short cbTableOwner,      char *__szTableName,
                        short __cbTableName,
                        unsigned short fScope,   unsigned short fNullable)
{
   Error Return = SQL_SUCCESS;
   StmtAttr *sa;
   OrderItem oi;
   AttributeList UniqIdxs;
   int minIndexNum;
   Relation *rl;
   IndexPart *ip;
   ODBCString TableName (__szTableName, __cbTableName);

   Clear();

   SelfSetAttrSpecCol();

// Si deve aggiungere DB agli attributi !!!

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   if ((sa = Fields.GetFirst()) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   View.SetRel(Fields, *DB);
   View.BufferStmtRelAlloc();
   // View.DefineIndex(OrderList, 1, PTrue);
   View.DefineOrderBy(OrderList, PTrue);
   Attribute *a;
   if ((Return = View.Create ()) == SQL_SUCCESS) {
      View.Clear();
      if (TableName.IsNotNull())
         if (rl = DB->GetRelation((char *)TableName, this)) {
/*
            if (rl->getName().size() == TableName.size() &&
                strncmp (TableName, rl->getName().gets(), TableName.size()) == 0)
*/
               if (rl->FileOpenExists()) {
                  if (fColType == SQL_BEST_ROWID) {
                     minIndexNum = 0;
                     for (a = rl->getVisAttrs().GetFirst(); a != 0;
                          a = rl->getVisAttrs().GetNext())
                        for (ip = a->GetFirstIndex();
                             ip != 0;
                             ip = a->GetNextIndex())
                           if (!ip->isDups()) {
                              UniqIdxs.AddItem (a);
                              if (minIndexNum < ip->getNumber ())
                                 minIndexNum = ip->getNumber ();
                           }
                     for (a = UniqIdxs.GetFirst(); Return == SQL_SUCCESS && a != 0;
                          a = UniqIdxs.GetNext())
                        if (a->IsIndexNumber (minIndexNum))
                           if ((Return = PrintSpecCol(a)) == SQL_SUCCESS)
                               Return = View.Write();
               }
            }
         } else
            Return = SQL_ERROR;
      if (Return == SQL_SUCCESS)
         View.StartNext ();
   } else {
      ClearExec ();
      PrintError (E_GENERAL_ERROR_001, "Temporary file creation failed", Return);
      Return = SQL_ERROR;
   }
   return Return;
}


void
SqlParser::SelfSetAttrStatist()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NON_UNIQUE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "INDEX_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "INDEX_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "SEQ_IN_INDEX", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLLATION", &View);
   sa->getAttr()->setType (T_CSTRING, 1, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "CARDINALITY", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PAGES", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "FILTER_CONDITION", &View);
   sa->getAttr()->setType (T_CSTRING, 1, 0);
   Info.AddItem (sa);
}

Error
SqlParser::PrintStatistic (Attribute *ra, IndexPart *ip)
{
   StmtAttr *sa;
   Error Return = SQL_SUCCESS;
   union cast val;

   if ((sa = View.GetFirstField()) != 0){ // 0 TABLE_QUALIFIER
      sa->setNullBuffer();
         /*
         GetPrivateProfileString(DB->Nome.gets(), "DataDirectory",
           "", szDbDir, sizeof(szDbDir), "ODBC.INI");
         memcpy (sa->GetBuffer(), szDbDir, strlen(szDbDir));
         */
   }
   if ((sa = View.GetNextField()) != 0){ // 1 TABLE_OWNER
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 2 TABLE_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(), ra->getParent()->getName().gets(), sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0) { // 3 NON_UNIQUE
      sa->setNullBuffer();
      val.sht = ip->isDups();
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 4 INDEX_QUALIFIER
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 5 INDEX_NAME
      sa->setNullBuffer();
      sprintf (sa->GetBuffer(), "%.*s_%.02x", (int) (sa->getAttr()->getFldSize() - 3),
                          ra->getParent()->getName().gets(),
                          ip->getNumber());
   }
   if ((sa = View.GetNextField()) != 0) { // 6 TYPE
      sa->setNullBuffer();
      val.sht = SQL_INDEX_OTHER;
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 7 SEQ_IN_INDEX
      sa->setNullBuffer();
      val.sht = ip->getPart();
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 8 COLUMN_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(), ra->getName().gets(), sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0) { // 9 COLLATION
      sa->setNullBuffer();
      if (ip->isDesc ())
         *sa->GetBuffer() = 'D';
      else
         *sa->GetBuffer() = 'A';
   }
   if ((sa = View.GetNextField()) != 0) { // 10 CARDINALITY
      sa->setNullBuffer();
      val.lng = NULLLONG;
      memcpy (sa->GetBuffer(), val.chr, sizeof(long));
   }
   if ((sa = View.GetNextField()) != 0) { // 11 PAGES
      sa->setNullBuffer();
      val.lng = NULLLONG;
      memcpy (sa->GetBuffer(), val.chr, sizeof(long));
   }
   if ((sa = View.GetNextField()) != 0) { // 12 FILTER_CONDITION
      sa->setNullBuffer();
   }
   return Return;
}

Error
SqlParser::PrintFirstStatistic (Relation *rl)
{
   StmtAttr *sa;
   Error Return = SQL_SUCCESS;
   union cast val;

   if ((sa = View.GetFirstField()) != 0){ // 0 TABLE_QUALIFIER
      sa->setNullBuffer();
         /*
         GetPrivateProfileString(DB->Nome.gets(), "DataDirectory",
           "", szDbDir, sizeof(szDbDir), "ODBC.INI");
         memcpy (sa->GetBuffer(), szDbDir, strlen(szDbDir));
         */
   }
   if ((sa = View.GetNextField()) != 0){ // 1 TABLE_OWNER
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 2 TABLE_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(), rl->getName().gets(), sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0) { // 3 NON_UNIQUE
      sa->setNullBuffer();
      val.sht = NULLSHORT;
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 4 INDEX_QUALIFIER
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 5 INDEX_NAME
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 6 TYPE
      sa->setNullBuffer();
      val.sht = SQL_TABLE_STAT;
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 7 SEQ_IN_INDEX
      sa->setNullBuffer();
      val.sht = NULLSHORT;
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 8 COLUMN_NAME
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 9 COLLATION
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 10 CARDINALITY
      sa->setNullBuffer();
      val.lng = NULLLONG;

      int rc = rl->GetNumRecords(&val.lng);
      memcpy (sa->GetBuffer(), val.chr, sizeof(long));
      if (rc != 0) {
         PrintError (E_GENERAL_ERROR_000, "System Error on file" + rl->getName(), rc);
         return Return = SQL_ERROR;
      }

   }
   if ((sa = View.GetNextField()) != 0) { // 11 PAGES
      sa->setNullBuffer();
      val.lng = NULLLONG;
      memcpy (sa->GetBuffer(), val.chr, sizeof(long));
   }
   if ((sa = View.GetNextField()) != 0) { // 12 FILTER_CONDITION
      sa->setNullBuffer();
   }
   return Return;
}

Error
SqlParser::Statistics (char *szTableQualifier, short cbTableQualifier,
                       char *szTableOwner,     short cbTableOwner,
                   char *__szTableName,      short __cbTableName,
                   unsigned short fUnique, unsigned short fAccuracy)
{
   Error Return = SQL_SUCCESS;
   Relation *rl;
   StmtAttr *sa;
   OrderItem oi;
   PBool esci = PFalse;
   IndexPart *ip;
   ODBCString TableName(__szTableName,__cbTableName);

   Clear();

   SelfSetAttrStatist();

// Si deve aggiungere DB agli attributi !!!

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   if ((sa = Fields.GetAt(3)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(6)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(4)) != 0)  {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(5)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(7)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   View.SetRel(Fields, *DB);
   View.BufferStmtRelAlloc();
   // View.DefineIndex(OrderList, 1, PTrue);
   View.DefineOrderBy(OrderList, PTrue);
   Attribute *a;
   if ((Return = View.Create ()) == SQL_SUCCESS) {
      View.Clear();
      if (TableName.IsNotNull())
         if (rl = DB->GetRelation((char *)TableName, this)) {
/*
            if (rl->getName().size() == TableName.size() &&
                strncmp (TableName, rl->getName().gets(), TableName.size()) == 0)
*/
               if (rl->FileOpenExists()) {
                  if ((Return = PrintFirstStatistic(rl)) == SQL_SUCCESS)
                     Return = View.Write();
                  AttributeIterator aI (rl->getVisAttrs());
                  for (a = rl->getVisAttrs().GetFirst();
                       a != 0 && Return == SQL_SUCCESS;
                       a = rl->getVisAttrs().GetNext())
                     for (ip = a->GetFirstIndex();
                          ip != 0;
                          ip = a->GetNextIndex ())
                        if (ip->getPart () == 1) {
                           for ( aI.reset(); *aI != 0 && Return == SQL_SUCCESS;
                                 aI++)
                              if ((*aI)->IsIndexNumber (ip->getNumber()))
                                 if (!ip->isDups () ||
                                     ip->isDups() && fUnique == SQL_INDEX_ALL)
                                    if ((Return = PrintStatistic(*aI,
                                           (*aI)->GetIndex(ip->getNumber())))
                                                                 == SQL_SUCCESS)
                                       Return = View.Write();
                        }
               }
         } else
            Return = SQL_ERROR;
      if (Return == SQL_SUCCESS)
         View.StartNext ();
   } else {
      ClearExec ();
      PrintError (E_GENERAL_ERROR_001, "Temporary file creation failed", Return);
      Return = SQL_ERROR;
   }
   return Return;
}

void
SqlParser::SelfSetAttrPrimaryKeys()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "KEY_SEQ", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PK_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);
}

Error
SqlParser::PrintPrimaryKeys (Attribute *ra, IndexPart *ip)
{
   StmtAttr *sa;
   Error Return = SQL_SUCCESS;
   union cast val;

   if ((sa = View.GetFirstField()) != 0){ // 0 TABLE_QUALIFIER
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0){ // 1 TABLE_OWNER
      sa->setNullBuffer();
   }
   if ((sa = View.GetNextField()) != 0) { // 2 TABLE_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(),
              ra->getParent()->getName().gets(), sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0) { // 3 COLUMN_NAME
      sa->setNullBuffer();
      strncpy(sa->GetBuffer(), ra->getName().gets(), sa->getAttr()->GetLen());
   }
   if ((sa = View.GetNextField()) != 0) { // 4 KEY_SEQ
      sa->setNullBuffer();
      val.sht = ip->getPart();
      memcpy (sa->GetBuffer(), val.chr, sizeof(short));
   }
   if ((sa = View.GetNextField()) != 0) { // 5 PK_NAME
      sa->setNullBuffer();
      sprintf (sa->GetBuffer(), "%.*s_%.02x",
                          (int) (sa->getAttr()->getFldSize() - 3),
                          ra->getParent()->getName().gets(),
                          ip->getNumber());
   }
   return Return;
}

Error
SqlParser::PrimaryKeys (char *szTableQualifier, short cbTableQualifier,
                        char *szTableOwner,     short cbTableOwner,
                       char *__szTableName,      short __cbTableName)
{
   Error Return = SQL_SUCCESS;
   Relation *rl;
   StmtAttr *sa;
   OrderItem oi;
   PBool esci = PFalse;
   IndexPart *ip;
   ODBCString TableName(__szTableName,__cbTableName);

   Clear();

   SelfSetAttrPrimaryKeys();

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   if ((sa = Fields.GetAt(0)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(1)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(2)) != 0)  {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   if ((sa = Fields.GetAt(4)) != 0) {
      oi.sa = sa;
      oi.desc = PFalse;
      OrderList.AddItem (oi);
   }
   View.SetRel(Fields, *DB);
   View.BufferStmtRelAlloc();
   View.DefineOrderBy(OrderList, PTrue);
   Attribute *a;
   if ((Return = View.Create ()) == SQL_SUCCESS) {
      View.Clear();
      if (TableName.IsNotNull())
         if (rl = DB->GetRelation((char *)TableName, this)) {
            if (rl->FileOpenExists()) {
               AttributeIterator aI (rl->getVisAttrs());
               for (a = rl->getVisAttrs().GetFirst();
                    a != 0 && Return == SQL_SUCCESS;
                    a = rl->getVisAttrs().GetNext())
                  for (ip = a->GetFirstIndex();
                       ip != 0;
                       ip = a->GetNextIndex ())
                     if (ip->getNumber() == 1 && ip->getPart () == 1) {
                        for ( aI.reset(); *aI != 0 && Return == SQL_SUCCESS;
                              aI++)
                           if ((*aI)->IsIndexNumber (ip->getNumber()))
                              if (!ip->isDups ())
                                 if ((Return = PrintPrimaryKeys(*aI,
                                        (*aI)->GetIndex(ip->getNumber())))
                                                              == SQL_SUCCESS)
                                    Return = View.Write();
                     }
            }
         } else
            Return = SQL_ERROR;
      if (Return == SQL_SUCCESS)
         View.StartNext ();
   } else {
      ClearExec ();
      PrintError (E_GENERAL_ERROR_001, "Temporary file creation failed", Return);
      Return = SQL_ERROR;
   }
   return Return;
}

void
SqlParser::SelfSetAttrForeignKeys()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "PKTABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PKTABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PKTABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PKCOLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "FKTABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "FKTABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "FKTABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "FKCOLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "KEY_SEQ", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "UPDATE_RULE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "DELETE_RULE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "FK_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PK_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);
}

Error
SqlParser::EmptyResult ()
{
   Error Return = SQL_SUCCESS;
   StmtAttr *sa;

   for (sa = Info.GetFirst(); sa; sa = Info.GetNext())
      Fields.AddItem(sa);

   View.SetRel(Fields, *DB);
   View.BufferStmtRelAlloc();
   if ((Return = View.Create ()) == SQL_SUCCESS) {
      View.Clear();
      View.StartNext ();
   } else {
      ClearExec ();
      PrintError (E_GENERAL_ERROR_001,"Temporary file creation failed", Return);
      Return = SQL_ERROR;
   }
   return Return;
}

Error
SqlParser::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 )
{
   Clear();

   SelfSetAttrForeignKeys();

   return EmptyResult();
}

void
SqlParser::SelfSetAttrProcedures()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "PROCEDURE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PROCEDURE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PROCEDURE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NUM_INPUT_PARAMS", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NUM_OUTPUT_PARAMS", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NUM_RESULT_SETS", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "REMARKS", &View);
   sa->getAttr()->setType (T_CSTRING, 30, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PROCEDURE_TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);
}

Error
SqlParser::Procedures (char *szProcQualifier, short cbProcQualifier,
                       char *szProcOwner,     short cbProcOwner,
                       char *__szProcName,    short __cbProcName)
{
   Clear();

   SelfSetAttrProcedures();

   return EmptyResult();
}

void
SqlParser::SelfSetAttrProcedureColumns()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "PROCEDURE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PROCEDURE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PROCEDURE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "DATA_TYPE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);


   sa = new StmtAttr (*DB, "PRECISION", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "LENGTH", &View);
   sa->getAttr()->setType (T_LONG, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "SCALE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "RADIX", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "NULLABLE", &View);
   sa->getAttr()->setType (T_SHORT, 0, 0);
   sa->getAttr()->setSign (INTERNAL_LEADING);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "REMARKS", &View);
   sa->getAttr()->setType (T_CSTRING, 30, 0);
   Info.AddItem (sa);
}

Error
SqlParser::ProcedureColumns (char *szProcQualifier, short cbProcQualifier,
                             char *szProcOwner,     short cbProcOwner,
                             char *__szProcName,    short __cbProcName,
                             char *__szColumnName,  short __cbColumnName)
{
   Clear();

   SelfSetAttrProcedureColumns();

   return EmptyResult();
}

void
SqlParser::SelfSetAttrTablePrivileges()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "GRANTOR", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PRIVILEGE", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "IS_GRANTABLE", &View);
   sa->getAttr()->setType (T_CSTRING, 3, 0);
   Info.AddItem (sa);
}

Error
SqlParser::TablePrivileges (char *szTableQualifier, short cbTableQualifier,
                            char *szTableOwner,     short cbTableOwner,
                            char *__szTableName,    short __cbTableName)
{
   Clear();

   SelfSetAttrTablePrivileges();

   return EmptyResult();
}

void
SqlParser::SelfSetAttrColumnPrivileges()
{
   StmtAttr *sa;

   sa = new StmtAttr (*DB, "TABLE_QUALIFIER", &View);
   sa->getAttr()->setType (T_CSTRING, 40, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_OWNER", &View);
   sa->getAttr()->setType (T_CSTRING, 20, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "TABLE_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "COLUMN_NAME", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "GRANTOR", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "GRANTEE", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "PRIVILEGE", &View);
   sa->getAttr()->setType (T_CSTRING, 32, 0);
   Info.AddItem (sa);

   sa = new StmtAttr (*DB, "IS_GRANTABLE", &View);
   sa->getAttr()->setType (T_CSTRING, 3, 0);
   Info.AddItem (sa);
}

Error
SqlParser::ColumnPrivileges (char *szTableQualifier, short cbTableQualifier,
                             char *szTableOwner,     short cbTableOwner,
                             char *__szTableName,    short __cbTableName,
                             char *szColumnName,    short cbColumnName)
{
   Clear();

   SelfSetAttrColumnPrivileges();

   return EmptyResult();
}
