add geometry check during stmt_bind_param

This commit is contained in:
Pengrongkun 2024-11-13 16:53:15 +08:00
parent 653fd8e291
commit 6f3c6548cb
6 changed files with 226 additions and 11 deletions

View File

@ -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 {

View File

@ -49,6 +49,7 @@ target_link_libraries(
PUBLIC os
PUBLIC util
INTERFACE api
PRIVATE geometry
)
if(${BUILD_S3})

View File

@ -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];
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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] = {&params[0]};
TAOS_STMT2_BINDV bindv = {1, &tbname, &tagv[0], &paramv[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();
}