[prev in list] [next in list] [prev in thread] [next in thread]
List: fdo-commits
Subject: [fdo-commits] r4862 - in trunk/Providers/SQLite/Src: Provider
From: svn_fdo () osgeo ! org
Date: 2009-07-27 15:52:23
Message-ID: 20090727155223.98047E000B8 () lists ! osgeo ! org
[Download RAW message or body]
Author: romicadascalescu
Date: 2009-07-27 11:52:22 -0400 (Mon, 27 Jul 2009)
New Revision: 4862
Modified:
trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp
trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h
trunk/Providers/SQLite/Src/Provider/SltExprExtensions.cpp
trunk/Providers/SQLite/Src/Provider/SltExprExtensions.h
trunk/Providers/SQLite/Src/Provider/SltProvider.cpp
trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.cpp
trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.h
trunk/Providers/SQLite/Src/Provider/SltReader.cpp
trunk/Providers/SQLite/Src/Provider/StringUtil.h
trunk/Providers/SQLite/Src/Provider/stdafx.h
trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.cpp
trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.h
Log:
#504 SQLite improvements: implement ToDate & ToString(date, format) functions
- Implement ToDate using a format.
- Implement ToString(date, [format])
- Added support in ToString for day of the week
- Fixed calculations based on other calculations failed to execute the query
- Improve the performance of query translator by using direct conversion
functions.
- fixed cases like: "date > string date" in provider query translator
Modified: trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp 2009-07-26 00:53:36 \
UTC (rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/SltConversionUtils.cpp 2009-07-27 15:52:22 \
UTC (rev 4862) @@ -19,6 +19,7 @@
#include "stdafx.h"
#include "SpatialIndex.h"
#include "SltConversionUtils.h"
+#include <locale.h>
std::string W2A_SLOW(const wchar_t* input)
{
@@ -195,10 +196,12 @@
else if (dt->IsTime())
{
_snprintf(s, nBytes, "%02d:%02d:%0.3f", dt->hour, dt->minute, dt->seconds);
+ EnsureNoIsLocalIndep(s);
}
else
{
_snprintf(s, nBytes, "%04d-%02d-%02dT%02d:%02d:%0.3f", dt->year, dt->month, \
dt->day, dt->hour, dt->minute, dt->seconds); + EnsureNoIsLocalIndep(s);
}
}
@@ -289,9 +292,9 @@
{
FdoDateTimeValue* v = (FdoDateTimeValue*)dv;
FdoDateTime dtm = v->GetDateTime();
- char s[64];
+ char s[31];
- DateToString(&dtm, s, 64);
+ DateToString(&dtm, s, 31);
rc = sqlite3_bind_text(stmt, i, s, -1, SQLITE_TRANSIENT);
}
@@ -365,4 +368,97 @@
}
}
+SLT_API TokenDateFormatType StringToDateFormat(const char* specifier)
+{
+ if (strncmp(specifier, "YY", 2) == 0)
+ return TokenDateFormatType_Year2;
+ if (strncmp(specifier, "YYYY", 4) == 0)
+ return TokenDateFormatType_Year4;
+
+ if (strncmp(specifier, "MONTH", 5) == 0)
+ return TokenDateFormatType_Month_FullName_All_Upper;
+
+ if (strncmp(specifier, "Month", 5) == 0)
+ return TokenDateFormatType_Month_FullName_First_Upper;
+
+ if (strncmp(specifier, "month", 5) == 0)
+ return TokenDateFormatType_Month_FullName_All_Lower;
+
+ if (strncmp(specifier, "MON", 3) == 0)
+ return TokenDateFormatType_Month_AbbName_All_Upper;
+
+ if (strncmp(specifier, "mon", 3) == 0)
+ return TokenDateFormatType_Month_AbbName_All_Lower;
+
+ if (strncmp(specifier, "MM", 2) == 0)
+ return TokenDateFormatType_Month_Number;
+
+ if (strncmp(specifier, "DAY", 3) == 0)
+ return TokenDateFormatType_Day_FullName_All_Upper;
+
+ if (strncmp(specifier, "Day", 3) == 0)
+ return TokenDateFormatType_Day_FullName_First_Upper;
+
+ if (strncmp(specifier, "day", 3) == 0)
+ return TokenDateFormatType_Day_FullName_All_Lower;
+
+ if (strncmp(specifier, "DY", 2) == 0)
+ return TokenDateFormatType_Day_AbbName_All_Upper;
+
+ if (strncmp(specifier, "dy", 2) == 0)
+ return TokenDateFormatType_Day_AbbName_All_Lower;
+
+ if (strncmp(specifier, "DD", 2) == 0)
+ return TokenDateFormatType_Day_Number;
+
+ if (strncmp(specifier, "hh24", 4) == 0 || strncmp(specifier, "hh", 2) == 0)
+ return TokenDateFormatType_Hour24;
+
+ if (strncmp(specifier, "hh12", 4) == 0)
+ return TokenDateFormatType_Hour12;
+
+ if (strncmp(specifier, "mm", 2) == 0)
+ return TokenDateFormatType_Minute;
+
+ if (strncmp(specifier, "ss", 2) == 0)
+ return TokenDateFormatType_Second;
+
+ if (strncmp(specifier, "am", 2) == 0 || strncmp(specifier, "AM", 2) == 0)
+ return TokenDateFormatType_am;
+
+ if (strncmp(specifier, "pm", 2) == 0 || strncmp(specifier, "PM", 2) == 0)
+ return TokenDateFormatType_pm;
+
+ // should we thow an exception !?
+ // we lose custom formats like "My date YY/MM/DD"
+ return TokenDateFormatType_Unknown;
+}
+
+char* EnsureNoIsLocalIndep(char* str)
+{
+ char* strtmp = str;
+ struct lconv* nls = localeconv();
+ char radix = (nls != NULL && *nls->decimal_point != '\0') ? *nls->decimal_point \
: '.'; + if (radix == '.')
+ {
+ while(*strtmp != '\0' && *strtmp != radix) strtmp++;
+ if (*strtmp == radix)
+ *strtmp = '.';
+ }
+ return str;
+}
+
+wchar_t* EnsureNoIsLocalIndep(wchar_t* str)
+{
+ wchar_t* strtmp = str;
+ struct lconv* nls = localeconv();
+ wchar_t radix = (nls != NULL && *nls->decimal_point != L'\0') ? \
*nls->decimal_point : L'.'; + if (radix == L'.')
+ {
+ while(*strtmp != L'\0' && *strtmp != radix) strtmp++;
+ if (*strtmp == radix)
+ *strtmp = L'.';
+ }
+ return str;
+}
Modified: trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h 2009-07-26 00:53:36 UTC \
(rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/SltConversionUtils.h 2009-07-27 15:52:22 UTC \
(rev 4862) @@ -22,6 +22,32 @@
struct DBounds;
struct sqlite3_stmt;
+enum TokenDateFormatType
+{
+ TokenDateFormatType_Unknown,
+ TokenDateFormatType_Separator,
+ TokenDateFormatType_Year2,
+ TokenDateFormatType_Year4,
+ TokenDateFormatType_Month_AbbName_All_Lower,
+ TokenDateFormatType_Month_AbbName_All_Upper,
+ TokenDateFormatType_Month_FullName_All_Lower,
+ TokenDateFormatType_Month_FullName_All_Upper,
+ TokenDateFormatType_Month_FullName_First_Upper,
+ TokenDateFormatType_Month_Number,
+ TokenDateFormatType_Day_AbbName_All_Lower,
+ TokenDateFormatType_Day_AbbName_All_Upper,
+ TokenDateFormatType_Day_FullName_All_Lower,
+ TokenDateFormatType_Day_FullName_All_Upper,
+ TokenDateFormatType_Day_FullName_First_Upper,
+ TokenDateFormatType_Day_Number,
+ TokenDateFormatType_Hour24,
+ TokenDateFormatType_Hour12,
+ TokenDateFormatType_Minute,
+ TokenDateFormatType_Second,
+ TokenDateFormatType_am,
+ TokenDateFormatType_pm
+};
+
SLT_API std::string W2A_SLOW(const wchar_t* input);
SLT_API std::wstring A2W_SLOW(const char* input);
@@ -40,5 +66,10 @@
SLT_API void BindPropValue(sqlite3_stmt* stmt, int i, FdoLiteralValue* lv);
SLT_API int StringContains(const char* str, const char* val);
+SLT_API TokenDateFormatType StringToDateFormat(const char* specifier);
+
+SLT_API char* EnsureNoIsLocalIndep(char* str);
+SLT_API wchar_t* EnsureNoIsLocalIndep(wchar_t* str);
+
#endif
Modified: trunk/Providers/SQLite/Src/Provider/SltExprExtensions.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltExprExtensions.cpp 2009-07-26 00:53:36 UTC \
(rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/SltExprExtensions.cpp 2009-07-27 15:52:22 UTC \
(rev 4862) @@ -4,6 +4,7 @@
#include "SltConversionUtils.h"
#include "SltGeomUtils.h"
#include "FdoCommonOSUtil.h"
+#include "StringUtil.h"
#include <math.h>
#include <algorithm>
#include <limits> // For quiet_NaN()
@@ -18,6 +19,569 @@
len = (z2 - str); \
\ } \
\
+class DateTokenFormat;
+
+class DateToken
+{
+ friend class DateTokenFormat;
+ std::string m_value;
+ TokenDateFormatType m_type;
+private:
+ DateToken(const char* val, TokenDateFormatType type = \
TokenDateFormatType_Unknown) + : m_type(type), m_value(val)
+ {
+
+ }
+ DateToken(const char* val, size_t sz, TokenDateFormatType type = \
TokenDateFormatType_Unknown) + : m_type(type)
+ {
+ m_value = std::string(val, sz);
+ }
+public:
+ size_t GetTokenLen()
+ {
+ return m_value.size();
+ }
+ const char* GetTokenValue()
+ {
+ return m_value.c_str();
+ }
+ TokenDateFormatType GetTokenType()
+ {
+ return m_type;
+ }
+};
+
+class DateTokenFormat
+{
+ std::vector<DateToken*> m_values;
+ StringBuffer m_result;
+ bool m_hasValidTokens;
+
+public:
+ DateTokenFormat() : m_hasValidTokens(false)
+ {
+ }
+ ~DateTokenFormat()
+ {
+ Clear();
+ }
+ void Clear()
+ {
+ for(std::vector<DateToken*>::iterator it = m_values.begin(); it < \
m_values.end(); it++) + delete *it;
+ m_values.clear();
+ }
+ bool HasValidTokens() {return m_hasValidTokens;}
+ DateToken* AddDateToken(const char* val, TokenDateFormatType type = \
TokenDateFormatType_Unknown) + {
+ DateToken* ret = new DateToken(val, type);
+ m_values.push_back(ret);
+ return ret;
+ }
+ DateToken* AddDateToken(const char* val, size_t sz, TokenDateFormatType type = \
TokenDateFormatType_Unknown) + {
+ DateToken* ret = new DateToken(val, sz, type);
+ m_values.push_back(ret);
+ return ret;
+ }
+ bool IsLeapYear (FdoInt16 year)
+ {
+ if (year % 4 != 0) return false;
+ if (year % 100 != 0) return true;
+ return ( year % 400 == 0 );
+ }
+
+ int CountOfFeb29 (FdoInt16 year)
+ {
+ int ret = 0;
+ if( year > 0 )
+ {
+ ret = 1; // Year 0 is a leap year
+ year--; // Year nYear is not in the period
+ }
+ ret += year/4 - year/100 + year/400;
+ return ret;
+ }
+
+ FdoInt8 DayOfWeek(FdoInt16 year, FdoInt8 month, FdoInt8 day)
+ {
+ int ret = 0;
+ const static int daysBeforeMonth[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, \
243, 273, 304, 334, 365}; +
+ if (year < 0 || (month < 1 || month > 12) || !(day <= \
(daysBeforeMonth[month+1]-daysBeforeMonth[month]) || + ( month == 2 && \
day == 29 && IsLeapYear(year) ))) + throw \
FdoException::Create(L"Unexpected result for function ToString"); +
+ // The day of Jan 1, year
+ ret = 6 + year % 7 + CountOfFeb29(year) % 7 + 14;
+ // The day of month 1, year
+ ret += daysBeforeMonth[month];
+ if (month > 2 && IsLeapYear(year))
+ ret++;
+ // The day of month day, year
+ ret += day - 1;
+ ret %= 7;
+ return (FdoInt8)ret;
+ }
+
+ void ProcessFormat(const char* str)
+ {
+ Clear();
+ if (str != NULL && *str != '\0')
+ {
+ size_t startPos = 0;
+ const char* strtmp = str;
+ int state = -1;
+ do
+ {
+ bool isSepChar = !isalnum(*strtmp);
+ switch(state)
+ {
+ case -1: // start
+ state = isSepChar ? 0 : 1;
+ break;
+ case 0: // separators
+ if (!isSepChar)
+ {
+ AddDateToken(str + startPos, (int)(strtmp-str) - startPos, \
TokenDateFormatType_Separator); + state = 1;
+ startPos = (int)(strtmp-str);
+ }
+ break;
+ case 1: // tokens
+ if (isSepChar)
+ {
+ TokenDateFormatType type = StringToDateFormat(str + \
startPos); + if (type != TokenDateFormatType_Unknown && type \
!= TokenDateFormatType_Separator) + m_hasValidTokens = \
true; + AddDateToken(str + startPos, (int)(strtmp-str) - \
startPos, type); + state = 0;
+ startPos = (int)(strtmp-str);
+ }
+ break;
+ }
+ strtmp++;
+ }
+ while (*strtmp != '\0');
+ if (state == 0)
+ AddDateToken(str + startPos, TokenDateFormatType_Separator);
+ else
+ {
+ TokenDateFormatType type = StringToDateFormat(str + startPos);
+ if (type != TokenDateFormatType_Unknown && type != \
TokenDateFormatType_Separator) + m_hasValidTokens = true;
+ AddDateToken(str + startPos, type);
+ }
+ }
+ else
+ {
+ // use the default format e.g. "21-JUL-2009 13:24:14.000"
+ AddDateToken("", TokenDateFormatType_Day_Number);
+ AddDateToken("-", TokenDateFormatType_Separator);
+ AddDateToken("", TokenDateFormatType_Month_AbbName_All_Upper);
+ AddDateToken("-", TokenDateFormatType_Separator);
+ AddDateToken("", TokenDateFormatType_Year4);
+ AddDateToken(" ", TokenDateFormatType_Separator);
+ AddDateToken("", TokenDateFormatType_Hour24);
+ AddDateToken(":", TokenDateFormatType_Separator);
+ AddDateToken("", TokenDateFormatType_Minute);
+ AddDateToken(":", TokenDateFormatType_Separator);
+ AddDateToken("", TokenDateFormatType_Second);
+ m_hasValidTokens = true;
+ }
+ }
+ const char* ToString(FdoDateTime dt)
+ {
+ char tmpUse[31];
+ const char* usePtr = NULL;
+ size_t idx = 0;
+
+ if (m_result.Length() == 0)
+ {
+ for(std::vector<DateToken*>::iterator it = m_values.begin(); it < \
m_values.end(); it++) + {
+ idx = 0;
+ DateToken* tk = *it;
+ switch(tk->GetTokenType())
+ {
+ case TokenDateFormatType_Year2:
+ if (dt.year == -1)
+ m_result.Append("00", 2);
+ else
+ m_result.Append(dt.year, "%04d", 2);
+ break;
+
+ case TokenDateFormatType_Year4:
+ if (dt.year == -1)
+ m_result.Append("0000", 4);
+ else
+ m_result.Append(dt.year, "%04d");
+ break;
+
+ case TokenDateFormatType_Month_AbbName_All_Lower:
+ {
+ FdoInt8 month = (dt.month == -1) ? 1 : dt.month;
+ if (month < 1 || month > 12)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_month_names[month-1];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Tolower(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse, 3);
+ }
+ break;
+
+ case TokenDateFormatType_Month_AbbName_All_Upper:
+ {
+ FdoInt8 month = (dt.month == -1) ? 1 : dt.month;
+ if (month < 1 || month > 12)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_month_names[month-1];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Toupper(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse, 3);
+ }
+ break;
+
+ case TokenDateFormatType_Month_FullName_All_Lower:
+ {
+ FdoInt8 month = (dt.month == -1) ? 1 : dt.month;
+ if (month < 1 || month > 12)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_month_names[month-1];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Tolower(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse);
+ }
+ break;
+
+ case TokenDateFormatType_Month_FullName_All_Upper:
+ {
+ FdoInt8 month = (dt.month == -1) ? 1 : dt.month;
+ if (month < 1 || month > 12)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_month_names[month-1];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Toupper(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse);
+ }
+ break;
+
+ case TokenDateFormatType_Month_FullName_First_Upper:
+ {
+ FdoInt8 month = (dt.month == -1) ? 1 : dt.month;
+ if (month < 1 || month > 12)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + \
m_result.Append(g_month_names[month-1]); + }
+ break;
+
+ case TokenDateFormatType_Month_Number:
+ {
+ FdoInt8 month = (dt.month == -1) ? 1 : dt.month;
+ if (month < 1 || month > 12)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append(month, "%02d");
+ }
+ break;
+
+ case TokenDateFormatType_Day_AbbName_All_Lower:
+ {
+ FdoInt8 dayweek = DayOfWeek(dt.year, dt.month, dt.day);
+ if (dayweek < 0 || dayweek > 6)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_day_names[dayweek];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Tolower(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse, 3);
+ }
+ break;
+
+ case TokenDateFormatType_Day_AbbName_All_Upper:
+ {
+ FdoInt8 dayweek = DayOfWeek(dt.year, dt.month, dt.day);
+ if (dayweek < 0 || dayweek > 6)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_day_names[dayweek];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Toupper(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse, 3);
+ }
+ break;
+
+ case TokenDateFormatType_Day_FullName_All_Lower:
+ {
+ FdoInt8 dayweek = DayOfWeek(dt.year, dt.month, dt.day);
+ if (dayweek < 0 || dayweek > 6)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_day_names[dayweek];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Tolower(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse);
+ }
+ break;
+
+ case TokenDateFormatType_Day_FullName_All_Upper:
+ {
+ FdoInt8 dayweek = DayOfWeek(dt.year, dt.month, dt.day);
+ if (dayweek < 0 || dayweek > 6)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + usePtr = g_day_names[dayweek];
+ while(*usePtr != '\0')
+ {
+ tmpUse[idx++] = sqlite3Toupper(*usePtr);
+ usePtr++;
+ }
+ tmpUse[idx] = '\0';
+ m_result.Append(tmpUse);
+ }
+ break;
+
+ case TokenDateFormatType_Day_FullName_First_Upper:
+ {
+ FdoInt8 dayweek = DayOfWeek(dt.year, dt.month, dt.day);
+ if (dayweek < 0 || dayweek > 6)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append(g_day_names[dayweek]);
+ }
+ break;
+
+ case TokenDateFormatType_Day_Number:
+ {
+ FdoInt8 day = (dt.day == -1) ? 1 : dt.day;
+ if (day < 1 || day > 31)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append(day, "%02d");
+ }
+ break;
+ case TokenDateFormatType_Hour24:
+ {
+ FdoInt8 hour = (dt.hour == -1) ? 0 : dt.hour;
+ if (hour < 0 || hour > 23)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append(hour, "%02d");
+ }
+ break;
+ case TokenDateFormatType_Hour12:
+ {
+ FdoInt8 hour = (dt.hour == -1) ? 0 : dt.hour;
+ if (hour < 0 || hour > 23)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append((hour > 12) ? (hour - \
12) : hour, "%02d"); + }
+ break;
+ case TokenDateFormatType_Minute:
+ {
+ FdoInt8 minute = (dt.minute == -1) ? 0 : dt.minute;
+ if (minute < 0 || minute > 59)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append(minute, "%02d");
+ }
+ break;
+ case TokenDateFormatType_Second:
+ {
+ if (dt.seconds == -1.0f)
+ m_result.Append("00");
+ else
+ {
+ if (dt.seconds < 0.0f || dt.seconds >= 60.0f)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + m_result.Append(dt.seconds, \
"%0.3f"); + }
+ }
+ break;
+ case TokenDateFormatType_am:
+ case TokenDateFormatType_pm:
+ {
+ FdoInt8 hour = (dt.hour == -1) ? 0 : dt.hour;
+ if (hour < 0 || hour > 23)
+ throw FdoException::Create(L"Unexpected result for \
function ToString"); + if (hour > 12)
+ m_result.Append("PM", 2);
+ else
+ m_result.Append("AM", 2);
+ }
+ break;
+ default: // Separator & Unknown
+ m_result.Append(tk->GetTokenValue(), tk->GetTokenLen());
+ break;
+ }
+ }
+ }
+ return m_result.Data();
+ }
+
+ FdoDateTime ToDateTime(const char* str, size_t sz)
+ {
+ FdoDateTime dt;
+ if (!m_hasValidTokens || str == NULL || *str == '\0')
+ return dt;
+ const char* strtmp = str;
+ for(std::vector<DateToken*>::iterator it = m_values.begin(); it < \
m_values.end(); it++) + {
+ DateToken* tk = *it;
+ switch(tk->GetTokenType())
+ {
+ case TokenDateFormatType_Year2:
+ if ((size_t)(strtmp-str+2) <= sz)
+ {
+ m_result.Reset();
+ m_result.Append(strtmp, 2);
+ dt.year = (FdoInt16)atoi(m_result.Data());
+ // year can be 09 = 2009 or 55 = 1955/2055 !?
+ // it's hard to know the real year when two characters are used
+ // let's split in half for now
+ if (dt.year > 0 && dt.year < 50)
+ dt.year += 2000;
+ strtmp += 2;
+ }
+ break;
+
+ case TokenDateFormatType_Year4:
+ if ((size_t)(strtmp-str+4) <= sz)
+ {
+ m_result.Reset();
+ m_result.Append(strtmp, 4);
+ dt.year = (FdoInt16)atoi(m_result.Data());
+ strtmp += 4;
+ }
+ break;
+
+ case TokenDateFormatType_Month_AbbName_All_Lower:
+ case TokenDateFormatType_Month_AbbName_All_Upper:
+ case TokenDateFormatType_Month_FullName_All_Lower:
+ case TokenDateFormatType_Month_FullName_All_Upper:
+ case TokenDateFormatType_Month_FullName_First_Upper:
+ {
+ if ((size_t)(strtmp-str+3) <= sz)
+ {
+ FdoInt8 idx = 0;
+ for (; idx < 12; idx++)
+ {
+ if (_strnicmp(strtmp, g_month_names[idx], 3) == 0)
+ {
+ dt.month = idx+1;
+ strtmp += 3;
+ break;
+ }
+ }
+ if (idx == 12)
+ strtmp++;
+ }
+ }
+ break;
+
+ case TokenDateFormatType_Month_Number:
+ if ((size_t)(strtmp-str+2) <= sz)
+ {
+ m_result.Reset();
+ m_result.Append(strtmp, 2);
+ dt.month = (FdoInt16)atoi(m_result.Data());
+ strtmp += 2;
+ }
+ break;
+
+ case TokenDateFormatType_Day_AbbName_All_Lower:
+ case TokenDateFormatType_Day_AbbName_All_Upper:
+ case TokenDateFormatType_Day_FullName_All_Lower:
+ case TokenDateFormatType_Day_FullName_All_Upper:
+ case TokenDateFormatType_Day_FullName_First_Upper:
+ // nothing to do here since day of the week don't help us
+ if ((size_t)(strtmp-str+3) <= sz)
+ strtmp += 3;
+ break;
+
+ case TokenDateFormatType_Day_Number:
+ if ((size_t)(strtmp-str+2) <= sz)
+ {
+ m_result.Reset();
+ m_result.Append(strtmp, 2);
+ dt.day = (FdoInt16)atoi(m_result.Data());
+ strtmp += 2;
+ }
+ break;
+ case TokenDateFormatType_Hour24:
+ case TokenDateFormatType_Hour12:
+ if ((size_t)(strtmp-str+2) <= sz)
+ {
+ m_result.Reset();
+ m_result.Append(strtmp, 2);
+ dt.hour = (FdoInt16)atoi(m_result.Data());
+ strtmp += 2;
+ }
+ break;
+ case TokenDateFormatType_Minute:
+ if ((size_t)(strtmp-str+2) <= sz)
+ {
+ m_result.Reset();
+ m_result.Append(strtmp, 2);
+ dt.minute = (FdoInt16)atoi(m_result.Data());
+ strtmp += 2;
+ }
+ break;
+ case TokenDateFormatType_Second:
+ if ((size_t)(strtmp-str+1) <= sz) // at least one character
+ {
+ // this will work since atof ignores other characters after \
numbers + dt.seconds = (float)atof(strtmp);
+ strtmp++; // just advance one position to be on number
+ }
+ break;
+ case TokenDateFormatType_am:
+ case TokenDateFormatType_pm:
+ if ((size_t)(strtmp-str+2) <= sz)
+ {
+ // if it's PM we need to add 12 to hour
+ if (dt.hour >= 0 && dt.hour < 12 && _strnicmp(strtmp, "PM", 2) \
== 0) + dt.hour += 12;
+ strtmp += 2;
+ }
+ break;
+ default: // Separator & Unknown
+ {
+ // can we get the token value?
+ int pos = StringContains(strtmp, tk->GetTokenValue());
+ if (pos != -1) // in case yes jump over the position
+ strtmp += (pos + tk->GetTokenLen());
+ }
+ break;
+ }
+ // stop in case we are at the end of date time string
+ if ((strtmp-str) >= sz)
+ break;
+ }
+ return dt;
+ }
+};
+
//===============================================================================
// Basic math functions
//===============================================================================
@@ -635,7 +1199,7 @@
// Conversion fuctions
//===============================================================================
//NOTE: these are implemented only for compatibility with FDO filters -- SQLite
-//expression evaluation uses implicit type conversion, so they are not sctrictly
+//expression evaluation uses implicit type conversion, so they are not strictly
//necessary
static void convFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
{
@@ -645,46 +1209,103 @@
switch(optype)
{
- case 1: //todate
+ case 1: //todouble
{
- //assumes date is stored in ISO 8601 string format
- const char* s = (const char*)sqlite3_value_text(argv[0]);
- sqlite3_result_text(context, s, -1, SQLITE_TRANSIENT);
- }
- break;
- case 2: //todouble
- {
double d = sqlite3_value_double(argv[0]);
sqlite3_result_double(context, d);
}
break;
- case 3: //tofloat
+ case 2: //tofloat
{
float f = (float)sqlite3_value_double(argv[0]);
sqlite3_result_double(context, f);
}
break;
- case 4: //toint32
+ case 3: //toint32
{
int i = sqlite3_value_int(argv[0]);
sqlite3_result_int(context, i);
}
break;
- case 5: //toint64
+ case 4: //toint64
{
sqlite_int64 i = sqlite3_value_int64(argv[0]);
sqlite3_result_int64(context, i);
}
break;
- case 6: //tostring
+ }
+}
+
+static void todateFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
+{
+ assert(argc == 1 || argc == 2);
+ int type = sqlite3_value_type(argv[0]);
+ const char* dateStr = (const char*)sqlite3_value_text(argv[0]);
+ if (type == SQLITE_NULL || dateStr == NULL || sqlite3_value_bytes(argv[0]) == 0)
+ {
+ sqlite3_result_null(context);
+ }
+ else if (type != SQLITE_TEXT)
+ {
+ sqlite3_result_null(context);
+ }
+ else
+ {
+ FdoDateTime dt = DateFromString(dateStr, false);
+ if (dt.IsDate() || dt.IsTime() || dt.IsDateTime())
{
const char* s = (const char*)sqlite3_value_text(argv[0]);
sqlite3_result_text(context, s, -1, SQLITE_TRANSIENT);
}
- break;
+ else
+ {
+ DateTokenFormat dtc;
+ if (argc == 2 && sqlite3_value_type(argv[1]) == SQLITE_TEXT && \
sqlite3_value_bytes(argv[1]) != 0) + dtc.ProcessFormat((const \
char*)sqlite3_value_text(argv[1])); + else
+ dtc.ProcessFormat(NULL);
+
+ dt = dtc.ToDateTime(dateStr, sqlite3_value_bytes(argv[0]));
+ if (dt.IsDate() || dt.IsTime() || dt.IsDateTime())
+ {
+ char dateBuff[31];
+ *dateBuff = '\0';
+ DateToString(&dt, dateBuff, 31);
+ sqlite3_result_text(context, dateBuff, -1, SQLITE_TRANSIENT);
+ }
+ else
+ sqlite3_result_null(context);
+ }
}
}
+static void toStringFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
+{
+ assert(argc == 1 || argc == 2);
+ int type = sqlite3_value_type(argv[0]);
+ const char* dateStr = (const char*)sqlite3_value_text(argv[0]);
+ if (type == SQLITE_NULL || dateStr == NULL || sqlite3_value_bytes(argv[0]) == 0)
+ {
+ sqlite3_result_null(context);
+ }
+ else if (type != SQLITE_TEXT)
+ {
+ sqlite3_result_text(context, dateStr, -1, SQLITE_TRANSIENT);
+ }
+ else // process date time
+ {
+ DateTokenFormat dtc;
+ FdoDateTime dt = DateFromString(dateStr);
+
+ if (argc == 2 && sqlite3_value_type(argv[1]) == SQLITE_TEXT && \
sqlite3_value_bytes(argv[1]) != 0) + dtc.ProcessFormat((const \
char*)sqlite3_value_text(argv[1])); + else
+ dtc.ProcessFormat(NULL);
+
+ sqlite3_result_text(context, dtc.ToString(dt), -1, SQLITE_TRANSIENT);
+ }
+}
+
static void nullvalueFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
{
assert(argc == 2);
@@ -1218,12 +1839,14 @@
{ "GeomFromText", 1, 0, SQLITE_UTF8, 0, GeomFromText },
- { "todate", 1, 1, SQLITE_UTF8, 0, convFunc },
- { "todouble", 1, 2, SQLITE_UTF8, 0, convFunc },
- { "tofloat", 1, 3, SQLITE_UTF8, 0, convFunc },
- { "toint32", 1, 4, SQLITE_UTF8, 0, convFunc },
- { "toint64", 1, 5, SQLITE_UTF8, 0, convFunc },
- { "tostring", 1, 6, SQLITE_UTF8, 0, convFunc },
+ { "todate", 1, 1, SQLITE_UTF8, 0, todateFunc },
+ { "todate", 2, 1, SQLITE_UTF8, 0, todateFunc },
+ { "todouble", 1, 1, SQLITE_UTF8, 0, convFunc },
+ { "tofloat", 1, 2, SQLITE_UTF8, 0, convFunc },
+ { "toint32", 1, 3, SQLITE_UTF8, 0, convFunc },
+ { "toint64", 1, 4, SQLITE_UTF8, 0, convFunc },
+ { "tostring", 1, 1, SQLITE_UTF8, 0, toStringFunc },
+ { "tostring", 2, 1, SQLITE_UTF8, 0, toStringFunc },
{ "nullvalue", 2, 1, SQLITE_UTF8, 0, nullvalueFunc }
};
Modified: trunk/Providers/SQLite/Src/Provider/SltExprExtensions.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltExprExtensions.h 2009-07-26 00:53:36 UTC \
(rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/SltExprExtensions.h 2009-07-27 15:52:22 UTC \
(rev 4862) @@ -18,5 +18,31 @@
"geom_bbox"
};
+static const char* g_month_names[] =
+{
+"January",
+"February",
+"March",
+"April",
+"May",
+"June",
+"July",
+"August",
+"September",
+"October",
+"November",
+"December"
+};
+static const char* g_day_names[] =
+{
+"Sunday",
+"Monday",
+"Tuesday",
+"Wednesday",
+"Thursday",
+"Friday",
+"Saturday"
+};
+
void RegisterExtensions (sqlite3* db);
Modified: trunk/Providers/SQLite/Src/Provider/SltProvider.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltProvider.cpp 2009-07-26 00:53:36 UTC (rev \
4861)
+++ trunk/Providers/SQLite/Src/Provider/SltProvider.cpp 2009-07-27 15:52:22 UTC (rev \
4862) @@ -850,7 +850,7 @@
}
StringBuffer sb;
- SltExpressionTranslator exTrans;
+ SltExpressionTranslator exTrans(properties);
if (bDistinct)
{
Modified: trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.cpp 2009-07-26 00:53:36 \
UTC (rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.cpp 2009-07-27 15:52:22 \
UTC (rev 4862) @@ -20,7 +20,7 @@
#include "SltGeomUtils.h"
#include "SltQueryTranslator.h"
#include "SltExprExtensions.h"
-
+#include <FdoExpressionEngineCopyFilter.h>
#include <algorithm>
recno_list* recno_list_union(recno_list* left, recno_list* right)
@@ -28,10 +28,10 @@
//if one of the lists is null it means it iterates over all features...
//so return that list as the union of the two
if (left == NULL)
- return left;
+ return right;
if (right == NULL)
- return right;
+ return left;
std::sort(left->begin(), left->end(), std::less<__int64>());
std::sort(right->begin(), right->end(), std::less<__int64>());
@@ -148,7 +148,6 @@
FdoBinaryLogicalOperations op = filter.GetOperation();
- StringBuffer spVal;
FilterChunk* ret = NULL;
//determine logical op we want as string
@@ -233,6 +232,7 @@
DBounds::Union(&ret->m_bounds, &lefts->m_bounds, &rights->m_bounds);
}
ret->m_ids = recno_list_intersection(lefts->m_ids, rights->m_ids);
+ lefts->m_ids = rights->m_ids = NULL;
}
break;
case FdoBinaryLogicalOperations_Or:
@@ -259,6 +259,7 @@
DBounds::Union(&ret->m_bounds, &lefts->m_bounds, &rights->m_bounds);
}
ret->m_ids = recno_list_union(lefts->m_ids, rights->m_ids);
+ lefts->m_ids = rights->m_ids = NULL;
}
break;
}
@@ -288,16 +289,16 @@
FdoPtr<FdoIdentifier> pname = filter.GetPropertyName();
//construct the SQLite function we want to use for this spatial op
- StringBuffer spVal;
- spVal.Append(sfunc);
- spVal.Append("(", 1);
- spVal.Append(pname->GetName());
- spVal.Append(",", 1);
- spVal.Append(expr->ToString());
- spVal.Append(")", 1);
+ m_sb.Reset();
+ m_sb.Append(sfunc);
+ m_sb.Append("(", 1);
+ m_sb.Append(pname->GetName());
+ m_sb.Append(",", 1);
+ m_sb.Append(expr->ToString());
+ m_sb.Append(")", 1);
DBounds bdGeom = expr->m_bounds;
- FilterChunk* ret = CreateFilterChunk(spVal.Data(), spVal.Length(), \
StlSpatialTypeOperation_And); + FilterChunk* ret = CreateFilterChunk(m_sb.Data(), \
m_sb.Length(), StlSpatialTypeOperation_And); //for some operations, we can speed up \
the query by also //performing a bbox check using the spatial index
switch(op)
@@ -369,40 +370,112 @@
FdoPtr<FdoExpression> left = filter.GetLeftExpression();
FdoPtr<FdoExpression> right = filter.GetRightExpression();
- FdoPtr<FdoDataPropertyDefinitionCollection> idpdc = \
m_fc->GetIdentityProperties();
- if (idpdc->GetCount() == 1)
+ if (filter.GetOperation() == FdoComparisonOperations_EqualTo)
{
- FdoPtr<FdoDataPropertyDefinition> idpd = idpdc->GetItem(0);
-
- if (filter.GetOperation() == FdoComparisonOperations_EqualTo && \
wcscmp(left->ToString(), idpd->GetName()) == 0) + \
FdoPtr<FdoDataPropertyDefinitionCollection> idpdc = m_fc->GetIdentityProperties(); + \
if (idpdc->GetCount() == 1) {
- __int64 idval = -1;
- size_t len = 0;
- int res = swscanf(right->ToString(), L"%lld%n", &idval, &len);
+ FdoPtr<FdoDataPropertyDefinition> idpd = idpdc->GetItem(0);
+ if (wcscmp(left->ToString(), idpd->GetName()) == 0)
+ {
+ __int64 idval = -1;
+ size_t len = 0;
+ int res = swscanf(right->ToString(), L"%lld%n", &idval, &len);
- if (res == 1 && len == wcslen(right->ToString()))
- {
- ret = CreateFilterChunk(filter.ToString());
- ret->m_ids = new recno_list;
- ret->m_ids->push_back(idval);
- m_canUseFastStepping = true;
+ if (res == 1 && len == wcslen(right->ToString()))
+ {
+ ret = CreateFilterChunk(filter.ToString());
+ ret->m_ids = new recno_list;
+ ret->m_ids->push_back(idval);
+ m_canUseFastStepping = true;
+ }
}
}
}
+ if (ret == NULL)
+ {
+ // we need to be sure we handle datetime values, e.g. DATEPROP > DATE \
'10-10-2000' + FdoPtr<FdoExpression> param = filter.GetLeftExpression();
+ param->Process(this);
+ FilterChunk* exprLeft = m_evalStack.back();
+ m_evalStack.pop_back();
+
+ param = filter.GetRightExpression();
+ param->Process(this);
+ FilterChunk* exprRight = m_evalStack.back();
+ m_evalStack.pop_back();
- m_evalStack.push_back((ret != NULL) ? ret : \
CreateFilterChunk(filter.ToString())); + ComplexFilterChunk* compExp = \
CreateComplexFilterChunk(); + ret = compExp;
+ compExp->AddToList(CreateFilterChunk("(", 1));
+ compExp->AddToList(exprLeft);
+
+ switch(filter.GetOperation())
+ {
+ case FdoComparisonOperations_EqualTo:
+ compExp->AddToList(CreateFilterChunk("=", 1));
+ break;
+ case FdoComparisonOperations_NotEqualTo:
+ compExp->AddToList(CreateFilterChunk("<>", 2));
+ break;
+ case FdoComparisonOperations_GreaterThan:
+ compExp->AddToList(CreateFilterChunk(">", 1));
+ break;
+ case FdoComparisonOperations_GreaterThanOrEqualTo:
+ compExp->AddToList(CreateFilterChunk(">=", 2));
+ break;
+ case FdoComparisonOperations_LessThan:
+ compExp->AddToList(CreateFilterChunk("<", 1));
+ break;
+ case FdoComparisonOperations_LessThanOrEqualTo:
+ compExp->AddToList(CreateFilterChunk("<=", 2));
+ break;
+ case FdoComparisonOperations_Like:
+ compExp->AddToList(CreateFilterChunk(" LIKE ", 6));
+ break;
+ }
+ compExp->AddToList(exprRight);
+ compExp->AddToList(CreateFilterChunk(")", 1));
+ }
+ m_evalStack.push_back(ret);
}
void SltQueryTranslator::ProcessInCondition(FdoInCondition& filter)
{
- m_evalStack.push_back(CreateFilterChunk(filter.ToString()));
+ size_t szBefore = m_evalStack.size();
+ FdoPtr<FdoValueExpressionCollection> vals = filter.GetValues();
+ int cnt = vals->GetCount();
+ for(int idx = 0; idx < cnt; idx++)
+ {
+ FdoPtr<FdoValueExpression> exp = vals->GetItem(idx);
+ exp->Process(this);
+ }
+ size_t szAfter = m_evalStack.size();
+
+ m_sb.Reset();
+ FdoPtr<FdoIdentifier> prop = filter.GetPropertyName();
+ m_sb.AppendDQuoted(prop->GetName());
+ m_sb.Append(" IN(", 4);
+ FilterChunk* item = NULL;
+ for(size_t idx = szBefore; idx < szAfter; idx++)
+ {
+ item = m_evalStack[idx];
+ m_sb.Append(item->ToString());
+ m_sb.Append(", ", 2);
+ }
+ m_sb.Data()[m_sb.Length()-2] = ')';
+ // clean stack
+ m_evalStack.erase(m_evalStack.begin() + szBefore, m_evalStack.end());
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), m_sb.Length()));
}
void SltQueryTranslator::ProcessNullCondition(FdoNullCondition& filter)
{
FdoPtr<FdoIdentifier> idf = filter.GetPropertyName();
- std::wstring val = std::wstring(L"\"" + std::wstring(idf->GetName()) + L"\" IS \
NULL");
- m_evalStack.push_back(CreateFilterChunk(val.c_str()));
+ m_sb.Reset();
+ m_sb.AppendDQuoted(idf->GetName());
+ m_sb.Append(" IS NULL", 8);
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), m_sb.Length()));
}
void SltQueryTranslator::ProcessDistanceCondition(FdoDistanceCondition& filter)
@@ -410,21 +483,100 @@
m_evalStack.push_back(CreateFilterChunk(filter.ToString()));
}
-
//--------------------------------------------------------------------
// FdoIExpressionProcessor
//--------------------------------------------------------------------
void SltQueryTranslator::ProcessBinaryExpression(FdoBinaryExpression& expr)
{
+ FdoPtr<FdoExpression> param = expr.GetLeftExpression();
+ param->Process(this);
+ FilterChunk* exprLeft = m_evalStack.back();
+ m_evalStack.pop_back();
+
+ param = expr.GetRightExpression();
+ param->Process(this);
+ FilterChunk* exprRight = m_evalStack.back();
+ m_evalStack.pop_back();
+
+ ComplexFilterChunk* ret = CreateComplexFilterChunk();
+ ret->AddToList(CreateFilterChunk("(", 1));
+ ret->AddToList(exprLeft);
+
+ switch(expr.GetOperation())
+ {
+ case FdoBinaryOperations_Add:
+ ret->AddToList(CreateFilterChunk("+", 1));
+ break;
+ case FdoBinaryOperations_Divide:
+ ret->AddToList(CreateFilterChunk("-", 1));
+ break;
+ case FdoBinaryOperations_Multiply:
+ ret->AddToList(CreateFilterChunk("*", 1));
+ break;
+ case FdoBinaryOperations_Subtract:
+ ret->AddToList(CreateFilterChunk("/", 1));
+ break;
+ }
+ ret->AddToList(exprRight);
+ ret->AddToList(CreateFilterChunk(")", 1));
+
+ m_evalStack.push_back(ret);
}
void SltQueryTranslator::ProcessUnaryExpression(FdoUnaryExpression& expr)
{
+ FdoPtr<FdoExpression> arg = expr.GetExpression();
+ arg->Process(this);
+
+ FilterChunk* exprRez = m_evalStack.back();
+ m_evalStack.pop_back();
+
+ ComplexFilterChunk* ret = CreateComplexFilterChunk();
+ ret->AddToList(CreateFilterChunk(" (-(", 4));
+ ret->AddToList(exprRez);
+ ret->AddToList(CreateFilterChunk("))", 2));
+
+ m_evalStack.push_back(ret);
}
void SltQueryTranslator::ProcessFunction(FdoFunction& expr)
{
+ // We need to handle this because of ToDate...
+ // "ToDate(DATE '10-10-2000')" which should be "ToDate('10-10-2000')"
+ // otherwise query will fail, because of syntax error
+
+ size_t szBefore = m_evalStack.size();
+ FdoPtr<FdoExpressionCollection> vals = expr.GetArguments();
+ int cnt = vals->GetCount();
+ for(int idx = 0; idx < cnt; idx++)
+ {
+ FdoPtr<FdoExpression> exp = vals->GetItem(idx);
+ exp->Process(this);
+ }
+ size_t szAfter = m_evalStack.size();
+ if (szAfter != szBefore)
+ {
+ m_sb.Reset();
+ m_sb.Append(expr.GetName());
+ m_sb.Append("(", 1);
+ for(size_t idx = szBefore; idx < szAfter; idx++)
+ {
+ m_sb.Append(m_evalStack[idx]->ToString());
+ m_sb.Append(", ", 2);
+ }
+ m_sb.Data()[m_sb.Length()-2] = ')';
+ // clean stack
+ m_evalStack.erase(m_evalStack.begin() + szBefore, m_evalStack.end());
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), m_sb.Length()));
+ }
+ else
+ {
+ m_sb.Reset();
+ m_sb.Append(expr.GetName());
+ m_sb.Append("()", 2);
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), m_sb.Length()));
+ }
}
void SltQueryTranslator::ProcessIdentifier(FdoIdentifier& expr)
@@ -458,63 +610,192 @@
}
}
- m_evalStack.push_back(CreateFilterChunk(expr.GetName()));
+ m_sb.Reset();
+ m_sb.AppendDQuoted(expr.GetName());
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), m_sb.Length()));
}
void SltQueryTranslator::ProcessComputedIdentifier(FdoComputedIdentifier& expr)
{
+ throw FdoException::Create(L"Unsupported FDO type in filters");
}
void SltQueryTranslator::ProcessParameter(FdoParameter& expr)
{
+ throw FdoException::Create(L"Unsupported FDO type in filters");
}
void SltQueryTranslator::ProcessBooleanValue(FdoBooleanValue& expr)
{
+ if (!expr.IsNull())
+ {
+ if (expr.GetBoolean())
+ m_evalStack.push_back(CreateFilterChunk("TRUE", 4));
+ else
+ m_evalStack.push_back(CreateFilterChunk("FALSE", 5));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessByteValue(FdoByteValue& expr)
{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+#ifdef _WIN32
+ _itoa_s(expr.GetByte() , m_sb.Data(), 256, 10);
+#else
+ itoa(expr.GetByte(), m_sb.Data(), 10);
+#endif
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), strlen(m_sb.Data())));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessDateTimeValue(FdoDateTimeValue& expr)
{
+ // the big issues here is FDO syntax add in front of the date
+ // DATE/TIME/TIMESTAMP which for SQLite should be removed
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+ char* dateStr = m_sb.Data();
+ *dateStr = '\'';
+ FdoDateTime dt = expr.GetDateTime();
+ DateToString(&dt, dateStr+1, 31);
+ size_t sz = strlen(dateStr+1);
+ dateStr[sz+1] = '\'';
+ m_evalStack.push_back(CreateFilterChunk(dateStr, sz+2));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessDecimalValue(FdoDecimalValue& expr)
{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+ char* ptr = m_sb.Data();
+#ifdef _WIN32
+ _snprintf(ptr, 256, "%g", expr.GetDecimal());
+#else
+ sprintf(ptr, 256, "%g", expr.GetDecimal());
+#endif
+ EnsureNoIsLocalIndep(ptr);
+ m_evalStack.push_back(CreateFilterChunk(ptr, strlen(ptr)));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessDoubleValue(FdoDoubleValue& expr)
{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+ char* ptr = m_sb.Data();
+#ifdef _WIN32
+ _snprintf(ptr, 256, "%g", expr.GetDouble());
+#else
+ sprintf(ptr, 256, "%g", expr.GetDouble());
+#endif
+ EnsureNoIsLocalIndep(ptr);
+ m_evalStack.push_back(CreateFilterChunk(ptr, strlen(ptr)));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
+void SltQueryTranslator::ProcessSingleValue(FdoSingleValue& expr)
+{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+ char* ptr = m_sb.Data();
+#ifdef _WIN32
+ _snprintf(ptr, 256, "%f", expr.GetSingle());
+#else
+ sprintf(ptr, 256, "%f", expr.GetSingle());
+#endif
+ EnsureNoIsLocalIndep(ptr);
+ m_evalStack.push_back(CreateFilterChunk(ptr, strlen(ptr)));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
+}
+
void SltQueryTranslator::ProcessInt16Value(FdoInt16Value& expr)
{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+#ifdef _WIN32
+ _itoa_s(expr.GetInt16(), m_sb.Data(), 256, 10);
+#else
+ itoa(expr.GetInt16(), m_sb.Data(), 10);
+#endif
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), strlen(m_sb.Data())));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessInt32Value(FdoInt32Value& expr)
{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+#ifdef _WIN32
+ _itoa_s(expr.GetInt32(), m_sb.Data(), 256, 10);
+#else
+ itoa(expr.GetInt32(), m_sb.Data(), 10);
+#endif
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), strlen(m_sb.Data())));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessInt64Value(FdoInt64Value& expr)
{
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+#ifdef _WIN32
+ _i64toa_s(expr.GetInt64(), m_sb.Data(), 256, 10);
+#else
+ sprintf(m_sb.Data(), 256, "%lld", expr.GetInt64());
+#endif
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), strlen(m_sb.Data())));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
-void SltQueryTranslator::ProcessSingleValue(FdoSingleValue& expr)
-{
-}
-
void SltQueryTranslator::ProcessStringValue(FdoStringValue& expr)
{
+ // it's faster than expr.ToString()
+ if (!expr.IsNull())
+ {
+ m_sb.Reset();
+ m_sb.AppendSQuoted(expr.GetString());
+ m_evalStack.push_back(CreateFilterChunk(m_sb.Data(), m_sb.Length()));
+ }
+ else
+ m_evalStack.push_back(CreateFilterChunk("null", 4));
}
void SltQueryTranslator::ProcessBLOBValue(FdoBLOBValue& expr)
{
+ throw FdoException::Create(L"Unsupported FDO type in filters");
}
void SltQueryTranslator::ProcessCLOBValue(FdoCLOBValue& expr)
{
+ throw FdoException::Create(L"Unsupported FDO type in filters");
}
void SltQueryTranslator::ProcessGeometryValue(FdoGeometryValue& expr)
@@ -577,15 +858,14 @@
delete[] wstr;
#else
m_geomCount++;
- wchar_t buf[70];
- *buf = L'\0';
+ m_sb.Reset();
#ifdef _WIN32
- _i64tow_s((FdoInt64)fgf.p, buf, 70, 10);
+ _i64toa_s((FdoInt64)fgf.p, m_sb.Data(), 256, 10);
#else
- swprintf(buf, 70, L"%lld", (FdoInt64)fgf.p);
+ sprintf(m_sb.Data(), 256, "%lld", (FdoInt64)fgf.p);
#endif
- FilterChunk* ret = CreateFilterChunk(buf);
+ FilterChunk* ret = CreateFilterChunk(m_sb.Data(), strlen(m_sb.Data()));
#endif
ret->m_bounds = ext;
@@ -706,13 +986,10 @@
void SltExpressionTranslator::ProcessUnaryExpression(FdoUnaryExpression& expr)
{
- if (expr.GetOperation() == FdoUnaryOperations_Negate)
- {
- m_expr.Append(" (-(", 4);
- FdoPtr<FdoExpression> param = expr.GetExpression();
- HandleExpr(param);
- m_expr.Append("))", 2);
- }
+ m_expr.Append(" (-(", 4);
+ FdoPtr<FdoExpression> param = expr.GetExpression();
+ HandleExpr(param);
+ m_expr.Append("))", 2);
}
void SltExpressionTranslator::ProcessFunction(FdoFunction& expr)
@@ -759,15 +1036,22 @@
void SltExpressionTranslator::ProcessIdentifier(FdoIdentifier& expr)
{
- m_expr.Append(expr.ToString());
+ m_expr.AppendDQuoted(expr.GetName());
}
void SltExpressionTranslator::ProcessComputedIdentifier(FdoComputedIdentifier& expr)
{
FdoPtr<FdoExpression> param = expr.GetExpression();
- HandleExpr(param);
+ if (m_props != NULL)
+ {
+ // expand the expressions in case we have expressions besad on other \
expressions. + FdoPtr<FdoExpression> expandedExpression = \
FdoExpressionEngineCopyFilter::Copy(param, m_props); + \
HandleExpr(expandedExpression); + }
+ else
+ HandleExpr(param);
m_expr.Append(" AS ", 4);
- m_expr.Append(expr.GetName());
+ m_expr.AppendDQuoted(expr.GetName());
}
void SltExpressionTranslator::ProcessParameter(FdoParameter& expr)
@@ -776,51 +1060,142 @@
}
void SltExpressionTranslator::ProcessBooleanValue(FdoBooleanValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+ if (expr.GetBoolean())
+ m_expr.Append("TRUE", 4);
+ else
+ m_expr.Append("FALSE", 5);
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessByteValue(FdoByteValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _itoa_s(expr.GetByte(), m_useConv, 256, 10);
+#else
+ itoa(expr.GetByte(), m_useConv, 10);
+#endif
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessDateTimeValue(FdoDateTimeValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+ FdoDateTime dt = expr.GetDateTime();
+ DateToString(&dt, m_useConv, 31);
+ m_expr.AppendSQuoted(m_useConv);
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessDecimalValue(FdoDecimalValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _snprintf(m_useConv, 256, "%g", expr.GetDecimal());
+#else
+ sprintf(m_useConv, 256, "%g", expr.GetDecimal());
+#endif
+ EnsureNoIsLocalIndep(m_useConv);
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessDoubleValue(FdoDoubleValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _snprintf(m_useConv, 256, "%g", expr.GetDouble());
+#else
+ sprintf(m_useConv, 256, "%g", expr.GetDouble());
+#endif
+ EnsureNoIsLocalIndep(m_useConv);
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessInt16Value(FdoInt16Value& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _itoa_s(expr.GetInt16(), m_useConv, 256, 10);
+#else
+ itoa(expr.GetInt16(), m_useConv, 10);
+#endif
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessInt32Value(FdoInt32Value& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _itoa_s(expr.GetInt32(), m_useConv, 256, 10);
+#else
+ itoa(expr.GetInt32(), m_useConv, 10);
+#endif
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessInt64Value(FdoInt64Value& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _i64toa_s(expr.GetInt64(), m_useConv, 256, 10);
+#else
+ sprintf(m_useConv, 256, "%lld", expr.GetInt64());
+#endif
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessSingleValue(FdoSingleValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ {
+#ifdef _WIN32
+ _snprintf(m_useConv, 256, "%f", expr.GetSingle());
+#else
+ sprintf(m_useConv, 256, "%f", expr.GetSingle());
+#endif
+ EnsureNoIsLocalIndep(m_useConv);
+ m_expr.Append(m_useConv, strlen(m_useConv));
+ }
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessStringValue(FdoStringValue& expr)
{
- m_expr.Append(expr.ToString());
+ if (!expr.IsNull())
+ m_expr.AppendSQuoted(expr.GetString());
+ else
+ m_expr.Append("null", 4);
}
void SltExpressionTranslator::ProcessBLOBValue(FdoBLOBValue& expr)
Modified: trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.h 2009-07-26 00:53:36 UTC \
(rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/SltQueryTranslator.h 2009-07-27 15:52:22 UTC \
(rev 4862) @@ -201,6 +201,8 @@
// list used to destroy the allocated objects at the end
FilterChunkList m_allocatedObjects;
+ // used as cache string operations
+ StringBuffer m_sb;
};
//Translates an FDO Expression to a SQLite expression
@@ -210,8 +212,10 @@
public:
- SltExpressionTranslator()
- {}
+ SltExpressionTranslator(FdoIdentifierCollection* props = NULL)
+ {
+ m_props = FDO_SAFE_ADDREF(props);
+ }
~SltExpressionTranslator()
{}
@@ -254,8 +258,9 @@
void Reset() { m_expr.Reset(); }
private:
-
+ FdoPtr<FdoIdentifierCollection> m_props;
StringBuffer m_expr;
+ char m_useConv[256];
};
//Helper class used at spatial context and count queries
Modified: trunk/Providers/SQLite/Src/Provider/SltReader.cpp
===================================================================
--- trunk/Providers/SQLite/Src/Provider/SltReader.cpp 2009-07-26 00:53:36 UTC (rev \
4861)
+++ trunk/Providers/SQLite/Src/Provider/SltReader.cpp 2009-07-27 15:52:22 UTC (rev \
4862) @@ -199,7 +199,7 @@
//so that he sees the properties he asked for.
if (props && props->GetCount())
{
- SltExpressionTranslator exTrans;
+ SltExpressionTranslator exTrans(props);
int nProps = props->GetCount();
m_reissueProps.Reserve(nProps);
for (int i=0; i<nProps; i++)
Modified: trunk/Providers/SQLite/Src/Provider/StringUtil.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/StringUtil.h 2009-07-26 00:53:36 UTC (rev \
4861)
+++ trunk/Providers/SQLite/Src/Provider/StringUtil.h 2009-07-27 15:52:22 UTC (rev \
4862) @@ -168,6 +168,31 @@
Append(tmp);
}
+ // used to format values like 12.34
+ void Append(double value, const char* format)
+ {
+ char tmp[64];
+ _snprintf(tmp, 32, format, value);
+ EnsureNoIsLocalIndep(tmp);
+ Append(tmp);
+ }
+
+ // used to format values like 09
+ void Append(int value, const char* format)
+ {
+ char tmp[32];
+ _snprintf(tmp, 32, format, value);
+ Append(tmp);
+ }
+
+ // used to format values like (result is 2009 and we need 09)
+ void Append(int value, const char* format, int startIdx)
+ {
+ char tmp[32];
+ _snprintf(tmp, 32, format, value);
+ Append(tmp+startIdx);
+ }
+
//append a string of unknown length
inline void Append(const char* str)
{
Modified: trunk/Providers/SQLite/Src/Provider/stdafx.h
===================================================================
--- trunk/Providers/SQLite/Src/Provider/stdafx.h 2009-07-26 00:53:36 UTC (rev 4861)
+++ trunk/Providers/SQLite/Src/Provider/stdafx.h 2009-07-27 15:52:22 UTC (rev 4862)
@@ -73,6 +73,7 @@
#define __forceinline __inline__
#define __fastcall
#define _wcsdup wcsdup
+ #define _strnicmp strncasecmp
#define _strdup strdup
#define _snprintf snprintf
#define _wcsicmp wcscasecmp
Modified: trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.cpp
===================================================================
--- trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.cpp 2009-07-26 \
00:53:36 UTC (rev 4861)
+++ trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.cpp 2009-07-27 \
15:52:22 UTC (rev 4862) @@ -26,9 +26,11 @@
#ifdef _WIN32
static const wchar_t* EXPFCT_TEST_FILE = L"..\\..\\TestData\\ExpFctTest.slt";
+static const wchar_t* SC_TEST_FILE = L"..\\..\\TestData\\ExpressionsTest.slt";
#else
#include <unistd.h>
static const wchar_t* EXPFCT_TEST_FILE = L"../../TestData/ExpFctTest.slt";
+static const wchar_t* SC_TEST_FILE = L"../../TestData/ExpressionsTest.slt";
#endif
CPPUNIT_TEST_SUITE_REGISTRATION(FdoExpressionFunctionTest);
@@ -91,6 +93,7 @@
try {
TestXYZMFunction();
+ TestDateStringConv();
} // try ...
@@ -110,3 +113,136 @@
return GetNaNOrdinate();
}
+void FdoExpressionFunctionTest::TestDateStringConv()
+{
+ FdoPtr<FdoIConnection> conn;
+
+ try
+ {
+ conn = UnitTestUtil::OpenConnection( SC_TEST_FILE, true, true);
+
+ //apply schema
+ FdoPtr<FdoIApplySchema> applyschema = \
static_cast<FdoIApplySchema*>(conn->CreateCommand(FdoCommandType_ApplySchema)); + \
FdoPtr<FdoFeatureSchemaCollection> schColl = \
FdoFeatureSchemaCollection::Create(NULL); + \
schColl->ReadXml(L"SchPKTest.xml"); + CPPUNIT_ASSERT(schColl->GetCount() == \
1); +
+ FdoPtr<FdoFeatureSchema> schema = schColl->GetItem(0);
+ applyschema->SetFeatureSchema(schema);
+ applyschema->Execute();
+
+ FdoPtr<FdoIInsert> insCmd = \
static_cast<FdoIInsert*>(conn->CreateCommand(FdoCommandType_Insert)); + \
FdoPtr<FdoPropertyValueCollection> vals = insCmd->GetPropertyValues(); + \
FdoPtr<FdoPropertyValue> propIns; +
+ FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance();
+ double coords[] = { 7.2068, 43.7556,
+ 77.2088, 43.7556,
+ 77.2088, 143.7574,
+ 7.2068, 143.7574,
+ 7.2068, 43.7556 };
+ FdoPtr<FdoILinearRing> outer = gf->CreateLinearRing(0, 10, coords);
+ FdoPtr<FdoIPolygon> poly = gf->CreatePolygon(outer, NULL);
+ FdoPtr<FdoByteArray> polyfgf = gf->GetFgf(poly);
+ FdoPtr<FdoGeometryValue> gv = FdoGeometryValue::Create(polyfgf);
+
+ FdoPtr<FdoPropertyValue> propGeomIns = FdoPropertyValue::Create(L"Geometry", \
gv); + // insert test
+ insCmd->SetFeatureClassName(L"TestCompPK");
+ try
+ {
+ FdoDateTime dt(2005, 1, 22, 8, 5, 1.0);
+ FdoPtr<FdoDateTimeValue> dtValue = FdoDateTimeValue::Create(dt);
+ propIns = FdoPropertyValue::Create(L"PropDT", dtValue);
+
+ FdoPtr<FdoInt64Value> id64Value = FdoInt64Value::Create(1);
+ FdoPtr<FdoPropertyValue> propInsId64 = \
FdoPropertyValue::Create(L"FeatId", id64Value); +
+ FdoPtr<FdoStringValue> idStrValue = FdoStringValue::Create(L"city");
+ FdoPtr<FdoPropertyValue> propInsIdStr = \
FdoPropertyValue::Create(L"Name", idStrValue); +
+ vals->Clear();
+ vals->Add(propIns);
+ vals->Add(propInsId64);
+ vals->Add(propInsIdStr);
+ vals->Add(propGeomIns);
+ FdoPtr<FdoIFeatureReader> rdr = insCmd->Execute();
+ CPPUNIT_ASSERT(rdr->ReadNext());
+ FdoPtr<FdoClassDefinition> clsrdr = rdr->GetClassDefinition();
+ CPPUNIT_ASSERT(rdr->GetInt64(L"FeatId") == 1);
+ CPPUNIT_ASSERT(((FdoStringP)rdr->GetString(L"Name")) == L"city");
+
+ rdr->Close();
+ }
+ catch(FdoException* exc)
+ {
+ UnitTestUtil::PrintException(exc);
+ exc->Release();
+ CPPUNIT_FAIL("\nUnexpected exception: ");
+ }
+
+ try
+ {
+ FdoPtr<FdoISelect> select = \
(FdoISelect*)conn->CreateCommand(FdoCommandType_Select); + \
select->SetFeatureClassName(L"TestCompPK"); + FdoPtr<FdoFilter> filter = \
FdoFilter::Parse(L"PropDT IN ( TIMESTAMP '2005-01-22 08:05:01', TIMESTAMP '2009-07-10 \
22:57:56')"); +
+ select->SetFilter(filter);
+ FdoPtr<FdoIdentifierCollection> selColl = select->GetPropertyNames();
+
+ FdoPtr<FdoExpression> exp = FdoExpression::Parse(L"ToString ( PropDT, \
'DD [Day] Month-YY' )"); + FdoPtr<FdoIdentifier> idfCalc = \
FdoComputedIdentifier::Create(L"Calc", exp); + selColl->Add(idfCalc);
+
+ FdoPtr<FdoExpression> exp2 = FdoExpression::Parse(L"ToDate ( Calc, 'DD \
[Day] Month-YY' )"); + FdoPtr<FdoIdentifier> idfCalc2 = \
FdoComputedIdentifier::Create(L"Calc2", exp2); + selColl->Add(idfCalc2);
+
+ FdoPtr<FdoIFeatureReader> rdr = select->Execute();
+ while(rdr->ReadNext())
+ {
+ if (!rdr->IsNull(L"Calc"))
+ {
+ FdoString* val = rdr->GetString(L"Calc");
+ printf ("Calc=%ls\n", val);
+ }
+ if (!rdr->IsNull(L"Calc2"))
+ {
+ FdoDateTime dt = rdr->GetDateTime(L"Calc2");
+ printf ("Calc2[year] = %d\n", dt.year);
+ }
+ }
+ FdoPtr<FdoClassDefinition> clsrdr = rdr->GetClassDefinition();
+ FdoPtr<FdoPropertyDefinitionCollection> rdrProps = \
clsrdr->GetProperties(); + rdr->Close();
+
+ filter = FdoFilter::Parse(L"PropDT >= TIMESTAMP '2004-01-22 08:05:01'");
+ select->SetFilter(filter);
+ rdr = select->Execute();
+ CPPUNIT_ASSERT(rdr->ReadNext());
+ rdr->Close();
+
+ filter = FdoFilter::Parse(L"PropDT >= TIMESTAMP '2009-01-22 08:05:01'");
+ select->SetFilter(filter);
+ rdr = select->Execute();
+ CPPUNIT_ASSERT(!rdr->ReadNext());
+ rdr->Close();
+ }
+ catch(FdoException* exc)
+ {
+ UnitTestUtil::PrintException(exc);
+ exc->Release();
+ CPPUNIT_FAIL("\nUnexpected exception: ");
+ }
+
+ }
+ catch ( CppUnit::Exception e )
+ {
+ throw;
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL ("caught unexpected exception");
+ }
+ printf( "Done\n" );
+}
Modified: trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.h
===================================================================
--- trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.h 2009-07-26 \
00:53:36 UTC (rev 4861)
+++ trunk/Providers/SQLite/Src/UnitTest/FdoExpressionFunctionTest.h 2009-07-27 \
15:52:22 UTC (rev 4862) @@ -54,6 +54,8 @@
virtual double GetNullOrdinate();
+ void TestDateStringConv();
+
}; // class FdoExpressionFunctionTest
#endif
_______________________________________________
fdo-commits mailing list
fdo-commits@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/fdo-commits
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic