Merge branch 'develop' into feature/TD-2581
This commit is contained in:
commit
e9f664f922
|
@ -13,3 +13,6 @@
|
|||
[submodule "deps/jemalloc"]
|
||||
path = deps/jemalloc
|
||||
url = https://github.com/jemalloc/jemalloc
|
||||
[submodule "deps/TSZ"]
|
||||
path = deps/TSZ
|
||||
url = https://github.com/taosdata/TSZ.git
|
||||
|
|
|
@ -83,6 +83,8 @@ IF (TD_ARM_64)
|
|||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "arm64 is defined")
|
||||
SET(COMMON_FLAGS "-Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lua/src)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_ARM_32)
|
||||
|
@ -91,6 +93,8 @@ IF (TD_ARM_32)
|
|||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "arm32 is defined")
|
||||
SET(COMMON_FLAGS "-Wall -Werror -fPIC -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wno-incompatible-pointer-types ")
|
||||
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lua/src)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_MIPS_64)
|
||||
|
@ -143,6 +147,7 @@ IF (TD_LINUX)
|
|||
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lua/src)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_DARWIN_64)
|
||||
|
@ -164,6 +169,7 @@ IF (TD_DARWIN_64)
|
|||
SET(RELEASE_FLAGS "-Og")
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lua/src)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_WINDOWS)
|
||||
|
@ -194,6 +200,7 @@ IF (TD_WINDOWS)
|
|||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/wepoll/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MsvcLibX/include)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lua/src)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_WINDOWS_64)
|
||||
|
|
|
@ -91,3 +91,12 @@ SET(TD_MEMORY_SANITIZER FALSE)
|
|||
IF (${MEMORY_SANITIZER} MATCHES "true")
|
||||
SET(TD_MEMORY_SANITIZER TRUE)
|
||||
ENDIF ()
|
||||
|
||||
IF (${TSZ_ENABLED} MATCHES "true")
|
||||
# define add
|
||||
MESSAGE(STATUS "build with TSZ enabled")
|
||||
ADD_DEFINITIONS(-DTD_TSZ)
|
||||
set(VAR_TSZ "TSZ" CACHE INTERNAL "global variant tsz" )
|
||||
ELSE()
|
||||
set(VAR_TSZ "" CACHE INTERNAL "global variant empty" )
|
||||
ENDIF()
|
||||
|
|
|
@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
|
|||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-*-dist.jar DESTINATION connector/jdbc)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.33-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
|
|
|
@ -4,7 +4,7 @@ PROJECT(TDengine)
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "2.1.4.1")
|
||||
SET(TD_VER_NUMBER "2.1.5.0")
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED VERCOMPATIBLE)
|
||||
|
|
|
@ -15,7 +15,6 @@ ADD_SUBDIRECTORY(cJson)
|
|||
ADD_SUBDIRECTORY(wepoll)
|
||||
ADD_SUBDIRECTORY(MsvcLibX)
|
||||
ADD_SUBDIRECTORY(rmonotonic)
|
||||
|
||||
ADD_SUBDIRECTORY(lua)
|
||||
|
||||
IF (TD_LINUX AND TD_MQTT)
|
||||
|
@ -38,3 +37,7 @@ IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
|
|||
BUILD_COMMAND ${MAKE}
|
||||
)
|
||||
ENDIF ()
|
||||
|
||||
IF (${TSZ_ENABLED} MATCHES "true")
|
||||
ADD_SUBDIRECTORY(TSZ)
|
||||
ENDIF()
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 0ca5b15a8eac40327dd737be52c926fa5675712c
|
|
@ -126,7 +126,7 @@ taos> source <filename>;
|
|||
$ taosdemo
|
||||
```
|
||||
|
||||
该命令将在数据库 test 下面自动创建一张超级表 meters,该超级表下有 1 万张表,表名为 "t0" 到 "t9999",每张表有 1 万条记录,每条记录有 (ts, current, voltage, phase) 四个字段,时间戳从 "2017-07-14 10:40:00 000" 到 "2017-07-14 10:40:09 999",每张表带有标签 location 和 groupdId,groupdId 被设置为 1 到 10, location 被设置为 "beijing" 或者 "shanghai"。
|
||||
该命令将在数据库 test 下面自动创建一张超级表 meters,该超级表下有 1 万张表,表名为 "d0" 到 "d9999",每张表有 1 万条记录,每条记录有 (ts, current, voltage, phase) 四个字段,时间戳从 "2017-07-14 10:40:00 000" 到 "2017-07-14 10:40:09 999",每张表带有标签 location 和 groupdId,groupdId 被设置为 1 到 10, location 被设置为 "beijing" 或者 "shanghai"。
|
||||
|
||||
执行这条命令大概需要几分钟,最后共插入 1 亿条记录。
|
||||
|
||||
|
@ -156,10 +156,10 @@ taos> select count(*) from test.meters where location="beijing";
|
|||
taos> select avg(current), max(voltage), min(phase) from test.meters where groupdId=10;
|
||||
```
|
||||
|
||||
- 对表 t10 按 10s 进行平均值、最大值和最小值聚合统计:
|
||||
- 对表 d10 按 10s 进行平均值、最大值和最小值聚合统计:
|
||||
|
||||
```mysql
|
||||
taos> select avg(current), max(voltage), min(phase) from test.t10 interval(10s);
|
||||
taos> select avg(current), max(voltage), min(phase) from test.d10 interval(10s);
|
||||
```
|
||||
|
||||
**Note:** taosdemo 命令本身带有很多选项,配置表的数目、记录条数等等,请执行 `taosdemo --help` 详细列出。您可以设置不同参数进行体验。
|
||||
|
|
|
@ -715,7 +715,7 @@ Query OK, 1 row(s) in set (0.001091s)
|
|||
2. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。
|
||||
3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))`。
|
||||
4. 从 2.0.17.0 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。
|
||||
5. 从 2.1.4.0 版本开始,条件过滤开始支持 IN 算子,例如 `WHERE city IN ('Beijing', 'Shanghai')`。说明:BOOL 类型写作 `{true, false}` 或 `{0, 1}` 均可,但不能写作 0、1 之外的整数;FLOAT 和 DOUBLE 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功。<!-- REPLACE_OPEN_TO_ENTERPRISE__IN_OPERATOR_AND_UNSIGNED_INTEGER -->
|
||||
5. 从 2.1.4.0 版本开始,条件过滤开始支持 IN 算子,例如 `WHERE city IN ('Beijing', 'Shanghai')`。说明:BOOL 类型写作 `{true, false}` 或 `{0, 1}` 均可,但不能写作 0、1 之外的整数;FLOAT 和 DOUBLE 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功;TIMESTAMP 类型支持非主键的列。<!-- REPLACE_OPEN_TO_ENTERPRISE__IN_OPERATOR_AND_UNSIGNED_INTEGER -->
|
||||
|
||||
<!--
|
||||
<a class="anchor" id="having"></a>
|
||||
|
@ -1338,7 +1338,8 @@ SELECT function_list FROM stb_name
|
|||
- 查询过滤、聚合等操作按照每个切分窗口为独立的单位执行。聚合查询目前支持三种窗口的划分方式:
|
||||
1. 时间窗口:聚合时间段的窗口宽度由关键词 INTERVAL 指定,最短时间间隔 10 毫秒(10a);并且支持偏移 offset(偏移必须小于间隔),也即时间窗口划分与“UTC 时刻 0”相比的偏移量。SLIDING 语句用于指定聚合时间段的前向增量,也即每次窗口向前滑动的时长。当 SLIDING 与 INTERVAL 取值相等的时候,滑动窗口即为翻转窗口。
|
||||
* 从 2.1.5.0 版本开始,INTERVAL 语句允许的最短时间间隔调整为 1 微秒(1u),当然如果所查询的 DATABASE 的时间精度设置为毫秒级,那么允许的最短时间间隔为 1 毫秒(1a)。
|
||||
2. 状态窗口:使用整数(布尔值)或字符串来标识产生记录时设备的状态量,产生的记录如果具有相同的状态量取值则归属于同一个状态窗口,数值改变后该窗口关闭。状态量所对应的列作为 STATE_WINDOW 语句的参数来指定。
|
||||
* **注意:**用到 INTERVAL 语句时,除非极特殊的情况,都要求把客户端和服务端的 taos.cfg 配置文件中的 timezone 参数配置为相同的取值,以避免时间处理函数频繁进行跨时区转换而导致的严重性能影响。
|
||||
2. 状态窗口:使用整数或布尔值来标识产生记录时设备的状态量,产生的记录如果具有相同的状态量取值则归属于同一个状态窗口,数值改变后该窗口关闭。状态量所对应的列作为 STATE_WINDOW 语句的参数来指定。
|
||||
3. 会话窗口:时间戳所在的列由 SESSION 语句的 ts_col 参数指定,会话窗口根据相邻两条记录的时间戳差值来确定是否属于同一个会话——如果时间戳差异在 tol_val 以内,则认为记录仍属于同一个窗口;如果时间变化超过 tol_val,则自动开启下一个窗口。
|
||||
- WHERE 语句可以指定查询的起止时间和其他过滤条件。
|
||||
- FILL 语句指定某一窗口区间数据缺失的情况下的填充模式。填充模式包括以下几种:
|
||||
|
|
|
@ -1132,7 +1132,7 @@ TDengine supports aggregations over data, they are listed below:
|
|||
```
|
||||
Function: Return the difference between the max value and the min value of a column in statistics /STable.
|
||||
|
||||
Return Data Type: Same as applicable fields.
|
||||
Return Data Type: Double.
|
||||
|
||||
Applicable Fields: All types except binary, nchar, bool.
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ echo "version=${version}"
|
|||
#docker manifest rm tdengine/tdengine
|
||||
#docker manifest rm tdengine/tdengine:${version}
|
||||
if [ "$verType" == "beta" ]; then
|
||||
docker manifest rm tdengine/tdengine:latest
|
||||
docker manifest create -a tdengine/tdengine-beta:${version} tdengine/tdengine-amd64-beta:${version} tdengine/tdengine-aarch64-beta:${version} tdengine/tdengine-aarch32-beta:${version}
|
||||
docker manifest create -a tdengine/tdengine-beta:latest tdengine/tdengine-amd64-beta:latest tdengine/tdengine-aarch64-beta:latest tdengine/tdengine-aarch32-beta:latest
|
||||
docker login -u tdengine -p ${passWord} #replace the docker registry username and password
|
||||
|
@ -51,6 +52,7 @@ if [ "$verType" == "beta" ]; then
|
|||
docker manifest push tdengine/tdengine-beta:${version}
|
||||
|
||||
elif [ "$verType" == "stable" ]; then
|
||||
docker manifest rm tdengine/tdengine:latest
|
||||
docker manifest create -a tdengine/tdengine:${version} tdengine/tdengine-amd64:${version} tdengine/tdengine-aarch64:${version} tdengine/tdengine-aarch32:${version}
|
||||
docker manifest create -a tdengine/tdengine:latest tdengine/tdengine-amd64:latest tdengine/tdengine-aarch64:latest tdengine/tdengine-aarch32:latest
|
||||
docker login -u tdengine -p ${passWord} #replace the docker registry username and password
|
||||
|
|
|
@ -67,8 +67,10 @@ done
|
|||
|
||||
if [ "$verType" == "beta" ]; then
|
||||
dockername=${cpuType}-${verType}
|
||||
dirName=${pkgFile%-beta*}
|
||||
elif [ "$verType" == "stable" ]; then
|
||||
dockername=${cpuType}
|
||||
dirName=${pkgFile%-Linux*}
|
||||
else
|
||||
echo "unknow verType, nor stabel or beta"
|
||||
exit 1
|
||||
|
@ -84,11 +86,10 @@ comunityArchiveDir=/nas/TDengine/v$version/community # community version’pac
|
|||
cd ${scriptDir}
|
||||
cp -f ${comunityArchiveDir}/${pkgFile} .
|
||||
|
||||
dirName=${pkgFile%-Linux*}
|
||||
echo "dirName=${dirName}"
|
||||
|
||||
|
||||
docker build --rm -f "Dockerfile" -t tdengine/tdengine-${dockername}:${version} "." --build-arg pkgFile=${pkgFile} --build-arg dirName=${dirName}
|
||||
docker build --rm -f "Dockerfile" --network=host -t tdengine/tdengine-${dockername}:${version} "." --build-arg pkgFile=${pkgFile} --build-arg dirName=${dirName}
|
||||
docker login -u tdengine -p ${passWord} #replace the docker registry username and password
|
||||
docker push tdengine/tdengine-${dockername}:${version}
|
||||
|
||||
|
|
|
@ -182,7 +182,13 @@ function install_jemalloc() {
|
|||
${csudo} /usr/bin/install -c -d /usr/local/share/man/man3
|
||||
${csudo} /usr/bin/install -c -m 644 ${jemalloc_dir}/share/man/man3/jemalloc.3 /usr/local/share/man/man3
|
||||
fi
|
||||
|
||||
if [ -d /etc/ld.so.conf.d ]; then
|
||||
${csudo} echo "/usr/local/lib" > /etc/ld.so.conf.d/jemalloc.conf
|
||||
${csudo} ldconfig
|
||||
else
|
||||
echo "/etc/ld.so.conf.d not found!"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ function install_service() {
|
|||
}
|
||||
|
||||
function update_TDengine() {
|
||||
echo -e "${GREEN}Start to update TDEngine...${NC}"
|
||||
echo -e "${GREEN}Start to update TDengine...${NC}"
|
||||
# Stop the service if running
|
||||
|
||||
if [ "$osType" != "Darwin" ]; then
|
||||
|
|
|
@ -59,7 +59,7 @@ pkg_name=${install_dir}-${osType}-${cpuType}
|
|||
# exit 1
|
||||
# fi
|
||||
|
||||
if [ "$verType" == "beta" ]; then
|
||||
if [[ "$verType" == "beta" ]] || [[ "$verType" == "preRelease" ]]; then
|
||||
pkg_name=${install_dir}-${verType}-${osType}-${cpuType}
|
||||
elif [ "$verType" == "stable" ]; then
|
||||
pkg_name=${pkg_name}
|
||||
|
|
|
@ -182,7 +182,7 @@ pkg_name=${install_dir}-${osType}-${cpuType}
|
|||
# exit 1
|
||||
# fi
|
||||
|
||||
if [ "$verType" == "beta" ]; then
|
||||
if [[ "$verType" == "beta" ]] || [[ "$verType" == "preRelease" ]]; then
|
||||
pkg_name=${install_dir}-${verType}-${osType}-${cpuType}
|
||||
elif [ "$verType" == "stable" ]; then
|
||||
pkg_name=${pkg_name}
|
||||
|
|
|
@ -67,6 +67,39 @@ mkdir -p ${install_dir}
|
|||
mkdir -p ${install_dir}/inc && cp ${header_files} ${install_dir}/inc
|
||||
mkdir -p ${install_dir}/cfg && cp ${cfg_dir}/taos.cfg ${install_dir}/cfg/taos.cfg
|
||||
|
||||
if [ -f ${build_dir}/bin/jemalloc-config ]; then
|
||||
mkdir -p ${install_dir}/jemalloc/{bin,lib,lib/pkgconfig,include/jemalloc,share/doc/jemalloc,share/man/man3}
|
||||
cp ${build_dir}/bin/jemalloc-config ${install_dir}/jemalloc/bin
|
||||
if [ -f ${build_dir}/bin/jemalloc.sh ]; then
|
||||
cp ${build_dir}/bin/jemalloc.sh ${install_dir}/jemalloc/bin
|
||||
fi
|
||||
if [ -f ${build_dir}/bin/jeprof ]; then
|
||||
cp ${build_dir}/bin/jeprof ${install_dir}/jemalloc/bin
|
||||
fi
|
||||
if [ -f ${build_dir}/include/jemalloc/jemalloc.h ]; then
|
||||
cp ${build_dir}/include/jemalloc/jemalloc.h ${install_dir}/jemalloc/include/jemalloc
|
||||
fi
|
||||
if [ -f ${build_dir}/lib/libjemalloc.so.2 ]; then
|
||||
cp ${build_dir}/lib/libjemalloc.so.2 ${install_dir}/jemalloc/lib
|
||||
ln -sf libjemalloc.so.2 ${install_dir}/jemalloc/lib/libjemalloc.so
|
||||
fi
|
||||
if [ -f ${build_dir}/lib/libjemalloc.a ]; then
|
||||
cp ${build_dir}/lib/libjemalloc.a ${install_dir}/jemalloc/lib
|
||||
fi
|
||||
if [ -f ${build_dir}/lib/libjemalloc_pic.a ]; then
|
||||
cp ${build_dir}/lib/libjemalloc_pic.a ${install_dir}/jemalloc/lib
|
||||
fi
|
||||
if [ -f ${build_dir}/lib/pkgconfig/jemalloc.pc ]; then
|
||||
cp ${build_dir}/lib/pkgconfig/jemalloc.pc ${install_dir}/jemalloc/lib/pkgconfig
|
||||
fi
|
||||
if [ -f ${build_dir}/share/doc/jemalloc/jemalloc.html ]; then
|
||||
cp ${build_dir}/share/doc/jemalloc/jemalloc.html ${install_dir}/jemalloc/share/doc/jemalloc
|
||||
fi
|
||||
if [ -f ${build_dir}/share/man/man3/jemalloc.3 ]; then
|
||||
cp ${build_dir}/share/man/man3/jemalloc.3 ${install_dir}/jemalloc/share/man/man3
|
||||
fi
|
||||
fi
|
||||
|
||||
sed -i '/dataDir/ {s/taos/power/g}' ${install_dir}/cfg/taos.cfg
|
||||
sed -i '/logDir/ {s/taos/power/g}' ${install_dir}/cfg/taos.cfg
|
||||
sed -i "s/TDengine/PowerDB/g" ${install_dir}/cfg/taos.cfg
|
||||
|
|
|
@ -215,7 +215,7 @@ pkg_name=${install_dir}-${osType}-${cpuType}
|
|||
# exit 1
|
||||
# fi
|
||||
|
||||
if [ "$verType" == "beta" ]; then
|
||||
if [[ "$verType" == "beta" ]] || [[ "$verType" == "preRelease" ]]; then
|
||||
pkg_name=${install_dir}-${verType}-${osType}-${cpuType}
|
||||
elif [ "$verType" == "stable" ]; then
|
||||
pkg_name=${pkg_name}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: tdengine
|
||||
base: core18
|
||||
version: '2.1.4.1'
|
||||
version: '2.1.5.0'
|
||||
icon: snap/gui/t-dengine.svg
|
||||
summary: an open-source big data platform designed and optimized for IoT.
|
||||
description: |
|
||||
|
@ -72,7 +72,7 @@ parts:
|
|||
- usr/bin/taosd
|
||||
- usr/bin/taos
|
||||
- usr/bin/taosdemo
|
||||
- usr/lib/libtaos.so.2.1.4.1
|
||||
- usr/lib/libtaos.so.2.1.5.0
|
||||
- usr/lib/libtaos.so.1
|
||||
- usr/lib/libtaos.so
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
static SBnThread tsBnThread;
|
||||
|
||||
static void *bnThreadFunc(void *arg) {
|
||||
setThreadName("bnThreadd");
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&tsBnThread.mutex);
|
||||
if (tsBnThread.stop) {
|
||||
|
|
|
@ -11,7 +11,7 @@ IF (TD_LINUX)
|
|||
|
||||
# set the static lib name
|
||||
ADD_LIBRARY(taos_static STATIC ${SRC})
|
||||
TARGET_LINK_LIBRARIES(taos_static common query trpc tutil pthread m rt)
|
||||
TARGET_LINK_LIBRARIES(taos_static common query trpc tutil pthread m rt ${VAR_TSZ})
|
||||
SET_TARGET_PROPERTIES(taos_static PROPERTIES OUTPUT_NAME "taos_static")
|
||||
SET_TARGET_PROPERTIES(taos_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
|
@ -37,13 +37,13 @@ ELSEIF (TD_DARWIN)
|
|||
|
||||
# set the static lib name
|
||||
ADD_LIBRARY(taos_static STATIC ${SRC})
|
||||
TARGET_LINK_LIBRARIES(taos_static common query trpc tutil pthread m)
|
||||
TARGET_LINK_LIBRARIES(taos_static common query trpc tutil pthread m lua)
|
||||
SET_TARGET_PROPERTIES(taos_static PROPERTIES OUTPUT_NAME "taos_static")
|
||||
SET_TARGET_PROPERTIES(taos_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
# generate dynamic library (*.dylib)
|
||||
ADD_LIBRARY(taos SHARED ${SRC})
|
||||
TARGET_LINK_LIBRARIES(taos common query trpc tutil pthread m)
|
||||
TARGET_LINK_LIBRARIES(taos common query trpc tutil pthread m lua)
|
||||
SET_TARGET_PROPERTIES(taos PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
#set version of .dylib
|
||||
|
@ -68,19 +68,19 @@ ELSEIF (TD_WINDOWS)
|
|||
IF (NOT TD_GODLL)
|
||||
SET_TARGET_PROPERTIES(taos PROPERTIES LINK_FLAGS /DEF:${TD_COMMUNITY_DIR}/src/client/src/taos.def)
|
||||
ENDIF ()
|
||||
TARGET_LINK_LIBRARIES(taos trpc tutil query)
|
||||
TARGET_LINK_LIBRARIES(taos trpc tutil query lua)
|
||||
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(CMAKE_MACOSX_RPATH 1)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux)
|
||||
|
||||
ADD_LIBRARY(taos_static STATIC ${SRC})
|
||||
TARGET_LINK_LIBRARIES(taos_static query trpc tutil pthread m)
|
||||
TARGET_LINK_LIBRARIES(taos_static query trpc tutil pthread m lua)
|
||||
SET_TARGET_PROPERTIES(taos_static PROPERTIES OUTPUT_NAME "taos_static")
|
||||
|
||||
# generate dynamic library (*.dylib)
|
||||
ADD_LIBRARY(taos SHARED ${SRC})
|
||||
TARGET_LINK_LIBRARIES(taos query trpc tutil pthread m)
|
||||
TARGET_LINK_LIBRARIES(taos query trpc tutil pthread m lua)
|
||||
|
||||
SET_TARGET_PROPERTIES(taos PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
|
|
|
@ -95,11 +95,23 @@ typedef struct SVgroupTableInfo {
|
|||
SArray *itemList; // SArray<STableIdInfo>
|
||||
} SVgroupTableInfo;
|
||||
|
||||
typedef struct SBlockKeyTuple {
|
||||
TSKEY skey;
|
||||
void* payloadAddr;
|
||||
} SBlockKeyTuple;
|
||||
|
||||
typedef struct SBlockKeyInfo {
|
||||
int32_t maxBytesAlloc;
|
||||
SBlockKeyTuple* pKeyTuple;
|
||||
} SBlockKeyInfo;
|
||||
|
||||
int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *len);
|
||||
|
||||
int32_t tscCreateDataBlock(size_t initialSize, int32_t rowSize, int32_t startOffset, SName* name, STableMeta* pTableMeta, STableDataBlocks** dataBlocks);
|
||||
void tscDestroyDataBlock(STableDataBlocks* pDataBlock, bool removeMeta);
|
||||
void tscSortRemoveDataBlockDupRows(STableDataBlocks* dataBuf);
|
||||
void tscSortRemoveDataBlockDupRowsRaw(STableDataBlocks* dataBuf);
|
||||
int tscSortRemoveDataBlockDupRows(STableDataBlocks* dataBuf, SBlockKeyInfo* pBlkKeyInfo);
|
||||
int32_t tsSetBlockInfo(SSubmitBlk *pBlocks, const STableMeta *pTableMeta, int32_t numOfRows);
|
||||
|
||||
void tscDestroyBoundColumnInfo(SParsedDataColInfo* pColInfo);
|
||||
void doRetrieveSubqueryData(SSchedMsg *pMsg);
|
||||
|
@ -108,6 +120,7 @@ SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint
|
|||
uint32_t offset);
|
||||
|
||||
void* tscDestroyBlockArrayList(SArray* pDataBlockList);
|
||||
void* tscDestroyUdfArrayList(SArray* pUdfList);
|
||||
void* tscDestroyBlockHashTable(SHashObj* pBlockHashTable, bool removeMeta);
|
||||
|
||||
int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock);
|
||||
|
@ -262,7 +275,8 @@ void tscVgroupTableCopy(SVgroupTableInfo* info, SVgroupTableInfo* pInfo);
|
|||
|
||||
int tscGetSTableVgroupInfo(SSqlObj* pSql, SQueryInfo* pQueryInfo);
|
||||
int tscGetTableMeta(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo);
|
||||
int tscGetTableMetaEx(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, bool createIfNotExists);
|
||||
int tscGetTableMetaEx(SSqlObj *pSql, STableMetaInfo *pTableMetaInfo, bool createIfNotExists, bool onlyLocal);
|
||||
int32_t tscGetUdfFromNode(SSqlObj *pSql, SQueryInfo* pQueryInfo);
|
||||
|
||||
void tscResetForNextRetrieve(SSqlRes* pRes);
|
||||
void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo);
|
||||
|
@ -309,10 +323,9 @@ bool hasMoreClauseToTry(SSqlObj* pSql);
|
|||
void tscFreeQueryInfo(SSqlCmd* pCmd, bool removeMeta);
|
||||
|
||||
void tscTryQueryNextVnode(SSqlObj *pSql, __async_cb_func_t fp);
|
||||
void tscAsyncQuerySingleRowForNextVnode(void *param, TAOS_RES *tres, int numOfRows);
|
||||
void tscTryQueryNextClause(SSqlObj* pSql, __async_cb_func_t fp);
|
||||
int tscSetMgmtEpSetFromCfg(const char *first, const char *second, SRpcCorEpSet *corEpSet);
|
||||
int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVgroupNameList, __async_cb_func_t fp);
|
||||
int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVgroupNameList, SArray* pUdfList, __async_cb_func_t fp, bool metaClone);
|
||||
|
||||
int tscTransferTableNameList(SSqlObj *pSql, const char *pNameList, int32_t length, SArray* pNameArray);
|
||||
|
||||
|
|
|
@ -88,13 +88,43 @@ typedef struct SBoundColumn {
|
|||
int32_t offset; // all column offset value
|
||||
} SBoundColumn;
|
||||
|
||||
typedef struct {
|
||||
uint16_t schemaColIdx;
|
||||
uint16_t boundIdx;
|
||||
uint16_t finalIdx;
|
||||
} SBoundIdxInfo;
|
||||
|
||||
typedef enum _COL_ORDER_STATUS {
|
||||
ORDER_STATUS_UNKNOWN = 0,
|
||||
ORDER_STATUS_ORDERED = 1,
|
||||
ORDER_STATUS_DISORDERED = 2,
|
||||
} EOrderStatus;
|
||||
|
||||
typedef struct SParsedDataColInfo {
|
||||
int16_t numOfCols;
|
||||
int16_t numOfBound;
|
||||
int32_t *boundedColumns;
|
||||
int32_t * boundedColumns; // bounded column idx according to schema
|
||||
SBoundColumn * cols;
|
||||
SBoundIdxInfo *colIdxInfo;
|
||||
int8_t orderStatus; // bounded columns:
|
||||
} SParsedDataColInfo;
|
||||
|
||||
#define IS_DATA_COL_ORDERED(s) ((s) == (int8_t)ORDER_STATUS_ORDERED)
|
||||
|
||||
typedef struct {
|
||||
SSchema * pSchema;
|
||||
int16_t sversion;
|
||||
int32_t flen;
|
||||
uint16_t nCols;
|
||||
void * buf;
|
||||
void * pDataBlock;
|
||||
SSubmitBlk *pSubmitBlk;
|
||||
} SMemRowBuilder;
|
||||
|
||||
typedef struct {
|
||||
TDRowLenT allNullLen;
|
||||
} SMemRowHelper;
|
||||
|
||||
typedef struct STableDataBlocks {
|
||||
SName tableName;
|
||||
int8_t tsSource; // where does the UNIX timestamp come from, server or client
|
||||
|
@ -108,6 +138,7 @@ typedef struct STableDataBlocks {
|
|||
uint32_t size;
|
||||
STableMeta *pTableMeta; // the tableMeta of current table, the table meta will be used during submit, keep a ref to avoid to be removed from cache
|
||||
char *pData;
|
||||
bool cloned;
|
||||
|
||||
SParsedDataColInfo boundColumnInfo;
|
||||
|
||||
|
@ -115,6 +146,7 @@ typedef struct STableDataBlocks {
|
|||
uint32_t numOfAllocedParams;
|
||||
uint32_t numOfParams;
|
||||
SParamInfo * params;
|
||||
SMemRowHelper rowHelper;
|
||||
} STableDataBlocks;
|
||||
|
||||
typedef struct {
|
||||
|
@ -128,6 +160,7 @@ typedef struct SInsertStatementParam {
|
|||
SHashObj *pTableBlockHashList; // data block for each table
|
||||
SArray *pDataBlocks; // SArray<STableDataBlocks*>. Merged submit block for each vgroup
|
||||
int8_t schemaAttached; // denote if submit block is built with table schema or not
|
||||
uint8_t payloadType; // EPayloadType. 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert
|
||||
STagData tagData; // NOTE: pTagData->data is used as a variant length array
|
||||
|
||||
int32_t batchSize; // for parameter ('?') binding and batch processing
|
||||
|
@ -139,6 +172,14 @@ typedef struct SInsertStatementParam {
|
|||
char *sql; // current sql statement position
|
||||
} SInsertStatementParam;
|
||||
|
||||
typedef enum {
|
||||
PAYLOAD_TYPE_KV = 0,
|
||||
PAYLOAD_TYPE_RAW = 1,
|
||||
} EPayloadType;
|
||||
|
||||
#define IS_RAW_PAYLOAD(t) \
|
||||
(((int)(t)) == PAYLOAD_TYPE_RAW) // 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert
|
||||
|
||||
// TODO extract sql parser supporter
|
||||
typedef struct {
|
||||
int command;
|
||||
|
@ -146,6 +187,7 @@ typedef struct {
|
|||
SInsertStatementParam insertParam;
|
||||
char reserve1[3]; // fix bus error on arm32
|
||||
int32_t count; // todo remove it
|
||||
bool subCmd;
|
||||
|
||||
char reserve2[3]; // fix bus error on arm32
|
||||
int16_t numOfCols;
|
||||
|
@ -242,6 +284,7 @@ typedef struct SSqlObj {
|
|||
void * pStream;
|
||||
void * pSubscription;
|
||||
char * sqlstr;
|
||||
void * pBuf; // table meta buffer
|
||||
char parseRetry;
|
||||
char retry;
|
||||
char maxRetry;
|
||||
|
@ -369,6 +412,7 @@ int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* s
|
|||
|
||||
int32_t tscValidateSqlInfo(SSqlObj *pSql, struct SSqlInfo *pInfo);
|
||||
|
||||
int32_t tsSetBlockInfo(SSubmitBlk *pBlocks, const STableMeta *pTableMeta, int32_t numOfRows);
|
||||
extern int32_t sentinel;
|
||||
extern SHashObj *tscVgroupMap;
|
||||
extern SHashObj *tscTableMetaInfo;
|
||||
|
@ -385,6 +429,11 @@ extern int (*tscBuildMsg[TSDB_SQL_MAX])(SSqlObj *pSql, SSqlInfo *pInfo);
|
|||
void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArray* tables);
|
||||
int16_t getNewResColId(SSqlCmd* pCmd);
|
||||
|
||||
int32_t schemaIdxCompar(const void *lhs, const void *rhs);
|
||||
int32_t boundIdxCompar(const void *lhs, const void *rhs);
|
||||
int initSMemRowHelper(SMemRowHelper *pHelper, SSchema *pSSchema, uint16_t nCols, uint16_t allNullColsLen);
|
||||
int32_t getExtendedRowSize(STableComInfo *tinfo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -946,3 +946,34 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI
|
|||
|
||||
return JNI_SUCCESS;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *env, jobject jobj,
|
||||
jobjectArray lines, jlong conn) {
|
||||
TAOS *taos = (TAOS *)conn;
|
||||
if (taos == NULL) {
|
||||
jniError("jobj:%p, connection already closed", jobj);
|
||||
return JNI_CONNECTION_NULL;
|
||||
}
|
||||
|
||||
int numLines = (*env)->GetArrayLength(env, lines);
|
||||
char** c_lines = calloc(numLines, sizeof(char*));
|
||||
|
||||
for (int i = 0; i < numLines; ++i) {
|
||||
jstring line = (jstring) ((*env)->GetObjectArrayElement(env, lines, i));
|
||||
c_lines[i] = (char*)(*env)->GetStringUTFChars(env, line, 0);
|
||||
}
|
||||
|
||||
int code = taos_insert_lines(taos, c_lines, numLines);
|
||||
|
||||
for (int i = 0; i < numLines; ++i) {
|
||||
jstring line = (jstring) ((*env)->GetObjectArrayElement(env, lines, i));
|
||||
(*env)->ReleaseStringUTFChars(env, line, c_lines[i]);
|
||||
}
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
jniError("jobj:%p, conn:%p, code:%s", jobj, taos, tstrerror(code));
|
||||
return JNI_TDENGINE_ERROR;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
|
@ -7,11 +7,16 @@ taos_connect_auth
|
|||
taos_close
|
||||
taos_stmt_init
|
||||
taos_stmt_prepare
|
||||
taos_stmt_set_tbname_tags
|
||||
taos_stmt_set_tbname
|
||||
taos_stmt_is_insert
|
||||
taos_stmt_num_params
|
||||
taos_stmt_bind_param
|
||||
taos_stmt_add_batch
|
||||
taos_stmt_execute
|
||||
taos_stmt_use_result
|
||||
taos_stmt_close
|
||||
taos_stmt_errstr
|
||||
taos_query
|
||||
taos_fetch_row
|
||||
taos_result_precision
|
||||
|
@ -37,6 +42,4 @@ taos_consume
|
|||
taos_unsubscribe
|
||||
taos_open_stream
|
||||
taos_close_stream
|
||||
taos_fetch_block
|
||||
taos_load_table_info
|
||||
|
||||
|
|
|
@ -602,6 +602,15 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
|
|||
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
|
||||
|
||||
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[functionId].mergeFunc(&pCtx[j]);
|
||||
}
|
||||
} else {
|
||||
|
@ -610,6 +619,15 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
|
|||
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
|
||||
|
||||
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[functionId].xFinalize(&pCtx[j]);
|
||||
}
|
||||
|
||||
|
@ -626,7 +644,11 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
|
|||
}
|
||||
|
||||
for(int32_t j = 0; j < numOfExpr; ++j) {
|
||||
aAggs[pCtx[j].functionId].init(&pCtx[j]);
|
||||
if (pCtx[j].functionId < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[pCtx[j].functionId].init(&pCtx[j], pCtx[j].resultInfo);
|
||||
}
|
||||
|
||||
for (int32_t j = 0; j < numOfExpr; ++j) {
|
||||
|
@ -638,6 +660,15 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
|
|||
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
|
||||
|
||||
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[functionId].mergeFunc(&pCtx[j]);
|
||||
}
|
||||
}
|
||||
|
@ -651,6 +682,15 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD
|
|||
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
|
||||
|
||||
doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[functionId].mergeFunc(&pCtx[j]);
|
||||
}
|
||||
}
|
||||
|
@ -871,7 +911,6 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
|
|||
|
||||
{
|
||||
if (pAggInfo->hasDataBlockForNewGroup) {
|
||||
pAggInfo->binfo.pRes->info.rows = 0;
|
||||
pAggInfo->hasPrev = false; // now we start from a new group data set.
|
||||
|
||||
// not belongs to the same group, return the result of current group;
|
||||
|
@ -880,7 +919,13 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
|
|||
|
||||
{ // reset output buffer
|
||||
for(int32_t j = 0; j < pOperator->numOfOutput; ++j) {
|
||||
aAggs[pAggInfo->binfo.pCtx[j].functionId].init(&pAggInfo->binfo.pCtx[j]);
|
||||
SQLFunctionCtx* pCtx = &pAggInfo->binfo.pCtx[j];
|
||||
if (pCtx->functionId < 0) {
|
||||
clearOutputBuf(&pAggInfo->binfo, &pAggInfo->bufCapacity);
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[pCtx->functionId].init(pCtx, pCtx->resultInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -933,6 +978,14 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pAggInfo->udfInfo, -1 * functionId - 1);
|
||||
|
||||
doInvokeUdf(pUdfInfo, &pAggInfo->binfo.pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
aAggs[functionId].xFinalize(&pAggInfo->binfo.pCtx[j]);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,10 +38,33 @@ enum {
|
|||
TSDB_USE_CLI_TS = 1,
|
||||
};
|
||||
|
||||
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
|
||||
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
|
||||
|
||||
static int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t *numOfRows);
|
||||
static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDataColInfo *pColInfo, SSchema *pSchema,
|
||||
char *str, char **end);
|
||||
|
||||
int32_t getExtendedRowSize(STableComInfo *tinfo) {
|
||||
return tinfo->rowSize + PAYLOAD_HEADER_LEN + PAYLOAD_COL_HEAD_LEN * tinfo->numOfColumns;
|
||||
}
|
||||
int initSMemRowHelper(SMemRowHelper *pHelper, SSchema *pSSchema, uint16_t nCols, uint16_t allNullColsLen) {
|
||||
pHelper->allNullLen = allNullColsLen; // TODO: get allNullColsLen when creating or altering table meta
|
||||
if (pHelper->allNullLen == 0) {
|
||||
for (uint16_t i = 0; i < nCols; ++i) {
|
||||
uint8_t type = pSSchema[i].type;
|
||||
int32_t typeLen = TYPE_BYTES[type];
|
||||
pHelper->allNullLen += typeLen;
|
||||
if (TSDB_DATA_TYPE_BINARY == type) {
|
||||
pHelper->allNullLen += (VARSTR_HEADER_SIZE + CHAR_BYTES);
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == type) {
|
||||
int len = VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE;
|
||||
pHelper->allNullLen += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int32_t tscToDouble(SStrToken *pToken, double *value, char **endPtr) {
|
||||
errno = 0;
|
||||
*value = strtold(pToken->z, endPtr);
|
||||
|
@ -378,6 +401,342 @@ int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, cha
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static FORCE_INLINE TDRowLenT tsSetPayloadColValue(char *payloadStart, char *payload, int16_t columnId,
|
||||
uint8_t columnType, const void *value, uint16_t valueLen, TDRowTLenT tOffset) {
|
||||
payloadColSetId(payload, columnId);
|
||||
payloadColSetType(payload, columnType);
|
||||
memcpy(POINTER_SHIFT(payloadStart,tOffset), value, valueLen);
|
||||
return valueLen;
|
||||
}
|
||||
|
||||
static int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pToken, char *payloadStart, char *primaryKeyStart,
|
||||
char *payload, char *msg, char **str, bool primaryKey, int16_t timePrec,
|
||||
TDRowTLenT tOffset, TDRowLenT *sizeAppend, TDRowLenT *dataRowColDeltaLen,
|
||||
TDRowLenT *kvRowColLen) {
|
||||
int64_t iv;
|
||||
int32_t ret;
|
||||
char * endptr = NULL;
|
||||
|
||||
if (IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) {
|
||||
return tscInvalidOperationMsg(msg, "invalid numeric data", pToken->z);
|
||||
}
|
||||
|
||||
switch (pSchema->type) {
|
||||
case TSDB_DATA_TYPE_BOOL: { // bool
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_BOOL), TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
||||
} else {
|
||||
if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) {
|
||||
if (strncmp(pToken->z, "true", pToken->n) == 0) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &TRUE_VALUE,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
||||
} else if (strncmp(pToken->z, "false", pToken->n) == 0) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &FALSE_VALUE,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
||||
} else {
|
||||
return tscSQLSyntaxErrMsg(msg, "invalid bool data", pToken->z);
|
||||
}
|
||||
} else if (pToken->type == TK_INTEGER) {
|
||||
iv = strtoll(pToken->z, NULL, 10);
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
((iv == 0) ? &FALSE_VALUE : &TRUE_VALUE), TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
||||
} else if (pToken->type == TK_FLOAT) {
|
||||
double dv = strtod(pToken->z, NULL);
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
((dv == 0) ? &FALSE_VALUE : &TRUE_VALUE), TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
||||
} else {
|
||||
return tscInvalidOperationMsg(msg, "invalid bool data", pToken->z);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_TINYINT), TYPE_BYTES[TSDB_DATA_TYPE_TINYINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid tinyint data", pToken->z);
|
||||
} else if (!IS_VALID_TINYINT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "data overflow", pToken->z);
|
||||
}
|
||||
|
||||
uint8_t tmpVal = (uint8_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_TINYINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_TINYINT]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_UTINYINT), TYPE_BYTES[TSDB_DATA_TYPE_UTINYINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid unsigned tinyint data", pToken->z);
|
||||
} else if (!IS_VALID_UTINYINT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "unsigned tinyint data overflow", pToken->z);
|
||||
}
|
||||
|
||||
uint8_t tmpVal = (uint8_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_UTINYINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_UTINYINT]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_SMALLINT), TYPE_BYTES[TSDB_DATA_TYPE_SMALLINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid smallint data", pToken->z);
|
||||
} else if (!IS_VALID_SMALLINT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "smallint data overflow", pToken->z);
|
||||
}
|
||||
|
||||
int16_t tmpVal = (int16_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_SMALLINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_SMALLINT]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend =
|
||||
tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_USMALLINT), TYPE_BYTES[TSDB_DATA_TYPE_USMALLINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid unsigned smallint data", pToken->z);
|
||||
} else if (!IS_VALID_USMALLINT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "unsigned smallint data overflow", pToken->z);
|
||||
}
|
||||
|
||||
uint16_t tmpVal = (uint16_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_USMALLINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_USMALLINT]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_INT), TYPE_BYTES[TSDB_DATA_TYPE_INT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid int data", pToken->z);
|
||||
} else if (!IS_VALID_INT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "int data overflow", pToken->z);
|
||||
}
|
||||
|
||||
int32_t tmpVal = (int32_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_INT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_INT]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_UINT), TYPE_BYTES[TSDB_DATA_TYPE_UINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid unsigned int data", pToken->z);
|
||||
} else if (!IS_VALID_UINT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "unsigned int data overflow", pToken->z);
|
||||
}
|
||||
|
||||
uint32_t tmpVal = (uint32_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_UINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_UINT]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_BIGINT), TYPE_BYTES[TSDB_DATA_TYPE_BIGINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid bigint data", pToken->z);
|
||||
} else if (!IS_VALID_BIGINT(iv)) {
|
||||
return tscInvalidOperationMsg(msg, "bigint data overflow", pToken->z);
|
||||
}
|
||||
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &iv,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_BIGINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BIGINT]);
|
||||
}
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_UBIGINT), TYPE_BYTES[TSDB_DATA_TYPE_UBIGINT], tOffset);
|
||||
} else {
|
||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid unsigned bigint data", pToken->z);
|
||||
} else if (!IS_VALID_UBIGINT((uint64_t)iv)) {
|
||||
return tscInvalidOperationMsg(msg, "unsigned bigint data overflow", pToken->z);
|
||||
}
|
||||
|
||||
uint64_t tmpVal = (uint64_t)iv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_UBIGINT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_UBIGINT]);
|
||||
}
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_FLOAT), TYPE_BYTES[TSDB_DATA_TYPE_FLOAT], tOffset);
|
||||
} else {
|
||||
double dv;
|
||||
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
|
||||
return tscInvalidOperationMsg(msg, "illegal float data", pToken->z);
|
||||
}
|
||||
|
||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
|
||||
isnan(dv)) {
|
||||
return tscInvalidOperationMsg(msg, "illegal float data", pToken->z);
|
||||
}
|
||||
|
||||
float tmpVal = (float)dv;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_FLOAT], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_FLOAT]);
|
||||
}
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
if (isNullStr(pToken)) {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_DOUBLE), TYPE_BYTES[TSDB_DATA_TYPE_DOUBLE], tOffset);
|
||||
} else {
|
||||
double dv;
|
||||
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
|
||||
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
|
||||
}
|
||||
|
||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
|
||||
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
|
||||
}
|
||||
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &dv,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_DOUBLE], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_DOUBLE]);
|
||||
}
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
// binary data cannot be null-terminated char string, otherwise the last char of the string is lost
|
||||
if (pToken->type == TK_NULL) {
|
||||
payloadColSetId(payload, pSchema->colId);
|
||||
payloadColSetType(payload, pSchema->type);
|
||||
memcpy(POINTER_SHIFT(payloadStart, tOffset), getNullValue(TSDB_DATA_TYPE_BINARY), VARSTR_HEADER_SIZE + CHAR_BYTES);
|
||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + CHAR_BYTES);
|
||||
} else { // too long values will return invalid sql, not be truncated automatically
|
||||
if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { // todo refactor
|
||||
return tscInvalidOperationMsg(msg, "string data overflow", pToken->z);
|
||||
}
|
||||
// STR_WITH_SIZE_TO_VARSTR(payload, pToken->z, pToken->n);
|
||||
|
||||
payloadColSetId(payload, pSchema->colId);
|
||||
payloadColSetType(payload, pSchema->type);
|
||||
varDataSetLen(POINTER_SHIFT(payloadStart,tOffset), pToken->n);
|
||||
memcpy(varDataVal(POINTER_SHIFT(payloadStart,tOffset)), pToken->z, pToken->n);
|
||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + pToken->n);
|
||||
*dataRowColDeltaLen += (TDRowLenT)(pToken->n - CHAR_BYTES);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + VARSTR_HEADER_SIZE + pToken->n);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
if (pToken->type == TK_NULL) {
|
||||
payloadColSetId(payload, pSchema->colId);
|
||||
payloadColSetType(payload, pSchema->type);
|
||||
memcpy(POINTER_SHIFT(payloadStart,tOffset), getNullValue(TSDB_DATA_TYPE_NCHAR), VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
|
||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
|
||||
} else {
|
||||
// if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
|
||||
int32_t output = 0;
|
||||
payloadColSetId(payload, pSchema->colId);
|
||||
payloadColSetType(payload, pSchema->type);
|
||||
if (!taosMbsToUcs4(pToken->z, pToken->n, varDataVal(POINTER_SHIFT(payloadStart,tOffset)),
|
||||
pSchema->bytes - VARSTR_HEADER_SIZE, &output)) {
|
||||
char buf[512] = {0};
|
||||
snprintf(buf, tListLen(buf), "%s", strerror(errno));
|
||||
return tscInvalidOperationMsg(msg, buf, pToken->z);
|
||||
}
|
||||
|
||||
varDataSetLen(POINTER_SHIFT(payloadStart,tOffset), output);
|
||||
|
||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + output);
|
||||
*dataRowColDeltaLen += (TDRowLenT)(output - sizeof(uint32_t));
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + VARSTR_HEADER_SIZE + output);
|
||||
}
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
if (pToken->type == TK_NULL) {
|
||||
if (primaryKey) {
|
||||
// When building SKVRow primaryKey, we should not skip even with NULL value.
|
||||
int64_t tmpVal = 0;
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, primaryKeyStart, pSchema->colId, pSchema->type, &tmpVal,
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP]);
|
||||
} else {
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
||||
getNullValue(TSDB_DATA_TYPE_TIMESTAMP),
|
||||
TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], tOffset);
|
||||
}
|
||||
} else {
|
||||
int64_t tmpVal;
|
||||
if (tsParseTime(pToken, &tmpVal, str, msg, timePrec) != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidOperationMsg(msg, "invalid timestamp", pToken->z);
|
||||
}
|
||||
|
||||
*sizeAppend = tsSetPayloadColValue(payloadStart, primaryKey ? primaryKeyStart : payload, pSchema->colId,
|
||||
pSchema->type, &tmpVal, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], tOffset);
|
||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* The server time/client time should not be mixed up in one sql string
|
||||
* Do not employ sort operation is not involved if server time is used.
|
||||
|
@ -414,24 +773,38 @@ int32_t tsCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, int32_t *len,
|
||||
char *tmpTokenBuf, SInsertStatementParam* pInsertParam) {
|
||||
int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, int32_t *len, char *tmpTokenBuf,
|
||||
SInsertStatementParam *pInsertParam) {
|
||||
int32_t index = 0;
|
||||
SStrToken sToken = {0};
|
||||
|
||||
SMemRowHelper *pHelper = &pDataBlocks->rowHelper;
|
||||
char * payload = pDataBlocks->pData + pDataBlocks->size;
|
||||
|
||||
SParsedDataColInfo *spd = &pDataBlocks->boundColumnInfo;
|
||||
SSchema * schema = tscGetTableSchema(pDataBlocks->pTableMeta);
|
||||
|
||||
TDRowTLenT dataRowLen = pHelper->allNullLen;
|
||||
TDRowTLenT kvRowLen = TD_MEM_ROW_KV_VER_SIZE;
|
||||
TDRowTLenT payloadValOffset = 0;
|
||||
TDRowLenT colValOffset = 0;
|
||||
ASSERT(dataRowLen > 0);
|
||||
|
||||
payloadSetNCols(payload, spd->numOfBound);
|
||||
payloadValOffset = payloadValuesOffset(payload); // rely on payloadNCols
|
||||
// payloadSetTLen(payload, payloadValOffset);
|
||||
|
||||
char *kvPrimaryKeyStart = payload + PAYLOAD_HEADER_LEN; // primaryKey in 1st column tuple
|
||||
char *kvStart = kvPrimaryKeyStart + PAYLOAD_COL_HEAD_LEN; // the column tuple behind the primaryKey
|
||||
|
||||
// 1. set the parsed value from sql string
|
||||
int32_t rowSize = 0;
|
||||
for (int i = 0; i < spd->numOfBound; ++i) {
|
||||
// the start position in data block buffer of current value in sql
|
||||
int32_t colIndex = spd->boundedColumns[i];
|
||||
|
||||
char *start = payload + spd->cols[colIndex].offset;
|
||||
SSchema *pSchema = &schema[colIndex];
|
||||
rowSize += pSchema->bytes;
|
||||
|
||||
SSchema *pSchema = &schema[colIndex]; // get colId here
|
||||
|
||||
index = 0;
|
||||
sToken = tStrGetToken(*str, &index, true);
|
||||
|
@ -453,7 +826,8 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
|
|||
|
||||
int16_t type = sToken.type;
|
||||
if ((type != TK_NOW && type != TK_INTEGER && type != TK_STRING && type != TK_FLOAT && type != TK_BOOL &&
|
||||
type != TK_NULL && type != TK_HEX && type != TK_OCT && type != TK_BIN) || (sToken.n == 0) || (type == TK_RP)) {
|
||||
type != TK_NULL && type != TK_HEX && type != TK_OCT && type != TK_BIN) ||
|
||||
(sToken.n == 0) || (type == TK_RP)) {
|
||||
return tscSQLSyntaxErrMsg(pInsertParam->msg, "invalid data or symbol", sToken.z);
|
||||
}
|
||||
|
||||
|
@ -488,41 +862,53 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
|
|||
}
|
||||
|
||||
bool isPrimaryKey = (colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
int32_t ret = tsParseOneColumn(pSchema, &sToken, start, pInsertParam->msg, str, isPrimaryKey, timePrec);
|
||||
TDRowLenT dataRowDeltaColLen = 0; // When combine the data as SDataRow, the delta len between all NULL columns.
|
||||
TDRowLenT kvRowColLen = 0;
|
||||
TDRowLenT colValAppended = 0;
|
||||
|
||||
if (!IS_DATA_COL_ORDERED(spd->orderStatus)) {
|
||||
ASSERT(spd->colIdxInfo != NULL);
|
||||
if(!isPrimaryKey) {
|
||||
kvStart = POINTER_SHIFT(kvPrimaryKeyStart, spd->colIdxInfo[i].finalIdx * PAYLOAD_COL_HEAD_LEN);
|
||||
} else {
|
||||
ASSERT(spd->colIdxInfo[i].finalIdx == 0);
|
||||
}
|
||||
}
|
||||
// the primary key locates in 1st column
|
||||
int32_t ret = tsParseOneColumnKV(pSchema, &sToken, payload, kvPrimaryKeyStart, kvStart, pInsertParam->msg, str,
|
||||
isPrimaryKey, timePrec, payloadValOffset + colValOffset, &colValAppended,
|
||||
&dataRowDeltaColLen, &kvRowColLen);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (isPrimaryKey && tsCheckTimestamp(pDataBlocks, start) != TSDB_CODE_SUCCESS) {
|
||||
if (isPrimaryKey) {
|
||||
if (tsCheckTimestamp(pDataBlocks, payloadValues(payload)) != TSDB_CODE_SUCCESS) {
|
||||
tscInvalidOperationMsg(pInsertParam->msg, "client time/server time can not be mixed up", sToken.z);
|
||||
return TSDB_CODE_TSC_INVALID_TIME_STAMP;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. set the null value for the columns that do not assign values
|
||||
if (spd->numOfBound < spd->numOfCols) {
|
||||
char *ptr = payload;
|
||||
|
||||
for (int32_t i = 0; i < spd->numOfCols; ++i) {
|
||||
if (!spd->cols[i].hasVal) { // current column do not have any value to insert, set it to null
|
||||
if (schema[i].type == TSDB_DATA_TYPE_BINARY) {
|
||||
varDataSetLen(ptr, sizeof(int8_t));
|
||||
*(uint8_t*) varDataVal(ptr) = TSDB_DATA_BINARY_NULL;
|
||||
} else if (schema[i].type == TSDB_DATA_TYPE_NCHAR) {
|
||||
varDataSetLen(ptr, sizeof(int32_t));
|
||||
*(uint32_t*) varDataVal(ptr) = TSDB_DATA_NCHAR_NULL;
|
||||
payloadColSetOffset(kvPrimaryKeyStart, colValOffset);
|
||||
} else {
|
||||
setNull(ptr, schema[i].type, schema[i].bytes);
|
||||
payloadColSetOffset(kvStart, colValOffset);
|
||||
if (IS_DATA_COL_ORDERED(spd->orderStatus)) {
|
||||
kvStart += PAYLOAD_COL_HEAD_LEN; // move to next column
|
||||
}
|
||||
}
|
||||
|
||||
ptr += schema[i].bytes;
|
||||
colValOffset += colValAppended;
|
||||
kvRowLen += kvRowColLen;
|
||||
dataRowLen += dataRowDeltaColLen;
|
||||
}
|
||||
|
||||
rowSize = (int32_t)(ptr - payload);
|
||||
if (kvRowLen < dataRowLen) {
|
||||
payloadSetType(payload, SMEM_ROW_KV);
|
||||
} else {
|
||||
payloadSetType(payload, SMEM_ROW_DATA);
|
||||
}
|
||||
|
||||
*len = rowSize;
|
||||
*len = (int32_t)(payloadValOffset + colValOffset);
|
||||
payloadSetTLen(payload, *len);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -536,6 +922,27 @@ static int32_t rowDataCompar(const void *lhs, const void *rhs) {
|
|||
return left > right ? 1 : -1;
|
||||
}
|
||||
}
|
||||
int32_t schemaIdxCompar(const void *lhs, const void *rhs) {
|
||||
uint16_t left = *(uint16_t *)lhs;
|
||||
uint16_t right = *(uint16_t *)rhs;
|
||||
|
||||
if (left == right) {
|
||||
return 0;
|
||||
} else {
|
||||
return left > right ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t boundIdxCompar(const void *lhs, const void *rhs) {
|
||||
uint16_t left = *(uint16_t *)POINTER_SHIFT(lhs, sizeof(uint16_t));
|
||||
uint16_t right = *(uint16_t *)POINTER_SHIFT(rhs, sizeof(uint16_t));
|
||||
|
||||
if (left == right) {
|
||||
return 0;
|
||||
} else {
|
||||
return left > right ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tsParseValues(char **str, STableDataBlocks *pDataBlock, int maxRows, SInsertStatementParam *pInsertParam,
|
||||
int32_t* numOfRows, char *tmpTokenBuf) {
|
||||
|
@ -551,21 +958,26 @@ int32_t tsParseValues(char **str, STableDataBlocks *pDataBlock, int maxRows, SIn
|
|||
|
||||
int32_t precision = tinfo.precision;
|
||||
|
||||
int32_t extendedRowSize = getExtendedRowSize(&tinfo);
|
||||
|
||||
initSMemRowHelper(&pDataBlock->rowHelper, tscGetTableSchema(pDataBlock->pTableMeta),
|
||||
tscGetNumOfColumns(pDataBlock->pTableMeta), 0);
|
||||
|
||||
while (1) {
|
||||
index = 0;
|
||||
sToken = tStrGetToken(*str, &index, false);
|
||||
if (sToken.n == 0 || sToken.type != TK_LP) break;
|
||||
|
||||
*str += index;
|
||||
if ((*numOfRows) >= maxRows || pDataBlock->size + tinfo.rowSize >= pDataBlock->nAllocSize) {
|
||||
if ((*numOfRows) >= maxRows || pDataBlock->size + extendedRowSize >= pDataBlock->nAllocSize) {
|
||||
int32_t tSize;
|
||||
code = tscAllocateMemIfNeed(pDataBlock, tinfo.rowSize, &tSize);
|
||||
code = tscAllocateMemIfNeed(pDataBlock, extendedRowSize, &tSize);
|
||||
if (code != TSDB_CODE_SUCCESS) { //TODO pass the correct error code to client
|
||||
strcpy(pInsertParam->msg, "client out of memory");
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ASSERT(tSize > maxRows);
|
||||
ASSERT(tSize >= maxRows);
|
||||
maxRows = tSize;
|
||||
}
|
||||
|
||||
|
@ -601,9 +1013,10 @@ int32_t tsParseValues(char **str, STableDataBlocks *pDataBlock, int maxRows, SIn
|
|||
void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32_t numOfCols) {
|
||||
pColInfo->numOfCols = numOfCols;
|
||||
pColInfo->numOfBound = numOfCols;
|
||||
|
||||
pColInfo->orderStatus = ORDER_STATUS_ORDERED;
|
||||
pColInfo->boundedColumns = calloc(pColInfo->numOfCols, sizeof(int32_t));
|
||||
pColInfo->cols = calloc(pColInfo->numOfCols, sizeof(SBoundColumn));
|
||||
pColInfo->colIdxInfo = NULL;
|
||||
|
||||
for (int32_t i = 0; i < pColInfo->numOfCols; ++i) {
|
||||
if (i > 0) {
|
||||
|
@ -643,7 +1056,7 @@ int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int3
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t tsSetBlockInfo(SSubmitBlk *pBlocks, const STableMeta *pTableMeta, int32_t numOfRows) {
|
||||
int32_t FORCE_INLINE tsSetBlockInfo(SSubmitBlk *pBlocks, const STableMeta *pTableMeta, int32_t numOfRows) {
|
||||
pBlocks->tid = pTableMeta->id.tid;
|
||||
pBlocks->uid = pTableMeta->id.uid;
|
||||
pBlocks->sversion = pTableMeta->sversion;
|
||||
|
@ -657,7 +1070,7 @@ static int32_t tsSetBlockInfo(SSubmitBlk *pBlocks, const STableMeta *pTableMeta,
|
|||
}
|
||||
|
||||
// data block is disordered, sort it in ascending order
|
||||
void tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf) {
|
||||
void tscSortRemoveDataBlockDupRowsRaw(STableDataBlocks *dataBuf) {
|
||||
SSubmitBlk *pBlocks = (SSubmitBlk *)dataBuf->pData;
|
||||
|
||||
// size is less than the total size, since duplicated rows may be removed yet.
|
||||
|
@ -701,11 +1114,89 @@ void tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf) {
|
|||
dataBuf->prevTS = INT64_MIN;
|
||||
}
|
||||
|
||||
// data block is disordered, sort it in ascending order
|
||||
int tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf, SBlockKeyInfo *pBlkKeyInfo) {
|
||||
SSubmitBlk *pBlocks = (SSubmitBlk *)dataBuf->pData;
|
||||
int16_t nRows = pBlocks->numOfRows;
|
||||
|
||||
// size is less than the total size, since duplicated rows may be removed yet.
|
||||
|
||||
// if use server time, this block must be ordered
|
||||
if (dataBuf->tsSource == TSDB_USE_SERVER_TS) {
|
||||
assert(dataBuf->ordered);
|
||||
}
|
||||
// allocate memory
|
||||
size_t nAlloc = nRows * sizeof(SBlockKeyTuple);
|
||||
if (pBlkKeyInfo->pKeyTuple == NULL || pBlkKeyInfo->maxBytesAlloc < nAlloc) {
|
||||
size_t nRealAlloc = nAlloc + 10 * sizeof(SBlockKeyTuple);
|
||||
char * tmp = trealloc(pBlkKeyInfo->pKeyTuple, nRealAlloc);
|
||||
if (tmp == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
pBlkKeyInfo->pKeyTuple = (SBlockKeyTuple *)tmp;
|
||||
pBlkKeyInfo->maxBytesAlloc = (int32_t)nRealAlloc;
|
||||
}
|
||||
memset(pBlkKeyInfo->pKeyTuple, 0, nAlloc);
|
||||
|
||||
SBlockKeyTuple *pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
|
||||
char * pBlockData = pBlocks->data;
|
||||
TDRowTLenT totolPayloadTLen = 0;
|
||||
TDRowTLenT payloadTLen = 0;
|
||||
int n = 0;
|
||||
while (n < nRows) {
|
||||
pBlkKeyTuple->skey = payloadTSKey(pBlockData);
|
||||
pBlkKeyTuple->payloadAddr = pBlockData;
|
||||
payloadTLen = payloadTLen(pBlockData);
|
||||
#if 0
|
||||
ASSERT(payloadNCols(pBlockData) <= 4096);
|
||||
ASSERT(payloadTLen(pBlockData) < 65536);
|
||||
#endif
|
||||
totolPayloadTLen += payloadTLen;
|
||||
// next loop
|
||||
pBlockData += payloadTLen;
|
||||
++pBlkKeyTuple;
|
||||
++n;
|
||||
}
|
||||
|
||||
if (!dataBuf->ordered) {
|
||||
pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
|
||||
qsort(pBlkKeyTuple, nRows, sizeof(SBlockKeyTuple), rowDataCompar);
|
||||
|
||||
pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
|
||||
int32_t i = 0;
|
||||
int32_t j = 1;
|
||||
while (j < nRows) {
|
||||
TSKEY ti = (pBlkKeyTuple + i)->skey;
|
||||
TSKEY tj = (pBlkKeyTuple + j)->skey;
|
||||
|
||||
if (ti == tj) {
|
||||
totolPayloadTLen -= payloadTLen(pBlkKeyTuple + j);
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t nextPos = (++i);
|
||||
if (nextPos != j) {
|
||||
memmove(pBlkKeyTuple + nextPos, pBlkKeyTuple + j, sizeof(SBlockKeyTuple));
|
||||
}
|
||||
++j;
|
||||
}
|
||||
|
||||
dataBuf->ordered = true;
|
||||
pBlocks->numOfRows = i + 1;
|
||||
}
|
||||
|
||||
dataBuf->size = sizeof(SSubmitBlk) + totolPayloadTLen;
|
||||
dataBuf->prevTS = INT64_MIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t doParseInsertStatement(SInsertStatementParam *pInsertParam, char **str, STableDataBlocks* dataBuf, int32_t *totalNum) {
|
||||
STableComInfo tinfo = tscGetTableInfo(dataBuf->pTableMeta);
|
||||
|
||||
int32_t maxNumOfRows;
|
||||
int32_t code = tscAllocateMemIfNeed(dataBuf, tinfo.rowSize, &maxNumOfRows);
|
||||
int32_t code = tscAllocateMemIfNeed(dataBuf, getExtendedRowSize(&tinfo), &maxNumOfRows);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -991,7 +1482,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC
|
|||
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, true);
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, true, false);
|
||||
if (TSDB_CODE_TSC_ACTION_IN_PROGRESS == code) {
|
||||
return code;
|
||||
}
|
||||
|
@ -1002,7 +1493,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql, char** boundC
|
|||
}
|
||||
|
||||
sql = sToken.z;
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, false);
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, false, false);
|
||||
if (pInsertParam->sql == NULL) {
|
||||
assert(code == TSDB_CODE_TSC_ACTION_IN_PROGRESS);
|
||||
}
|
||||
|
@ -1038,10 +1529,11 @@ static int32_t validateDataSource(SInsertStatementParam *pInsertParam, int32_t t
|
|||
|
||||
static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDataColInfo* pColInfo, SSchema* pSchema,
|
||||
char* str, char **end) {
|
||||
pColInfo->numOfBound = 0;
|
||||
int32_t nCols = pColInfo->numOfCols;
|
||||
|
||||
memset(pColInfo->boundedColumns, 0, sizeof(int32_t) * pColInfo->numOfCols);
|
||||
for(int32_t i = 0; i < pColInfo->numOfCols; ++i) {
|
||||
pColInfo->numOfBound = 0;
|
||||
memset(pColInfo->boundedColumns, 0, sizeof(int32_t) * nCols);
|
||||
for (int32_t i = 0; i < nCols; ++i) {
|
||||
pColInfo->cols[i].hasVal = false;
|
||||
}
|
||||
|
||||
|
@ -1056,6 +1548,8 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
|||
goto _clean;
|
||||
}
|
||||
|
||||
bool isOrdered = true;
|
||||
int32_t lastColIdx = -1; // last column found
|
||||
while (1) {
|
||||
index = 0;
|
||||
sToken = tStrGetToken(str, &index, false);
|
||||
|
@ -1076,7 +1570,8 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
|||
bool findColumnIndex = false;
|
||||
|
||||
// todo speedup by using hash list
|
||||
for (int32_t t = 0; t < pColInfo->numOfCols; ++t) {
|
||||
int32_t nScanned = 0, t = lastColIdx + 1;
|
||||
while (t < nCols) {
|
||||
if (strncmp(sToken.z, pSchema[t].name, sToken.n) == 0 && strlen(pSchema[t].name) == sToken.n) {
|
||||
if (pColInfo->cols[t].hasVal == true) {
|
||||
code = tscInvalidOperationMsg(pInsertParam->msg, "duplicated column name", sToken.z);
|
||||
|
@ -1085,10 +1580,39 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
|||
|
||||
pColInfo->cols[t].hasVal = true;
|
||||
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
|
||||
pColInfo->numOfBound += 1;
|
||||
++pColInfo->numOfBound;
|
||||
findColumnIndex = true;
|
||||
if (isOrdered && (lastColIdx > t)) {
|
||||
isOrdered = false;
|
||||
}
|
||||
lastColIdx = t;
|
||||
break;
|
||||
}
|
||||
++t;
|
||||
++nScanned;
|
||||
}
|
||||
if (!findColumnIndex) {
|
||||
t = 0;
|
||||
int32_t nRemain = nCols - nScanned;
|
||||
while (t < nRemain) {
|
||||
if (strncmp(sToken.z, pSchema[t].name, sToken.n) == 0 && strlen(pSchema[t].name) == sToken.n) {
|
||||
if (pColInfo->cols[t].hasVal == true) {
|
||||
code = tscInvalidOperationMsg(pInsertParam->msg, "duplicated column name", sToken.z);
|
||||
goto _clean;
|
||||
}
|
||||
|
||||
pColInfo->cols[t].hasVal = true;
|
||||
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
|
||||
++pColInfo->numOfBound;
|
||||
findColumnIndex = true;
|
||||
if (isOrdered && (lastColIdx > t)) {
|
||||
isOrdered = false;
|
||||
}
|
||||
lastColIdx = t;
|
||||
break;
|
||||
}
|
||||
++t;
|
||||
}
|
||||
}
|
||||
|
||||
if (!findColumnIndex) {
|
||||
|
@ -1097,7 +1621,29 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
|||
}
|
||||
}
|
||||
|
||||
memset(&pColInfo->boundedColumns[pColInfo->numOfBound], 0 , sizeof(int32_t) * (pColInfo->numOfCols - pColInfo->numOfBound));
|
||||
pColInfo->orderStatus = isOrdered ? ORDER_STATUS_ORDERED : ORDER_STATUS_DISORDERED;
|
||||
|
||||
if (!isOrdered) {
|
||||
pColInfo->colIdxInfo = tcalloc(pColInfo->numOfBound, sizeof(SBoundIdxInfo));
|
||||
if (pColInfo->colIdxInfo == NULL) {
|
||||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto _clean;
|
||||
}
|
||||
SBoundIdxInfo *pColIdx = pColInfo->colIdxInfo;
|
||||
for (uint16_t i = 0; i < pColInfo->numOfBound; ++i) {
|
||||
pColIdx[i].schemaColIdx = (uint16_t)pColInfo->boundedColumns[i];
|
||||
pColIdx[i].boundIdx = i;
|
||||
}
|
||||
qsort(pColIdx, pColInfo->numOfBound, sizeof(SBoundIdxInfo), schemaIdxCompar);
|
||||
for (uint16_t i = 0; i < pColInfo->numOfBound; ++i) {
|
||||
pColIdx[i].finalIdx = i;
|
||||
}
|
||||
qsort(pColIdx, pColInfo->numOfBound, sizeof(SBoundIdxInfo), boundIdxCompar);
|
||||
}
|
||||
|
||||
memset(&pColInfo->boundedColumns[pColInfo->numOfBound], 0,
|
||||
sizeof(int32_t) * (pColInfo->numOfCols - pColInfo->numOfBound));
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_clean:
|
||||
|
@ -1358,7 +1904,6 @@ int tsInsertInitialCheck(SSqlObj *pSql) {
|
|||
int tsParseSql(SSqlObj *pSql, bool initial) {
|
||||
int32_t ret = TSDB_CODE_SUCCESS;
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
if (!initial) {
|
||||
tscDebug("0x%"PRIx64" resume to parse sql: %s", pSql->self, pCmd->insertParam.sql);
|
||||
}
|
||||
|
@ -1494,21 +2039,24 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow
|
|||
}
|
||||
|
||||
STableDataBlocks *pTableDataBlock = NULL;
|
||||
int32_t ret =
|
||||
tscGetDataBlockFromList(pInsertParam->pTableBlockHashList, pTableMeta->id.uid, TSDB_PAYLOAD_SIZE, sizeof(SSubmitBlk),
|
||||
tinfo.rowSize, &pTableMetaInfo->name, pTableMeta, &pTableDataBlock, NULL);
|
||||
int32_t ret = tscGetDataBlockFromList(pInsertParam->pTableBlockHashList, pTableMeta->id.uid, TSDB_PAYLOAD_SIZE,
|
||||
sizeof(SSubmitBlk), tinfo.rowSize, &pTableMetaInfo->name, pTableMeta,
|
||||
&pTableDataBlock, NULL);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
pParentSql->res.code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
tscAllocateMemIfNeed(pTableDataBlock, tinfo.rowSize, &maxRows);
|
||||
tscAllocateMemIfNeed(pTableDataBlock, getExtendedRowSize(&tinfo), &maxRows);
|
||||
tokenBuf = calloc(1, TSDB_MAX_BYTES_PER_ROW);
|
||||
if (tokenBuf == NULL) {
|
||||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
initSMemRowHelper(&pTableDataBlock->rowHelper, tscGetTableSchema(pTableDataBlock->pTableMeta),
|
||||
tscGetNumOfColumns(pTableDataBlock->pTableMeta), 0);
|
||||
|
||||
while ((readLen = tgetline(&line, &n, fp)) != -1) {
|
||||
if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
|
||||
line[--readLen] = 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,6 +47,7 @@ typedef struct SNormalStmt {
|
|||
typedef struct SMultiTbStmt {
|
||||
bool nameSet;
|
||||
bool tagSet;
|
||||
bool subSet;
|
||||
uint64_t currentUid;
|
||||
char *sqlstr;
|
||||
uint32_t tbNum;
|
||||
|
@ -54,6 +55,7 @@ typedef struct SMultiTbStmt {
|
|||
SStrToken stbname;
|
||||
SStrToken values;
|
||||
SArray *tags;
|
||||
STableDataBlocks *lastBlock;
|
||||
SHashObj *pTableHash;
|
||||
SHashObj *pTableBlockHashList; // data block for each table
|
||||
} SMultiTbStmt;
|
||||
|
@ -347,7 +349,7 @@ int32_t fillTablesColumnsNull(SSqlObj* pSql) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// functions for insertion statement preparation
|
||||
static int doBindParam(STableDataBlocks* pBlock, char* data, SParamInfo* param, TAOS_BIND* bind, int32_t colNum) {
|
||||
static FORCE_INLINE int doBindParam(STableDataBlocks* pBlock, char* data, SParamInfo* param, TAOS_BIND* bind, int32_t colNum) {
|
||||
if (bind->is_null != NULL && *(bind->is_null)) {
|
||||
setNull(data + param->offset, param->type, param->bytes);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -746,25 +748,25 @@ static int doBindParam(STableDataBlocks* pBlock, char* data, SParamInfo* param,
|
|||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
size = 1;
|
||||
*(uint8_t *)(data + param->offset) = *(uint8_t *)bind->buffer;
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
size = 2;
|
||||
*(uint16_t *)(data + param->offset) = *(uint16_t *)bind->buffer;
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
size = 4;
|
||||
*(uint32_t *)(data + param->offset) = *(uint32_t *)bind->buffer;
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
size = 8;
|
||||
*(uint64_t *)(data + param->offset) = *(uint64_t *)bind->buffer;
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
|
@ -790,7 +792,6 @@ static int doBindParam(STableDataBlocks* pBlock, char* data, SParamInfo* param,
|
|||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
memcpy(data + param->offset, bind->buffer, size);
|
||||
if (param->offset == 0) {
|
||||
if (tsCheckTimestamp(pBlock, data + param->offset) != TSDB_CODE_SUCCESS) {
|
||||
tscError("invalid timestamp");
|
||||
|
@ -801,6 +802,58 @@ static int doBindParam(STableDataBlocks* pBlock, char* data, SParamInfo* param,
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t insertStmtGenLastBlock(STableDataBlocks** lastBlock, STableDataBlocks* pBlock) {
|
||||
*lastBlock = (STableDataBlocks*)malloc(sizeof(STableDataBlocks));
|
||||
memcpy(*lastBlock, pBlock, sizeof(STableDataBlocks));
|
||||
(*lastBlock)->cloned = true;
|
||||
|
||||
(*lastBlock)->pData = NULL;
|
||||
(*lastBlock)->ordered = true;
|
||||
(*lastBlock)->prevTS = INT64_MIN;
|
||||
(*lastBlock)->size = sizeof(SSubmitBlk);
|
||||
(*lastBlock)->tsSource = -1;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int32_t insertStmtGenBlock(STscStmt* pStmt, STableDataBlocks** pBlock, STableMeta* pTableMeta, SName* name) {
|
||||
int32_t code = 0;
|
||||
|
||||
if (pStmt->mtb.lastBlock == NULL) {
|
||||
tscError("no previous data block");
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
}
|
||||
|
||||
int32_t msize = tscGetTableMetaSize(pTableMeta);
|
||||
int32_t tsize = sizeof(STableDataBlocks) + msize;
|
||||
|
||||
void *t = malloc(tsize);
|
||||
*pBlock = t;
|
||||
|
||||
memcpy(*pBlock, pStmt->mtb.lastBlock, sizeof(STableDataBlocks));
|
||||
|
||||
t = (char *)t + sizeof(STableDataBlocks);
|
||||
(*pBlock)->pTableMeta = t;
|
||||
memcpy((*pBlock)->pTableMeta, pTableMeta, msize);
|
||||
|
||||
(*pBlock)->pData = malloc((*pBlock)->nAllocSize);
|
||||
|
||||
(*pBlock)->vgId = (*pBlock)->pTableMeta->vgId;
|
||||
|
||||
tNameAssign(&(*pBlock)->tableName, name);
|
||||
|
||||
SSubmitBlk* blk = (SSubmitBlk*)(*pBlock)->pData;
|
||||
memset(blk, 0, sizeof(*blk));
|
||||
|
||||
code = tsSetBlockInfo(blk, pTableMeta, 0);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
STMT_RET(code);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int doBindBatchParam(STableDataBlocks* pBlock, SParamInfo* param, TAOS_MULTI_BIND* bind, int32_t rowNum) {
|
||||
if (bind->buffer_type != param->type || !isValidDataType(param->type)) {
|
||||
|
@ -1227,11 +1280,11 @@ int stmtParseInsertTbTags(SSqlObj* pSql, STscStmt* pStmt) {
|
|||
pStmt->mtb.tbname = sToken;
|
||||
pStmt->mtb.nameSet = false;
|
||||
if (pStmt->mtb.pTableHash == NULL) {
|
||||
pStmt->mtb.pTableHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false);
|
||||
pStmt->mtb.pTableHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false);
|
||||
}
|
||||
|
||||
if (pStmt->mtb.pTableBlockHashList == NULL) {
|
||||
pStmt->mtb.pTableBlockHashList = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false);
|
||||
pStmt->mtb.pTableBlockHashList = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false);
|
||||
}
|
||||
|
||||
pStmt->mtb.tagSet = true;
|
||||
|
@ -1522,6 +1575,7 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
|
|||
|
||||
int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
int32_t code = 0;
|
||||
|
||||
if (stmt == NULL || pStmt->pSql == NULL || pStmt->taos == NULL) {
|
||||
STMT_RET(TSDB_CODE_TSC_DISCONNECTED);
|
||||
|
@ -1559,6 +1613,11 @@ int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags
|
|||
|
||||
SSubmitBlk* pBlk = (SSubmitBlk*) (*t1)->pData;
|
||||
pCmd->batchSize = pBlk->numOfRows;
|
||||
if (pBlk->numOfRows == 0) {
|
||||
(*t1)->prevTS = INT64_MIN;
|
||||
}
|
||||
|
||||
tsSetBlockInfo(pBlk, (*t1)->pTableMeta, pBlk->numOfRows);
|
||||
|
||||
taosHashPut(pCmd->insertParam.pTableBlockHashList, (void *)&pStmt->mtb.currentUid, sizeof(pStmt->mtb.currentUid), (void*)t1, POINTER_BYTES);
|
||||
|
||||
|
@ -1566,6 +1625,51 @@ int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags
|
|||
STMT_RET(TSDB_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
if (pStmt->mtb.subSet && taosHashGetSize(pStmt->mtb.pTableHash) > 0) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, 0);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
char sTableName[TSDB_TABLE_FNAME_LEN];
|
||||
strncpy(sTableName, pTableMeta->sTableName, sizeof(sTableName));
|
||||
|
||||
SStrToken tname = {0};
|
||||
tname.type = TK_STRING;
|
||||
tname.z = (char *)name;
|
||||
tname.n = (uint32_t)strlen(name);
|
||||
SName fullname = {0};
|
||||
tscSetTableFullName(&fullname, &tname, pSql);
|
||||
|
||||
memcpy(&pTableMetaInfo->name, &fullname, sizeof(fullname));
|
||||
|
||||
code = tscGetTableMetaEx(pSql, pTableMetaInfo, false, true);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
STMT_RET(code);
|
||||
}
|
||||
|
||||
pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
if (strcmp(sTableName, pTableMeta->sTableName)) {
|
||||
tscError("0x%"PRIx64" only tables belongs to one stable is allowed", pSql->self);
|
||||
STMT_RET(TSDB_CODE_TSC_APP_ERROR);
|
||||
}
|
||||
|
||||
STableDataBlocks* pBlock = NULL;
|
||||
|
||||
insertStmtGenBlock(pStmt, &pBlock, pTableMeta, &pTableMetaInfo->name);
|
||||
|
||||
pCmd->batchSize = 0;
|
||||
|
||||
pStmt->mtb.currentUid = pTableMeta->id.uid;
|
||||
pStmt->mtb.tbNum++;
|
||||
|
||||
taosHashPut(pCmd->insertParam.pTableBlockHashList, (void *)&pStmt->mtb.currentUid, sizeof(pStmt->mtb.currentUid), (void*)&pBlock, POINTER_BYTES);
|
||||
taosHashPut(pStmt->mtb.pTableBlockHashList, (void *)&pStmt->mtb.currentUid, sizeof(pStmt->mtb.currentUid), (void*)&pBlock, POINTER_BYTES);
|
||||
taosHashPut(pStmt->mtb.pTableHash, name, strlen(name), (char*) &pTableMeta->id.uid, sizeof(pTableMeta->id.uid));
|
||||
|
||||
tscDebug("0x%"PRIx64" table:%s is prepared, uid:%" PRIx64, pSql->self, name, pStmt->mtb.currentUid);
|
||||
|
||||
STMT_RET(TSDB_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
if (pStmt->mtb.tagSet) {
|
||||
pStmt->mtb.tbname = tscReplaceStrToken(&pSql->sqlstr, &pStmt->mtb.tbname, name);
|
||||
} else {
|
||||
|
@ -1594,7 +1698,7 @@ int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags
|
|||
pCmd->insertParam.pTableBlockHashList = hashList;
|
||||
}
|
||||
|
||||
int32_t code = tsParseSql(pStmt->pSql, true);
|
||||
code = tsParseSql(pStmt->pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
// wait for the callback function to post the semaphore
|
||||
tsem_wait(&pStmt->pSql->rspSem);
|
||||
|
@ -1622,6 +1726,10 @@ int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags
|
|||
taosHashPut(pStmt->mtb.pTableBlockHashList, (void *)&pStmt->mtb.currentUid, sizeof(pStmt->mtb.currentUid), (void*)&pBlock, POINTER_BYTES);
|
||||
taosHashPut(pStmt->mtb.pTableHash, name, strlen(name), (char*) &pTableMeta->id.uid, sizeof(pTableMeta->id.uid));
|
||||
|
||||
if (pStmt->mtb.lastBlock == NULL) {
|
||||
insertStmtGenLastBlock(&pStmt->mtb.lastBlock, pBlock);
|
||||
}
|
||||
|
||||
tscDebug("0x%"PRIx64" table:%s is prepared, uid:%" PRIx64, pSql->self, name, pStmt->mtb.currentUid);
|
||||
}
|
||||
|
||||
|
@ -1629,7 +1737,17 @@ int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags
|
|||
}
|
||||
|
||||
|
||||
int taos_stmt_set_sub_tbname(TAOS_STMT* stmt, const char* name) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
pStmt->mtb.subSet = true;
|
||||
return taos_stmt_set_tbname_tags(stmt, name, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
pStmt->mtb.subSet = false;
|
||||
return taos_stmt_set_tbname_tags(stmt, name, NULL);
|
||||
}
|
||||
|
||||
|
@ -1653,6 +1771,7 @@ int taos_stmt_close(TAOS_STMT* stmt) {
|
|||
if (pStmt->pSql && pStmt->pSql->res.code != 0) {
|
||||
rmMeta = true;
|
||||
}
|
||||
tscDestroyDataBlock(pStmt->mtb.lastBlock, rmMeta);
|
||||
pStmt->mtb.pTableBlockHashList = tscDestroyBlockHashTable(pStmt->mtb.pTableBlockHashList, rmMeta);
|
||||
taosHashCleanup(pStmt->pSql->cmd.insertParam.pTableBlockHashList);
|
||||
pStmt->pSql->cmd.insertParam.pTableBlockHashList = NULL;
|
||||
|
@ -1687,6 +1806,8 @@ int taos_stmt_bind_param(TAOS_STMT* stmt, TAOS_BIND* bind) {
|
|||
|
||||
pStmt->last = STMT_BIND;
|
||||
|
||||
tscDebug("tableId:%" PRIu64 ", try to bind one row", pStmt->mtb.currentUid);
|
||||
|
||||
STMT_RET(insertStmtBindParam(pStmt, bind));
|
||||
} else {
|
||||
STMT_RET(normalStmtBindParam(pStmt, bind));
|
||||
|
@ -1806,6 +1927,7 @@ int taos_stmt_execute(TAOS_STMT* stmt) {
|
|||
|
||||
pStmt->last = STMT_EXECUTE;
|
||||
|
||||
pStmt->pSql->cmd.insertParam.payloadType = PAYLOAD_TYPE_RAW;
|
||||
if (pStmt->multiTbInsert) {
|
||||
ret = insertBatchStmtExecute(pStmt);
|
||||
} else {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "os.h"
|
||||
#include "tscLog.h"
|
||||
#include "tsclient.h"
|
||||
#include "tsocket.h"
|
||||
#include "ttimer.h"
|
||||
#include "tutil.h"
|
||||
#include "taosmsg.h"
|
||||
|
@ -252,6 +253,16 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
|
|||
//pQdesc->useconds = htobe64(pSql->res.useconds);
|
||||
pQdesc->useconds = htobe64(now - pSql->stime);
|
||||
pQdesc->qId = htobe64(pSql->res.qId);
|
||||
pQdesc->sqlObjId = htobe64(pSql->self);
|
||||
pQdesc->pid = pHeartbeat->pid;
|
||||
if (pSql->cmd.pQueryInfo->stableQuery == true) {
|
||||
pQdesc->numOfSub = pSql->subState.numOfSub;
|
||||
} else {
|
||||
pQdesc->numOfSub = 1;
|
||||
}
|
||||
pQdesc->numOfSub = htonl(pQdesc->numOfSub);
|
||||
|
||||
taosGetFqdn(pQdesc->fqdn);
|
||||
|
||||
pHeartbeat->numOfQueries++;
|
||||
pQdesc++;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "tstrbuild.h"
|
||||
#include "ttoken.h"
|
||||
#include "ttokendef.h"
|
||||
#include "qScript.h"
|
||||
#include "ttype.h"
|
||||
#include "qFilter.h"
|
||||
|
||||
|
@ -78,7 +79,8 @@ static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pC
|
|||
static int32_t setObjFullName(char* fullName, const char* account, SStrToken* pDB, SStrToken* tableName, int32_t* len);
|
||||
static void getColumnName(tSqlExprItem* pItem, char* resultFieldName, char* rawName, int32_t nameLength);
|
||||
|
||||
static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult);
|
||||
static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem,
|
||||
bool finalResult, SUdfInfo* pUdfInfo);
|
||||
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
|
||||
int8_t type, char* fieldName, SExprInfo* pSqlExpr);
|
||||
|
||||
|
@ -184,9 +186,6 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType,
|
|||
if (var->nType != TSDB_DATA_TYPE_BOOL && !IS_SIGNED_NUMERIC_TYPE(var->nType)) {
|
||||
break;
|
||||
}
|
||||
if (colType == TSDB_DATA_TYPE_BOOL && (var->i64 > 1 ||var->i64 < 0)) {
|
||||
break;
|
||||
}
|
||||
tbufWriteInt64(&bw, var->i64);
|
||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(colType)) {
|
||||
if (IS_SIGNED_NUMERIC_TYPE(var->nType) || IS_UNSIGNED_NUMERIC_TYPE(var->nType)) {
|
||||
|
@ -391,6 +390,137 @@ static int32_t normalizeVarDataTypeLength(SSqlCmd* pCmd) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t readFromFile(char *name, uint32_t *len, void **buf) {
|
||||
struct stat fileStat;
|
||||
if (stat(name, &fileStat) < 0) {
|
||||
tscError("stat file %s failed, error:%s", name, strerror(errno));
|
||||
return TAOS_SYSTEM_ERROR(errno);
|
||||
}
|
||||
|
||||
*len = fileStat.st_size;
|
||||
|
||||
if (*len <= 0) {
|
||||
tscError("file %s is empty", name);
|
||||
return TSDB_CODE_TSC_FILE_EMPTY;
|
||||
}
|
||||
|
||||
*buf = calloc(1, *len);
|
||||
if (*buf == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
int fd = open(name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
tscError("open file %s failed, error:%s", name, strerror(errno));
|
||||
tfree(*buf);
|
||||
return TAOS_SYSTEM_ERROR(errno);
|
||||
}
|
||||
|
||||
int64_t s = taosRead(fd, *buf, *len);
|
||||
if (s != *len) {
|
||||
tscError("read file %s failed, error:%s", name, strerror(errno));
|
||||
close(fd);
|
||||
tfree(*buf);
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||
const char *msg1 = "function name is too long";
|
||||
const char *msg2 = "path is too long";
|
||||
const char *msg3 = "invalid outputtype";
|
||||
const char *msg4 = "invalid script";
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
switch (pInfo->type) {
|
||||
case TSDB_SQL_CREATE_FUNCTION: {
|
||||
SCreateFuncInfo *createInfo = &pInfo->pMiscInfo->funcOpt;
|
||||
uint32_t len = 0;
|
||||
void *buf = NULL;
|
||||
|
||||
if (createInfo->output.type == (uint8_t)-1 || createInfo->output.bytes < 0) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
||||
createInfo->name.z[createInfo->name.n] = 0;
|
||||
|
||||
strdequote(createInfo->name.z);
|
||||
|
||||
if (strlen(createInfo->name.z) >= TSDB_FUNC_NAME_LEN) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
createInfo->path.z[createInfo->path.n] = 0;
|
||||
|
||||
strdequote(createInfo->path.z);
|
||||
|
||||
if (strlen(createInfo->path.z) >= PATH_MAX) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
int32_t ret = readFromFile(createInfo->path.z, &len, &buf);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
//distinguish *.lua and *.so
|
||||
int32_t pathLen = (int32_t)strlen(createInfo->path.z);
|
||||
if ((pathLen > 3) && (0 == strncmp(createInfo->path.z + pathLen - 3, "lua", 3)) && !isValidScript(buf, len)) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
}
|
||||
|
||||
//TODO CHECK CODE
|
||||
if (len + sizeof(SCreateFuncMsg) > pSql->cmd.allocSize) {
|
||||
ret = tscAllocPayload(&pSql->cmd, len + sizeof(SCreateFuncMsg));
|
||||
if (ret) {
|
||||
tfree(buf);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SCreateFuncMsg *pMsg = (SCreateFuncMsg *)pSql->cmd.payload;
|
||||
|
||||
strcpy(pMsg->name, createInfo->name.z);
|
||||
strcpy(pMsg->path, createInfo->path.z);
|
||||
|
||||
pMsg->funcType = htonl(createInfo->type);
|
||||
pMsg->bufSize = htonl(createInfo->bufSize);
|
||||
|
||||
pMsg->outputType = createInfo->output.type;
|
||||
pMsg->outputLen = htons(createInfo->output.bytes);
|
||||
|
||||
pMsg->codeLen = htonl(len);
|
||||
memcpy(pMsg->code, buf, len);
|
||||
tfree(buf);
|
||||
|
||||
break;
|
||||
}
|
||||
case TSDB_SQL_DROP_FUNCTION: {
|
||||
SStrToken* t0 = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
|
||||
SDropFuncMsg *pMsg = (SDropFuncMsg *)pSql->cmd.payload;
|
||||
|
||||
t0->z[t0->n] = 0;
|
||||
|
||||
strdequote(t0->z);
|
||||
|
||||
if (strlen(t0->z) >= TSDB_FUNC_NAME_LEN) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
strcpy(pMsg->name, t0->z);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||
if (pInfo == NULL || pSql == NULL) {
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
|
@ -491,6 +621,16 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
break;
|
||||
}
|
||||
|
||||
case TSDB_SQL_CREATE_FUNCTION:
|
||||
case TSDB_SQL_DROP_FUNCTION: {
|
||||
code = handleUserDefinedFunc(pSql, pInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_SQL_ALTER_DB:
|
||||
case TSDB_SQL_CREATE_DB: {
|
||||
const char* msg1 = "invalid db name";
|
||||
|
@ -774,7 +914,15 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
return code;
|
||||
}
|
||||
|
||||
SArray *pUdfInfo = NULL;
|
||||
if (pQueryInfo->pUdfInfo) {
|
||||
pUdfInfo = taosArrayDup(pQueryInfo->pUdfInfo);
|
||||
}
|
||||
|
||||
pQueryInfo = pCmd->active;
|
||||
pQueryInfo->pUdfInfo = pUdfInfo;
|
||||
pQueryInfo->udfCopy = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1250,12 +1398,16 @@ static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd) {
|
|||
const char* msg4 = "invalid data type";
|
||||
const char* msg5 = "invalid binary/nchar column length";
|
||||
const char* msg6 = "invalid column name";
|
||||
const char* msg7 = "too many columns";
|
||||
|
||||
// number of fields no less than 2
|
||||
size_t numOfCols = taosArrayGetSize(pFieldList);
|
||||
if (numOfCols <= 1 || numOfCols > TSDB_MAX_COLUMNS) {
|
||||
if (numOfCols <= 1 ) {
|
||||
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
return false;
|
||||
} else if (numOfCols > TSDB_MAX_COLUMNS) {
|
||||
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
return false;
|
||||
}
|
||||
|
||||
// first column must be timestamp
|
||||
|
@ -1390,6 +1542,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
|
|||
const char* msg4 = "invalid tag name";
|
||||
const char* msg5 = "invalid binary/nchar tag length";
|
||||
const char* msg6 = "invalid data type in tags";
|
||||
const char* msg7 = "too many columns";
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, 0);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
@ -1397,6 +1550,12 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
|
|||
int32_t numOfTags = tscGetNumOfTags(pTableMeta);
|
||||
int32_t numOfCols = tscGetNumOfColumns(pTableMeta);
|
||||
|
||||
// no more max columns
|
||||
if (numOfTags + numOfCols >= TSDB_MAX_COLUMNS) {
|
||||
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
return false;
|
||||
}
|
||||
|
||||
// no more than 6 tags
|
||||
if (numOfTags == TSDB_MAX_TAGS) {
|
||||
char msg[128] = {0};
|
||||
|
@ -1814,6 +1973,74 @@ static bool hasNoneUserDefineExpr(SQueryInfo* pQueryInfo) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void genUdfList(SArray* pUdfInfo, tSqlExpr *pNode) {
|
||||
if (pNode == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pNode->type == SQL_NODE_EXPR) {
|
||||
genUdfList(pUdfInfo, pNode->pLeft);
|
||||
genUdfList(pUdfInfo, pNode->pRight);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pNode->type == SQL_NODE_SQLFUNCTION) {
|
||||
pNode->functionId = isValidFunction(pNode->Expr.operand.z, pNode->Expr.operand.n);
|
||||
if (pNode->functionId < 0) { // extract all possible user defined function
|
||||
struct SUdfInfo info = {0};
|
||||
info.name = strndup(pNode->Expr.operand.z, pNode->Expr.operand.n);
|
||||
int32_t functionId = (int32_t)taosArrayGetSize(pUdfInfo) * (-1) - 1;
|
||||
info.functionId = functionId;
|
||||
|
||||
taosArrayPush(pUdfInfo, &info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static int32_t checkForUdf(SSqlObj* pSql, SQueryInfo* pQueryInfo, SArray* pSelection) {
|
||||
if (pQueryInfo->pUdfInfo != NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
pQueryInfo->pUdfInfo = taosArrayInit(4, sizeof(struct SUdfInfo));
|
||||
|
||||
size_t nExpr = taosArrayGetSize(pSelection);
|
||||
|
||||
for (int32_t i = 0; i < nExpr; ++i) {
|
||||
tSqlExprItem* pItem = taosArrayGet(pSelection, i);
|
||||
|
||||
int32_t type = pItem->pNode->type;
|
||||
if (type == SQL_NODE_EXPR || type == SQL_NODE_SQLFUNCTION) {
|
||||
genUdfList(pQueryInfo->pUdfInfo, pItem->pNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (taosArrayGetSize(pQueryInfo->pUdfInfo) > 0) {
|
||||
return tscGetUdfFromNode(pSql, pQueryInfo);
|
||||
} else {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static SUdfInfo* isValidUdf(SArray* pUdfInfo, const char* name, int32_t len) {
|
||||
if(pUdfInfo == NULL){
|
||||
tscError("udfinfo is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t t = taosArrayGetSize(pUdfInfo);
|
||||
for(int32_t i = 0; i < t; ++i) {
|
||||
SUdfInfo* pUdf = taosArrayGet(pUdfInfo, i);
|
||||
if (strlen(pUdf->name) == len && strncasecmp(pUdf->name, name, len) == 0) {
|
||||
return pUdf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelNodeList, bool joinQuery,
|
||||
bool timeWindowQuery, bool outerQuery) {
|
||||
assert(pSelNodeList != NULL && pCmd != NULL);
|
||||
|
@ -1846,12 +2073,18 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
|
|||
int32_t type = pItem->pNode->type;
|
||||
if (type == SQL_NODE_SQLFUNCTION) {
|
||||
pItem->pNode->functionId = isValidFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||
SUdfInfo* pUdfInfo = NULL;
|
||||
if (pItem->pNode->functionId < 0) {
|
||||
pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||
if (pUdfInfo == NULL) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
}
|
||||
|
||||
pItem->pNode->functionId = pUdfInfo->functionId;
|
||||
}
|
||||
|
||||
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, pItem, true) != TSDB_CODE_SUCCESS) {
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, pItem, true, pUdfInfo) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
} else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) {
|
||||
|
@ -2106,7 +2339,8 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
|
|||
}
|
||||
|
||||
static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSchema* pSchema, SConvertFunc cvtFunc,
|
||||
const char* name, int32_t resColIdx, SColumnIndex* pColIndex, bool finalResult) {
|
||||
const char* name, int32_t resColIdx, SColumnIndex* pColIndex, bool finalResult,
|
||||
SUdfInfo* pUdfInfo) {
|
||||
const char* msg1 = "not support column types";
|
||||
|
||||
int32_t f = cvtFunc.execFuncId;
|
||||
|
@ -2122,7 +2356,7 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
|
|||
int16_t resBytes = 0;
|
||||
int32_t interBufSize = 0;
|
||||
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, f, 0, &resType, &resBytes, &interBufSize, 0, false);
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, f, 0, &resType, &resBytes, &interBufSize, 0, false, pUdfInfo);
|
||||
SExprInfo* pExpr = tscExprAppend(pQueryInfo, f, pColIndex, resType, resBytes, getNewResColId(pCmd), interBufSize, false);
|
||||
tstrncpy(pExpr->base.aliasName, name, tListLen(pExpr->base.aliasName));
|
||||
|
||||
|
@ -2194,18 +2428,19 @@ static void updateLastScanOrderIfNeeded(SQueryInfo* pQueryInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
static UNUSED_FUNC void updateFunctionInterBuf(SQueryInfo* pQueryInfo, bool superTable) {
|
||||
static UNUSED_FUNC void updateFunctionInterBuf(SQueryInfo* pQueryInfo, bool superTable, SUdfInfo* pUdfInfo) {
|
||||
size_t numOfExpr = tscNumOfExprs(pQueryInfo);
|
||||
for (int32_t i = 0; i < numOfExpr; ++i) {
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
|
||||
|
||||
int32_t param = (int32_t)pExpr->base.param[0].i64;
|
||||
getResultDataInfo(pExpr->base.colType, pExpr->base.colBytes, pExpr->base.functionId, param, &pExpr->base.resType, &pExpr->base.resBytes,
|
||||
&pExpr->base.interBytes, 0, superTable);
|
||||
&pExpr->base.interBytes, 0, superTable, pUdfInfo);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult) {
|
||||
int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult,
|
||||
SUdfInfo* pUdfInfo) {
|
||||
STableMetaInfo* pTableMetaInfo = NULL;
|
||||
int32_t functionId = pItem->pNode->functionId;
|
||||
|
||||
|
@ -2354,7 +2589,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
int32_t intermediateResSize = 0;
|
||||
|
||||
if (getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize,
|
||||
&intermediateResSize, 0, false) != TSDB_CODE_SUCCESS) {
|
||||
&intermediateResSize, 0, false, NULL) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
|
@ -2488,7 +2723,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
SStrToken t = {.z = pSchema[j].name, .n = (uint32_t)strnlen(pSchema[j].name, TSDB_COL_NAME_LEN)};
|
||||
setResultColName(name, pItem, cvtFunc.originFuncId, &t, true);
|
||||
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[j], cvtFunc, name, colIndex++, &index, finalResult) != 0) {
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[j], cvtFunc, name, colIndex++, &index,
|
||||
finalResult, pUdfInfo) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
@ -2511,7 +2747,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
bool multiColOutput = taosArrayGetSize(pItem->pNode->Expr.paramList) > 1;
|
||||
setResultColName(name, pItem, cvtFunc.originFuncId, &pParamElem->pNode->columnName, multiColOutput);
|
||||
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex++, &index, finalResult) != 0) {
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, name, colIndex++, &index, finalResult, pUdfInfo) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
@ -2536,7 +2772,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
SStrToken t = {.z = pSchema[i].name, .n = (uint32_t)strnlen(pSchema[i].name, TSDB_COL_NAME_LEN)};
|
||||
setResultColName(name, pItem, cvtFunc.originFuncId, &t, true);
|
||||
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[index.columnIndex], cvtFunc, name, colIndex, &index, finalResult) != 0) {
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, &pSchema[index.columnIndex], cvtFunc, name, colIndex, &index,
|
||||
finalResult, pUdfInfo) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
colIndex++;
|
||||
|
@ -2607,7 +2844,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
}
|
||||
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize, &interResult, 0, false);
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resultType, &resultSize, &interResult, 0, false,
|
||||
pUdfInfo);
|
||||
|
||||
/*
|
||||
* sql function transformation
|
||||
|
@ -2720,7 +2958,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
int16_t type = 0;
|
||||
int32_t inter = 0;
|
||||
|
||||
int32_t ret = getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0);
|
||||
int32_t ret = getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0, NULL);
|
||||
assert(ret == TSDB_CODE_SUCCESS);
|
||||
|
||||
s.type = (uint8_t)type;
|
||||
|
@ -2744,7 +2982,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
int32_t inter = 0;
|
||||
int16_t resType = 0;
|
||||
int16_t bytes = 0;
|
||||
getResultDataInfo(TSDB_DATA_TYPE_INT, 4, TSDB_FUNC_BLKINFO, 0, &resType, &bytes, &inter, 0, 0);
|
||||
|
||||
getResultDataInfo(TSDB_DATA_TYPE_INT, 4, TSDB_FUNC_BLKINFO, 0, &resType, &bytes, &inter, 0, 0, NULL);
|
||||
|
||||
SSchema s = {.name = "block_dist", .type = TSDB_DATA_TYPE_BINARY, .bytes = bytes};
|
||||
|
||||
|
@ -2762,10 +3001,64 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
default:
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
default: {
|
||||
pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||
if (pUdfInfo == NULL) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9);
|
||||
}
|
||||
|
||||
tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0);;
|
||||
if (pParamElem->pNode->tokenId != TK_ID) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
||||
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
|
||||
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
|
||||
// functions can not be applied to tags
|
||||
if (index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
|
||||
int32_t inter = 0;
|
||||
int16_t resType = 0;
|
||||
int16_t bytes = 0;
|
||||
getResultDataInfo(TSDB_DATA_TYPE_INT, 4, functionId, 0, &resType, &bytes, &inter, 0, false, pUdfInfo);
|
||||
|
||||
SExprInfo* pExpr = tscExprAppend(pQueryInfo, functionId, &index, resType, bytes, getNewResColId(pCmd), inter, false);
|
||||
|
||||
memset(pExpr->base.aliasName, 0, tListLen(pExpr->base.aliasName));
|
||||
getColumnName(pItem, pExpr->base.aliasName, pExpr->base.token, sizeof(pExpr->base.aliasName) - 1);
|
||||
|
||||
SSchema s = {0};
|
||||
s.type = (uint8_t)resType;
|
||||
s.bytes = bytes;
|
||||
s.colId = pExpr->base.colInfo.colId;
|
||||
|
||||
uint64_t uid = pTableMetaInfo->pTableMeta->id.uid;
|
||||
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
|
||||
if (finalResult) {
|
||||
insertResultField(pQueryInfo, colIndex, &ids, pUdfInfo->resBytes, pUdfInfo->resType, pExpr->base.aliasName, pExpr);
|
||||
} else {
|
||||
for (int32_t i = 0; i < ids.num; ++i) {
|
||||
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, uid, &s);
|
||||
}
|
||||
}
|
||||
|
||||
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// todo refactor
|
||||
|
@ -2800,8 +3093,7 @@ static bool isTablenameToken(SStrToken* token) {
|
|||
SStrToken tableToken = {0};
|
||||
|
||||
extractTableNameFromToken(&tmpToken, &tableToken);
|
||||
|
||||
return (strncasecmp(TSQL_TBNAME_L, tmpToken.z, tmpToken.n) == 0 && tmpToken.n == strlen(TSQL_TBNAME_L));
|
||||
return (tmpToken.n == strlen(TSQL_TBNAME_L) && strncasecmp(TSQL_TBNAME_L, tmpToken.z, tmpToken.n) == 0);
|
||||
}
|
||||
|
||||
static int16_t doGetColumnIndex(SQueryInfo* pQueryInfo, int32_t index, SStrToken* pToken) {
|
||||
|
@ -2832,8 +3124,11 @@ int32_t doGetColumnIndexByName(SStrToken* pToken, SQueryInfo* pQueryInfo, SColum
|
|||
|
||||
if (isTablenameToken(pToken)) {
|
||||
pIndex->columnIndex = TSDB_TBNAME_COLUMN_INDEX;
|
||||
} else if (strncasecmp(pToken->z, DEFAULT_PRIMARY_TIMESTAMP_COL_NAME, pToken->n) == 0) {
|
||||
pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
} else if (strlen(DEFAULT_PRIMARY_TIMESTAMP_COL_NAME) == pToken->n &&
|
||||
strncasecmp(pToken->z, DEFAULT_PRIMARY_TIMESTAMP_COL_NAME, pToken->n) == 0) {
|
||||
pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX; // just make runtime happy, need fix java test case InsertSpecialCharacterJniTest
|
||||
} else if (pToken->n == 0) {
|
||||
pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX; // just make runtime happy, need fix java test case InsertSpecialCharacterJniTest
|
||||
} else {
|
||||
// not specify the table name, try to locate the table index by column name
|
||||
if (pIndex->tableIndex == COLUMN_INDEX_INITIAL_VAL) {
|
||||
|
@ -3077,7 +3372,7 @@ int32_t tscTansformFuncForSTableQuery(SQueryInfo* pQueryInfo) {
|
|||
(functionId >= TSDB_FUNC_FIRST_DST && functionId <= TSDB_FUNC_STDDEV_DST) ||
|
||||
(functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_IRATE)) {
|
||||
if (getResultDataInfo(pSrcSchema->type, pSrcSchema->bytes, functionId, (int32_t)pExpr->base.param[0].i64, &type, &bytes,
|
||||
&interBytes, 0, true) != TSDB_CODE_SUCCESS) {
|
||||
&interBytes, 0, true, NULL) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
|
@ -3108,6 +3403,10 @@ void tscRestoreFuncForSTableQuery(SQueryInfo* pQueryInfo) {
|
|||
int32_t inter = 0;
|
||||
|
||||
int32_t functionId = pExpr->base.functionId;
|
||||
if (functionId < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId >= TSDB_FUNC_TS && functionId <= TSDB_FUNC_DIFF) {
|
||||
continue;
|
||||
}
|
||||
|
@ -3120,8 +3419,8 @@ void tscRestoreFuncForSTableQuery(SQueryInfo* pQueryInfo) {
|
|||
functionId = TSDB_FUNC_STDDEV;
|
||||
}
|
||||
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &pExpr->base.resType, &pExpr->base.resBytes,
|
||||
&inter, 0, false);
|
||||
getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &pExpr->base.resType, &pExpr->base.resBytes, &inter,
|
||||
0, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3134,6 +3433,10 @@ bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo)
|
|||
size_t size = tscNumOfExprs(pQueryInfo);
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
int32_t functionId = tscExprGet(pQueryInfo, i)->base.functionId;
|
||||
if (functionId < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((aAggs[functionId].status & TSDB_FUNCSTATE_STABLE) == 0) {
|
||||
invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
return true;
|
||||
|
@ -3178,40 +3481,48 @@ static bool groupbyTagsOrNull(SQueryInfo* pQueryInfo) {
|
|||
|
||||
static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool twQuery) {
|
||||
int32_t startIdx = 0;
|
||||
int32_t aggUdf = 0;
|
||||
int32_t scalarUdf = 0;
|
||||
int32_t prjNum = 0;
|
||||
int32_t aggNum = 0;
|
||||
|
||||
size_t numOfExpr = tscNumOfExprs(pQueryInfo);
|
||||
assert(numOfExpr > 0);
|
||||
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, startIdx);
|
||||
|
||||
// ts function can be simultaneously used with any other functions.
|
||||
int32_t functionID = pExpr->base.functionId;
|
||||
if (functionID == TSDB_FUNC_TS || functionID == TSDB_FUNC_TS_DUMMY) {
|
||||
startIdx++;
|
||||
}
|
||||
|
||||
int32_t factor = functionCompatList[tscExprGet(pQueryInfo, startIdx)->base.functionId];
|
||||
|
||||
if (tscExprGet(pQueryInfo, 0)->base.functionId == TSDB_FUNC_LAST_ROW && (joinQuery || twQuery || !groupbyTagsOrNull(pQueryInfo))) {
|
||||
return false;
|
||||
}
|
||||
int32_t factor = INT32_MAX;
|
||||
|
||||
// diff function cannot be executed with other function
|
||||
// arithmetic function can be executed with other arithmetic functions
|
||||
size_t size = tscNumOfExprs(pQueryInfo);
|
||||
|
||||
for (int32_t i = startIdx + 1; i < size; ++i) {
|
||||
for (int32_t i = startIdx; i < size; ++i) {
|
||||
SExprInfo* pExpr1 = tscExprGet(pQueryInfo, i);
|
||||
|
||||
int16_t functionId = pExpr1->base.functionId;
|
||||
if (functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TS) {
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * functionId - 1);
|
||||
pUdfInfo->funcType == TSDB_UDF_TYPE_AGGREGATE ? ++aggUdf : ++scalarUdf;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY) {
|
||||
++prjNum;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_PRJ) {
|
||||
++prjNum;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_PRJ && (pExpr1->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX || TSDB_COL_IS_UD_COL(pExpr1->base.colInfo.flag))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (factor == INT32_MAX) {
|
||||
factor = functionCompatList[functionId];
|
||||
} else {
|
||||
if (functionCompatList[functionId] != factor) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -3219,12 +3530,25 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery, bool
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_LAST_ROW && (joinQuery || twQuery || !groupbyTagsOrNull(pQueryInfo))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
aggNum = (int32_t)size - prjNum - aggUdf - scalarUdf;
|
||||
|
||||
assert(aggNum >= 0);
|
||||
|
||||
if (aggUdf > 0 && (prjNum > 0 || aggNum > 0 || scalarUdf > 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scalarUdf > 0 && aggNum > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3397,9 +3721,16 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
|
|||
int32_t bufLen = 0;
|
||||
if (IS_NUMERIC_TYPE(pRight->value.nType)) {
|
||||
bufLen = 60;
|
||||
} else {
|
||||
/*
|
||||
* make memory sanitizer happy;
|
||||
*/
|
||||
if (pRight->value.nLen == 0) {
|
||||
bufLen = pRight->value.nLen + 2;
|
||||
} else {
|
||||
bufLen = pRight->value.nLen + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pExpr->tokenId == TK_LE || pExpr->tokenId == TK_LT) {
|
||||
retVal = tVariantDump(&pRight->value, (char*)&pColumnFilter->upperBndd, colType, false);
|
||||
|
@ -3877,7 +4208,7 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSqlExpr* pExpr, SQueryInfo* pQuer
|
|||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, false) != TSDB_CODE_SUCCESS) {
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, false, NULL) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
|
@ -5320,6 +5651,7 @@ int32_t validateFillNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNo
|
|||
|
||||
if (pQueryInfo->fillVal == NULL) {
|
||||
pQueryInfo->fillVal = calloc(numOfFields, sizeof(int64_t));
|
||||
pQueryInfo->numOfFillVal = (int32_t)numOfFields;
|
||||
if (pQueryInfo->fillVal == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -5956,6 +6288,16 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
return invalidOperationMsg(pMsg, msg22);
|
||||
}
|
||||
|
||||
SSchema* pSchema = (SSchema*) pTableMetaInfo->pTableMeta->schema;
|
||||
int16_t numOfColumns = pTableMetaInfo->pTableMeta->tableInfo.numOfColumns;
|
||||
int16_t i;
|
||||
uint32_t nLen = 0;
|
||||
for (i = 0; i < numOfColumns; ++i) {
|
||||
nLen += (i != columnIndex.columnIndex) ? pSchema[i].bytes : pItem->bytes;
|
||||
}
|
||||
if (nLen >= TSDB_MAX_BYTES_PER_ROW) {
|
||||
return invalidOperationMsg(pMsg, msg24);
|
||||
}
|
||||
TAOS_FIELD f = tscCreateField(pColSchema->type, name.z, pItem->bytes);
|
||||
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
}else if (pAlterSQL->type == TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN) {
|
||||
|
@ -5997,6 +6339,17 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
return invalidOperationMsg(pMsg, msg22);
|
||||
}
|
||||
|
||||
SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
|
||||
int16_t numOfTags = tscGetNumOfTags(pTableMetaInfo->pTableMeta);
|
||||
int16_t i;
|
||||
uint32_t nLen = 0;
|
||||
for (i = 0; i < numOfTags; ++i) {
|
||||
nLen += (i != columnIndex.columnIndex) ? pSchema[i].bytes : pItem->bytes;
|
||||
}
|
||||
if (nLen >= TSDB_MAX_TAGS_LEN) {
|
||||
return invalidOperationMsg(pMsg, msg24);
|
||||
}
|
||||
|
||||
TAOS_FIELD f = tscCreateField(pColSchema->type, name.z, pItem->bytes);
|
||||
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
}
|
||||
|
@ -6037,6 +6390,16 @@ int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQu
|
|||
for (int32_t k = 0; k < size; ++k) {
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, k);
|
||||
|
||||
if (pExpr->base.functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * pExpr->base.functionId - 1);
|
||||
if (pUdfInfo->funcType == TSDB_UDF_TYPE_SCALAR) {
|
||||
isProjectionFunction = true;
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// projection query on primary timestamp, the selectivity function needs to be present.
|
||||
if (pExpr->base.functionId == TSDB_FUNC_PRJ && pExpr->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
bool hasSelectivity = false;
|
||||
|
@ -6056,6 +6419,7 @@ int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQu
|
|||
int32_t f = pExpr->base.functionId;
|
||||
if ((f == TSDB_FUNC_PRJ && pExpr->base.numOfParams == 0) || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_ARITHM || f == TSDB_FUNC_DERIVATIVE) {
|
||||
isProjectionFunction = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6541,11 +6905,15 @@ static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) {
|
|||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
|
||||
if (pExpr->base.functionId < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pExpr->base.functionId != TSDB_FUNC_TAG_DUMMY && pExpr->base.functionId != TSDB_FUNC_TS_DUMMY) &&
|
||||
!(pExpr->base.functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExpr->base.colInfo.flag))) {
|
||||
SSchema* pColSchema = &pSchema[pExpr->base.colInfo.colIndex];
|
||||
getResultDataInfo(pColSchema->type, pColSchema->bytes, pExpr->base.functionId, (int32_t)pExpr->base.param[0].i64, &pExpr->base.resType,
|
||||
&pExpr->base.resBytes, &pExpr->base.interBytes, tagLength, isSTable);
|
||||
&pExpr->base.resBytes, &pExpr->base.interBytes, tagLength, isSTable, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6673,6 +7041,14 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, char* msg) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * functionId - 1);
|
||||
if (pUdfInfo->funcType == TSDB_UDF_TYPE_AGGREGATE) {
|
||||
++numOfAggregation;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((aAggs[functionId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) {
|
||||
numOfSelectivity++;
|
||||
|
@ -6900,6 +7276,10 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
|
|||
}
|
||||
}
|
||||
|
||||
if (f < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!pQueryInfo->stateWindow) && (f == TSDB_FUNC_DIFF || f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE)) {
|
||||
for (int32_t j = 0; j < pQueryInfo->groupbyExpr.numOfGroupCols; ++j) {
|
||||
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, j);
|
||||
|
@ -6913,8 +7293,8 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_MULTIOUTPUT(aAggs[f].status) && f != TSDB_FUNC_TOP && f != TSDB_FUNC_BOTTOM &&
|
||||
f != TSDB_FUNC_DIFF && f != TSDB_FUNC_DERIVATIVE && f != TSDB_FUNC_TAGPRJ && f != TSDB_FUNC_PRJ) {
|
||||
if (IS_MULTIOUTPUT(aAggs[f].status) && f != TSDB_FUNC_TOP && f != TSDB_FUNC_BOTTOM && f != TSDB_FUNC_DIFF &&
|
||||
f != TSDB_FUNC_DERIVATIVE && f != TSDB_FUNC_TAGPRJ && f != TSDB_FUNC_PRJ) {
|
||||
return invalidOperationMsg(msg, msg1);
|
||||
}
|
||||
|
||||
|
@ -6941,6 +7321,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
|
|||
return checkUpdateTagPrjFunctions(pQueryInfo, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t doLocalQueryProcess(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode) {
|
||||
const char* msg1 = "only one expression allowed";
|
||||
const char* msg2 = "invalid expression in select clause";
|
||||
|
@ -7119,9 +7500,17 @@ void tscPrintSelNodeList(SSqlObj* pSql, int32_t subClauseIndex) {
|
|||
|
||||
char tmpBuf[1024] = {0};
|
||||
int32_t tmpLen = 0;
|
||||
char *name = NULL;
|
||||
|
||||
if (pExpr->base.functionId < 0) {
|
||||
SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * pExpr->base.functionId - 1);
|
||||
name = pUdfInfo->name;
|
||||
} else {
|
||||
name = aAggs[pExpr->base.functionId].name;
|
||||
}
|
||||
|
||||
tmpLen =
|
||||
sprintf(tmpBuf, "%s(uid:%" PRIu64 ", %d)", aAggs[pExpr->base.functionId].name, pExpr->base.uid,
|
||||
pExpr->base.colInfo.colId);
|
||||
sprintf(tmpBuf, "%s(uid:%" PRId64 ", %d)", name, pExpr->base.uid, pExpr->base.colInfo.colId);
|
||||
|
||||
if (tmpLen + offset >= totalBufSize - 1) break;
|
||||
|
||||
|
@ -7650,7 +8039,7 @@ int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelect
|
|||
int32_t outputIndex = (int32_t)tscNumOfExprs(pQueryInfo);
|
||||
|
||||
// ADD TRUE FOR TEST
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, true) != TSDB_CODE_SUCCESS) {
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, true, NULL) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
|
@ -7926,6 +8315,28 @@ static void freeElem(void* p) {
|
|||
tfree(*(char**)p);
|
||||
}
|
||||
|
||||
int32_t tnameComparFn(const void* p1, const void* p2) {
|
||||
SName* pn1 = (SName*)p1;
|
||||
SName* pn2 = (SName*)p2;
|
||||
|
||||
int32_t ret = strncmp(pn1->acctId, pn2->acctId, tListLen(pn1->acctId));
|
||||
if (ret != 0) {
|
||||
return ret > 0? 1:-1;
|
||||
} else {
|
||||
ret = strncmp(pn1->dbname, pn2->dbname, tListLen(pn1->dbname));
|
||||
if (ret != 0) {
|
||||
return ret > 0? 1:-1;
|
||||
} else {
|
||||
ret = strncmp(pn1->tname, pn2->tname, tListLen(pn1->tname));
|
||||
if (ret != 0) {
|
||||
return ret > 0? 1:-1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
|
@ -7940,6 +8351,7 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
SArray* pVgroupList = NULL;
|
||||
SArray* plist = NULL;
|
||||
STableMeta* pTableMeta = NULL;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfo(pCmd);
|
||||
|
||||
pCmd->pTableMetaMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||
|
||||
|
@ -7968,13 +8380,20 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
uint32_t maxSize = tscGetTableMetaMaxSize();
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
|
||||
char buf[80 * 1024] = {0};
|
||||
assert(maxSize < 80 * 1024);
|
||||
assert(maxSize < 80 * TSDB_MAX_COLUMNS);
|
||||
if (!pSql->pBuf) {
|
||||
if (NULL == (pSql->pBuf = tcalloc(1, 80 * TSDB_MAX_COLUMNS))) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
pTableMeta = calloc(1, maxSize);
|
||||
|
||||
plist = taosArrayInit(4, POINTER_BYTES);
|
||||
pVgroupList = taosArrayInit(4, POINTER_BYTES);
|
||||
|
||||
taosArraySort(tableNameList, tnameComparFn);
|
||||
taosArrayRemoveDuplicate(tableNameList, tnameComparFn, NULL);
|
||||
|
||||
size_t numOfTables = taosArrayGetSize(tableNameList);
|
||||
for (int32_t i = 0; i < numOfTables; ++i) {
|
||||
SName* pname = taosArrayGet(tableNameList, i);
|
||||
|
@ -7986,7 +8405,7 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
|
||||
if (pTableMeta->id.uid > 0) {
|
||||
if (pTableMeta->tableType == TSDB_CHILD_TABLE) {
|
||||
code = tscCreateTableMetaFromSTableMeta(pTableMeta, name, buf);
|
||||
code = tscCreateTableMetaFromSTableMeta(pTableMeta, name, pSql->pBuf);
|
||||
|
||||
// create the child table meta from super table failed, try load it from mnode
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -7995,26 +8414,65 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
continue;
|
||||
}
|
||||
} else if (pTableMeta->tableType == TSDB_SUPER_TABLE) {
|
||||
// the vgroup list of a super table is not kept in local buffer, so here need retrieve it
|
||||
// from the mnode each time
|
||||
// the vgroup list of super table is not kept in local buffer, so here need retrieve it from the mnode each time
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(pVgroupList, &t);
|
||||
}
|
||||
|
||||
STableMeta* pMeta = tscTableMetaDup(pTableMeta);
|
||||
STableMetaVgroupInfo p = { .pTableMeta = pMeta };
|
||||
//STableMeta* pMeta = tscTableMetaDup(pTableMeta);
|
||||
//STableMetaVgroupInfo p = { .pTableMeta = pMeta };
|
||||
|
||||
//const char* px = tNameGetTableName(pname);
|
||||
//taosHashPut(pCmd->pTableMetaMap, px, strlen(px), &p, sizeof(STableMetaVgroupInfo));
|
||||
// avoid mem leak, may should update pTableMeta
|
||||
const char* px = tNameGetTableName(pname);
|
||||
if (taosHashGet(pCmd->pTableMetaMap, px, strlen(px)) == NULL) {
|
||||
STableMeta* pMeta = tscTableMetaDup(pTableMeta);
|
||||
STableMetaVgroupInfo p = { .pTableMeta = pMeta, .pVgroupInfo = NULL};
|
||||
taosHashPut(pCmd->pTableMetaMap, px, strlen(px), &p, sizeof(STableMetaVgroupInfo));
|
||||
}
|
||||
} else { // add to the retrieve table meta array list.
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(plist, &t);
|
||||
}
|
||||
}
|
||||
|
||||
size_t funcSize = 0;
|
||||
if (pInfo->funcs) {
|
||||
funcSize = taosArrayGetSize(pInfo->funcs);
|
||||
}
|
||||
|
||||
if (funcSize > 0) {
|
||||
for (size_t i = 0; i < funcSize; ++i) {
|
||||
SStrToken* t = taosArrayGet(pInfo->funcs, i);
|
||||
if (NULL == t) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t->n >= TSDB_FUNC_NAME_LEN) {
|
||||
code = tscSQLSyntaxErrMsg(tscGetErrorMsgPayload(pCmd), "too long function name", t->z);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t functionId = isValidFunction(t->z, t->n);
|
||||
if (functionId < 0) {
|
||||
struct SUdfInfo info = {0};
|
||||
info.name = strndup(t->z, t->n);
|
||||
if (pQueryInfo->pUdfInfo == NULL) {
|
||||
pQueryInfo->pUdfInfo = taosArrayInit(4, sizeof(struct SUdfInfo));
|
||||
}
|
||||
|
||||
info.functionId = (int32_t)taosArrayGetSize(pQueryInfo->pUdfInfo) * (-1) - 1;;
|
||||
taosArrayPush(pQueryInfo->pUdfInfo, &info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load the table meta for a given table name list
|
||||
if (taosArrayGetSize(plist) > 0 || taosArrayGetSize(pVgroupList) > 0) {
|
||||
code = getMultiTableMetaFromMnode(pSql, plist, pVgroupList, tscTableMetaCallBack);
|
||||
if (taosArrayGetSize(plist) > 0 || taosArrayGetSize(pVgroupList) > 0 || (pQueryInfo->pUdfInfo && taosArrayGetSize(pQueryInfo->pUdfInfo) > 0)) {
|
||||
code = getMultiTableMetaFromMnode(pSql, plist, pVgroupList, pQueryInfo->pUdfInfo, tscTableMetaCallBack, true);
|
||||
}
|
||||
|
||||
_end:
|
||||
|
@ -8143,12 +8601,21 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS
|
|||
|
||||
// union all is not support currently
|
||||
SSqlNode* p = taosArrayGetP(subInfo->pSubquery, 0);
|
||||
|
||||
if (taosArrayGetSize(subInfo->pSubquery) >= 2) {
|
||||
return invalidOperationMsg(msgBuf, "not support union in subquery");
|
||||
}
|
||||
SQueryInfo* pSub = calloc(1, sizeof(SQueryInfo));
|
||||
tscInitQueryInfo(pSub);
|
||||
|
||||
SArray *pUdfInfo = NULL;
|
||||
if (pQueryInfo->pUdfInfo) {
|
||||
pUdfInfo = taosArrayDup(pQueryInfo->pUdfInfo);
|
||||
}
|
||||
|
||||
pSub->pUdfInfo = pUdfInfo;
|
||||
pSub->udfCopy = true;
|
||||
|
||||
int32_t code = validateSqlNode(pSql, p, pSub);
|
||||
assert(code != TSDB_CODE_TSC_ACTION_IN_PROGRESS);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
@ -8457,7 +8924,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
|
||||
// in case of join query, time range is required.
|
||||
if (QUERY_IS_JOIN_QUERY(pQueryInfo->type)) {
|
||||
int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey);
|
||||
uint64_t timeRange = (uint64_t)pQueryInfo->window.ekey - pQueryInfo->window.skey;
|
||||
if (timeRange == 0 && pQueryInfo->window.skey == 0) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
@ -8486,6 +8953,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
pQueryInfo->simpleAgg = isSimpleAggregateRv(pQueryInfo);
|
||||
pQueryInfo->onlyTagQuery = onlyTagPrjFunction(pQueryInfo);
|
||||
pQueryInfo->groupbyColumn = tscGroupbyColumn(pQueryInfo);
|
||||
//pQueryInfo->globalMerge = tscIsTwoStageSTableQuery(pQueryInfo, 0);
|
||||
|
||||
pQueryInfo->arithmeticOnAgg = tsIsArithmeticQueryOnAggResult(pQueryInfo);
|
||||
pQueryInfo->orderProjectQuery = tscOrderedProjectionQueryOnSTable(pQueryInfo, 0);
|
||||
|
@ -8499,6 +8967,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
}
|
||||
|
||||
taosArrayAddBatch(pQueryInfo->exprList1, (void*) p, numOfExpr);
|
||||
tfree(p);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -8719,11 +9188,10 @@ void normalizeSqlNode(SSqlNode* pSqlNode, const char* dbName) {
|
|||
// 2. pSqlNode->pWhere
|
||||
// 3. pSqlNode->pHaving
|
||||
// 4. pSqlNode->pSortOrder
|
||||
|
||||
// pSqlNode->from
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|