SqlDate.h

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calculator/SqlDate.h#3 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 //
00022 // SqlDate
00023 //
00024 // Sql date/time/timestamp functionality.
00025 */
00026 #ifndef Fennel_SqlDate_Included
00027 #define Fennel_SqlDate_Included
00028 
00029 // this include needs to come first, since some int64 macros in ICU conflicts
00030 // with the boost ones.  Fortunately ICU is smart enough.
00031 #include <boost/date_time/posix_time/posix_time.hpp>
00032 #include <boost/date_time/local_time/local_time.hpp>
00033 #include <boost/date_time/gregorian/gregorian_types.hpp>
00034 #include <boost/date_time/c_local_time_adjustor.hpp>
00035 
00036 #ifdef HAVE_ICU
00037 #include <unicode/ustring.h>
00038 #endif
00039 
00040 
00041 FENNEL_BEGIN_NAMESPACE
00042 
00043 #if !(defined LITTLEENDIAN || defined BIGENDIAN)
00044 #error "endian not defined"
00045 #endif
00046 
00053 enum SqlDateTimeType {
00054     SQLDATE,
00055     SQLTIME,
00056     SQLTIMESTAMP
00057 };
00058 
00059 boost::posix_time::ptime const epoc(boost::gregorian::date(1970,1,1));
00060 
00061 int FENNEL_CALCULATOR_EXPORT TimeToIsoString(
00062     char *dest, boost::posix_time::ptime t);
00063 int FENNEL_CALCULATOR_EXPORT DateToIsoString(
00064     char *dest, boost::posix_time::ptime t);
00065 int FENNEL_CALCULATOR_EXPORT TimestampToIsoString(
00066     char *dest, boost::posix_time::ptime t);
00067 
00068 int64_t FENNEL_CALCULATOR_EXPORT IsoStringToTime(
00069     char const * const src, int len);
00070 int64_t FENNEL_CALCULATOR_EXPORT IsoStringToDate(
00071     char const * const src, int len);
00072 int64_t FENNEL_CALCULATOR_EXPORT IsoStringToTimestamp(
00073     char const * const src, int len);
00074 
00075 template <
00076     int CodeUnitBytes,
00077     int MaxCodeUnitsPerCodePoint,
00078     SqlDateTimeType dateTimeType>
00079 int
00080 SqlDateToStr(
00081     char *dest,
00082     int destStorageBytes,
00083     int64_t const d,
00084     bool fixed = false,  // e.g. char, else variable (varchar)
00085     int padchar = ' ')
00086 {
00087     using namespace boost::posix_time;
00088     using namespace boost::gregorian;
00089 
00090     typedef boost::date_time::c_local_adjustor<boost::posix_time::ptime>
00091         local_adj;
00092     if (CodeUnitBytes == MaxCodeUnitsPerCodePoint) {
00093         if (CodeUnitBytes == 1) {
00094             // ASCII
00095 
00096             // from_time_t isn't in the version of boost we're using. sigh.
00097             // FIXME: jhyde: No longer true. Let's use it.
00098             //   boost::posix_time::ptime t = boost::posix_time::from_time_t(d);
00099 
00100             // we could use the millisecond() duration constructor,
00101             // instead of time_duration(...), but the time_duration was
00102             // the only way i could find didn't use an explicit long
00103             // parameter, instead of the type parameter, since
00104             // int64_t == (long long) on (fc1) linux.
00105             boost::posix_time::ptime t = epoc + time_duration(0,0,0,d);
00106 
00107             int len;
00108             char buf[20];
00109             switch (dateTimeType) {
00110             case SQLDATE:
00111                 len = DateToIsoString(buf, t);
00112                 if (len > destStorageBytes) {
00113                     // SQL99 Part 2 Section 6.22 General Rule 9.a.iii =>
00114                     // exception SQL99 22.1 22-001 "String Data Right
00115                     // truncation"
00116                     throw "22001";
00117                 }
00118                 memcpy(dest,buf,len);
00119                 break;
00120             case SQLTIME:
00121                 len = TimeToIsoString(buf, t);
00122                 if (len > destStorageBytes) {
00123                     // SQL99 Part 2 Section 6.22 General Rule 9.a.iii =>
00124                     // exception SQL99 22.1 22-001 "String Data Right
00125                     // truncation"
00126                     throw "22001";
00127                 }
00128                 memcpy(dest,buf,len);
00129                 break;
00130             case SQLTIMESTAMP:
00131                 len = TimestampToIsoString(buf, t);
00132                 if (len > destStorageBytes) {
00133                     // SQL99 Part 2 Section 6.22 General Rule 9.a.iii =>
00134                     // exception SQL99 22.1 22-001 "String Data Right
00135                     // truncation"
00136                     throw "22001";
00137                 }
00138                 memcpy(dest,buf,len);
00139                 break;
00140             default:
00141                 throw std::logic_error("bad dateTimeType" + dateTimeType);
00142             }
00143 
00144             if (fixed) {
00145                 memset(dest + len, padchar, destStorageBytes - len);
00146                 return destStorageBytes;
00147             } else {
00148                 return len;
00149             }
00150         } else if (CodeUnitBytes == 2) {
00151             // TODO: Add UCS2 here
00152             throw std::logic_error("no UCS2");
00153         } else {
00154             throw std::logic_error("no such encoding");
00155         }
00156     } else {
00157         throw std::logic_error("no UTF8/16/32");
00158     }
00159 
00160 }
00161 
00162 template <
00163     int CodeUnitBytes,
00164     int MaxCodeUnitsPerCodePoint,
00165     SqlDateTimeType dateTimeType>
00166 int64_t
00167 SqlStrToDate(char *src, int len)
00168 {
00169     using namespace boost::posix_time;
00170     using namespace boost::gregorian;
00171 
00172     if (CodeUnitBytes == MaxCodeUnitsPerCodePoint) {
00173         if (CodeUnitBytes == 1) {
00174             // ASCII
00175 
00176             switch (dateTimeType) {
00177             case SQLDATE:
00178                 return IsoStringToDate(src,len);
00179             case SQLTIME:
00180                 return IsoStringToTime(src,len);
00181             case SQLTIMESTAMP:
00182                 return IsoStringToTimestamp(src,len);
00183             }
00184         } else if (CodeUnitBytes == 2) {
00185             // TODO: Add UCS2 here
00186             throw std::logic_error("no UCS2");
00187         } else {
00188             throw std::logic_error("no such encoding");
00189         }
00190     } else {
00191         throw std::logic_error("no UTF8/16/32");
00192     }
00193 }
00194 
00199 int64_t FENNEL_CALCULATOR_EXPORT UniversalTime();
00200 
00206 int64_t FENNEL_CALCULATOR_EXPORT UniversalTimestamp();
00207 
00209 int64_t FENNEL_CALCULATOR_EXPORT LocalTime(
00210     boost::local_time::time_zone_ptr tzPtr);
00211 
00213 int64_t FENNEL_CALCULATOR_EXPORT LocalTimestamp(
00214     boost::local_time::time_zone_ptr tzPtr);
00215 
00216 FENNEL_END_NAMESPACE
00217 
00218 #endif
00219 
00220 // End SqlDate.h

Generated on Mon Jun 22 04:00:17 2009 for Fennel by  doxygen 1.5.1