Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbiFieldType.cxx

Go to the documentation of this file.
00001 // $Id: DbiFieldType.cxx,v 1.28 2007/07/03 11:42:37 west Exp $
00002 
00003 
00004 
00008 
00009 
00010 
00011 #include <iostream>
00012 
00013 #include <sstream>
00014 
00015 #include "TSQLServer.h"
00016 #include "TString.h"
00017 
00018 #include "DatabaseInterface/DbiFieldType.h"
00019 #include "LeakChecker/Lea.h"
00020 #include "MessageService/MsgService.h"
00021 
00022 ClassImp(DbiFieldType)
00023 
00024 //   Definition of static data members
00025 //   *********************************
00026 
00027 CVSID("$Id: DbiFieldType.cxx,v 1.28 2007/07/03 11:42:37 west Exp $");
00028 
00029 //    Definition of all member functions (static or otherwise)
00030 //    *******************************************************
00031 //
00032 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00033 
00034 //.....................................................................
00035 
00036 DbiFieldType::DbiFieldType(Int_t type /* = Dbi::kInt */) 
00037 {
00038 //
00039 //
00040 //  Purpose:  Default constructor
00041 //
00042 //  Arguments:   
00043 //    type     in    Data type  (default Dbi::kInt).
00044 
00045 
00046   LEA_CTOR    //Leak Checker
00047 
00048   this->Init(type);
00049 
00050 }
00051 //.....................................................................
00052 
00053 DbiFieldType::DbiFieldType(Int_t type,
00054                            Int_t size,
00055                            const char* typeName) {
00056 
00057 
00058 //
00059 //
00060 //  Purpose:  Constructor for TSQL meta-data.
00061 //
00062 //  Arguments:   
00063 //    type      in    value from TSQLColumnInfo::GetSQLType()
00064 //    size      in    value from TSQLColumnInfo::GetLength()
00065 //    typeName  in    value from TSQLColumnInfo::GetTypeName()
00066 
00067   LEA_CTOR    //Leak Checker
00068     
00069   TString name(typeName);
00070   name.ToUpper();
00071 
00072   // Handle integer types.
00073 
00074   if ( type == TSQLServer::kSQL_INTEGER || type == TSQLServer::kSQL_NUMERIC ) {
00075 
00076     // TSQLServer reports e.g. int(32) as size 32, (even though maximum display is 11)
00077     // so treat any type starting int or INT as size kMaxInt (i.e. standard 4 byte int)
00078     if ( name.BeginsWith("INT") ) size = kMaxInt;
00079     if      ( size <= kMaxTinyInt  ) { this->Init(Dbi::kTiny);  return; }
00080     else if ( size <= kMaxSmallInt ) { this->Init(Dbi::kShort); return; }
00081     else if ( size <= kMaxInt      ) { this->Init(Dbi::kInt);   return; }
00082     else                             { this->Init(Dbi::kLong);  return; }
00083 
00084   }
00085 
00086   // Handle floating point types
00087 
00088   if ( type == TSQLServer::kSQL_FLOAT  ) { this->Init(Dbi::kFloat);  return; } 
00089   if ( type == TSQLServer::kSQL_DOUBLE ) { this->Init(Dbi::kDouble);  return; } 
00090 
00091   // Handle cases where type is determined uniquely by type name.
00092 
00093   if ( name == "BINARY_FLOAT" )  { this->Init(Dbi::kFloat);  return; }
00094   if ( name == "BINARY_DOUBLE" ) { this->Init(Dbi::kDouble); return; }
00095   if ( name == "TINYTEXT" )      { this->Init(Dbi::kString,kMaxMySQLVarchar);   return; }
00096   if ( name == "TEXT" )          { this->Init(Dbi::kString,kMaxMySQLText);   return; }
00097   if ( name == "DATE" )          { this->Init(Dbi::kDate);   return; }
00098   if ( name == "DATETIME" )      { this->Init(Dbi::kDate);   return; }
00099 
00100   // Handle character types
00101 
00102   if ( type == TSQLServer::kSQL_CHAR && size <= kMaxChar ) {
00103     this->Init(Dbi::kChar,size);
00104     return;
00105   }
00106   if ( type == TSQLServer::kSQL_CHAR || type == TSQLServer::kSQL_VARCHAR ) {
00107     if ( size < kMaxMySQLVarchar ) Init(Dbi::kString,size);
00108     else                           Init(Dbi::kString,kMaxMySQLText);
00109     return;
00110   }
00111 
00112   // Anything else is bad news!
00113 
00114   MAXMSG("Dbi",Msg::kError,20) 
00115         << "Unable to form SQL DbiFieldType from: " << type << endl;
00116   this->Init(Dbi::kUnknown);
00117 
00118 }
00119 
00120 //.....................................................................
00121 
00122 DbiFieldType::DbiFieldType(const DbiFieldType& from)
00123 {
00124 //
00125 //
00126 //  Purpose:  Copy constructor
00127 
00128 //  Program Notes:-
00129 //  =============
00130 
00131 //  Make explicit for leak checking.
00132 
00133   LEA_CTOR    //Leak Checker
00134 
00135   *this = from;
00136 }
00137 
00138 //.....................................................................
00139 
00140 DbiFieldType::DbiFieldType(const string& sql,
00141                            Int_t size )
00142 {
00143 //
00144 //
00145 //  Purpose:  Constructor from a MySQL type string
00146 
00147 
00148   LEA_CTOR    //Leak Checker
00149 
00150 
00151   if (         sql == "TINYINT" )   this->Init(Dbi::kTiny); 
00152 
00153   else if (    sql == "SMALLINT" )  this->Init(Dbi::kShort);
00154 
00155   else if (    sql == "INT" 
00156             || sql == "INTEGER" 
00157             || sql == "NUMERIC" )   this->Init(Dbi::kInt);
00158 
00159   else if (     sql == "BIGINT" )   this->Init(Dbi::kLong);
00160 
00161   else if (    sql == "FLOAT"  
00162             || sql == "REAL")       this->Init(Dbi::kFloat);
00163 
00164   else if (    sql == "DOUBLE" )    this->Init(Dbi::kDouble);
00165 
00166   else if (    sql == "CHAR" 
00167             || sql == "VARCHAR"
00168             || sql == "TEXT"  
00169             || sql == "TINYTEXT" ) {
00170 
00171     if      ( sql == "TINYTEXT" ) size = kMaxMySQLVarchar;
00172     else if ( sql == "TEXT"     ) size = kMaxMySQLText;
00173     else {
00174       if ( size < 0 ) {
00175         if ( sql == "CHAR" ) size = 1;
00176         else                 size = kMaxMySQLVarchar -1;
00177       }
00178     }
00179     if ( fSize <= kMaxChar ) this->Init(Dbi::kChar,size);
00180     else                     this->Init(Dbi::kString,size);
00181 
00182   }
00183 
00184   else if ( sql == "DATETIME" )     this->Init(Dbi::kDate);
00185 
00186   else {
00187     MAXMSG("Dbi",Msg::kError,20) 
00188       << "Unable to type from SQL: " << sql << endl;
00189                                     this->Init(Dbi::kUnknown);
00190   }
00191     
00192 }
00193 
00194 
00195 //.....................................................................
00196 
00197 DbiFieldType::~DbiFieldType() {
00198 //
00199 //
00200 //  Purpose: Destructor
00201 //
00202 //  Arguments: 
00203 //    None.
00204 //
00205 //  Return:    n/a
00206 //
00207 //  Contact:   N. West
00208 //
00209 //  Specification:-
00210 //  =============
00211 //
00212 //  o  Destroy FieldType.
00213 
00214 
00215 //  Program Notes:-
00216 //  =============
00217 
00218 //  None.
00219 
00220   LEA_DTOR    //Leak Checker
00221 
00222 
00223 }
00224 
00225 //.....................................................................
00226 
00227 string DbiFieldType::AsString() const {
00228 //
00229 //
00230 //  Purpose:  Return field type as a string.
00231 //
00232 //  Arguments: None.
00233 //
00234 //  Return:    Field type as a string e.g. "Int"
00235 //
00236 //  Contact:   N. West
00237 //
00238 //  Specification:-
00239 //  =============
00240 //
00241 //  o Return field type as a string.
00242 
00243 //  Program Notes:-
00244 //  =============
00245 
00246 //  None.
00247 
00248   switch ( fType ) {
00249 
00250   case  Dbi::kBool    : return "Bool";  
00251   case  Dbi::kChar    : return "Char";
00252   case  Dbi::kUChar   : return "UChar";
00253   case  Dbi::kTiny    : return "Tiny";
00254   case  Dbi::kUTiny   : return "UTiny";
00255   case  Dbi::kShort   : return "Short";
00256   case  Dbi::kUShort  : return "UShort";
00257   case  Dbi::kInt     : return "Int";
00258   case  Dbi::kUInt    : return "UInt";
00259   case  Dbi::kLong    : return "Long";
00260   case  Dbi::kULong   : return "ULong";
00261   case  Dbi::kFloat   : return "Float";
00262   case  Dbi::kDouble  : return "Double";
00263   case  Dbi::kString  : return "String";
00264   case  Dbi::kTString : return "TString";
00265   case  Dbi::kDate    : return "Date";
00266   }
00267   return "Unknown";
00268 }
00269 //.....................................................................
00270 
00271 string DbiFieldType::AsSQLString(Dbi::DbTypes dbType) const {
00272 //
00273 //
00274 //  Purpose:  Return field type as a string suitable for MySQL/ORACLE column.
00275 
00276   ostringstream os;
00277 
00278 //  Deal with MySQL ddl
00279 
00280   if ( dbType != Dbi::kOracle ) {
00281     switch ( fType ) {
00282     
00283       case  Dbi::kBool    :   os << "CHAR";          break;
00284 
00285       case  Dbi::kUTiny   :
00286       case  Dbi::kTiny    :   os << "TINYINT";       break;
00287 
00288       case  Dbi::kShort   : 
00289       case  Dbi::kUShort  :   os << "SMALLINT";      break;
00290 
00291       case  Dbi::kInt     : 
00292       case  Dbi::kUInt    :   os << "INT";           break;
00293 
00294       case  Dbi::kLong    : 
00295       case  Dbi::kULong   :   os << "BIGINT";        break;
00296 
00297       case  Dbi::kFloat   :   os << "FLOAT";         break;
00298 
00299       case  Dbi::kDouble  :   os << "DOUBLE";        break;
00300 
00301       case  Dbi::kChar    : 
00302       case  Dbi::kUChar   : 
00303       case  Dbi::kString  : 
00304       case  Dbi::kTString : 
00305         if      ( fSize == 1)                os << "CHAR";
00306         else if ( fSize <= kMaxChar)         os << "CHAR("    << fSize << ')';
00307         else if ( fSize <  kMaxMySQLVarchar) os << "VARCHAR(" << fSize << ')';
00308         else if ( fSize == kMaxMySQLVarchar) os << "TINYTEXT";
00309         else                                 os << "TEXT";
00310         break;
00311 
00312       case  Dbi::kDate    :   os << "DATETIME";      break;
00313 
00314       default :               os << "Unknown";
00315 
00316     }
00317   }
00318 
00319   else {
00320 
00321 //  Deal with ORACLE ddl
00322 
00323 
00324     int size = fSize;
00325     if ( fSize < kMaxOracleVarchar ) size = kMaxOracleVarchar;
00326 
00327     switch ( fType ) {
00328 
00329       case  Dbi::kBool    :   os << "CHAR";          break;
00330 
00331       case  Dbi::kUTiny   :
00332       case  Dbi::kTiny    :   os << "NUMBER(4)";     break;
00333 
00334       case  Dbi::kShort   : 
00335       case  Dbi::kUShort  :   os << "NUMBER(6)";     break;
00336 
00337       case  Dbi::kInt     : 
00338       case  Dbi::kUInt    :   os << "NUMBER(11)";    break;
00339 
00340       case  Dbi::kLong    : 
00341       case  Dbi::kULong   :   os << "NUMBER(20)";    break;
00342 
00343       case  Dbi::kFloat   :   os << "BINARY_FLOAT";  break;
00344 
00345       case  Dbi::kDouble  :   os << "BINARY_DOUBLE"; break;
00346 
00347       case  Dbi::kChar    : 
00348       case  Dbi::kUChar   : 
00349       case  Dbi::kString  : 
00350       case  Dbi::kTString :
00351         if      ( size == 1)        os << "CHAR";
00352         else if ( size <= kMaxChar) os << "CHAR("    << size << ')';
00353         else                        os << "VARCHAR(" << size << ')';
00354         break;
00355 
00356       case  Dbi::kDate    :   os << "DATE";          break;
00357 
00358       default :               os << "Unknown";
00359 
00360     }
00361   }
00362 
00363   return os.str();
00364 
00365 }
00366 
00367 
00368 //.....................................................................
00369 
00370 
00371 void DbiFieldType::Init(Int_t type  /* Type as defined by Dbi::DataTypes */, 
00372                         Int_t size  /* Size in bytes (default: -1 - take size from type)*/ ) {
00373 //
00374 //
00375 //  Purpose:  Initialise object.
00376 //
00377 
00378   switch ( type ) {
00379 
00380   case Dbi::kBool : 
00381       fType      = Dbi::kBool; 
00382       fConcept   = Dbi::kBool;
00383       fSize      = 1;
00384       break;
00385 
00386     case Dbi::kChar :
00387       fType      = Dbi::kChar;
00388       fConcept   = Dbi::kChar;
00389       fSize      = 1;
00390       break;
00391 
00392     case Dbi::kUChar :
00393       fType      = Dbi::kUChar;
00394       fConcept   = Dbi::kUChar;
00395       fSize      = 1;
00396       break;
00397 
00398     case Dbi::kTiny :
00399       fType      = Dbi::kTiny;
00400       fConcept   = Dbi::kInt;
00401       fSize      = 1;
00402       break;
00403 
00404     case Dbi::kUTiny :
00405       fType      = Dbi::kUTiny;
00406       fConcept   = Dbi::kUInt;
00407       fSize      = 1;
00408       break;
00409 
00410     case Dbi::kShort :
00411       fType      = Dbi::kShort;
00412       fConcept   = Dbi::kInt;
00413       fSize      = 2;
00414       break;
00415 
00416     case Dbi::kUShort :
00417       fType      = Dbi::kUShort;
00418       fConcept   = Dbi::kUInt;
00419       fSize      = 2;
00420       break;
00421 
00422     case Dbi::kInt :
00423       fType      = Dbi::kInt;
00424       fConcept   = Dbi::kInt;
00425       fSize      = 4;
00426       break;
00427 
00428     case Dbi::kUInt :
00429       fType      = Dbi::kUInt;
00430       fConcept   = Dbi::kUInt;
00431       fSize      = 4;
00432       break;
00433 
00434     case Dbi::kLong :
00435       fType    = Dbi::kLong;
00436       fConcept = Dbi::kInt;
00437       fSize    = 8;
00438       break;
00439 
00440     case Dbi::kULong :
00441       fType    = Dbi::kULong;
00442       fConcept = Dbi::kUInt;
00443       fSize    = 8;
00444       break;
00445 
00446     case Dbi::kFloat :
00447       fType      = Dbi::kFloat;
00448       fConcept   = Dbi::kFloat;
00449       fSize      = 4;
00450       break;
00451 
00452     case Dbi::kDouble :
00453       fType      = Dbi::kDouble;
00454       fConcept   = Dbi::kFloat;
00455       fSize      = 8;
00456       break;
00457 
00458     case Dbi::kString :
00459       fType      = Dbi::kString;
00460       fConcept   = Dbi::kString;
00461       fSize      = 65535;
00462       break;
00463 
00464     case Dbi::kTString :
00465       fType      = Dbi::kTString;
00466       fConcept   = Dbi::kString;
00467       fSize      = 65535;
00468       break;
00469 
00470     case Dbi::kDate :
00471       fType      = Dbi::kDate;
00472       fConcept   = Dbi::kDate;
00473       fSize      = 4;
00474       break;
00475 
00476     case Dbi::kUnknown :
00477       fType      = Dbi::kUnknown;
00478       fConcept   = Dbi::kUnknown;
00479       break;
00480 
00481     default : 
00482       MAXMSG("Dbi",Msg::kError,20)
00483         << "Unable to form Root DbiFieldType from: " << type << endl;
00484       fType      = Dbi::kUnknown;
00485       fConcept   = Dbi::kUnknown;
00486       fSize      = 0;
00487   }
00488 
00489   // Override fSize if necessary.
00490 
00491   if ( size      >= 0  ) fSize      = size;
00492 
00493 }
00494 
00495 //.....................................................................
00496 
00497 Bool_t DbiFieldType::IsCompatible(const DbiFieldType& other) const {
00498 //
00499 //
00500 //  Purpose: Return kTRUE if this is compatible with or can accept
00501 //           the other type. 
00502 //
00503 //  Arguments: 
00504 //    other        in    The DbiFieldType to be compared
00505 //
00506 //  Return: kTRUE if the this type can accept other type.    
00507 //
00508 //  Contact:   N. West
00509 //
00510 //  Specification:-
00511 //  =============
00512 //
00513 //  o If the two types have the same concept or have compatible 
00514 //    concepts return kTRUE.
00515 //
00516 //  o Also return true if the other type can be be used as input.
00517 //
00518 
00519 //  Program Notes:-
00520 //  =============
00521 
00522 //  None.
00523 
00524 #define MATCHES(x,y)  \
00525      (fConcept == x) && (concept == y) \
00526   || (fConcept == y) && (concept == x) 
00527   UInt_t concept = other.GetConcept();
00528   if ( fConcept == concept ) return kTRUE;
00529   if ( MATCHES(Dbi::kBool,  Dbi::kChar)  ) return kTRUE;
00530   if ( MATCHES(Dbi::kBool,  Dbi::kUChar) ) return kTRUE;
00531   if ( MATCHES(Dbi::kInt,   Dbi::kChar)  ) return kTRUE;
00532   if ( MATCHES(Dbi::kUInt,  Dbi::kUChar) ) return kTRUE;
00533 //  Allow unsigned to match signed because the TSQLResultSetL interface
00534 //  does not support unsigned types but its GetShort and GetInt
00535 //  methods will return unsigned data intact so we must trust
00536 //  that the user knows what they are doing!
00537   if ( MATCHES(Dbi::kUInt,  Dbi::kInt)   ) return kTRUE;
00538 //  Allow char to be input to string.
00539   if ( concept == Dbi::kChar && fConcept == Dbi::kString ) return kTRUE;
00540 
00541 return kFALSE;
00542 
00543 }
00544 
00545 //.....................................................................
00546 
00547 string DbiFieldType::UndefinedValue() const {
00548 //
00549 //
00550 //  Purpose:  Return value to be used when unknown.
00551 //
00552 //  Arguments: None
00553 //
00554 //  Return:   Value as a string to be used when unknown. 
00555 //
00556 //  Contact:   N. West
00557 //
00558 //  Specification:-
00559 //  =============
00560 //
00561 //  o Return value to be used when unknown.
00562 
00563 //  Program Notes:-
00564 //  =============
00565 
00566 //  For each conceptual data type there is an associated 
00567 //  data type to be used when attemping to get value from outside
00568 //  the table or when table type incompatible with data.
00569 
00570 
00571   switch ( fConcept ) {
00572     case Dbi::kBool   : return "0";
00573     case Dbi::kChar   : return "";
00574     case Dbi::kUChar  : return "";
00575     case Dbi::kInt    : return "-999";
00576     case Dbi::kUInt   : return " 999";
00577     case Dbi::kFloat  : return "-999.";
00578     case Dbi::kString : return "";
00579     case Dbi::kDate   : return "1980-00-00 00:00:00";
00580 
00581     default : 
00582       MAXMSG("Dbi",Msg::kError,20) << "Unable to define undefined type for: " 
00583             << fConcept << endl;
00584       return "";
00585   }
00586 }
00587 

Generated on Mon Feb 15 11:06:34 2010 for loon by  doxygen 1.3.9.1