summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 57ec5be)
raw | patch | inline | side by side (parent: 57ec5be)
author | Sebastian Harl <sh@tokkee.org> | |
Fri, 1 Aug 2014 06:59:50 +0000 (08:59 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Fri, 1 Aug 2014 06:59:50 +0000 (08:59 +0200) |
The following cases are now supported:
- <integer> or <decimal> <mul> <datetime>
- <datetime> <mul> or <div> or <mod> <integer> or <decimal>
Think of <datetime> having a time unit like seconds. It's perfectly fine to
multiply with or divide seconds by a number. However, since we don't have any
type having the unit Hertz, we cannot support numbers divided by <datetime>.
- <integer> or <decimal> <mul> <datetime>
- <datetime> <mul> or <div> or <mod> <integer> or <decimal>
Think of <datetime> having a time unit like seconds. It's perfectly fine to
multiply with or divide seconds by a number. However, since we don't have any
type having the unit Hertz, we cannot support numbers divided by <datetime>.
src/core/data.c | patch | blob | history | |
src/include/core/data.h | patch | blob | history | |
t/unit/core/data_test.c | patch | blob | history |
diff --git a/src/core/data.c b/src/core/data.c
index cdafac30f284701482b583bd2f14f85e508b6526..fc646f0b5456c5842900223e759698866699b7f3 100644 (file)
--- a/src/core/data.c
+++ b/src/core/data.c
sdb_data_expr_eval(int op, const sdb_data_t *d1, const sdb_data_t *d2,
sdb_data_t *res)
{
- if (d1->type != d2->type)
- return -1;
-
switch (op) {
case SDB_DATA_CONCAT:
return data_concat(d1, d2, res);
case SDB_DATA_ADD:
+ if (d1->type != d2->type)
+ return -1;
switch (d1->type) {
case SDB_TYPE_INTEGER:
res->data.integer = d1->data.integer + d2->data.integer;
}
break;
case SDB_DATA_SUB:
+ if (d1->type != d2->type)
+ return -1;
switch (d1->type) {
case SDB_TYPE_INTEGER:
res->data.integer = d1->data.integer - d2->data.integer;
case SDB_DATA_MUL:
switch (d1->type) {
case SDB_TYPE_INTEGER:
- res->data.integer = d1->data.integer * d2->data.integer;
+ if (d2->type == SDB_TYPE_INTEGER)
+ res->data.integer = d1->data.integer
+ * d2->data.integer;
+ else if (d2->type == SDB_TYPE_DATETIME) {
+ res->data.datetime = (sdb_time_t)d1->data.integer
+ * d2->data.datetime;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else
+ return -1;
break;
case SDB_TYPE_DECIMAL:
- res->data.decimal = d1->data.decimal * d2->data.decimal;
+ if (d2->type == SDB_TYPE_DECIMAL)
+ res->data.decimal = d1->data.decimal
+ * d2->data.decimal;
+ else if (d2->type == SDB_TYPE_DATETIME) {
+ double tmp = d1->data.decimal
+ * (double)d2->data.datetime;
+ res->data.datetime = (sdb_time_t)tmp;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else
+ return -1;
break;
case SDB_TYPE_DATETIME:
- res->data.datetime = d1->data.datetime * d2->data.datetime;
+ if (d2->type == SDB_TYPE_DATETIME)
+ res->data.datetime = d1->data.datetime
+ * d2->data.datetime;
+ else if (d2->type == SDB_TYPE_INTEGER) {
+ res->data.datetime = d1->data.datetime
+ * (sdb_time_t)d2->data.integer;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else if (d2->type == SDB_TYPE_DECIMAL) {
+ double tmp = (double)d1->data.datetime
+ * d2->data.decimal;
+ res->data.datetime = (sdb_time_t)tmp;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else
+ return -1;
break;
default:
return -1;
case SDB_DATA_DIV:
switch (d1->type) {
case SDB_TYPE_INTEGER:
+ if (d2->type != SDB_TYPE_INTEGER)
+ return -1;
res->data.integer = d1->data.integer / d2->data.integer;
break;
case SDB_TYPE_DECIMAL:
+ if (d2->type != SDB_TYPE_DECIMAL)
+ return -1;
res->data.decimal = d1->data.decimal / d2->data.decimal;
break;
case SDB_TYPE_DATETIME:
- res->data.datetime = d1->data.datetime / d2->data.datetime;
+ if (d2->type == SDB_TYPE_DATETIME)
+ res->data.datetime = d1->data.datetime
+ / d2->data.datetime;
+ else if (d2->type == SDB_TYPE_INTEGER) {
+ res->data.datetime = d1->data.datetime
+ / (sdb_time_t)d2->data.integer;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else if (d2->type == SDB_TYPE_DECIMAL) {
+ double tmp = (double)d1->data.datetime
+ / d2->data.decimal;
+ res->data.datetime = (sdb_time_t)tmp;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else
+ return -1;
break;
default:
return -1;
case SDB_DATA_MOD:
switch (d1->type) {
case SDB_TYPE_INTEGER:
+ if (d2->type != SDB_TYPE_INTEGER)
+ return -1;
res->data.integer = d1->data.integer % d2->data.integer;
break;
case SDB_TYPE_DECIMAL:
+ if (d2->type != SDB_TYPE_DECIMAL)
+ return -1;
res->data.decimal = fmod(d1->data.decimal, d2->data.decimal);
break;
case SDB_TYPE_DATETIME:
- res->data.datetime = d1->data.datetime % d2->data.datetime;
+ if (d2->type == SDB_TYPE_DATETIME)
+ res->data.datetime = d1->data.datetime
+ % d2->data.datetime;
+ else if (d2->type == SDB_TYPE_INTEGER) {
+ res->data.datetime = d1->data.datetime
+ % (sdb_time_t)d2->data.integer;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else if (d2->type == SDB_TYPE_DECIMAL) {
+ double tmp = fmod((double)d1->data.datetime,
+ d2->data.decimal);
+ res->data.datetime = (sdb_time_t)tmp;
+ res->type = SDB_TYPE_DATETIME;
+ return 0;
+ }
+ else
+ return -1;
break;
default:
return -1;
index 2e9b90bcfd55af660d3cb576b1c5e3e21427730e..8f9b282777925330c3f4ed9669febbb73b846760 100644 (file)
--- a/src/include/core/data.h
+++ b/src/include/core/data.h
/*
* sdb_data_expr_eval:
- * Evaluate a simple arithmetic expression on two data points. The data-type
- * of d1 and d2 have to be the same. String and binary data only support
- * concatenation and all other data types only support the other operators.
+ * Evaluate a simple arithmetic expression on two data points. String and
+ * binary data only support concatenation and all other data types only
+ * support the other operators.
+ *
+ * The data-types of d1 and d2 have to be the same, except for the following
+ * cases:
+ * - <integer> or <decimal> <mul> <datetime>
+ * - <datetime> <mul> or <div> or <mod> <integer> or <decimal>
*
* Returns:
* - 0 on success
index 0fd61a57539ff7e322be0356666a5375add663ee..606eae53b1cf69415eb2076a8c868be0ae890f40 100644 (file)
--- a/t/unit/core/data_test.c
+++ b/t/unit/core/data_test.c
{ .binary = { 6, (unsigned char *)"a\0ab\0b" } },
},
},
+ /* supported type-mismatches */
+ {
+ /* int * datetime */
+ { SDB_TYPE_INTEGER, { .integer = 20 } },
+ { SDB_TYPE_DATETIME, { .datetime = 2 } },
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ { SDB_TYPE_DATETIME, { .datetime = 40 } },
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ },
+ {
+ /* datetime * int, datetime / int, datetime % int */
+ { SDB_TYPE_DATETIME, { .datetime = 20 } },
+ { SDB_TYPE_INTEGER, { .integer = 2 } },
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ { SDB_TYPE_DATETIME, { .datetime = 40 } },
+ { SDB_TYPE_DATETIME, { .datetime = 10 } },
+ { SDB_TYPE_DATETIME, { .datetime = 0 } },
+ SDB_DATA_INIT,
+ },
+ {
+ /* float * datetime */
+ { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
+ { SDB_TYPE_DATETIME, { .datetime = 2 } },
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ { SDB_TYPE_DATETIME, { .datetime = 40 } },
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ },
+ {
+ /* datetime * float, datetime / float, datetime % float */
+ { SDB_TYPE_DATETIME, { .datetime = 20 } },
+ { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
+ SDB_DATA_INIT,
+ SDB_DATA_INIT,
+ { SDB_TYPE_DATETIME, { .datetime = 40 } },
+ { SDB_TYPE_DATETIME, { .datetime = 10 } },
+ { SDB_TYPE_DATETIME, { .datetime = 0 } },
+ SDB_DATA_INIT,
+ },
};
size_t i;