mirror of
https://github.com/mdbtools/mdbtools.git
synced 2026-02-26 05:33:03 +08:00
Added strptime function to SQL parser as a feature. This is needed to i.e. be able to query time-fields in DB and to use dates <1.1.1970 and >19.1.2038. All changes should be backwards-compatible to not break existing queries.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include "mdbtools.h"
|
||||
@@ -37,6 +38,9 @@ static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size);
|
||||
#endif
|
||||
|
||||
static char date_fmt[64] = "%x %X";
|
||||
static int noleap_cal[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
|
||||
static int leap_cal[] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
|
||||
|
||||
|
||||
void mdb_set_date_fmt(const char *fmt)
|
||||
{
|
||||
@@ -778,18 +782,29 @@ static int trim_trailing_zeros(char * buff)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Date/Time is stored as a double, where the whole
|
||||
part is the days from 12/30/1899 and the fractional
|
||||
part is the fractional part of one day. */
|
||||
|
||||
void
|
||||
mdb_tm_to_date(struct tm *t, double *td)
|
||||
{
|
||||
short yr = t->tm_year + 1900;
|
||||
char leap = ((yr & 3) == 0) && ((yr % 100) != 0 || (yr % 400) == 0);
|
||||
int *cal = leap ? leap_cal : noleap_cal;
|
||||
long int time = (yr*365+(yr/4)-(yr/100)+(yr/400)+cal[t->tm_mon]+t->tm_mday)-693959;
|
||||
|
||||
*td = (((long)t->tm_hour * 3600)+((long)t->tm_min * 60)+((long)t->tm_sec)) / 86400.0;
|
||||
if (time>=0) *td+=time; else *td=time-*td;
|
||||
}
|
||||
|
||||
void
|
||||
mdb_date_to_tm(double td, struct tm *t)
|
||||
{
|
||||
long int day, time;
|
||||
int yr, q;
|
||||
int *cal;
|
||||
int noleap_cal[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
|
||||
int leap_cal[] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
|
||||
|
||||
day = (long int)(td);
|
||||
time = (long int)(fabs(td - day) * 86400.0 + 0.5);
|
||||
|
||||
@@ -98,6 +98,43 @@ int mdb_test_int(MdbSargNode *node, gint32 i)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Actually used to not rely on libm.
|
||||
* Maybe there is a cleaner and faster solution? */
|
||||
static double poor_mans_trunc(double x)
|
||||
{
|
||||
char buf[16];
|
||||
sprintf(buf, "%.6f", x);
|
||||
sscanf(buf, "%lf", &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
int mdb_test_double(int op, double vd, double d)
|
||||
{
|
||||
switch (op) {
|
||||
case MDB_EQUAL:
|
||||
//fprintf(stderr, "comparing %lf and %lf\n", d, node->value.d);
|
||||
if (vd == d) return 1;
|
||||
break;
|
||||
case MDB_GT:
|
||||
if (vd < d) return 1;
|
||||
break;
|
||||
case MDB_LT:
|
||||
if (vd > d) return 1;
|
||||
break;
|
||||
case MDB_GTEQ:
|
||||
if (vd <= d) return 1;
|
||||
break;
|
||||
case MDB_LTEQ:
|
||||
if (vd >= d) return 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_double() for operator %d\n",op);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 // Obsolete
|
||||
int
|
||||
mdb_test_date(MdbSargNode *node, double td)
|
||||
{
|
||||
@@ -140,6 +177,7 @@ mdb_test_date(MdbSargNode *node, double td)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
@@ -196,7 +234,7 @@ mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field
|
||||
mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, 256);
|
||||
return mdb_test_string(node, tmpbuf);
|
||||
case MDB_DATETIME:
|
||||
return mdb_test_date(node, mdb_get_double(field->value, 0));
|
||||
return mdb_test_double(node->op, poor_mans_trunc(node->value.d), poor_mans_trunc(mdb_get_double(field->value, 0)));
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user