未验证 提交 5a5c20bd 编写于 作者: D dapan1121 提交者: GitHub

Merge pull request #9059 from taosdata/fix/TD-11970

[TD-11970]<fix>: support timestamp arithmetic operation like "now + 1h/s/d" on timestamp tags
......@@ -39,7 +39,9 @@ typedef struct tVariant {
bool tVariantIsValid(tVariant *pVar);
void tVariantCreate(tVariant *pVar, SStrToken *token, bool needRmquoteEscape);
void tVariantCreate(tVariant *pVar, SStrToken *token);
void tVariantCreateExt(tVariant *pVar, SStrToken *token, int32_t optrType, bool needRmquoteEscape);
void tVariantCreateFromBinary(tVariant *pVar, const char *pz, size_t len, uint32_t type);
......
......@@ -16,6 +16,7 @@
#include "hash.h"
#include "taos.h"
#include "taoserror.h"
#include "taosdef.h"
#include "ttoken.h"
#include "ttokendef.h"
......@@ -30,7 +31,11 @@
assert(0); \
} while (0)
void tVariantCreate(tVariant *pVar, SStrToken *token, bool needRmquoteEscape) {
void tVariantCreate(tVariant *pVar, SStrToken *token) {
tVariantCreateExt(pVar, token, TK_ID, true);
}
void tVariantCreateExt(tVariant *pVar, SStrToken *token, int32_t optrType, bool needRmquoteEscape) {
int32_t ret = 0;
int32_t type = token->type;
......@@ -54,7 +59,7 @@ void tVariantCreate(tVariant *pVar, SStrToken *token, bool needRmquoteEscape) {
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_INT:{
ret = tStrToInteger(token->z, token->type, token->n, &pVar->i64, true);
if (ret != 0) {
if (ret != TSDB_CODE_SUCCESS) {
SStrToken t = {0};
tGetToken(token->z, &t.type);
if (t.type == TK_MINUS) { // it is a signed number which is greater than INT64_MAX or less than INT64_MIN
......@@ -64,7 +69,7 @@ void tVariantCreate(tVariant *pVar, SStrToken *token, bool needRmquoteEscape) {
// data overflow, try unsigned parse the input number
ret = tStrToInteger(token->z, token->type, token->n, &pVar->i64, false);
if (ret != 0) {
if (ret != TSDB_CODE_SUCCESS) {
pVar->nType = -1; // -1 means error type
return;
}
......@@ -85,15 +90,29 @@ void tVariantCreate(tVariant *pVar, SStrToken *token, bool needRmquoteEscape) {
break;
}
case TSDB_DATA_TYPE_TIMESTAMP: {
pVar->i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
break;
}
if (optrType == TK_NOW) {
pVar->i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
} else if (optrType == TK_PLUS || optrType == TK_MINUS) {
char unit = 0;
ret = parseAbsoluteDuration(token->z, token->n, &pVar->i64, &unit, TSDB_TIME_PRECISION_NANO);
if (ret != TSDB_CODE_SUCCESS) {
pVar->nType = -1; // -1 means error type
return;
}
if (optrType == TK_PLUS) {
pVar->i64 += taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
} else {
pVar->i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO) - pVar->i64;
}
}
break;
}
default: { // nType == 0 means the null value
type = TSDB_DATA_TYPE_NULL;
}
}
pVar->nType = type;
}
......@@ -164,7 +183,7 @@ void tVariantCreateFromBinary(tVariant *pVar, const char *pz, size_t len, uint32
pVar->wpz = calloc(1, (lenInwchar + 1) * TSDB_NCHAR_SIZE);
memcpy(pVar->wpz, pz, lenInwchar * TSDB_NCHAR_SIZE);
pVar->nLen = (int32_t)len;
break;
}
case TSDB_DATA_TYPE_JSON:{
......@@ -179,18 +198,18 @@ void tVariantCreateFromBinary(tVariant *pVar, const char *pz, size_t len, uint32
pVar->nLen = (int32_t)len;
break;
}
default:
pVar->i64 = GET_INT32_VAL(pz);
pVar->nLen = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
}
pVar->nType = type;
}
void tVariantDestroy(tVariant *pVar) {
if (pVar == NULL) return;
if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR || pVar->nType == TSDB_DATA_TYPE_JSON) {
tfree(pVar->pz);
pVar->nLen = 0;
......@@ -248,7 +267,7 @@ bool tVariantTypeMatch(tVariant *pVar, int8_t dbType){
void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
if (pSrc == NULL || pDst == NULL) return;
pDst->nType = pSrc->nType;
if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR || pSrc->nType == TSDB_DATA_TYPE_JSON) {
int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
......@@ -332,14 +351,14 @@ int32_t tVariantCompare(const tVariant* p1, const tVariant* p2) {
int32_t tVariantToString(tVariant *pVar, char *dst) {
if (pVar == NULL || dst == NULL) return 0;
switch (pVar->nType) {
case TSDB_DATA_TYPE_BINARY: {
int32_t len = sprintf(dst, "\'%s\'", pVar->pz);
assert(len <= pVar->nLen + sizeof("\'") * 2); // two more chars
return len;
}
case TSDB_DATA_TYPE_NCHAR: {
dst[0] = '\'';
taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1);
......@@ -348,7 +367,7 @@ int32_t tVariantToString(tVariant *pVar, char *dst) {
dst[len + 1] = 0;
return len + 1;
}
case TSDB_DATA_TYPE_BOOL:
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_SMALLINT:
......@@ -357,7 +376,7 @@ int32_t tVariantToString(tVariant *pVar, char *dst) {
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
return sprintf(dst, "%d", (int32_t)pVar->i64);
case TSDB_DATA_TYPE_BIGINT:
return sprintf(dst, "%" PRId64, pVar->i64);
case TSDB_DATA_TYPE_UBIGINT:
......@@ -365,7 +384,7 @@ int32_t tVariantToString(tVariant *pVar, char *dst) {
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
return sprintf(dst, "%.9lf", pVar->dKey);
default:
return 0;
}
......@@ -403,21 +422,21 @@ static int32_t toBinary(tVariant *pVariant, char **pDest, int32_t *pDestSize) {
if (*pDest == pVariant->pz) {
pBuf = calloc(1, INITIAL_ALLOC_SIZE);
}
if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
size_t newSize = pVariant->nLen * TSDB_NCHAR_SIZE;
if (pBuf != NULL) {
if (newSize >= INITIAL_ALLOC_SIZE) {
pBuf = realloc(pBuf, newSize + 1);
}
taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf);
free(pVariant->wpz);
pBuf[newSize] = 0;
} else {
taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest);
}
} else {
if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType)) {
sprintf(pBuf == NULL ? *pDest : pBuf, "%" PRId64, pVariant->i64);
......@@ -429,18 +448,18 @@ static int32_t toBinary(tVariant *pVariant, char **pDest, int32_t *pDestSize) {
setNull(pBuf == NULL ? *pDest : pBuf, TSDB_DATA_TYPE_BINARY, 0);
}
}
if (pBuf != NULL) {
*pDest = pBuf;
}
*pDestSize = (int32_t)strlen(*pDest);
return 0;
}
static int32_t toNchar(tVariant *pVariant, char **pDest, int32_t *pDestSize) {
char tmpBuf[40] = {0};
char * pDst = tmpBuf;
int32_t nLen = 0;
......@@ -778,7 +797,7 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
if (converted) {
*converted = true;
}
if (value > FLT_MAX || value < -FLT_MAX) {
SET_EXT_INFO(converted, value, -FLT_MAX, FLT_MAX, extInfo);
return -1;
......@@ -789,8 +808,8 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
if (converted) {
*converted = true;
}
if (pVariant->i64 > FLT_MAX || pVariant->i64 < -FLT_MAX) {
if (pVariant->i64 > FLT_MAX || pVariant->i64 < -FLT_MAX) {
SET_EXT_INFO(converted, pVariant->i64, -FLT_MAX, FLT_MAX, extInfo);
return -1;
}
......@@ -800,12 +819,12 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
if (converted) {
*converted = true;
}
if (pVariant->dKey > FLT_MAX || pVariant->dKey < -FLT_MAX) {
if (pVariant->dKey > FLT_MAX || pVariant->dKey < -FLT_MAX) {
SET_EXT_INFO(converted, pVariant->dKey, -FLT_MAX, FLT_MAX, extInfo);
return -1;
}
SET_FLOAT_VAL(payload, pVariant->dKey);
} else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
*((uint32_t *)payload) = TSDB_DATA_FLOAT_NULL;
......@@ -850,7 +869,7 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
break;
}
case TSDB_DATA_TYPE_BINARY:{
if (!includeLengthPrefix) {
if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
......@@ -921,7 +940,7 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
assert(p == varDataVal(payload));
}
}
break;
}
case TSDB_DATA_TYPE_JSON:{
......@@ -935,7 +954,7 @@ int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool inc
break;
}
}
return 0;
}
......@@ -950,13 +969,13 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) {
if (pVariant == NULL || pVariant->nType == 0) { // value is not set
return 0;
}
switch (type) {
case TSDB_DATA_TYPE_BOOL: { // bool
if (convertToBool(pVariant, &pVariant->i64) < 0) {
return -1;
}
pVariant->nType = type;
break;
}
......@@ -977,7 +996,7 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) {
free(pVariant->pz);
return -1;
}
free(pVariant->pz);
pVariant->dKey = v;
} else if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
......@@ -987,14 +1006,14 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) {
free(pVariant->pz);
return -1;
}
free(pVariant->pz);
pVariant->dKey = v;
} else if (pVariant->nType >= TSDB_DATA_TYPE_BOOL && pVariant->nType <= TSDB_DATA_TYPE_BIGINT) {
double tmp = (double) pVariant->i64;
pVariant->dKey = tmp;
}
pVariant->nType = TSDB_DATA_TYPE_DOUBLE;
break;
}
......@@ -1015,6 +1034,6 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) {
break;
}
}
return 0;
}
......@@ -16,7 +16,6 @@
#ifndef TDENGINE_TTOKENDEF_H
#define TDENGINE_TTOKENDEF_H
#define TK_ID 1
#define TK_BOOL 2
#define TK_TINYINT 3
......@@ -139,12 +138,12 @@
#define TK_USING 120
#define TK_NULL 121
#define TK_NOW 122
#define TK_SELECT 123
#define TK_UNION 124
#define TK_ALL 125
#define TK_DISTINCT 126
#define TK_FROM 127
#define TK_VARIABLE 128
#define TK_VARIABLE 123
#define TK_SELECT 124
#define TK_UNION 125
#define TK_ALL 126
#define TK_DISTINCT 127
#define TK_FROM 128
#define TK_RANGE 129
#define TK_INTERVAL 130
#define TK_EVERY 131
......@@ -219,7 +218,6 @@
#define TK_FILE 200
#define TK_SPACE 300
#define TK_COMMENT 301
#define TK_ILLEGAL 302
......
......@@ -253,7 +253,7 @@ acct_optr(Y) ::= pps(C) tseries(D) storage(P) streams(F) qtime(Q) dbs(E) users(K
intitemlist(A) ::= intitemlist(X) COMMA intitem(Y). { A = tVariantListAppend(X, &Y, -1); }
intitemlist(A) ::= intitem(X). { A = tVariantListAppend(NULL, &X, -1); }
intitem(A) ::= INTEGER(X). { toTSDBType(X.type); tVariantCreate(&A, &X, true); }
intitem(A) ::= INTEGER(X). { toTSDBType(X.type); tVariantCreate(&A, &X); }
%type keep {SArray*}
%destructor keep {taosArrayDestroy($$);}
......@@ -438,39 +438,49 @@ column(A) ::= ids(X) typename(Y). {
tagitemlist(A) ::= tagitemlist(X) COMMA tagitem(Y). { A = tVariantListAppend(X, &Y, -1); }
tagitemlist(A) ::= tagitem(X). { A = tVariantListAppend(NULL, &X, -1); }
tagitem(A) ::= INTEGER(X). { toTSDBType(X.type); tVariantCreate(&A, &X, true); }
tagitem(A) ::= FLOAT(X). { toTSDBType(X.type); tVariantCreate(&A, &X, true); }
tagitem(A) ::= STRING(X). { toTSDBType(X.type); tVariantCreate(&A, &X, true); }
tagitem(A) ::= BOOL(X). { toTSDBType(X.type); tVariantCreate(&A, &X, true); }
tagitem(A) ::= NULL(X). { X.type = 0; tVariantCreate(&A, &X, true); }
tagitem(A) ::= NOW(X). { X.type = TSDB_DATA_TYPE_TIMESTAMP; tVariantCreate(&A, &X, true);}
tagitem(A) ::= INTEGER(X). { toTSDBType(X.type); tVariantCreate(&A, &X); }
tagitem(A) ::= FLOAT(X). { toTSDBType(X.type); tVariantCreate(&A, &X); }
tagitem(A) ::= STRING(X). { toTSDBType(X.type); tVariantCreate(&A, &X); }
tagitem(A) ::= BOOL(X). { toTSDBType(X.type); tVariantCreate(&A, &X); }
tagitem(A) ::= NULL(X). { X.type = 0; tVariantCreate(&A, &X); }
tagitem(A) ::= NOW(X). { X.type = TSDB_DATA_TYPE_TIMESTAMP; tVariantCreateExt(&A, &X, TK_NOW, true);}
tagitem(A) ::= NOW PLUS VARIABLE(X).{
X.type = TSDB_DATA_TYPE_TIMESTAMP;
tVariantCreateExt(&A, &X, TK_PLUS, true);
}
tagitem(A) ::= NOW MINUS VARIABLE(X).{
X.type = TSDB_DATA_TYPE_TIMESTAMP;
tVariantCreateExt(&A, &X, TK_MINUS, true);
}
tagitem(A) ::= MINUS(X) INTEGER(Y).{
X.n += Y.n;
X.type = Y.type;
toTSDBType(X.type);
tVariantCreate(&A, &X, true);
tVariantCreate(&A, &X);
}
tagitem(A) ::= MINUS(X) FLOAT(Y). {
X.n += Y.n;
X.type = Y.type;
toTSDBType(X.type);
tVariantCreate(&A, &X, true);
tVariantCreate(&A, &X);
}
tagitem(A) ::= PLUS(X) INTEGER(Y). {
X.n += Y.n;
X.type = Y.type;
toTSDBType(X.type);
tVariantCreate(&A, &X, true);
tVariantCreate(&A, &X);
}
tagitem(A) ::= PLUS(X) FLOAT(Y). {
X.n += Y.n;
X.type = Y.type;
toTSDBType(X.type);
tVariantCreate(&A, &X, true);
tVariantCreate(&A, &X);
}
//////////////////////// The SELECT statement /////////////////////////////////
......@@ -609,7 +619,7 @@ fill_opt(N) ::= . { N = 0; }
fill_opt(N) ::= FILL LP ID(Y) COMMA tagitemlist(X) RP. {
tVariant A = {0};
toTSDBType(Y.type);
tVariantCreate(&A, &Y, true);
tVariantCreate(&A, &Y);
tVariantListInsert(X, &A, -1, 0);
N = X;
......@@ -652,12 +662,12 @@ sortlist(A) ::= arrow(Y) sortorder(Z). {
%type item {tVariant}
item(A) ::= ID(X). {
toTSDBType(X.type);
tVariantCreate(&A, &X, true);
tVariantCreate(&A, &X);
}
item(A) ::= ID(X) DOT ID(Y). {
toTSDBType(X.type);
X.n += (1+Y.n);
tVariantCreate(&A, &X, true);
tVariantCreate(&A, &X);
}
%type sortorder {int}
......
......@@ -143,14 +143,14 @@ tSqlExpr *tSqlExprCreateIdValue(SSqlInfo* pInfo, SStrToken *pToken, int32_t optr
if (optrType == TK_NULL) {
if (pToken){
pToken->type = TSDB_DATA_TYPE_NULL;
tVariantCreate(&pSqlExpr->value, pToken, true);
tVariantCreate(&pSqlExpr->value, pToken);
}
pSqlExpr->tokenId = optrType;
pSqlExpr->type = SQL_NODE_VALUE;
} else if (optrType == TK_INTEGER || optrType == TK_STRING || optrType == TK_FLOAT || optrType == TK_BOOL) {
if (pToken) {
toTSDBType(pToken->type);
tVariantCreate(&pSqlExpr->value, pToken, true);
tVariantCreate(&pSqlExpr->value, pToken);
}
pSqlExpr->tokenId = optrType;
pSqlExpr->type = SQL_NODE_VALUE;
......@@ -211,7 +211,7 @@ tSqlExpr *tSqlExprCreateTimestamp(SStrToken *pToken, int32_t optrType) {
if (optrType == TK_INTEGER || optrType == TK_STRING) {
if (pToken) {
toTSDBType(pToken->type);
tVariantCreate(&pSqlExpr->value, pToken, true);
tVariantCreate(&pSqlExpr->value, pToken);
}
pSqlExpr->tokenId = optrType;
pSqlExpr->type = SQL_NODE_VALUE;
......@@ -599,7 +599,7 @@ SArray *tVariantListAppendToken(SArray *pList, SStrToken *pToken, uint8_t order,
if (pToken) {
tVariantListItem item;
tVariantCreate(&item.pVar, pToken, needRmquoteEscape);
tVariantCreateExt(&item.pVar, pToken, TK_ID, needRmquoteEscape);
item.sortOrder = order;
taosArrayPush(pList, &item);
......
此差异已折叠。
......@@ -238,3 +238,4 @@ run general/parser/tbname_escape.sim
run general/parser/columnName_escape.sim
run general/parser/tagName_escape.sim
run general/parser/interp_blocks.sim
run general/parser/create_tb_with_timestamp_tag.sim
system sh/stop_dnodes.sh
system sh/deploy.sh -n dnode1 -i 1
system sh/cfg.sh -n dnode1 -c walLevel -v 1
system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2
system sh/exec.sh -n dnode1 -s start
sleep 100
sql connect
print ======================== dnode1 start
$db = testdb
sql create database $db precision 'ns'
sql use $db
sql create stable st1 (ts timestamp , c1 int) tags(t1 timestamp, t2 int)
sql create table t1_0 using st1 tags(now, 0)
#nanoseconds
sql create table t1_1 using st1 tags(now + 1b, 0)
#microseconds
sql create table t1_2 using st1 tags(now + 1u, 0)
#milliseconds
sql create table t1_3 using st1 tags(now + 1a, 0)
#seconds
sql create table t1_4 using st1 tags(now + 1s, 0)
#minutes
sql create table t1_5 using st1 tags(now + 1m, 0)
#hours
sql create table t1_6 using st1 tags(now + 1h, 0)
#days
sql create table t1_7 using st1 tags(now + 1d, 0)
#weeks
sql create table t1_8 using st1 tags(now + 1w, 0)
#months(not supported)
sql_error create table t1_9 using st1 tags(now + 1n, 0)
#years(not supported)
sql_error create table t1_10 using st1 tags(now + 1y, 0)
sql create stable st2 (ts timestamp , c1 int) tags(t1 timestamp, t2 int)
sql create table t2_0 using st2 tags(now, 0)
#nanoseconds
sql create table t2_1 using st2 tags(now - 1b, 0)
#microseconds
sql create table t2_2 using st2 tags(now - 1u, 0)
#milliseconds
sql create table t2_3 using st2 tags(now - 1a, 0)
#seconds
sql create table t2_4 using st2 tags(now - 1s, 0)
#minutes
sql create table t2_5 using st2 tags(now - 1m, 0)
#hours
sql create table t2_6 using st2 tags(now - 1h, 0)
#days
sql create table t2_7 using st2 tags(now - 1d, 0)
#weeks
sql create table t2_8 using st2 tags(now - 1w, 0)
#months(not supported)
sql_error create table t2_9 using st2 tags(now - 1n, 0)
#years(not supported)
sql_error create table t2_10 using st2 tags(now - 1y, 0)
sql insert into t1_0 values (now, 0)
sql insert into t1_1 values (now, 1)
sql insert into t1_2 values (now, 2)
sql insert into t1_3 values (now, 3)
sql insert into t1_4 values (now, 4)
sql insert into t1_5 values (now, 5)
sql insert into t1_6 values (now, 6)
sql insert into t1_7 values (now, 7)
sql insert into t1_8 values (now, 8)
sql insert into t2_0 values (now, 0)
sql insert into t2_1 values (now, 1)
sql insert into t2_2 values (now, 2)
sql insert into t2_3 values (now, 3)
sql insert into t2_4 values (now, 4)
sql insert into t2_5 values (now, 5)
sql insert into t2_6 values (now, 6)
sql insert into t2_7 values (now, 7)
sql insert into t2_8 values (now, 8)
sql select * from st1
if $rows != 9 then
return -1
endi
sql select * from st2
if $rows != 9 then
return -1
endi
sql create stable st3 (ts timestamp , c1 int) tags (t1 timestamp, t2 timestamp, t3 timestamp, t4 timestamp, t5 timestamp, t6 timestamp, t7 timestamp, t8 timestamp, t9 timestamp)
sql create table t3 using st3 tags(now, now + 1b, now + 1u, now + 1a, now + 1s, now + 1m, now + 1h, now + 1d, now + 1w)
sql insert into t3 values (now, 1)
sql select * from st3
if $rows != 1 then
return -1
endi
sql create stable st4 (ts timestamp , c1 int) tags (t1 timestamp, t2 timestamp, t3 timestamp, t4 timestamp, t5 timestamp, t6 timestamp, t7 timestamp, t8 timestamp, t9 timestamp)
sql create table t4 using st4 tags(now, now - 1b, now - 1u, now - 1a, now - 1s, now - 1m, now - 1h, now - 1d, now - 1w)
sql insert into t4 values (now, 1)
sql select * from st4
if $rows != 1 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册