ci: the compilation of the c samples in the documentation is separate from the TDengine build
This commit is contained in:
commit
e5dbf39e86
|
@ -426,6 +426,10 @@ pipeline {
|
||||||
cd ${WKC}/tests/parallel_test
|
cd ${WKC}/tests/parallel_test
|
||||||
./run_check_assert_container.sh -d ${WKDIR}
|
./run_check_assert_container.sh -d ${WKDIR}
|
||||||
'''
|
'''
|
||||||
|
sh '''
|
||||||
|
cd ${WKC}/tests/parallel_test
|
||||||
|
./run_check_void_container.sh -d ${WKDIR}
|
||||||
|
'''
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
rm -rf ${WKC}/debug
|
rm -rf ${WKC}/debug
|
||||||
|
|
|
@ -7,7 +7,17 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PREPARE_ENV_CMD}
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${TD_TESTS_OUTPUT_DIR}/cfg/
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${TD_TESTS_OUTPUT_DIR}/cfg/
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${TD_TESTS_OUTPUT_DIR}/log/
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${TD_TESTS_OUTPUT_DIR}/log/
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${TD_TESTS_OUTPUT_DIR}/data/
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${TD_TESTS_OUTPUT_DIR}/data/
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo dataDir ${TD_TESTS_OUTPUT_DIR}/data > ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
COMMAND ${CMAKE_COMMAND} -E echo firstEp localhost:6030 > ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo fqdn localhost >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo serverPort 6030 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo debugFlag 135 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo asyncLog 0 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo supportVnodes 1024 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo numOfLogLines 300000000 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo logKeepDays -1 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo checkpointInterval 60 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo snodeAddress 127.0.0.1:873 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo dataDir ${TD_TESTS_OUTPUT_DIR}/data >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo logDir ${TD_TESTS_OUTPUT_DIR}/log >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
COMMAND ${CMAKE_COMMAND} -E echo logDir ${TD_TESTS_OUTPUT_DIR}/log >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo charset UTF-8 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
COMMAND ${CMAKE_COMMAND} -E echo charset UTF-8 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo monitor 0 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
COMMAND ${CMAKE_COMMAND} -E echo monitor 0 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
*
|
||||||
|
!*.c
|
||||||
|
!.gitignore
|
|
@ -0,0 +1,21 @@
|
||||||
|
// compile with
|
||||||
|
// gcc connect_example.c -o connect_example -ltaos
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ws_enable_log("debug");
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "Connected to %s successfully.\n", dsn);
|
||||||
|
|
||||||
|
/* put your code here for read and write */
|
||||||
|
|
||||||
|
// close & clean
|
||||||
|
ws_close(taos);
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||||
|
// to compile: gcc -o create_db_demo create_db_demo.c -ltaos
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
static int DemoCreateDB() {
|
||||||
|
ws_enable_log("debug");
|
||||||
|
// ANCHOR: create_db_and_table
|
||||||
|
int code = 0;
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
// connect
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create database
|
||||||
|
WS_RES *result = ws_query(taos, "CREATE DATABASE IF NOT EXISTS power");
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to create database power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(result);
|
||||||
|
fprintf(stdout, "Create database power successfully.\n");
|
||||||
|
|
||||||
|
// create table
|
||||||
|
const char *sql =
|
||||||
|
"CREATE STABLE IF NOT EXISTS power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId "
|
||||||
|
"INT, location BINARY(24))";
|
||||||
|
result = ws_query(taos, sql);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to create stable power.meters, ErrCode: 0x%x, ErrMessage: %s\n.", code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(result);
|
||||||
|
fprintf(stdout, "Create stable power.meters successfully.\n");
|
||||||
|
|
||||||
|
// close & clean
|
||||||
|
ws_close(taos);
|
||||||
|
return 0;
|
||||||
|
// ANCHOR_END: create_db_and_table
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) { return DemoCreateDB(); }
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||||
|
// to compile: gcc -o insert_data_demo insert_data_demo.c -ltaos
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
static int DemoInsertData() {
|
||||||
|
// ANCHOR: insert_data
|
||||||
|
int code = 0;
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
// connect
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert data, please make sure the database and table are already created
|
||||||
|
const char *sql =
|
||||||
|
"INSERT INTO "
|
||||||
|
"power.d1001 USING power.meters TAGS(2,'California.SanFrancisco') "
|
||||||
|
"VALUES "
|
||||||
|
"(NOW + 1a, 10.30000, 219, 0.31000) "
|
||||||
|
"(NOW + 2a, 12.60000, 218, 0.33000) "
|
||||||
|
"(NOW + 3a, 12.30000, 221, 0.31000) "
|
||||||
|
"power.d1002 USING power.meters TAGS(3, 'California.SanFrancisco') "
|
||||||
|
"VALUES "
|
||||||
|
"(NOW + 1a, 10.30000, 218, 0.25000) ";
|
||||||
|
WS_RES *result = ws_query(taos, sql);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to insert data to power.meters, sql: %s, ErrCode: 0x%x, ErrMessage: %s\n.", sql, code,
|
||||||
|
ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// you can check affectedRows here
|
||||||
|
int rows = ws_affected_rows(result);
|
||||||
|
fprintf(stdout, "Successfully inserted %d rows into power.meters.\n", rows);
|
||||||
|
|
||||||
|
// close & clean
|
||||||
|
ws_close(taos);
|
||||||
|
return 0;
|
||||||
|
// ANCHOR_END: insert_data
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) { return DemoInsertData(); }
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||||
|
// to compile: gcc -o query_data_demo query_data_demo.c -ltaos
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
static int DemoQueryData() {
|
||||||
|
// ANCHOR: query_data
|
||||||
|
int code = 0;
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
|
||||||
|
// connect
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// query data, please make sure the database and table are already created
|
||||||
|
const char *sql = "SELECT ts, current, location FROM power.meters limit 100";
|
||||||
|
WS_RES *result = ws_query(taos, sql);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to query data from power.meters, sql: %s, ErrCode: 0x%x, ErrMessage: %s\n.", sql, code,
|
||||||
|
ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WS_ROW row = NULL;
|
||||||
|
int rows = 0;
|
||||||
|
int num_fields = ws_field_count(result);
|
||||||
|
const WS_FIELD *fields = ws_fetch_fields(result);
|
||||||
|
|
||||||
|
fprintf(stdout, "query successfully, got %d fields, the sql is: %s.\n", num_fields, sql);
|
||||||
|
|
||||||
|
// fetch the records row by row
|
||||||
|
while ((row = ws_fetch_row(result))) {
|
||||||
|
// Add your data processing logic here
|
||||||
|
|
||||||
|
rows++;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "total rows: %d\n", rows);
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// close & clean
|
||||||
|
ws_close(taos);
|
||||||
|
return 0;
|
||||||
|
// ANCHOR_END: query_data
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) { return DemoQueryData(); }
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||||
|
// to compile: gcc -o sml_insert_demo sml_insert_demo.c -ltaos
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
static int DemoSmlInsert() {
|
||||||
|
// ANCHOR: schemaless
|
||||||
|
int code = 0;
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
|
||||||
|
// connect
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create database
|
||||||
|
WS_RES *result = ws_query(taos, "CREATE DATABASE IF NOT EXISTS power");
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to create database power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// use database
|
||||||
|
result = ws_query(taos, "USE power");
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to execute use power, ErrCode: 0x%x, ErrMessage: %s\n.", code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// schemaless demo data
|
||||||
|
char *line_demo =
|
||||||
|
"meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 "
|
||||||
|
"1626006833639";
|
||||||
|
char *telnet_demo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";
|
||||||
|
char *json_demo =
|
||||||
|
"{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, "
|
||||||
|
"\"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";
|
||||||
|
|
||||||
|
// influxdb line protocol
|
||||||
|
char *lines[] = {line_demo};
|
||||||
|
int totalLines = 0;
|
||||||
|
result = ws_schemaless_insert_raw(taos, line_demo, strlen(line_demo), &totalLines, WS_TSDB_SML_LINE_PROTOCOL,
|
||||||
|
WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to insert schemaless line data, data: %s, ErrCode: 0x%x, ErrMessage: %s\n.", line_demo,
|
||||||
|
code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "Insert %d rows of schemaless line data successfully.\n", totalLines);
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// opentsdb telnet protocol
|
||||||
|
totalLines = 0;
|
||||||
|
result = ws_schemaless_insert_raw(taos, telnet_demo, strlen(telnet_demo), &totalLines, WS_TSDB_SML_TELNET_PROTOCOL,
|
||||||
|
WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to insert schemaless telnet data, data: %s, ErrCode: 0x%x, ErrMessage: %s\n.", telnet_demo,
|
||||||
|
code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "Insert %d rows of schemaless telnet data successfully.\n", totalLines);
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// opentsdb json protocol
|
||||||
|
char *jsons[1] = {0};
|
||||||
|
// allocate memory for json data. can not use static memory.
|
||||||
|
totalLines = 0;
|
||||||
|
result = ws_schemaless_insert_raw(taos, json_demo, strlen(json_demo), &totalLines, WS_TSDB_SML_JSON_PROTOCOL,
|
||||||
|
WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
free(jsons[0]);
|
||||||
|
fprintf(stderr, "Failed to insert schemaless json data, Server: %s, ErrCode: 0x%x, ErrMessage: %s\n.", json_demo,
|
||||||
|
code, ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(jsons[0]);
|
||||||
|
|
||||||
|
fprintf(stdout, "Insert %d rows of schemaless json data successfully.\n", totalLines);
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// close & clean
|
||||||
|
ws_close(taos);
|
||||||
|
return 0;
|
||||||
|
// ANCHOR_END: schemaless
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) { return DemoSmlInsert(); }
|
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||||
|
// to compile: gcc -o stmt_insert_demo stmt_insert_demo.c -ltaos
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief execute sql only.
|
||||||
|
*
|
||||||
|
* @param taos
|
||||||
|
* @param sql
|
||||||
|
*/
|
||||||
|
void executeSQL(WS_TAOS *taos, const char *sql) {
|
||||||
|
WS_RES *res = ws_query(taos, sql);
|
||||||
|
int code = ws_errno(res);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "%s\n", ws_errstr(res));
|
||||||
|
ws_free_result(res);
|
||||||
|
ws_close(taos);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
ws_free_result(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief check return status and exit program when error occur.
|
||||||
|
*
|
||||||
|
* @param stmt
|
||||||
|
* @param code
|
||||||
|
* @param msg
|
||||||
|
*/
|
||||||
|
void checkErrorCode(WS_STMT *stmt, int code, const char *msg) {
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "%s. code: %d, error: %s\n", msg, code, ws_stmt_errstr(stmt));
|
||||||
|
ws_stmt_close(stmt);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_t ts;
|
||||||
|
float current;
|
||||||
|
int voltage;
|
||||||
|
float phase;
|
||||||
|
} Row;
|
||||||
|
|
||||||
|
int num_of_sub_table = 10;
|
||||||
|
int num_of_row = 10;
|
||||||
|
int total_affected = 0;
|
||||||
|
/**
|
||||||
|
* @brief insert data using stmt API
|
||||||
|
*
|
||||||
|
* @param taos
|
||||||
|
*/
|
||||||
|
void insertData(WS_TAOS *taos) {
|
||||||
|
// init
|
||||||
|
WS_STMT *stmt = ws_stmt_init(taos);
|
||||||
|
if (stmt == NULL) {
|
||||||
|
fprintf(stderr, "Failed to init ws_stmt, error: %s\n", ws_stmt_errstr(NULL));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// prepare
|
||||||
|
const char *sql = "INSERT INTO ? USING meters TAGS(?,?) VALUES (?,?,?,?)";
|
||||||
|
int code = ws_stmt_prepare(stmt, sql, 0);
|
||||||
|
checkErrorCode(stmt, code, "Failed to execute ws_stmt_prepare");
|
||||||
|
for (int i = 1; i <= num_of_sub_table; i++) {
|
||||||
|
char table_name[20];
|
||||||
|
sprintf(table_name, "d_bind_%d", i);
|
||||||
|
char location[20];
|
||||||
|
sprintf(location, "location_%d", i);
|
||||||
|
|
||||||
|
// set table name and tags
|
||||||
|
WS_MULTI_BIND tags[2];
|
||||||
|
// groupId
|
||||||
|
tags[0].buffer_type = TSDB_DATA_TYPE_INT;
|
||||||
|
tags[0].buffer_length = sizeof(int);
|
||||||
|
tags[0].length = (int32_t *)&tags[0].buffer_length;
|
||||||
|
tags[0].buffer = &i;
|
||||||
|
tags[0].is_null = NULL;
|
||||||
|
tags[0].num = 1;
|
||||||
|
// location
|
||||||
|
tags[1].buffer_type = TSDB_DATA_TYPE_BINARY;
|
||||||
|
tags[1].buffer_length = strlen(location);
|
||||||
|
tags[1].length = (int32_t *)&tags[1].buffer_length;
|
||||||
|
tags[1].buffer = location;
|
||||||
|
tags[1].is_null = NULL;
|
||||||
|
tags[1].num = 1;
|
||||||
|
code = ws_stmt_set_tbname_tags(stmt, table_name, tags, 2);
|
||||||
|
checkErrorCode(stmt, code, "Failed to set table name and tags\n");
|
||||||
|
|
||||||
|
// insert rows
|
||||||
|
WS_MULTI_BIND params[4];
|
||||||
|
// ts
|
||||||
|
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
|
||||||
|
params[0].buffer_length = sizeof(int64_t);
|
||||||
|
params[0].length = (int32_t *)¶ms[0].buffer_length;
|
||||||
|
params[0].is_null = NULL;
|
||||||
|
params[0].num = 1;
|
||||||
|
// current
|
||||||
|
params[1].buffer_type = TSDB_DATA_TYPE_FLOAT;
|
||||||
|
params[1].buffer_length = sizeof(float);
|
||||||
|
params[1].length = (int32_t *)¶ms[1].buffer_length;
|
||||||
|
params[1].is_null = NULL;
|
||||||
|
params[1].num = 1;
|
||||||
|
// voltage
|
||||||
|
params[2].buffer_type = TSDB_DATA_TYPE_INT;
|
||||||
|
params[2].buffer_length = sizeof(int);
|
||||||
|
params[2].length = (int32_t *)¶ms[2].buffer_length;
|
||||||
|
params[2].is_null = NULL;
|
||||||
|
params[2].num = 1;
|
||||||
|
// phase
|
||||||
|
params[3].buffer_type = TSDB_DATA_TYPE_FLOAT;
|
||||||
|
params[3].buffer_length = sizeof(float);
|
||||||
|
params[3].length = (int32_t *)¶ms[3].buffer_length;
|
||||||
|
params[3].is_null = NULL;
|
||||||
|
params[3].num = 1;
|
||||||
|
|
||||||
|
for (int j = 0; j < num_of_row; j++) {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
long long milliseconds = tv.tv_sec * 1000LL + tv.tv_usec / 1000; // current timestamp in milliseconds
|
||||||
|
int64_t ts = milliseconds + j;
|
||||||
|
float current = (float)rand() / RAND_MAX * 30;
|
||||||
|
int voltage = rand() % 300;
|
||||||
|
float phase = (float)rand() / RAND_MAX;
|
||||||
|
params[0].buffer = &ts;
|
||||||
|
params[1].buffer = ¤t;
|
||||||
|
params[2].buffer = &voltage;
|
||||||
|
params[3].buffer = &phase;
|
||||||
|
// bind param
|
||||||
|
code = ws_stmt_bind_param_batch(stmt, params, 4);
|
||||||
|
checkErrorCode(stmt, code, "Failed to bind param");
|
||||||
|
}
|
||||||
|
// add batch
|
||||||
|
code = ws_stmt_add_batch(stmt);
|
||||||
|
checkErrorCode(stmt, code, "Failed to add batch");
|
||||||
|
// execute batch
|
||||||
|
int affected_rows = 0;
|
||||||
|
code = ws_stmt_execute(stmt, &affected_rows);
|
||||||
|
checkErrorCode(stmt, code, "Failed to exec stmt");
|
||||||
|
// get affected rows
|
||||||
|
int affected = ws_stmt_affected_rows_once(stmt);
|
||||||
|
total_affected += affected;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "Successfully inserted %d rows to power.meters.\n", total_affected);
|
||||||
|
ws_stmt_close(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int code = 0;
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// create database and table
|
||||||
|
executeSQL(taos, "CREATE DATABASE IF NOT EXISTS power");
|
||||||
|
executeSQL(taos, "USE power");
|
||||||
|
executeSQL(taos,
|
||||||
|
"CREATE STABLE IF NOT EXISTS power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS "
|
||||||
|
"(groupId INT, location BINARY(24))");
|
||||||
|
insertData(taos);
|
||||||
|
ws_close(taos);
|
||||||
|
}
|
|
@ -0,0 +1,488 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// to compile: gcc -o tmq_demo tmq_demo.c -ltaos -lpthread
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
volatile int thread_stop = 0;
|
||||||
|
static int running = 1;
|
||||||
|
static int count = 0;
|
||||||
|
const char* topic_name = "topic_meters";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* enable_auto_commit;
|
||||||
|
const char* auto_commit_interval_ms;
|
||||||
|
const char* group_id;
|
||||||
|
const char* client_id;
|
||||||
|
const char* td_connect_host;
|
||||||
|
const char* td_connect_port;
|
||||||
|
const char* td_connect_user;
|
||||||
|
const char* td_connect_pass;
|
||||||
|
const char* auto_offset_reset;
|
||||||
|
} ConsumerConfig;
|
||||||
|
|
||||||
|
ConsumerConfig config = {.enable_auto_commit = "true",
|
||||||
|
.auto_commit_interval_ms = "1000",
|
||||||
|
.group_id = "group1",
|
||||||
|
.client_id = "client1",
|
||||||
|
.td_connect_host = "localhost",
|
||||||
|
.td_connect_port = "6030",
|
||||||
|
.td_connect_user = "root",
|
||||||
|
.td_connect_pass = "taosdata",
|
||||||
|
.auto_offset_reset = "latest"};
|
||||||
|
|
||||||
|
void* prepare_data(void* arg) {
|
||||||
|
int code = 0;
|
||||||
|
char* dsn = "ws://localhost:6041";
|
||||||
|
WS_TAOS* pConn = ws_connect(dsn);
|
||||||
|
if (pConn == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WS_RES* pRes;
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
while (!thread_stop) {
|
||||||
|
char buf[200] = {0};
|
||||||
|
i++;
|
||||||
|
snprintf(
|
||||||
|
buf, sizeof(buf),
|
||||||
|
"INSERT INTO power.d1001 USING power.meters TAGS(2,'California.SanFrancisco') VALUES (NOW + %da, 10.30000, "
|
||||||
|
"219, 0.31000)",
|
||||||
|
i);
|
||||||
|
|
||||||
|
pRes = ws_query(pConn, buf);
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to insert data to power.meters, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "Prepare data thread exit\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANCHOR: msg_process
|
||||||
|
int32_t msg_process(WS_RES* msg) {
|
||||||
|
int32_t rows = 0;
|
||||||
|
const char* topicName = ws_tmq_get_topic_name(msg);
|
||||||
|
const char* dbName = ws_tmq_get_db_name(msg);
|
||||||
|
int32_t vgroupId = ws_tmq_get_vgroup_id(msg);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// get one row data from message
|
||||||
|
WS_ROW row = ws_fetch_row(msg);
|
||||||
|
if (row == NULL) break;
|
||||||
|
|
||||||
|
// Add your data processing logic here
|
||||||
|
|
||||||
|
rows++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
// ANCHOR_END: msg_process
|
||||||
|
|
||||||
|
WS_TAOS* init_env() {
|
||||||
|
int code = 0;
|
||||||
|
char* dsn = "ws://localhost:6041";
|
||||||
|
WS_TAOS* pConn = ws_connect(dsn);
|
||||||
|
if (pConn == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WS_RES* pRes;
|
||||||
|
// drop database if exists
|
||||||
|
pRes = ws_query(pConn, "DROP TOPIC IF EXISTS topic_meters");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to drop topic_meters, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
goto END;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
|
||||||
|
pRes = ws_query(pConn, "DROP DATABASE IF EXISTS power");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to drop database power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
goto END;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
|
||||||
|
// create database
|
||||||
|
pRes = ws_query(pConn, "CREATE DATABASE power PRECISION 'ms' WAL_RETENTION_PERIOD 3600");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to create power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
goto END;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
|
||||||
|
// create super table
|
||||||
|
pRes =
|
||||||
|
ws_query(pConn,
|
||||||
|
"CREATE STABLE IF NOT EXISTS power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS "
|
||||||
|
"(groupId INT, location BINARY(24))");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to create super table meters, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
goto END;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
|
||||||
|
return pConn;
|
||||||
|
|
||||||
|
END:
|
||||||
|
ws_free_result(pRes);
|
||||||
|
ws_close(pConn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deinit_env(WS_TAOS* pConn) {
|
||||||
|
if (pConn) ws_close(pConn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t create_topic(WS_TAOS* pConn) {
|
||||||
|
WS_RES* pRes;
|
||||||
|
int code = 0;
|
||||||
|
|
||||||
|
if (!pConn) {
|
||||||
|
fprintf(stderr, "Invalid input parameter.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pRes = ws_query(pConn, "USE power");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (ws_errno(pRes) != 0) {
|
||||||
|
fprintf(stderr, "Failed to use power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
|
||||||
|
pRes = ws_query(
|
||||||
|
pConn,
|
||||||
|
"CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT ts, current, voltage, phase, groupid, location FROM meters");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to create topic topic_meters, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t drop_topic(WS_TAOS* pConn) {
|
||||||
|
WS_RES* pRes;
|
||||||
|
int code = 0;
|
||||||
|
|
||||||
|
if (!pConn) {
|
||||||
|
fprintf(stderr, "Invalid input parameter.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pRes = ws_query(pConn, "USE power");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (ws_errno(pRes) != 0) {
|
||||||
|
fprintf(stderr, "Failed to use power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
|
||||||
|
pRes = ws_query(pConn, "DROP TOPIC IF EXISTS topic_meters");
|
||||||
|
code = ws_errno(pRes);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to drop topic topic_meters, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(pRes));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ws_free_result(pRes);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmq_commit_cb_print(ws_tmq_t* tmq, int32_t code, void* param) {
|
||||||
|
count += 1;
|
||||||
|
fprintf(stdout, "tmq_commit_cb_print() code: %d, tmq: %p, param: %p, count: %d.\n", code, tmq, param, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANCHOR: create_consumer_1
|
||||||
|
ws_tmq_t* build_consumer(const ConsumerConfig* config) {
|
||||||
|
ws_tmq_conf_res_t code;
|
||||||
|
ws_tmq_t* tmq = NULL;
|
||||||
|
|
||||||
|
// create a configuration object
|
||||||
|
ws_tmq_conf_t* conf = ws_tmq_conf_new();
|
||||||
|
|
||||||
|
// set the configuration parameters
|
||||||
|
code = ws_tmq_conf_set(conf, "enable.auto.commit", config->enable_auto_commit);
|
||||||
|
if (WS_TMQ_CONF_OK != code) {
|
||||||
|
ws_tmq_conf_destroy(conf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
code = ws_tmq_conf_set(conf, "auto.commit.interval.ms", config->auto_commit_interval_ms);
|
||||||
|
if (WS_TMQ_CONF_OK != code) {
|
||||||
|
ws_tmq_conf_destroy(conf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
code = ws_tmq_conf_set(conf, "group.id", config->group_id);
|
||||||
|
if (WS_TMQ_CONF_OK != code) {
|
||||||
|
ws_tmq_conf_destroy(conf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
code = ws_tmq_conf_set(conf, "client.id", config->client_id);
|
||||||
|
if (WS_TMQ_CONF_OK != code) {
|
||||||
|
ws_tmq_conf_destroy(conf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = ws_tmq_conf_set(conf, "auto.offset.reset", config->auto_offset_reset);
|
||||||
|
if (WS_TMQ_CONF_OK != code) {
|
||||||
|
ws_tmq_conf_destroy(conf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a consumer object
|
||||||
|
tmq = ws_tmq_consumer_new(conf, "taos://localhost:6041", NULL, 0);
|
||||||
|
|
||||||
|
_end:
|
||||||
|
// destroy the configuration object
|
||||||
|
ws_tmq_conf_destroy(conf);
|
||||||
|
return tmq;
|
||||||
|
}
|
||||||
|
// ANCHOR_END: create_consumer_1
|
||||||
|
|
||||||
|
// ANCHOR: build_topic_list
|
||||||
|
// build a topic list used to subscribe
|
||||||
|
ws_tmq_list_t* build_topic_list() {
|
||||||
|
// create a empty topic list
|
||||||
|
ws_tmq_list_t* topicList = ws_tmq_list_new();
|
||||||
|
|
||||||
|
// append topic name to the list
|
||||||
|
int32_t code = ws_tmq_list_append(topicList, topic_name);
|
||||||
|
if (code) {
|
||||||
|
// if failed, destroy the list and return NULL
|
||||||
|
ws_tmq_list_destroy(topicList);
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to create topic_list, topic: %s, groupId: %s, clientId: %s, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, code, ws_tmq_errstr(NULL));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// if success, return the list
|
||||||
|
return topicList;
|
||||||
|
}
|
||||||
|
// ANCHOR_END: build_topic_list
|
||||||
|
|
||||||
|
// ANCHOR: basic_consume_loop
|
||||||
|
void basic_consume_loop(ws_tmq_t* tmq) {
|
||||||
|
int32_t totalRows = 0; // total rows consumed
|
||||||
|
int32_t msgCnt = 0; // total messages consumed
|
||||||
|
int32_t timeout = 5000; // poll timeout
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
// poll message from TDengine
|
||||||
|
WS_RES* tmqmsg = ws_tmq_consumer_poll(tmq, timeout);
|
||||||
|
if (tmqmsg) {
|
||||||
|
msgCnt++;
|
||||||
|
|
||||||
|
// Add your data processing logic here
|
||||||
|
totalRows += msg_process(tmqmsg);
|
||||||
|
|
||||||
|
// free the message
|
||||||
|
ws_free_result(tmqmsg);
|
||||||
|
}
|
||||||
|
if (msgCnt > 50) {
|
||||||
|
// consume 50 messages and break
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the result: total messages and total rows consumed
|
||||||
|
fprintf(stdout, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
|
||||||
|
}
|
||||||
|
// ANCHOR_END: basic_consume_loop
|
||||||
|
|
||||||
|
// ANCHOR: consume_repeatly
|
||||||
|
void consume_repeatly(ws_tmq_t* tmq) {
|
||||||
|
int32_t numOfAssignment = 0;
|
||||||
|
ws_tmq_topic_assignment* pAssign = NULL;
|
||||||
|
|
||||||
|
// get the topic assignment
|
||||||
|
int32_t code = ws_tmq_get_topic_assignment(tmq, topic_name, &pAssign, &numOfAssignment);
|
||||||
|
if (code != 0 || pAssign == NULL || numOfAssignment == 0) {
|
||||||
|
fprintf(stderr, "Failed to get assignment, topic: %s, groupId: %s, clientId: %s, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, code, ws_tmq_errstr(tmq));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// seek to the earliest offset
|
||||||
|
for (int32_t i = 0; i < numOfAssignment; ++i) {
|
||||||
|
ws_tmq_topic_assignment* p = &pAssign[i];
|
||||||
|
|
||||||
|
code = ws_tmq_offset_seek(tmq, topic_name, p->vgId, p->begin);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to seek offset, topic: %s, groupId: %s, clientId: %s, vgId: %d, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, p->vgId, code, ws_tmq_errstr(tmq));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (code == 0) fprintf(stdout, "Assignment seek to beginning successfully.\n");
|
||||||
|
|
||||||
|
// free the assignment array
|
||||||
|
ws_tmq_free_assignment(pAssign, numOfAssignment);
|
||||||
|
|
||||||
|
// let's consume the messages again
|
||||||
|
basic_consume_loop(tmq);
|
||||||
|
}
|
||||||
|
// ANCHOR_END: consume_repeatly
|
||||||
|
|
||||||
|
// ANCHOR: manual_commit
|
||||||
|
void manual_commit(ws_tmq_t* tmq) {
|
||||||
|
int32_t totalRows = 0; // total rows consumed
|
||||||
|
int32_t msgCnt = 0; // total messages consumed
|
||||||
|
int32_t timeout = 5000; // poll timeout
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
// poll message from TDengine
|
||||||
|
WS_RES* tmqmsg = ws_tmq_consumer_poll(tmq, timeout);
|
||||||
|
if (tmqmsg) {
|
||||||
|
msgCnt++;
|
||||||
|
// process the message
|
||||||
|
totalRows += msg_process(tmqmsg);
|
||||||
|
// commit the message
|
||||||
|
int32_t code = ws_tmq_commit_sync(tmq, tmqmsg);
|
||||||
|
if (code) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to commit offset, topic: %s, groupId: %s, clientId: %s, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, code, ws_tmq_errstr(tmq));
|
||||||
|
// free the message
|
||||||
|
ws_free_result(tmqmsg);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Commit offset manually successfully.\n");
|
||||||
|
}
|
||||||
|
// free the message
|
||||||
|
ws_free_result(tmqmsg);
|
||||||
|
}
|
||||||
|
if (msgCnt > 50) {
|
||||||
|
// consume 50 messages and break
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the result: total messages and total rows consumed
|
||||||
|
fprintf(stdout, "%d msg consumed, include %d rows.\n", msgCnt, totalRows);
|
||||||
|
}
|
||||||
|
// ANCHOR_END: manual_commit
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
int32_t code;
|
||||||
|
pthread_t thread_id;
|
||||||
|
|
||||||
|
WS_TAOS* pConn = init_env();
|
||||||
|
if (pConn == NULL) {
|
||||||
|
fprintf(stderr, "Failed to init env.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_topic(pConn) < 0) {
|
||||||
|
fprintf(stderr, "Failed to create topic.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create(&thread_id, NULL, &prepare_data, NULL)) {
|
||||||
|
fprintf(stderr, "Failed to create thread.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANCHOR: create_consumer_2
|
||||||
|
ws_tmq_t* tmq = build_consumer(&config);
|
||||||
|
if (NULL == tmq) {
|
||||||
|
fprintf(stderr, "Failed to create native consumer, host: %s, groupId: %s, , clientId: %s.\n",
|
||||||
|
config.td_connect_host, config.group_id, config.client_id);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Create consumer successfully, host: %s, groupId: %s, clientId: %s.\n", config.td_connect_host,
|
||||||
|
config.group_id, config.client_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANCHOR_END: create_consumer_2
|
||||||
|
|
||||||
|
// ANCHOR: subscribe_3
|
||||||
|
ws_tmq_list_t* topic_list = build_topic_list();
|
||||||
|
if (NULL == topic_list) {
|
||||||
|
fprintf(stderr, "Failed to create topic_list, topic: %s, groupId: %s, clientId: %s.\n", topic_name, config.group_id,
|
||||||
|
config.client_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((code = ws_tmq_subscribe(tmq, topic_list))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to subscribe topic_list, topic: %s, groupId: %s, clientId: %s, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, code, ws_tmq_errstr(tmq));
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Subscribe topics successfully.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ws_tmq_list_destroy(topic_list);
|
||||||
|
|
||||||
|
basic_consume_loop(tmq);
|
||||||
|
// ANCHOR_END: subscribe_3
|
||||||
|
|
||||||
|
consume_repeatly(tmq);
|
||||||
|
|
||||||
|
manual_commit(tmq);
|
||||||
|
|
||||||
|
// ANCHOR: unsubscribe_and_close
|
||||||
|
// unsubscribe the topic
|
||||||
|
code = ws_tmq_unsubscribe(tmq);
|
||||||
|
if (code) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to unsubscribe consumer, topic: %s, groupId: %s, clientId: %s, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, code, ws_tmq_errstr(tmq));
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Consumer unsubscribed successfully.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the consumer
|
||||||
|
code = ws_tmq_consumer_close(tmq);
|
||||||
|
if (code) {
|
||||||
|
fprintf(stderr, "Failed to close consumer, topic: %s, groupId: %s, clientId: %s, ErrCode: 0x%x, ErrMessage: %s.\n",
|
||||||
|
topic_name, config.group_id, config.client_id, code, ws_tmq_errstr(tmq));
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Consumer closed successfully.\n");
|
||||||
|
}
|
||||||
|
// ANCHOR_END: unsubscribe_and_close
|
||||||
|
|
||||||
|
thread_stop = 1;
|
||||||
|
pthread_join(thread_id, NULL);
|
||||||
|
|
||||||
|
if (drop_topic(pConn) < 0) {
|
||||||
|
fprintf(stderr, "Failed to drop topic.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit_env(pConn);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||||
|
// to compile: gcc -o with_reqid_demo with_reqid_demo.c -ltaos
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "taosws.h"
|
||||||
|
|
||||||
|
static int DemoWithReqId() {
|
||||||
|
// ANCHOR: with_reqid
|
||||||
|
int code = 0;
|
||||||
|
char *dsn = "ws://localhost:6041";
|
||||||
|
|
||||||
|
// connect
|
||||||
|
WS_TAOS *taos = ws_connect(dsn);
|
||||||
|
if (taos == NULL) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sql = "SELECT ts, current, location FROM power.meters limit 1";
|
||||||
|
// query data with reqid
|
||||||
|
long reqid = 3L;
|
||||||
|
WS_RES *result = ws_query_with_reqid(taos, sql, reqid);
|
||||||
|
code = ws_errno(result);
|
||||||
|
if (code != 0) {
|
||||||
|
fprintf(stderr, "Failed to execute sql withQID: %ld, ErrCode: 0x%x, ErrMessage: %s\n.", reqid, code,
|
||||||
|
ws_errstr(result));
|
||||||
|
ws_close(taos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WS_ROW row = NULL;
|
||||||
|
int rows = 0;
|
||||||
|
int num_fields = ws_field_count(result);
|
||||||
|
const WS_FIELD *fields = ws_fetch_fields(result);
|
||||||
|
|
||||||
|
fprintf(stdout, "query successfully, got %d fields, the sql is: %s.\n", num_fields, sql);
|
||||||
|
|
||||||
|
// fetch the records row by row
|
||||||
|
while ((row = ws_fetch_row(result))) {
|
||||||
|
// Add your data processing logic here
|
||||||
|
|
||||||
|
rows++;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "total rows: %d\n", rows);
|
||||||
|
ws_free_result(result);
|
||||||
|
|
||||||
|
// close & clean
|
||||||
|
ws_close(taos);
|
||||||
|
return 0;
|
||||||
|
// ANCHOR_END: with_reqid
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) { return DemoWithReqId(); }
|
|
@ -4,7 +4,6 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tdengine/client": "^3.0.1",
|
"@tdengine/websocket": "^3.1.0"
|
||||||
"@tdengine/rest": "^3.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ async function json_tag_example() {
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to create database example_json_tag or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to create database example_json_tag or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
if (wsSql) {
|
if (wsSql) {
|
||||||
await wsSql.close();
|
await wsSql.close();
|
||||||
|
@ -78,9 +79,10 @@ async function all_type_example() {
|
||||||
let row = wsRows.getData();
|
let row = wsRows.getData();
|
||||||
console.log(row);
|
console.log(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to create database all_type_example or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to create database all_type_example or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
if (wsSql) {
|
if (wsSql) {
|
||||||
await wsSql.close();
|
await wsSql.close();
|
||||||
|
@ -91,7 +93,7 @@ async function all_type_example() {
|
||||||
|
|
||||||
async function test() {
|
async function test() {
|
||||||
await json_tag_example()
|
await json_tag_example()
|
||||||
await all_type_example()
|
await all_type_example()
|
||||||
taos.destroy();
|
taos.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ async function json_tag_example() {
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to create database example_json_tag or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to create database example_json_tag or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err
|
||||||
} finally {
|
} finally {
|
||||||
if (wsSql) {
|
if (wsSql) {
|
||||||
await wsSql.close();
|
await wsSql.close();
|
||||||
|
@ -125,6 +126,7 @@ async function all_type_example() {
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to create database all_type_example or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to create database all_type_example or stable stb, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
if (stmt) {
|
if (stmt) {
|
||||||
await stmt.close();
|
await stmt.close();
|
||||||
|
@ -136,10 +138,7 @@ async function all_type_example() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
|
||||||
async function test() {
|
|
||||||
taos.setLevel("debug")
|
|
||||||
await json_tag_example()
|
await json_tag_example()
|
||||||
await all_type_example()
|
await all_type_example()
|
||||||
taos.destroy();
|
taos.destroy();
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
const taos = require("@tdengine/websocket");
|
|
||||||
|
|
||||||
var host = null;
|
|
||||||
for(var i = 2; i < global.process.argv.length; i++){
|
|
||||||
var key = global.process.argv[i].split("=")[0];
|
|
||||||
var value = global.process.argv[i].split("=")[1];
|
|
||||||
if("host" == key){
|
|
||||||
host = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(host == null){
|
|
||||||
console.log("Usage: node nodejsChecker.js host=<hostname> port=<port>");
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let dbData = ["{\"metric\": \"meter_current\",\"timestamp\": 1626846402,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}",
|
|
||||||
"{\"metric\": \"meter_current\",\"timestamp\": 1626846403,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1002\"}}",
|
|
||||||
"{\"metric\": \"meter_current\",\"timestamp\": 1626846404,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1003\"}}"]
|
|
||||||
|
|
||||||
async function createConnect() {
|
|
||||||
let dsn = 'ws://' + host + ':6041'
|
|
||||||
let conf = new taos.WSConfig(dsn);
|
|
||||||
conf.setUser('root');
|
|
||||||
conf.setPwd('taosdata');
|
|
||||||
conf.setDb('power');
|
|
||||||
return await taos.sqlConnect(conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function test() {
|
|
||||||
let wsSql = null;
|
|
||||||
let wsRows = null;
|
|
||||||
let reqId = 0;
|
|
||||||
try {
|
|
||||||
wsSql = await createConnect()
|
|
||||||
await wsSql.exec('CREATE DATABASE IF NOT EXISTS power KEEP 3650 DURATION 10 BUFFER 16 WAL_LEVEL 1;', reqId++);
|
|
||||||
await wsSql.schemalessInsert([dbData], taos.SchemalessProto.OpenTSDBJsonFormatProtocol, taos.Precision.SECONDS, 0);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.error(err.code, err.message);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (wsRows) {
|
|
||||||
await wsRows.close();
|
|
||||||
}
|
|
||||||
if (wsSql) {
|
|
||||||
await wsSql.close();
|
|
||||||
}
|
|
||||||
taos.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test()
|
|
|
@ -15,8 +15,8 @@ async function createConnect() {
|
||||||
return wsSql;
|
return wsSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function test() {
|
async function test() {
|
||||||
let dsn = 'ws://localhost:6041'
|
|
||||||
let wsSql = null;
|
let wsSql = null;
|
||||||
let wsRows = null;
|
let wsRows = null;
|
||||||
let ttl = 0;
|
let ttl = 0;
|
||||||
|
@ -29,6 +29,7 @@ async function test() {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(`Failed to insert data with schemaless, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to insert data with schemaless, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (wsRows) {
|
if (wsRows) {
|
||||||
|
@ -40,4 +41,5 @@ async function test() {
|
||||||
taos.destroy();
|
taos.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test()
|
test()
|
||||||
|
|
|
@ -10,11 +10,9 @@ for(var i = 2; i < global.process.argv.length; i++){
|
||||||
}
|
}
|
||||||
|
|
||||||
if(host == null){
|
if(host == null){
|
||||||
console.log("Usage: node nodejsChecker.js host=<hostname> port=<port>");
|
host = 'localhost';
|
||||||
process.exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function createConnect() {
|
async function createConnect() {
|
||||||
let dsn = 'ws://' + host + ':6041'
|
let dsn = 'ws://' + host + ':6041'
|
||||||
console.log(dsn)
|
console.log(dsn)
|
||||||
|
@ -41,7 +39,7 @@ async function test() {
|
||||||
taosResult = await wsSql.exec('USE power', reqId++);
|
taosResult = await wsSql.exec('USE power', reqId++);
|
||||||
console.log(taosResult);
|
console.log(taosResult);
|
||||||
|
|
||||||
taosResult = await wsSql.exec('CREATE STABLE IF NOT EXISTS meters (_ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);', reqId++);
|
taosResult = await wsSql.exec('CREATE STABLE IF NOT EXISTS meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);', reqId++);
|
||||||
console.log(taosResult);
|
console.log(taosResult);
|
||||||
|
|
||||||
taosResult = await wsSql.exec('DESCRIBE meters', reqId++);
|
taosResult = await wsSql.exec('DESCRIBE meters', reqId++);
|
||||||
|
@ -62,6 +60,7 @@ async function test() {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(err.code, err.message);
|
console.error(err.code, err.message);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (wsRows) {
|
if (wsRows) {
|
||||||
|
|
|
@ -41,6 +41,7 @@ async function createDbAndTable() {
|
||||||
console.log("Create stable power.meters successfully");
|
console.log("Create stable power.meters successfully");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to create database power or stable meters, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to create database power or stable meters, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
if (wsSql) {
|
if (wsSql) {
|
||||||
await wsSql.close();
|
await wsSql.close();
|
||||||
|
@ -53,21 +54,23 @@ async function createDbAndTable() {
|
||||||
// ANCHOR: insertData
|
// ANCHOR: insertData
|
||||||
async function insertData() {
|
async function insertData() {
|
||||||
let wsSql = null
|
let wsSql = null
|
||||||
|
let insertQuery = "INSERT INTO " +
|
||||||
|
"power.d1001 USING power.meters (location, groupId) TAGS('California.SanFrancisco', 2) " +
|
||||||
|
"VALUES " +
|
||||||
|
"(NOW + 1a, 10.30000, 219, 0.31000) " +
|
||||||
|
"(NOW + 2a, 12.60000, 218, 0.33000) " +
|
||||||
|
"(NOW + 3a, 12.30000, 221, 0.31000) " +
|
||||||
|
"power.d1002 USING power.meters (location, groupId) TAGS('California.SanFrancisco', 3) " +
|
||||||
|
"VALUES " +
|
||||||
|
"(NOW + 1a, 10.30000, 218, 0.25000) ";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
wsSql = await createConnect();
|
wsSql = await createConnect();
|
||||||
let insertQuery = "INSERT INTO " +
|
|
||||||
"power.d1001 USING power.meters (location, groupId) TAGS('California.SanFrancisco', 2) " +
|
|
||||||
"VALUES " +
|
|
||||||
"(NOW + 1a, 10.30000, 219, 0.31000) " +
|
|
||||||
"(NOW + 2a, 12.60000, 218, 0.33000) " +
|
|
||||||
"(NOW + 3a, 12.30000, 221, 0.31000) " +
|
|
||||||
"power.d1002 USING power.meters TAGS('California.SanFrancisco', 3) " +
|
|
||||||
"VALUES " +
|
|
||||||
"(NOW + 1a, 10.30000, 218, 0.25000) ";
|
|
||||||
taosResult = await wsSql.exec(insertQuery);
|
taosResult = await wsSql.exec(insertQuery);
|
||||||
console.log("Successfully inserted " + taosResult.getAffectRows() + " rows to power.meters.");
|
console.log("Successfully inserted " + taosResult.getAffectRows() + " rows to power.meters.");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to insert data to power.meters, sql: ${insertQuery}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to insert data to power.meters, sql: ${insertQuery}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
if (wsSql) {
|
if (wsSql) {
|
||||||
await wsSql.close();
|
await wsSql.close();
|
||||||
|
@ -91,6 +94,7 @@ async function queryData() {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(`Failed to query data from power.meters, sql: ${sql}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to query data from power.meters, sql: ${sql}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (wsRows) {
|
if (wsRows) {
|
||||||
|
@ -118,6 +122,7 @@ async function sqlWithReqid() {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(`Failed to query data from power.meters, reqId: ${reqId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to query data from power.meters, reqId: ${reqId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (wsRows) {
|
if (wsRows) {
|
||||||
|
@ -135,7 +140,7 @@ async function test() {
|
||||||
await insertData();
|
await insertData();
|
||||||
await queryData();
|
await queryData();
|
||||||
await sqlWithReqid();
|
await sqlWithReqid();
|
||||||
taos.destroy();
|
taos.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
test()
|
test()
|
||||||
|
|
|
@ -23,7 +23,7 @@ async function prepare() {
|
||||||
return wsSql
|
return wsSql
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
async function test() {
|
||||||
let stmt = null;
|
let stmt = null;
|
||||||
let connector = null;
|
let connector = null;
|
||||||
try {
|
try {
|
||||||
|
@ -60,6 +60,7 @@ async function prepare() {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(`Failed to insert to table meters using stmt, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to insert to table meters using stmt, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (stmt) {
|
if (stmt) {
|
||||||
|
@ -70,4 +71,6 @@ async function prepare() {
|
||||||
}
|
}
|
||||||
taos.destroy();
|
taos.destroy();
|
||||||
}
|
}
|
||||||
})();
|
}
|
||||||
|
|
||||||
|
test()
|
|
@ -1,58 +0,0 @@
|
||||||
const taos = require("@tdengine/websocket");
|
|
||||||
|
|
||||||
var host = null;
|
|
||||||
for(var i = 2; i < global.process.argv.length; i++){
|
|
||||||
var key = global.process.argv[i].split("=")[0];
|
|
||||||
var value = global.process.argv[i].split("=")[1];
|
|
||||||
if("host" == key){
|
|
||||||
host = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(host == null){
|
|
||||||
console.log("Usage: node nodejsChecker.js host=<hostname> port=<port>");
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let dbData = ["meters.current 1648432611249 10.3 location=California.SanFrancisco groupid=2",
|
|
||||||
"meters.current 1648432611250 12.6 location=California.SanFrancisco groupid=2",
|
|
||||||
"meters.current 1648432611249 10.8 location=California.LosAngeles groupid=3",
|
|
||||||
"meters.current 1648432611250 11.3 location=California.LosAngeles groupid=3",
|
|
||||||
"meters.voltage 1648432611249 219 location=California.SanFrancisco groupid=2",
|
|
||||||
"meters.voltage 1648432611250 218 location=California.SanFrancisco groupid=2",
|
|
||||||
"meters.voltage 1648432611249 221 location=California.LosAngeles groupid=3",
|
|
||||||
"meters.voltage 1648432611250 217 location=California.LosAngeles groupid=3",];
|
|
||||||
|
|
||||||
async function createConnect() {
|
|
||||||
let dsn = 'ws://' + host + ':6041'
|
|
||||||
let conf = new taos.WSConfig(dsn);
|
|
||||||
conf.setUser('root');
|
|
||||||
conf.setPwd('taosdata');
|
|
||||||
|
|
||||||
return await taos.sqlConnect(conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function test() {
|
|
||||||
let wsSql = null;
|
|
||||||
let wsRows = null;
|
|
||||||
let reqId = 0;
|
|
||||||
try {
|
|
||||||
wsSql = await createConnect()
|
|
||||||
await wsSql.exec('create database if not exists power KEEP 3650 DURATION 10 BUFFER 16 WAL_LEVEL 1;', reqId++);
|
|
||||||
await wsSql.exec('use power', reqId++);
|
|
||||||
await wsSql.schemalessInsert(dbData, taos.SchemalessProto.OpenTSDBTelnetLineProtocol, taos.Precision.MILLI_SECONDS, 0);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.error(err.code, err.message);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (wsRows) {
|
|
||||||
await wsRows.close();
|
|
||||||
}
|
|
||||||
if (wsSql) {
|
|
||||||
await wsSql.close();
|
|
||||||
}
|
|
||||||
taos.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test()
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
const { sleep } = require("@tdengine/websocket");
|
||||||
const taos = require("@tdengine/websocket");
|
const taos = require("@tdengine/websocket");
|
||||||
|
|
||||||
// ANCHOR: create_consumer
|
// ANCHOR: create_consumer
|
||||||
|
@ -49,12 +50,20 @@ async function prepare() {
|
||||||
|
|
||||||
let createTopic = `CREATE TOPIC IF NOT EXISTS ${topics[0]} AS SELECT * FROM ${db}.${stable}`;
|
let createTopic = `CREATE TOPIC IF NOT EXISTS ${topics[0]} AS SELECT * FROM ${db}.${stable}`;
|
||||||
await wsSql.exec(createTopic);
|
await wsSql.exec(createTopic);
|
||||||
|
await wsSql.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function insert() {
|
||||||
for (let i = 0; i < 10; i++) {
|
let conf = new taos.WSConfig('ws://localhost:6041');
|
||||||
|
conf.setUser('root');
|
||||||
|
conf.setPwd('taosdata');
|
||||||
|
conf.setDb('power');
|
||||||
|
let wsSql = await taos.sqlConnect(conf);
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
await wsSql.exec(`INSERT INTO d1001 USING ${stable} (location, groupId) TAGS ("California.SanFrancisco", 3) VALUES (NOW, ${10 + i}, ${200 + i}, ${0.32 + i})`);
|
await wsSql.exec(`INSERT INTO d1001 USING ${stable} (location, groupId) TAGS ("California.SanFrancisco", 3) VALUES (NOW, ${10 + i}, ${200 + i}, ${0.32 + i})`);
|
||||||
|
await sleep(100);
|
||||||
}
|
}
|
||||||
wsSql.close();
|
await wsSql.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function subscribe(consumer) {
|
async function subscribe(consumer) {
|
||||||
|
@ -82,13 +91,17 @@ async function test() {
|
||||||
let consumer = null;
|
let consumer = null;
|
||||||
try {
|
try {
|
||||||
await prepare();
|
await prepare();
|
||||||
consumer = await createConsumer()
|
consumer = await createConsumer();
|
||||||
await subscribe(consumer)
|
const allPromises = [];
|
||||||
|
allPromises.push(subscribe(consumer));
|
||||||
|
allPromises.push(insert());
|
||||||
|
await Promise.all(allPromises);
|
||||||
await consumer.unsubscribe();
|
await consumer.unsubscribe();
|
||||||
console.log("Consumer unsubscribed successfully.");
|
console.log("Consumer unsubscribed successfully.");
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(`Failed to unsubscribe consumer, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to unsubscribe consumer, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (consumer) {
|
if (consumer) {
|
||||||
|
|
|
@ -1,41 +1,45 @@
|
||||||
|
const { sleep } = require("@tdengine/websocket");
|
||||||
const taos = require("@tdengine/websocket");
|
const taos = require("@tdengine/websocket");
|
||||||
|
|
||||||
const db = 'power';
|
const db = 'power';
|
||||||
const stable = 'meters';
|
const stable = 'meters';
|
||||||
|
const url = 'ws://localhost:6041';
|
||||||
const topic = 'topic_meters'
|
const topic = 'topic_meters'
|
||||||
const topics = [topic];
|
const topics = [topic];
|
||||||
const groupId = "group1";
|
const groupId = "group1";
|
||||||
const clientId = "client1";
|
const clientId = "client1";
|
||||||
|
|
||||||
|
|
||||||
// ANCHOR: create_consumer
|
|
||||||
async function createConsumer() {
|
async function createConsumer() {
|
||||||
|
|
||||||
|
let groupId = "group1";
|
||||||
|
let clientId = "client1";
|
||||||
let configMap = new Map([
|
let configMap = new Map([
|
||||||
[taos.TMQConstants.GROUP_ID, "group1"],
|
[taos.TMQConstants.GROUP_ID, groupId],
|
||||||
[taos.TMQConstants.CLIENT_ID, 'client1'],
|
[taos.TMQConstants.CLIENT_ID, clientId],
|
||||||
[taos.TMQConstants.CONNECT_USER, "root"],
|
[taos.TMQConstants.CONNECT_USER, "root"],
|
||||||
[taos.TMQConstants.CONNECT_PASS, "taosdata"],
|
[taos.TMQConstants.CONNECT_PASS, "taosdata"],
|
||||||
[taos.TMQConstants.AUTO_OFFSET_RESET, "latest"],
|
[taos.TMQConstants.AUTO_OFFSET_RESET, "latest"],
|
||||||
[taos.TMQConstants.WS_URL, 'ws://localhost:6041'],
|
[taos.TMQConstants.WS_URL, url],
|
||||||
[taos.TMQConstants.ENABLE_AUTO_COMMIT, 'true'],
|
[taos.TMQConstants.ENABLE_AUTO_COMMIT, 'true'],
|
||||||
[taos.TMQConstants.AUTO_COMMIT_INTERVAL_MS, '1000']
|
[taos.TMQConstants.AUTO_COMMIT_INTERVAL_MS, '1000']
|
||||||
]);
|
]);
|
||||||
try {
|
try {
|
||||||
return await taos.tmqConnect(configMap);
|
conn = await taos.tmqConnect(configMap);
|
||||||
|
console.log(`Create consumer successfully, host: ${url}, groupId: ${groupId}, clientId: ${clientId}`)
|
||||||
|
return conn;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(`Failed to create websocket consumer, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// ANCHOR_END: create_consumer
|
|
||||||
|
|
||||||
async function prepare() {
|
async function prepare() {
|
||||||
let conf = new taos.WSConfig('ws://localhost:6041');
|
let conf = new taos.WSConfig('ws://192.168.1.98:6041');
|
||||||
conf.setUser('root');
|
conf.setUser('root');
|
||||||
conf.setPwd('taosdata');
|
conf.setPwd('taosdata');
|
||||||
conf.setDb('power');
|
conf.setDb('power');
|
||||||
const createDB = `CREATE DATABASE IF NOT EXISTS ${db} KEEP 3650 DURATION 10 BUFFER 16 WAL_LEVEL 1;`;
|
const createDB = `CREATE DATABASE IF NOT EXISTS ${db}`;
|
||||||
const createStable = `CREATE STABLE IF NOT EXISTS ${db}.${stable} (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);`;
|
const createStable = `CREATE STABLE IF NOT EXISTS ${db}.${stable} (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);`;
|
||||||
|
|
||||||
let wsSql = await taos.sqlConnect(conf);
|
let wsSql = await taos.sqlConnect(conf);
|
||||||
|
@ -44,58 +48,63 @@ async function prepare() {
|
||||||
|
|
||||||
let createTopic = `CREATE TOPIC IF NOT EXISTS ${topics[0]} AS SELECT * FROM ${db}.${stable}`;
|
let createTopic = `CREATE TOPIC IF NOT EXISTS ${topics[0]} AS SELECT * FROM ${db}.${stable}`;
|
||||||
await wsSql.exec(createTopic);
|
await wsSql.exec(createTopic);
|
||||||
|
await wsSql.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function insert() {
|
||||||
for (let i = 0; i < 10; i++) {
|
let conf = new taos.WSConfig('ws://localhost:6041');
|
||||||
|
conf.setUser('root');
|
||||||
|
conf.setPwd('taosdata');
|
||||||
|
conf.setDb('power');
|
||||||
|
let wsSql = await taos.sqlConnect(conf);
|
||||||
|
for (let i = 0; i < 1; i++) {
|
||||||
await wsSql.exec(`INSERT INTO d1001 USING ${stable} (location, groupId) TAGS ("California.SanFrancisco", 3) VALUES (NOW, ${10 + i}, ${200 + i}, ${0.32 + i})`);
|
await wsSql.exec(`INSERT INTO d1001 USING ${stable} (location, groupId) TAGS ("California.SanFrancisco", 3) VALUES (NOW, ${10 + i}, ${200 + i}, ${0.32 + i})`);
|
||||||
}
|
}
|
||||||
await wsSql.close();
|
await wsSql.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANCHOR: subscribe
|
// ANCHOR: offset
|
||||||
async function subscribe(consumer) {
|
async function subscribe(consumer) {
|
||||||
try {
|
try {
|
||||||
await consumer.subscribe(['topic_meters']);
|
|
||||||
for (let i = 0; i < 50; i++) {
|
|
||||||
let res = await consumer.poll(100);
|
|
||||||
for (let [key, value] of res) {
|
|
||||||
// Add your data processing logic here
|
|
||||||
console.log(`data: ${key} ${value}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`Failed to poll data, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// ANCHOR_END: subscribe
|
|
||||||
|
|
||||||
// ANCHOR: offset
|
|
||||||
async function test() {
|
|
||||||
let consumer = null;
|
|
||||||
try {
|
|
||||||
await prepare();
|
|
||||||
let consumer = await createConsumer()
|
|
||||||
await consumer.subscribe(['topic_meters']);
|
await consumer.subscribe(['topic_meters']);
|
||||||
let res = new Map();
|
let res = new Map();
|
||||||
while (res.size == 0) {
|
while (res.size == 0) {
|
||||||
res = await consumer.poll(100);
|
res = await consumer.poll(100);
|
||||||
|
await consumer.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
let assignment = await consumer.assignment();
|
let assignment = await consumer.assignment();
|
||||||
await consumer.seekToBeginning(assignment);
|
await consumer.seekToBeginning(assignment);
|
||||||
console.log("Assignment seek to beginning successfully");
|
console.log("Assignment seek to beginning successfully");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Failed to seek offset, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ANCHOR_END: offset
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
let consumer = null;
|
||||||
|
try {
|
||||||
|
await prepare();
|
||||||
|
consumer = await createConsumer();
|
||||||
|
const allPromises = [];
|
||||||
|
allPromises.push(subscribe(consumer));
|
||||||
|
allPromises.push(insert());
|
||||||
|
await Promise.all(allPromises);
|
||||||
|
await consumer.unsubscribe();
|
||||||
|
console.log("Consumer unsubscribed successfully.");
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(`Failed to seek offset, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
console.error(`Failed to consumer, topic: ${topic}, groupId: ${groupId}, clientId: ${clientId}, ErrCode: ${err.code}, ErrMessage: ${err.message}`);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (consumer) {
|
if (consumer) {
|
||||||
await consumer.close();
|
await consumer.close();
|
||||||
|
console.log("Consumer closed successfully.");
|
||||||
}
|
}
|
||||||
taos.destroy();
|
taos.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ANCHOR_END: offset
|
|
||||||
test()
|
test()
|
||||||
|
|
|
@ -15,6 +15,7 @@ def create_connection():
|
||||||
print(f"Connected to {host}:{port} successfully.");
|
print(f"Connected to {host}:{port} successfully.");
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to connect to {host}:{port} , ErrMessage:{err}")
|
print(f"Failed to connect to {host}:{port} , ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -15,7 +15,7 @@ def create_connection():
|
||||||
print(f"Connected to {host}:{port} successfully.");
|
print(f"Connected to {host}:{port} successfully.");
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to connect to {host}:{port} , ErrMessage:{err}")
|
print(f"Failed to connect to {host}:{port} , ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
return conn
|
return conn
|
||||||
# ANCHOR_END: connect
|
# ANCHOR_END: connect
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ def create_db_table(conn):
|
||||||
conn.execute("CREATE TABLE IF NOT EXISTS `d0` USING `meters` (groupId, location) TAGS(0, 'Los Angles')")
|
conn.execute("CREATE TABLE IF NOT EXISTS `d0` USING `meters` (groupId, location) TAGS(0, 'Los Angles')")
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f'Exception {err}')
|
print(f'Exception {err}')
|
||||||
|
raise err
|
||||||
# ANCHOR_END: create_db
|
# ANCHOR_END: create_db
|
||||||
|
|
||||||
def insert(conn):
|
def insert(conn):
|
||||||
|
@ -42,9 +43,10 @@ def insert(conn):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
inserted = conn.execute(sql)
|
inserted = conn.execute(sql)
|
||||||
assert inserted == 8
|
assert inserted == 4
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f'Exception111 {err}')
|
print(f'Exception111 {err}')
|
||||||
|
raise err
|
||||||
# ANCHOR_END: insert
|
# ANCHOR_END: insert
|
||||||
|
|
||||||
def query(conn):
|
def query(conn):
|
||||||
|
@ -58,6 +60,7 @@ def query(conn):
|
||||||
print(row)
|
print(row)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f'Exception {err}')
|
print(f'Exception {err}')
|
||||||
|
raise err
|
||||||
# ANCHOR_END: query
|
# ANCHOR_END: query
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -21,6 +21,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to create database power or stable meters, ErrMessage:{err}")
|
print(f"Failed to create database power or stable meters, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -20,6 +20,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to create database power or stable meters, ErrMessage:{err}")
|
print(f"Failed to create database power or stable meters, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -21,6 +21,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to create database power or stable meters, ErrMessage:{err}")
|
print(f"Failed to create database power or stable meters, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -22,6 +22,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to insert data to power.meters, sql: {sql}, ErrMessage: {err}.")
|
print(f"Failed to insert data to power.meters, sql: {sql}, ErrMessage: {err}.")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -21,6 +21,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to insert data to power.meters, sql:{sql}, ErrMessage:{err}.")
|
print(f"Failed to insert data to power.meters, sql:{sql}, ErrMessage:{err}.")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -22,6 +22,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to insert data to power.meters, sql: {sql}, ErrMessage: {err}.")
|
print(f"Failed to insert data to power.meters, sql: {sql}, ErrMessage: {err}.")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -16,6 +16,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to query data from power.meters, sql: {sql}, ErrMessage:{err}")
|
print(f"Failed to query data from power.meters, sql: {sql}, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -15,3 +15,4 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to query data from power.meters, sql: {sql}, ErrMessage:{err}")
|
print(f"Failed to query data from power.meters, sql: {sql}, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
|
|
|
@ -15,6 +15,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to query data from power.meters, sql: {sql}, ErrMessage:{err}")
|
print(f"Failed to query data from power.meters, sql: {sql}, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -18,7 +18,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to execute sql with reqId:{reqId}, ErrMessage:{err}")
|
print(f"Failed to execute sql with reqId:{reqId}, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -16,3 +16,4 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to execute sql with reqId:{reqId}, ErrMessage:{err}")
|
print(f"Failed to execute sql with reqId:{reqId}, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
|
|
|
@ -19,6 +19,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to execute sql with reqId:{reqId}, ErrMessage:{err}")
|
print(f"Failed to execute sql with reqId:{reqId}, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -35,6 +35,7 @@ try:
|
||||||
print("Inserted data with schemaless successfully.");
|
print("Inserted data with schemaless successfully.");
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to insert data with schemaless, ErrMessage:{err}")
|
print(f"Failed to insert data with schemaless, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -75,8 +75,6 @@ def schemaless_insert():
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
prepare()
|
||||||
prepare()
|
schemaless_insert()
|
||||||
schemaless_insert()
|
|
||||||
except Exception as err:
|
|
||||||
print(f"Failed to insert data with schemaless, err:{err}")
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to insert to table meters using stmt, ErrMessage:{err}")
|
print(f"Failed to insert to table meters using stmt, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if stmt:
|
if stmt:
|
||||||
stmt.close()
|
stmt.close()
|
||||||
|
|
|
@ -62,6 +62,7 @@ try:
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to insert to table meters using stmt, ErrMessage:{err}")
|
print(f"Failed to insert to table meters using stmt, ErrMessage:{err}")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if stmt:
|
if stmt:
|
||||||
stmt.close()
|
stmt.close()
|
||||||
|
|
|
@ -152,6 +152,7 @@ def unsubscribe(consumer):
|
||||||
print("Consumer unsubscribed successfully.");
|
print("Consumer unsubscribed successfully.");
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to unsubscribe consumer. topic: {topic}, groupId: {groupId}, clientId: {clientId}, ErrMessage:{err}.")
|
print(f"Failed to unsubscribe consumer. topic: {topic}, groupId: {groupId}, clientId: {clientId}, ErrMessage:{err}.")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if consumer:
|
if consumer:
|
||||||
consumer.close()
|
consumer.close()
|
||||||
|
@ -166,7 +167,6 @@ if __name__ == "__main__":
|
||||||
subscribe(consumer)
|
subscribe(consumer)
|
||||||
seek_offset(consumer)
|
seek_offset(consumer)
|
||||||
commit_offset(consumer)
|
commit_offset(consumer)
|
||||||
except Exception as err:
|
|
||||||
print(f"Failed to execute consumer example, topic: {topic}, groupId: {groupId}, clientId: {clientId}, ErrMessage:{err}.")
|
|
||||||
finally:
|
finally:
|
||||||
unsubscribe(consumer);
|
if consumer:
|
||||||
|
unsubscribe(consumer);
|
||||||
|
|
|
@ -31,7 +31,7 @@ def prepareMeta():
|
||||||
|
|
||||||
# create super table
|
# create super table
|
||||||
rowsAffected = conn.execute(
|
rowsAffected = conn.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) TAGS (`groupid` INT, `location` BINARY(16))"
|
"CREATE TABLE IF NOT EXISTS `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) TAGS (`groupid` INT, `location` BINARY(64))"
|
||||||
)
|
)
|
||||||
assert rowsAffected == 0
|
assert rowsAffected == 0
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@ def unsubscribe(consumer):
|
||||||
print("Consumer unsubscribed successfully.");
|
print("Consumer unsubscribed successfully.");
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(f"Failed to unsubscribe consumer. topic: {topic}, groupId: {groupId}, clientId: {clientId}, ErrMessage:{err}.")
|
print(f"Failed to unsubscribe consumer. topic: {topic}, groupId: {groupId}, clientId: {clientId}, ErrMessage:{err}.")
|
||||||
|
raise err
|
||||||
finally:
|
finally:
|
||||||
if consumer:
|
if consumer:
|
||||||
consumer.close()
|
consumer.close()
|
||||||
|
@ -170,7 +171,6 @@ if __name__ == "__main__":
|
||||||
subscribe(consumer)
|
subscribe(consumer)
|
||||||
seek_offset(consumer)
|
seek_offset(consumer)
|
||||||
commit_offset(consumer)
|
commit_offset(consumer)
|
||||||
except Exception as err:
|
|
||||||
print(f"Failed to execute consumer example, topic: {topic}, groupId: {groupId}, clientId: {clientId}, ErrMessage:{err}.")
|
|
||||||
finally:
|
finally:
|
||||||
unsubscribe(consumer)
|
if consumer:
|
||||||
|
unsubscribe(consumer)
|
||||||
|
|
|
@ -83,7 +83,6 @@ async fn main() -> anyhow::Result<()> {
|
||||||
eprintln!("Failed to execute insert: {:?}", e);
|
eprintln!("Failed to execute insert: {:?}", e);
|
||||||
}
|
}
|
||||||
tokio::time::sleep(Duration::from_millis(10)).await;
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
||||||
println!("Succed to execute insert 1 row");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -181,7 +181,7 @@ INTERVAL(interval_val [, interval_offset])
|
||||||
- FILL:用于指定窗口区间数据缺失的情况下,数据的填充模式。
|
- FILL:用于指定窗口区间数据缺失的情况下,数据的填充模式。
|
||||||
|
|
||||||
对于时间窗口,interval_val 和 sliding_val 都表示时间段, 语法上支持三种方式。例如:
|
对于时间窗口,interval_val 和 sliding_val 都表示时间段, 语法上支持三种方式。例如:
|
||||||
1. INTERVAL(1s, 500a) SLIDING(1s),带时间单位的形式,其中的时间单位是单字符表示, 分别为: a (毫秒), b (纳秒), d (天), h (小时), m (分钟), n (月), s (秒), u (微妙), w (周), y (年);
|
1. INTERVAL(1s, 500a) SLIDING(1s),带时间单位的形式,其中的时间单位是单字符表示, 分别为: a (毫秒), b (纳秒), d (天), h (小时), m (分钟), n (月), s (秒), u (微秒), w (周), y (年);
|
||||||
2. INTERVAL(1000, 500) SLIDING(1000),不带时间单位的形式,将使用查询库的时间精度作为默认时间单位,当存在多个库时默认采用精度更高的库;
|
2. INTERVAL(1000, 500) SLIDING(1000),不带时间单位的形式,将使用查询库的时间精度作为默认时间单位,当存在多个库时默认采用精度更高的库;
|
||||||
3. INTERVAL('1s', '500a') SLIDING('1s'),带时间单位的字符串形式,字符串内部不能有任何空格等其它字符。
|
3. INTERVAL('1s', '500a') SLIDING('1s'),带时间单位的字符串形式,字符串内部不能有任何空格等其它字符。
|
||||||
|
|
||||||
|
|
|
@ -208,3 +208,15 @@ CSV 文件中的每个 Row 配置一个 OPC 数据点位。Row 的规则如下
|
||||||
### 8. 创建完成
|
### 8. 创建完成
|
||||||
|
|
||||||
点击 **提交** 按钮,完成创建 OPC UA 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
点击 **提交** 按钮,完成创建 OPC UA 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
||||||
|
|
||||||
|
## 增加数据点位
|
||||||
|
|
||||||
|
在任务运行中,点击 **编辑**,点击 **增加数据点位** 按钮,追加数据点位到 CSV 文件中。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在弹出的表单中,填写数据点位的信息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击 **确定** 按钮,完成数据点位的追加。
|
|
@ -182,3 +182,15 @@ CSV 文件中的每个 Row 配置一个 OPC 数据点位。Row 的规则如下
|
||||||
### 7. 创建完成
|
### 7. 创建完成
|
||||||
|
|
||||||
点击 **提交** 按钮,完成创建 OPC DA 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
点击 **提交** 按钮,完成创建 OPC DA 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
||||||
|
|
||||||
|
## 增加数据点位
|
||||||
|
|
||||||
|
在任务运行中,点击 **编辑**,点击 **增加数据点位** 按钮,追加数据点位到 CSV 文件中。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在弹出的表单中,填写数据点位的信息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击 **确定** 按钮,完成数据点位的追加。
|
|
@ -44,8 +44,50 @@ TDengine 可以高效地从 Kafka 读取数据并将其写入 TDengine,以实
|
||||||
|
|
||||||
如果服务端开启了 SASL 认证机制,此处需要启用 SASL 并配置相关内容,目前支持 PLAIN/SCRAM-SHA-256/GSSAPI 三种认证机制,请按实际情况进行选择。
|
如果服务端开启了 SASL 认证机制,此处需要启用 SASL 并配置相关内容,目前支持 PLAIN/SCRAM-SHA-256/GSSAPI 三种认证机制,请按实际情况进行选择。
|
||||||
|
|
||||||
|
#### 4.1. PLAIN 认证
|
||||||
|
|
||||||
|
选择 `PLAIN` 认证机制,输入用户名和密码:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 4.1. SCRAM(SCRAM-SHA-256) 认证
|
||||||
|
|
||||||
|
选择 `SCRAM-SHA-256` 认证机制,输入用户名和密码:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### 4.3. GSSAPI 认证
|
||||||
|
|
||||||
|
选择 `GSSAPI` ,将通过 [RDkafka 客户端](https://github.com/confluentinc/librdkafka) 调用 GSSAPI 应用 Kerberos 认证机制:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
需要输入的信息有:
|
||||||
|
|
||||||
|
- Kerberos 服务名,一般是 `kafka`;
|
||||||
|
- Kerberos 认证主体,即认证用户名,例如 `kafkaclient`;
|
||||||
|
- Kerberos 初始化命令(可选,一般不用填写);
|
||||||
|
- Kerberos 密钥表,需提供文件并上传;
|
||||||
|
|
||||||
|
以上信息均需由 Kafka 服务管理者提供。
|
||||||
|
|
||||||
|
除此之外,在服务器上需要配置 [Kerberos](https://web.mit.edu/kerberos/) 认证服务。在 Ubuntu 下使用 `apt install krb5-user` ;在 CentOS 下,使用 `yum install krb5-workstation`;即可。
|
||||||
|
|
||||||
|
配置完成后,可以使用 [kcat](https://github.com/edenhill/kcat) 工具进行 Kafka 主题消费验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kcat <topic> \
|
||||||
|
-b <kafka-server:port> \
|
||||||
|
-G kcat \
|
||||||
|
-X security.protocol=SASL_PLAINTEXT \
|
||||||
|
-X sasl.mechanism=GSSAPI \
|
||||||
|
-X sasl.kerberos.keytab=</path/to/kafkaclient.keytab> \
|
||||||
|
-X sasl.kerberos.principal=<kafkaclient> \
|
||||||
|
-X sasl.kerberos.service.name=kafka
|
||||||
|
```
|
||||||
|
|
||||||
|
如果出现错误:“Server xxxx not found in kerberos database”,则需要配置 Kafka 节点对应的域名并在 Kerberos 客户端配置文件 `/etc/krb5.conf` 中配置反向域名解析 `rdns = true`。
|
||||||
|
|
||||||
### 5. 配置 SSL 证书
|
### 5. 配置 SSL 证书
|
||||||
|
|
||||||
如果服务端开启了 SSL 加密认证,此处需要启用 SSL 并配置相关内容。
|
如果服务端开启了 SSL 加密认证,此处需要启用 SSL 并配置相关内容。
|
||||||
|
@ -160,4 +202,4 @@ json 数据支持 JSONObject 或者 JSONArray,使用 json 解析器可以解
|
||||||
|
|
||||||
### 9. 创建完成
|
### 9. 创建完成
|
||||||
|
|
||||||
点击 **提交** 按钮,完成创建 Kafka 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
点击 **提交** 按钮,完成创建 Kafka 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
After Width: | Height: | Size: 175 KiB |
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
|
@ -387,7 +387,19 @@ DSN 的详细说明和如何使用详见 [连接功能](../../reference/connecto
|
||||||
- `reconnectIntervalMs`:重连间隔毫秒时间,默认为 2000。
|
- `reconnectIntervalMs`:重连间隔毫秒时间,默认为 2000。
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数据库的连接。其参数详细说明如下:
|
**Websocket 连接**
|
||||||
|
C/C++ 语言连接器 Websocket 连接方式使用 `ws_connect()` 函数用于建立与 TDengine 数据库的连接。其参数为 DSN 描述字符串,其基本结构如下:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<driver>[+<protocol>]://[[<username>:<password>@]<host>:<port>][/<database>][?<p1>=<v1>[&<p2>=<v2>]]
|
||||||
|
|------|------------|---|-----------|-----------|------|------|------------|-----------------------|
|
||||||
|
|driver| protocol | | username | password | host | port | database | params |
|
||||||
|
```
|
||||||
|
|
||||||
|
DSN 的详细说明和如何使用详见 [连接功能](../../reference/connector/cpp/#dsn)
|
||||||
|
|
||||||
|
**原生连接**
|
||||||
|
C/C++ 语言连接器原生连接方式使用 `taos_connect()` 函数用于建立与 TDengine 数据库的连接。其参数详细说明如下:
|
||||||
|
|
||||||
- `host`:要连接的数据库服务器的主机名或IP地址。如果是本地数据库,可以使用 `"localhost"`。
|
- `host`:要连接的数据库服务器的主机名或IP地址。如果是本地数据库,可以使用 `"localhost"`。
|
||||||
- `user`:用于登录数据库的用户名。
|
- `user`:用于登录数据库的用户名。
|
||||||
|
@ -440,7 +452,10 @@ C/C++ 语言连接器使用 `taos_connect()` 函数用于建立与 TDengine 数
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/connect_example.c}}
|
||||||
|
```
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
|
|
@ -68,9 +68,15 @@ REST API:直接调用 `taosadapter` 提供的 REST API 接口,进行数据
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
```c
|
|
||||||
|
```c title="Websocket 连接"
|
||||||
|
{{#include docs/examples/c-ws/create_db_demo.c:create_db_and_table}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c title="原生连接"
|
||||||
{{#include docs/examples/c/create_db_demo.c:create_db_and_table}}
|
{{#include docs/examples/c/create_db_demo.c:create_db_and_table}}
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
|
|
||||||
|
@ -144,7 +150,12 @@ NOW 为系统内部函数,默认为客户端所在计算机当前时间。 NOW
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
```c
|
|
||||||
|
```c title="Websocket 连接"
|
||||||
|
{{#include docs/examples/c-ws/insert_data_demo.c:insert_data}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c title="原生连接"
|
||||||
{{#include docs/examples/c/insert_data_demo.c:insert_data}}
|
{{#include docs/examples/c/insert_data_demo.c:insert_data}}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -218,7 +229,12 @@ rust 连接器还支持使用 **serde** 进行反序列化行为结构体的结
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
```c
|
|
||||||
|
```c title="Websocket 连接"
|
||||||
|
{{#include docs/examples/c-ws/query_data_demo.c:query_data}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c title="原生连接"
|
||||||
{{#include docs/examples/c/query_data_demo.c:query_data}}
|
{{#include docs/examples/c/query_data_demo.c:query_data}}
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
@ -293,9 +309,15 @@ reqId 可用于请求链路追踪,reqId 就像分布式系统中的 traceId
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
```c
|
|
||||||
|
```c "Websocket 连接"
|
||||||
|
{{#include docs/examples/c-ws/with_reqid_demo.c:with_reqid}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c "原生连接"
|
||||||
{{#include docs/examples/c/with_reqid_demo.c:with_reqid}}
|
{{#include docs/examples/c/with_reqid_demo.c:with_reqid}}
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,10 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
|
||||||
|
```c
|
||||||
|
{{#include docs/examples/c-ws/sml_insert_demo.c:schemaless}}
|
||||||
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
|
|
@ -64,7 +64,9 @@ import TabItem from "@theme/TabItem";
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/stmt_insert_demo.c}}
|
||||||
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
|
|
@ -28,21 +28,21 @@ TDengine 消费者的概念跟 Kafka 类似,消费者通过订阅主题来接
|
||||||
### 创建参数
|
### 创建参数
|
||||||
创建消费者的参数较多,非常灵活的支持了各种连接类型、 Offset 提交方式、压缩、重连、反序列化等特性。各语言连接器都适用的通用基础配置项如下表所示:
|
创建消费者的参数较多,非常灵活的支持了各种连接类型、 Offset 提交方式、压缩、重连、反序列化等特性。各语言连接器都适用的通用基础配置项如下表所示:
|
||||||
|
|
||||||
| 参数名称 | 类型 | 参数说明 | 备注 |
|
| 参数名称 | 类型 | 参数说明 | 备注 |
|
||||||
| :-----------------------: | :-----: | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| :-----------------------: | :-----: | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `td.connect.ip` | string | 服务端的 IP 地址 | |
|
| `td.connect.ip` | string | 服务端的 IP 地址 | |
|
||||||
| `td.connect.user` | string | 用户名 | |
|
| `td.connect.user` | string | 用户名 | |
|
||||||
| `td.connect.pass` | string | 密码 | |
|
| `td.connect.pass` | string | 密码 | |
|
||||||
| `td.connect.port` | integer | 服务端的端口号 | |
|
| `td.connect.port` | integer | 服务端的端口号 | |
|
||||||
| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | <br />**必填项**。最大长度:192。<br />每个topic最多可建立 100 个 consumer group |
|
| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | <br />**必填项**。最大长度:192。<br />每个topic最多可建立 100 个 consumer group |
|
||||||
| `client.id` | string | 客户端 ID | 最大长度:192 |
|
| `client.id` | string | 客户端 ID | 最大长度:192 |
|
||||||
| `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`: default(version < 3.2.0.0);从头开始订阅; <br/>`latest`: default(version >= 3.2.0.0);仅从最新数据开始订阅; <br/>`none`: 没有提交的 offset 无法订阅 |
|
| `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`: default(version < 3.2.0.0);从头开始订阅; <br/>`latest`: default(version >= 3.2.0.0);仅从最新数据开始订阅; <br/>`none`: 没有提交的 offset 无法订阅 |
|
||||||
| `enable.auto.commit` | boolean | 是否启用消费位点自动提交,true: 自动提交,客户端应用无需commit;false:客户端应用需要自行commit | 默认值为 true |
|
| `enable.auto.commit` | boolean | 是否启用消费位点自动提交,true: 自动提交,客户端应用无需commit;false:客户端应用需要自行commit | 默认值为 true |
|
||||||
| `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 |
|
| `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 |
|
||||||
| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句)(从3.2.0.0版本该参数废弃,恒为true) | 默认关闭 |
|
| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句)(从3.2.0.0版本该参数废弃,恒为true) | 默认关闭 |
|
||||||
| `enable.replay` | boolean | 是否开启数据回放功能 | 默认关闭 |
|
| `enable.replay` | boolean | 是否开启数据回放功能 | 默认关闭 |
|
||||||
| `session.timeout.ms` | integer | consumer 心跳丢失后超时时间,超时后会触发 rebalance 逻辑,成功后该 consumer 会被删除(从3.3.3.0版本开始支持) | 默认值为 12000,取值范围 [6000, 1800000] |
|
| `session.timeout.ms` | integer | consumer 心跳丢失后超时时间,超时后会触发 rebalance 逻辑,成功后该 consumer 会被删除(从3.3.3.0版本开始支持) | 默认值为 12000,取值范围 [6000, 1800000] |
|
||||||
| `max.poll.interval.ms` | integer | consumer poll 拉取数据间隔的最长时间,超过该时间,会认为该 consumer 离线,触发rebalance 逻辑,成功后该 consumer 会被删除(从3.3.3.0版本开始支持) | 默认值为 300000,[1000,INT32_MAX] |
|
| `max.poll.interval.ms` | integer | consumer poll 拉取数据间隔的最长时间,超过该时间,会认为该 consumer 离线,触发rebalance 逻辑,成功后该 consumer 会被删除(从3.3.3.0版本开始支持) | 默认值为 300000,[1000,INT32_MAX] |
|
||||||
|
|
||||||
|
|
||||||
下面是各语言连接器创建参数:
|
下面是各语言连接器创建参数:
|
||||||
|
@ -94,8 +94,8 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
|
- Websocket 连接: 因为使用 dsn,不需要 `td.connect.ip`,`td.connect.port`,`td.connect.user` 和 `td.connect.pass` 四个配置项,其余同通用配置项。
|
||||||
同通用基础配置项。
|
- 原生连接: 同通用基础配置项。
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
|
@ -154,7 +154,15 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:create_consumer_1}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:create_consumer_2}}
|
||||||
|
```
|
||||||
|
|
||||||
|
调用 `build_consumer` 函数尝试获取消费者实例 `tmq`。成功则打印成功日志,失败则打印失败日志。
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
@ -283,7 +291,29 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:build_topic_list}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:basic_consume_loop}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:msg_process}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:subscribe_3}}
|
||||||
|
```
|
||||||
|
|
||||||
|
订阅消费数据步骤:
|
||||||
|
1. 调用 `ws_build_topic_list` 函数创建一个主题列表 `topic_list`。
|
||||||
|
2. 如果 `topic_list` 为 `NULL`,表示创建失败,函数返回 `-1`。
|
||||||
|
3. 使用 `ws_tmq_subscribe` 函数订阅 `tmq` 指定的主题列表。如果订阅失败,打印错误信息。
|
||||||
|
4. 销毁主题列表 `topic_list` 以释放资源。
|
||||||
|
5. 调用 `basic_consume_loop` 函数开始基本的消费循环,处理订阅的消息。
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
@ -427,7 +457,17 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:consume_repeatly}}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 通过 `ws_tmq_get_topic_assignment` 函数获取特定主题的分配信息,包括分配的数量和具体分配详情。
|
||||||
|
2. 如果获取分配信息失败,则打印错误信息并返回。
|
||||||
|
3. 对于每个分配,使用 `ws_tmq_offset_seek` 函数将消费者的偏移量设置到最早的偏移量。
|
||||||
|
4. 如果设置偏移量失败,则打印错误信息。
|
||||||
|
5. 释放分配信息数组以释放资源。
|
||||||
|
6. 调用 `basic_consume_loop` 函数开始新的消费循环,处理消息。
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
@ -554,7 +594,12 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:manual_commit}}
|
||||||
|
```
|
||||||
|
|
||||||
|
可以通过 `ws_tmq_commit_sync` 函数来手工提交消费进度。
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
@ -662,7 +707,9 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
```
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c:unsubscribe_and_close}}
|
||||||
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
@ -777,7 +824,13 @@ Rust 连接器创建消费者的参数为 DSN, 可以设置的参数列表请
|
||||||
</details>
|
</details>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="C" value="c">
|
<TabItem label="C" value="c">
|
||||||
不支持
|
<details>
|
||||||
|
<summary>完整代码示例</summary>
|
||||||
|
```c
|
||||||
|
{{#include docs/examples/c-ws/tmq_demo.c}}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem label="REST API" value="rest">
|
<TabItem label="REST API" value="rest">
|
||||||
不支持
|
不支持
|
||||||
|
|
|
@ -14,7 +14,8 @@ description: 让开发者能够快速上手的指南
|
||||||
7. 在很多场景下(如车辆管理),应用需要获取每个数据采集点的最新状态,那么建议你采用 TDengine 的 Cache 功能,而不用单独部署 Redis 等缓存软件。
|
7. 在很多场景下(如车辆管理),应用需要获取每个数据采集点的最新状态,那么建议你采用 TDengine 的 Cache 功能,而不用单独部署 Redis 等缓存软件。
|
||||||
8. 如果你发现 TDengine 的函数无法满足你的要求,那么你可以使用用户自定义函数(UDF)来解决问题。
|
8. 如果你发现 TDengine 的函数无法满足你的要求,那么你可以使用用户自定义函数(UDF)来解决问题。
|
||||||
|
|
||||||
本部分内容就是按照上述顺序组织的。为便于理解,TDengine 为每个功能和每个支持的编程语言都提供了示例代码。如果你希望深入了解 SQL 的使用,需要查看[SQL 手册](../reference/taos-sql/)。如果想更深入地了解各连接器的使用,请阅读[连接器参考指南](../reference/connector/)。如果还希望想将 TDengine 与第三方系统集成起来,比如 Grafana, 请参考[第三方工具](../third-party/)。
|
本部分内容就是按照上述顺序组织的。为便于理解,TDengine 为每个功能和每个支持的编程语言都提供了示例代码,位于 [示例代码](https://github.com/taosdata/TDengine/tree/main/docs/examples)。所有示例代码都会有 CI 保证正确性,脚本位于 [示例代码 CI](https://github.com/taosdata/TDengine/tree/main/tests/docs-examples-test)。
|
||||||
|
如果你希望深入了解 SQL 的使用,需要查看[SQL 手册](../reference/taos-sql/)。如果想更深入地了解各连接器的使用,请阅读[连接器参考指南](../reference/connector/)。如果还希望想将 TDengine 与第三方系统集成起来,比如 Grafana, 请参考[第三方工具](../third-party/)。
|
||||||
|
|
||||||
如果在开发过程中遇到任何问题,请点击每个页面下方的["反馈问题"](https://github.com/taosdata/TDengine/issues/new/choose), 在 GitHub 上直接递交 Issue。
|
如果在开发过程中遇到任何问题,请点击每个页面下方的["反馈问题"](https://github.com/taosdata/TDengine/issues/new/choose), 在 GitHub 上直接递交 Issue。
|
||||||
|
|
||||||
|
|
|
@ -421,7 +421,6 @@ taosX 会将监控指标上报给 taosKeeper,这些监控指标会被 taosKeep
|
||||||
| write_raw_fails | 本次运行写入 raw meta 失败的次数 |
|
| write_raw_fails | 本次运行写入 raw meta 失败的次数 |
|
||||||
| success_blocks | 本次写入成功的数据块数 |
|
| success_blocks | 本次写入成功的数据块数 |
|
||||||
|
|
||||||
|
|
||||||
### taosX 其他数据源 任务
|
### taosX 其他数据源 任务
|
||||||
|
|
||||||
这些数据源包括: InfluxDB,OpenTSDB,OPC UA,OPC DA,PI,CSV,MQTT,AVEVA Historian 和 Kafka。
|
这些数据源包括: InfluxDB,OpenTSDB,OPC UA,OPC DA,PI,CSV,MQTT,AVEVA Historian 和 Kafka。
|
||||||
|
@ -452,3 +451,93 @@ taosX 会将监控指标上报给 taosKeeper,这些监控指标会被 taosKeep
|
||||||
| written_blocks | 本次运行此任务写人成功的 raw block 数 |
|
| written_blocks | 本次运行此任务写人成功的 raw block 数 |
|
||||||
| failed_blocks | 本次运行此任务写入失败的 raw block 数 |
|
| failed_blocks | 本次运行此任务写入失败的 raw block 数 |
|
||||||
|
|
||||||
|
## taosX 数据解析插件
|
||||||
|
|
||||||
|
接入 kafka / mqtt 消息中间件时,需要对原始数据进行解析,如果使用 json/regex 等模式解析器无法满足解析需求,同时 UDT(自定义解析脚本) 也无法满足性能要求时,可以自定义数据解析插件。
|
||||||
|
|
||||||
|
### 插件概述
|
||||||
|
|
||||||
|
taosX Parser 插件是一个要求用 C/Rust 语言开发的 C ABI 兼容动态库,该动态库要实现约定的 API 并编译为在 taosX 所在运行环境中能够正确运行的动态库,然后复制到约定位置由 taosX 在运行时加载,并在处理数据的 Parsing 阶段调用。
|
||||||
|
|
||||||
|
### 插件部署
|
||||||
|
|
||||||
|
完成插件开发后,编译环境需要和目标运行环境兼容,将编译好的插件动态库复制到插件目录下,taosX 启动后,系统首次使用插件时初始化加载插件。可以在 explorer 的 kafka 或者 mqtt 数据接入配置页面中,检查是否加载成功。如下图,如果加载成功,则在解析器选择列表中展示出来。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
插件目录在 `taosx.toml` 配置文件中复用 plugins 配置,追加`/parsers`作为插件安装路径,默认值在 UNIX 环境下为 `/usr/local/taos/plugins/parsers`,在 Windows 下为 `C:\TDengine\plugins\parsers`。
|
||||||
|
|
||||||
|
### 插件 api 说明
|
||||||
|
|
||||||
|
#### 1. 获取插件名称
|
||||||
|
|
||||||
|
获取插件名,用于前端显示。
|
||||||
|
|
||||||
|
**函数签名**:const char* parser_name()
|
||||||
|
|
||||||
|
**返回值**:字符串。
|
||||||
|
|
||||||
|
#### 2. 获取插件版本
|
||||||
|
|
||||||
|
插件版本,方便问题定位。
|
||||||
|
|
||||||
|
**函数签名**:const char* parser_version()
|
||||||
|
|
||||||
|
**返回值**:字符串。
|
||||||
|
|
||||||
|
#### 3. 配置解析器
|
||||||
|
|
||||||
|
将一个字符串参数解析为一个配置对象,仅插件内部使用。
|
||||||
|
|
||||||
|
**函数签名**:parser_resp_t parser_new(char* ctx, uint32_t len);
|
||||||
|
|
||||||
|
char* ctx: 用户自定义配置字符串。
|
||||||
|
|
||||||
|
uint32_t len: 该字符串的二进制长度(不含 `\0`)。
|
||||||
|
|
||||||
|
**返回值**:
|
||||||
|
|
||||||
|
``` c
|
||||||
|
struct parser_resp_t {
|
||||||
|
int e; // 0 if success.
|
||||||
|
void* p; // Success if contains.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
当创建对象失败时,e 不为 0。
|
||||||
|
|
||||||
|
当创建成功时,e = 0,p 为解析器对象。
|
||||||
|
|
||||||
|
#### 4. 解析数据
|
||||||
|
|
||||||
|
**函数签名**:
|
||||||
|
|
||||||
|
对输入 payload 进行解析,返回结果为 JSON 格式 [u8] 。返回的 JSON 将使用默认的 JSON 解析器进行完全解码(展开根数组和所有的对象)。
|
||||||
|
|
||||||
|
``` c
|
||||||
|
const char* parser_mutate(
|
||||||
|
void* parser,
|
||||||
|
const uint8_t* in_ptr, uint32_t in_len,
|
||||||
|
const void* uint8_t* out_ptr, uint32_t* out_len
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
`void* parser`: parser_new 生成的对象指针;
|
||||||
|
|
||||||
|
`const uint8_t* in_ptr`:输入 Payload 的指针;
|
||||||
|
|
||||||
|
`uint32_t in_len`: 输入 Payload 的 bytes 长度(不含 `\0`);
|
||||||
|
|
||||||
|
`const void* uint8_t* out_ptr`:输出 JSON 字符串的指针(不含 \0)。当 out_ptr 指向为空时,表示输出为空。
|
||||||
|
|
||||||
|
`uint32_t * out_len`:输出 JSON 字符串长度。
|
||||||
|
|
||||||
|
**返回值**: 当调用成功时,返回值为 NULL。
|
||||||
|
|
||||||
|
#### 5. 释放解析器
|
||||||
|
|
||||||
|
释放解析器对象内存。
|
||||||
|
|
||||||
|
**函数签名**: void parser_free(void* parser);
|
||||||
|
|
||||||
|
void* parser: parser_new 生成的对象指针。
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
|
@ -80,7 +80,6 @@ database_option: {
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
create database if not exists db vgroups 10 buffer 10
|
create database if not exists db vgroups 10 buffer 10
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
以上示例创建了一个有 10 个 vgroup 名为 db 的数据库, 其中每个 vnode 分配 10MB 的写入缓存
|
以上示例创建了一个有 10 个 vgroup 名为 db 的数据库, 其中每个 vnode 分配 10MB 的写入缓存
|
||||||
|
|
|
@ -1214,7 +1214,7 @@ TO_TIMESTAMP(ts_str_literal, format_str_literal)
|
||||||
- 如果没有指定完整的时间,那么默认时间值为指定或默认时区的 `1970-01-01 00:00:00`, 未指定部分使用该默认值中的对应部分. 暂不支持只指定年日而不指定月日的格式, 如'yyyy-mm-DDD', 支持'yyyy-mm-DD'.
|
- 如果没有指定完整的时间,那么默认时间值为指定或默认时区的 `1970-01-01 00:00:00`, 未指定部分使用该默认值中的对应部分. 暂不支持只指定年日而不指定月日的格式, 如'yyyy-mm-DDD', 支持'yyyy-mm-DD'.
|
||||||
- 如果格式串中有`AM`, `PM`等, 那么小时必须是12小时制, 范围必须是01-12.
|
- 如果格式串中有`AM`, `PM`等, 那么小时必须是12小时制, 范围必须是01-12.
|
||||||
- `to_timestamp`转换具有一定的容错机制, 在格式串和时间戳串不完全对应时, 有时也可转换, 如: `to_timestamp('200101/2', 'yyyyMM1/dd')`, 格式串中多出来的1会被丢弃. 格式串与时间戳串中多余的空格字符(空格, tab等)也会被 自动忽略. 如`to_timestamp(' 23 年 - 1 月 - 01 日 ', 'yy 年-MM月-dd日')` 可以被成功转换. 虽然`MM`等字段需要两个数字对应(只有一位时前面补0), 在`to_timestamp`时, 一个数字也可以成功转换.
|
- `to_timestamp`转换具有一定的容错机制, 在格式串和时间戳串不完全对应时, 有时也可转换, 如: `to_timestamp('200101/2', 'yyyyMM1/dd')`, 格式串中多出来的1会被丢弃. 格式串与时间戳串中多余的空格字符(空格, tab等)也会被 自动忽略. 如`to_timestamp(' 23 年 - 1 月 - 01 日 ', 'yy 年-MM月-dd日')` 可以被成功转换. 虽然`MM`等字段需要两个数字对应(只有一位时前面补0), 在`to_timestamp`时, 一个数字也可以成功转换.
|
||||||
- 输出时间戳的精度与查询表的精度相同, 若查询未指定表, 则输出精度为毫秒. 如`select to_timestamp('2023-08-1 10:10:10.123456789', 'yyyy-mm-dd hh:mi:ss.ns')`的输出将会把微妙和纳秒进行截断. 如果指定一张纳秒表, 那么就不会发生截断, 如`select to_timestamp('2023-08-1 10:10:10.123456789', 'yyyy-mm-dd hh:mi:ss.ns') from db_ns.table_ns limit 1`.
|
- 输出时间戳的精度与查询表的精度相同, 若查询未指定表, 则输出精度为毫秒. 如`select to_timestamp('2023-08-1 10:10:10.123456789', 'yyyy-mm-dd hh:mi:ss.ns')`的输出将会把微秒和纳秒进行截断. 如果指定一张纳秒表, 那么就不会发生截断, 如`select to_timestamp('2023-08-1 10:10:10.123456789', 'yyyy-mm-dd hh:mi:ss.ns') from db_ns.table_ns limit 1`.
|
||||||
|
|
||||||
|
|
||||||
### 时间和日期函数
|
### 时间和日期函数
|
||||||
|
|
|
@ -41,9 +41,11 @@ TDengine 支持 `UNION ALL` 和 `UNION` 操作符。UNION ALL 将查询返回的
|
||||||
| 5 | IS [NOT] NULL | 所有类型 | 是否为空值 |
|
| 5 | IS [NOT] NULL | 所有类型 | 是否为空值 |
|
||||||
| 6 | [NOT] BETWEEN AND | 除 BOOL、BLOB、MEDIUMBLOB、JSON 和 GEOMETRY 外的所有类型 | 闭区间比较 |
|
| 6 | [NOT] BETWEEN AND | 除 BOOL、BLOB、MEDIUMBLOB、JSON 和 GEOMETRY 外的所有类型 | 闭区间比较 |
|
||||||
| 7 | IN | 除 BLOB、MEDIUMBLOB 和 JSON 外的所有类型,且不可以为表的时间戳主键列 | 与列表内的任意值相等 |
|
| 7 | IN | 除 BLOB、MEDIUMBLOB 和 JSON 外的所有类型,且不可以为表的时间戳主键列 | 与列表内的任意值相等 |
|
||||||
| 8 | LIKE | BINARY、NCHAR 和 VARCHAR | 通配符匹配 |
|
| 8 | NOT IN | 除 BLOB、MEDIUMBLOB 和 JSON 外的所有类型,且不可以为表的时间戳主键列 | 与列表内的任意值都不相等 |
|
||||||
| 9 | MATCH, NMATCH | BINARY、NCHAR 和 VARCHAR | 正则表达式匹配 |
|
| 9 | LIKE | BINARY、NCHAR 和 VARCHAR | 通配符匹配所指定的模式串 |
|
||||||
| 10 | CONTAINS | JSON | JSON 中是否存在某键 |
|
| 10 | NOT LIKE | BINARY、NCHAR 和 VARCHAR | 通配符不匹配所指定的模式串 |
|
||||||
|
| 11 | MATCH, NMATCH | BINARY、NCHAR 和 VARCHAR | 正则表达式匹配 |
|
||||||
|
| 12 | CONTAINS | JSON | JSON 中是否存在某键 |
|
||||||
|
|
||||||
LIKE 条件使用通配符字符串进行匹配检查,规则如下:
|
LIKE 条件使用通配符字符串进行匹配检查,规则如下:
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ TSMA只能基于超级表和普通表创建, 不能基于子表创建.
|
||||||
|
|
||||||
由于TSMA输出为一张超级表, 因此输出表的行长度受最大行长度限制, 不同函数的`中间结果`大小各异, 一般都大于原始数据大小, 若输出表的行长度大于最大行长度限制, 将会报`Row length exceeds max length`错误. 此时需要减少函数个数或者将常用的函数进行分组拆分到多个TSMA中.
|
由于TSMA输出为一张超级表, 因此输出表的行长度受最大行长度限制, 不同函数的`中间结果`大小各异, 一般都大于原始数据大小, 若输出表的行长度大于最大行长度限制, 将会报`Row length exceeds max length`错误. 此时需要减少函数个数或者将常用的函数进行分组拆分到多个TSMA中.
|
||||||
|
|
||||||
窗口大小的限制为[1m ~ 1y/12n]. INTERVAL 的单位与查询中INTERVAL子句相同, 如 a (毫秒), b (纳秒), h (小时), m (分钟), s (秒), u (微妙), d (天), w(周), n(月), y(年).
|
窗口大小的限制为[1m ~ 1y/12n]. INTERVAL 的单位与查询中INTERVAL子句相同, 如 a (毫秒), b (纳秒), h (小时), m (分钟), s (秒), u (微秒), d (天), w(周), n(月), y(年).
|
||||||
|
|
||||||
TSMA为库内对象, 但名字全局唯一. 集群内一共可创建TSMA个数受参数`maxTsmaNum`限制, 参数默认值为3, 范围: [0-3]. 注意, 由于TSMA后台计算使用流计算, 因此每创建一条TSMA, 将会创建一条流, 因此能够创建的TSMA条数也受当前已经存在的流条数和最大可创建流条数限制.
|
TSMA为库内对象, 但名字全局唯一. 集群内一共可创建TSMA个数受参数`maxTsmaNum`限制, 参数默认值为3, 范围: [0-3]. 注意, 由于TSMA后台计算使用流计算, 因此每创建一条TSMA, 将会创建一条流, 因此能够创建的TSMA条数也受当前已经存在的流条数和最大可创建流条数限制.
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,615 @@ title: C/C++ Connector
|
||||||
toc_max_heading_level: 4
|
toc_max_heading_level: 4
|
||||||
---
|
---
|
||||||
|
|
||||||
C/C++ 开发人员可以使用 TDengine 的客户端驱动,即 C/C++连接器 (以下都用 TDengine 客户端驱动表示),开发自己的应用来连接 TDengine 集群完成数据存储、查询以及其他功能。TDengine 客户端驱动的 API 类似于 MySQL 的 C API。应用程序使用时,需要包含 TDengine 头文件 _taos.h_,里面列出了提供的 API 的函数原型;应用程序还要链接到所在平台上对应的动态库。
|
C/C++ 开发人员可以使用 TDengine 的客户端驱动,即 C/C++连接器 (以下都用 TDengine 客户端驱动表示),开发自己的应用来连接 TDengine 集群完成数据存储、查询以及其他功能。TDengine 客户端驱动的 API 类似于 MySQL 的 C API。应用程序使用时,需要包含 TDengine 头文件,里面列出了提供的 API 的函数原型;应用程序还要链接到所在平台上对应的动态库。
|
||||||
|
TDengine 的客户端驱动提供了 taosws 和 taos 两个动态库,分别支持 Websocket 连接和原生连接。 Websocket 连接和原生连接的区别是 Websocket 连接方式不要求客户端和服务端版本完全匹配,而原生连接要求,在性能上 Websocket 连接方式也接近于原生连接,一般我们推荐使用 Websocket 连接方式。
|
||||||
|
|
||||||
|
下面我们分开介绍两种连接方式的使用方法。
|
||||||
|
|
||||||
|
|
||||||
|
## Websocket 连接方式
|
||||||
|
|
||||||
|
Websocket 连接方式需要使用 taosws.h 头文件和 taosws 动态库。
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <taosws.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
TDengine 服务端或客户端安装后,`taosws.h` 位于:
|
||||||
|
|
||||||
|
- Linux:`/usr/local/taos/include`
|
||||||
|
- Windows:`C:\TDengine\include`
|
||||||
|
- macOS:`/usr/local/include`
|
||||||
|
|
||||||
|
TDengine 客户端驱动的动态库位于:
|
||||||
|
|
||||||
|
- Linux: `/usr/local/taos/driver/libtaosws.so`
|
||||||
|
- Windows: `C:\TDengine\taosws.dll`
|
||||||
|
- macOS: `/usr/local/lib/libtaosws.dylib`
|
||||||
|
|
||||||
|
### 支持的平台
|
||||||
|
|
||||||
|
请参考[支持的平台列表](../#支持的平台)
|
||||||
|
|
||||||
|
### 版本历史
|
||||||
|
|
||||||
|
| TDengine 客户端版本 | 主要变化 | TDengine 版本 |
|
||||||
|
| :------------------: | :---------------------------: | :----------------: |
|
||||||
|
| 3.3.3.0 | 首次发布,提供了 SQL执行,参数绑定,无模式写入和数据订阅等全面功能支持。 | 3.3.2.0及更高版本 |
|
||||||
|
|
||||||
|
|
||||||
|
### 错误码
|
||||||
|
|
||||||
|
在 C 接口的设计中,错误码采用整数类型表示,每个错误码都对应一个特定的错误状态。如未特别说明,当 API 的返回值是整数时,_0_ 代表成功,其它是代表失败原因的错误码,当返回值是指针时, _NULL_ 表示失败。
|
||||||
|
Websocket 连接方式单独的错误码在 `taosws.h` 中,
|
||||||
|
|
||||||
|
|
||||||
|
| 错误码 | 错误描述 | 可能的出错场景或者可能的原因 | 建议用户采取的措施 |
|
||||||
|
| ------- | -------- | ---------------------------- | ------------------ |
|
||||||
|
| 0xE000 | DSN 错误 | DSN 不符合规范 | 检查 dsn 字符串是否符合规范 |
|
||||||
|
| 0xE001 | 内部错误 | 不确定 | 保留现场和日志,github上报issue |
|
||||||
|
| 0xE002 | 连接关闭 | 网络断开 | 请检查网络状况,查看 `taosadapter` 日志。 |
|
||||||
|
| 0xE003 | 发送超时 | 网络断开 | 请检查网络状况 |
|
||||||
|
| 0xE004 | 接收超时 | 慢查询,或者网络断开 | 排查 `taosadapter` 日志 |
|
||||||
|
|
||||||
|
其余错误码请参考同目录下 `taoserror.h` 文件,详细的原生连接错误码说明参考:[错误码](../../../reference/error-code)。
|
||||||
|
:::info
|
||||||
|
WebSocket 连接方式错误码只保留了原生连接错误码的后两个字节。
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 示例程序
|
||||||
|
|
||||||
|
本节展示了使用客户端驱动访问 TDengine 集群的常见访问方式的示例代码。
|
||||||
|
|
||||||
|
- 同步查询示例:[同步查询](https://github.com/taosdata/TDengine/tree/main/docs/examples/c-ws/query_data_demo.c)
|
||||||
|
|
||||||
|
- 参数绑定示例:[参数绑定](https://github.com/taosdata/TDengine/tree/main/docs/examples/c-ws/stmt_insert_demo.c)
|
||||||
|
|
||||||
|
- 无模式写入示例:[无模式写入](https://github.com/taosdata/TDengine/tree/main/docs/examples/c-ws/sml_insert_demo.c)
|
||||||
|
|
||||||
|
- 订阅和消费示例:[订阅和消费](https://github.com/taosdata/TDengine/tree/main/docs/examples/c-ws/tmq_demo.c)
|
||||||
|
|
||||||
|
:::info
|
||||||
|
更多示例代码及下载请见 [GitHub](https://github.com/taosdata/TDengine/tree/main/docs/examples/c-ws)。
|
||||||
|
:::
|
||||||
|
|
||||||
|
### API 参考
|
||||||
|
|
||||||
|
以下分别介绍 TDengine 客户端驱动的 DSN、基础 API、同步查询 API、参数绑定 API、无模式写入 API 和 数据订阅订阅 API。
|
||||||
|
|
||||||
|
#### DSN
|
||||||
|
|
||||||
|
C/C++ Websocket 连接器通过 DSN 连接描述字符串来表示连接信息。
|
||||||
|
DSN 描述字符串基本结构如下:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<driver>[+<protocol>]://[[<username>:<password>@]<host>:<port>][/<database>][?<p1>=<v1>[&<p2>=<v2>]]
|
||||||
|
|------|------------|---|-----------|-----------|------|------|------------|-----------------------|
|
||||||
|
|driver| protocol | | username | password | host | port | database | params |
|
||||||
|
```
|
||||||
|
|
||||||
|
各部分意义见下表:
|
||||||
|
|
||||||
|
- **driver**: 必须指定驱动名以便连接器选择何种方式创建连接,支持如下驱动名:
|
||||||
|
- **taos**: 默认驱动,支持 SQL 执行,参数绑定,无模式写入。
|
||||||
|
- **tmq**: 使用 TMQ 订阅数据。
|
||||||
|
- **protocol**: 显示指定以何种方式建立连接,例如:`taos+ws://localhost:6041` 指定以 Websocket 方式建立连接。
|
||||||
|
- **http/ws**: 使用 Websocket 协议。
|
||||||
|
- **https/wss**: 在 Websocket 连接方式下显示启用 SSL/TLS 协议。
|
||||||
|
|
||||||
|
- **username/password**: 用于创建连接的用户名及密码。
|
||||||
|
- **host/port**: 指定创建连接的服务器及端口,当不指定服务器地址及端口时 Websocket 连接默认为 `localhost:6041` 。
|
||||||
|
- **database**: 指定默认连接的数据库名,可选参数。
|
||||||
|
- **params**:其他可选参数。
|
||||||
|
|
||||||
|
一个完整的 DSN 描述字符串示例如下:`taos+ws://localhost:6041/test`, 表示使用 Websocket(`ws`)方式通过 `6041` 端口连接服务器 `localhost`,并指定默认数据库为 `test`。
|
||||||
|
|
||||||
|
#### 基础 API
|
||||||
|
|
||||||
|
基础 API 用于完成创建数据库连接等工作,为其它 API 的执行提供运行时环境。
|
||||||
|
|
||||||
|
- `char *ws_get_client_info()`
|
||||||
|
- **接口说明**:获取客户端版本信息。
|
||||||
|
- **返回值**:返回客户端版本信息。
|
||||||
|
|
||||||
|
- `WS_TAOS *ws_connect(const char *dsn)`
|
||||||
|
- **接口说明**:创建数据库连接,初始化连接上下文。
|
||||||
|
- **参数说明**:
|
||||||
|
- dsn:[入参] 连接信息,见上文 DSN 章节。
|
||||||
|
- **返回值**:返回数据库连接,返回值为空表示失败。应用程序需要保存返回的参数,以便后续使用。
|
||||||
|
:::info
|
||||||
|
同一进程可以根据不同的 dsn 连接多个 TDengine 集群
|
||||||
|
:::
|
||||||
|
|
||||||
|
- `const char *ws_get_server_info(WS_TAOS *taos)`
|
||||||
|
- **接口说明**:获取服务端版本信息。
|
||||||
|
- **参数说明**:
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- **返回值**:返回获取服务端版本信息。
|
||||||
|
|
||||||
|
- `int32_t ws_select_db(WS_TAOS *taos, const char *db)`
|
||||||
|
- **接口说明**:将当前的缺省数据库设置为 `db`。
|
||||||
|
- **参数说明**:
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- db:[入参] 数据库名称。
|
||||||
|
- **返回值**:`0`:成功,非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int32_t ws_get_current_db(WS_TAOS *taos, char *database, int len, int *required)`
|
||||||
|
- **接口说明**:获取当前数据库名称。
|
||||||
|
- **参数说明**:
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- database:[出参] 存储当前数据库名称。
|
||||||
|
- len:[入参] database 的空间大小。
|
||||||
|
- required:[出参] 存储当前数据库名称所需的空间(包含最后的'\0')。
|
||||||
|
- **返回值**:`0`:成功,`-1`:失败,可调用函数 ws_errstr(NULL) 获取更详细的错误信息。
|
||||||
|
- 如果,database == NULL 或者 len\<=0 返回失败。
|
||||||
|
- 如果,len 小于 存储数据库名称所需的空间(包含最后的'\0'),返回失败,database 里赋值截断的数据,以'\0'结尾。
|
||||||
|
- 如果,len 大于等于 存储数据库名称所需的空间(包含最后的'\0'),返回成功,database 里赋值以'\0‘结尾数据库名称。
|
||||||
|
|
||||||
|
- `int32_t ws_close(WS_TAOS *taos);`
|
||||||
|
- **接口说明**:关闭连接。
|
||||||
|
- **参数说明**:
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- **返回值**:`0`:成功,非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
#### 同步查询
|
||||||
|
|
||||||
|
本小节介绍 API 均属于同步接口。应用调用后,会阻塞等待响应,直到获得返回结果或错误信息。
|
||||||
|
|
||||||
|
- `WS_RES *ws_query(WS_TAOS *taos, const char *sql)`
|
||||||
|
- **接口说明**:执行 SQL 语句,可以是 DQL、DML 或 DDL 语句。
|
||||||
|
- **参数说明**:
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- sql:[入参] 需要执行 SQL 语句。
|
||||||
|
- **返回值**:不能通过返回值是否是 `NULL` 来判断执行结果是否失败,而是需要调用 `ws_errno()` 函数解析结果集中的错误代码来进行判断。
|
||||||
|
- ws_errno 返回值:`0`:成功,`-1`:失败,详情请调用 ws_errstr 函数来获取错误提示。
|
||||||
|
|
||||||
|
- `int32_t ws_result_precision(const WS_RES *rs)`
|
||||||
|
- **接口说明**:返回结果集时间戳字段的精度类别。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:`0`:毫秒,`1`:微秒,`2`:纳秒。
|
||||||
|
|
||||||
|
- `WS_ROW ws_fetch_row(WS_RES *rs)`
|
||||||
|
- **接口说明**:按行获取查询结果集中的数据。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:非 `NULL`:成功,`NULL`:失败,可调用函数 ws_errstr(NULL) 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_fetch_raw_block(WS_RES *rs, const void **pData, int32_t *numOfRows)`
|
||||||
|
- **接口说明**:批量获取查询结果集中的数据。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- pData:[出参] 用于存储从结果集中获取一个数据块。
|
||||||
|
- numOfRows:[出参] 用于存储从结果集中获取数据块包含的行数。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int32_t ws_num_fields(const WS_RES *rs)` 和 `int32_t ws_field_count(const WS_RES *rs)`
|
||||||
|
- **接口说明**:这两个 API 等价,用于获取查询结果集中的列数。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:返回值为结果集中列的数量。
|
||||||
|
|
||||||
|
- `int32_t ws_affected_rows(const WS_RES *rs)`
|
||||||
|
- **接口说明**:获取被所执行的 SQL 语句影响的行数。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:返回值表示受影响的行数。
|
||||||
|
|
||||||
|
- `int64_t ws_affected_rows64(const WS_RES *rs)`
|
||||||
|
- **接口说明**:获取被所执行的 SQL 语句影响的行数。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:返回值表示受影响的行数。
|
||||||
|
|
||||||
|
- `const struct WS_FIELD *ws_fetch_fields(WS_RES *rs)`
|
||||||
|
- **接口说明**:获取查询结果集每列数据的属性(列的名称、列的数据类型、列的长度),与 `ws_num_fields()` 配合使用,可用来解析 `ws_fetch_row()` 返回的一个元组(一行)的数据。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个指向 WS_FIELD 结构体的指针,每个元素代表一列的元数据。`NULL`:失败。
|
||||||
|
|
||||||
|
- `int32_t ws_stop_query(WS_RES *rs)`
|
||||||
|
- **接口说明**:停止当前查询的执行。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int32_t ws_free_result(WS_RES *rs)`
|
||||||
|
- **接口说明**:释放查询结果集以及相关的资源。查询完成后,务必调用该 API 释放资源,否则可能导致应用内存泄露。但也需注意,释放资源后,如果再调用 `ws_fetch_fields()` 等获取查询结果的函数,将导致应用崩溃。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `const char *ws_errstr(WS_RES *rs)`
|
||||||
|
- **接口说明**:获取最近一次 API 调用失败的原因,返回值为字符串标识的错误提示信息。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:字符串标识的错误提示信息。
|
||||||
|
|
||||||
|
- `int32_t ws_errno(WS_RES *rs)`
|
||||||
|
- **接口说明**:获取最近一次 API 调用失败的原因,返回值为错误代码。
|
||||||
|
- **参数说明**:
|
||||||
|
- res:[入参] 结果集。
|
||||||
|
- **返回值**:字符串标识的错误提示信息。
|
||||||
|
|
||||||
|
:::note
|
||||||
|
TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池。不要在应用中将该连接 (WS_TAOS\*) 结构体传递到不同的线程共享使用。
|
||||||
|
另一个需要注意的是,在上述同步 API 执行过程中,不能调用类似 pthread_cancel 之类的 API 来强制结束线程,因为涉及一些模块的同步操作,如果强制结束线程有可能造成包括但不限于死锁等异常状况。
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### 参数绑定
|
||||||
|
|
||||||
|
除了直接调用 `ws_query()` 通过执行 SQL 进行数据写入,TDengine 也提供了支持参数绑定的 Prepare API,风格与 MySQL 类似,目前也仅支持用问号 `?` 来代表待绑定的参数。
|
||||||
|
|
||||||
|
通过参数绑定接口写入数据时,可以避免 SQL 语法解析的资源消耗,从而在绝大多数情况下显著提升写入性能。此时的典型操作步骤如下:
|
||||||
|
|
||||||
|
1. 调用 `ws_stmt_init()` 创建参数绑定对象;
|
||||||
|
2. 调用 `ws_stmt_prepare()` 解析 INSERT 语句;
|
||||||
|
3. 如果 INSERT 语句中预留了表名但没有预留 TAGS,那么调用 `ws_stmt_set_tbname()` 来设置表名;
|
||||||
|
4. 如果 INSERT 语句中既预留了表名又预留了 TAGS(例如 INSERT 语句采取的是自动建表的方式),那么调用 `ws_stmt_set_tbname_tags()` 来设置表名和 TAGS 的值;
|
||||||
|
5. 调用 `ws_stmt_bind_param_batch()` 以多行的方式设置 VALUES 的值;
|
||||||
|
6. 调用 `ws_stmt_add_batch()` 把当前绑定的参数加入批处理;
|
||||||
|
7. 可以重复第 3 ~ 6 步,为批处理加入更多的数据行;
|
||||||
|
8. 调用 `ws_stmt_execute()` 执行已经准备好的批处理指令;
|
||||||
|
9. 执行完毕,调用 `ws_stmt_close()` 释放所有资源。
|
||||||
|
|
||||||
|
说明:如果 `ws_stmt_execute()` 执行成功,假如不需要改变 SQL 语句的话,那么是可以复用 `ws_stmt_prepare()` 的解析结果,直接进行第 3 ~ 6 步绑定新数据的。但如果执行出错,那么并不建议继续在当前的环境上下文下继续工作,而是建议释放资源,然后从 `ws_stmt_init()` 步骤重新开始。
|
||||||
|
|
||||||
|
接口相关的具体函数如下(也可以参考 [stmt_insert_demo.c](https://github.com/taosdata/TDengine/blob/develop/docs/examples/c-ws/stmt_insert_demo.c) 文件中使用对应函数的方式):
|
||||||
|
|
||||||
|
- `WS_STMT *ws_stmt_init(const WS_TAOS *taos)`
|
||||||
|
- **接口说明**:初始化一个预编译的 SQL 语句对象。
|
||||||
|
- **参数说明**:
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个指向 WS_STMT 结构体的指针,该结构体表示预编译的 SQL 语句对象。`NULL`:失败,详情请调用 ws_stmt_errstr() 函数来获取错误提示。
|
||||||
|
|
||||||
|
- `int ws_stmt_prepare(WS_STMT *stmt, const char *sql, unsigned long len)`
|
||||||
|
- **接口说明**:解析一条预编译的 SQL 语句,将解析结果和参数信息绑定到 stmt 上。
|
||||||
|
- **参数说明**:
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- sql:[入参] 需要解析的 SQL 语句。
|
||||||
|
- len:[入参] 参数 sql 的长度。如果参数 len 大于 0,将使用此参数作为 SQL 语句的长度,如等于 0,将自动判断 SQL 语句的长度。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int ws_stmt_bind_param_batch(WS_STMT *stmt, const WS_MULTI_BIND *bind, uint32_t len)`
|
||||||
|
- **接口说明**:以多列的方式传递待绑定的数据,需要保证这里传递的数据列的顺序、列的数量与 SQL 语句中的 VALUES 参数完全一致。
|
||||||
|
- **参数说明**:
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- bind:[入参] 指向一个有效的 WS_MULTI_BIND 结构体指针,该结构体包含了要批量绑定到 SQL 语句中的参数列表。
|
||||||
|
- len: [入参] bind 数组的元素个数。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int ws_stmt_set_tbname(WS_STMT *stmt, const char *name)`
|
||||||
|
- **接口说明**:(仅支持用于替换 INSERT 语句中的参数值)当 SQL 语句中的表名使用了 `?` 占位时,可以使用此函数绑定一个具体的表名。
|
||||||
|
- **参数说明**:
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- name:[入参] 指向一个包含子表名称的字符串常量。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int ws_stmt_set_tbname_tags(WS_STMT *stmt,
|
||||||
|
const char *name,
|
||||||
|
const WS_MULTI_BIND *bind,
|
||||||
|
uint32_t len);`
|
||||||
|
- **接口说明**:(仅支持用于替换 INSERT 语句中的参数值)当 SQL 语句中的表名和 TAGS 都使用了 `?` 占位时,可以使用此函数绑定具体的表名和具体的 TAGS 取值。最典型的使用场景是使用了自动建表功能的 INSERT 语句(目前版本不支持指定具体的 TAGS 列)。TAGS 参数中的列数量需要与 SQL 语句中要求的 TAGS 数量完全一致。
|
||||||
|
- **参数说明**:
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- name:[入参] 指向一个包含子表名称的字符串常量。
|
||||||
|
- tags:[入参] 指向一个有效的 WS_MULTI_BIND 结构体指针,该结构体包含了子表标签的值。
|
||||||
|
- len:[入参] bind 数组的元素个数。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int ws_stmt_add_batch(WS_STMT *stmt)`
|
||||||
|
- **接口说明**:将当前绑定的参数加入批处理中,调用此函数后,可以再次调用 `ws_stmt_bind_param_batch()` 绑定新的参数。需要注意,此函数仅支持 INSERT/IMPORT 语句,如果是 SELECT 等其他 SQL 语句,将返回错误。
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int ws_stmt_execute(WS_STMT *stmt, int32_t *affected_rows)`
|
||||||
|
- **接口说明**:执行准备好的语句。目前,一条语句只能执行一次。
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- affected_rows:[出参] 成功写入的行数。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `int ws_stmt_affected_rows(WS_STMT *stmt)`
|
||||||
|
- **接口说明**:获取执行预编译 SQL 语句后受影响的行数。
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- **返回值**:返回受影响的行数。
|
||||||
|
|
||||||
|
- `int ws_stmt_affected_rows_once(WS_STMT *stmt)`
|
||||||
|
- **接口说明**:获取执行一次绑定语句影响的行数。
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- **返回值**:返回受影响的行数。
|
||||||
|
|
||||||
|
- `int32_t ws_stmt_close(WS_STMT *stmt)`
|
||||||
|
- **接口说明**:执行完毕,释放所有资源。
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,详情请参考错误码页面。
|
||||||
|
|
||||||
|
- `const char *ws_stmt_errstr(WS_STMT *stmt)`
|
||||||
|
- **接口说明**:用于在其他 STMT API 返回错误(返回错误码或空指针)时获取错误信息。
|
||||||
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
|
- **返回值**:返回一个指向包含错误信息的字符串的指针。
|
||||||
|
|
||||||
|
#### 无模式写入
|
||||||
|
|
||||||
|
除了使用 SQL 方式或者使用参数绑定 API 写入数据外,还可以使用 Schemaless 的方式完成写入。Schemaless 可以免于预先创建超级表/数据子表的数据结构,而是可以直接写入数据,TDengine 系统会根据写入的数据内容自动创建和维护所需要的表结构。Schemaless 的使用方式详见 [Schemaless 写入](../../../develop/schemaless/) 章节,这里介绍与之配套使用的 C/C++ API。
|
||||||
|
- `WS_RES *ws_schemaless_insert_raw(WS_TAOS *taos,
|
||||||
|
const char *lines,
|
||||||
|
int len,
|
||||||
|
int32_t *totalRows,
|
||||||
|
int protocal,
|
||||||
|
int precision)`
|
||||||
|
- **接口说明**:执行无模式的批量插入操作,将行协议的文本数据写入到 TDengine 中。通过传递的参数lines指针和长度len来表示数据,为了解决原始接口数据包含'\0'而被截断的问题。
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- lines:[入参] 文本数据。满足解析格式要求的无模式文本字符串。
|
||||||
|
- len:[入参] 数据缓冲区 lines 的总长度(字节数)。
|
||||||
|
- totalRows:[出参] 指向一个整数指针,用于返回成功插入的记录总数。
|
||||||
|
- protocol:[入参] 行协议类型,用于标识文本数据格式。
|
||||||
|
- precision:[入参] 文本数据中的时间戳精度字符串。
|
||||||
|
- **返回值**:返回一个指向 WS_RES 结构体的指针,该结构体包含了插入操作的结果。应用可以通过使用 `ws_errstr()` 获得错误信息,也可以使用 `ws_errno()` 获得错误码。在某些情况下,返回的 WS_RES 为 `NULL`,此时仍然可以调用 `ws_errno()` 来安全地获得错误码信息。
|
||||||
|
返回的 WS_RES 需要调用方来负责释放,否则会出现内存泄漏。
|
||||||
|
|
||||||
|
**说明**
|
||||||
|
协议类型是枚举类型,包含以下三种格式:
|
||||||
|
|
||||||
|
- WS_TSDB_SML_LINE_PROTOCOL:InfluxDB 行协议(Line Protocol)
|
||||||
|
- WS_TSDB_SML_TELNET_PROTOCOL: OpenTSDB Telnet 文本行协议
|
||||||
|
- WS_TSDB_SML_JSON_PROTOCOL: OpenTSDB Json 协议格式
|
||||||
|
|
||||||
|
时间戳分辨率的定义,定义在 `taosws.h` 文件中,具体内容如下:
|
||||||
|
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_NOT_CONFIGURED = 0,
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_HOURS,
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_MINUTES,
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_SECONDS,
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS,
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_MICRO_SECONDS,
|
||||||
|
- WS_TSDB_SML_TIMESTAMP_NANO_SECONDS
|
||||||
|
|
||||||
|
需要注意的是,时间戳分辨率参数只在协议类型为 `WS_SML_LINE_PROTOCOL` 的时候生效。
|
||||||
|
对于 OpenTSDB 的文本协议,时间戳的解析遵循其官方解析规则 — 按照时间戳包含的字符的数量来确认时间精度。
|
||||||
|
|
||||||
|
**schemaless 其他相关的接口**
|
||||||
|
|
||||||
|
- `WS_RES *ws_schemaless_insert_raw_with_reqid(WS_TAOS *taos,
|
||||||
|
const char *lines,
|
||||||
|
int len,
|
||||||
|
int32_t *totalRows,
|
||||||
|
int protocal,
|
||||||
|
int precision,
|
||||||
|
uint64_t reqid)`
|
||||||
|
- **接口说明**:执行无模式的批量插入操作,将行协议的文本数据写入到 TDengine 中。通过传递的参数lines指针和长度len来表示数据,为了解决原始接口数据包含'\0'而被截断的问题。通过传递参数reqid来跟踪整个的函数调用链情况。
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- lines:[入参] 文本数据。满足解析格式要求的无模式文本字符串。
|
||||||
|
- len:[入参] 数据缓冲区 lines 的总长度(字节数)。
|
||||||
|
- totalRows:[出参] 指向一个整数指针,用于返回成功插入的记录总数。
|
||||||
|
- protocol:[入参] 行协议类型,用于标识文本数据格式。
|
||||||
|
- precision:[入参] 文本数据中的时间戳精度字符串。
|
||||||
|
- reqid:[入参] 指定的请求 ID,用于跟踪调用请求。请求 ID (reqid) 可以用于在客户端和服务器端之间建立请求和响应之间的关联,对于分布式系统中的跟踪和调试非常有用。
|
||||||
|
- **返回值**:返回一个指向 WS_RES 结构体的指针,该结构体包含了插入操作的结果。应用可以通过使用 `ws_errstr()` 获得错误信息,也可以使用 `ws_errno()` 获得错误码。在某些情况下,返回的 WS_RES 为 `NULL`,此时仍然可以调用 `ws_errno()` 来安全地获得错误码信息。
|
||||||
|
返回的 WS_RES 需要调用方来负责释放,否则会出现内存泄漏。
|
||||||
|
|
||||||
|
- `WS_RES *ws_schemaless_insert_raw_ttl(WS_TAOS *taos,
|
||||||
|
const char *lines,
|
||||||
|
int len,
|
||||||
|
int32_t *totalRows,
|
||||||
|
int protocal,
|
||||||
|
int precision,
|
||||||
|
int ttl)`
|
||||||
|
- **接口说明**:执行无模式的批量插入操作,将行协议的文本数据写入到 TDengine 中。通过传递的参数lines指针和长度len来表示数据,为了解决原始接口数据包含'\0'而被截断的问题。通过传递ttl参数来控制建表的ttl到期时间。
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- lines:[入参] 文本数据。满足解析格式要求的无模式文本字符串。
|
||||||
|
- len:[入参] 数据缓冲区 lines 的总长度(字节数)。
|
||||||
|
- totalRows:[出参] 指向一个整数指针,用于返回成功插入的记录总数。
|
||||||
|
- protocol:[入参] 行协议类型,用于标识文本数据格式。
|
||||||
|
- precision:[入参] 文本数据中的时间戳精度字符串。
|
||||||
|
- ttl:[入参] 指定的生存时间(TTL),单位为天。记录在超过这个生存时间后会被自动删除。
|
||||||
|
- **返回值**:返回一个指向 WS_RES 结构体的指针,该结构体包含了插入操作的结果。应用可以通过使用 `ws_errstr()` 获得错误信息,也可以使用 `ws_errno()` 获得错误码。在某些情况下,返回的 WS_RES 为 `NULL`,此时仍然可以调用 `ws_errno()` 来安全地获得错误码信息。
|
||||||
|
返回的 WS_RES 需要调用方来负责释放,否则会出现内存泄漏。
|
||||||
|
|
||||||
|
- `WS_RES *ws_schemaless_insert_raw_ttl_with_reqid(WS_TAOS *taos,
|
||||||
|
const char *lines,
|
||||||
|
int len,
|
||||||
|
int32_t *totalRows,
|
||||||
|
int protocal,
|
||||||
|
int precision,
|
||||||
|
int ttl,
|
||||||
|
uint64_t reqid)`
|
||||||
|
- **接口说明**:执行无模式的批量插入操作,将行协议的文本数据写入到 TDengine 中。通过传递的参数lines指针和长度len来表示数据,为了解决原始接口数据包含'\0'而被截断的问题。通过传递ttl参数来控制建表的ttl到期时间。通过传递参数reqid来跟踪整个的函数调用链情况。
|
||||||
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `ws_connect()` 函数建立。
|
||||||
|
- lines:[入参] 文本数据。满足解析格式要求的无模式文本字符串。
|
||||||
|
- len:[入参] 数据缓冲区 lines 的总长度(字节数)。
|
||||||
|
- totalRows:[出参] 指向一个整数指针,用于返回成功插入的记录总数。
|
||||||
|
- protocol:[入参] 行协议类型,用于标识文本数据格式。
|
||||||
|
- precision:[入参] 文本数据中的时间戳精度字符串。
|
||||||
|
- ttl:[入参] 指定的生存时间(TTL),单位为天。记录在超过这个生存时间后会被自动删除。
|
||||||
|
- reqid:[入参] 指定的请求 ID,用于跟踪调用请求。请求 ID (reqid) 可以用于在客户端和服务器端之间建立请求和响应之间的关联,对于分布式系统中的跟踪和调试非常有用。
|
||||||
|
- **返回值**:返回一个指向 WS_RES 结构体的指针,该结构体包含了插入操作的结果。应用可以通过使用 `ws_errstr()` 获得错误信息,也可以使用 `ws_errno()` 获得错误码。在某些情况下,返回的 WS_RES 为 `NULL`,此时仍然可以调用 `ws_errno()` 来安全地获得错误码信息。
|
||||||
|
返回的 WS_RES 需要调用方来负责释放,否则会出现内存泄漏。
|
||||||
|
|
||||||
|
**说明**
|
||||||
|
- 上面这3个接口是扩展接口,主要用于在 schemaless 写入时传递 ttl、reqid 参数,可以根据需要使用。
|
||||||
|
- 带 ttl 的接口可以传递 ttl 参数来控制建表的ttl到期时间。
|
||||||
|
- 带 reqid 的接口可以通过传递 reqid 参数来追踪整个的调用链。
|
||||||
|
|
||||||
|
#### 数据订阅
|
||||||
|
- `const char *ws_tmq_errstr(ws_tmq_t *tmq)`
|
||||||
|
- **接口说明**:用于获取数据订阅的错误信息。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- **返回值**:返回一个指向包含错误信息字符串的指针,返回值非NULL,但是错误信息可能为空字符串。
|
||||||
|
|
||||||
|
- `ws_tmq_conf_t *ws_tmq_conf_new(void);`
|
||||||
|
- **接口说明**:创建一个新的 TMQ 配置对象。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个指向 ws_tmq_conf_t 结构体的指针,该结构体用于配置 TMQ 的行为和特性。`NULL`:失败,可调用函数 ws_errstr(NULL) 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `enum ws_tmq_conf_res_t ws_tmq_conf_set(ws_tmq_conf_t *conf, const char *key, const char *value)`
|
||||||
|
- **接口说明**:设置 TMQ 配置对象中的配置项,用于配置消费参数。
|
||||||
|
- conf:[入参] 指向一个有效的 ws_tmq_conf_t 结构体指针,该结构体代表一个 TMQ 配置对象。
|
||||||
|
- key:[入参] 数配置项的键名。
|
||||||
|
- value:[入参] 配置项的值。
|
||||||
|
- **返回值**:返回一个 ws_tmq_conf_res_t 枚举值,表示配置设置的结果。
|
||||||
|
- WS_TMQ_CONF_OK:成功设置配置项。
|
||||||
|
- WS_TMQ_CONF_INVALID_KEY:键值无效。
|
||||||
|
- WS_TMQ_CONF_UNKNOWN:键名无效。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_conf_destroy(ws_tmq_conf_t *conf)`
|
||||||
|
- **接口说明**:销毁一个 TMQ 配置对象并释放相关资源。
|
||||||
|
- conf:[入参] 指向一个有效的 ws_tmq_conf_t 结构体指针,该结构体代表一个 TMQ 配置对象。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(NULL)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `ws_tmq_list_t *ws_tmq_list_new(void)`
|
||||||
|
- **接口说明**:用于创建一个 ws_tmq_list_t 结构体,用于存储订阅的 topic。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个指向 ws_tmq_list_t 结构体的指针。`NULL`:失败,可调用函数 `ws_tmq_errstr(NULL)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_list_append(ws_tmq_list_t *list, const char *topic)`
|
||||||
|
- **接口说明**:用于向 ws_tmq_list_t 结构体中添加一个 topic。
|
||||||
|
- list:[入参] 指向一个有效的 ws_tmq_list_t 结构体指针,该结构体代表一个 TMQ 列表对象。
|
||||||
|
- topic:[入参] topic 名称。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(NULL)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_list_destroy(ws_tmq_list_t *list);`
|
||||||
|
- **接口说明**:用于销毁 ws_tmq_list_t 结构体,ws_tmq_list_new 的结果需要通过该接口销毁。
|
||||||
|
- list:[入参] 指向一个有效的 ws_tmq_list_t 结构体指针,该结构体代表一个 TMQ 列表对象。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(NULL)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_list_get_size(ws_tmq_list_t *list);`
|
||||||
|
- **接口说明**:用于获取 ws_tmq_list_t 结构体中 topic 的个数。
|
||||||
|
- list:[入参] 指向一个有效的 ws_tmq_list_t 结构体指针,该结构体代表一个 TMQ 列表对象。
|
||||||
|
- **返回值**:`>=0`:成功,返回 ws_tmq_list_t 结构体中 topic 的个数。`-1`:失败,表示输入参数 list 为 NULL 。
|
||||||
|
|
||||||
|
- `char **ws_tmq_list_to_c_array(const ws_tmq_list_t *list, uint32_t *topic_num);`
|
||||||
|
- **接口说明**:用于将 ws_tmq_list_t 结构体转换为 C 数组,数组每个元素为字符串指针。
|
||||||
|
- list:[入参] 指向一个有效的 ws_tmq_list_t 结构体指针,该结构体代表一个 TMQ 列表对象。
|
||||||
|
- topic_num:[入参] list 的元素个数。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回 c 数组, 每个元素是字符串指针,代表一个 topic 名称。`NULL`:失败,表示输入参数 list 为 NULL 。
|
||||||
|
|
||||||
|
- `ws_tmq_t *ws_tmq_consumer_new(ws_tmq_conf_t *conf, const char *dsn, char *errstr, int errstr_len)`
|
||||||
|
- **接口说明**:用于创建一个 ws_tmq_t 结构体,用于消费数据,消费完数据后需调用 tmq_consumer_close 关闭消费者。
|
||||||
|
- conf:[入参] 指向一个有效的 ws_tmq_conf_t 结构体指针,该结构体代表一个 TMQ 配置对象。
|
||||||
|
- dsn:[入参] dsn 信息字符串,具体可参考上面 DSN 章节。一个常见的合法 dsn 为 "tmq+ws://root:taosdata@localhost:6041"。
|
||||||
|
- errstr:[出参] 指向一个有效的字符缓冲区指针,用于接收创建过程中可能产生的错误信息。内存的申请/释放由调用者负责。
|
||||||
|
- errstrLen:[入参] 指定 errstr 缓冲区的大小(以字节为单位)。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个指向 ws_tmq_t 结构体的指针,该结构体代表一个 TMQ 消费者对象。。`NULL`:失败,错误信息存储在参数 errstr 中 。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_subscribe(ws_tmq_t *tmq, const ws_tmq_list_t *topic_list)`
|
||||||
|
- **接口说明**:用于订阅 topic 列表,消费完数据后,需调用 ws_tmq_subscribe 取消订阅。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- topic_list:[入参] 指向一个有效的 ws_tmq_list_t 结构体指针,该结构体包含一个或多个主题名称,目前仅支持一个主题名称。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_unsubscribe(ws_tmq_t *tmq)`
|
||||||
|
- **接口说明**:用于取消订阅的 topic 列表。需与 ws_tmq_subscribe 配合使用。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `WS_RES *ws_tmq_consumer_poll(ws_tmq_t *tmq, int64_t timeout)`
|
||||||
|
- **接口说明**:用于轮询消费数据,每一个消费者,只能单线程调用该接口。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- timeout:[入参] 轮询的超时时间,单位为毫秒,负数表示默认超时1秒。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个指向 WS_RES 结构体的指针,该结构体包含了接收到的消息。`NULL`:失败,表示没有数据。WS_RES 结果和 taos_query 返回结果一致,可通过查询的各种接口获取 WS_RES 里的信息,比如 schema 等。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_consumer_close(ws_tmq_t *tmq)`
|
||||||
|
- **接口说明**:用于关闭 ws_tmq_t 结构体。需与 ws_tmq_consumer_new 配合使用。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_get_topic_assignment(ws_tmq_t *tmq,
|
||||||
|
const char *pTopicName,
|
||||||
|
struct ws_tmq_topic_assignment **assignment,
|
||||||
|
int32_t *numOfAssignment)`
|
||||||
|
- **接口说明**:返回当前 consumer 分配的 vgroup 的信息,每个 vgroup 的信息包括 vgId,wal 的最大最小 offset,以及当前消费到的 offset。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- pTopicName:[入参] 要查询分配信息的主题名称。
|
||||||
|
- assignment:[出参] 指向一个 tmq_topic_assignment 结构体指针的指针,用于接收分配信息。数据大小为 numOfAssignment,需要通过 tmq_free_assignment 接口释放。
|
||||||
|
- numOfAssignment:[出参] 指向一个整数指针,用于接收分配给该 consumer 有效的 vgroup 个数。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_free_assignment(struct ws_tmq_topic_assignment *pAssignment, int32_t numOfAssignment)`
|
||||||
|
- **接口说明**:返回当前consumer分配的vgroup的信息,每个vgroup的信息包括vgId,wal的最大最小offset,以及当前消费到的offset。
|
||||||
|
- pAssignment:[入参] 指向一个有效的 ws_tmq_topic_assignment 结构体数组的指针,该数组包含了 vgroup 分配信息。
|
||||||
|
- numOfAssignment:[入参] pAssignment 指向的数组元素个数。
|
||||||
|
- **返回值**:`0`:成功。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int64_t ws_tmq_committed(ws_tmq_t *tmq, const char *pTopicName, int32_t vgId)`
|
||||||
|
- **接口说明**:获取 TMQ 消费者对象对特定 topic 和 vgroup 的已提交偏移量。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- pTopicName:[入参] 要查询已提交偏移量的主题名称。
|
||||||
|
- vgId:[入参] vgroup 的 ID。
|
||||||
|
- **返回值**:`>=0`:成功,返回一个 int64_t 类型的值,表示已提交的偏移量。`<0`:失败,返回值就是错误码,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_commit_sync(ws_tmq_t *tmq, const WS_RES *rs)`
|
||||||
|
- **接口说明**:同步提交 TMQ 消费者对象处理的消息偏移量。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- rs:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了已处理的消息。如果为 NULL,提交当前 consumer 所有消费的 vgroup 的当前进度。
|
||||||
|
- **返回值**:`0`:成功,已经成功提交偏移量。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_commit_offset_sync(ws_tmq_t *tmq,
|
||||||
|
const char *pTopicName,
|
||||||
|
int32_t vgId,
|
||||||
|
int64_t offset)`
|
||||||
|
- **接口说明**:同步提交 TMQ 消费者对象的特定主题和 vgroup 的偏移量。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- pTopicName:[入参] 要提交偏移量的主题名称。
|
||||||
|
- vgId:[入参] 虚拟组 vgroup 的 ID。
|
||||||
|
- offset:[入参] 要提交的偏移量。
|
||||||
|
- **返回值**:`0`:成功,已经成功提交偏移量。非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int64_t ws_tmq_position(ws_tmq_t *tmq, const char *pTopicName, int32_t vgId)`
|
||||||
|
- **接口说明**:获取当前消费位置,即已消费到的数据位置的下一个位置.
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- pTopicName:[入参] 要查询当前位置的主题名称。
|
||||||
|
- vgId:[入参] 虚拟组 vgroup 的 ID。
|
||||||
|
- **返回值**:`>=0`:成功,返回一个 int64_t 类型的值,表示当前位置的偏移量。`<0`:失败,返回值就是错误码,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_offset_seek(ws_tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset)`
|
||||||
|
- **接口说明**:将 TMQ 消费者对象在某个特定 topic 和 vgroup 的偏移量设置到指定的位置。
|
||||||
|
- tmq:[入参] 指向一个有效的 ws_tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
|
- pTopicName:[入参] 要查询当前位置的主题名称。
|
||||||
|
- vgId:[入参] 虚拟组 vgroup 的 ID。
|
||||||
|
- offset:[入参] 虚拟组 vgroup 的 ID。
|
||||||
|
- **返回值**:`0`:成功,非 `0`:失败,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int64_t ws_tmq_get_vgroup_offset(const WS_RES *rs)`
|
||||||
|
- **接口说明**:从 TMQ 消费者获取的消息结果中提取虚拟组(vgroup)的当前消费数据位置的偏移量。
|
||||||
|
- res:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了从 TMQ 消费者轮询得到的消息。
|
||||||
|
- **返回值**:`>=0`:成功,返回一个 int64_t 类型的值,表示当前消费位置的偏移量。`<0`:失败,返回值就是错误码,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `int32_t ws_tmq_get_vgroup_id(const WS_RES *rs)`
|
||||||
|
- **接口说明**:从 TMQ 消费者获取的消息结果中提取所属虚拟组(vgroup)的 ID。
|
||||||
|
- res:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了从 TMQ 消费者轮询得到的消息。
|
||||||
|
- **返回值**:`>=0`:成功,返回一个 int32_t 类型的值,表示虚拟组(vgroup)的 ID。`<0`:失败,返回值就是错误码,可调用函数 `ws_tmq_errstr(tmq)` 获取更详细的错误信息。
|
||||||
|
|
||||||
|
- `const char *ws_tmq_get_table_name(const WS_RES *rs)`
|
||||||
|
- **接口说明**:从 TMQ 消费者获取的消息结果中获取所属的表名。
|
||||||
|
- res:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了从 TMQ 消费者轮询得到的消息。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个 const char * 类型的指针,指向表名字符串。`NULL`:失败,非法的输入参数。
|
||||||
|
|
||||||
|
- `enum ws_tmq_res_t ws_tmq_get_res_type(const WS_RES *rs)`
|
||||||
|
- **接口说明**:从 TMQ 消费者获取的消息结果中获取消息类型。
|
||||||
|
- res:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了从 TMQ 消费者轮询得到的消息。
|
||||||
|
- **返回值**:返回一个 ws_tmq_res_t 类型的枚举值,表示消息类型。
|
||||||
|
- ws_tmq_res_t 表示消费到的数据类型,定义如下:
|
||||||
|
```
|
||||||
|
typedef enum ws_tmq_res_t {
|
||||||
|
WS_TMQ_RES_INVALID = -1, // 无效
|
||||||
|
WS_TMQ_RES_DATA = 1, // 数据类型
|
||||||
|
WS_TMQ_RES_TABLE_META = 2, // 元数据类型
|
||||||
|
WS_TMQ_RES_METADATA = 3 // 既有元数据类型又有数据类型,即自动建表
|
||||||
|
} tmq_res_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
- `const char *ws_tmq_get_topic_name(const WS_RES *rs)`
|
||||||
|
- **接口说明**:从 TMQ 消费者获取的消息结果中获取所属的 topic 名称。
|
||||||
|
- res:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了从 TMQ 消费者轮询得到的消息。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个 const char * 类型的指针,指向 topic 名称字符串。`NULL`:失败,非法的输入参数。
|
||||||
|
|
||||||
|
- `const char *ws_tmq_get_db_name(const WS_RES *rs)`
|
||||||
|
- **接口说明**:从 TMQ 消费者获取的消息结果中获取所属的数据库名称。
|
||||||
|
- res:[入参] 指向一个有效的 WS_RES 结构体指针,该结构体包含了从 TMQ 消费者轮询得到的消息。
|
||||||
|
- **返回值**:非 `NULL`:成功,返回一个 const char * 类型的指针,指向数据库名称字符串。`NULL`:失败,非法的输入参数。
|
||||||
|
|
||||||
|
## 原生连接方式
|
||||||
|
原生连接方式需要使用 taos.h 头文件和 taos 动态库。
|
||||||
```c
|
```c
|
||||||
#include <taos.h>
|
#include <taos.h>
|
||||||
```
|
```
|
||||||
|
@ -22,21 +629,21 @@ TDengine 客户端驱动的动态库位于:
|
||||||
- Windows: `C:\TDengine\taos.dll`
|
- Windows: `C:\TDengine\taos.dll`
|
||||||
- macOS: `/usr/local/lib/libtaos.dylib`
|
- macOS: `/usr/local/lib/libtaos.dylib`
|
||||||
|
|
||||||
## 支持的平台
|
### 支持的平台
|
||||||
|
|
||||||
请参考[支持的平台列表](../#支持的平台)
|
请参考[支持的平台列表](../#支持的平台)
|
||||||
|
|
||||||
## 支持的版本
|
### 支持的版本
|
||||||
|
|
||||||
TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一对应的强对应关系,建议使用与 TDengine 服务端完全相同的客户端驱动。虽然低版本的客户端驱动在前三段版本号一致(即仅第四段版本号不同)的情况下也能够与高版本的服务端相兼容,但这并非推荐用法。强烈不建议使用高版本的客户端驱动访问低版本的服务端。
|
TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一对应的强对应关系,建议使用与 TDengine 服务端完全相同的客户端驱动。虽然低版本的客户端驱动在前三段版本号一致(即仅第四段版本号不同)的情况下也能够与高版本的服务端相兼容,但这并非推荐用法。强烈不建议使用高版本的客户端驱动访问低版本的服务端。
|
||||||
|
|
||||||
## 错误码
|
### 错误码
|
||||||
|
|
||||||
在 C 接口的设计中,错误码采用整数类型表示,每个错误码都对应一个特定的错误状态。如未特别说明,当 API 的返回值是整数时,_0_ 代表成功,其它是代表失败原因的错误码,当返回值是指针时, _NULL_ 表示失败。
|
在 C 接口的设计中,错误码采用整数类型表示,每个错误码都对应一个特定的错误状态。如未特别说明,当 API 的返回值是整数时,_0_ 代表成功,其它是代表失败原因的错误码,当返回值是指针时, _NULL_ 表示失败。
|
||||||
所有的错误码以及对应的原因描述在 `taoserror.h` 文件中。
|
所有的错误码以及对应的原因描述在 `taoserror.h` 文件中。
|
||||||
详细的错误码说明参考:[错误码](../../../reference/error-code)
|
详细的错误码说明参考:[错误码](../../../reference/error-code)
|
||||||
|
|
||||||
## 示例程序
|
### 示例程序
|
||||||
|
|
||||||
本节展示了使用客户端驱动访问 TDengine 集群的常见访问方式的示例代码。
|
本节展示了使用客户端驱动访问 TDengine 集群的常见访问方式的示例代码。
|
||||||
|
|
||||||
|
@ -57,11 +664,11 @@ TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## API 参考
|
### API 参考
|
||||||
|
|
||||||
以下分别介绍 TDengine 客户端驱动的基础 API、同步 API、异步 API、订阅 API 和无模式写入 API。
|
以下分别介绍 TDengine 客户端驱动的基础 API、同步 API、异步 API、参数绑定 API,无模式写入 API 和数据订阅 API。
|
||||||
|
|
||||||
### 基础 API
|
#### 基础 API
|
||||||
|
|
||||||
基础 API 用于完成创建数据库连接等工作,为其它 API 的执行提供运行时环境。
|
基础 API 用于完成创建数据库连接等工作,为其它 API 的执行提供运行时环境。
|
||||||
|
|
||||||
|
@ -145,7 +752,7 @@ TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一
|
||||||
- **参数说明**:
|
- **参数说明**:
|
||||||
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `taos_connect()` 函数建立。
|
- taos:[入参] 指向数据库连接的指针,数据库连接是通过 `taos_connect()` 函数建立。
|
||||||
|
|
||||||
### 同步查询
|
#### 同步查询
|
||||||
|
|
||||||
本小节介绍 API 均属于同步接口。应用调用后,会阻塞等待响应,直到获得返回结果或错误信息。
|
本小节介绍 API 均属于同步接口。应用调用后,会阻塞等待响应,直到获得返回结果或错误信息。
|
||||||
|
|
||||||
|
@ -228,7 +835,7 @@ TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### 异步查询
|
#### 异步查询
|
||||||
|
|
||||||
TDengine 还提供性能更高的异步 API 处理数据插入、查询操作。在软硬件环境相同的情况下,异步 API 处理数据插入的速度比同步 API 快 2 ~ 4 倍。异步 API 采用非阻塞式的调用方式,在系统真正完成某个具体数据库操作前,立即返回。调用的线程可以去处理其他工作,从而可以提升整个应用的性能。异步 API 在网络延迟严重的情况下,优势尤为突出。
|
TDengine 还提供性能更高的异步 API 处理数据插入、查询操作。在软硬件环境相同的情况下,异步 API 处理数据插入的速度比同步 API 快 2 ~ 4 倍。异步 API 采用非阻塞式的调用方式,在系统真正完成某个具体数据库操作前,立即返回。调用的线程可以去处理其他工作,从而可以提升整个应用的性能。异步 API 在网络延迟严重的情况下,优势尤为突出。
|
||||||
|
|
||||||
|
@ -252,7 +859,7 @@ TDengine 还提供性能更高的异步 API 处理数据插入、查询操作。
|
||||||
|
|
||||||
TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多线程同时打开多张表,并可以同时对每张打开的表进行查询或者插入操作。需要指出的是,**客户端应用必须确保对同一张表的操作完全串行化**,即对同一个表的插入或查询操作未完成时(未返回时),不能够执行第二个插入或查询操作。
|
TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多线程同时打开多张表,并可以同时对每张打开的表进行查询或者插入操作。需要指出的是,**客户端应用必须确保对同一张表的操作完全串行化**,即对同一个表的插入或查询操作未完成时(未返回时),不能够执行第二个插入或查询操作。
|
||||||
|
|
||||||
### 参数绑定
|
#### 参数绑定
|
||||||
|
|
||||||
除了直接调用 `taos_query()` 进行查询,TDengine 也提供了支持参数绑定的 Prepare API,风格与 MySQL 类似,目前也仅支持用问号 `?` 来代表待绑定的参数。
|
除了直接调用 `taos_query()` 进行查询,TDengine 也提供了支持参数绑定的 Prepare API,风格与 MySQL 类似,目前也仅支持用问号 `?` 来代表待绑定的参数。
|
||||||
|
|
||||||
|
@ -350,7 +957,7 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多
|
||||||
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
- stmt:[入参] 指向一个有效的预编译的 SQL 语句对象指针。
|
||||||
- **返回值**:返回一个指向包含错误信息的字符串的指针。
|
- **返回值**:返回一个指向包含错误信息的字符串的指针。
|
||||||
|
|
||||||
### 无模式写入
|
#### 无模式写入
|
||||||
|
|
||||||
除了使用 SQL 方式或者使用参数绑定 API 写入数据外,还可以使用 Schemaless 的方式完成写入。Schemaless 可以免于预先创建超级表/数据子表的数据结构,而是可以直接写入数据,TDengine 系统会根据写入的数据内容自动创建和维护所需要的表结构。Schemaless 的使用方式详见 [Schemaless 写入](../../../develop/schemaless/) 章节,这里介绍与之配套使用的 C/C++ API。
|
除了使用 SQL 方式或者使用参数绑定 API 写入数据外,还可以使用 Schemaless 的方式完成写入。Schemaless 可以免于预先创建超级表/数据子表的数据结构,而是可以直接写入数据,TDengine 系统会根据写入的数据内容自动创建和维护所需要的表结构。Schemaless 的使用方式详见 [Schemaless 写入](../../../develop/schemaless/) 章节,这里介绍与之配套使用的 C/C++ API。
|
||||||
|
|
||||||
|
@ -474,7 +1081,7 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多
|
||||||
- 带_ttl的接口可以传递ttl参数来控制建表的ttl到期时间。
|
- 带_ttl的接口可以传递ttl参数来控制建表的ttl到期时间。
|
||||||
- 带_reqid的接口可以通过传递reqid参数来追踪整个的调用链。
|
- 带_reqid的接口可以通过传递reqid参数来追踪整个的调用链。
|
||||||
|
|
||||||
### 数据订阅
|
#### 数据订阅
|
||||||
- `const char *tmq_err2str(int32_t code)`
|
- `const char *tmq_err2str(int32_t code)`
|
||||||
- **接口说明**:用于将数据订阅的错误码转换为错误信息。
|
- **接口说明**:用于将数据订阅的错误码转换为错误信息。
|
||||||
- code:[入参] 数据订阅的错误码。
|
- code:[入参] 数据订阅的错误码。
|
||||||
|
@ -584,7 +1191,7 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多
|
||||||
- **接口说明**:获取 TMQ 消费者对象对特定 topic 和 vgroup 的已提交偏移量。
|
- **接口说明**:获取 TMQ 消费者对象对特定 topic 和 vgroup 的已提交偏移量。
|
||||||
- tmq:[入参] 指向一个有效的 tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
- tmq:[入参] 指向一个有效的 tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
- pTopicName:[入参] 要查询已提交偏移量的主题名称。
|
- pTopicName:[入参] 要查询已提交偏移量的主题名称。
|
||||||
- assignment:[入参] vgroup 的 ID。
|
- vgId:[入参] vgroup 的 ID。
|
||||||
- **返回值**:`>=0`:成功,返回一个 int64_t 类型的值,表示已提交的偏移量。`<0`:失败,返回值就是错误码,可调用函数 `char *tmq_err2str(int32_t code)` 获取更详细的错误信息。
|
- **返回值**:`>=0`:成功,返回一个 int64_t 类型的值,表示已提交的偏移量。`<0`:失败,返回值就是错误码,可调用函数 `char *tmq_err2str(int32_t code)` 获取更详细的错误信息。
|
||||||
|
|
||||||
- `int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg)`
|
- `int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg)`
|
||||||
|
@ -604,6 +1211,8 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多
|
||||||
- **接口说明**:同步提交 TMQ 消费者对象的特定主题和 vgroup 的偏移量。
|
- **接口说明**:同步提交 TMQ 消费者对象的特定主题和 vgroup 的偏移量。
|
||||||
- tmq:[入参] 指向一个有效的 tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
- tmq:[入参] 指向一个有效的 tmq_t 结构体指针,该结构体代表一个 TMQ 消费者对象。
|
||||||
- pTopicName:[入参] 要提交偏移量的主题名称。
|
- pTopicName:[入参] 要提交偏移量的主题名称。
|
||||||
|
- vgId:[入参] 虚拟组 vgroup 的 ID。
|
||||||
|
- offset:[入参] 要提交的偏移量。
|
||||||
- **返回值**:`0`:成功,已经成功提交偏移量。非 `0`:失败,可调用函数 `char *tmq_err2str(int32_t code)` 获取更详细的错误信息。
|
- **返回值**:`0`:成功,已经成功提交偏移量。非 `0`:失败,可调用函数 `char *tmq_err2str(int32_t code)` 获取更详细的错误信息。
|
||||||
|
|
||||||
- `void tmq_commit_offset_async(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset, tmq_commit_cb *cb, void *param)`
|
- `void tmq_commit_offset_async(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset, tmq_commit_cb *cb, void *param)`
|
||||||
|
|
|
@ -113,11 +113,11 @@ DSN 描述字符串基本结构如下:
|
||||||
各部分意义见下表:
|
各部分意义见下表:
|
||||||
|
|
||||||
- **driver**: 必须指定驱动名以便连接器选择何种方式创建连接,支持如下驱动名:
|
- **driver**: 必须指定驱动名以便连接器选择何种方式创建连接,支持如下驱动名:
|
||||||
- **taos**: 表名使用 TDengine 连接器驱动。
|
- **taos**: 使用 TDengine 连接器驱动,默认是使用 taos 驱动。
|
||||||
- **tmq**: 使用 TMQ 订阅数据。
|
- **tmq**: 使用 TMQ 订阅数据。
|
||||||
|
- **protocol**: 显示指定以何种方式建立连接,例如:`taos+ws://localhost:6041` 指定以 Websocket 方式建立连接。
|
||||||
- **http/ws**: 使用 Websocket 创建连接。
|
- **http/ws**: 使用 Websocket 创建连接。
|
||||||
- **https/wss**: 在 Websocket 连接方式下显示启用 SSL/TLS 连接。
|
- **https/wss**: 在 Websocket 连接方式下显示启用 SSL/TLS 连接。
|
||||||
- **protocol**: 显示指定以何种方式建立连接,例如:`taos+ws://localhost:6041` 指定以 Websocket 方式建立连接。
|
|
||||||
- **username/password**: 用于创建连接的用户名及密码。
|
- **username/password**: 用于创建连接的用户名及密码。
|
||||||
- **host/port**: 指定创建连接的服务器及端口,当不指定服务器地址及端口时(`taos://`),原生连接默认为 `localhost:6030`,Websocket 连接默认为 `localhost:6041` 。
|
- **host/port**: 指定创建连接的服务器及端口,当不指定服务器地址及端口时(`taos://`),原生连接默认为 `localhost:6030`,Websocket 连接默认为 `localhost:6041` 。
|
||||||
- **database**: 指定默认连接的数据库名,可选参数。
|
- **database**: 指定默认连接的数据库名,可选参数。
|
||||||
|
@ -522,6 +522,6 @@ Offset 结构体提供了获取当前消息所属的数据库,主题和分区
|
||||||
|
|
||||||
## 附录
|
## 附录
|
||||||
- Rust 连接器文档:https://docs.rs/taos
|
- Rust 连接器文档:https://docs.rs/taos
|
||||||
- Rust 连接器项目地址: https://github.com/taosdata/rust-connector-taos
|
- Rust 连接器项目地址: https://github.com/taosdata/taos-connector-rust
|
||||||
- deadpool 连接池: https://crates.io/crates/deadpool
|
- deadpool 连接池: https://crates.io/crates/deadpool
|
||||||
- r2d2 连接池: https://crates.io/crates/r2d2
|
- r2d2 连接池: https://crates.io/crates/r2d2
|
||||||
|
|
|
@ -85,8 +85,6 @@ Node.js 连接器目前仅支持 Websocket 连接器, 其通过 taosAdapter
|
||||||
| [sql_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/sql_example.js) | 基本的使用如如建立连接,执行 SQL 等操作。 |
|
| [sql_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/sql_example.js) | 基本的使用如如建立连接,执行 SQL 等操作。 |
|
||||||
| [stmt_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/stmt_example.js) | 绑定参数插入的示例。 | |
|
| [stmt_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/stmt_example.js) | 绑定参数插入的示例。 | |
|
||||||
| [line_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/line_example.js) | 行协议写入示例。 |
|
| [line_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/line_example.js) | 行协议写入示例。 |
|
||||||
| [telnet_line_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/telnet_line_example.js) | OpenTSDB Telnet 行协议写入示例。 |
|
|
||||||
| [json_line_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/json_line_example.js) | OpenTSDB JSON 行协议写入示例。 |
|
|
||||||
| [tmq_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/tmq_example.js) | 订阅的使用示例。 |
|
| [tmq_example](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/tmq_example.js) | 订阅的使用示例。 |
|
||||||
| [all_type_query](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/all_type_query.js) | 支持全部类型示例。 |
|
| [all_type_query](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/all_type_query.js) | 支持全部类型示例。 |
|
||||||
| [all_type_stmt](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/all_type_stmt.js) | 参数绑定支持全部类型示例。 |
|
| [all_type_stmt](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/all_type_stmt.js) | 参数绑定支持全部类型示例。 |
|
||||||
|
|
|
@ -28,14 +28,14 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
|
||||||
|
|
||||||
TDengine 版本更新往往会增加新的功能特性,列表中的连接器版本为连接器最佳适配版本。
|
TDengine 版本更新往往会增加新的功能特性,列表中的连接器版本为连接器最佳适配版本。
|
||||||
|
|
||||||
| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** |
|
| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | **C/C++** |
|
||||||
| ---------------------- | ----------- | ------------------------------------------- | ------------ | ------------- | --------------- | -------- |
|
| ---------------------- | ----------- | ------------------------------------------- | ------------ | ------------- | --------------- | -------- | -------------------- |
|
||||||
| **3.3.0.0 及以上** | 3.3.0及以上 | taospy 2.7.15及以上,taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 |
|
| **3.3.0.0 及以上** | 3.3.0及以上 | taospy 2.7.15及以上,taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 | 与 TDengine 相同版本 |
|
||||||
| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 |
|
| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 | 与 TDengine 相同版本 |
|
||||||
| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
|
| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | 与 TDengine 相同版本 |
|
||||||
| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
|
| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | 与 TDengine 相同版本 |
|
||||||
| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 |
|
| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | 与 TDengine 相同版本 |
|
||||||
| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 |
|
| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | 与 TDengine 相同版本 |
|
||||||
|
|
||||||
## 功能特性
|
## 功能特性
|
||||||
|
|
||||||
|
@ -43,13 +43,13 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
|
||||||
|
|
||||||
### 使用原生接口(taosc)
|
### 使用原生接口(taosc)
|
||||||
|
|
||||||
| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Rust** |
|
| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Rust** | **C/C++** |
|
||||||
| ------------------- | -------- | ---------- | ------ | ------ | -------- |
|
| ------------------- | -------- | ---------- | ------ | ------ | -------- | --------- |
|
||||||
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **执行 SQL** | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **执行 SQL** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **无模式写入** | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **无模式写入** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
|
|
||||||
:::info
|
:::info
|
||||||
由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。
|
由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。
|
||||||
|
@ -64,13 +64,13 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
|
||||||
|
|
||||||
### 使用 Websocket 接口
|
### 使用 Websocket 接口
|
||||||
|
|
||||||
| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** |
|
| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | **C/C++** |
|
||||||
| ------------------- | -------- | ---------- | ------ | ------ | ----------- | -------- |
|
| ------------------- | -------- | ---------- | ------ | ------ | ----------- | -------- | --------- |
|
||||||
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **执行 SQL** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **执行 SQL** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
| **无模式写入** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
| **无模式写入** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
- 无论选用何种编程语言的连接器,2.0 及以上版本的 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池,以避免连接内的“USE statement”状态量在线程之间相互干扰(但连接的查询和写入操作都是线程安全的)。
|
- 无论选用何种编程语言的连接器,2.0 及以上版本的 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池,以避免连接内的“USE statement”状态量在线程之间相互干扰(但连接的查询和写入操作都是线程安全的)。
|
||||||
|
|
|
@ -7,11 +7,11 @@ description: "TDengine 服务端、客户端和连接器支持的平台列表"
|
||||||
## TDengine 服务端支持的平台列表
|
## TDengine 服务端支持的平台列表
|
||||||
|
|
||||||
| | **Windows server 2016/2019** | **Windows 10/11** | **CentOS 7.9/8** | **Ubuntu 18 以上** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** | **macOS** |
|
| | **Windows server 2016/2019** | **Windows 10/11** | **CentOS 7.9/8** | **Ubuntu 18 以上** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** | **macOS** |
|
||||||
| ------------ | ---------------------------- | ----------------- | ---------------- | ---------------- | ------------ | ----------------- | ---------------- | --------- |
|
| ------------ | ---------------------------- | ----------------- | ---------------- | ------------------ | ------------ | ----------------- | ---------------- | --------- |
|
||||||
| X64 | ●/E | ●/E | ● | ● | ●/E | ●/E | ●/E | ● |
|
| X64 | ●/E | ●/E | ● | ● | ●/E | ●/E | ●/E | ● |
|
||||||
| 树莓派 ARM64 | | | ● | | | | | |
|
| 树莓派 ARM64 | | | ● | | | | | |
|
||||||
| 华为云 ARM64 | | | | ● | | | | |
|
| 华为云 ARM64 | | | | ● | | | | |
|
||||||
| M1 | | | | | | | | ● |
|
| M1 | | | | | | | | ● |
|
||||||
|
|
||||||
注:1) ● 表示经过官方测试验证, ○ 表示非官方测试验证,E 表示仅企业版支持。
|
注:1) ● 表示经过官方测试验证, ○ 表示非官方测试验证,E 表示仅企业版支持。
|
||||||
2) 社区版仅支持主流操作系统的较新版本,包括 Ubuntu 18+/CentOS 7+/RedHat/Debian/CoreOS/FreeBSD/OpenSUSE/SUSE Linux/Fedora/macOS 等。如果有其他操作系统及版本的需求,请联系企业版支持。
|
2) 社区版仅支持主流操作系统的较新版本,包括 Ubuntu 18+/CentOS 7+/RedHat/Debian/CoreOS/FreeBSD/OpenSUSE/SUSE Linux/Fedora/macOS 等。如果有其他操作系统及版本的需求,请联系企业版支持。
|
||||||
|
@ -31,6 +31,7 @@ description: "TDengine 服务端、客户端和连接器支持的平台列表"
|
||||||
| **Go** | ● | ● | ● | ● | ● |
|
| **Go** | ● | ● | ● | ● | ● |
|
||||||
| **NodeJs** | ● | ● | ● | ○ | ○ |
|
| **NodeJs** | ● | ● | ● | ○ | ○ |
|
||||||
| **C#** | ● | ● | ○ | ○ | ○ |
|
| **C#** | ● | ● | ○ | ○ | ○ |
|
||||||
|
| **Rust** | ● | ● | ○ | ● | ● |
|
||||||
| **RESTful** | ● | ● | ● | ● | ● |
|
| **RESTful** | ● | ● | ● | ● | ● |
|
||||||
|
|
||||||
注:● 表示官方测试验证通过,○ 表示非官方测试验证通过,-- 表示未经验证。
|
注:● 表示官方测试验证通过,○ 表示非官方测试验证通过,-- 表示未经验证。
|
||||||
|
|
|
@ -32,7 +32,6 @@ extern int32_t tsS3PageCacheSize;
|
||||||
extern int32_t tsS3UploadDelaySec;
|
extern int32_t tsS3UploadDelaySec;
|
||||||
|
|
||||||
int32_t s3Init();
|
int32_t s3Init();
|
||||||
void s3CleanUp();
|
|
||||||
int32_t s3CheckCfg();
|
int32_t s3CheckCfg();
|
||||||
int32_t s3PutObjectFromFile(const char *file, const char *object);
|
int32_t s3PutObjectFromFile(const char *file, const char *object);
|
||||||
int32_t s3PutObjectFromFile2(const char *file, const char *object, int8_t withcp);
|
int32_t s3PutObjectFromFile2(const char *file, const char *object, int8_t withcp);
|
||||||
|
|
|
@ -153,7 +153,6 @@ char *tTagValToData(const STagVal *pTagVal, bool isJson);
|
||||||
int32_t tEncodeTag(SEncoder *pEncoder, const STag *pTag);
|
int32_t tEncodeTag(SEncoder *pEncoder, const STag *pTag);
|
||||||
int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag);
|
int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag);
|
||||||
int32_t tTagToValArray(const STag *pTag, SArray **ppArray);
|
int32_t tTagToValArray(const STag *pTag, SArray **ppArray);
|
||||||
void tTagSetCid(const STag *pTag, int16_t iTag, int16_t cid);
|
|
||||||
void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remove
|
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 parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, void *pMsgBuf);
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,9 @@ extern taos_collector_registry_t *TAOS_COLLECTOR_REGISTRY_DEFAULT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the default collector registry and enables metric collection on the executing process
|
* @brief Initializes the default collector registry and enables metric collection on the executing process
|
||||||
* @return A non-zero integer value upon failure
|
* @return
|
||||||
*/
|
*/
|
||||||
int taos_collector_registry_default_init(void);
|
void taos_collector_registry_default_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a taos_collector_registry_t*
|
* @brief Constructs a taos_collector_registry_t*
|
||||||
|
|
|
@ -76,7 +76,6 @@ typedef int (*__compar_fn_t)(const void *, const void *);
|
||||||
|
|
||||||
char *strsep(char **stringp, const char *delim);
|
char *strsep(char **stringp, const char *delim);
|
||||||
char *getpass(const char *prefix);
|
char *getpass(const char *prefix);
|
||||||
char *strndup(const char *s, int n);
|
|
||||||
|
|
||||||
// for send function in tsocket.c
|
// for send function in tsocket.c
|
||||||
#define MSG_NOSIGNAL 0
|
#define MSG_NOSIGNAL 0
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef enum { M2C = 0, C2M } ConvType;
|
||||||
#define strtod STR_TO_LD_FUNC_TAOS_FORBID
|
#define strtod STR_TO_LD_FUNC_TAOS_FORBID
|
||||||
#define strtold STR_TO_D_FUNC_TAOS_FORBID
|
#define strtold STR_TO_D_FUNC_TAOS_FORBID
|
||||||
#define strtof STR_TO_F_FUNC_TAOS_FORBID
|
#define strtof STR_TO_F_FUNC_TAOS_FORBID
|
||||||
|
#define strndup STR_TO_F_FUNC_TAOS_FORBID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tstrncpy(dst, src, size) \
|
#define tstrncpy(dst, src, size) \
|
||||||
|
@ -101,8 +102,9 @@ int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix);
|
||||||
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix);
|
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix);
|
||||||
double taosStr2Double(const char *str, char **pEnd);
|
double taosStr2Double(const char *str, char **pEnd);
|
||||||
float taosStr2Float(const char *str, char **pEnd);
|
float taosStr2Float(const char *str, char **pEnd);
|
||||||
int32_t taosHex2Ascii(const char *z, uint32_t n, void** data, uint32_t* size);
|
int32_t taosHex2Ascii(const char *z, uint32_t n, void **data, uint32_t *size);
|
||||||
int32_t taosAscii2Hex(const char *z, uint32_t n, void** data, uint32_t* size);
|
int32_t taosAscii2Hex(const char *z, uint32_t n, void **data, uint32_t *size);
|
||||||
|
char *taosStrndup(const char *s, int n);
|
||||||
//int32_t taosBin2Ascii(const char *z, uint32_t n, void** data, uint32_t* size);
|
//int32_t taosBin2Ascii(const char *z, uint32_t n, void** data, uint32_t* size);
|
||||||
bool isHex(const char* z, uint32_t n);
|
bool isHex(const char* z, uint32_t n);
|
||||||
bool isValidateHex(const char* z, uint32_t n);
|
bool isValidateHex(const char* z, uint32_t n);
|
||||||
|
|
|
@ -72,8 +72,8 @@ extern "C" {
|
||||||
#ifdef TD_TSZ
|
#ifdef TD_TSZ
|
||||||
extern bool lossyFloat;
|
extern bool lossyFloat;
|
||||||
extern bool lossyDouble;
|
extern bool lossyDouble;
|
||||||
int32_t tsCompressInit(char *lossyColumns, float fPrecision, double dPrecision, uint32_t maxIntervals,
|
void tsCompressInit(char *lossyColumns, float fPrecision, double dPrecision, uint32_t maxIntervals, uint32_t intervals,
|
||||||
uint32_t intervals, int32_t ifAdtFse, const char *compressor);
|
int32_t ifAdtFse, const char *compressor);
|
||||||
|
|
||||||
void tsCompressExit();
|
void tsCompressExit();
|
||||||
|
|
||||||
|
@ -153,11 +153,10 @@ int32_t tsDecompressBigint(void *pIn, int32_t nIn, int32_t nEle, void *pOut, int
|
||||||
int32_t getWordLength(char type);
|
int32_t getWordLength(char type);
|
||||||
|
|
||||||
int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements, char *const output, const char type);
|
int32_t tsDecompressIntImpl_Hw(const char *const input, const int32_t nelements, char *const output, const char type);
|
||||||
int32_t tsDecompressFloatImplAvx512(const char *const input, const int32_t nelements, char *const output);
|
void tsDecompressFloatImplAvx512(const char *const input, const int32_t nelements, char *const output);
|
||||||
int32_t tsDecompressFloatImplAvx2(const char *const input, const int32_t nelements, char *const output);
|
void tsDecompressFloatImplAvx2(const char *const input, const int32_t nelements, char *const output);
|
||||||
int32_t tsDecompressTimestampAvx512(const char *const input, const int32_t nelements, char *const output,
|
void tsDecompressTimestampAvx512(const char *const input, const int32_t nelements, char *const output, bool bigEndian);
|
||||||
bool bigEndian);
|
void tsDecompressTimestampAvx2(const char *const input, const int32_t nelements, char *const output, bool bigEndian);
|
||||||
int32_t tsDecompressTimestampAvx2(const char *const input, const int32_t nelements, char *const output, bool bigEndian);
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* REGULAR COMPRESSION 2
|
* REGULAR COMPRESSION 2
|
||||||
|
|
|
@ -116,23 +116,14 @@ function install_bin() {
|
||||||
${csudo}cp -r ${script_dir}/bin/* ${install_main_dir}/bin && ${csudo}chmod 0555 ${install_main_dir}/bin/*
|
${csudo}cp -r ${script_dir}/bin/* ${install_main_dir}/bin && ${csudo}chmod 0555 ${install_main_dir}/bin/*
|
||||||
|
|
||||||
#Make link
|
#Make link
|
||||||
[ -x ${install_main_dir}/bin/${clientName} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName} ${bin_link_dir}/${clientName} || :
|
[ -x ${install_main_dir}/bin/${clientName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName2} ${bin_link_dir}/${clientName2} || :
|
||||||
if [ "$osType" != "Darwin" ]; then
|
if [ "$osType" != "Darwin" ]; then
|
||||||
[ -x ${install_main_dir}/bin/${demoName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${demoName2} ${bin_link_dir}/${demoName2} || :
|
[ -x ${install_main_dir}/bin/${demoName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${demoName2} ${bin_link_dir}/${demoName2} || :
|
||||||
fi
|
fi
|
||||||
[ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/${uninstallScript} || :
|
[ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/${uninstallScript} || :
|
||||||
[ -x ${install_main_dir}/bin/set_core.sh ] && ${csudo}ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || :
|
[ -x ${install_main_dir}/bin/set_core.sh ] && ${csudo}ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || :
|
||||||
|
[ -x ${install_main_dir}/bin/${benchmarkName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${benchmarkName2} ${bin_link_dir}/${benchmarkName2} || :
|
||||||
if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then
|
[ -x ${install_main_dir}/bin/${dumpName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${dumpName2} ${bin_link_dir}/${dumpName2} || :
|
||||||
#Make link
|
|
||||||
[ -x ${install_main_dir}/bin/${clientName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName2} ${bin_link_dir}/${clientName2} || :
|
|
||||||
if [ "$osType" != "Darwin" ]; then
|
|
||||||
[ -x ${install_main_dir}/bin/${demoName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${demoName2} ${bin_link_dir}/${demoName2} || :
|
|
||||||
[ -x ${install_main_dir}/bin/${benchmarkName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${benchmarkName2} ${bin_link_dir}/${benchmarkName2} || :
|
|
||||||
[ -x ${install_main_dir}/bin/${dumpName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${dumpName2} ${bin_link_dir}/${dumpName2} || :
|
|
||||||
fi
|
|
||||||
[ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo}ln -sf ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/${uninstallScript2} || :
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clean_lib() {
|
function clean_lib() {
|
||||||
|
|
|
@ -26,10 +26,10 @@ extern "C" {
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "taos.h"
|
#include "taos.h"
|
||||||
#include "tcommon.h"
|
#include "tcommon.h"
|
||||||
#include "tmisce.h"
|
|
||||||
#include "tdef.h"
|
#include "tdef.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "tlist.h"
|
#include "tlist.h"
|
||||||
|
#include "tmisce.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
#include "tmsgtype.h"
|
#include "tmsgtype.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
|
@ -86,7 +86,7 @@ typedef struct {
|
||||||
int8_t threadStop;
|
int8_t threadStop;
|
||||||
int8_t quitByKill;
|
int8_t quitByKill;
|
||||||
TdThread thread;
|
TdThread thread;
|
||||||
TdThreadMutex lock; // used when app init and cleanup
|
TdThreadMutex lock; // used when app init and cleanup
|
||||||
SHashObj* appSummary;
|
SHashObj* appSummary;
|
||||||
SHashObj* appHbHash; // key: clusterId
|
SHashObj* appHbHash; // key: clusterId
|
||||||
SArray* appHbMgrs; // SArray<SAppHbMgr*> one for each cluster
|
SArray* appHbMgrs; // SArray<SAppHbMgr*> one for each cluster
|
||||||
|
@ -95,11 +95,11 @@ typedef struct {
|
||||||
} SClientHbMgr;
|
} SClientHbMgr;
|
||||||
|
|
||||||
typedef struct SQueryExecMetric {
|
typedef struct SQueryExecMetric {
|
||||||
int64_t start; // start timestamp, us
|
int64_t start; // start timestamp, us
|
||||||
int64_t ctgStart; // start to parse, us
|
int64_t ctgStart; // start to parse, us
|
||||||
int64_t execStart; // start to parse, us
|
int64_t execStart; // start to parse, us
|
||||||
|
|
||||||
int64_t parseCostUs;
|
int64_t parseCostUs;
|
||||||
int64_t ctgCostUs;
|
int64_t ctgCostUs;
|
||||||
int64_t analyseCostUs;
|
int64_t analyseCostUs;
|
||||||
int64_t planCostUs;
|
int64_t planCostUs;
|
||||||
|
@ -193,7 +193,7 @@ typedef struct SReqResultInfo {
|
||||||
char** convertBuf;
|
char** convertBuf;
|
||||||
TAOS_ROW row;
|
TAOS_ROW row;
|
||||||
SResultColumn* pCol;
|
SResultColumn* pCol;
|
||||||
uint64_t numOfRows; // from int32_t change to int64_t
|
uint64_t numOfRows; // from int32_t change to int64_t
|
||||||
uint64_t totalRows;
|
uint64_t totalRows;
|
||||||
uint64_t current;
|
uint64_t current;
|
||||||
bool localResultFetched;
|
bool localResultFetched;
|
||||||
|
@ -319,12 +319,14 @@ void syncCatalogFn(SMetaData* pResult, void* param, int32_t code);
|
||||||
TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly, int8_t source);
|
TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly, int8_t source);
|
||||||
TAOS_RES* taosQueryImplWithReqid(TAOS* taos, const char* sql, bool validateOnly, int64_t reqid);
|
TAOS_RES* taosQueryImplWithReqid(TAOS* taos, const char* sql, bool validateOnly, int64_t reqid);
|
||||||
|
|
||||||
void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly, int8_t source);
|
void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly,
|
||||||
|
int8_t source);
|
||||||
void taosAsyncQueryImplWithReqid(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly,
|
void taosAsyncQueryImplWithReqid(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly,
|
||||||
int64_t reqid);
|
int64_t reqid);
|
||||||
void taosAsyncFetchImpl(SRequestObj *pRequest, __taos_async_fn_t fp, void *param);
|
void taosAsyncFetchImpl(SRequestObj* pRequest, __taos_async_fn_t fp, void* param);
|
||||||
int32_t clientParseSql(void* param, const char* dbName, const char* sql, bool parseOnly, const char* effectiveUser, SParseSqlRes* pRes);
|
int32_t clientParseSql(void* param, const char* dbName, const char* sql, bool parseOnly, const char* effectiveUser,
|
||||||
void syncQueryFn(void* param, void* res, int32_t code);
|
SParseSqlRes* pRes);
|
||||||
|
void syncQueryFn(void* param, void* res, int32_t code);
|
||||||
|
|
||||||
int32_t getVersion1BlockMetaSize(const char* p, int32_t numOfCols);
|
int32_t getVersion1BlockMetaSize(const char* p, int32_t numOfCols);
|
||||||
|
|
||||||
|
@ -333,7 +335,7 @@ static FORCE_INLINE SReqResultInfo* tmqGetCurResInfo(TAOS_RES* res) {
|
||||||
return (SReqResultInfo*)&msg->common.resInfo;
|
return (SReqResultInfo*)&msg->common.resInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4, SReqResultInfo** pResInfo);
|
int32_t tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4, SReqResultInfo** pResInfo);
|
||||||
static FORCE_INLINE SReqResultInfo* tscGetCurResInfo(TAOS_RES* res) {
|
static FORCE_INLINE SReqResultInfo* tscGetCurResInfo(TAOS_RES* res) {
|
||||||
if (TD_RES_QUERY(res)) return &(((SRequestObj*)res)->body.resInfo);
|
if (TD_RES_QUERY(res)) return &(((SRequestObj*)res)->body.resInfo);
|
||||||
return tmqGetCurResInfo(res);
|
return tmqGetCurResInfo(res);
|
||||||
|
@ -349,8 +351,8 @@ __async_send_cb_fn_t getMsgRspHandle(int32_t msgType);
|
||||||
|
|
||||||
SMsgSendInfo* buildMsgInfoImpl(SRequestObj* pReqObj);
|
SMsgSendInfo* buildMsgInfoImpl(SRequestObj* pReqObj);
|
||||||
|
|
||||||
int32_t createTscObj(const char *user, const char *auth, const char *db, int32_t connType, SAppInstInfo *pAppInfo,
|
int32_t createTscObj(const char* user, const char* auth, const char* db, int32_t connType, SAppInstInfo* pAppInfo,
|
||||||
STscObj **p);
|
STscObj** p);
|
||||||
void destroyTscObj(void* pObj);
|
void destroyTscObj(void* pObj);
|
||||||
STscObj* acquireTscObj(int64_t rid);
|
STscObj* acquireTscObj(int64_t rid);
|
||||||
void releaseTscObj(int64_t rid);
|
void releaseTscObj(int64_t rid);
|
||||||
|
@ -358,7 +360,7 @@ void destroyAppInst(void* pAppInfo);
|
||||||
|
|
||||||
uint64_t generateRequestId();
|
uint64_t generateRequestId();
|
||||||
|
|
||||||
int32_t createRequest(uint64_t connId, int32_t type, int64_t reqid, SRequestObj **pRequest);
|
int32_t createRequest(uint64_t connId, int32_t type, int64_t reqid, SRequestObj** pRequest);
|
||||||
void destroyRequest(SRequestObj* pRequest);
|
void destroyRequest(SRequestObj* pRequest);
|
||||||
SRequestObj* acquireRequest(int64_t rid);
|
SRequestObj* acquireRequest(int64_t rid);
|
||||||
int32_t releaseRequest(int64_t rid);
|
int32_t releaseRequest(int64_t rid);
|
||||||
|
@ -372,9 +374,9 @@ void resetConnectDB(STscObj* pTscObj);
|
||||||
|
|
||||||
int taos_options_imp(TSDB_OPTION option, const char* str);
|
int taos_options_imp(TSDB_OPTION option, const char* str);
|
||||||
|
|
||||||
int32_t openTransporter(const char* user, const char* auth, int32_t numOfThreads, void **pDnodeConn);
|
int32_t openTransporter(const char* user, const char* auth, int32_t numOfThreads, void** pDnodeConn);
|
||||||
void tscStopCrashReport();
|
void tscStopCrashReport();
|
||||||
void cleanupAppInfo();
|
void cleanupAppInfo();
|
||||||
|
|
||||||
typedef struct AsyncArg {
|
typedef struct AsyncArg {
|
||||||
SRpcMsg msg;
|
SRpcMsg msg;
|
||||||
|
@ -402,17 +404,17 @@ int32_t hbMgrInit();
|
||||||
void hbMgrCleanUp();
|
void hbMgrCleanUp();
|
||||||
|
|
||||||
// cluster level
|
// cluster level
|
||||||
int32_t appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key, SAppHbMgr **pAppHbMgr);
|
int32_t appHbMgrInit(SAppInstInfo* pAppInstInfo, char* key, SAppHbMgr** pAppHbMgr);
|
||||||
void appHbMgrCleanup(void);
|
void appHbMgrCleanup(void);
|
||||||
void hbRemoveAppHbMrg(SAppHbMgr** pAppHbMgr);
|
void hbRemoveAppHbMrg(SAppHbMgr** pAppHbMgr);
|
||||||
void destroyAllRequests(SHashObj* pRequests);
|
void destroyAllRequests(SHashObj* pRequests);
|
||||||
void stopAllRequests(SHashObj* pRequests);
|
void stopAllRequests(SHashObj* pRequests);
|
||||||
|
|
||||||
//SAppInstInfo* getAppInstInfo(const char* clusterKey);
|
// SAppInstInfo* getAppInstInfo(const char* clusterKey);
|
||||||
|
|
||||||
// conn level
|
// conn level
|
||||||
int32_t hbRegisterConn(SAppHbMgr* pAppHbMgr, int64_t tscRefId, int64_t clusterId, int8_t connType);
|
int32_t hbRegisterConn(SAppHbMgr* pAppHbMgr, int64_t tscRefId, int64_t clusterId, int8_t connType);
|
||||||
void hbDeregisterConn(STscObj* pTscObj, SClientHbKey connKey);
|
void hbDeregisterConn(STscObj* pTscObj, SClientHbKey connKey);
|
||||||
|
|
||||||
typedef struct SSqlCallbackWrapper {
|
typedef struct SSqlCallbackWrapper {
|
||||||
SParseContext* pParseCtx;
|
SParseContext* pParseCtx;
|
||||||
|
@ -421,9 +423,9 @@ typedef struct SSqlCallbackWrapper {
|
||||||
void* pPlanInfo;
|
void* pPlanInfo;
|
||||||
} SSqlCallbackWrapper;
|
} SSqlCallbackWrapper;
|
||||||
|
|
||||||
void setQueryRequest(int64_t rId);
|
void setQueryRequest(int64_t rId);
|
||||||
SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQuery, void** res);
|
void launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQuery, void** res);
|
||||||
int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList);
|
int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList);
|
||||||
void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultMeta, SSqlCallbackWrapper* pWrapper);
|
void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultMeta, SSqlCallbackWrapper* pWrapper);
|
||||||
int32_t refreshMeta(STscObj* pTscObj, SRequestObj* pRequest);
|
int32_t refreshMeta(STscObj* pTscObj, SRequestObj* pRequest);
|
||||||
int32_t updateQnodeList(SAppInstInfo* pInfo, SArray* pNodeList);
|
int32_t updateQnodeList(SAppInstInfo* pInfo, SArray* pNodeList);
|
||||||
|
@ -431,20 +433,21 @@ void doAsyncQuery(SRequestObj* pRequest, bool forceUpdateMeta);
|
||||||
int32_t removeMeta(STscObj* pTscObj, SArray* tbList, bool isView);
|
int32_t removeMeta(STscObj* pTscObj, SArray* tbList, bool isView);
|
||||||
int32_t handleAlterTbExecRes(void* res, struct SCatalog* pCatalog);
|
int32_t handleAlterTbExecRes(void* res, struct SCatalog* pCatalog);
|
||||||
int32_t handleCreateTbExecRes(void* res, SCatalog* pCatalog);
|
int32_t handleCreateTbExecRes(void* res, SCatalog* pCatalog);
|
||||||
int32_t qnodeRequired(SRequestObj* pRequest, bool *required);
|
int32_t qnodeRequired(SRequestObj* pRequest, bool* required);
|
||||||
void continueInsertFromCsv(SSqlCallbackWrapper* pWrapper, SRequestObj* pRequest);
|
void continueInsertFromCsv(SSqlCallbackWrapper* pWrapper, SRequestObj* pRequest);
|
||||||
void destorySqlCallbackWrapper(SSqlCallbackWrapper* pWrapper);
|
void destorySqlCallbackWrapper(SSqlCallbackWrapper* pWrapper);
|
||||||
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code);
|
void handleQueryAnslyseRes(SSqlCallbackWrapper* pWrapper, SMetaData* pResultMeta, int32_t code);
|
||||||
void restartAsyncQuery(SRequestObj *pRequest, int32_t code);
|
void restartAsyncQuery(SRequestObj* pRequest, int32_t code);
|
||||||
int32_t buildPreviousRequest(SRequestObj *pRequest, const char* sql, SRequestObj** pNewRequest);
|
int32_t buildPreviousRequest(SRequestObj* pRequest, const char* sql, SRequestObj** pNewRequest);
|
||||||
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce);
|
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper** ppWrapper, SRequestObj* pRequest, bool updateMetaForce);
|
||||||
void returnToUser(SRequestObj* pRequest);
|
void returnToUser(SRequestObj* pRequest);
|
||||||
void stopAllQueries(SRequestObj *pRequest);
|
void stopAllQueries(SRequestObj* pRequest);
|
||||||
void doRequestCallback(SRequestObj* pRequest, int32_t code);
|
void doRequestCallback(SRequestObj* pRequest, int32_t code);
|
||||||
void freeQueryParam(SSyncQueryParam* param);
|
void freeQueryParam(SSyncQueryParam* param);
|
||||||
|
|
||||||
#ifdef TD_ENTERPRISE
|
#ifdef TD_ENTERPRISE
|
||||||
int32_t clientParseSqlImpl(void* param, const char* dbName, const char* sql, bool parseOnly, const char* effeciveUser, SParseSqlRes* pRes);
|
int32_t clientParseSqlImpl(void* param, const char* dbName, const char* sql, bool parseOnly, const char* effeciveUser,
|
||||||
|
SParseSqlRes* pRes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TSC_ERR_RET(c) \
|
#define TSC_ERR_RET(c) \
|
||||||
|
@ -474,13 +477,9 @@ int32_t clientParseSqlImpl(void* param, const char* dbName, const char* sql, boo
|
||||||
|
|
||||||
void slowQueryLog(int64_t rid, bool killed, int32_t code, int32_t cost);
|
void slowQueryLog(int64_t rid, bool killed, int32_t code, int32_t cost);
|
||||||
|
|
||||||
enum {
|
enum { MONITORSQLTYPESELECT = 0, MONITORSQLTYPEINSERT = 1, MONITORSQLTYPEDELETE = 2 };
|
||||||
MONITORSQLTYPESELECT = 0,
|
|
||||||
MONITORSQLTYPEINSERT = 1,
|
|
||||||
MONITORSQLTYPEDELETE = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
void sqlReqLog(int64_t rid, bool killed, int32_t code, int8_t type);
|
void sqlReqLog(int64_t rid, bool killed, int32_t code, int8_t type);
|
||||||
|
|
||||||
void tmqMgmtClose(void);
|
void tmqMgmtClose(void);
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,12 @@ static int32_t generateWriteSlowLog(STscObj *pTscObj, SRequestObj *pRequest, int
|
||||||
ENV_JSON_FALSE_CHECK(cJSON_AddItemToObject(json, "db", cJSON_CreateString("")));
|
ENV_JSON_FALSE_CHECK(cJSON_AddItemToObject(json, "db", cJSON_CreateString("")));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *value = cJSON_PrintUnformatted(json);
|
char *value = cJSON_PrintUnformatted(json);
|
||||||
|
if (value == NULL) {
|
||||||
|
tscError("failed to print json");
|
||||||
|
code = TSDB_CODE_FAILED;
|
||||||
|
goto _end;
|
||||||
|
}
|
||||||
MonitorSlowLogData data = {0};
|
MonitorSlowLogData data = {0};
|
||||||
data.clusterId = pTscObj->pAppInfo->clusterId;
|
data.clusterId = pTscObj->pAppInfo->clusterId;
|
||||||
data.type = SLOW_LOG_WRITE;
|
data.type = SLOW_LOG_WRITE;
|
||||||
|
|
|
@ -679,9 +679,15 @@ _return:
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void freeVgList(void* list) {
|
||||||
|
SArray* pList = *(SArray**)list;
|
||||||
|
taosArrayDestroy(pList);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray* pMnodeList, SMetaData* pResultMeta) {
|
int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray* pMnodeList, SMetaData* pResultMeta) {
|
||||||
SArray* pDbVgList = NULL;
|
SArray* pDbVgList = NULL;
|
||||||
SArray* pQnodeList = NULL;
|
SArray* pQnodeList = NULL;
|
||||||
|
FDelete fp = NULL;
|
||||||
int32_t code = 0;
|
int32_t code = 0;
|
||||||
|
|
||||||
switch (tsQueryPolicy) {
|
switch (tsQueryPolicy) {
|
||||||
|
@ -705,6 +711,43 @@ int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray
|
||||||
goto _return;
|
goto _return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fp = freeVgList;
|
||||||
|
|
||||||
|
int32_t dbNum = taosArrayGetSize(pRequest->dbList);
|
||||||
|
if (dbNum > 0) {
|
||||||
|
SCatalog* pCtg = NULL;
|
||||||
|
SAppInstInfo* pInst = pRequest->pTscObj->pAppInfo;
|
||||||
|
code = catalogGetHandle(pInst->clusterId, &pCtg);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pDbVgList = taosArrayInit(dbNum, POINTER_BYTES);
|
||||||
|
if (NULL == pDbVgList) {
|
||||||
|
code = terrno;
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
SArray* pVgList = NULL;
|
||||||
|
for (int32_t i = 0; i < dbNum; ++i) {
|
||||||
|
char* dbFName = taosArrayGet(pRequest->dbList, i);
|
||||||
|
SRequestConnInfo conn = {.pTrans = pInst->pTransporter,
|
||||||
|
.requestId = pRequest->requestId,
|
||||||
|
.requestObjRefId = pRequest->self,
|
||||||
|
.mgmtEps = getEpSet_s(&pInst->mgmtEp)};
|
||||||
|
|
||||||
|
// catalogGetDBVgList will handle dbFName == null.
|
||||||
|
code = catalogGetDBVgList(pCtg, &conn, dbFName, &pVgList);
|
||||||
|
if (code) {
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == taosArrayPush(pDbVgList, &pVgList)) {
|
||||||
|
code = terrno;
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
code = buildVnodePolicyNodeList(pRequest, pNodeList, pMnodeList, pDbVgList);
|
code = buildVnodePolicyNodeList(pRequest, pNodeList, pMnodeList, pDbVgList);
|
||||||
|
@ -745,17 +788,12 @@ int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray
|
||||||
}
|
}
|
||||||
|
|
||||||
_return:
|
_return:
|
||||||
taosArrayDestroy(pDbVgList);
|
taosArrayDestroyEx(pDbVgList, fp);
|
||||||
taosArrayDestroy(pQnodeList);
|
taosArrayDestroy(pQnodeList);
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeVgList(void* list) {
|
|
||||||
SArray* pList = *(SArray**)list;
|
|
||||||
taosArrayDestroy(pList);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t buildSyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray* pMnodeList) {
|
int32_t buildSyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray* pMnodeList) {
|
||||||
SArray* pDbVgList = NULL;
|
SArray* pDbVgList = NULL;
|
||||||
SArray* pQnodeList = NULL;
|
SArray* pQnodeList = NULL;
|
||||||
|
@ -1211,7 +1249,7 @@ void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQuery, void** res) {
|
void launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQuery, void** res) {
|
||||||
int32_t code = 0;
|
int32_t code = 0;
|
||||||
|
|
||||||
if (pQuery->pRoot) {
|
if (pQuery->pRoot) {
|
||||||
|
@ -1297,8 +1335,6 @@ SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQue
|
||||||
*res = pRequest->body.resInfo.execRes.res;
|
*res = pRequest->body.resInfo.execRes.res;
|
||||||
pRequest->body.resInfo.execRes.res = NULL;
|
pRequest->body.resInfo.execRes.res = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pRequest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultMeta,
|
static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultMeta,
|
||||||
|
@ -2405,10 +2441,9 @@ char* getDbOfConnection(STscObj* pObj) {
|
||||||
(void)taosThreadMutexLock(&pObj->mutex);
|
(void)taosThreadMutexLock(&pObj->mutex);
|
||||||
size_t len = strlen(pObj->db);
|
size_t len = strlen(pObj->db);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
p = strndup(pObj->db, tListLen(pObj->db));
|
p = taosStrndup(pObj->db, tListLen(pObj->db));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
tscError("failed to strndup db name");
|
tscError("failed to taosStrndup db name");
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2896,8 +2931,8 @@ TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly, int8_t s
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
code = tsem_destroy(¶m->sem);
|
code = tsem_destroy(¶m->sem);
|
||||||
if(TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
tscError("failed to destroy semaphore since %s", tstrerror(code));
|
tscError("failed to destroy semaphore since %s", tstrerror(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
SRequestObj* pRequest = NULL;
|
SRequestObj* pRequest = NULL;
|
||||||
|
|
|
@ -1316,9 +1316,9 @@ void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
|
||||||
tscDebug("0x%" PRIx64 " client retry to handle the error, code:%d - %s, tryCount:%d,QID:0x%" PRIx64,
|
tscDebug("0x%" PRIx64 " client retry to handle the error, code:%d - %s, tryCount:%d,QID:0x%" PRIx64,
|
||||||
pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
|
pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
|
||||||
code = refreshMeta(pRequest->pTscObj, pRequest);
|
code = refreshMeta(pRequest->pTscObj, pRequest);
|
||||||
if (code != 0){
|
if (code != 0) {
|
||||||
tscWarn("0x%" PRIx64 " refresh meta failed, code:%d - %s,QID:0x%" PRIx64, pRequest->self, code,
|
tscWarn("0x%" PRIx64 " refresh meta failed, code:%d - %s,QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
|
||||||
tstrerror(code), pRequest->requestId);
|
pRequest->requestId);
|
||||||
}
|
}
|
||||||
pRequest->prevCode = code;
|
pRequest->prevCode = code;
|
||||||
doAsyncQuery(pRequest, true);
|
doAsyncQuery(pRequest, true);
|
||||||
|
@ -1985,7 +1985,9 @@ int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col
|
||||||
|
|
||||||
STscStmt2 *pStmt = (STscStmt2 *)stmt;
|
STscStmt2 *pStmt = (STscStmt2 *)stmt;
|
||||||
if (pStmt->options.asyncExecFn && !pStmt->semWaited) {
|
if (pStmt->options.asyncExecFn && !pStmt->semWaited) {
|
||||||
(void)tsem_wait(&pStmt->asyncQuerySem);
|
if (tsem_wait(&pStmt->asyncQuerySem) != 0) {
|
||||||
|
tscError("wait async query sem failed");
|
||||||
|
}
|
||||||
pStmt->semWaited = true;
|
pStmt->semWaited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -447,20 +447,19 @@ static char* readFile(TdFilePtr pFile, int64_t* offset, int64_t size) {
|
||||||
char* pCont = NULL;
|
char* pCont = NULL;
|
||||||
int64_t totalSize = 0;
|
int64_t totalSize = 0;
|
||||||
if (size - *offset >= SLOW_LOG_SEND_SIZE_MAX) {
|
if (size - *offset >= SLOW_LOG_SEND_SIZE_MAX) {
|
||||||
pCont = taosMemoryCalloc(1, 4 + SLOW_LOG_SEND_SIZE_MAX); // 4 reserved for []
|
|
||||||
totalSize = 4 + SLOW_LOG_SEND_SIZE_MAX;
|
totalSize = 4 + SLOW_LOG_SEND_SIZE_MAX;
|
||||||
} else {
|
} else {
|
||||||
pCont = taosMemoryCalloc(1, 4 + (size - *offset));
|
|
||||||
totalSize = 4 + (size - *offset);
|
totalSize = 4 + (size - *offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pCont = taosMemoryCalloc(1, totalSize); // 4 reserved for []
|
||||||
if (pCont == NULL) {
|
if (pCont == NULL) {
|
||||||
tscError("failed to allocate memory for slow log, size:%" PRId64, totalSize);
|
tscError("failed to allocate memory for slow log, size:%" PRId64, totalSize);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char* buf = pCont;
|
char* buf = pCont;
|
||||||
(void)strcat(buf++, "[");
|
(void)strcat(buf++, "[");
|
||||||
int64_t readSize = taosReadFile(pFile, buf, SLOW_LOG_SEND_SIZE_MAX);
|
int64_t readSize = taosReadFile(pFile, buf, totalSize - 4); // 4 reserved for []
|
||||||
if (readSize <= 0) {
|
if (readSize <= 0) {
|
||||||
if (readSize < 0) {
|
if (readSize < 0) {
|
||||||
tscError("failed to read len from file:%p since %s", pFile, terrstr());
|
tscError("failed to read len from file:%p since %s", pFile, terrstr());
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#define RAW_NULL_CHECK(c) \
|
#define RAW_NULL_CHECK(c) \
|
||||||
do { \
|
do { \
|
||||||
if (c == NULL) { \
|
if (c == NULL) { \
|
||||||
code = TSDB_CODE_OUT_OF_MEMORY; \
|
code = terrno; \
|
||||||
goto end; \
|
goto end; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -394,7 +394,7 @@ static void buildChildElement(cJSON* json, SVCreateTbReq* pCreateReq) {
|
||||||
uint8_t tagNum = pCreateReq->ctb.tagNum;
|
uint8_t tagNum = pCreateReq->ctb.tagNum;
|
||||||
int32_t code = 0;
|
int32_t code = 0;
|
||||||
cJSON* tags = NULL;
|
cJSON* tags = NULL;
|
||||||
cJSON* tableName = cJSON_CreateString(name);
|
cJSON* tableName = cJSON_CreateString(name);
|
||||||
RAW_NULL_CHECK(tableName);
|
RAW_NULL_CHECK(tableName);
|
||||||
RAW_FALSE_CHECK(cJSON_AddItemToObject(json, "tableName", tableName));
|
RAW_FALSE_CHECK(cJSON_AddItemToObject(json, "tableName", tableName));
|
||||||
cJSON* using = cJSON_CreateString(sname);
|
cJSON* using = cJSON_CreateString(sname);
|
||||||
|
@ -417,7 +417,7 @@ static void buildChildElement(cJSON* json, SVCreateTbReq* pCreateReq) {
|
||||||
}
|
}
|
||||||
char* pJson = NULL;
|
char* pJson = NULL;
|
||||||
parseTagDatatoJson(pTag, &pJson);
|
parseTagDatatoJson(pTag, &pJson);
|
||||||
if(pJson == NULL) {
|
if (pJson == NULL) {
|
||||||
uError("parseTagDatatoJson failed, pJson == NULL");
|
uError("parseTagDatatoJson failed, pJson == NULL");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -731,7 +731,7 @@ static void processAlterTable(SMqMetaRsp* metaRsp, cJSON** pJson) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
parseTagDatatoJson(vAlterTbReq.pTagVal, &buf);
|
parseTagDatatoJson(vAlterTbReq.pTagVal, &buf);
|
||||||
if(buf == NULL) {
|
if (buf == NULL) {
|
||||||
uError("parseTagDatatoJson failed, buf == NULL");
|
uError("parseTagDatatoJson failed, buf == NULL");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -978,7 +978,7 @@ static int32_t taosCreateStb(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
pQuery.msgType = pQuery.pCmdMsg->msgType;
|
pQuery.msgType = pQuery.pCmdMsg->msgType;
|
||||||
pQuery.stableQuery = true;
|
pQuery.stableQuery = true;
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, &pQuery, true, NULL); // ignore, because return value is pRequest
|
launchQueryImpl(pRequest, &pQuery, true, NULL); // ignore, because return value is pRequest
|
||||||
|
|
||||||
taosMemoryFree(pCmdMsg.pMsg);
|
taosMemoryFree(pCmdMsg.pMsg);
|
||||||
|
|
||||||
|
@ -1082,7 +1082,7 @@ static int32_t taosDropStb(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
pQuery.msgType = pQuery.pCmdMsg->msgType;
|
pQuery.msgType = pQuery.pCmdMsg->msgType;
|
||||||
pQuery.stableQuery = true;
|
pQuery.stableQuery = true;
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, &pQuery, true, NULL); // ignore, because return value is pRequest
|
launchQueryImpl(pRequest, &pQuery, true, NULL); // ignore, because return value is pRequest
|
||||||
taosMemoryFree(pCmdMsg.pMsg);
|
taosMemoryFree(pCmdMsg.pMsg);
|
||||||
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
||||||
// ignore the error code
|
// ignore the error code
|
||||||
|
@ -1120,7 +1120,8 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
SRequestObj* pRequest = NULL;
|
SRequestObj* pRequest = NULL;
|
||||||
SQuery* pQuery = NULL;
|
SQuery* pQuery = NULL;
|
||||||
SHashObj* pVgroupHashmap = NULL;
|
SHashObj* pVgroupHashmap = NULL;
|
||||||
|
SArray* pTagList = taosArrayInit(0, POINTER_BYTES);
|
||||||
|
RAW_NULL_CHECK(pTagList);
|
||||||
RAW_RETURN_CHECK(buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0));
|
RAW_RETURN_CHECK(buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0));
|
||||||
uDebug(LOG_ID_TAG " create table, meta:%p, metaLen:%d", LOG_ID_VALUE, meta, metaLen);
|
uDebug(LOG_ID_TAG " create table, meta:%p, metaLen:%d", LOG_ID_VALUE, meta, metaLen);
|
||||||
|
|
||||||
|
@ -1186,6 +1187,14 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
}
|
}
|
||||||
pCreateReq->ctb.suid = pTableMeta->uid;
|
pCreateReq->ctb.suid = pTableMeta->uid;
|
||||||
|
|
||||||
|
SArray* pTagVals = NULL;
|
||||||
|
code = tTagToValArray((STag *)pCreateReq->ctb.pTag, &pTagVals);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
taosMemoryFreeClear(pTableMeta);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rebuildTag = false;
|
||||||
for (int32_t i = 0; i < taosArrayGetSize(pCreateReq->ctb.tagName); i++) {
|
for (int32_t i = 0; i < taosArrayGetSize(pCreateReq->ctb.tagName); i++) {
|
||||||
char* tName = taosArrayGet(pCreateReq->ctb.tagName, i);
|
char* tName = taosArrayGet(pCreateReq->ctb.tagName, i);
|
||||||
if (tName == NULL) {
|
if (tName == NULL) {
|
||||||
|
@ -1195,11 +1204,34 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
j < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; j++) {
|
j < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; j++) {
|
||||||
SSchema* tag = &pTableMeta->schema[j];
|
SSchema* tag = &pTableMeta->schema[j];
|
||||||
if (strcmp(tag->name, tName) == 0 && tag->type != TSDB_DATA_TYPE_JSON) {
|
if (strcmp(tag->name, tName) == 0 && tag->type != TSDB_DATA_TYPE_JSON) {
|
||||||
tTagSetCid((STag*)pCreateReq->ctb.pTag, i, tag->colId);
|
STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, i);
|
||||||
|
if (pTagVal) {
|
||||||
|
if (pTagVal->cid != tag->colId){
|
||||||
|
pTagVal->cid = tag->colId;
|
||||||
|
rebuildTag = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uError("create tb invalid data %s, size:%d index:%d cid:%d", pCreateReq->name, (int)taosArrayGetSize(pTagVals), i, tag->colId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taosMemoryFreeClear(pTableMeta);
|
taosMemoryFreeClear(pTableMeta);
|
||||||
|
if (rebuildTag){
|
||||||
|
STag* ppTag = NULL;
|
||||||
|
code = tTagNew(pTagVals, 1, false, &ppTag);
|
||||||
|
taosArrayDestroy(pTagVals);
|
||||||
|
pTagVals = NULL;
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (NULL == taosArrayPush(pTagList, &ppTag)) {
|
||||||
|
tTagFree(ppTag);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
pCreateReq->ctb.pTag = (uint8_t*)ppTag;
|
||||||
|
}
|
||||||
|
taosArrayDestroy(pTagVals);
|
||||||
}
|
}
|
||||||
RAW_NULL_CHECK(taosArrayPush(pRequest->tableList, &pName));
|
RAW_NULL_CHECK(taosArrayPush(pRequest->tableList, &pName));
|
||||||
|
|
||||||
|
@ -1236,7 +1268,7 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
|
|
||||||
RAW_RETURN_CHECK(rewriteToVnodeModifyOpStmt(pQuery, pBufArray));
|
RAW_RETURN_CHECK(rewriteToVnodeModifyOpStmt(pQuery, pBufArray));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
||||||
RAW_RETURN_CHECK(removeMeta(pTscObj, pRequest->tableList, false));
|
RAW_RETURN_CHECK(removeMeta(pTscObj, pRequest->tableList, false));
|
||||||
}
|
}
|
||||||
|
@ -1251,6 +1283,7 @@ end:
|
||||||
destroyRequest(pRequest);
|
destroyRequest(pRequest);
|
||||||
tDecoderClear(&coder);
|
tDecoderClear(&coder);
|
||||||
qDestroyQuery(pQuery);
|
qDestroyQuery(pQuery);
|
||||||
|
taosArrayDestroyP(pTagList, taosMemoryFree);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,7 +1398,7 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
if (TSDB_CODE_SUCCESS != code) goto end;
|
if (TSDB_CODE_SUCCESS != code) goto end;
|
||||||
RAW_RETURN_CHECK(rewriteToVnodeModifyOpStmt(pQuery, pBufArray));
|
RAW_RETURN_CHECK(rewriteToVnodeModifyOpStmt(pQuery, pBufArray));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
||||||
RAW_RETURN_CHECK(removeMeta(pTscObj, pRequest->tableList, false));
|
RAW_RETURN_CHECK(removeMeta(pTscObj, pRequest->tableList, false));
|
||||||
}
|
}
|
||||||
|
@ -1510,7 +1543,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) {
|
||||||
if (TSDB_CODE_SUCCESS != code) goto end;
|
if (TSDB_CODE_SUCCESS != code) goto end;
|
||||||
RAW_RETURN_CHECK(rewriteToVnodeModifyOpStmt(pQuery, pArray));
|
RAW_RETURN_CHECK(rewriteToVnodeModifyOpStmt(pQuery, pArray));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
|
|
||||||
pVgData = NULL;
|
pVgData = NULL;
|
||||||
pArray = NULL;
|
pArray = NULL;
|
||||||
|
@ -1587,7 +1620,7 @@ int taos_write_raw_block_with_fields_with_reqid(TAOS* taos, int rows, char* pDat
|
||||||
RAW_RETURN_CHECK(rawBlockBindData(pQuery, pTableMeta, pData, NULL, fields, numFields, false, NULL, 0));
|
RAW_RETURN_CHECK(rawBlockBindData(pQuery, pTableMeta, pData, NULL, fields, numFields, false, NULL, 0));
|
||||||
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
code = pRequest->code;
|
code = pRequest->code;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -1647,7 +1680,7 @@ int taos_write_raw_block_with_reqid(TAOS* taos, int rows, char* pData, const cha
|
||||||
RAW_RETURN_CHECK(rawBlockBindData(pQuery, pTableMeta, pData, NULL, NULL, 0, false, NULL, 0));
|
RAW_RETURN_CHECK(rawBlockBindData(pQuery, pTableMeta, pData, NULL, NULL, 0, false, NULL, 0));
|
||||||
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
code = pRequest->code;
|
code = pRequest->code;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -1766,7 +1799,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) {
|
||||||
|
|
||||||
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
code = pRequest->code;
|
code = pRequest->code;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -1780,6 +1813,42 @@ end:
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t buildCreateTbMap(STaosxRsp* rsp, SHashObj* pHashObj) {
|
||||||
|
// find schema data info
|
||||||
|
int32_t code = 0;
|
||||||
|
SVCreateTbReq pCreateReq = {0};
|
||||||
|
SDecoder decoderTmp = {0};
|
||||||
|
|
||||||
|
for (int j = 0; j < rsp->createTableNum; j++) {
|
||||||
|
void** dataTmp = taosArrayGet(rsp->createTableReq, j);
|
||||||
|
RAW_NULL_CHECK(dataTmp);
|
||||||
|
int32_t* lenTmp = taosArrayGet(rsp->createTableLen, j);
|
||||||
|
RAW_NULL_CHECK(lenTmp);
|
||||||
|
|
||||||
|
tDecoderInit(&decoderTmp, *dataTmp, *lenTmp);
|
||||||
|
RAW_RETURN_CHECK (tDecodeSVCreateTbReq(&decoderTmp, &pCreateReq));
|
||||||
|
|
||||||
|
if (pCreateReq.type != TSDB_CHILD_TABLE) {
|
||||||
|
code = TSDB_CODE_INVALID_MSG;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (taosHashGet(pHashObj, pCreateReq.name, strlen(pCreateReq.name)) == NULL){
|
||||||
|
RAW_RETURN_CHECK(taosHashPut(pHashObj, pCreateReq.name, strlen(pCreateReq.name), &pCreateReq, sizeof(SVCreateTbReq)));
|
||||||
|
} else{
|
||||||
|
tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE);
|
||||||
|
pCreateReq = (SVCreateTbReq){0};
|
||||||
|
}
|
||||||
|
|
||||||
|
tDecoderClear(&decoderTmp);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
tDecoderClear(&decoderTmp);
|
||||||
|
tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) {
|
static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) {
|
||||||
if (taos == NULL || data == NULL) {
|
if (taos == NULL || data == NULL) {
|
||||||
SET_ERROR_MSG("taos:%p or data:%p is NULL", taos, data);
|
SET_ERROR_MSG("taos:%p or data:%p is NULL", taos, data);
|
||||||
|
@ -1791,7 +1860,7 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen)
|
||||||
SMqTaosxRspObj rspObj = {0};
|
SMqTaosxRspObj rspObj = {0};
|
||||||
SDecoder decoder = {0};
|
SDecoder decoder = {0};
|
||||||
STableMeta* pTableMeta = NULL;
|
STableMeta* pTableMeta = NULL;
|
||||||
SVCreateTbReq* pCreateReqDst = NULL;
|
SHashObj* pCreateTbHash = NULL;
|
||||||
|
|
||||||
SRequestObj* pRequest = NULL;
|
SRequestObj* pRequest = NULL;
|
||||||
RAW_RETURN_CHECK(createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0, &pRequest));
|
RAW_RETURN_CHECK(createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0, &pRequest));
|
||||||
|
@ -1832,6 +1901,9 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen)
|
||||||
RAW_RETURN_CHECK(smlInitHandle(&pQuery));
|
RAW_RETURN_CHECK(smlInitHandle(&pQuery));
|
||||||
pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
|
pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
|
||||||
RAW_NULL_CHECK(pVgHash);
|
RAW_NULL_CHECK(pVgHash);
|
||||||
|
pCreateTbHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
||||||
|
RAW_NULL_CHECK(pCreateTbHash);
|
||||||
|
RAW_RETURN_CHECK(buildCreateTbMap(&rspObj.rsp, pCreateTbHash));
|
||||||
|
|
||||||
uDebug(LOG_ID_TAG " write raw metadata block num:%d", LOG_ID_VALUE, rspObj.rsp.common.blockNum);
|
uDebug(LOG_ID_TAG " write raw metadata block num:%d", LOG_ID_VALUE, rspObj.rsp.common.blockNum);
|
||||||
while (++rspObj.common.resIter < rspObj.rsp.common.blockNum) {
|
while (++rspObj.common.resIter < rspObj.rsp.common.blockNum) {
|
||||||
|
@ -1854,40 +1926,7 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen)
|
||||||
(void)strcpy(pName.tname, tbName);
|
(void)strcpy(pName.tname, tbName);
|
||||||
|
|
||||||
// find schema data info
|
// find schema data info
|
||||||
for (int j = 0; j < rspObj.rsp.createTableNum; j++) {
|
SVCreateTbReq* pCreateReqDst = (SVCreateTbReq*)taosHashGet(pCreateTbHash, tbName, strlen(tbName));
|
||||||
void** dataTmp = taosArrayGet(rspObj.rsp.createTableReq, j);
|
|
||||||
RAW_NULL_CHECK(dataTmp);
|
|
||||||
int32_t* lenTmp = taosArrayGet(rspObj.rsp.createTableLen, j);
|
|
||||||
RAW_NULL_CHECK(dataTmp);
|
|
||||||
|
|
||||||
SDecoder decoderTmp = {0};
|
|
||||||
SVCreateTbReq pCreateReq = {0};
|
|
||||||
tDecoderInit(&decoderTmp, *dataTmp, *lenTmp);
|
|
||||||
if (tDecodeSVCreateTbReq(&decoderTmp, &pCreateReq) < 0) {
|
|
||||||
tDecoderClear(&decoderTmp);
|
|
||||||
tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE);
|
|
||||||
code = TSDB_CODE_TMQ_INVALID_MSG;
|
|
||||||
SET_ERROR_MSG("decode create table:%s req failed", tbName);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCreateReq.type != TSDB_CHILD_TABLE) {
|
|
||||||
code = TSDB_CODE_TSC_INVALID_VALUE;
|
|
||||||
tDecoderClear(&decoderTmp);
|
|
||||||
tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE);
|
|
||||||
SET_ERROR_MSG("create table req type is not child table: %s, type: %d", tbName, pCreateReq.type);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
if (strcmp(tbName, pCreateReq.name) == 0) {
|
|
||||||
RAW_RETURN_CHECK(cloneSVreateTbReq(&pCreateReq, &pCreateReqDst));
|
|
||||||
tDecoderClear(&decoderTmp);
|
|
||||||
tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tDecoderClear(&decoderTmp);
|
|
||||||
tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
SVgroupInfo vg = {0};
|
SVgroupInfo vg = {0};
|
||||||
RAW_RETURN_CHECK(catalogGetTableHashVgroup(pCatalog, &conn, &pName, &vg));
|
RAW_RETURN_CHECK(catalogGetTableHashVgroup(pCatalog, &conn, &pName, &vg));
|
||||||
if (pCreateReqDst) { // change stable name to get meta
|
if (pCreateReqDst) { // change stable name to get meta
|
||||||
|
@ -1920,13 +1959,17 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen)
|
||||||
}
|
}
|
||||||
void* rawData = getRawDataFromRes(pRetrieve);
|
void* rawData = getRawDataFromRes(pRetrieve);
|
||||||
char err[ERR_MSG_LEN] = {0};
|
char err[ERR_MSG_LEN] = {0};
|
||||||
code = rawBlockBindData(pQuery, pTableMeta, rawData, &pCreateReqDst, fields, pSW->nCols, true, err, ERR_MSG_LEN);
|
SVCreateTbReq* pCreateReqTmp = NULL;
|
||||||
|
if (pCreateReqDst){
|
||||||
|
RAW_RETURN_CHECK(cloneSVreateTbReq(pCreateReqDst, &pCreateReqTmp));
|
||||||
|
}
|
||||||
|
code = rawBlockBindData(pQuery, pTableMeta, rawData, &pCreateReqTmp, fields, pSW->nCols, true, err, ERR_MSG_LEN);
|
||||||
|
if (pCreateReqTmp != NULL) {
|
||||||
|
tdDestroySVCreateTbReq(pCreateReqTmp);
|
||||||
|
taosMemoryFree(pCreateReqTmp);
|
||||||
|
}
|
||||||
taosMemoryFree(fields);
|
taosMemoryFree(fields);
|
||||||
taosMemoryFreeClear(pTableMeta);
|
taosMemoryFreeClear(pTableMeta);
|
||||||
if (pCreateReqDst) {
|
|
||||||
tdDestroySVCreateTbReq(pCreateReqDst);
|
|
||||||
taosMemoryFreeClear(pCreateReqDst);
|
|
||||||
}
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
SET_ERROR_MSG("table:%s, err:%s", tbName, err);
|
SET_ERROR_MSG("table:%s, err:%s", tbName, err);
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -1935,21 +1978,23 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen)
|
||||||
|
|
||||||
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
RAW_RETURN_CHECK(smlBuildOutput(pQuery, pVgHash));
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, pQuery, true, NULL);
|
launchQueryImpl(pRequest, pQuery, true, NULL);
|
||||||
code = pRequest->code;
|
code = pRequest->code;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
uDebug(LOG_ID_TAG " write raw metadata return, msg:%s", LOG_ID_VALUE, tstrerror(code));
|
uDebug(LOG_ID_TAG " write raw metadata return, msg:%s", LOG_ID_VALUE, tstrerror(code));
|
||||||
|
void* pIter = taosHashIterate(pCreateTbHash, NULL);
|
||||||
|
while (pIter) {
|
||||||
|
tDestroySVCreateTbReq(pIter, TSDB_MSG_FLG_DECODE);
|
||||||
|
pIter = taosHashIterate(pCreateTbHash, pIter);
|
||||||
|
}
|
||||||
|
taosHashCleanup(pCreateTbHash);
|
||||||
tDeleteSTaosxRsp(&rspObj.rsp);
|
tDeleteSTaosxRsp(&rspObj.rsp);
|
||||||
tDecoderClear(&decoder);
|
tDecoderClear(&decoder);
|
||||||
qDestroyQuery(pQuery);
|
qDestroyQuery(pQuery);
|
||||||
destroyRequest(pRequest);
|
destroyRequest(pRequest);
|
||||||
taosHashCleanup(pVgHash);
|
taosHashCleanup(pVgHash);
|
||||||
taosMemoryFreeClear(pTableMeta);
|
taosMemoryFreeClear(pTableMeta);
|
||||||
if (pCreateReqDst) {
|
|
||||||
tdDestroySVCreateTbReq(pCreateReqDst);
|
|
||||||
taosMemoryFreeClear(pCreateReqDst);
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ static int32_t smlCheckAuth(SSmlHandle *info, SRequestConnInfo *conn, const char
|
||||||
SUserAuthInfo pAuth = {0};
|
SUserAuthInfo pAuth = {0};
|
||||||
(void)snprintf(pAuth.user, sizeof(pAuth.user), "%s", info->taos->user);
|
(void)snprintf(pAuth.user, sizeof(pAuth.user), "%s", info->taos->user);
|
||||||
if (NULL == pTabName) {
|
if (NULL == pTabName) {
|
||||||
if (tNameSetDbName(&pAuth.tbName, info->taos->acctId, info->pRequest->pDb, strlen(info->pRequest->pDb)) != 0){
|
if (tNameSetDbName(&pAuth.tbName, info->taos->acctId, info->pRequest->pDb, strlen(info->pRequest->pDb)) != 0) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -165,7 +165,7 @@ int64_t smlGetTimeValue(const char *value, int32_t len, uint8_t fromPrecision, u
|
||||||
return convertTimePrecision(tsInt64, fromPrecision, toPrecision);
|
return convertTimePrecision(tsInt64, fromPrecision, toPrecision);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t smlBuildTableInfo(int numRows, const char *measure, int32_t measureLen, SSmlTableInfo** tInfo) {
|
int32_t smlBuildTableInfo(int numRows, const char *measure, int32_t measureLen, SSmlTableInfo **tInfo) {
|
||||||
SSmlTableInfo *tag = (SSmlTableInfo *)taosMemoryCalloc(sizeof(SSmlTableInfo), 1);
|
SSmlTableInfo *tag = (SSmlTableInfo *)taosMemoryCalloc(sizeof(SSmlTableInfo), 1);
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
return terrno;
|
return terrno;
|
||||||
|
@ -203,13 +203,13 @@ static void smlDestroySTableMeta(void *para) {
|
||||||
taosMemoryFree(meta);
|
taosMemoryFree(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t smlBuildSuperTableInfo(SSmlHandle *info, SSmlLineInfo *currElement, SSmlSTableMeta** sMeta) {
|
int32_t smlBuildSuperTableInfo(SSmlHandle *info, SSmlLineInfo *currElement, SSmlSTableMeta **sMeta) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
char *measure = currElement->measure;
|
char *measure = currElement->measure;
|
||||||
int measureLen = currElement->measureLen;
|
int measureLen = currElement->measureLen;
|
||||||
if (currElement->measureEscaped) {
|
if (currElement->measureEscaped) {
|
||||||
measure = (char *)taosMemoryMalloc(measureLen);
|
measure = (char *)taosMemoryMalloc(measureLen);
|
||||||
if (measure == NULL){
|
if (measure == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
(void)memcpy(measure, currElement->measure, measureLen);
|
(void)memcpy(measure, currElement->measure, measureLen);
|
||||||
|
@ -233,7 +233,7 @@ int32_t smlBuildSuperTableInfo(SSmlHandle *info, SSmlLineInfo *currElement, SSml
|
||||||
}
|
}
|
||||||
(*sMeta)->tableMeta = pTableMeta;
|
(*sMeta)->tableMeta = pTableMeta;
|
||||||
code = taosHashPut(info->superTables, currElement->measure, currElement->measureLen, sMeta, POINTER_BYTES);
|
code = taosHashPut(info->superTables, currElement->measure, currElement->measureLen, sMeta, POINTER_BYTES);
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
smlDestroySTableMeta(*sMeta);
|
smlDestroySTableMeta(*sMeta);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -250,11 +250,11 @@ int32_t smlBuildSuperTableInfo(SSmlHandle *info, SSmlLineInfo *currElement, SSml
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < pTableMeta->tableInfo.numOfColumns) {
|
if (i < pTableMeta->tableInfo.numOfColumns) {
|
||||||
if(taosArrayPush((*sMeta)->cols, &kv) == NULL){
|
if (taosArrayPush((*sMeta)->cols, &kv) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(taosArrayPush((*sMeta)->tags, &kv) == NULL){
|
if (taosArrayPush((*sMeta)->tags, &kv) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ bool isSmlColAligned(SSmlHandle *info, int cnt, SSmlKv *kv) {
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxColKVs, cnt);
|
SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxColKVs, cnt);
|
||||||
if (maxKV == NULL){
|
if (maxKV == NULL) {
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
if (unlikely(!IS_SAME_KEY)) {
|
if (unlikely(!IS_SAME_KEY)) {
|
||||||
|
@ -336,9 +336,9 @@ int32_t smlJoinMeasureTag(SSmlLineInfo *elements) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool smlIsPKTable(STableMeta *pTableMeta){
|
static bool smlIsPKTable(STableMeta *pTableMeta) {
|
||||||
for(int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++){
|
for (int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) {
|
||||||
if(pTableMeta->schema[i].flags & COL_IS_KEY){
|
if (pTableMeta->schema[i].flags & COL_IS_KEY) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,14 +368,14 @@ int32_t smlProcessSuperTable(SSmlHandle *info, SSmlLineInfo *elements) {
|
||||||
info->maxTagKVs = sMeta->tags;
|
info->maxTagKVs = sMeta->tags;
|
||||||
info->maxColKVs = sMeta->cols;
|
info->maxColKVs = sMeta->cols;
|
||||||
|
|
||||||
if(smlIsPKTable(sMeta->tableMeta)){
|
if (smlIsPKTable(sMeta->tableMeta)) {
|
||||||
return TSDB_CODE_SML_NOT_SUPPORT_PK;
|
return TSDB_CODE_SML_NOT_SUPPORT_PK;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t smlProcessChildTable(SSmlHandle *info, SSmlLineInfo *elements) {
|
int32_t smlProcessChildTable(SSmlHandle *info, SSmlLineInfo *elements) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
SSmlTableInfo **oneTable =
|
SSmlTableInfo **oneTable =
|
||||||
(SSmlTableInfo **)taosHashGet(info->childTables, elements->measureTag, elements->measureTagsLen);
|
(SSmlTableInfo **)taosHashGet(info->childTables, elements->measureTag, elements->measureTagsLen);
|
||||||
SSmlTableInfo *tinfo = NULL;
|
SSmlTableInfo *tinfo = NULL;
|
||||||
|
@ -385,19 +385,19 @@ int32_t smlProcessChildTable(SSmlHandle *info, SSmlLineInfo *elements) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
code = taosHashPut(info->childTables, elements->measureTag, elements->measureTagsLen, &tinfo, POINTER_BYTES);
|
code = taosHashPut(info->childTables, elements->measureTag, elements->measureTagsLen, &tinfo, POINTER_BYTES);
|
||||||
if(code != 0){
|
if (code != 0) {
|
||||||
smlDestroyTableInfo(&tinfo);
|
smlDestroyTableInfo(&tinfo);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
tinfo->tags = taosArrayDup(info->preLineTagKV, NULL);
|
tinfo->tags = taosArrayDup(info->preLineTagKV, NULL);
|
||||||
if(tinfo->tags == NULL){
|
if (tinfo->tags == NULL) {
|
||||||
smlDestroyTableInfo(&tinfo);
|
smlDestroyTableInfo(&tinfo);
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < taosArrayGetSize(info->preLineTagKV); i++) {
|
for (size_t i = 0; i < taosArrayGetSize(info->preLineTagKV); i++) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(info->preLineTagKV, i);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(info->preLineTagKV, i);
|
||||||
if(kv == NULL){
|
if (kv == NULL) {
|
||||||
smlDestroyTableInfo(&tinfo);
|
smlDestroyTableInfo(&tinfo);
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
@ -406,12 +406,12 @@ int32_t smlProcessChildTable(SSmlHandle *info, SSmlLineInfo *elements) {
|
||||||
}
|
}
|
||||||
|
|
||||||
code = smlSetCTableName(tinfo, info->tbnameKey);
|
code = smlSetCTableName(tinfo, info->tbnameKey);
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
smlDestroyTableInfo(&tinfo);
|
smlDestroyTableInfo(&tinfo);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
code = getTableUid(info, elements, tinfo);
|
code = getTableUid(info, elements, tinfo);
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
smlDestroyTableInfo(&tinfo);
|
smlDestroyTableInfo(&tinfo);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -458,10 +458,10 @@ int32_t smlParseEndTelnetJson(SSmlHandle *info, SSmlLineInfo *elements, SSmlKv *
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (taosArrayPush(elements->colArray, kvTs) == NULL){
|
if (taosArrayPush(elements->colArray, kvTs) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
if (taosArrayPush(elements->colArray, kv) == NULL){
|
if (taosArrayPush(elements->colArray, kv) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,11 +495,11 @@ int32_t smlParseEndLine(SSmlHandle *info, SSmlLineInfo *elements, SSmlKv *kvTs)
|
||||||
static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnameKey) {
|
static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnameKey) {
|
||||||
bool autoChildName = false;
|
bool autoChildName = false;
|
||||||
size_t delimiter = strlen(tsSmlAutoChildTableNameDelimiter);
|
size_t delimiter = strlen(tsSmlAutoChildTableNameDelimiter);
|
||||||
if(delimiter > 0 && tbnameKey == NULL){
|
if (delimiter > 0 && tbnameKey == NULL) {
|
||||||
size_t totalNameLen = delimiter * (taosArrayGetSize(tags) - 1);
|
size_t totalNameLen = delimiter * (taosArrayGetSize(tags) - 1);
|
||||||
for (int i = 0; i < taosArrayGetSize(tags); i++) {
|
for (int i = 0; i < taosArrayGetSize(tags); i++) {
|
||||||
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
|
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
|
||||||
if(tag == NULL){
|
if (tag == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
totalNameLen += tag->length;
|
totalNameLen += tag->length;
|
||||||
|
@ -512,7 +512,7 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnam
|
||||||
(void)memset(childTableName, 0, TSDB_TABLE_NAME_LEN);
|
(void)memset(childTableName, 0, TSDB_TABLE_NAME_LEN);
|
||||||
for (int i = 0; i < taosArrayGetSize(tags); i++) {
|
for (int i = 0; i < taosArrayGetSize(tags); i++) {
|
||||||
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
|
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
|
||||||
if(tag == NULL){
|
if (tag == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
(void)strncat(childTableName, tag->value, tag->length);
|
(void)strncat(childTableName, tag->value, tag->length);
|
||||||
|
@ -523,8 +523,8 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnam
|
||||||
if (tsSmlDot2Underline) {
|
if (tsSmlDot2Underline) {
|
||||||
smlStrReplace(childTableName, strlen(childTableName));
|
smlStrReplace(childTableName, strlen(childTableName));
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
if (tbnameKey == NULL){
|
if (tbnameKey == NULL) {
|
||||||
tbnameKey = tsSmlChildTableName;
|
tbnameKey = tsSmlChildTableName;
|
||||||
}
|
}
|
||||||
size_t childTableNameLen = strlen(tbnameKey);
|
size_t childTableNameLen = strlen(tbnameKey);
|
||||||
|
@ -532,13 +532,14 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnam
|
||||||
|
|
||||||
for (int i = 0; i < taosArrayGetSize(tags); i++) {
|
for (int i = 0; i < taosArrayGetSize(tags); i++) {
|
||||||
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
|
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
|
||||||
if(tag == NULL){
|
if (tag == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
// handle child table name
|
// handle child table name
|
||||||
if (childTableNameLen == tag->keyLen && strncmp(tag->key, tbnameKey, tag->keyLen) == 0) {
|
if (childTableNameLen == tag->keyLen && strncmp(tag->key, tbnameKey, tag->keyLen) == 0) {
|
||||||
(void)memset(childTableName, 0, TSDB_TABLE_NAME_LEN);
|
(void)memset(childTableName, 0, TSDB_TABLE_NAME_LEN);
|
||||||
(void)strncpy(childTableName, tag->value, (tag->length < TSDB_TABLE_NAME_LEN ? tag->length : TSDB_TABLE_NAME_LEN));
|
(void)strncpy(childTableName, tag->value,
|
||||||
|
(tag->length < TSDB_TABLE_NAME_LEN ? tag->length : TSDB_TABLE_NAME_LEN));
|
||||||
if (tsSmlDot2Underline) {
|
if (tsSmlDot2Underline) {
|
||||||
smlStrReplace(childTableName, strlen(childTableName));
|
smlStrReplace(childTableName, strlen(childTableName));
|
||||||
}
|
}
|
||||||
|
@ -553,7 +554,7 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnam
|
||||||
|
|
||||||
int32_t smlSetCTableName(SSmlTableInfo *oneTable, char *tbnameKey) {
|
int32_t smlSetCTableName(SSmlTableInfo *oneTable, char *tbnameKey) {
|
||||||
int32_t code = smlParseTableName(oneTable->tags, oneTable->childTableName, tbnameKey);
|
int32_t code = smlParseTableName(oneTable->tags, oneTable->childTableName, tbnameKey);
|
||||||
if(code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +563,7 @@ int32_t smlSetCTableName(SSmlTableInfo *oneTable, char *tbnameKey) {
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
if(oneTable->sTableNameLen >= TSDB_TABLE_NAME_LEN){
|
if (oneTable->sTableNameLen >= TSDB_TABLE_NAME_LEN) {
|
||||||
uError("SML:smlSetCTableName super table name is too long");
|
uError("SML:smlSetCTableName super table name is too long");
|
||||||
taosArrayDestroy(dst);
|
taosArrayDestroy(dst);
|
||||||
return TSDB_CODE_SML_INTERNAL_ERROR;
|
return TSDB_CODE_SML_INTERNAL_ERROR;
|
||||||
|
@ -578,7 +579,7 @@ int32_t smlSetCTableName(SSmlTableInfo *oneTable, char *tbnameKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
code = buildChildTableName(&rName);
|
code = buildChildTableName(&rName);
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
taosArrayDestroy(dst);
|
taosArrayDestroy(dst);
|
||||||
|
@ -906,13 +907,13 @@ static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols, SArray *checkDumplicateCols,
|
static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols,
|
||||||
ESchemaAction *action, bool isTag) {
|
SArray *checkDumplicateCols, ESchemaAction *action, bool isTag) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
for (int j = 0; j < taosArrayGetSize(cols); ++j) {
|
for (int j = 0; j < taosArrayGetSize(cols); ++j) {
|
||||||
if (j == 0 && !isTag) continue;
|
if (j == 0 && !isTag) continue;
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, j);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, j);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, action, info);
|
code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, action, info);
|
||||||
|
@ -923,10 +924,10 @@ static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SH
|
||||||
|
|
||||||
for (int j = 0; j < taosArrayGetSize(checkDumplicateCols); ++j) {
|
for (int j = 0; j < taosArrayGetSize(checkDumplicateCols); ++j) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(checkDumplicateCols, j);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(checkDumplicateCols, j);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
if(taosHashGet(schemaHash, kv->key, kv->keyLen) != NULL){
|
if (taosHashGet(schemaHash, kv->key, kv->keyLen) != NULL) {
|
||||||
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -934,16 +935,16 @@ static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SH
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool isTag) {
|
static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool isTag) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
SHashObj *hashTmp = taosHashInit(length, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
SHashObj *hashTmp = taosHashInit(length, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
||||||
if (hashTmp == NULL) {
|
if (hashTmp == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
for (; i < length; i++) {
|
for (; i < length; i++) {
|
||||||
code = taosHashPut(hashTmp, schema[i].name, strlen(schema[i].name), &i, SHORT_BYTES);
|
code = taosHashPut(hashTmp, schema[i].name, strlen(schema[i].name), &i, SHORT_BYTES);
|
||||||
if (code != 0){
|
if (code != 0) {
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -955,7 +956,7 @@ static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool
|
||||||
}
|
}
|
||||||
for (; i < taosArrayGetSize(cols); i++) {
|
for (; i < taosArrayGetSize(cols); i++) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
code = TSDB_CODE_SML_INVALID_DATA;
|
code = TSDB_CODE_SML_INVALID_DATA;
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
|
@ -982,8 +983,8 @@ static int32_t getBytes(uint8_t type, int32_t length) {
|
||||||
static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols,
|
static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols,
|
||||||
SArray *results, int32_t numOfCols, bool isTag) {
|
SArray *results, int32_t numOfCols, bool isTag) {
|
||||||
for (int j = 0; j < taosArrayGetSize(cols); ++j) {
|
for (int j = 0; j < taosArrayGetSize(cols); ++j) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, j);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, j);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
ESchemaAction action = SCHEMA_ACTION_NULL;
|
ESchemaAction action = SCHEMA_ACTION_NULL;
|
||||||
|
@ -996,7 +997,7 @@ static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashO
|
||||||
field.type = kv->type;
|
field.type = kv->type;
|
||||||
field.bytes = getBytes(kv->type, kv->length);
|
field.bytes = getBytes(kv->type, kv->length);
|
||||||
(void)memcpy(field.name, kv->key, kv->keyLen);
|
(void)memcpy(field.name, kv->key, kv->keyLen);
|
||||||
if (taosArrayPush(results, &field) == NULL){
|
if (taosArrayPush(results, &field) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
} else if (action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) {
|
} else if (action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) {
|
||||||
|
@ -1008,7 +1009,7 @@ static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashO
|
||||||
uint16_t newIndex = *index;
|
uint16_t newIndex = *index;
|
||||||
if (isTag) newIndex -= numOfCols;
|
if (isTag) newIndex -= numOfCols;
|
||||||
SField *field = (SField *)taosArrayGet(results, newIndex);
|
SField *field = (SField *)taosArrayGet(results, newIndex);
|
||||||
if (field == NULL){
|
if (field == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
field->bytes = getBytes(kv->type, kv->length);
|
field->bytes = getBytes(kv->type, kv->length);
|
||||||
|
@ -1019,7 +1020,7 @@ static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashO
|
||||||
int32_t len = 0;
|
int32_t len = 0;
|
||||||
for (int j = 0; j < taosArrayGetSize(results); ++j) {
|
for (int j = 0; j < taosArrayGetSize(results); ++j) {
|
||||||
SField *field = taosArrayGet(results, j);
|
SField *field = taosArrayGet(results, j);
|
||||||
if (field == NULL){
|
if (field == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
len += field->bytes;
|
len += field->bytes;
|
||||||
|
@ -1051,14 +1052,14 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < pReq.numOfColumns; ++i) {
|
for (int32_t i = 0; i < pReq.numOfColumns; ++i) {
|
||||||
SField *pField = taosArrayGet(pColumns, i);
|
SField *pField = taosArrayGet(pColumns, i);
|
||||||
if (pField == NULL){
|
if (pField == NULL) {
|
||||||
code = TSDB_CODE_SML_INVALID_DATA;
|
code = TSDB_CODE_SML_INVALID_DATA;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
SFieldWithOptions fieldWithOption = {0};
|
SFieldWithOptions fieldWithOption = {0};
|
||||||
setFieldWithOptions(&fieldWithOption, pField);
|
setFieldWithOptions(&fieldWithOption, pField);
|
||||||
setDefaultOptionsForField(&fieldWithOption);
|
setDefaultOptionsForField(&fieldWithOption);
|
||||||
if (taosArrayPush(pReq.pColumns, &fieldWithOption) == NULL){
|
if (taosArrayPush(pReq.pColumns, &fieldWithOption) == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1105,7 +1106,7 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
||||||
field.type = TSDB_DATA_TYPE_NCHAR;
|
field.type = TSDB_DATA_TYPE_NCHAR;
|
||||||
field.bytes = TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
field.bytes = TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||||
tstrncpy(field.name, tsSmlTagName, sizeof(field.name));
|
tstrncpy(field.name, tsSmlTagName, sizeof(field.name));
|
||||||
if (taosArrayPush(pReq.pTags, &field) == NULL){
|
if (taosArrayPush(pReq.pTags, &field) == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1121,7 +1122,7 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
||||||
pCmdMsg.epSet = getEpSet_s(&info->taos->pAppInfo->mgmtEp);
|
pCmdMsg.epSet = getEpSet_s(&info->taos->pAppInfo->mgmtEp);
|
||||||
pCmdMsg.msgType = TDMT_MND_CREATE_STB;
|
pCmdMsg.msgType = TDMT_MND_CREATE_STB;
|
||||||
pCmdMsg.msgLen = tSerializeSMCreateStbReq(NULL, 0, &pReq);
|
pCmdMsg.msgLen = tSerializeSMCreateStbReq(NULL, 0, &pReq);
|
||||||
if (pCmdMsg.msgLen < 0){
|
if (pCmdMsg.msgLen < 0) {
|
||||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1132,7 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tSerializeSMCreateStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq) < 0){
|
if (tSerializeSMCreateStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq) < 0) {
|
||||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
taosMemoryFree(pCmdMsg.pMsg);
|
taosMemoryFree(pCmdMsg.pMsg);
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -1144,11 +1145,11 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
|
||||||
pQuery.msgType = pQuery.pCmdMsg->msgType;
|
pQuery.msgType = pQuery.pCmdMsg->msgType;
|
||||||
pQuery.stableQuery = true;
|
pQuery.stableQuery = true;
|
||||||
|
|
||||||
(void)launchQueryImpl(pRequest, &pQuery, true, NULL); // no need to check return value
|
launchQueryImpl(pRequest, &pQuery, true, NULL); // no need to check return value
|
||||||
|
|
||||||
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
if (pRequest->code == TSDB_CODE_SUCCESS) {
|
||||||
code = catalogRemoveTableMeta(info->pCatalog, pName);
|
code = catalogRemoveTableMeta(info->pCatalog, pName);
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1187,7 +1188,7 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
size_t superTableLen = 0;
|
size_t superTableLen = 0;
|
||||||
void *superTable = taosHashGetKey(tmp, &superTableLen);
|
void *superTable = taosHashGetKey(tmp, &superTableLen);
|
||||||
char *measure = taosMemoryMalloc(superTableLen);
|
char *measure = taosMemoryMalloc(superTableLen);
|
||||||
if (measure == NULL){
|
if (measure == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1246,28 +1247,28 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
} else if (code == TSDB_CODE_SUCCESS) {
|
} else if (code == TSDB_CODE_SUCCESS) {
|
||||||
|
if (smlIsPKTable(pTableMeta)) {
|
||||||
if(smlIsPKTable(pTableMeta)){
|
|
||||||
code = TSDB_CODE_SML_NOT_SUPPORT_PK;
|
code = TSDB_CODE_SML_NOT_SUPPORT_PK;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashTmp = taosHashInit(pTableMeta->tableInfo.numOfTags, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true,
|
hashTmp = taosHashInit(pTableMeta->tableInfo.numOfTags, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true,
|
||||||
HASH_NO_LOCK);
|
HASH_NO_LOCK);
|
||||||
if (hashTmp == NULL){
|
if (hashTmp == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
for (uint16_t i = pTableMeta->tableInfo.numOfColumns;
|
for (uint16_t i = pTableMeta->tableInfo.numOfColumns;
|
||||||
i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) {
|
i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) {
|
||||||
code = taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES);
|
code = taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES);
|
||||||
if (code != 0){
|
if (code != 0) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ESchemaAction action = SCHEMA_ACTION_NULL;
|
ESchemaAction action = SCHEMA_ACTION_NULL;
|
||||||
code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->tags, sTableData->cols, &action, true);
|
code =
|
||||||
|
smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->tags, sTableData->cols, &action, true);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1280,13 +1281,13 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
action);
|
action);
|
||||||
SArray *pColumns =
|
SArray *pColumns =
|
||||||
taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField));
|
taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField));
|
||||||
if (pColumns == NULL){
|
if (pColumns == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
SArray *pTags =
|
SArray *pTags =
|
||||||
taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField));
|
taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField));
|
||||||
if (pTags == NULL){
|
if (pTags == NULL) {
|
||||||
taosArrayDestroy(pColumns);
|
taosArrayDestroy(pColumns);
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -1297,14 +1298,14 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
field.bytes = pTableMeta->schema[i].bytes;
|
field.bytes = pTableMeta->schema[i].bytes;
|
||||||
tstrncpy(field.name, pTableMeta->schema[i].name, sizeof(field.name));
|
tstrncpy(field.name, pTableMeta->schema[i].name, sizeof(field.name));
|
||||||
if (i < pTableMeta->tableInfo.numOfColumns) {
|
if (i < pTableMeta->tableInfo.numOfColumns) {
|
||||||
if (taosArrayPush(pColumns, &field) == NULL){
|
if (taosArrayPush(pColumns, &field) == NULL) {
|
||||||
taosArrayDestroy(pColumns);
|
taosArrayDestroy(pColumns);
|
||||||
taosArrayDestroy(pTags);
|
taosArrayDestroy(pTags);
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (taosArrayPush(pTags, &field) == NULL){
|
if (taosArrayPush(pTags, &field) == NULL) {
|
||||||
taosArrayDestroy(pColumns);
|
taosArrayDestroy(pColumns);
|
||||||
taosArrayDestroy(pTags);
|
taosArrayDestroy(pTags);
|
||||||
code = terrno;
|
code = terrno;
|
||||||
|
@ -1363,7 +1364,8 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
action = SCHEMA_ACTION_NULL;
|
action = SCHEMA_ACTION_NULL;
|
||||||
code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->cols, sTableData->tags, &action, false);
|
code =
|
||||||
|
smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->cols, sTableData->tags, &action, false);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1376,13 +1378,13 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
action);
|
action);
|
||||||
SArray *pColumns =
|
SArray *pColumns =
|
||||||
taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField));
|
taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField));
|
||||||
if (pColumns == NULL){
|
if (pColumns == NULL) {
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
SArray *pTags =
|
SArray *pTags =
|
||||||
taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField));
|
taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField));
|
||||||
if (pTags == NULL){
|
if (pTags == NULL) {
|
||||||
taosArrayDestroy(pColumns);
|
taosArrayDestroy(pColumns);
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -1393,14 +1395,14 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
|
||||||
field.bytes = pTableMeta->schema[i].bytes;
|
field.bytes = pTableMeta->schema[i].bytes;
|
||||||
tstrncpy(field.name, pTableMeta->schema[i].name, sizeof(field.name));
|
tstrncpy(field.name, pTableMeta->schema[i].name, sizeof(field.name));
|
||||||
if (i < pTableMeta->tableInfo.numOfColumns) {
|
if (i < pTableMeta->tableInfo.numOfColumns) {
|
||||||
if (taosArrayPush(pColumns, &field) == NULL){
|
if (taosArrayPush(pColumns, &field) == NULL) {
|
||||||
taosArrayDestroy(pColumns);
|
taosArrayDestroy(pColumns);
|
||||||
taosArrayDestroy(pTags);
|
taosArrayDestroy(pTags);
|
||||||
code = terrno;
|
code = terrno;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (taosArrayPush(pTags, &field) == NULL){
|
if (taosArrayPush(pTags, &field) == NULL) {
|
||||||
taosArrayDestroy(pColumns);
|
taosArrayDestroy(pColumns);
|
||||||
taosArrayDestroy(pTags);
|
taosArrayDestroy(pTags);
|
||||||
code = terrno;
|
code = terrno;
|
||||||
|
@ -1483,7 +1485,7 @@ end:
|
||||||
taosHashCancelIterate(info->superTables, tmp);
|
taosHashCancelIterate(info->superTables, tmp);
|
||||||
taosHashCleanup(hashTmp);
|
taosHashCleanup(hashTmp);
|
||||||
taosMemoryFreeClear(pTableMeta);
|
taosMemoryFreeClear(pTableMeta);
|
||||||
(void)catalogRefreshTableMeta(info->pCatalog, &conn, &pName, 1); // ignore refresh meta code if there is an error
|
(void)catalogRefreshTableMeta(info->pCatalog, &conn, &pName, 1); // ignore refresh meta code if there is an error
|
||||||
uError("SML:0x%" PRIx64 " smlModifyDBSchemas end failed:%d:%s, format:%d, needModifySchema:%d", info->id, code,
|
uError("SML:0x%" PRIx64 " smlModifyDBSchemas end failed:%d:%s, format:%d, needModifySchema:%d", info->id, code,
|
||||||
tstrerror(code), info->dataFormat, info->needModifySchema);
|
tstrerror(code), info->dataFormat, info->needModifySchema);
|
||||||
|
|
||||||
|
@ -1494,34 +1496,35 @@ static int32_t smlInsertMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols
|
||||||
terrno = 0;
|
terrno = 0;
|
||||||
for (int16_t i = 0; i < taosArrayGetSize(cols); ++i) {
|
for (int16_t i = 0; i < taosArrayGetSize(cols); ++i) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
int ret = taosHashPut(metaHash, kv->key, kv->keyLen, &i, SHORT_BYTES);
|
int ret = taosHashPut(metaHash, kv->key, kv->keyLen, &i, SHORT_BYTES);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
if (taosArrayPush(metaArray, kv) == NULL){
|
if (taosArrayPush(metaArray, kv) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
if(taosHashGet(checkDuplicate, kv->key, kv->keyLen) != NULL) {
|
if (taosHashGet(checkDuplicate, kv->key, kv->keyLen) != NULL) {
|
||||||
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
||||||
}
|
}
|
||||||
}else if(terrno == TSDB_CODE_DUP_KEY){
|
} else if (terrno == TSDB_CODE_DUP_KEY) {
|
||||||
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, bool isTag, SSmlMsgBuf *msg, SHashObj* checkDuplicate) {
|
static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, bool isTag, SSmlMsgBuf *msg,
|
||||||
|
SHashObj *checkDuplicate) {
|
||||||
for (int i = 0; i < taosArrayGetSize(cols); ++i) {
|
for (int i = 0; i < taosArrayGetSize(cols); ++i) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
int16_t *index = (int16_t *)taosHashGet(metaHash, kv->key, kv->keyLen);
|
int16_t *index = (int16_t *)taosHashGet(metaHash, kv->key, kv->keyLen);
|
||||||
if (index) {
|
if (index) {
|
||||||
SSmlKv *value = (SSmlKv *)taosArrayGet(metaArray, *index);
|
SSmlKv *value = (SSmlKv *)taosArrayGet(metaArray, *index);
|
||||||
if (value == NULL){
|
if (value == NULL) {
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,13 +1552,13 @@ static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols
|
||||||
int16_t size = tmp;
|
int16_t size = tmp;
|
||||||
int ret = taosHashPut(metaHash, kv->key, kv->keyLen, &size, SHORT_BYTES);
|
int ret = taosHashPut(metaHash, kv->key, kv->keyLen, &size, SHORT_BYTES);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
if(taosArrayPush(metaArray, kv) == NULL){
|
if (taosArrayPush(metaArray, kv) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
if(taosHashGet(checkDuplicate, kv->key, kv->keyLen) != NULL) {
|
if (taosHashGet(checkDuplicate, kv->key, kv->keyLen) != NULL) {
|
||||||
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1586,7 +1589,7 @@ void freeSSmlKv(void *data) {
|
||||||
|
|
||||||
void smlDestroyInfo(SSmlHandle *info) {
|
void smlDestroyInfo(SSmlHandle *info) {
|
||||||
if (!info) return;
|
if (!info) return;
|
||||||
// qDestroyQuery(info->pQuery);
|
// qDestroyQuery(info->pQuery);
|
||||||
|
|
||||||
taosHashCleanup(info->pVgHash);
|
taosHashCleanup(info->pVgHash);
|
||||||
taosHashCleanup(info->childTables);
|
taosHashCleanup(info->childTables);
|
||||||
|
@ -1657,7 +1660,7 @@ int32_t smlBuildSmlInfo(TAOS *taos, SSmlHandle **handle) {
|
||||||
|
|
||||||
info->id = smlGenId();
|
info->id = smlGenId();
|
||||||
code = smlInitHandle(&info->pQuery);
|
code = smlInitHandle(&info->pQuery);
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
goto FAILED;
|
goto FAILED;
|
||||||
}
|
}
|
||||||
info->dataFormat = true;
|
info->dataFormat = true;
|
||||||
|
@ -1688,7 +1691,7 @@ static int32_t smlPushCols(SArray *colsArray, SArray *cols) {
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < taosArrayGetSize(cols); i++) {
|
for (size_t i = 0; i < taosArrayGetSize(cols); i++) {
|
||||||
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i);
|
||||||
if (kv == NULL){
|
if (kv == NULL) {
|
||||||
taosHashCleanup(kvHash);
|
taosHashCleanup(kvHash);
|
||||||
return TSDB_CODE_SML_INVALID_DATA;
|
return TSDB_CODE_SML_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
@ -1698,7 +1701,7 @@ static int32_t smlPushCols(SArray *colsArray, SArray *cols) {
|
||||||
taosHashCleanup(kvHash);
|
taosHashCleanup(kvHash);
|
||||||
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
return TSDB_CODE_PAR_DUPLICATED_COLUMN;
|
||||||
}
|
}
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
taosHashCleanup(kvHash);
|
taosHashCleanup(kvHash);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -1759,9 +1762,11 @@ static int32_t smlParseLineBottom(SSmlHandle *info) {
|
||||||
if (tableMeta) { // update meta
|
if (tableMeta) { // update meta
|
||||||
uDebug("SML:0x%" PRIx64 " smlParseLineBottom update meta, format:%d, linenum:%d", info->id, info->dataFormat,
|
uDebug("SML:0x%" PRIx64 " smlParseLineBottom update meta, format:%d, linenum:%d", info->id, info->dataFormat,
|
||||||
info->lineNum);
|
info->lineNum);
|
||||||
ret = smlUpdateMeta((*tableMeta)->colHash, (*tableMeta)->cols, elements->colArray, false, &info->msgBuf, (*tableMeta)->tagHash);
|
ret = smlUpdateMeta((*tableMeta)->colHash, (*tableMeta)->cols, elements->colArray, false, &info->msgBuf,
|
||||||
|
(*tableMeta)->tagHash);
|
||||||
if (ret == TSDB_CODE_SUCCESS) {
|
if (ret == TSDB_CODE_SUCCESS) {
|
||||||
ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, tinfo->tags, true, &info->msgBuf, (*tableMeta)->colHash);
|
ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, tinfo->tags, true, &info->msgBuf,
|
||||||
|
(*tableMeta)->colHash);
|
||||||
}
|
}
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
uError("SML:0x%" PRIx64 " smlUpdateMeta failed, ret:%d", info->id, ret);
|
uError("SML:0x%" PRIx64 " smlUpdateMeta failed, ret:%d", info->id, ret);
|
||||||
|
@ -1801,17 +1806,17 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
||||||
|
|
||||||
if (info->pRequest->dbList == NULL) {
|
if (info->pRequest->dbList == NULL) {
|
||||||
info->pRequest->dbList = taosArrayInit(1, TSDB_DB_FNAME_LEN);
|
info->pRequest->dbList = taosArrayInit(1, TSDB_DB_FNAME_LEN);
|
||||||
if (info->pRequest->dbList == NULL){
|
if (info->pRequest->dbList == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char *data = (char *)taosArrayReserve(info->pRequest->dbList, 1);
|
char *data = (char *)taosArrayReserve(info->pRequest->dbList, 1);
|
||||||
if (data == NULL){
|
if (data == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}};
|
SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}};
|
||||||
tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname));
|
tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname));
|
||||||
(void)tNameGetFullDbName(&pName, data); //ignore
|
(void)tNameGetFullDbName(&pName, data); // ignore
|
||||||
|
|
||||||
SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL);
|
SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL);
|
||||||
while (oneTable) {
|
while (oneTable) {
|
||||||
|
@ -1819,7 +1824,7 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
||||||
|
|
||||||
int measureLen = tableData->sTableNameLen;
|
int measureLen = tableData->sTableNameLen;
|
||||||
char *measure = (char *)taosMemoryMalloc(tableData->sTableNameLen);
|
char *measure = (char *)taosMemoryMalloc(tableData->sTableNameLen);
|
||||||
if (measure == NULL){
|
if (measure == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
(void)memcpy(measure, tableData->sTableName, tableData->sTableNameLen);
|
(void)memcpy(measure, tableData->sTableName, tableData->sTableNameLen);
|
||||||
|
@ -1830,11 +1835,11 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
||||||
|
|
||||||
if (info->pRequest->tableList == NULL) {
|
if (info->pRequest->tableList == NULL) {
|
||||||
info->pRequest->tableList = taosArrayInit(1, sizeof(SName));
|
info->pRequest->tableList = taosArrayInit(1, sizeof(SName));
|
||||||
if (info->pRequest->tableList == NULL){
|
if (info->pRequest->tableList == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (taosArrayPush(info->pRequest->tableList, &pName) == NULL){
|
if (taosArrayPush(info->pRequest->tableList, &pName) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1862,7 +1867,7 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
code = taosHashPut(info->pVgHash, (const char *)&vg.vgId, sizeof(vg.vgId), (char *)&vg, sizeof(vg));
|
code = taosHashPut(info->pVgHash, (const char *)&vg.vgId, sizeof(vg.vgId), (char *)&vg, sizeof(vg));
|
||||||
if (code != TSDB_CODE_SUCCESS){
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
uError("SML:0x%" PRIx64 " taosHashPut failed. table name: %s", info->id, tableData->childTableName);
|
uError("SML:0x%" PRIx64 " taosHashPut failed. table name: %s", info->id, tableData->childTableName);
|
||||||
taosMemoryFree(measure);
|
taosMemoryFree(measure);
|
||||||
taosHashCancelIterate(info->childTables, oneTable);
|
taosHashCancelIterate(info->childTables, oneTable);
|
||||||
|
@ -1904,9 +1909,9 @@ static int32_t smlInsertData(SSmlHandle *info) {
|
||||||
info->cost.insertRpcTime = taosGetTimestampUs();
|
info->cost.insertRpcTime = taosGetTimestampUs();
|
||||||
|
|
||||||
SAppClusterSummary *pActivity = &info->taos->pAppInfo->summary;
|
SAppClusterSummary *pActivity = &info->taos->pAppInfo->summary;
|
||||||
(void)atomic_add_fetch_64((int64_t *)&pActivity->numOfInsertsReq, 1); // no need to check return code
|
(void)atomic_add_fetch_64((int64_t *)&pActivity->numOfInsertsReq, 1); // no need to check return code
|
||||||
|
|
||||||
(void)launchQueryImpl(info->pRequest, info->pQuery, true, NULL); // no need to check return code
|
launchQueryImpl(info->pRequest, info->pQuery, true, NULL); // no need to check return code
|
||||||
|
|
||||||
uDebug("SML:0x%" PRIx64 " smlInsertData end, format:%d, code:%d,%s", info->id, info->dataFormat, info->pRequest->code,
|
uDebug("SML:0x%" PRIx64 " smlInsertData end, format:%d, code:%d,%s", info->id, info->dataFormat, info->pRequest->code,
|
||||||
tstrerror(info->pRequest->code));
|
tstrerror(info->pRequest->code));
|
||||||
|
@ -1975,12 +1980,12 @@ static bool getLine(SSmlHandle *info, char *lines[], char **rawLine, char *rawLi
|
||||||
|
|
||||||
if (*rawLine != NULL && (uDebugFlag & DEBUG_DEBUG)) {
|
if (*rawLine != NULL && (uDebugFlag & DEBUG_DEBUG)) {
|
||||||
char *print = taosMemoryCalloc(*len + 1, 1);
|
char *print = taosMemoryCalloc(*len + 1, 1);
|
||||||
if (print != NULL){
|
if (print != NULL) {
|
||||||
(void)memcpy(print, *tmp, *len);
|
(void)memcpy(print, *tmp, *len);
|
||||||
uDebug("SML:0x%" PRIx64 " smlParseLine is raw, numLines:%d, protocol:%d, len:%d, data:%s", info->id, numLines,
|
uDebug("SML:0x%" PRIx64 " smlParseLine is raw, numLines:%d, protocol:%d, len:%d, data:%s", info->id, numLines,
|
||||||
info->protocol, *len, print);
|
info->protocol, *len, print);
|
||||||
taosMemoryFree(print);
|
taosMemoryFree(print);
|
||||||
} else{
|
} else {
|
||||||
uError("SML:0x%" PRIx64 " smlParseLine taosMemoryCalloc failed", info->id);
|
uError("SML:0x%" PRIx64 " smlParseLine taosMemoryCalloc failed", info->id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2228,7 +2233,7 @@ TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine,
|
||||||
uInfo("SML:%" PRIx64 " retry:%d/10,ver is old retry or object is creating code:%d, msg:%s", info->id, cnt, code,
|
uInfo("SML:%" PRIx64 " retry:%d/10,ver is old retry or object is creating code:%d, msg:%s", info->id, cnt, code,
|
||||||
tstrerror(code));
|
tstrerror(code));
|
||||||
code = refreshMeta(request->pTscObj, request);
|
code = refreshMeta(request->pTscObj, request);
|
||||||
if (code != 0){
|
if (code != 0) {
|
||||||
uInfo("SML:%" PRIx64 " refresh meta error code:%d, msg:%s", info->id, code, tstrerror(code));
|
uInfo("SML:%" PRIx64 " refresh meta error code:%d, msg:%s", info->id, code, tstrerror(code));
|
||||||
}
|
}
|
||||||
smlDestroyInfo(info);
|
smlDestroyInfo(info);
|
||||||
|
@ -2266,7 +2271,7 @@ end:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TAOS_RES *taos_schemaless_insert_ttl_with_reqid_tbname_key(TAOS *taos, char *lines[], int numLines, int protocol,
|
TAOS_RES *taos_schemaless_insert_ttl_with_reqid_tbname_key(TAOS *taos, char *lines[], int numLines, int protocol,
|
||||||
int precision, int32_t ttl, int64_t reqid, char *tbnameKey){
|
int precision, int32_t ttl, int64_t reqid, char *tbnameKey) {
|
||||||
return taos_schemaless_insert_inner(taos, lines, NULL, NULL, numLines, protocol, precision, ttl, reqid, tbnameKey);
|
return taos_schemaless_insert_inner(taos, lines, NULL, NULL, numLines, protocol, precision, ttl, reqid, tbnameKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2306,14 +2311,17 @@ static void getRawLineLen(char *lines, int len, int32_t *totalRows, int protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(TAOS *taos, char *lines, int len, int32_t *totalRows,
|
TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(TAOS *taos, char *lines, int len, int32_t *totalRows,
|
||||||
int protocol, int precision, int32_t ttl, int64_t reqid, char *tbnameKey){
|
int protocol, int precision, int32_t ttl, int64_t reqid,
|
||||||
|
char *tbnameKey) {
|
||||||
getRawLineLen(lines, len, totalRows, protocol);
|
getRawLineLen(lines, len, totalRows, protocol);
|
||||||
return taos_schemaless_insert_inner(taos, NULL, lines, lines + len, *totalRows, protocol, precision, ttl, reqid, tbnameKey);
|
return taos_schemaless_insert_inner(taos, NULL, lines, lines + len, *totalRows, protocol, precision, ttl, reqid,
|
||||||
|
tbnameKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol,
|
TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol,
|
||||||
int precision, int32_t ttl, int64_t reqid) {
|
int precision, int32_t ttl, int64_t reqid) {
|
||||||
return taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(taos, lines, len, totalRows, protocol, precision, ttl, reqid, NULL);
|
return taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(taos, lines, len, totalRows, protocol, precision, ttl,
|
||||||
|
reqid, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol,
|
TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol,
|
||||||
|
|
|
@ -25,7 +25,7 @@ static FORCE_INLINE int32_t stmtAllocQNodeFromBuf(STableBufInfo* pTblBuf, void**
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(taosArrayPush(pTblBuf->pBufList, &buff) == NULL){
|
if (taosArrayPush(pTblBuf->pBufList, &buff) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,10 +184,16 @@ int32_t stmtBackupQueryFields(STscStmt* pStmt) {
|
||||||
|
|
||||||
int32_t size = pRes->numOfCols * sizeof(TAOS_FIELD);
|
int32_t size = pRes->numOfCols * sizeof(TAOS_FIELD);
|
||||||
pRes->fields = taosMemoryMalloc(size);
|
pRes->fields = taosMemoryMalloc(size);
|
||||||
pRes->userFields = taosMemoryMalloc(size);
|
if (pRes->fields == NULL) {
|
||||||
if (NULL == pRes->fields || NULL == pRes->userFields) {
|
|
||||||
STMT_ERR_RET(terrno);
|
STMT_ERR_RET(terrno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pRes->userFields = taosMemoryMalloc(size);
|
||||||
|
if (pRes->userFields == NULL) {
|
||||||
|
taosMemoryFreeClear(pRes->fields);
|
||||||
|
STMT_ERR_RET(terrno);
|
||||||
|
}
|
||||||
|
|
||||||
(void)memcpy(pRes->fields, pStmt->exec.pRequest->body.resInfo.fields, size);
|
(void)memcpy(pRes->fields, pStmt->exec.pRequest->body.resInfo.fields, size);
|
||||||
(void)memcpy(pRes->userFields, pStmt->exec.pRequest->body.resInfo.userFields, size);
|
(void)memcpy(pRes->userFields, pStmt->exec.pRequest->body.resInfo.userFields, size);
|
||||||
|
|
||||||
|
@ -224,8 +230,8 @@ int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags,
|
||||||
bool autoCreateTbl) {
|
bool autoCreateTbl) {
|
||||||
STscStmt* pStmt = (STscStmt*)stmt;
|
STscStmt* pStmt = (STscStmt*)stmt;
|
||||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||||
int32_t code = tNameExtractFullName(tbName, tbFName);
|
int32_t code = tNameExtractFullName(tbName, tbFName);
|
||||||
if (code != 0){
|
if (code != 0) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +778,7 @@ void* stmtBindThreadFunc(void* param) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = stmtAsyncOutput(pStmt, asyncParam);
|
int ret = stmtAsyncOutput(pStmt, asyncParam);
|
||||||
if (ret != 0){
|
if (ret != 0) {
|
||||||
qError("stmtAsyncOutput failed, reason:%s", tstrerror(ret));
|
qError("stmtAsyncOutput failed, reason:%s", tstrerror(ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,7 +827,7 @@ int32_t stmtInitTableBuf(STableBufInfo* pTblBuf) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taosArrayPush(pTblBuf->pBufList, &buff) == NULL){
|
if (taosArrayPush(pTblBuf->pBufList, &buff) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,9 +929,9 @@ int stmtPrepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
|
||||||
length = strlen(sql);
|
length = strlen(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
pStmt->sql.sqlStr = strndup(sql, length);
|
pStmt->sql.sqlStr = taosStrndup(sql, length);
|
||||||
if (!pStmt->sql.sqlStr) {
|
if (!pStmt->sql.sqlStr) {
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return terrno;
|
||||||
}
|
}
|
||||||
pStmt->sql.sqlLen = length;
|
pStmt->sql.sqlLen = length;
|
||||||
pStmt->sql.stbInterlaceMode = pStmt->stbInterlaceMode;
|
pStmt->sql.stbInterlaceMode = pStmt->stbInterlaceMode;
|
||||||
|
@ -967,7 +973,7 @@ int32_t stmtInitStbInterlaceTableInfo(STscStmt* pStmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int stmtSetDbName(TAOS_STMT* stmt, const char* dbName) {
|
int stmtSetDbName(TAOS_STMT* stmt, const char* dbName) {
|
||||||
STscStmt *pStmt = (STscStmt *) stmt;
|
STscStmt* pStmt = (STscStmt*)stmt;
|
||||||
|
|
||||||
STMT_DLOG("start to set dbName: %s", dbName);
|
STMT_DLOG("start to set dbName: %s", dbName);
|
||||||
|
|
||||||
|
@ -1045,7 +1051,7 @@ int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) {
|
||||||
|
|
||||||
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTAGS));
|
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTAGS));
|
||||||
|
|
||||||
SBoundColInfo *tags_info = (SBoundColInfo*)pStmt->bInfo.boundTags;
|
SBoundColInfo* tags_info = (SBoundColInfo*)pStmt->bInfo.boundTags;
|
||||||
if (tags_info->numOfBound <= 0 || tags_info->numOfCols <= 0) {
|
if (tags_info->numOfBound <= 0 || tags_info->numOfCols <= 0) {
|
||||||
tscWarn("no tags bound in sql, will not bound tags");
|
tscWarn("no tags bound in sql, will not bound tags");
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -1192,7 +1198,7 @@ static FORCE_INLINE int32_t stmtGetTableColsFromCache(STscStmt* pStmt, SArray**
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taosArrayPush(pStmt->sql.siInfo.pTableCols, &pTblCols) == NULL){
|
if (taosArrayPush(pStmt->sql.siInfo.pTableCols, &pTblCols) == NULL) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1222,6 @@ int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
|
||||||
|
|
||||||
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_BIND));
|
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_BIND));
|
||||||
|
|
||||||
|
|
||||||
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
|
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
|
||||||
STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
|
STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
|
||||||
pStmt->bInfo.needParse = false;
|
pStmt->bInfo.needParse = false;
|
||||||
|
@ -1256,7 +1261,7 @@ int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
|
||||||
|
|
||||||
if (pStmt->sql.pQuery->haveResultSet) {
|
if (pStmt->sql.pQuery->haveResultSet) {
|
||||||
STMT_ERR_RET(setResSchemaInfo(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->pResSchema,
|
STMT_ERR_RET(setResSchemaInfo(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->pResSchema,
|
||||||
pStmt->sql.pQuery->numOfResCols));
|
pStmt->sql.pQuery->numOfResCols));
|
||||||
taosMemoryFreeClear(pStmt->sql.pQuery->pResSchema);
|
taosMemoryFreeClear(pStmt->sql.pQuery->pResSchema);
|
||||||
setResPrecision(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->precision);
|
setResPrecision(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->precision);
|
||||||
}
|
}
|
||||||
|
@ -1549,7 +1554,7 @@ int stmtExec(TAOS_STMT* stmt) {
|
||||||
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_EXECUTE));
|
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_EXECUTE));
|
||||||
|
|
||||||
if (STMT_TYPE_QUERY == pStmt->sql.type) {
|
if (STMT_TYPE_QUERY == pStmt->sql.type) {
|
||||||
(void)launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
|
launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
|
||||||
} else {
|
} else {
|
||||||
if (pStmt->sql.stbInterlaceMode) {
|
if (pStmt->sql.stbInterlaceMode) {
|
||||||
int64_t startTs = taosGetTimestampUs();
|
int64_t startTs = taosGetTimestampUs();
|
||||||
|
@ -1571,7 +1576,7 @@ int stmtExec(TAOS_STMT* stmt) {
|
||||||
STMT_ERR_RET(qBuildStmtOutput(pStmt->sql.pQuery, pStmt->sql.pVgHash, pStmt->exec.pBlockHash));
|
STMT_ERR_RET(qBuildStmtOutput(pStmt->sql.pQuery, pStmt->sql.pVgHash, pStmt->exec.pBlockHash));
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
|
launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) {
|
if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) {
|
||||||
|
|
|
@ -698,7 +698,9 @@ static void* stmtBindThreadFunc(void* param) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)stmtAsyncOutput(pStmt, asyncParam);
|
if (stmtAsyncOutput(pStmt, asyncParam) != 0) {
|
||||||
|
qError("stmt async output failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qInfo("stmt bind thread stopped");
|
qInfo("stmt bind thread stopped");
|
||||||
|
@ -822,7 +824,11 @@ TAOS_STMT2* stmtInit2(STscObj* taos, TAOS_STMT2_OPTION* pOptions) {
|
||||||
|
|
||||||
pStmt->sql.siInfo.tableColsReady = true;
|
pStmt->sql.siInfo.tableColsReady = true;
|
||||||
if (pStmt->options.asyncExecFn) {
|
if (pStmt->options.asyncExecFn) {
|
||||||
(void)tsem_init(&pStmt->asyncQuerySem, 0, 1);
|
if (tsem_init(&pStmt->asyncQuerySem, 0, 1) != 0) {
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
(void)stmtClose(pStmt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pStmt->semWaited = false;
|
pStmt->semWaited = false;
|
||||||
|
|
||||||
|
@ -868,9 +874,9 @@ int stmtPrepare2(TAOS_STMT2* stmt, const char* sql, unsigned long length) {
|
||||||
length = strlen(sql);
|
length = strlen(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
pStmt->sql.sqlStr = strndup(sql, length);
|
pStmt->sql.sqlStr = taosStrndup(sql, length);
|
||||||
if (!pStmt->sql.sqlStr) {
|
if (!pStmt->sql.sqlStr) {
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return terrno;
|
||||||
}
|
}
|
||||||
pStmt->sql.sqlLen = length;
|
pStmt->sql.sqlLen = length;
|
||||||
pStmt->sql.stbInterlaceMode = pStmt->stbInterlaceMode;
|
pStmt->sql.stbInterlaceMode = pStmt->stbInterlaceMode;
|
||||||
|
@ -1603,7 +1609,9 @@ static void asyncQueryCb(void* userdata, TAOS_RES* res, int code) {
|
||||||
(void)stmtCleanExecInfo(pStmt, (code ? false : true), false);
|
(void)stmtCleanExecInfo(pStmt, (code ? false : true), false);
|
||||||
++pStmt->sql.runTimes;
|
++pStmt->sql.runTimes;
|
||||||
|
|
||||||
(void)tsem_post(&pStmt->asyncQuerySem);
|
if (tsem_post(&pStmt->asyncQuerySem) != 0) {
|
||||||
|
tscError("failed to post asyncQuerySem");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int stmtExec2(TAOS_STMT2* stmt, int* affected_rows) {
|
int stmtExec2(TAOS_STMT2* stmt, int* affected_rows) {
|
||||||
|
@ -1645,7 +1653,7 @@ int stmtExec2(TAOS_STMT2* stmt, int* affected_rows) {
|
||||||
__taos_async_fn_t fp = pStmt->options.asyncExecFn;
|
__taos_async_fn_t fp = pStmt->options.asyncExecFn;
|
||||||
|
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
(void)launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
|
launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
|
||||||
|
|
||||||
if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) {
|
if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) {
|
||||||
code = refreshMeta(pStmt->exec.pRequest->pTscObj, pStmt->exec.pRequest);
|
code = refreshMeta(pStmt->exec.pRequest->pTscObj, pStmt->exec.pRequest);
|
||||||
|
@ -1710,7 +1718,9 @@ int stmtClose2(TAOS_STMT2* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pStmt->options.asyncExecFn && !pStmt->semWaited) {
|
if (pStmt->options.asyncExecFn && !pStmt->semWaited) {
|
||||||
(void)tsem_wait(&pStmt->asyncQuerySem);
|
if (tsem_wait(&pStmt->asyncQuerySem) != 0) {
|
||||||
|
tscError("failed to wait asyncQuerySem");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STMT_DLOG("stmt %p closed, stbInterlaceMode: %d, statInfo: ctgGetTbMetaNum=>%" PRId64 ", getCacheTbInfo=>%" PRId64
|
STMT_DLOG("stmt %p closed, stbInterlaceMode: %d, statInfo: ctgGetTbMetaNum=>%" PRId64 ", getCacheTbInfo=>%" PRId64
|
||||||
|
@ -1727,7 +1737,9 @@ int stmtClose2(TAOS_STMT2* stmt) {
|
||||||
STMT_ERR_RET(stmtCleanSQLInfo(pStmt));
|
STMT_ERR_RET(stmtCleanSQLInfo(pStmt));
|
||||||
|
|
||||||
if (pStmt->options.asyncExecFn) {
|
if (pStmt->options.asyncExecFn) {
|
||||||
(void)tsem_destroy(&pStmt->asyncQuerySem);
|
if (tsem_destroy(&pStmt->asyncQuerySem) != 0) {
|
||||||
|
tscError("failed to destroy asyncQuerySem");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
taosMemoryFree(stmt);
|
taosMemoryFree(stmt);
|
||||||
|
|
||||||
|
@ -1873,6 +1885,8 @@ int stmtGetParamNum2(TAOS_STMT2* stmt, int* nums) {
|
||||||
|
|
||||||
int stmtGetParamTbName(TAOS_STMT2* stmt, int* nums) {
|
int stmtGetParamTbName(TAOS_STMT2* stmt, int* nums) {
|
||||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||||
|
int32_t code = 0;
|
||||||
|
int32_t preCode = pStmt->errCode;
|
||||||
|
|
||||||
STMT_DLOG_E("start to get param num");
|
STMT_DLOG_E("start to get param num");
|
||||||
|
|
||||||
|
@ -1895,17 +1909,19 @@ int stmtGetParamTbName(TAOS_STMT2* stmt, int* nums) {
|
||||||
STMT_ERR_RET(stmtCreateRequest(pStmt));
|
STMT_ERR_RET(stmtCreateRequest(pStmt));
|
||||||
|
|
||||||
if (pStmt->bInfo.needParse) {
|
if (pStmt->bInfo.needParse) {
|
||||||
STMT_ERR_RET(stmtParseSql(pStmt));
|
STMT_ERRI_JRET(stmtParseSql(pStmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSDB_CODE_TSC_STMT_TBNAME_ERROR == pStmt->errCode) {
|
*nums = STMT_TYPE_MULTI_INSERT == pStmt->sql.type ? 1 : 0;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
if (TSDB_CODE_TSC_STMT_TBNAME_ERROR == code) {
|
||||||
*nums = 1;
|
*nums = 1;
|
||||||
pStmt->errCode = TSDB_CODE_SUCCESS;
|
code = TSDB_CODE_SUCCESS;
|
||||||
} else {
|
|
||||||
*nums = STMT_TYPE_MULTI_INSERT == pStmt->sql.type ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
pStmt->errCode = preCode;
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
int stmtGetParam(TAOS_STMT* stmt, int idx, int* type, int* bytes) {
|
int stmtGetParam(TAOS_STMT* stmt, int idx, int* type, int* bytes) {
|
||||||
|
|
|
@ -63,13 +63,10 @@ int32_t s3Begin() {
|
||||||
TAOS_RETURN(TSDB_CODE_SUCCESS);
|
TAOS_RETURN(TSDB_CODE_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void s3End() { (void)S3_deinitialize(); }
|
void s3End() { S3_deinitialize(); }
|
||||||
|
|
||||||
int32_t s3Init() { TAOS_RETURN(TSDB_CODE_SUCCESS); /*s3Begin();*/ }
|
int32_t s3Init() { TAOS_RETURN(TSDB_CODE_SUCCESS); /*s3Begin();*/ }
|
||||||
|
|
||||||
void s3CleanUp() { /*s3End();*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t s3ListBucket(char const *bucketname);
|
static int32_t s3ListBucket(char const *bucketname);
|
||||||
|
|
||||||
static void s3DumpCfgByEp(int8_t epIndex) {
|
static void s3DumpCfgByEp(int8_t epIndex) {
|
||||||
|
@ -506,7 +503,9 @@ S3Status initial_multipart_callback(const char *upload_id, void *callbackData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
S3Status MultipartResponseProperiesCallback(const S3ResponseProperties *properties, void *callbackData) {
|
S3Status MultipartResponseProperiesCallback(const S3ResponseProperties *properties, void *callbackData) {
|
||||||
(void)responsePropertiesCallbackNull(properties, callbackData);
|
if (S3StatusOK != responsePropertiesCallbackNull(properties, callbackData)) {
|
||||||
|
uError("%s failed at line %d to process null callback.", __func__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
MultipartPartData *data = (MultipartPartData *)callbackData;
|
MultipartPartData *data = (MultipartPartData *)callbackData;
|
||||||
int seq = data->seq;
|
int seq = data->seq;
|
||||||
|
@ -517,7 +516,9 @@ S3Status MultipartResponseProperiesCallback(const S3ResponseProperties *properti
|
||||||
}
|
}
|
||||||
|
|
||||||
S3Status MultipartResponseProperiesCallbackWithCp(const S3ResponseProperties *properties, void *callbackData) {
|
S3Status MultipartResponseProperiesCallbackWithCp(const S3ResponseProperties *properties, void *callbackData) {
|
||||||
(void)responsePropertiesCallbackNull(properties, callbackData);
|
if (S3StatusOK != responsePropertiesCallbackNull(properties, callbackData)) {
|
||||||
|
uError("%s failed at line %d to process null callback.", __func__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
MultipartPartData *data = (MultipartPartData *)callbackData;
|
MultipartPartData *data = (MultipartPartData *)callbackData;
|
||||||
int seq = data->seq;
|
int seq = data->seq;
|
||||||
|
@ -897,8 +898,6 @@ upload:
|
||||||
if (partData.put_object_data.status != S3StatusOK) {
|
if (partData.put_object_data.status != S3StatusOK) {
|
||||||
s3PrintError(__FILE__, __LINE__, __func__, partData.put_object_data.status, partData.put_object_data.err_msg);
|
s3PrintError(__FILE__, __LINE__, __func__, partData.put_object_data.status, partData.put_object_data.err_msg);
|
||||||
TAOS_CHECK_GOTO(TAOS_SYSTEM_ERROR(EIO), &lino, _exit);
|
TAOS_CHECK_GOTO(TAOS_SYSTEM_ERROR(EIO), &lino, _exit);
|
||||||
|
|
||||||
//(void)cos_cp_dump(&cp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manager.etags[seq - 1]) {
|
if (!manager.etags[seq - 1]) {
|
||||||
|
@ -952,7 +951,9 @@ _exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cp.thefile) {
|
if (cp.thefile) {
|
||||||
(void)cos_cp_close(cp.thefile);
|
if (cos_cp_close(cp.thefile)) {
|
||||||
|
uError("%s failed at line %d to close cp file.", __func__, lino);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cp.parts) {
|
if (cp.parts) {
|
||||||
taosMemoryFree(cp.parts);
|
taosMemoryFree(cp.parts);
|
||||||
|
@ -1292,7 +1293,10 @@ int32_t s3DeleteObjects(const char *object_name[], int nobject) {
|
||||||
void s3DeleteObjectsByPrefix(const char *prefix) {
|
void s3DeleteObjectsByPrefix(const char *prefix) {
|
||||||
SArray *objectArray = getListByPrefix(prefix);
|
SArray *objectArray = getListByPrefix(prefix);
|
||||||
if (objectArray == NULL) return;
|
if (objectArray == NULL) return;
|
||||||
(void)s3DeleteObjects(TARRAY_DATA(objectArray), TARRAY_SIZE(objectArray));
|
int32_t code = s3DeleteObjects(TARRAY_DATA(objectArray), TARRAY_SIZE(objectArray));
|
||||||
|
if (!code) {
|
||||||
|
uError("%s failed at line %d since %s.", __func__, __LINE__, tstrerror(code));
|
||||||
|
}
|
||||||
taosArrayDestroyEx(objectArray, s3FreeObjectKey);
|
taosArrayDestroyEx(objectArray, s3FreeObjectKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,7 +1543,7 @@ int32_t s3Init() {
|
||||||
TAOS_RETURN(TSDB_CODE_SUCCESS);
|
TAOS_RETURN(TSDB_CODE_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void s3CleanUp() { cos_http_io_deinitialize(); }
|
// void s3CleanUp() { cos_http_io_deinitialize(); }
|
||||||
|
|
||||||
static void log_status(cos_status_t *s) {
|
static void log_status(cos_status_t *s) {
|
||||||
cos_warn_log("status->code: %d", s->code);
|
cos_warn_log("status->code: %d", s->code);
|
||||||
|
@ -1745,20 +1749,20 @@ bool s3Get(const char *object_name, const char *path) {
|
||||||
cos_table_t *headers = NULL;
|
cos_table_t *headers = NULL;
|
||||||
int traffic_limit = 0;
|
int traffic_limit = 0;
|
||||||
|
|
||||||
//创建内存池
|
// 创建内存池
|
||||||
cos_pool_create(&p, NULL);
|
cos_pool_create(&p, NULL);
|
||||||
|
|
||||||
//初始化请求选项
|
// 初始化请求选项
|
||||||
options = cos_request_options_create(p);
|
options = cos_request_options_create(p);
|
||||||
s3InitRequestOptions(options, is_cname);
|
s3InitRequestOptions(options, is_cname);
|
||||||
cos_str_set(&bucket, tsS3BucketName);
|
cos_str_set(&bucket, tsS3BucketName);
|
||||||
if (traffic_limit) {
|
if (traffic_limit) {
|
||||||
//限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s,如果超出该范围将返回400错误
|
// 限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s,如果超出该范围将返回400错误
|
||||||
headers = cos_table_make(p, 1);
|
headers = cos_table_make(p, 1);
|
||||||
cos_table_add_int(headers, "x-cos-traffic-limit", 819200);
|
cos_table_add_int(headers, "x-cos-traffic-limit", 819200);
|
||||||
}
|
}
|
||||||
|
|
||||||
//下载对象
|
// 下载对象
|
||||||
cos_str_set(&file, path);
|
cos_str_set(&file, path);
|
||||||
cos_str_set(&object, object_name);
|
cos_str_set(&object, object_name);
|
||||||
s = cos_get_object_to_file(options, &bucket, &object, headers, NULL, &file, &resp_headers);
|
s = cos_get_object_to_file(options, &bucket, &object, headers, NULL, &file, &resp_headers);
|
||||||
|
@ -1769,7 +1773,7 @@ bool s3Get(const char *object_name, const char *path) {
|
||||||
cos_warn_log("get object failed\n");
|
cos_warn_log("get object failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//销毁内存池
|
// 销毁内存池
|
||||||
cos_pool_destroy(p);
|
cos_pool_destroy(p);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1791,10 +1795,10 @@ int32_t s3GetObjectBlock(const char *object_name, int64_t offset, int64_t block_
|
||||||
// int traffic_limit = 0;
|
// int traffic_limit = 0;
|
||||||
char range_buf[64];
|
char range_buf[64];
|
||||||
|
|
||||||
//创建内存池
|
// 创建内存池
|
||||||
cos_pool_create(&p, NULL);
|
cos_pool_create(&p, NULL);
|
||||||
|
|
||||||
//初始化请求选项
|
// 初始化请求选项
|
||||||
options = cos_request_options_create(p);
|
options = cos_request_options_create(p);
|
||||||
// init_test_request_options(options, is_cname);
|
// init_test_request_options(options, is_cname);
|
||||||
s3InitRequestOptions(options, is_cname);
|
s3InitRequestOptions(options, is_cname);
|
||||||
|
@ -1843,7 +1847,7 @@ int32_t s3GetObjectBlock(const char *object_name, int64_t offset, int64_t block_
|
||||||
// cos_warn_log("Download data=%s", buf);
|
// cos_warn_log("Download data=%s", buf);
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
//销毁内存池
|
// 销毁内存池
|
||||||
cos_pool_destroy(p);
|
cos_pool_destroy(p);
|
||||||
|
|
||||||
*ppBlock = buf;
|
*ppBlock = buf;
|
||||||
|
@ -1932,15 +1936,15 @@ long s3Size(const char *object_name) {
|
||||||
cos_string_t object;
|
cos_string_t object;
|
||||||
cos_table_t *resp_headers = NULL;
|
cos_table_t *resp_headers = NULL;
|
||||||
|
|
||||||
//创建内存池
|
// 创建内存池
|
||||||
cos_pool_create(&p, NULL);
|
cos_pool_create(&p, NULL);
|
||||||
|
|
||||||
//初始化请求选项
|
// 初始化请求选项
|
||||||
options = cos_request_options_create(p);
|
options = cos_request_options_create(p);
|
||||||
s3InitRequestOptions(options, is_cname);
|
s3InitRequestOptions(options, is_cname);
|
||||||
cos_str_set(&bucket, tsS3BucketName);
|
cos_str_set(&bucket, tsS3BucketName);
|
||||||
|
|
||||||
//获取对象元数据
|
// 获取对象元数据
|
||||||
cos_str_set(&object, object_name);
|
cos_str_set(&object, object_name);
|
||||||
s = cos_head_object(options, &bucket, &object, NULL, &resp_headers);
|
s = cos_head_object(options, &bucket, &object, NULL, &resp_headers);
|
||||||
// print_headers(resp_headers);
|
// print_headers(resp_headers);
|
||||||
|
@ -1954,7 +1958,7 @@ long s3Size(const char *object_name) {
|
||||||
cos_warn_log("head object failed\n");
|
cos_warn_log("head object failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//销毁内存池
|
// 销毁内存池
|
||||||
cos_pool_destroy(p);
|
cos_pool_destroy(p);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
@ -1963,7 +1967,6 @@ long s3Size(const char *object_name) {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int32_t s3Init() { return 0; }
|
int32_t s3Init() { return 0; }
|
||||||
void s3CleanUp() {}
|
|
||||||
int32_t s3PutObjectFromFile(const char *file, const char *object) { return 0; }
|
int32_t s3PutObjectFromFile(const char *file, const char *object) { return 0; }
|
||||||
int32_t s3PutObjectFromFile2(const char *file, const char *object, int8_t withcp) { return 0; }
|
int32_t s3PutObjectFromFile2(const char *file, const char *object, int8_t withcp) { return 0; }
|
||||||
int32_t s3PutObjectFromFileOffset(const char *file, const char *object_name, int64_t offset, int64_t size) { return 0; }
|
int32_t s3PutObjectFromFileOffset(const char *file, const char *object_name, int64_t offset, int64_t size) { return 0; }
|
||||||
|
|
|
@ -309,7 +309,7 @@ int32_t cos_cp_dump(SCheckpoint* cp) {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
TAOS_CHECK_GOTO(TSDB_CODE_OUT_OF_MEMORY, &lino, _exit);
|
TAOS_CHECK_GOTO(TSDB_CODE_OUT_OF_MEMORY, &lino, _exit);
|
||||||
}
|
}
|
||||||
(void)cJSON_AddItemToArray(ajson, item);
|
if (!cJSON_AddItemToArray(ajson, item)) goto _exit;
|
||||||
|
|
||||||
if (NULL == cJSON_AddNumberToObject(item, "index", cp->parts[i].index)) {
|
if (NULL == cJSON_AddNumberToObject(item, "index", cp->parts[i].index)) {
|
||||||
TAOS_CHECK_GOTO(TSDB_CODE_OUT_OF_MEMORY, &lino, _exit);
|
TAOS_CHECK_GOTO(TSDB_CODE_OUT_OF_MEMORY, &lino, _exit);
|
||||||
|
|
|
@ -1771,26 +1771,6 @@ _err:
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tTagSetCid(const STag *pTag, int16_t iTag, int16_t cid) {
|
|
||||||
uint8_t *p = NULL;
|
|
||||||
int8_t isLarge = pTag->flags & TD_TAG_LARGE;
|
|
||||||
int16_t offset = 0;
|
|
||||||
|
|
||||||
if (isLarge) {
|
|
||||||
p = (uint8_t *)&((int16_t *)pTag->idx)[pTag->nTag];
|
|
||||||
} else {
|
|
||||||
p = (uint8_t *)&pTag->idx[pTag->nTag];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLarge) {
|
|
||||||
offset = ((int16_t *)pTag->idx)[iTag];
|
|
||||||
} else {
|
|
||||||
offset = pTag->idx[iTag];
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t nt = tPutI16v(p + offset, cid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// STSchema ========================================
|
// STSchema ========================================
|
||||||
STSchema *tBuildTSchema(SSchema *aSchema, int32_t numOfCols, int32_t version) {
|
STSchema *tBuildTSchema(SSchema *aSchema, int32_t numOfCols, int32_t version) {
|
||||||
STSchema *pTSchema = taosMemoryCalloc(1, sizeof(STSchema) + sizeof(STColumn) * numOfCols);
|
STSchema *pTSchema = taosMemoryCalloc(1, sizeof(STSchema) + sizeof(STColumn) * numOfCols);
|
||||||
|
|
|
@ -2299,11 +2299,14 @@ static int taosLogVarComp(void const *lp, void const *rp) {
|
||||||
return strcasecmp(lpVar->name, rpVar->name);
|
return strcasecmp(lpVar->name, rpVar->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t taosCheckAndSetDebugFlag(int32_t *pFlagPtr, char *name, int32_t flag, SArray *noNeedToSetVars) {
|
static void taosCheckAndSetDebugFlag(int32_t *pFlagPtr, char *name, int32_t flag, SArray *noNeedToSetVars) {
|
||||||
if (noNeedToSetVars != NULL && taosArraySearch(noNeedToSetVars, name, taosLogVarComp, TD_EQ) != NULL) {
|
if (noNeedToSetVars != NULL && taosArraySearch(noNeedToSetVars, name, taosLogVarComp, TD_EQ) != NULL) {
|
||||||
TAOS_RETURN(TSDB_CODE_SUCCESS);
|
return;
|
||||||
}
|
}
|
||||||
return taosSetDebugFlag(pFlagPtr, name, flag);
|
if (taosSetDebugFlag(pFlagPtr, name, flag) != 0) {
|
||||||
|
uError("failed to set flag %s to %d", name, flag);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t taosSetGlobalDebugFlag(int32_t flag) { return taosSetAllDebugFlag(tsCfg, flag); }
|
int32_t taosSetGlobalDebugFlag(int32_t flag) { return taosSetAllDebugFlag(tsCfg, flag); }
|
||||||
|
@ -2320,29 +2323,29 @@ static int32_t taosSetAllDebugFlag(SConfig *pCfg, int32_t flag) {
|
||||||
pItem->i32 = flag;
|
pItem->i32 = flag;
|
||||||
noNeedToSetVars = pItem->array;
|
noNeedToSetVars = pItem->array;
|
||||||
|
|
||||||
(void)taosCheckAndSetDebugFlag(&simDebugFlag, "simDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&simDebugFlag, "simDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&uDebugFlag, "uDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&uDebugFlag, "uDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&rpcDebugFlag, "rpcDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&rpcDebugFlag, "rpcDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&qDebugFlag, "qDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&qDebugFlag, "qDebugFlag", flag, noNeedToSetVars);
|
||||||
|
|
||||||
(void)taosCheckAndSetDebugFlag(&jniDebugFlag, "jniDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&jniDebugFlag, "jniDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&cDebugFlag, "cDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&cDebugFlag, "cDebugFlag", flag, noNeedToSetVars);
|
||||||
|
|
||||||
(void)taosCheckAndSetDebugFlag(&dDebugFlag, "dDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&dDebugFlag, "dDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&vDebugFlag, "vDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&vDebugFlag, "vDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&mDebugFlag, "mDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&mDebugFlag, "mDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&wDebugFlag, "wDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&wDebugFlag, "wDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&sDebugFlag, "sDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&sDebugFlag, "sDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&tsdbDebugFlag, "tsdbDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&tsdbDebugFlag, "tsdbDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&tqDebugFlag, "tqDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&tqDebugFlag, "tqDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&fsDebugFlag, "fsDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&fsDebugFlag, "fsDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&udfDebugFlag, "udfDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&udfDebugFlag, "udfDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&smaDebugFlag, "smaDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&smaDebugFlag, "smaDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&idxDebugFlag, "idxDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&idxDebugFlag, "idxDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&tdbDebugFlag, "tdbDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&tdbDebugFlag, "tdbDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&metaDebugFlag, "metaDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&metaDebugFlag, "metaDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&stDebugFlag, "stDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&stDebugFlag, "stDebugFlag", flag, noNeedToSetVars);
|
||||||
(void)taosCheckAndSetDebugFlag(&sndDebugFlag, "sndDebugFlag", flag, noNeedToSetVars);
|
taosCheckAndSetDebugFlag(&sndDebugFlag, "sndDebugFlag", flag, noNeedToSetVars);
|
||||||
|
|
||||||
taosArrayClear(noNeedToSetVars); // reset array
|
taosArrayClear(noNeedToSetVars); // reset array
|
||||||
|
|
||||||
|
|
|
@ -354,8 +354,10 @@ bool tdSKvRowGetVal(STSRow *pRow, col_id_t colId, col_id_t colIdx, SCellVal *pVa
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pBitmap = tdGetBitmapAddrKv(pRow, tdRowGetNCols(pRow));
|
void *pBitmap = tdGetBitmapAddrKv(pRow, tdRowGetNCols(pRow));
|
||||||
(void)tdGetKvRowValOfCol(pVal, pRow, pBitmap, pColIdx->offset,
|
if (tdGetKvRowValOfCol(pVal, pRow, pBitmap, pColIdx->offset,
|
||||||
POINTER_DISTANCE(pColIdx, TD_ROW_COL_IDX(pRow)) / sizeof(SKvRowIdx));
|
POINTER_DISTANCE(pColIdx, TD_ROW_COL_IDX(pRow)) / sizeof(SKvRowIdx)) != TSDB_CODE_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,9 @@ static int64_t m_deltaUtc = 0;
|
||||||
|
|
||||||
void deltaToUtcInitOnce() {
|
void deltaToUtcInitOnce() {
|
||||||
struct tm tm = {0};
|
struct tm tm = {0};
|
||||||
(void)taosStrpTime("1970-01-01 00:00:00", (const char*)("%Y-%m-%d %H:%M:%S"), &tm);
|
if (taosStrpTime("1970-01-01 00:00:00", (const char*)("%Y-%m-%d %H:%M:%S"), &tm) != 0) {
|
||||||
|
uError("failed to parse time string");
|
||||||
|
}
|
||||||
m_deltaUtc = (int64_t)taosMktime(&tm);
|
m_deltaUtc = (int64_t)taosMktime(&tm);
|
||||||
// printf("====delta:%lld\n\n", seconds);
|
// printf("====delta:%lld\n\n", seconds);
|
||||||
}
|
}
|
||||||
|
@ -689,10 +691,10 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) {
|
||||||
int64_t numOfMonth = (unit == 'y') ? duration * 12 : duration;
|
int64_t numOfMonth = (unit == 'y') ? duration * 12 : duration;
|
||||||
int64_t fraction = t % TSDB_TICK_PER_SECOND(precision);
|
int64_t fraction = t % TSDB_TICK_PER_SECOND(precision);
|
||||||
|
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t tt = (time_t)(t / TSDB_TICK_PER_SECOND(precision));
|
time_t tt = (time_t)(t / TSDB_TICK_PER_SECOND(precision));
|
||||||
(void)taosLocalTime(&tt, &tm, NULL);
|
struct tm* ptm = taosLocalTime(&tt, &tm, NULL);
|
||||||
int32_t mon = tm.tm_year * 12 + tm.tm_mon + (int32_t)numOfMonth;
|
int32_t mon = tm.tm_year * 12 + tm.tm_mon + (int32_t)numOfMonth;
|
||||||
tm.tm_year = mon / 12;
|
tm.tm_year = mon / 12;
|
||||||
tm.tm_mon = mon % 12;
|
tm.tm_mon = mon % 12;
|
||||||
int daysOfMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
int daysOfMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
@ -750,13 +752,13 @@ int32_t taosTimeCountIntervalForFill(int64_t skey, int64_t ekey, int64_t interva
|
||||||
skey /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
|
skey /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
|
||||||
ekey /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
|
ekey /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
|
||||||
|
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t t = (time_t)skey;
|
time_t t = (time_t)skey;
|
||||||
(void)taosLocalTime(&t, &tm, NULL);
|
struct tm* ptm = taosLocalTime(&t, &tm, NULL);
|
||||||
int32_t smon = tm.tm_year * 12 + tm.tm_mon;
|
int32_t smon = tm.tm_year * 12 + tm.tm_mon;
|
||||||
|
|
||||||
t = (time_t)ekey;
|
t = (time_t)ekey;
|
||||||
(void)taosLocalTime(&t, &tm, NULL);
|
ptm = taosLocalTime(&t, &tm, NULL);
|
||||||
int32_t emon = tm.tm_year * 12 + tm.tm_mon;
|
int32_t emon = tm.tm_year * 12 + tm.tm_mon;
|
||||||
|
|
||||||
if (unit == 'y') {
|
if (unit == 'y') {
|
||||||
|
@ -778,9 +780,9 @@ int64_t taosTimeTruncate(int64_t ts, const SInterval* pInterval) {
|
||||||
|
|
||||||
if (IS_CALENDAR_TIME_DURATION(pInterval->slidingUnit)) {
|
if (IS_CALENDAR_TIME_DURATION(pInterval->slidingUnit)) {
|
||||||
start /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
|
start /= (int64_t)(TSDB_TICK_PER_SECOND(precision));
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t tt = (time_t)start;
|
time_t tt = (time_t)start;
|
||||||
(void)taosLocalTime(&tt, &tm, NULL);
|
struct tm* ptm = taosLocalTime(&tt, &tm, NULL);
|
||||||
tm.tm_sec = 0;
|
tm.tm_sec = 0;
|
||||||
tm.tm_min = 0;
|
tm.tm_min = 0;
|
||||||
tm.tm_hour = 0;
|
tm.tm_hour = 0;
|
||||||
|
|
|
@ -81,11 +81,21 @@ static void dmSetAssert(int32_t signum, void *sigInfo, void *context) { tsAssert
|
||||||
static void dmStopDnode(int signum, void *sigInfo, void *context) {
|
static void dmStopDnode(int signum, void *sigInfo, void *context) {
|
||||||
// taosIgnSignal(SIGUSR1);
|
// taosIgnSignal(SIGUSR1);
|
||||||
// taosIgnSignal(SIGUSR2);
|
// taosIgnSignal(SIGUSR2);
|
||||||
(void)taosIgnSignal(SIGTERM);
|
if (taosIgnSignal(SIGTERM) != 0) {
|
||||||
(void)taosIgnSignal(SIGHUP);
|
dWarn("failed to ignore signal SIGTERM");
|
||||||
(void)taosIgnSignal(SIGINT);
|
}
|
||||||
(void)taosIgnSignal(SIGABRT);
|
if (taosIgnSignal(SIGHUP) != 0) {
|
||||||
(void)taosIgnSignal(SIGBREAK);
|
dWarn("failed to ignore signal SIGHUP");
|
||||||
|
}
|
||||||
|
if (taosIgnSignal(SIGINT) != 0) {
|
||||||
|
dWarn("failed to ignore signal SIGINT");
|
||||||
|
}
|
||||||
|
if (taosIgnSignal(SIGABRT) != 0) {
|
||||||
|
dWarn("failed to ignore signal SIGABRT");
|
||||||
|
}
|
||||||
|
if (taosIgnSignal(SIGBREAK) != 0) {
|
||||||
|
dWarn("failed to ignore signal SIGBREAK");
|
||||||
|
}
|
||||||
|
|
||||||
dInfo("shut down signal is %d", signum);
|
dInfo("shut down signal is %d", signum);
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
|
@ -103,11 +113,19 @@ void dmLogCrash(int signum, void *sigInfo, void *context) {
|
||||||
// taosIgnSignal(SIGBREAK);
|
// taosIgnSignal(SIGBREAK);
|
||||||
|
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
(void)taosIgnSignal(SIGBUS);
|
if (taosIgnSignal(SIGBUS) != 0) {
|
||||||
|
dWarn("failed to ignore signal SIGBUS");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
(void)taosIgnSignal(SIGABRT);
|
if (taosIgnSignal(SIGABRT) != 0) {
|
||||||
(void)taosIgnSignal(SIGFPE);
|
dWarn("failed to ignore signal SIGABRT");
|
||||||
(void)taosIgnSignal(SIGSEGV);
|
}
|
||||||
|
if (taosIgnSignal(SIGFPE) != 0) {
|
||||||
|
dWarn("failed to ignore signal SIGABRT");
|
||||||
|
}
|
||||||
|
if (taosIgnSignal(SIGSEGV) != 0) {
|
||||||
|
dWarn("failed to ignore signal SIGABRT");
|
||||||
|
}
|
||||||
|
|
||||||
char *pMsg = NULL;
|
char *pMsg = NULL;
|
||||||
const char *flags = "UTL FATAL ";
|
const char *flags = "UTL FATAL ";
|
||||||
|
@ -136,24 +154,31 @@ _return:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dmSetSignalHandle() {
|
static void dmSetSignalHandle() {
|
||||||
(void)taosSetSignal(SIGUSR1, dmSetDebugFlag);
|
if (taosSetSignal(SIGUSR1, dmSetDebugFlag) != 0) {
|
||||||
(void)taosSetSignal(SIGUSR2, dmSetAssert);
|
dWarn("failed to set signal SIGUSR1");
|
||||||
(void)taosSetSignal(SIGTERM, dmStopDnode);
|
}
|
||||||
(void)taosSetSignal(SIGHUP, dmStopDnode);
|
if (taosSetSignal(SIGUSR2, dmSetAssert) != 0) {
|
||||||
(void)taosSetSignal(SIGINT, dmStopDnode);
|
dWarn("failed to set signal SIGUSR1");
|
||||||
(void)taosSetSignal(SIGBREAK, dmStopDnode);
|
}
|
||||||
|
if (taosSetSignal(SIGTERM, dmStopDnode) != 0) {
|
||||||
|
dWarn("failed to set signal SIGUSR1");
|
||||||
|
}
|
||||||
|
if (taosSetSignal(SIGHUP, dmStopDnode) != 0) {
|
||||||
|
dWarn("failed to set signal SIGUSR1");
|
||||||
|
}
|
||||||
|
if (taosSetSignal(SIGINT, dmStopDnode) != 0) {
|
||||||
|
dWarn("failed to set signal SIGUSR1");
|
||||||
|
}
|
||||||
|
if (taosSetSignal(SIGBREAK, dmStopDnode) != 0) {
|
||||||
|
dWarn("failed to set signal SIGUSR1");
|
||||||
|
}
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
(void)taosSetSignal(SIGTSTP, dmStopDnode);
|
if (taosSetSignal(SIGTSTP, dmStopDnode) != 0) {
|
||||||
(void)taosSetSignal(SIGQUIT, dmStopDnode);
|
dWarn("failed to set signal SIGUSR1");
|
||||||
#endif
|
}
|
||||||
|
if (taosSetSignal(SIGQUIT, dmStopDnode) != 0) {
|
||||||
#if 0
|
dWarn("failed to set signal SIGUSR1");
|
||||||
#ifndef WINDOWS
|
}
|
||||||
(void)taosSetSignal(SIGBUS, dmLogCrash);
|
|
||||||
#endif
|
|
||||||
(void)taosSetSignal(SIGABRT, dmLogCrash);
|
|
||||||
(void)taosSetSignal(SIGFPE, dmLogCrash);
|
|
||||||
(void)taosSetSignal(SIGSEGV, dmLogCrash);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,9 @@ static void dmMayShouldUpdateIpWhiteList(SDnodeMgmt *pMgmt, int64_t ver) {
|
||||||
if (pMgmt->pData->ipWhiteVer == ver) {
|
if (pMgmt->pData->ipWhiteVer == ver) {
|
||||||
if (ver == 0) {
|
if (ver == 0) {
|
||||||
dDebug("disable ip-white-list on dnode ver: %" PRId64 ", status ver: %" PRId64 "", pMgmt->pData->ipWhiteVer, ver);
|
dDebug("disable ip-white-list on dnode ver: %" PRId64 ", status ver: %" PRId64 "", pMgmt->pData->ipWhiteVer, ver);
|
||||||
(void)rpcSetIpWhite(pMgmt->msgCb.serverRpc, NULL);
|
if (rpcSetIpWhite(pMgmt->msgCb.serverRpc, NULL) != 0) {
|
||||||
|
dError("failed to disable ip white list on dnode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +93,9 @@ static void dmProcessStatusRsp(SDnodeMgmt *pMgmt, SRpcMsg *pRsp) {
|
||||||
dGInfo("dnode:%d, set to dropped since not exist in mnode, statusSeq:%d", pMgmt->pData->dnodeId,
|
dGInfo("dnode:%d, set to dropped since not exist in mnode, statusSeq:%d", pMgmt->pData->dnodeId,
|
||||||
pMgmt->statusSeq);
|
pMgmt->statusSeq);
|
||||||
pMgmt->pData->dropped = 1;
|
pMgmt->pData->dropped = 1;
|
||||||
(void)dmWriteEps(pMgmt->pData);
|
if (dmWriteEps(pMgmt->pData) != 0) {
|
||||||
|
dError("failed to write dnode file");
|
||||||
|
}
|
||||||
dInfo("dnode will exit since it is in the dropped state");
|
dInfo("dnode will exit since it is in the dropped state");
|
||||||
(void)raise(SIGINT);
|
(void)raise(SIGINT);
|
||||||
}
|
}
|
||||||
|
@ -147,7 +151,9 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) {
|
||||||
req.clusterCfg.monitorParas.tsSlowLogThresholdTest = tsSlowLogThresholdTest;
|
req.clusterCfg.monitorParas.tsSlowLogThresholdTest = tsSlowLogThresholdTest;
|
||||||
tstrncpy(req.clusterCfg.monitorParas.tsSlowLogExceptDb, tsSlowLogExceptDb, TSDB_DB_NAME_LEN);
|
tstrncpy(req.clusterCfg.monitorParas.tsSlowLogExceptDb, tsSlowLogExceptDb, TSDB_DB_NAME_LEN);
|
||||||
char timestr[32] = "1970-01-01 00:00:00.00";
|
char timestr[32] = "1970-01-01 00:00:00.00";
|
||||||
(void)taosParseTime(timestr, &req.clusterCfg.checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0);
|
if (taosParseTime(timestr, &req.clusterCfg.checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0) != 0) {
|
||||||
|
dError("failed to parse time since %s", tstrerror(code));
|
||||||
|
}
|
||||||
memcpy(req.clusterCfg.timezone, tsTimezoneStr, TD_TIMEZONE_LEN);
|
memcpy(req.clusterCfg.timezone, tsTimezoneStr, TD_TIMEZONE_LEN);
|
||||||
memcpy(req.clusterCfg.locale, tsLocale, TD_LOCALE_LEN);
|
memcpy(req.clusterCfg.locale, tsLocale, TD_LOCALE_LEN);
|
||||||
memcpy(req.clusterCfg.charset, tsCharset, TD_LOCALE_LEN);
|
memcpy(req.clusterCfg.charset, tsCharset, TD_LOCALE_LEN);
|
||||||
|
@ -243,7 +249,9 @@ void dmSendNotifyReq(SDnodeMgmt *pMgmt, SNotifyReq *pReq) {
|
||||||
|
|
||||||
SEpSet epSet = {0};
|
SEpSet epSet = {0};
|
||||||
dmGetMnodeEpSet(pMgmt->pData, &epSet);
|
dmGetMnodeEpSet(pMgmt->pData, &epSet);
|
||||||
(void)rpcSendRequest(pMgmt->msgCb.clientRpc, &epSet, &rpcMsg, NULL);
|
if (rpcSendRequest(pMgmt->msgCb.clientRpc, &epSet, &rpcMsg, NULL) != 0) {
|
||||||
|
dError("failed to send notify req");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t dmProcessAuthRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
int32_t dmProcessAuthRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
||||||
|
|
|
@ -305,11 +305,16 @@ int32_t dmStartNotifyThread(SDnodeMgmt *pMgmt) {
|
||||||
|
|
||||||
void dmStopNotifyThread(SDnodeMgmt *pMgmt) {
|
void dmStopNotifyThread(SDnodeMgmt *pMgmt) {
|
||||||
if (taosCheckPthreadValid(pMgmt->notifyThread)) {
|
if (taosCheckPthreadValid(pMgmt->notifyThread)) {
|
||||||
(void)tsem_post(&dmNotifyHdl.sem);
|
if (tsem_post(&dmNotifyHdl.sem) != 0) {
|
||||||
|
dError("failed to post notify sem");
|
||||||
|
}
|
||||||
|
|
||||||
(void)taosThreadJoin(pMgmt->notifyThread, NULL);
|
(void)taosThreadJoin(pMgmt->notifyThread, NULL);
|
||||||
taosThreadClear(&pMgmt->notifyThread);
|
taosThreadClear(&pMgmt->notifyThread);
|
||||||
}
|
}
|
||||||
(void)tsem_destroy(&dmNotifyHdl.sem);
|
if (tsem_destroy(&dmNotifyHdl.sem) != 0) {
|
||||||
|
dError("failed to destroy notify sem");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t dmStartMonitorThread(SDnodeMgmt *pMgmt) {
|
int32_t dmStartMonitorThread(SDnodeMgmt *pMgmt) {
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
#include "mmInt.h"
|
#include "mmInt.h"
|
||||||
|
|
||||||
void mmGetMonitorInfo(SMnodeMgmt *pMgmt, SMonMmInfo *pInfo) {
|
void mmGetMonitorInfo(SMnodeMgmt *pMgmt, SMonMmInfo *pInfo) {
|
||||||
(void)mndGetMonitorInfo(pMgmt->pMnode, &pInfo->cluster, &pInfo->vgroup, &pInfo->stb, &pInfo->grant);
|
if (mndGetMonitorInfo(pMgmt->pMnode, &pInfo->cluster, &pInfo->vgroup, &pInfo->stb, &pInfo->grant) != 0) {
|
||||||
|
dError("failed to get monitor info");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmGetMnodeLoads(SMnodeMgmt *pMgmt, SMonMloadInfo *pInfo) {
|
void mmGetMnodeLoads(SMnodeMgmt *pMgmt, SMonMloadInfo *pInfo) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ static inline void qmSendRsp(SRpcMsg *pMsg, int32_t code) {
|
||||||
.contLen = pMsg->info.rspLen,
|
.contLen = pMsg->info.rspLen,
|
||||||
.info = pMsg->info,
|
.info = pMsg->info,
|
||||||
};
|
};
|
||||||
(void)tmsgSendRsp(&rsp);
|
tmsgSendRsp(&rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmProcessQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
static void qmProcessQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
||||||
|
|
|
@ -23,15 +23,15 @@ static inline void smSendRsp(SRpcMsg *pMsg, int32_t code) {
|
||||||
.contLen = pMsg->info.rspLen,
|
.contLen = pMsg->info.rspLen,
|
||||||
.info = pMsg->info,
|
.info = pMsg->info,
|
||||||
};
|
};
|
||||||
(void)tmsgSendRsp(&rsp);
|
tmsgSendRsp(&rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smProcessWriteQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
|
static void smProcessWriteQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) {
|
||||||
SSnodeMgmt *pMgmt = pInfo->ahandle;
|
SSnodeMgmt *pMgmt = pInfo->ahandle;
|
||||||
|
|
||||||
for (int32_t i = 0; i < numOfMsgs; i++) {
|
for (int32_t i = 0; i < numOfMsgs; i++) {
|
||||||
SRpcMsg *pMsg = NULL;
|
SRpcMsg *pMsg = NULL;
|
||||||
(void)taosGetQitem(qall, (void **)&pMsg);
|
int32_t num = taosGetQitem(qall, (void **)&pMsg);
|
||||||
const STraceId *trace = &pMsg->info.traceId;
|
const STraceId *trace = &pMsg->info.traceId;
|
||||||
|
|
||||||
dTrace("msg:%p, get from snode-write queue", pMsg);
|
dTrace("msg:%p, get from snode-write queue", pMsg);
|
||||||
|
|
|
@ -35,10 +35,14 @@ void vmGetVnodeLoads(SVnodeMgmt *pMgmt, SMonVloadInfo *pInfo, bool isReset) {
|
||||||
SVnodeObj *pVnode = *ppVnode;
|
SVnodeObj *pVnode = *ppVnode;
|
||||||
SVnodeLoad vload = {.vgId = pVnode->vgId};
|
SVnodeLoad vload = {.vgId = pVnode->vgId};
|
||||||
if (!pVnode->failed) {
|
if (!pVnode->failed) {
|
||||||
(void)vnodeGetLoad(pVnode->pImpl, &vload);
|
if (vnodeGetLoad(pVnode->pImpl, &vload) != 0) {
|
||||||
|
dError("failed to get vnode load");
|
||||||
|
}
|
||||||
if (isReset) vnodeResetLoad(pVnode->pImpl, &vload);
|
if (isReset) vnodeResetLoad(pVnode->pImpl, &vload);
|
||||||
}
|
}
|
||||||
(void)taosArrayPush(pInfo->pVloads, &vload);
|
if (taosArrayPush(pInfo->pVloads, &vload) == NULL) {
|
||||||
|
dError("failed to push vnode load");
|
||||||
|
}
|
||||||
pIter = taosHashIterate(pMgmt->hash, pIter);
|
pIter = taosHashIterate(pMgmt->hash, pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +120,9 @@ void vmGetMonitorInfo(SVnodeMgmt *pMgmt, SMonVmInfo *pInfo) {
|
||||||
pMgmt->state.numOfBatchInsertReqs = numOfBatchInsertReqs;
|
pMgmt->state.numOfBatchInsertReqs = numOfBatchInsertReqs;
|
||||||
pMgmt->state.numOfBatchInsertSuccessReqs = numOfBatchInsertSuccessReqs;
|
pMgmt->state.numOfBatchInsertSuccessReqs = numOfBatchInsertSuccessReqs;
|
||||||
|
|
||||||
(void)tfsGetMonitorInfo(pMgmt->pTfs, &pInfo->tfs);
|
if (tfsGetMonitorInfo(pMgmt->pTfs, &pInfo->tfs) != 0) {
|
||||||
|
dError("failed to get tfs monitor info");
|
||||||
|
}
|
||||||
taosArrayDestroy(pVloads);
|
taosArrayDestroy(pVloads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,7 +851,9 @@ int32_t vmProcessDropVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
vmCloseVnode(pMgmt, pVnode, false);
|
vmCloseVnode(pMgmt, pVnode, false);
|
||||||
(void)vmWriteVnodeListToFile(pMgmt);
|
if (vmWriteVnodeListToFile(pMgmt) != 0) {
|
||||||
|
dError("vgId:%d, failed to write vnode list since %s", vgId, terrstr());
|
||||||
|
}
|
||||||
|
|
||||||
dInfo("vgId:%d, is dropped", vgId);
|
dInfo("vgId:%d, is dropped", vgId);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -24,7 +24,7 @@ int32_t vmGetPrimaryDisk(SVnodeMgmt *pMgmt, int32_t vgId) {
|
||||||
SVnodeObj *pVnode = NULL;
|
SVnodeObj *pVnode = NULL;
|
||||||
|
|
||||||
(void)taosThreadRwlockRdlock(&pMgmt->lock);
|
(void)taosThreadRwlockRdlock(&pMgmt->lock);
|
||||||
(void)taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
|
int32_t r = taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
|
||||||
if (pVnode != NULL) {
|
if (pVnode != NULL) {
|
||||||
diskId = pVnode->diskPrimary;
|
diskId = pVnode->diskPrimary;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ SVnodeObj *vmAcquireVnodeImpl(SVnodeMgmt *pMgmt, int32_t vgId, bool strict) {
|
||||||
SVnodeObj *pVnode = NULL;
|
SVnodeObj *pVnode = NULL;
|
||||||
|
|
||||||
(void)taosThreadRwlockRdlock(&pMgmt->lock);
|
(void)taosThreadRwlockRdlock(&pMgmt->lock);
|
||||||
(void)taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
|
int32_t r = taosHashGetDup(pMgmt->hash, &vgId, sizeof(int32_t), (void *)&pVnode);
|
||||||
if (pVnode == NULL || strict && (pVnode->dropped || pVnode->failed)) {
|
if (pVnode == NULL || strict && (pVnode->dropped || pVnode->failed)) {
|
||||||
terrno = TSDB_CODE_VND_INVALID_VGROUP_ID;
|
terrno = TSDB_CODE_VND_INVALID_VGROUP_ID;
|
||||||
pVnode = NULL;
|
pVnode = NULL;
|
||||||
|
@ -165,7 +165,7 @@ int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl) {
|
||||||
|
|
||||||
(void)taosThreadRwlockWrlock(&pMgmt->lock);
|
(void)taosThreadRwlockWrlock(&pMgmt->lock);
|
||||||
SVnodeObj *pOld = NULL;
|
SVnodeObj *pOld = NULL;
|
||||||
(void)taosHashGetDup(pMgmt->hash, &pVnode->vgId, sizeof(int32_t), (void *)&pOld);
|
int32_t r = taosHashGetDup(pMgmt->hash, &pVnode->vgId, sizeof(int32_t), (void *)&pOld);
|
||||||
if (pOld) {
|
if (pOld) {
|
||||||
vmFreeVnodeObj(&pOld);
|
vmFreeVnodeObj(&pOld);
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode, bool commitAndRemoveWal)
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)taosThreadRwlockWrlock(&pMgmt->lock);
|
(void)taosThreadRwlockWrlock(&pMgmt->lock);
|
||||||
(void)taosHashRemove(pMgmt->hash, &pVnode->vgId, sizeof(int32_t));
|
int32_t r = taosHashRemove(pMgmt->hash, &pVnode->vgId, sizeof(int32_t));
|
||||||
(void)taosThreadRwlockUnlock(&pMgmt->lock);
|
(void)taosThreadRwlockUnlock(&pMgmt->lock);
|
||||||
vmReleaseVnode(pMgmt, pVnode);
|
vmReleaseVnode(pMgmt, pVnode);
|
||||||
|
|
||||||
|
@ -233,8 +233,12 @@ void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode, bool commitAndRemoveWal)
|
||||||
|
|
||||||
if (commitAndRemoveWal) {
|
if (commitAndRemoveWal) {
|
||||||
dInfo("vgId:%d, commit data for vnode split", pVnode->vgId);
|
dInfo("vgId:%d, commit data for vnode split", pVnode->vgId);
|
||||||
(void)vnodeSyncCommit(pVnode->pImpl);
|
if (vnodeSyncCommit(pVnode->pImpl) != 0) {
|
||||||
(void)vnodeBegin(pVnode->pImpl);
|
dError("vgId:%d, failed to commit data", pVnode->vgId);
|
||||||
|
}
|
||||||
|
if (vnodeBegin(pVnode->pImpl) != 0) {
|
||||||
|
dError("vgId:%d, failed to begin", pVnode->vgId);
|
||||||
|
}
|
||||||
dInfo("vgId:%d, commit data finished", pVnode->vgId);
|
dInfo("vgId:%d, commit data finished", pVnode->vgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,8 +252,12 @@ _closed:
|
||||||
if (commitAndRemoveWal) {
|
if (commitAndRemoveWal) {
|
||||||
snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d%swal", TD_DIRSEP, pVnode->vgId, TD_DIRSEP);
|
snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d%swal", TD_DIRSEP, pVnode->vgId, TD_DIRSEP);
|
||||||
dInfo("vgId:%d, remove all wals, path:%s", pVnode->vgId, path);
|
dInfo("vgId:%d, remove all wals, path:%s", pVnode->vgId, path);
|
||||||
(void)tfsRmdir(pMgmt->pTfs, path);
|
if (tfsRmdir(pMgmt->pTfs, path) != 0) {
|
||||||
(void)tfsMkdir(pMgmt->pTfs, path);
|
dTrace("vgId:%d, failed to remove wals, path:%s", pVnode->vgId, path);
|
||||||
|
}
|
||||||
|
if (tfsMkdir(pMgmt->pTfs, path) != 0) {
|
||||||
|
dTrace("vgId:%d, failed to create wals, path:%s", pVnode->vgId, path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pVnode->dropped) {
|
if (pVnode->dropped) {
|
||||||
|
@ -289,11 +297,22 @@ static void *vmOpenVnodeInThread(void *param) {
|
||||||
SVnodeMgmt *pMgmt = pThread->pMgmt;
|
SVnodeMgmt *pMgmt = pThread->pMgmt;
|
||||||
char path[TSDB_FILENAME_LEN];
|
char path[TSDB_FILENAME_LEN];
|
||||||
|
|
||||||
dInfo("thread:%d, start to open %d vnodes", pThread->threadIndex, pThread->vnodeNum);
|
dInfo("thread:%d, start to open or destroy %d vnodes", pThread->threadIndex, pThread->vnodeNum);
|
||||||
setThreadName("open-vnodes");
|
setThreadName("open-vnodes");
|
||||||
|
|
||||||
for (int32_t v = 0; v < pThread->vnodeNum; ++v) {
|
for (int32_t v = 0; v < pThread->vnodeNum; ++v) {
|
||||||
SWrapperCfg *pCfg = &pThread->pCfgs[v];
|
SWrapperCfg *pCfg = &pThread->pCfgs[v];
|
||||||
|
if (pCfg->dropped) {
|
||||||
|
char stepDesc[TSDB_STEP_DESC_LEN] = {0};
|
||||||
|
snprintf(stepDesc, TSDB_STEP_DESC_LEN, "vgId:%d, start to destroy, %d of %d have been dropped", pCfg->vgId,
|
||||||
|
pMgmt->state.openVnodes, pMgmt->state.totalVnodes);
|
||||||
|
tmsgReportStartup("vnode-destroy", stepDesc);
|
||||||
|
|
||||||
|
snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, pCfg->vgId);
|
||||||
|
vnodeDestroy(pCfg->vgId, path, pMgmt->pTfs, 0);
|
||||||
|
pThread->updateVnodesList = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
char stepDesc[TSDB_STEP_DESC_LEN] = {0};
|
char stepDesc[TSDB_STEP_DESC_LEN] = {0};
|
||||||
snprintf(stepDesc, TSDB_STEP_DESC_LEN, "vgId:%d, start to restore, %d of %d have been opened", pCfg->vgId,
|
snprintf(stepDesc, TSDB_STEP_DESC_LEN, "vgId:%d, start to restore, %d of %d have been opened", pCfg->vgId,
|
||||||
|
|
|
@ -187,7 +187,9 @@ static void vmProcessSyncQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOf
|
||||||
static void vmSendResponse(SRpcMsg *pMsg) {
|
static void vmSendResponse(SRpcMsg *pMsg) {
|
||||||
if (pMsg->info.handle) {
|
if (pMsg->info.handle) {
|
||||||
SRpcMsg rsp = {.info = pMsg->info, .code = terrno};
|
SRpcMsg rsp = {.info = pMsg->info, .code = terrno};
|
||||||
(void)rpcSendResponse(&rsp);
|
if (rpcSendResponse(&rsp) != 0) {
|
||||||
|
dError("failed to send response since %s", terrstr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,10 +391,28 @@ int32_t vmAllocQueue(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) {
|
||||||
SMultiWorkerCfg scfg = {.max = 1, .name = "vnode-sync", .fp = (FItems)vmProcessSyncQueue, .param = pVnode};
|
SMultiWorkerCfg scfg = {.max = 1, .name = "vnode-sync", .fp = (FItems)vmProcessSyncQueue, .param = pVnode};
|
||||||
SMultiWorkerCfg sccfg = {.max = 1, .name = "vnode-sync-rd", .fp = (FItems)vmProcessSyncQueue, .param = pVnode};
|
SMultiWorkerCfg sccfg = {.max = 1, .name = "vnode-sync-rd", .fp = (FItems)vmProcessSyncQueue, .param = pVnode};
|
||||||
SMultiWorkerCfg acfg = {.max = 1, .name = "vnode-apply", .fp = (FItems)vnodeApplyWriteMsg, .param = pVnode->pImpl};
|
SMultiWorkerCfg acfg = {.max = 1, .name = "vnode-apply", .fp = (FItems)vnodeApplyWriteMsg, .param = pVnode->pImpl};
|
||||||
(void)tMultiWorkerInit(&pVnode->pWriteW, &wcfg);
|
code = tMultiWorkerInit(&pVnode->pWriteW, &wcfg);
|
||||||
(void)tMultiWorkerInit(&pVnode->pSyncW, &scfg);
|
if (code) {
|
||||||
(void)tMultiWorkerInit(&pVnode->pSyncRdW, &sccfg);
|
return code;
|
||||||
(void)tMultiWorkerInit(&pVnode->pApplyW, &acfg);
|
}
|
||||||
|
code = tMultiWorkerInit(&pVnode->pSyncW, &scfg);
|
||||||
|
if (code) {
|
||||||
|
tMultiWorkerCleanup(&pVnode->pWriteW);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
code = tMultiWorkerInit(&pVnode->pSyncRdW, &sccfg);
|
||||||
|
if (code) {
|
||||||
|
tMultiWorkerCleanup(&pVnode->pWriteW);
|
||||||
|
tMultiWorkerCleanup(&pVnode->pSyncW);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
code = tMultiWorkerInit(&pVnode->pApplyW, &acfg);
|
||||||
|
if (code) {
|
||||||
|
tMultiWorkerCleanup(&pVnode->pWriteW);
|
||||||
|
tMultiWorkerCleanup(&pVnode->pSyncW);
|
||||||
|
tMultiWorkerCleanup(&pVnode->pSyncRdW);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
pVnode->pQueryQ = tQueryAutoQWorkerAllocQueue(&pMgmt->queryPool, pVnode, (FItem)vmProcessQueryQueue);
|
pVnode->pQueryQ = tQueryAutoQWorkerAllocQueue(&pMgmt->queryPool, pVnode, (FItem)vmProcessQueryQueue);
|
||||||
pVnode->pStreamQ = tAutoQWorkerAllocQueue(&pMgmt->streamPool, pVnode, (FItem)vmProcessStreamQueue);
|
pVnode->pStreamQ = tAutoQWorkerAllocQueue(&pMgmt->streamPool, pVnode, (FItem)vmProcessStreamQueue);
|
||||||
|
|
|
@ -47,8 +47,14 @@ static int32_t dmCheckRepeatInit(SDnode *pDnode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t dmInitSystem() {
|
static int32_t dmInitSystem() {
|
||||||
(void)taosIgnSIGPIPE();
|
if (taosIgnSIGPIPE() != 0) {
|
||||||
(void)taosBlockSIGPIPE();
|
dError("failed to ignore SIGPIPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taosBlockSIGPIPE() != 0) {
|
||||||
|
dError("failed to block SIGPIPE");
|
||||||
|
}
|
||||||
|
|
||||||
taosResolveCRC();
|
taosResolveCRC();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -204,7 +210,9 @@ void dmCleanup() {
|
||||||
auditCleanup();
|
auditCleanup();
|
||||||
syncCleanUp();
|
syncCleanUp();
|
||||||
walCleanUp();
|
walCleanUp();
|
||||||
(void)udfcClose();
|
if (udfcClose() != 0) {
|
||||||
|
dError("failed to close udfc");
|
||||||
|
}
|
||||||
udfStopUdfd();
|
udfStopUdfd();
|
||||||
taosStopCacheRefreshWorker();
|
taosStopCacheRefreshWorker();
|
||||||
(void)dmDiskClose();
|
(void)dmDiskClose();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue