add geometry check during stmt_bind_param
This commit is contained in:
parent
653fd8e291
commit
6f3c6548cb
|
@ -155,6 +155,7 @@ int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag);
|
|||
int32_t tTagToValArray(const STag *pTag, SArray **ppArray);
|
||||
void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remove
|
||||
int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, void *pMsgBuf);
|
||||
int32_t parseGeotoTagData(const char *g, SArray *pTagVals, SSchema *pTagSchema, unsigned char *output);
|
||||
|
||||
// SColData ================================
|
||||
typedef struct {
|
||||
|
|
|
@ -49,6 +49,7 @@ target_link_libraries(
|
|||
PUBLIC os
|
||||
PUBLIC util
|
||||
INTERFACE api
|
||||
PRIVATE geometry
|
||||
)
|
||||
|
||||
if(${BUILD_S3})
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "tdataformat.h"
|
||||
#include "geosWrapper.h"
|
||||
#include "tRealloc.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tlog.h"
|
||||
|
@ -3036,6 +3037,35 @@ _exit:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t formatGeometry(SColData *pColData, int8_t *buf, int32_t lenght, int32_t buffMaxLen) {
|
||||
int32_t code = 0;
|
||||
unsigned char *output = NULL;
|
||||
size_t size = 0;
|
||||
uint8_t *g = NULL;
|
||||
code = tRealloc(&g, lenght);
|
||||
if (code) {
|
||||
return code;
|
||||
}
|
||||
|
||||
(void)memcpy(g, buf, lenght);
|
||||
code = doGeomFromText(g, &output, &size);
|
||||
tFree(g);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
if (size > buffMaxLen) {
|
||||
code = TSDB_CODE_PAR_VALUE_TOO_LONG;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, output, size);
|
||||
|
||||
_exit:
|
||||
geosFreeBuffer(output);
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tColDataAddValueByBind(SColData *pColData, TAOS_MULTI_BIND *pBind, int32_t buffMaxLen) {
|
||||
int32_t code = 0;
|
||||
|
||||
|
@ -3046,6 +3076,13 @@ int32_t tColDataAddValueByBind(SColData *pColData, TAOS_MULTI_BIND *pBind, int32
|
|||
}
|
||||
|
||||
if (IS_VAR_DATA_TYPE(pColData->type)) { // var-length data type
|
||||
if (pColData->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
code = initCtxGeomFromText();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
uError("init geom from text failed, code:%d", code);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
for (int32_t i = 0; i < pBind->num; ++i) {
|
||||
if (pBind->is_null && pBind->is_null[i]) {
|
||||
if (pColData->cflag & COL_IS_KEY) {
|
||||
|
@ -3055,11 +3092,15 @@ int32_t tColDataAddValueByBind(SColData *pColData, TAOS_MULTI_BIND *pBind, int32
|
|||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0);
|
||||
if (code) goto _exit;
|
||||
} else if (pBind->length[i] > buffMaxLen) {
|
||||
uError("var data length too big, len:%d, max:%d", pBind->length[i], buffMaxLen);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
return TSDB_CODE_PAR_VALUE_TOO_LONG;
|
||||
} else {
|
||||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](
|
||||
pColData, (uint8_t *)pBind->buffer + pBind->buffer_length * i, pBind->length[i]);
|
||||
if (pColData->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
code = formatGeometry(pColData, (uint8_t *)pBind->buffer + pBind->buffer_length * i, pBind->length[i],
|
||||
buffMaxLen);
|
||||
} else {
|
||||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](
|
||||
pColData, (uint8_t *)pBind->buffer + pBind->buffer_length * i, pBind->length[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // fixed-length data type
|
||||
|
@ -3119,6 +3160,13 @@ int32_t tColDataAddValueByBind2(SColData *pColData, TAOS_STMT2_BIND *pBind, int3
|
|||
|
||||
if (IS_VAR_DATA_TYPE(pColData->type)) { // var-length data type
|
||||
uint8_t *buf = pBind->buffer;
|
||||
if (pColData->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
code = initCtxGeomFromText();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
uError("init geom from text failed, code:%d", code);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
for (int32_t i = 0; i < pBind->num; ++i) {
|
||||
if (pBind->is_null && pBind->is_null[i]) {
|
||||
if (pColData->cflag & COL_IS_KEY) {
|
||||
|
@ -3133,10 +3181,13 @@ int32_t tColDataAddValueByBind2(SColData *pColData, TAOS_STMT2_BIND *pBind, int3
|
|||
if (code) goto _exit;
|
||||
}
|
||||
} else if (pBind->length[i] > buffMaxLen) {
|
||||
uError("var data length too big, len:%d, max:%d", pBind->length[i], buffMaxLen);
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
return TSDB_CODE_PAR_VALUE_TOO_LONG;
|
||||
} else {
|
||||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, buf, pBind->length[i]);
|
||||
if (pColData->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
code = formatGeometry(pColData, buf, pBind->length[i], buffMaxLen);
|
||||
} else {
|
||||
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, buf, pBind->length[i]);
|
||||
}
|
||||
buf += pBind->length[i];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "geosWrapper.h"
|
||||
#include "os.h"
|
||||
#include "parInsertUtil.h"
|
||||
#include "parInt.h"
|
||||
|
@ -187,11 +188,24 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const ch
|
|||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
} else if (pTagSchema->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
char* tmp = taosMemoryCalloc(1, colLen);
|
||||
if (!tmp) {
|
||||
code = terrno;
|
||||
goto end;
|
||||
}
|
||||
memcpy(tmp, bind[c].buffer, colLen);
|
||||
unsigned char* out = NULL;
|
||||
code = parseGeotoTagData(tmp, pTagArray, pTagSchema, out);
|
||||
taosMemoryFree(tmp);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
geosFreeBuffer(out);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY || pTagSchema->type == TSDB_DATA_TYPE_VARBINARY ||
|
||||
pTagSchema->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY || pTagSchema->type == TSDB_DATA_TYPE_VARBINARY) {
|
||||
val.pData = (uint8_t*)bind[c].buffer;
|
||||
val.nData = colLen;
|
||||
} else if (pTagSchema->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
|
@ -251,6 +265,9 @@ end:
|
|||
if (p->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
taosMemoryFreeClear(p->pData);
|
||||
}
|
||||
if (p->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
geosFreeBuffer(p->pData);
|
||||
}
|
||||
}
|
||||
taosArrayDestroy(pTagArray);
|
||||
taosArrayDestroy(tagName);
|
||||
|
@ -539,11 +556,24 @@ int32_t qBindStmtTagsValue2(void* pBlock, void* boundTags, int64_t suid, const c
|
|||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
} else if (pTagSchema->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
char* tmp = taosMemoryCalloc(1, colLen);
|
||||
if (!tmp) {
|
||||
code = terrno;
|
||||
goto end;
|
||||
}
|
||||
memcpy(tmp, bind[c].buffer, colLen);
|
||||
unsigned char* out = NULL;
|
||||
code = parseGeotoTagData(tmp, pTagArray, pTagSchema, out);
|
||||
taosMemoryFree(tmp);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
geosFreeBuffer(out);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY || pTagSchema->type == TSDB_DATA_TYPE_VARBINARY ||
|
||||
pTagSchema->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY || pTagSchema->type == TSDB_DATA_TYPE_VARBINARY) {
|
||||
val.pData = (uint8_t*)bind[c].buffer;
|
||||
val.nData = colLen;
|
||||
} else if (pTagSchema->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
|
@ -603,6 +633,9 @@ end:
|
|||
if (p->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
taosMemoryFreeClear(p->pData);
|
||||
}
|
||||
if (p->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
geosFreeBuffer(p->pData);
|
||||
}
|
||||
}
|
||||
taosArrayDestroy(pTagArray);
|
||||
taosArrayDestroy(tagName);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "parUtil.h"
|
||||
#include "cJSON.h"
|
||||
#include "geosWrapper.h"
|
||||
#include "querynodes.h"
|
||||
#include "tarray.h"
|
||||
#include "tlog.h"
|
||||
|
@ -518,6 +519,35 @@ end:
|
|||
return retCode;
|
||||
}
|
||||
|
||||
int32_t parseGeotoTagData(const char* g, SArray* pTagVals, SSchema* pTagSchema, unsigned char* output) {
|
||||
int32_t code = 0;
|
||||
size_t size = 0;
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
code = initCtxGeomFromText();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
code = doGeomFromText(g, &output, &size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
if (size > pTagSchema->bytes) {
|
||||
code = TSDB_CODE_PAR_VALUE_TOO_LONG;
|
||||
goto end;
|
||||
}
|
||||
|
||||
val.pData = (uint8_t*)output;
|
||||
val.nData = (uint32_t)size;
|
||||
|
||||
if (NULL == taosArrayPush(pTagVals, &val)) {
|
||||
code = terrno;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t getInsTagsTableTargetNameFromOp(int32_t acctId, SOperatorNode* pOper, SName* pName) {
|
||||
if (OP_TYPE_EQUAL != pOper->opType) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "taos.h"
|
||||
|
||||
void do_query(TAOS* taos, const char* sql) {
|
||||
printf("[sql]%s\n", sql);
|
||||
TAOS_RES* result = taos_query(taos, sql);
|
||||
int code = taos_errno(result);
|
||||
if (code) {
|
||||
printf(" failed to query: %s, reason:%s\n", sql, taos_errstr(result));
|
||||
taos_free_result(result);
|
||||
return;
|
||||
}
|
||||
taos_free_result(result);
|
||||
}
|
||||
|
||||
void execute_test(TAOS* taos, const char* tbname, const char* tag2, const char* col2, const char* case_desc) {
|
||||
// prepare stmt
|
||||
TAOS_STMT2_OPTION option = {0, true, false, NULL, NULL};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
const char* sql;
|
||||
if (tbname == "tb4") {
|
||||
sql = "insert into db.? using db.stb2 tags(?, ?) values(?,?)";
|
||||
} else {
|
||||
sql = "insert into db.? using db.stb tags(?, ?) values(?,?)";
|
||||
}
|
||||
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||
printf("\n%s\n insert into db.? using db.stb tags(?, ?) values(?,?)\n bind_tag : %s, bind_col : %s\n", case_desc,
|
||||
tag2, col2);
|
||||
if (code != 0) {
|
||||
printf(" failed to execute taos_stmt2_prepare. error:%s\n", taos_stmt2_error(stmt));
|
||||
taos_stmt2_close(stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare data
|
||||
int t1_val = 0;
|
||||
int64_t ts = 1591060628000;
|
||||
int32_t length[5] = {sizeof(int), 2, sizeof(int64_t), (int32_t)strlen(tag2), (int32_t)strlen(col2)};
|
||||
TAOS_STMT2_BIND tags[2] = {{TSDB_DATA_TYPE_INT, &t1_val, &length[0], NULL, 1},
|
||||
{TSDB_DATA_TYPE_GEOMETRY, (void*)tag2, &length[3], NULL, 1}};
|
||||
TAOS_STMT2_BIND params[2] = {{TSDB_DATA_TYPE_TIMESTAMP, &ts, &length[2], NULL, 1},
|
||||
{TSDB_DATA_TYPE_GEOMETRY, (void*)col2, &length[4], NULL, 1}};
|
||||
TAOS_STMT2_BIND* tagv[1] = {&tags[0]};
|
||||
TAOS_STMT2_BIND* paramv[1] = {¶ms[0]};
|
||||
|
||||
TAOS_STMT2_BINDV bindv = {1, &tbname, &tagv[0], ¶mv[0]};
|
||||
code = taos_stmt2_bind_param(stmt, &bindv, -1);
|
||||
if (code != 0) {
|
||||
printf(" failed to bind param. error:%s\n", taos_stmt2_error(stmt));
|
||||
taos_stmt2_close(stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (taos_stmt2_exec(stmt, NULL)) {
|
||||
printf(" failed to execute insert statement.error:%s\n", taos_stmt2_error(stmt));
|
||||
taos_stmt2_close(stmt);
|
||||
return;
|
||||
}
|
||||
printf("[ok]\n");
|
||||
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
void test1(TAOS* taos) {
|
||||
execute_test(taos, "tb1", "POINT(1.0 1.0)", "LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", "[normal]case 1");
|
||||
}
|
||||
|
||||
void test2(TAOS* taos) {
|
||||
execute_test(taos, "tb2", "hello", "LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", "[wrong tag]case 2");
|
||||
}
|
||||
|
||||
void test3(TAOS* taos) { execute_test(taos, "tb3", "POLYGON((0 0, 4 0, 4 4, 0 4, 0 0))", "1", "[wrong col]case 3"); }
|
||||
|
||||
void test4(TAOS* taos) {
|
||||
execute_test(taos, "tb4", "POLYGON((0 0, 4 0, 4 4, 0 4, 0 0))", "POINT(1.0 1.0)", "[wrong size]case 4");
|
||||
}
|
||||
|
||||
int main() {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0);
|
||||
if (!taos) {
|
||||
printf("failed to connect to db, reason:%s\n", taos_errstr(taos));
|
||||
exit(1);
|
||||
}
|
||||
// init test db & stb table
|
||||
do_query(taos, "drop database if exists db");
|
||||
do_query(taos, "create database db");
|
||||
do_query(taos, "create table db.stb (ts timestamp, b geometry(100)) tags(t1 int, t2 geometry(100))");
|
||||
do_query(taos, "create table db.stb2 (ts timestamp, b geometry(100)) tags(t1 int, t2 geometry(10))");
|
||||
|
||||
test1(taos);
|
||||
test2(taos);
|
||||
test3(taos);
|
||||
test4(taos);
|
||||
|
||||
taos_close(taos);
|
||||
taos_cleanup();
|
||||
}
|
Loading…
Reference in New Issue