Merge branch 'develop' into feature/grafana_plugin

This commit is contained in:
xieyinglin 2019-12-19 20:03:27 +08:00
commit c7148e4e47
245 changed files with 15909 additions and 8244 deletions

View File

@ -38,21 +38,56 @@ IF (NOT DEFINED TD_CLUSTER)
# Set macro definitions according to os platform # Set macro definitions according to os platform
SET(TD_LINUX_64 FALSE) SET(TD_LINUX_64 FALSE)
SET(TD_LINUX_32 FALSE) SET(TD_LINUX_32 FALSE)
SET(TD_ARM FALSE)
SET(TD_ARM_64 FALSE) SET(TD_ARM_64 FALSE)
SET(TD_ARM_32 FALSE) SET(TD_ARM_32 FALSE)
SET(TD_MIPS_64 FALSE) SET(TD_MIPS_64 FALSE)
SET(TD_DARWIN_64 FALSE) SET(TD_DARWIN_64 FALSE)
SET(TD_WINDOWS_64 FALSE) SET(TD_WINDOWS_64 FALSE)
# if generate ARM version:
# cmake -DARMVER=arm32 .. or cmake -DARMVER=arm64
IF (${ARMVER} MATCHES "arm32")
SET(TD_ARM TRUE)
SET(TD_ARM_32 TRUE)
ADD_DEFINITIONS(-D_TD_ARM_)
ADD_DEFINITIONS(-D_TD_ARM_32_)
ELSEIF (${ARMVER} MATCHES "arm64")
SET(TD_ARM TRUE)
SET(TD_ARM_64 TRUE)
ADD_DEFINITIONS(-D_TD_ARM_)
ADD_DEFINITIONS(-D_TD_ARM_64_)
ENDIF ()
IF (TD_ARM)
ADD_DEFINITIONS(-D_TD_ARM_)
IF (TD_ARM_32)
ADD_DEFINITIONS(-D_TD_ARM_32_)
ELSEIF (TD_ARM_64)
ADD_DEFINITIONS(-D_TD_ARM_64_)
ELSE ()
EXIT ()
ENDIF ()
ENDIF ()
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
SET(TD_LINUX_64 TRUE) SET(TD_LINUX_64 TRUE)
SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/linux) SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/linux)
ADD_DEFINITIONS(-D_M_X64) ADD_DEFINITIONS(-D_M_X64)
MESSAGE(STATUS "The current platform is Linux 64-bit") MESSAGE(STATUS "The current platform is Linux 64-bit")
ELSE () ELSEIF (${CMAKE_SIZEOF_VOID_P} MATCHES 4)
IF (TD_ARM)
SET(TD_LINUX_32 TRUE) SET(TD_LINUX_32 TRUE)
MESSAGE(FATAL_ERROR "The current platform is Linux 32-bit, not supported yet") SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/linux)
#ADD_DEFINITIONS(-D_M_IX86)
MESSAGE(STATUS "The current platform is Linux 32-bit")
ELSE ()
MESSAGE(FATAL_ERROR "The current platform is Linux 32-bit, but no ARM not supported yet")
EXIT ()
ENDIF ()
ELSE ()
MESSAGE(FATAL_ERROR "The current platform is Linux neither 32-bit nor 64-bit, not supported yet")
EXIT () EXIT ()
ENDIF () ENDIF ()
ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@ -90,7 +125,9 @@ IF (NOT DEFINED TD_CLUSTER)
# debug flag # debug flag
# #
# ADD_DEFINITIONS(-D_CHECK_HEADER_FILE_) # ADD_DEFINITIONS(-D_CHECK_HEADER_FILE_)
# ADD_DEFINITIONS(-D_TAOS_MEM_TEST_) IF (${MEM_CHECK} MATCHES "true")
ADD_DEFINITIONS(-DTAOS_MEM_CHECK)
ENDIF ()
IF (TD_CLUSTER) IF (TD_CLUSTER)
ADD_DEFINITIONS(-DCLUSTER) ADD_DEFINITIONS(-DCLUSTER)
@ -102,13 +139,27 @@ IF (NOT DEFINED TD_CLUSTER)
IF (TD_LINUX_64) IF (TD_LINUX_64)
SET(DEBUG_FLAGS "-O0 -DDEBUG") SET(DEBUG_FLAGS "-O0 -DDEBUG")
SET(RELEASE_FLAGS "-O0") SET(RELEASE_FLAGS "-O0")
IF (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") IF (NOT TD_ARM)
SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -malign-double -g -Wno-char-subscripts -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") IF (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -malign-double -g -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ELSE ()
SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -malign-double -g -malign-stringops -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
ELSE () ELSE ()
SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -malign-double -g -Wno-char-subscripts -malign-stringops -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF () ENDIF ()
ADD_DEFINITIONS(-DLINUX) ADD_DEFINITIONS(-DLINUX)
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT) ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
ELSEIF (TD_LINUX_32)
IF (NOT TD_ARM)
EXIT ()
ENDIF ()
SET(DEBUG_FLAGS "-O0 -DDEBUG")
SET(RELEASE_FLAGS "-O0")
SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -g -fsigned-char -munaligned-access -fpack-struct=8 -latomic -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ADD_DEFINITIONS(-DLINUX)
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
ADD_DEFINITIONS(-DUSE_LIBICONV)
ELSEIF (TD_WINDOWS_64) ELSEIF (TD_WINDOWS_64)
SET(CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE) SET(CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE)
SET(COMMON_FLAGS "/nologo /WX- /Oi /Oy- /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Gd /errorReport:prompt /analyze-") SET(COMMON_FLAGS "/nologo /WX- /Oi /Oy- /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Gd /errorReport:prompt /analyze-")
@ -120,7 +171,7 @@ IF (NOT DEFINED TD_CLUSTER)
ADD_DEFINITIONS(-DPTW32_BUILD) ADD_DEFINITIONS(-DPTW32_BUILD)
ADD_DEFINITIONS(-D_MBCS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) ADD_DEFINITIONS(-D_MBCS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
ELSEIF (TD_DARWIN_64) ELSEIF (TD_DARWIN_64)
SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -malign-double -g -Wno-char-subscripts -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -Wno-unused-variable -Wno-bitfield-constant-conversion") SET(COMMON_FLAGS "-std=gnu99 -Wall -fPIC -malign-double -g -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
SET(DEBUG_FLAGS "-O0 -DDEBUG") SET(DEBUG_FLAGS "-O0 -DDEBUG")
SET(RELEASE_FLAGS "-O0") SET(RELEASE_FLAGS "-O0")
ADD_DEFINITIONS(-DDARWIN) ADD_DEFINITIONS(-DDARWIN)
@ -169,6 +220,14 @@ IF (NOT DEFINED TD_CLUSTER)
INSTALL(CODE "MESSAGE(\"make install script: ${TD_MAKE_INSTALL_SH}\")") INSTALL(CODE "MESSAGE(\"make install script: ${TD_MAKE_INSTALL_SH}\")")
INSTALL(CODE "execute_process(COMMAND chmod 777 ${TD_MAKE_INSTALL_SH})") INSTALL(CODE "execute_process(COMMAND chmod 777 ${TD_MAKE_INSTALL_SH})")
INSTALL(CODE "execute_process(COMMAND ${TD_MAKE_INSTALL_SH} ${TD_COMMUNITY_DIR} ${PROJECT_BINARY_DIR})") INSTALL(CODE "execute_process(COMMAND ${TD_MAKE_INSTALL_SH} ${TD_COMMUNITY_DIR} ${PROJECT_BINARY_DIR})")
ELSEIF (TD_LINUX_32)
IF (NOT TD_ARM)
EXIT ()
ENDIF ()
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
INSTALL(CODE "MESSAGE(\"make install script: ${TD_MAKE_INSTALL_SH}\")")
INSTALL(CODE "execute_process(COMMAND chmod 777 ${TD_MAKE_INSTALL_SH})")
INSTALL(CODE "execute_process(COMMAND ${TD_MAKE_INSTALL_SH} ${TD_COMMUNITY_DIR} ${PROJECT_BINARY_DIR})")
ELSEIF (TD_WINDOWS_64) ELSEIF (TD_WINDOWS_64)
SET(CMAKE_INSTALL_PREFIX C:/TDengine) SET(CMAKE_INSTALL_PREFIX C:/TDengine)
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector)

View File

@ -39,12 +39,18 @@ sudo apt-get install maven
``` ```
Build TDengine: Build TDengine:
```cmd
```
mkdir build && cd build mkdir build && cd build
cmake .. && cmake --build . cmake .. && cmake --build .
``` ```
if compiling on an arm64 processor, you need add one parameter:
```cmd
cmake .. -DARMVER=arm64 && cmake --build .
```
# Quick Run # Quick Run
To quickly start a TDengine server after building, run the command below in terminal: To quickly start a TDengine server after building, run the command below in terminal:
```cmd ```cmd

View File

@ -114,23 +114,84 @@ public Connection getConn() throws Exception{
</ul> </ul>
<p>对于TDengine操作的报错信息用户可使用JDBCDriver包里提供的枚举类TSDBError.java来获取error message和error code的列表。对于更多的具体操作的相关代码请参考TDengine提供的使用示范项目<code>JDBCDemo</code></p> <p>对于TDengine操作的报错信息用户可使用JDBCDriver包里提供的枚举类TSDBError.java来获取error message和error code的列表。对于更多的具体操作的相关代码请参考TDengine提供的使用示范项目<code>JDBCDemo</code></p>
<a class='anchor' id='Python-Connector'></a><h2>Python Connector</h2> <a class='anchor' id='Python-Connector'></a><h2>Python Connector</h2>
<a class='anchor' id='Python客户端安装'></a><h3>Python客户端安装</h3> <a class='anchor' id='安装准备'></a><h3>安装准备</h3>
<p>用户可以在源代码的src/connector/python文件夹下找到python2和python3的安装包。用户可以通过pip命令安装 </p> <li>已安装TDengine, 如果客户端在Windows上需要安装Windows 版本的TDengine客户端</li>
<p> <code>pip install src/connector/python/python2/</code></p> <li>已安装python 2.7 or >= 3.4</li>
<p></p> <li>已安装pip</li>
<p> <code>pip install src/connector/python/python3/</code></p> <a class='anchor' id='安装'></a><h3>安装</h3>
<p>如果机器上没有pip命令用户可将src/connector/python/python3或src/connector/python/python2下的taos文件夹拷贝到应用程序的目录使用。</p> <a class='anchor' id='Linux'></a><h4>Linux</h4>
<a class='anchor' id='Python客户端接口'></a><h3>Python客户端接口</h3> <p>用户可以在源代码的src/connector/python文件夹下找到python2和python3的安装包 然后通过pip命令安装</p>
<p>在使用TDengine的python接口时需导入TDengine客户端模块</p> <pre><code class="cmd language-cmd">pip install src/connector/python/linux/python2/</code></pre>
<pre><code>import taos </code></pre> <p>或者</p>
<p>用户可通过python的帮助信息直接查看模块的使用信息或者参考code/examples/python中的示例程序。以下为部分常用类和方法</p> <pre><code>pip install src/connector/python/linux/python3/</code></pre>
<a class='anchor' id='Windows'></a><h4>Windows</h4>
<p>在已安装Windows TDengine 客户端的情况下, 将文件"C:\TDengine\driver\taos.dll" 拷贝到 "C:\windows\system32" 目录下, 然后进入Windwos <em>cmd</em> 命令行界面</p>
<pre><code>cd C:\TDengine\connector\python\windows</code></pre>
<pre><code>pip install python2\</code></pre>
<p>或者</p>
<pre><code>cd C:\TDengine\connector\python\windows</code></pre>
<pre><code>pip install python3\</code></pre>
<p>* 如果机器上没有<em>pip</em>命令用户可将src/connector/python/windows/python3或src/connector/python/windows/python2下的taos文件夹拷贝到应用程序的目录使用。 </p>
<a class='anchor' id='使用'></a><h3>使用</h3>
<a class='anchor' id='代码示例'></a><h4>代码示例</h4>
<li>导入TDengine客户端模块</li>
<pre><code class="python language-python">import taos </code></pre>
<li>获取连接</li>
<pre><code>
conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/etc/taos")
c1 = conn.cursor()
</code></pre>
<p>* <em>host 是TDengine 服务端所有IP, config 为客户端配置文件所在目录</em></p>
<li>写入数据</li>
<pre><code>
import datetime
# 创建数据库
c1.execute('create database db')
c1.execute('use db')
# 建表
c1.execute('create table tb (ts timestamp, temperature int, humidity float)')
# 插入数据
start_time = datetime.datetime(2019, 11, 1)
affected_rows = c1.execute('insert into tb values (\'%s\', 0, 0.0)' %start_time)
# 批量插入数据
time_interval = datetime.timedelta(seconds=60)
sqlcmd = ['insert into tb values']
for irow in range(1,11):
start_time += time_interval
sqlcmd.append('(\'%s\', %d, %f)' %(start_time, irow, irow*1.2))
affected_rows = c1.execute(' '.join(sqlcmd))
</code></pre>
<li>查询数据</li>
<code><pre>
c1.execute('select * from tb')
# 拉取查询结果
data = c1.fetchall()
# 返回的结果是一个列表,每一行构成列表的一个元素
numOfRows = c1.rowcount
numOfCols = c1.descriptions
for irow in range(numOfRows):
print("Row%d: ts=%s, temperature=%d, humidity=%f" %(irow, data[irow][0], data[irow][1],data[irow][2])
# 直接使用cursor 循环拉取查询结果
c1.execute('select * from tb')
for data in c1:
print("ts=%s, temperature=%d, humidity=%f" %(data[0], data[1],data[2])
</pre></code>
<li>关闭连接</li>
<code><pre>
c1.close()
conn.close()
</pre></code>
<a class='anchor' id='帮助信息''></a><h4>帮助信息</h4>
<p>用户可通过python的帮助信息直接查看模块的使用信息或者参考code/examples/python中的示例程序。以下为部分常用类和方法:</p>
<ul> <ul>
<li><p><em>TaosConnection</em></p> <li><p><em>TaosConnection</em> </p>
<p>参考python中help(taos.TaosConnection)。</p></li> <p>参考python中<code>help(taos.TDengineConnection)</code></p></li>
<li><p><em>TaosCursor</em></p> <li><p><em>TaosCursor</em> </p>
<p>参考python中help(taos.TaosCursor)。</p></li> <p>参考python中<code>help(taos.TDengineCursor)</code></p></li>
<li><p><em>connect</em>方法</p> <li><p>connect 方法</p>
<p>用于生成taos.TaosConnection的实例。</p></li> <p>用于生成taos.TDengineConnection的实例。</p></li>
</ul> </ul>
<a class='anchor' id='RESTful-Connector'></a><h2>RESTful Connector</h2> <a class='anchor' id='RESTful-Connector'></a><h2>RESTful Connector</h2>
<p>为支持各种不同类型平台的开发TDengine提供符合REST设计标准的API即RESTful API。为最大程度降低学习成本不同于其他数据库RESTful API的设计方法TDengine直接通过HTTP POST 请求BODY中包含的SQL语句来操作数据库仅需要一个URL。 </p> <p>为支持各种不同类型平台的开发TDengine提供符合REST设计标准的API即RESTful API。为最大程度降低学习成本不同于其他数据库RESTful API的设计方法TDengine直接通过HTTP POST 请求BODY中包含的SQL语句来操作数据库仅需要一个URL。 </p>

View File

@ -28,7 +28,7 @@
<p>在TDengine终端中用户可以通过SQL命令来创建/删除数据库、表等并进行插入查询操作。在终端中运行的SQL语句需要以分号结束来运行。示例</p> <p>在TDengine终端中用户可以通过SQL命令来创建/删除数据库、表等并进行插入查询操作。在终端中运行的SQL语句需要以分号结束来运行。示例</p>
<pre><code class="mysql language-mysql">create database db; <pre><code class="mysql language-mysql">create database db;
use db; use db;
create table t (ts timestamp, cdata int); create table t (ts timestamp, speed int);
insert into t values ('2019-07-15 00:00:00', 10); insert into t values ('2019-07-15 00:00:00', 10);
insert into t values ('2019-07-15 01:00:00', 20); insert into t values ('2019-07-15 01:00:00', 20);
select * from t; select * from t;
@ -63,7 +63,7 @@ Query OK, 2 row(s) in set (0.001700s)</code></pre>
<a class='anchor' id='主要功能'></a><h2>主要功能</h2> <a class='anchor' id='主要功能'></a><h2>主要功能</h2>
<p>TDengine的核心功能是时序数据库。除此之外为减少研发的复杂度、系统维护的难度TDengine还提供缓存、消息队列、订阅、流式计算等功能。更详细的功能如下</p> <p>TDengine的核心功能是时序数据库。除此之外为减少研发的复杂度、系统维护的难度TDengine还提供缓存、消息队列、订阅、流式计算等功能。更详细的功能如下</p>
<ul> <ul>
<li>使用类SQL语言插入或查询数据</li> <li>使用类SQL语言插入或查询数据</li>
<li>支持C/C++, Java(JDBC), Python, Go, RESTful, and Node.JS 开发接口</li> <li>支持C/C++, Java(JDBC), Python, Go, RESTful, and Node.JS 开发接口</li>
<li>可通过Python/R/Matlab or TDengine shell做Ad Hoc查询分析</li> <li>可通过Python/R/Matlab or TDengine shell做Ad Hoc查询分析</li>
<li>通过定时连续查询支持基于滑动窗口的流式计算</li> <li>通过定时连续查询支持基于滑动窗口的流式计算</li>
@ -85,4 +85,4 @@ Query OK, 2 row(s) in set (0.001700s)</code></pre>
</ul> </ul>
<p>TDengine是专为物联网、车联网、工业互联网、运维监测等场景优化设计的时序数据处理引擎。与其他方案相比它的插入查询速度都快10倍以上。单核一秒钟就能插入100万数据点读出1000万数据点。由于采用列式存储和优化的压缩算法存储空间不及普通数据库的1/10.</p> <p>TDengine是专为物联网、车联网、工业互联网、运维监测等场景优化设计的时序数据处理引擎。与其他方案相比它的插入查询速度都快10倍以上。单核一秒钟就能插入100万数据点读出1000万数据点。由于采用列式存储和优化的压缩算法存储空间不及普通数据库的1/10.</p>
<a class='anchor' id='深入了解TDengine'></a><h2>深入了解TDengine</h2> <a class='anchor' id='深入了解TDengine'></a><h2>深入了解TDengine</h2>
<p>请继续阅读<a href="../documentation">文档</a>来深入了解TDengine。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html> <p>请继续阅读<a href="../documentation">文档</a>来深入了解TDengine。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>

View File

@ -24,7 +24,7 @@ tags (location binary(20), type int)</code></pre>
<p>说明:</p> <p>说明:</p>
<ol> <ol>
<li>TAGS列总长度不能超过512 bytes</li> <li>TAGS列总长度不能超过512 bytes</li>
<li>TAGS列的数据类型不能是timestamp和nchar类型;</li> <li>TAGS列的数据类型不能是timestamp类型</li>
<li>TAGS列名不能与其他列名相同;</li> <li>TAGS列名不能与其他列名相同;</li>
<li>TAGS列名不能为预留关键字. </li></ol></li> <li>TAGS列名不能为预留关键字. </li></ol></li>
<li><p>显示已创建的超级表</p> <li><p>显示已创建的超级表</p>
@ -40,7 +40,7 @@ tags (location binary(20), type int)</code></pre>
<p>统计属于某个STable并满足查询条件的子表的数量</p></li> <p>统计属于某个STable并满足查询条件的子表的数量</p></li>
</ul> </ul>
<a class='anchor' id='写数据时自动建子表'></a><h2>写数据时自动建子表</h2> <a class='anchor' id='写数据时自动建子表'></a><h2>写数据时自动建子表</h2>
<p>在某些特殊场景中,用户在写数据时并不确定某个设备的表是否存在,此时可使用自动建表语法来实现写入数据时用超级表定义的表结构自动创建不存在的子表若该表已存在则不会建立新表。注意自动建表语句只能自动建立子表而不能建立超级表这就要求超级表已经被事先定义好。自动建表语法跟insert/import语法非常相似唯一区别是语句中增加了超级表和标签信息。具体语法如下</p> <p>在某些特殊场景中用户在写数据时并不确定某个设备的表是否存在此时可使用自动建表语法来实现写入数据时用超级表定义的表结构自动创建不存在的子表若该表已存在则不会建立新表。注意自动建表语句只能自动建立子表而不能建立超级表这就要求超级表已经被事先定义好。自动建表语法跟insert/import语法非常相似唯一区别是语句中增加了超级表和标签信息。具体语法如下</p>
<pre><code class="mysql language-mysql">INSERT INTO &lt;tb_name&gt; USING &lt;stb_name&gt; TAGS (&lt;tag1_value&gt;, ...) VALUES (field_value, ...) (field_value, ...) ...;</code></pre> <pre><code class="mysql language-mysql">INSERT INTO &lt;tb_name&gt; USING &lt;stb_name&gt; TAGS (&lt;tag1_value&gt;, ...) VALUES (field_value, ...) (field_value, ...) ...;</code></pre>
<p>向表tb_name中插入一条或多条记录如果tb_name这张表不存在则会用超级表stb_name定义的表结构以及用户指定的标签值(即tag1_value…)来创建名为tb_name新表并将用户指定的值写入表中。如果tb_name已经存在则建表过程会被忽略系统也不会检查tb_name的标签是否与用户指定的标签值一致也即不会更新已存在表的标签。</p> <p>向表tb_name中插入一条或多条记录如果tb_name这张表不存在则会用超级表stb_name定义的表结构以及用户指定的标签值(即tag1_value…)来创建名为tb_name新表并将用户指定的值写入表中。如果tb_name已经存在则建表过程会被忽略系统也不会检查tb_name的标签是否与用户指定的标签值一致也即不会更新已存在表的标签。</p>
<pre><code class="mysql language-mysql">INSERT INTO &lt;tb1_name&gt; USING &lt;stb1_name&gt; TAGS (&lt;tag1_value1&gt;, ...) VALUES (&lt;field1_value1&gt;, ...) (&lt;field1_value2&gt;, ...) ... &lt;tb_name2&gt; USING &lt;stb_name2&gt; TAGS(&lt;tag1_value2&gt;, ...) VALUES (&lt;field1_value1&gt;, ...) ...;</code></pre> <pre><code class="mysql language-mysql">INSERT INTO &lt;tb1_name&gt; USING &lt;stb1_name&gt; TAGS (&lt;tag1_value1&gt;, ...) VALUES (&lt;field1_value1&gt;, ...) (&lt;field1_value2&gt;, ...) ... &lt;tb_name2&gt; USING &lt;stb_name2&gt; TAGS(&lt;tag1_value2&gt;, ...) VALUES (&lt;field1_value1&gt;, ...) ...;</code></pre>
@ -105,6 +105,6 @@ GROUP BY location, type </code></pre>
<p>查询仅位于北京以外地区的温度传感器最近24小时(24h)采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)和最低温度min(degree)将采集结果按照10分钟为周期进行聚合并将结果按所处地域(location)和传感器类型(type)再次进行聚合。</p> <p>查询仅位于北京以外地区的温度传感器最近24小时(24h)采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)和最低温度min(degree)将采集结果按照10分钟为周期进行聚合并将结果按所处地域(location)和传感器类型(type)再次进行聚合。</p>
<pre><code class="mysql language-mysql">SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree) <pre><code class="mysql language-mysql">SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree)
FROM thermometer FROM thermometer
WHERE name&lt;&gt;'beijing' and ts&gt;=now-1d WHERE location&lt;&gt;'beijing' and ts&gt;=now-1d
INTERVAL(10M) INTERVAL(10M)
GROUP BY location, type</code></pre><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html> GROUP BY location, type</code></pre><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>

View File

@ -359,9 +359,9 @@ SELECT function_list FROM tb_name
SELECT function_list FROM stb_name SELECT function_list FROM stb_name
[WHERE where_condition] [WHERE where_condition]
[GROUP BY tags] [FILL ({ VALUE | PREV | NULL | LINEAR})]
INTERVAL (interval) INTERVAL (interval)
[FILL ({ VALUE | PREV | NULL | LINEAR})]</code></pre> [GROUP BY tags]</code></pre>
<ul> <ul>
<li>聚合时间段的长度由关键词INTERVAL指定最短时间间隔10毫秒10a。聚合查询中能够同时执行的聚合和选择函数仅限于单个输出的函数count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last不能使用具有多行输出结果的函数例如top、bottom、diff以及四则运算</li> <li>聚合时间段的长度由关键词INTERVAL指定最短时间间隔10毫秒10a。聚合查询中能够同时执行的聚合和选择函数仅限于单个输出的函数count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last不能使用具有多行输出结果的函数例如top、bottom、diff以及四则运算</li>
<li>WHERE语句可以指定查询的起止时间和其他过滤条件 </li> <li>WHERE语句可以指定查询的起止时间和其他过滤条件 </li>

View File

@ -122,15 +122,76 @@ public Connection getConn() throws Exception{
</ul> </ul>
<p>All the error codes and error messages can be found in <code>TSDBError.java</code> . For a more detailed coding example, please refer to the demo project <code>JDBCDemo</code> in TDengine's code examples. </p> <p>All the error codes and error messages can be found in <code>TSDBError.java</code> . For a more detailed coding example, please refer to the demo project <code>JDBCDemo</code> in TDengine's code examples. </p>
<a class='anchor' id='Python-Connector'></a><h2>Python Connector</h2> <a class='anchor' id='Python-Connector'></a><h2>Python Connector</h2>
<a class='anchor' id='Install-TDengine-Python-client'></a><h3>Install TDengine Python client</h3> <a class='anchor' id='Pre-requirement'></a><h3>Pre-requirement</h3>
<p>Users can find python client packages in our source code directory <em>src/connector/python</em>. There are two directories corresponding two python versions. Please choose the correct package to install. Users can use <em>pip</em> command to install:</p> <li>TDengine installed, TDengine-client installed if on Windows</li>
<pre><code class="cmd language-cmd">pip install src/connector/python/python2/</code></pre> <li>python 2.7 or >= 3.4</li>
<li>pip installed </li>
<a class='anchor' id='Installation'></a><h3>Installation</h3>
<a class='anchor' id='Linux'></a><h4>Linux</h4>
<p>Users can find python client packages in our source code directory <em>src/connector/python</em>. There are two directories corresponding to two python versions. Please choose the correct package to install. Users can use <em>pip</em> command to install:</p>
<pre><code class="cmd language-cmd">pip install src/connector/python/linux/python2/</code></pre>
<p>or</p> <p>or</p>
<pre><code>pip install src/connector/python/python3/</code></pre> <pre><code>pip install src/connector/python/linux/python3/</code></pre>
<p>If <em>pip</em> command is not installed on the system, users can choose to install pip or just copy the <em>taos</em> directory in the python client directory to the application directory to use.</p> <a class='anchor' id='Windows'></a><h4>Windows</h4>
<a class='anchor' id='Python-client-interfaces'></a><h3>Python client interfaces</h3> <p>Assumed the Windows TDengine client has been installed , copy the file "C:\TDengine\driver\taos.dll" to the folder "C:\windows\system32", and then enter the <em>cmd</em> Windows command interface</p>
<p>To use TDengine Python client, import TDengine module at first:</p> <pre><code>cd C:\TDengine\connector\python\windows</code></pre>
<pre><code>pip install python2\</code></pre>
<p>or</p>
<pre><code>cd C:\TDengine\connector\python\windows</code></pre>
<pre><code>pip install python3\</code></pre>
<p>* If <em>pip</em> command is not installed on the system, users can choose to install pip or just copy the <em>taos</em> directory in the python client directory to the application directory to use.</p>
<a class='anchor' id='Usage'></a><h3>Usage</h3>
<a class='anchor' id='Examples'></a><h4>Examples</h4>
<li>import TDengine module at first:</li>
<pre><code class="python language-python">import taos </code></pre> <pre><code class="python language-python">import taos </code></pre>
<li>get the connection</li>
<pre><code>
conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/etc/taos")
c1 = conn.cursor()
</code></pre>
<p>* <em>host is the IP of TDengine server, and config is the directory where exists the TDengine client configure file</em></p>
<li>insert records into the database</li>
<pre><code>
import datetime
# create a database
c1.execute('create database db')
c1.execute('use db')
# create a table
c1.execute('create table tb (ts timestamp, temperature int, humidity float)')
# insert a record
start_time = datetime.datetime(2019, 11, 1)
affected_rows = c1.execute('insert into tb values (\'%s\', 0, 0.0)' %start_time)
# insert multiple records in a batch
time_interval = datetime.timedelta(seconds=60)
sqlcmd = ['insert into tb values']
for irow in range(1,11):
start_time += time_interval
sqlcmd.append('(\'%s\', %d, %f)' %(start_time, irow, irow*1.2))
affected_rows = c1.execute(' '.join(sqlcmd))
</code></pre>
<li>query the database</li>
<code><pre>
c1.execute('select * from tb')
# fetch all returned results
data = c1.fetchall()
# data is a list of returned rows with each row being a tuple
numOfRows = c1.rowcount
numOfCols = c1.descriptions
for irow in range(numOfRows):
print("Row%d: ts=%s, temperature=%d, humidity=%f" %(irow, data[irow][0], data[irow][1],data[irow][2])
# use the cursor as an iterator to retrieve all returned results
c1.execute('select * from tb')
for data in c1:
print("ts=%s, temperature=%d, humidity=%f" %(data[0], data[1],data[2])
</pre></code>
<li>close the connection</li>
<code><pre>
c1.close()
conn.close()
</pre></code>
<a class='anchor' id='Help information''></a><h4>Help information</h4>
<p>Users can get module information from Python help interface or refer to our [python code example](). We list the main classes and methods below:</p> <p>Users can get module information from Python help interface or refer to our [python code example](). We list the main classes and methods below:</p>
<ul> <ul>
<li><p><em>TaosConnection</em> class</p> <li><p><em>TaosConnection</em> class</p>

View File

@ -28,7 +28,7 @@
<p>In the TDengine shell, you can create databases, create tables and insert/query data with SQL. Each query command ends with a semicolon. It works like MySQL, for example:</p> <p>In the TDengine shell, you can create databases, create tables and insert/query data with SQL. Each query command ends with a semicolon. It works like MySQL, for example:</p>
<pre><code class="mysql language-mysql">create database db; <pre><code class="mysql language-mysql">create database db;
use db; use db;
create table t (ts timestamp, cdata int); create table t (ts timestamp, speed int);
insert into t values ('2019-07-15 10:00:00', 10); insert into t values ('2019-07-15 10:00:00', 10);
insert into t values ('2019-07-15 10:01:05', 20); insert into t values ('2019-07-15 10:01:05', 20);
select * from t; select * from t;
@ -85,4 +85,4 @@ Query OK, 2 row(s) in set (0.001700s)</code></pre>
</ul> </ul>
<p>TDengine is specially designed and optimized for time-series data processing in IoT, connected cars, Industrial IoT, IT infrastructure and application monitoring, and other scenarios. Compared with other solutions, it is 10x faster on insert/query speed. With a single-core machine, over 20K requestes can be processed, millions data points can be ingested, and over 10 million data points can be retrieved in a second. Via column-based storage and tuned compression algorithm for different data types, less than 1/10 storage space is required. </p> <p>TDengine is specially designed and optimized for time-series data processing in IoT, connected cars, Industrial IoT, IT infrastructure and application monitoring, and other scenarios. Compared with other solutions, it is 10x faster on insert/query speed. With a single-core machine, over 20K requestes can be processed, millions data points can be ingested, and over 10 million data points can be retrieved in a second. Via column-based storage and tuned compression algorithm for different data types, less than 1/10 storage space is required. </p>
<a class='anchor' id='Explore-More-on-TDengine'></a><h2>Explore More on TDengine</h2> <a class='anchor' id='Explore-More-on-TDengine'></a><h2>Explore More on TDengine</h2>
<p>Please read through the whole <a href='../documentation'>documentation</a> to learn more about TDengine.</p><a href='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html> <p>Please read through the whole <a href='../documentation'>documentation</a> to learn more about TDengine.</p><a href='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>

View File

@ -6,9 +6,9 @@
<p>Like a table, you can create, show, delete and describe STables. Most query operations on tables can be applied to STable too, including the aggregation and selector functions. For queries on a STable, if no tags filter, the operations are applied to all the tables created via this STable. If there is a tag filter, the operations are applied only to a subset of the tables which satisfy the tag filter conditions. It will be very convenient to use tags to put devices into different groups for aggregation.</p> <p>Like a table, you can create, show, delete and describe STables. Most query operations on tables can be applied to STable too, including the aggregation and selector functions. For queries on a STable, if no tags filter, the operations are applied to all the tables created via this STable. If there is a tag filter, the operations are applied only to a subset of the tables which satisfy the tag filter conditions. It will be very convenient to use tags to put devices into different groups for aggregation.</p>
<a class='anchor' id='Create-a-STable'></a><h2>Create a STable</h2> <a class='anchor' id='Create-a-STable'></a><h2>Create a STable</h2>
<p>Similiar to creating a standard table, syntax is: </p> <p>Similiar to creating a standard table, syntax is: </p>
<pre><code class="mysql language-mysql">CREATE TABLE &lt;stable_name&gt; (&lt;field_name&gt; TIMESTAMP, field_name1 field_type,…) TAGS(tag_name tag_type, …)</code></pre> <pre><code class="mysql language-mysql">CREATE TABLE &lt;stable_name&gt; (&lt;field_name&gt; TIMESTAMP, field_name1 field_type, ...) TAGS(tag_name tag_type, ...)</code></pre>
<p>New keyword "tags" is introduced, where tag_name is the tag name, and tag_type is the associated data type. </p> <p>New keyword "tags" is introduced, where tag_name is the tag name, and tag_type is the associated data type. </p>
<p>Note</p> <p>Note: </p>
<ol> <ol>
<li>The bytes of all tags together shall be less than 512 </li> <li>The bytes of all tags together shall be less than 512 </li>
<li>Tag's data type can not be time stamp or nchar</li> <li>Tag's data type can not be time stamp or nchar</li>
@ -30,12 +30,12 @@ tags (location binary(20), type int)</code></pre>
create table t4 using thermometer tags ('shanghai', 20); create table t4 using thermometer tags ('shanghai', 20);
create table t5 using thermometer tags ('new york', 10);</code></pre> create table t5 using thermometer tags ('new york', 10);</code></pre>
<a class='anchor' id='Aggregate-Tables-via-STable'></a><h2>Aggregate Tables via STable</h2> <a class='anchor' id='Aggregate-Tables-via-STable'></a><h2>Aggregate Tables via STable</h2>
<p>You can group a set of tables together by specifying the tags filter condition, then apply the aggregation operations. The result set can be grouped and ordered based on tag value. Syntax is</p> <p>You can group a set of tables together by specifying the tags filter condition, then apply the aggregation operations. The result set can be grouped and ordered based on tag value. Syntax is:</p>
<pre><code class="mysql language-mysql">SELECT function&lt;field_name&gt;, <pre><code class="mysql language-mysql">SELECT function&lt;field_name&gt;, ...
FROM &lt;stable_name&gt; FROM &lt;stable_name&gt;
WHERE &lt;tag_name&gt; &lt;[=|&lt;=|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] …) WHERE &lt;tag_name&gt; &lt;[=|&lt;=|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] ...
INTERVAL (&lt;time range&gt;) INTERVAL (&lt;time range&gt;)
GROUP BY &lt;tag_name&gt;, &lt;tag_name&gt; GROUP BY &lt;tag_name&gt;, &lt;tag_name&gt; ...
ORDER BY &lt;tag_name&gt; &lt;asc|desc&gt; ORDER BY &lt;tag_name&gt; &lt;asc|desc&gt;
SLIMIT &lt;group_limit&gt; SLIMIT &lt;group_limit&gt;
SOFFSET &lt;group_offset&gt; SOFFSET &lt;group_offset&gt;
@ -75,9 +75,9 @@ INTERVAL(10M)</code></pre>
<pre><code class="mysql language-mysql">DROP TABLE &lt;stable_name&gt;</code></pre> <pre><code class="mysql language-mysql">DROP TABLE &lt;stable_name&gt;</code></pre>
<p>To delete a STable, all the tables created via this STable shall be deleted first, otherwise, it will fail.</p> <p>To delete a STable, all the tables created via this STable shall be deleted first, otherwise, it will fail.</p>
<a class='anchor' id='List-the-Associated-Tables-of-a-STable'></a><h3>List the Associated Tables of a STable</h3> <a class='anchor' id='List-the-Associated-Tables-of-a-STable'></a><h3>List the Associated Tables of a STable</h3>
<pre><code class="mysql language-mysql">SELECT TBNAME,[TAG_NAME,] FROM &lt;stable_name&gt; WHERE &lt;tag_name&gt; &lt;[=|=&lt;|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] )</code></pre> <pre><code class="mysql language-mysql">SELECT TBNAME,[TAG_NAME, ...] FROM &lt;stable_name&gt; WHERE &lt;tag_name&gt; &lt;[=|=&lt;|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] ...)</code></pre>
<p>It will list all the tables which satisfy the tag filter conditions. The tables are all created from this specific STable. TBNAME is a new keyword introduced, it is the table name associated with the STable. </p> <p>It will list all the tables which satisfy the tag filter conditions. The tables are all created from this specific STable. TBNAME is a new keyword introduced, it is the table name associated with the STable. </p>
<pre><code class="mysql language-mysql">SELECT COUNT(TBNAME) FROM &lt;stable_name&gt; WHERE &lt;tag_name&gt; &lt;[=|=&lt;|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] )</code></pre> <pre><code class="mysql language-mysql">SELECT COUNT(TBNAME) FROM &lt;stable_name&gt; WHERE &lt;tag_name&gt; &lt;[=|=&lt;|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] ...)</code></pre>
<p>The above SQL statement will list the number of tables in a STable, which satisfy the filter condition.</p> <p>The above SQL statement will list the number of tables in a STable, which satisfy the filter condition.</p>
<a class='anchor' id='Management-of-Tags'></a><h2>Management of Tags</h2> <a class='anchor' id='Management-of-Tags'></a><h2>Management of Tags</h2>
<p>You can add, delete and change the tags for a STable, and you can change the tag value of a table. The SQL commands are listed below. </p> <p>You can add, delete and change the tags for a STable, and you can change the tag value of a table. The SQL commands are listed below. </p>

View File

@ -8,7 +8,7 @@ C/C++ APIs are similar to the MySQL APIs. Applications should include TDengine h
```C ```C
#include <taos.h> #include <taos.h>
``` ```
Make sure TDengine library _libtaos.so_ is installed and use _-ltaos_ option to link the library when compiling. The return values of all APIs are _-1_ or _NULL_ for failure. Make sure TDengine library _libtaos.so_ is installed and use _-ltaos_ option to link the library when compiling. In most cases, if the return value of an API is integer, it return _0_ for success and other values as an error code for failure; if the return value is pointer, then _NULL_ is used for failure.
### C/C++ sync API ### C/C++ sync API
@ -78,6 +78,51 @@ The 12 APIs are the most important APIs frequently used. Users can check _taos.h
**Note**: The connection to a TDengine server is not multi-thread safe. So a connection can only be used by one thread. **Note**: The connection to a TDengine server is not multi-thread safe. So a connection can only be used by one thread.
### C/C++ parameter binding API
TDengine also provides parameter binding APIs, like MySQL, only question mark `?` can be used to represent a parameter in these APIs.
- `TAOS_STMT* taos_stmt_init(TAOS *taos)`
Create a TAOS_STMT to represent the prepared statement for other APIs.
- `int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length)`
Parse SQL statement _sql_ and bind result to _stmt_ , if _length_ larger than 0, its value is used to determine the length of _sql_, the API auto detects the actual length of _sql_ otherwise.
- `int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_BIND *bind)`
Bind values to parameters. _bind_ points to an array, the element count and sequence of the array must be identical as the parameters of the SQL statement. The usage of _TAOS_BIND_ is same as _MYSQL_BIND_ in MySQL, its definition is as below:
```c
typedef struct TAOS_BIND {
int buffer_type;
void * buffer;
unsigned long buffer_length; // not used in TDengine
unsigned long *length;
int * is_null;
int is_unsigned; // not used in TDengine
int * error; // not used in TDengine
} TAOS_BIND;
```
- `int taos_stmt_add_batch(TAOS_STMT *stmt)`
Add bound parameters to batch, client can call `taos_stmt_bind_param` again after calling this API. Note this API only support _insert_ / _import_ statements, it returns an error in other cases.
- `int taos_stmt_execute(TAOS_STMT *stmt)`
Execute the prepared statement. This API can only be called once for a statement at present.
- `TAOS_RES* taos_stmt_use_result(TAOS_STMT *stmt)`
Acquire the result set of an executed statement. The usage of the result is same as `taos_use_result`, `taos_free_result` must be called after one you are done with the result set to release resources.
- `int taos_stmt_close(TAOS_STMT *stmt)`
Close the statement, release all resources.
### C/C++ async API ### C/C++ async API
In addition to sync APIs, TDengine also provides async APIs, which are more efficient. Async APIs are returned right away without waiting for a response from the server, allowing the application to continute with other tasks without blocking. So async APIs are more efficient, especially useful when in a poor network. In addition to sync APIs, TDengine also provides async APIs, which are more efficient. Async APIs are returned right away without waiting for a response from the server, allowing the application to continute with other tasks without blocking. So async APIs are more efficient, especially useful when in a poor network.
@ -153,56 +198,104 @@ For the time being, TDengine supports subscription on one table. It is implement
## Java Connector ## Java Connector
### JDBC Interface To Java delevopers, TDengine provides `taos-jdbcdriver` according to the JDBC(3.0) API. Users can find and download it through [Sonatype Repository][1].
TDengine provides a JDBC driver `taos-jdbcdriver-x.x.x.jar` for Enterprise Java developers. TDengine's JDBC Driver is implemented as a subset of the standard JDBC 3.0 Specification and supports the most common Java development frameworks. The driver have been published to dependency repositories such as Sonatype Maven Repository, and users could refer to the following `pom.xml` configuration file. Since the native language of TDengine is C, the necessary TDengine library should be checked before using the taos-jdbcdriver:
* libtaos.so (Linux)
After TDengine is installed successfully, the library `libtaos.so` will be automatically copied to the `/usr/lib/`, which is the system's default search path.
* taos.dll (Windows)
After TDengine client is installed, the library `taos.dll` will be automatically copied to the `C:/Windows/System32`, which is the system's default search path.
> Note: Please make sure that TDengine Windows client has been installed if developing on Windows.
Since TDengine is time-series database, there are still some differences compared with traditional databases in using TDengine JDBC driver:
* TDengine doesn't allow to delete/modify a single record, and thus JDBC driver also has no such method.
* No support for transaction
* No support for union between tables
* No support for nested query`There is at most one open ResultSet for each Connection. Thus, TSDB JDBC Driver will close current ResultSet if it is not closed and a new query begins`.
## Version list of TAOS-JDBCDriver and required TDengine and JDK
| taos-jdbcdriver | TDengine | JDK |
| --- | --- | --- |
| 1.0.3 | 1.6.1.x or higher | 1.8.x |
| 1.0.2 | 1.6.1.x or higher | 1.8.x |
| 1.0.1 | 1.6.1.x or higher | 1.8.x |
## DataType in TDengine and Java
The datatypes in TDengine include timestamp, number, string and boolean, which are converted as follows in Java:
| TDengine | Java |
| --- | --- |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| SMALLINT, TINYINT |java.lang.Short |
| BOOL | java.lang.Boolean |
| BINARY, NCHAR | java.lang.String |
## How to get TAOS-JDBC Driver
### maven repository
taos-jdbcdriver has been published to [Sonatype Repository][1]:
* [sonatype][8]
* [mvnrepository][9]
* [maven.aliyun][10]
Using the following pom.xml for maven projects
```xml ```xml
<repositories>
<repository>
<id>oss-sonatype</id>
<name>oss-sonatype</name>
<url>https://oss.sonatype.org/content/groups/public</url>
</repository>
</repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.taosdata.jdbc</groupId> <groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId> <artifactId>taos-jdbcdriver</artifactId>
<version>1.0.1</version> <version>1.0.3</version>
</dependency> </dependency>
</dependencies> </dependencies>
``` ```
Please note the JDBC driver itself relies on a native library written in C. On a Linux OS, the driver relies on a `libtaos.so` native library, where .so stands for "Shared Object". After the successful installation of TDengine on Linux, `libtaos.so` should be automatically copied to `/usr/local/lib/taos` and added to the system's default search path. On a Windows OS, the driver relies on a `taos.dll` native library, where .dll stands for "Dynamic Link Library". After the successful installation of the TDengine client on Windows, the `taos-jdbcdriver.jar` file can be found in `C:/TDengine/driver/JDBC`; the `taos.dll` file can be found in `C:/TDengine/driver/C` and should have been automatically copied to the system's searching path `C:/Windows/System32`. ### JAR file from the source code
Developers can refer to the Oracle's official JDBC API documentation for detailed usage on classes and methods. However, there are some differences of connection configurations and supported methods in the driver implementation between TDengine and traditional relational databases. After downloading the [TDengine][3] source code, execute `mvn clean package` in the directory `src/connector/jdbc` and then the corresponding jar file is generated.
For database connections, TDengine's JDBC driver has the following configurable parameters in the JDBC URL. The standard format of a TDengine JDBC URL is: ## Usage
`jdbc:TSDB://{host_ip}:{port}/{database_name}?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]` ### get the connection
where `{}` marks the required parameters and `[]` marks the optional. The usage of each parameter is pretty straightforward:
* user - login user name for TDengine; by default, it's `root`
* password - login password; by default, it's `taosdata`
* charset - the client-side charset; by default, it's the operation system's charset
* cfgdir - the directory of TDengine client configuration file; by default it's `/etc/taos` on Linux and `C:\TDengine/cfg` on Windows
* locale - the language environment of TDengine client; by default, it's the operation system's locale
* timezone - the timezone of the TDengine client; by default, it's the operation system's timezone
All parameters can be configured at the time when creating a connection using the java.sql.DriverManager class, for example:
```java ```java
import java.sql.Connection; Class.forName("com.taosdata.jdbc.TSDBDriver");
import java.sql.DriverManager; String jdbcUrl = "jdbc:TAOS://127.0.0.1:6030/log?user=root&password=taosdata";
import java.util.Properties; Connection conn = DriverManager.getConnection(jdbcUrl);
import com.taosdata.jdbc.TSDBDriver; ```
> `6030` is the default port and `log` is the default database for system monitor.
A normal JDBC URL looks as follows:
`jdbc:TSDB://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
values in `{}` are necessary while values in `[]` are optional。Each option in the above URL denotes:
* useruser name for login, defaultly root。
* passwordpassword for logindefaultly taosdata。
* charsetcharset for clientdefaultly system charset
* cfgdirlog directory for client, defaultly _/etc/taos/_ on Linux and _C:/TDengine/cfg_ on Windows。
* localelanguage for clientdefaultly system locale。
* timezonetimezone for clientdefaultly system timezone。
The options above can be configures (`ordered by priority`):
1. JDBC URL
As explained above.
2. java.sql.DriverManager.getConnection(String jdbcUrl, Properties connProps)
```java
public Connection getConn() throws Exception{ public Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver"); Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://127.0.0.1:0/db?user=root&password=taosdata"; String jdbcUrl = "jdbc:TAOS://127.0.0.1:0/log?user=root&password=taosdata";
Properties connProps = new Properties(); Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
@ -215,42 +308,294 @@ public Connection getConn() throws Exception{
} }
``` ```
Except `cfgdir`, all the parameters listed above can also be configured in the configuration file. The properties specified when calling DriverManager.getConnection() has the highest priority among all configuration methods. The JDBC URL has the second-highest priority, and the configuration file has the lowest priority. The explicitly configured parameters in a method with higher priorities always overwrite that same parameter configured in methods with lower priorities. For example, if `charset` is explicitly configured as "UTF-8" in the JDBC URL and "GKB" in the `taos.cfg` file, then "UTF-8" will be used. 3. Configuration file (taos.cfg)
Although the JDBC driver is implemented following the JDBC standard as much as possible, there are major differences between TDengine and traditional databases in terms of data models that lead to the differences in the driver implementation. Here is a list of head-ups for developers who have plenty of experience on traditional databases but little on TDengine: Default configuration file is _/var/lib/taos/taos.cfg_ On Linux and _C:\TDengine\cfg\taos.cfg_ on Windows
```properties
# client default username
# defaultUser root
* TDengine does NOT support updating or deleting a specific record, which leads to some unsupported methods in the JDBC driver # client default password
* TDengine currently does not support `join` or `union` operations, and thus, is lack of support for associated methods in the JDBC driver # defaultPass taosdata
* TDengine supports batch insertions which are controlled at the level of SQL statement writing instead of API calls
* TDengine doesn't support nested queries and neither does the JDBC driver. Thus for each established connection to TDengine, there should be only one open result set associated with it # default system charset
# charset UTF-8
# system locale
# locale en_US.UTF-8
```
> More options can refer to [client configuration][13]
### Create databases and tables
```java
Statement stmt = conn.createStatement();
// create database
stmt.executeUpdate("create database if not exists db");
// use database
stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
```
> Note: if no step like `use db`, the name of database must be added as prefix like _db.tb_ when operating on tables
### Insert data
```java
// insert data
int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now + 1s, 20, 9.3)");
System.out.println("insert " + affectedRows + " rows.");
```
> _now_ is the server time.
> _now+1s_ is 1 second later than current server time. The time unit includes: _a_(millisecond), _s_(second), _m_(minute), _h_(hour), _d_(day), _w_(week), _n_(month), _y_(year).
### Query database
```java
// query data
ResultSet resultSet = stmt.executeQuery("select * from tb");
Timestamp ts = null;
int temperature = 0;
float humidity = 0;
while(resultSet.next()){
ts = resultSet.getTimestamp(1);
temperature = resultSet.getInt(2);
humidity = resultSet.getFloat("humidity");
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
```
> query is consistent with relational database. The subscript start with 1 when retrieving return results. It is recommended to use the column name to retrieve results.
### Close all
```java
resultSet.close();
stmt.close();
conn.close();
```
> `please make sure the connection is closed to avoid the error like connection leakage`
## Using connection pool
**HikariCP**
* dependence in pom.xml
```xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.1</version>
</dependency>
```
* Examples
```java
public static void main(String[] args) throws SQLException {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:TAOS://127.0.0.1:6030/log");
config.setUsername("root");
config.setPassword("taosdata");
config.setMinimumIdle(3); //minimum number of idle connection
config.setMaximumPoolSize(10); //maximum number of connection in the pool
config.setConnectionTimeout(10000); //maximum wait milliseconds for get connection from pool
config.setIdleTimeout(60000); // max idle time for recycle idle connection
config.setConnectionTestQuery("describe log.dn"); //validation query
config.setValidationTimeout(3000); //validation query timeout
HikariDataSource ds = new HikariDataSource(config); //create datasource
Connection connection = ds.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to conneciton pool
}
```
> The close() method will not close the connection from HikariDataSource.getConnection(). Instead, the connection is put back to the connection pool.
> More instructions can refer to [User Guide][5]
**Druid**
* dependency in pom.xml
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
```
* Examples
```java
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("driverClassName","com.taosdata.jdbc.TSDBDriver");
properties.put("url","jdbc:TAOS://127.0.0.1:6030/log");
properties.put("username","root");
properties.put("password","taosdata");
properties.put("maxActive","10"); //maximum number of connection in the pool
properties.put("initialSize","3");//initial number of connection
properties.put("maxWait","10000");//maximum wait milliseconds for get connection from pool
properties.put("minIdle","3");//minimum number of connection in the pool
properties.put("timeBetweenEvictionRunsMillis","3000");// the interval milliseconds to test connection
properties.put("minEvictableIdleTimeMillis","60000");//the minimum milliseconds to keep idle
properties.put("maxEvictableIdleTimeMillis","90000");//the maximum milliseconds to keep idle
properties.put("validationQuery","describe log.dn"); //validation query
properties.put("testWhileIdle","true"); // test connection while idle
properties.put("testOnBorrow","false"); // don't need while testWhileIdle is true
properties.put("testOnReturn","false"); // don't need while testWhileIdle is true
//create druid datasource
DataSource ds = DruidDataSourceFactory.createDataSource(properties);
Connection connection = ds.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to conneciton pool
}
```
> More instructions can refer to [User Guide][6]
**Notice**
* TDengine `v1.6.4.1` provides a function `select server_status()` to check heartbeat. It is highly recommended to use this function for `Validation Query`.
As follows`1` will be returned if `select server_status()` is successfully executed。
```shell
taos> select server_status();
server_status()|
================
1 |
Query OK, 1 row(s) in set (0.000141s)
```
## Integrated with framework
* Please refer to [SpringJdbcTemplate][11] if using taos-jdbcdriver in Spring JdbcTemplate
* Please refer to [springbootdemo][12] if using taos-jdbcdriver in Spring JdbcTemplate
## FAQ
* java.lang.UnsatisfiedLinkError: no taos in java.library.path
**Cause**The application program cannot find Library function _taos_
**Answer**Copy `C:\TDengine\driver\taos.dll` to `C:\Windows\System32\` on Windows and make a soft link through ` ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` on Linux.
* java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
**Cause**Currently TDengine only support 64bit JDK
**Answer**re-install 64bit JDK.
* For other questions, please refer to [Issues][7]
All the error codes and error messages can be found in `TSDBError.java` . For a more detailed coding example, please refer to the demo project `JDBCDemo` in TDengine's code examples.
## Python Connector ## Python Connector
### Install TDengine Python client ### Pre-requirement
* TDengine installed, TDengine-client installed if on Windows [(Windows TDengine client installation)](https://www.taosdata.com/cn/documentation/connector/#Windows客户端及程序接口)
* python 2.7 or >= 3.4
* pip installed
Users can find python client packages in our source code directory _src/connector/python_. There are two directories corresponding two python versions. Please choose the correct package to install. Users can use _pip_ command to install: ### Installation
#### Linux
Users can find python client packages in our source code directory _src/connector/python_. There are two directories corresponding to two python versions. Please choose the correct package to install. Users can use _pip_ command to install:
```cmd ```cmd
pip install src/connector/python/[linux|Windows]/python2/ pip install src/connector/python/linux/python3/
``` ```
or or
``` ```
pip install src/connector/python/[linux|Windows]/python3/ pip install src/connector/python/linux/python2/
``` ```
#### Windows
Assumed the Windows TDengine client has been installed , copy the file "C:\TDengine\driver\taos.dll" to the folder "C:\windows\system32", and then enter the _cmd_ Windows command interface
```
cd C:\TDengine\connector\python\windows
pip install python3\
```
or
```
cd C:\TDengine\connector\python\windows
pip install python2\
```
*If _pip_ command is not installed on the system, users can choose to install pip or just copy the _taos_ directory in the python client directory to the application directory to use.
If _pip_ command is not installed on the system, users can choose to install pip or just copy the _taos_ directory in the python client directory to the application directory to use. ### Usage
#### Examples
### Python client interfaces * import TDengine module
To use TDengine Python client, import TDengine module at first:
```python ```python
import taos import taos
``` ```
* get the connection
```python
conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/etc/taos")
c1 = conn.cursor()
```
*<em>host</em> is the IP of TDengine server, and <em>config</em> is the directory where exists the TDengine client configure file
* insert records into the database
```python
import datetime
# create a database
c1.execute('create database db')
c1.execute('use db')
# create a table
c1.execute('create table tb (ts timestamp, temperature int, humidity float)')
# insert a record
start_time = datetime.datetime(2019, 11, 1)
affected_rows = c1.execute('insert into tb values (\'%s\', 0, 0.0)' %start_time)
# insert multiple records in a batch
time_interval = datetime.timedelta(seconds=60)
sqlcmd = ['insert into tb values']
for irow in range(1,11):
start_time += time_interval
sqlcmd.append('(\'%s\', %d, %f)' %(start_time, irow, irow*1.2))
affected_rows = c1.execute(' '.join(sqlcmd))
```
* query the database
```python
c1.execute('select * from tb')
# fetch all returned results
data = c1.fetchall()
# data is a list of returned rows with each row being a tuple
numOfRows = c1.rowcount
numOfCols = len(c1.description)
for irow in range(numOfRows):
print("Row%d: ts=%s, temperature=%d, humidity=%f" %(irow, data[irow][0], data[irow][1],data[irow][2])
# use the cursor as an iterator to retrieve all returned results
c1.execute('select * from tb')
for data in c1:
print("ts=%s, temperature=%d, humidity=%f" %(data[0], data[1],data[2])
```
* close the connection
```python
c1.close()
conn.close()
```
#### Help information
Users can get module information from Python help interface or refer to our [python code example](). We list the main classes and methods below: Users can get module information from Python help interface or refer to our [python code example](). We list the main classes and methods below:
@ -524,3 +869,17 @@ An example of using the NodeJS connector to create a table with weather data and
An example of using the NodeJS connector to achieve the same things but without all the object wrappers that wrap around the data returned to achieve higher functionality can be found [here](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js) An example of using the NodeJS connector to achieve the same things but without all the object wrappers that wrap around the data returned to achieve higher functionality can be found [here](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js)
[1]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[2]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[3]: https://github.com/taosdata/TDengine
[4]: https://www.taosdata.com/blog/2019/12/03/jdbcdriver%e6%89%be%e4%b8%8d%e5%88%b0%e5%8a%a8%e6%80%81%e9%93%be%e6%8e%a5%e5%ba%93/
[5]: https://github.com/brettwooldridge/HikariCP
[6]: https://github.com/alibaba/druid
[7]: https://github.com/taosdata/TDengine/issues
[8]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[9]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[10]: https://maven.aliyun.com/mvn/search
[11]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate
[12]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo
[13]: https://www.taosdata.com/cn/documentation/administrator/#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE

View File

@ -54,7 +54,7 @@ STable从属于库一个STable只属于一个库但一个库可以有一
说明: 说明:
1. TAGS列总长度不能超过512 bytes 1. TAGS列总长度不能超过512 bytes
2. TAGS列的数据类型不能是timestamp和nchar类型 2. TAGS列的数据类型不能是timestamp
3. TAGS列名不能与其他列名相同; 3. TAGS列名不能与其他列名相同;
4. TAGS列名不能为预留关键字. 4. TAGS列名不能为预留关键字.
@ -169,7 +169,7 @@ SELECT function<field_name>,…
以温度传感器采集时序数据作为例示范STable的使用。 在这个例子中对每个温度计都会建立一张表表名为温度计的ID温度计读数的时刻记为ts采集的值记为degree。通过tags给每个采集器打上不同的标签其中记录温度计的地区和类型以方便我们后面的查询。所有温度计的采集量都一样因此我们用STable来定义表结构。 以温度传感器采集时序数据作为例示范STable的使用。 在这个例子中对每个温度计都会建立一张表表名为温度计的ID温度计读数的时刻记为ts采集的值记为degree。通过tags给每个采集器打上不同的标签其中记录温度计的地区和类型以方便我们后面的查询。所有温度计的采集量都一样因此我们用STable来定义表结构。
###定义STable表结构并使用它创建子表 ###1:定义STable表结构并使用它创建子表
创建STable语句如下 创建STable语句如下
@ -189,7 +189,7 @@ CREATE TABLE therm4 USING thermometer TAGS ('shanghai', 3);
其中therm1therm2therm3therm4是超级表thermometer四个具体的子表也即普通的Table。以therm1为例它表示采集器therm1的数据表结构完全由thermometer定义标签location=”beijing”, type=1表示therm1的地区是北京类型是第1类的温度计。 其中therm1therm2therm3therm4是超级表thermometer四个具体的子表也即普通的Table。以therm1为例它表示采集器therm1的数据表结构完全由thermometer定义标签location=”beijing”, type=1表示therm1的地区是北京类型是第1类的温度计。
###写入数据 ###2:写入数据
注意写入数据时不能直接对STable操作而是要对每张子表进行操作。我们分别向四张表therm1therm2 therm3 therm4写入一条数据写入语句如下 注意写入数据时不能直接对STable操作而是要对每张子表进行操作。我们分别向四张表therm1therm2 therm3 therm4写入一条数据写入语句如下
@ -200,7 +200,7 @@ INSERT INTO therm3 VALUES ('2018-01-01 00:00:00.000', 24);
INSERT INTO therm4 VALUES ('2018-01-01 00:00:00.000', 23); INSERT INTO therm4 VALUES ('2018-01-01 00:00:00.000', 23);
``` ```
### 按标签聚合查询 ###3:按标签聚合查询
查询位于北京(beijing)和天津(tianjing)两个地区的温度传感器采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)、最低温度min(degree),并将结果按所处地域(location)和传感器类型(type)进行聚合。 查询位于北京(beijing)和天津(tianjing)两个地区的温度传感器采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)、最低温度min(degree),并将结果按所处地域(location)和传感器类型(type)进行聚合。
@ -211,14 +211,14 @@ WHERE location='beijing' or location='tianjin'
GROUP BY location, type GROUP BY location, type
``` ```
### 按时间周期聚合查询 ###4:按时间周期聚合查询
查询仅位于北京以外地区的温度传感器最近24小时(24h)采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)和最低温度min(degree)将采集结果按照10分钟为周期进行聚合并将结果按所处地域(location)和传感器类型(type)再次进行聚合。 查询仅位于北京以外地区的温度传感器最近24小时(24h)采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)和最低温度min(degree)将采集结果按照10分钟为周期进行聚合并将结果按所处地域(location)和传感器类型(type)再次进行聚合。
```mysql ```mysql
SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree) SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree)
FROM thermometer FROM thermometer
WHERE name<>'beijing' and ts>=now-1d WHERE location<>'beijing' and ts>=now-1d
INTERVAL(10M) INTERVAL(10M)
GROUP BY location, type GROUP BY location, type
``` ```

View File

@ -23,7 +23,7 @@ New keyword "tags" is introduced, where tag_name is the tag name, and tag_type i
Note Note
1. The bytes of all tags together shall be less than 512 1. The bytes of all tags together shall be less than 512
2. Tag's data type can not be time stamp or nchar 2. Tag's data type can not be time stamp
3. Tag name shall be different from the field name 3. Tag name shall be different from the field name
4. Tag name shall not be the same as system keywords 4. Tag name shall not be the same as system keywords
5. Maximum number of tags is 6 5. Maximum number of tags is 6
@ -102,7 +102,7 @@ List the number of records, average, maximum, and minimum temperature every 10 m
```mysql ```mysql
SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree) SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree)
FROM thermometer FROM thermometer
WHERE name='beijing' and type=10 and ts>=now-1d WHERE location='beijing' and type=10 and ts>=now-1d
INTERVAL(10M) INTERVAL(10M)
``` ```

View File

@ -18,6 +18,7 @@ TDengine提供类似SQL语法用户可以在TDengine Shell中使用SQL语句
- 插入记录时如果时间戳为0插入数据时使用服务器当前时间 - 插入记录时如果时间戳为0插入数据时使用服务器当前时间
- Epoch Time: 时间戳也可以是一个长整数表示从1970-01-01 08:00:00.000开始的毫秒数 - Epoch Time: 时间戳也可以是一个长整数表示从1970-01-01 08:00:00.000开始的毫秒数
- 时间可以加减,比如 now-2h表明查询时刻向前推2个小时(最近2小时)。数字后面的时间单位a(毫秒), s(秒), m(分), h(小时), d(天)w(周), n(月), y(年)。比如select * from t1 where ts > now-2w and ts <= now-1w, 表示查询两周前整整一周的数据 - 时间可以加减,比如 now-2h表明查询时刻向前推2个小时(最近2小时)。数字后面的时间单位a(毫秒), s(秒), m(分), h(小时), d(天)w(周), n(月), y(年)。比如select * from t1 where ts > now-2w and ts <= now-1w, 表示查询两周前整整一周的数据
- TDengine暂不支持时间窗口按照自然年和自然月切分。Where条件中的时间窗口单位的换算关系如下interval(1y) 等效于 interval(365d), interval(1n) 等效于 interval(30d), interval(1w) 等效于 interval(7d)
TDengine缺省的时间戳是毫秒精度但通过修改配置参数enableMicrosecond就可支持微秒。 TDengine缺省的时间戳是毫秒精度但通过修改配置参数enableMicrosecond就可支持微秒。
@ -424,9 +425,9 @@ SELECT function_list FROM tb_name
SELECT function_list FROM stb_name SELECT function_list FROM stb_name
[WHERE where_condition] [WHERE where_condition]
[GROUP BY tags]
INTERVAL (interval) INTERVAL (interval)
[FILL ({ VALUE | PREV | NULL | LINEAR})] [FILL ({ VALUE | PREV | NULL | LINEAR})]
[GROUP BY tags]
``` ```
- 聚合时间段的长度由关键词INTERVAL指定最短时间间隔10毫秒10a。聚合查询中能够同时执行的聚合和选择函数仅限于单个输出的函数count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last不能使用具有多行输出结果的函数例如top、bottom、diff以及四则运算 - 聚合时间段的长度由关键词INTERVAL指定最短时间间隔10毫秒10a。聚合查询中能够同时执行的聚合和选择函数仅限于单个输出的函数count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last不能使用具有多行输出结果的函数例如top、bottom、diff以及四则运算

View File

@ -474,9 +474,9 @@ SELECT function_list FROM tb_name
SELECT function_list FROM stb_name SELECT function_list FROM stb_name
[WHERE where_condition] [WHERE where_condition]
[GROUP BY tags]
INTERVAL (interval) INTERVAL (interval)
[FILL ({ VALUE | PREV | NULL | LINEAR})] [FILL ({ VALUE | PREV | NULL | LINEAR})]
[GROUP BY tags]
``` ```
The downsampling time window is defined by `interval`, which is at least 10 milliseconds. The query returns a new series of downsampled data that has a series of fixed timestamps with an increment of `interval`. The downsampling time window is defined by `interval`, which is at least 10 milliseconds. The query returns a new series of downsampled data that has a series of fixed timestamps with an increment of `interval`.

View File

@ -2,15 +2,15 @@
## 文件目录结构 ## 文件目录结构
安装TDengine后,默认会在操作系统中生成下列目录或文件: 安装TDengine的过程中,安装程序将在操作系统中创建以下目录或文件:
| 目录/文件 | 说明 | | 目录/文件 | 说明 |
| ---------------------- | :------------------------------------------------| | ---------------------- | :------------------------------------------------|
| /etc/taos/taos.cfg | TDengine默认[配置文件] | | /etc/taos/taos.cfg | 默认[配置文件] |
| /usr/local/taos/driver | TDengine动态链接库目录 | | /usr/local/taos/driver | 动态链接库目录 |
| /var/lib/taos | TDengine默认数据文件目录,可通过[配置文件]修改位置. | | /var/lib/taos | 默认数据文件目录,可通过[配置文件]修改位置. |
| /var/log/taos | TDengine默认日志文件目录,可通过[配置文件]修改位置 | | /var/log/taos | 默认日志文件目录,可通过[配置文件]修改位置 |
| /usr/local/taos/bin | TDengine可执行文件目录 | | /usr/local/taos/bin | 可执行文件目录 |
### 可执行文件 ### 可执行文件
@ -19,33 +19,89 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
- _taosd_TDengine服务端可执行文件 - _taosd_TDengine服务端可执行文件
- _taos_ TDengine Shell可执行文件 - _taos_ TDengine Shell可执行文件
- _taosdump_:数据导出工具 - _taosdump_:数据导出工具
- *rmtaos* 一个卸载TDengine的脚本, 请谨慎执行 - *rmtaos* 卸载TDengine的脚本, 该脚本会删除全部的程序和数据文件。务必谨慎执行,如非必须不建议使用。
您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录 您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录
## 服务端配置 ## 服务端配置
TDengine系统后台服务由taosd提供可以在配置文件taos.cfg里修改配置参数以满足不同场景的需求。配置文件的缺省位置在/etc/taos目录可以通过taosd命令行执行参数-c指定配置文件目录。比如taosd -c /home/user来指定配置文件位于/home/user这个目录。 TDengine系统后台服务程序是`taosd`,其启动时候读取的配置文件缺省目录是`/etc/taos`。可以通过命令行执行参数-c指定配置文件目录比如
```
taosd -c /home/user
```
指定`taosd`启动的时候读取`/home/user`目录下的配置文件taos.cfg。
下面仅仅列出一些重要的配置参数,更多的参数请看配置文件里的说明。各个参数的详细介绍及作用请看前述章节。**注意:配置修改后,需要重启*taosd*服务才能生效。** 下面仅仅列出一些重要的配置参数,更多的参数请看配置文件里的说明。各个参数的详细介绍及作用请看前述章节。**注意:配置修改后,需要重启*taosd*服务才能生效。**
- internalIp: 对外提供服务的IP地址默认取第一个IP地址 **internalIp**
- mgmtShellPort管理节点与客户端通信使用的TCP/UDP端口号默认值是6030。此端口号在内向后连续的5个端口都会被UDP通信占用即UDP占用[6030-6034]同时TCP通信也会使用端口[6030]。 - 默认值操作配置的IP地址列表中的第一个IP地址
- vnodeShellPort数据节点与客户端通信使用的TCP/UDP端口号默认值是6035。此端口号在内向后连续的5个端口都会被UDP通信占用即UDP占用[6035-6039]同时TCP通信也会使用端口[6035]
- httpPort数据节点对外提供RESTful服务使用TCP端口号[6020] 对外提供服务的IP地址。
- dataDir: 数据文件目录,缺省是/var/lib/taos
- maxUsers用户的最大数量 **mgmtShellPort**
- maxDbs数据库的最大数量 - 默认值: _6030_
- maxTables数据表的最大数量
- enableMonitor: 系统监测标志位0关闭1打开 数据库服务中管理节点与客户端通信使用的TCP/UDP端口号。
- logDir: 日志文件目录,缺省是/var/log/taos > 端口范围 _6030_ - _6034_ 均用于UDP通讯。此外还使用端口 _6030_ 用于TCP通讯。
- numOfLogLines日志文件的最大行数
- debugFlag: 系统debug日志开关131仅错误和报警信息135所有 **vnodeShellPort**
- 默认值: _6035_
数据节点与客户端通信使用的TCP/UDP端口号。
> 端口范围 _6035_ - _6039_ 的5个端口用于UDP通信。此外还使用端口 _6035_ 用于TCP通讯。
**httpPort**
- 默认值: _6020_
RESTful服务使用的端口号所有的HTTP请求TCP都需要向该接口发起查询/写入请求。
**dataDir**
- 默认值:/var/lib/taos
数据文件目录,所有的数据文件都将写入该目录。
**logDir**
- 默认值:/var/log/taos
日志文件目录,客户端和服务器的运行日志将写入该目录。
**maxUsers**
- 默认值10,000
系统允许创建用户数量的上限
**maxDbs**
- 默认值1,000
系统允许的创建数据库的上限
**maxTables**
- 默认值650,000
系统允许创建数据表的上限。
>系统能够创建的表受到多种因素的限制,单纯地增大该参数并不能直接增加系统能够创建的表数量。例如,由于每个表创建均需要消耗一定量的缓存空间,系统可用内存一定的情况下,创建表的总数的上限是一个固定的值。
**monitor**
- 默认值1激活状态
服务器内部的系统监控开关。监控主要负责收集物理节点的负载状况包括CPU、内存、硬盘、网络带宽、HTTP请求量的监控记录记录信息存储在`LOG`库中。0表示关闭监控服务1表示激活监控服务。
**numOfLogLines**
- 默认值10,000,000
单个日志文件允许的最大行数10,000,000行
**debugFlag**
- 默认值131仅输出错误和警告信息
系统(服务端和客户端)运行日志开关:
- 131 仅输出错误和警告信息
- 135 输入错误ERROR、警告WARN、信息Info
不同应用场景的数据往往具有不同的数据特征比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率TDengine提供如下存储相关的系统配置参数 不同应用场景的数据往往具有不同的数据特征比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率TDengine提供如下存储相关的系统配置参数
- days一个数据文件覆盖的时间长度单位为天 - days数据文件存储数据的时间跨度,单位为天
- keep数据库中数据保留的天数 - keep数据保留的天数
- rows: 文件块中记录条数 - rows: 文件块中记录条数
- comp: 文件压缩标志位0关闭1:一阶段压缩2:两阶段压缩 - comp: 文件压缩标志位0关闭1:一阶段压缩2:两阶段压缩
- ctime数据从写入内存到写入硬盘的最长时间间隔单位为秒 - ctime数据从写入内存到写入硬盘的最长时间间隔单位为秒
@ -66,19 +122,139 @@ TDengine系统后台服务由taosd提供可以在配置文件taos.cfg里修
## 客户端配置 ## 客户端配置
TDengine系统的前台交互客户端应用程序为taos它与taosd共享同一个配置文件taos.cfg。运行taos时使用参数-c指定配置文件目录如taos -c /home/cfg表示使用/home/cfg/目录下的taos.cfg配置文件中的参数缺省目录是/etc/taos。更多taos的使用方法请见[Shell命令行程序](#_TDengine_Shell命令行程序)。本节主要讲解taos客户端应用在配置文件taos.cfg文件中使用到的参数。 TDengine系统的前台交互客户端应用程序为taosWindows平台上为taos.exe。与服务端程序一样也可以通过设置taos.cfg来配置`taos`启动和运行的配置项。启动的时候如果不指定taos加载配置文件路径默认读取`/etc/taos/`路径下的`taos.cfg`文件。指定配置文件来启动`taos`的命令如下:
客户端配置参数列表及解释 ```
taos -c /home/cfg/
```
**注意:启动设置的是配置文件所在目录,而不是配置文件本身**
- masterIP客户端默认发起请求的服务器的IP地址 如果`/home/cfg/`目录下没有配置文件,程序会继续启动并打印如下告警信息:
- charset指明客户端所使用的字符集默认值为UTF-8。TDengine存储nchar类型数据时使用的是unicode存储因此客户端需要告知服务自己所使用的字符集也即客户端所在系统的字符集。 ```plaintext
- locale设置系统语言环境。Linux上客户端与服务端共享 Welcome to the TDengine shell from linux, client version:1.6.4.0
- defaultUser默认登录用户默认值root option file:/home/cfg/taos.cfg not found, all options are set to system default
- defaultPass默认登录密码默认值taosdata ```
更多taos的使用方法请见[Shell命令行程序](#_TDengine_Shell命令行程序)。本节主要讲解taos客户端应用在配置文件taos.cfg文件中使用到的参数。
TCP/UDP端口以及日志的配置参数与server的配置参数完全一样。 客户端配置参数说明
启动taos时你也可以从命令行指定IP地址、端口号用户名和密码否则就从taos.cfg读取。 **masterIP**
- 默认值127.0.0.1
客户端连接的TDengine服务器IP地址如果不设置默认连接127.0.0.1的节点。以下两个命令等效:
```
taos
taos -h 127.0.0.1
```
其中的IP地址是从配置文件中读取的masterIP的值。
**locale**
- 默认值系统中动态获取如果自动获取失败需要用户在配置文件设置或通过API设置
TDengine为存储中文、日文、韩文等非ASCII编码的宽字符提供一种专门的字段类型`nchar`。写入`nchar`字段的数据将统一采用`UCS4-LE`格式进行编码并发送到服务器。需要注意的是,**编码正确性**是客户端来保证。因此,如果用户想要正常使用`nchar`字段来存储诸如中文、日文、韩文等非ASCII字符需要正确设置客户端的编码格式。
客户端的输入的字符均采用操作系统当前默认的编码格式在Linux系统上多为`UTF-8`,部分中文系统编码则可能是`GB18030`或`GBK`等。在docker环境中默认的编码是`POSIX`。在中文版Windows系统中编码则是`CP936`。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证`nchar`中的数据正确转换为`UCS4-LE`编码格式。
在 Linux 中 locale 的命名规则为:
`<语言>_<地区>.<字符集编码>`
如:`zh_CN.UTF-8`zh代表中文CN代表大陆地区UTF-8表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux系统与Mac OSX系统可以通过设置locale来确定系统的字符编码由于Windows使用的locale中不是POSIX标准的locale格式因此在Windows下需要采用另一个配置参数`charset`来指定字符编码。在Linux系统中也可以使用charset来指定字符编码。
**charset**
- 默认值系统中动态获取如果自动获取失败需要用户在配置文件设置或通过API设置
如果配置文件中不设置`charset`在Linux系统中taos在启动时候自动读取系统当前的locale信息并从locale信息中解析提取charset编码格式。如果自动读取locale信息失败则尝试读取charset配置如果读取charset配置也失败**则中断启动过程**。
在Linux系统中locale信息包含了字符编码信息因此正确设置了Linux系统locale以后可以不用再单独设置charset。例如
```
locale zh_CN.UTF-8
```
在Windows系统中无法从locale获取系统当前编码。如果无法从配置文件中读取字符串编码信息`taos`默认设置为字符编码为`CP936`。其等效在配置文件中添加如下配置:
```
charset CP936
```
如果需要调整字符编码,请查阅当前操作系统使用的编码,并在配置文件中正确设置。
在Linux系统中如果用户同时设置了locale和字符集编码charset并且locale和charset的不一致后设置的值将覆盖前面设置的值。
```
locale zh_CN.UTF-8
charset GBK
```
则`charset`的有效值是`GBK`。
```
charset GBK
locale zh_CN.UTF-8
```
`charset`的有效值是`UTF-8`。
**sockettype**
- 默认值UDP
客户端连接服务端的套接字的方式,可以使用`UDP`和`TCP`两种配置。
在客户端和服务端之间的通讯需要经过恶劣的网络环境下如公共网络、互联网、客户端与数据库服务端连接不稳定由于MTU的问题导致UDP丢包的情况下可以将连接的套接字类型调整为`TCP`
>注意:客户端套接字的类型需要和服务端的套接字类型相同,否则无法连接数据库。
**compressMsgSize**
- 默认值:-1不压缩
客户端与服务器之间进行消息通讯过程中,对通讯的消息进行压缩的阈值,默认值为-1不压缩。如果要压缩消息建议设置为64330字节即大于64330字节的消息体才进行压缩。在配置文件中增加如下配置项即可
```
compressMsgSize 64330
```
如果配置项设置为0`compressMsgSize 0`表示对所有的消息均进行压缩。
**timezone**
- 默认值:从系统中动态获取当前的时区设置
客户端运行系统所在的时区。为应对多时区的数据写入和查询问题TDengine采用Unix时间戳([Unix Timestamp](https://en.wikipedia.org/wiki/Unix_time))来记录和存储时间戳。Unix时间戳的特点决定了任一时刻不论在任何时区产生的时间戳均一致。需要注意的是Unix时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的Unix时间戳需要设置正确的时区。
在Linux系统中客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如
```
timezone UTC-8
timezone GMT-8
timezone Asia/Shanghai
```
均是合法的设置东八区时区的格式。
时区的设置对于查询和写入SQL语句中非Unix时间戳的内容时间戳字符串、关键词`now`的解析)产生影响。例如:
```
SELECT count(*) FROM table_name WHERE TS<'2019-04-11 12:01:08';
```
在东八区SQL语句等效于
```
SELECT count(*) FROM table_name WHERE TS<1554955268000;
```
在UTC时区SQL语句等效于
```
SELECT count(*) FROM table_name WHERE TS<1554984068000;
```
为了避免使用字符串时间格式带来的不确定性也可以直接使用Unix时间戳。此外还可以在SQL语句中使用带有时区的时间戳字符串例如RFC3339格式的时间戳字符串`2013-04-12T15:52:01.123+08:00`或者ISO-8601格式时间戳字符串`2013-04-12T15:52:01.123+0800`。上述两个字符串转化为Unix时间戳不受系统所在时区的影响。
**defaultUser**
- 默认值root
登录用户名,客户端登录的时候,如果不指定用户名,则自动使用该用户名登录。默认情况下,以下的两个命令等效
```
taos
taos -u root
```
用户名为从配置中读取的`defaultUser`配置项。如果更改`defaultUser abc`,则以下两个命令等效:
```
taos
taos -u abc
```
**defaultPass**
- 默认值taosdata
登录用户名,客户端登录的时候,如果不指定密码,则自动使用该密码登录。默认情况下,以下的两个命令等效
```
taos
taos -ptaosdata
```
TCP/UDP端口以及日志的配置参数与server的配置参数完全一样。使用命令`taos -?` 可查看`taos`允许的可选项。
## 用户管理 ## 用户管理
@ -191,6 +367,6 @@ KILL STREAM <stream-id>
## 系统监控 ## 系统监控
TDengine启动后会自动创建一个监测数据库SYS并自动将服务器的CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入该数据库。TDengine还将重要的系统操作比如登录、创建、删除数据库等日志以及各种错误报警信息记录下来存放在SYS库里。系统管理员可以从CLI直接查看这个数据库也可以在WEB通过图形化界面查看这些监测信息 TDengine启动后会自动创建一个监测数据库`LOG`并自动将服务器的CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入该数据库。TDengine还将重要的系统操作比如登录、创建、删除数据库等日志以及各种错误报警信息记录下来存放在`LOG`库里。系统管理员可以通过客户端程序查看记录库中的运行负载信息,(在企业版中)还可以通过浏览器查看数据的图标可视化结果
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。 这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项`monitor`将其关闭或打开。

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,12 @@
# The server and client should have the same socket type. Otherwise, connect will fail. # The server and client should have the same socket type. Otherwise, connect will fail.
# sockettype udp # sockettype udp
# The compressed rpc message, option:
# -1 (no compression)
# 0 (all message compressed),
# > 0 (rpc message body which larger than this value will be compressed)
# compressMsgSize -1
# RPC re-try timer, millisecond # RPC re-try timer, millisecond
# rpcTimer 300 # rpcTimer 300
@ -94,6 +100,9 @@
# default system charset # default system charset
# charset UTF-8 # charset UTF-8
# system time zone
# timezone Asia/Shanghai (CST, +0800)
# enable/disable commit log # enable/disable commit log
# clog 1 # clog 1

View File

@ -9,13 +9,13 @@ fi
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
${csudo} systemctl stop taosd || : ${csudo} systemctl stop taosd || :
elif $(which insserv &> /dev/null); then elif $(which service &> /dev/null); then
${csudo} service taosd stop || :
elif $(which update-rc.d &> /dev/null); then
${csudo} service taosd stop || : ${csudo} service taosd stop || :
else else
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
fi fi
echo "Stop taosd service success!" echo "Stop taosd service success!"
sleep 1 sleep 1

View File

@ -35,6 +35,8 @@ else
${csudo} rm -f ${data_link_dir} || : ${csudo} rm -f ${data_link_dir} || :
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
fi fi

View File

@ -7,6 +7,7 @@
compile_dir=$1 compile_dir=$1
output_dir=$2 output_dir=$2
tdengine_ver=$3 tdengine_ver=$3
armver=$4
script_dir="$(dirname $(readlink -f $0))" script_dir="$(dirname $(readlink -f $0))"
top_dir="$(readlink -m ${script_dir}/../..)" top_dir="$(readlink -m ${script_dir}/../..)"
@ -24,8 +25,7 @@ fi
mkdir -p ${pkg_dir} mkdir -p ${pkg_dir}
cd ${pkg_dir} cd ${pkg_dir}
versioninfo=$(${script_dir}/../tools/get_version.sh ${script_dir}/../../src/util/src/version.c) libfile="libtaos.so.${tdengine_ver}"
libfile="libtaos.so.${versioninfo}"
# create install dir # create install dir
install_home_path="/usr/local/taos" install_home_path="/usr/local/taos"
@ -49,6 +49,7 @@ cp ${compile_dir}/build/bin/taosd ${pkg_dir}${install_home_pat
cp ${compile_dir}/build/bin/taos ${pkg_dir}${install_home_path}/bin cp ${compile_dir}/build/bin/taos ${pkg_dir}${install_home_path}/bin
cp ${compile_dir}/build/lib/${libfile} ${pkg_dir}${install_home_path}/driver cp ${compile_dir}/build/lib/${libfile} ${pkg_dir}${install_home_path}/driver
cp ${compile_dir}/../src/inc/taos.h ${pkg_dir}${install_home_path}/include cp ${compile_dir}/../src/inc/taos.h ${pkg_dir}${install_home_path}/include
cp ${compile_dir}/../src/inc/taoserror.h ${pkg_dir}${install_home_path}/include
cp -r ${top_dir}/tests/examples/* ${pkg_dir}${install_home_path}/examples cp -r ${top_dir}/tests/examples/* ${pkg_dir}${install_home_path}/examples
cp -r ${top_dir}/src/connector/grafana ${pkg_dir}${install_home_path}/connector cp -r ${top_dir}/src/connector/grafana ${pkg_dir}${install_home_path}/connector
cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector
@ -63,7 +64,16 @@ debver="Version: "$tdengine_ver
sed -i "2c$debver" ${pkg_dir}/DEBIAN/control sed -i "2c$debver" ${pkg_dir}/DEBIAN/control
#get taos version, then set deb name #get taos version, then set deb name
debname="tdengine-"${tdengine_ver}".deb" if [ -z "$armver" ]; then
debname="TDengine-"${tdengine_ver}".deb"
elif [ "$armver" == "arm64" ]; then
debname="TDengine-"${tdengine_ver}"-arm64.deb"
elif [ "$armver" == "arm32" ]; then
debname="TDengine-"${tdengine_ver}"-arm32.deb"
else
echo "input parameter error!!!"
return
fi
# make deb package # make deb package
dpkg -b ${pkg_dir} $debname dpkg -b ${pkg_dir} $debname

View File

@ -3,7 +3,9 @@
# Generate the deb package for ubunt, or rpm package for centos, or tar.gz package for other linux os # Generate the deb package for ubunt, or rpm package for centos, or tar.gz package for other linux os
set -e set -e
#set -x # set -x
armver=$1
curr_dir=$(pwd) curr_dir=$(pwd)
script_dir="$(dirname $(readlink -f $0))" script_dir="$(dirname $(readlink -f $0))"
@ -107,24 +109,32 @@ build_time=$(date +"%F %R")
echo "char version[64] = \"${version}\";" > ${versioninfo} echo "char version[64] = \"${version}\";" > ${versioninfo}
echo "char compatible_version[64] = \"${compatible_version}\";" >> ${versioninfo} echo "char compatible_version[64] = \"${compatible_version}\";" >> ${versioninfo}
echo "char gitinfo[128] = \"$(git rev-parse --verify HEAD)\";" >> ${versioninfo} echo "char gitinfo[128] = \"$(git rev-parse --verify HEAD)\";" >> ${versioninfo}
echo "char gitinfoOfInternal[128] = \"\";" >> ${versioninfo}
echo "char buildinfo[512] = \"Built by ${USER} at ${build_time}\";" >> ${versioninfo} echo "char buildinfo[512] = \"Built by ${USER} at ${build_time}\";" >> ${versioninfo}
# 2. cmake executable file # 2. cmake executable file
#default use debug mode
compile_mode="debug"
if [[ $1 == "Release" ]] || [[ $1 == "release" ]]; then
compile_mode="Release"
fi
compile_dir="${top_dir}/${compile_mode}" compile_dir="${top_dir}/debug"
if [ -d ${compile_dir} ]; then if [ -d ${compile_dir} ]; then
${csudo} rm -rf ${compile_dir} ${csudo} rm -rf ${compile_dir}
fi fi
${csudo} mkdir -p ${compile_dir} ${csudo} mkdir -p ${compile_dir}
cd ${compile_dir} cd ${compile_dir}
${csudo} cmake -DCMAKE_BUILD_TYPE=${compile_mode} ${top_dir}
${csudo} make # arm only support lite ver
if [ -z "$armver" ]; then
cmake ../
elif [ "$armver" == "arm64" ]; then
cmake ../ -DARMVER=arm64
elif [ "$armver" == "arm32" ]; then
cmake ../ -DARMVER=arm32
else
echo "input parameter error!!!"
return
fi
make
cd ${curr_dir} cd ${curr_dir}
@ -140,7 +150,7 @@ if [ -d ${output_dir} ]; then
fi fi
${csudo} mkdir -p ${output_dir} ${csudo} mkdir -p ${output_dir}
cd ${script_dir}/deb cd ${script_dir}/deb
${csudo} ./makedeb.sh ${compile_dir} ${output_dir} ${version} ${csudo} ./makedeb.sh ${compile_dir} ${output_dir} ${version} ${armver}
echo "do rpm package for the centos system" echo "do rpm package for the centos system"
output_dir="${top_dir}/rpms" output_dir="${top_dir}/rpms"
@ -149,11 +159,12 @@ if [ -d ${output_dir} ]; then
fi fi
${csudo} mkdir -p ${output_dir} ${csudo} mkdir -p ${output_dir}
cd ${script_dir}/rpm cd ${script_dir}/rpm
${csudo} ./makerpm.sh ${compile_dir} ${output_dir} ${version} ${csudo} ./makerpm.sh ${compile_dir} ${output_dir} ${version} ${armver}
echo "do tar.gz package for all systems" echo "do tar.gz package for all systems"
cd ${script_dir}/tools cd ${script_dir}/tools
${csudo} ./makepkg.sh ${compile_dir} ${version} "${build_time}" ${csudo} ./makepkg.sh ${compile_dir} ${version} "${build_time}" ${armver}
${csudo} ./makeclient.sh ${compile_dir} ${version} "${build_time}" ${armver}
# 4. Clean up temporary compile directories # 4. Clean up temporary compile directories
#${csudo} rm -rf ${compile_dir} #${csudo} rm -rf ${compile_dir}

View File

@ -2,10 +2,14 @@
# #
# Generate rpm package for centos # Generate rpm package for centos
#set -e
#set -x
#curr_dir=$(pwd) #curr_dir=$(pwd)
compile_dir=$1 compile_dir=$1
output_dir=$2 output_dir=$2
tdengine_ver=$3 tdengine_ver=$3
armver=$4
script_dir="$(dirname $(readlink -f $0))" script_dir="$(dirname $(readlink -f $0))"
top_dir="$(readlink -m ${script_dir}/../..)" top_dir="$(readlink -m ${script_dir}/../..)"
@ -24,8 +28,25 @@ if command -v sudo > /dev/null; then
csudo="sudo" csudo="sudo"
fi fi
function cp_rpm_package() {
local cur_dir
cd $1
cur_dir=$(pwd)
for dirlist in $(ls ${cur_dir}); do
if test -d ${dirlist}; then
cd ${dirlist}
cp_rpm_package ${cur_dir}/${dirlist}
cd ..
fi
if test -e ${dirlist}; then
cp ${cur_dir}/${dirlist} ${output_dir}/TDengine-${tdengine_ver}.rpm
fi
done
}
if [ -d ${pkg_dir} ]; then if [ -d ${pkg_dir} ]; then
${csudo} rm -rf ${pkg_dir} ${csudo} rm -rf ${pkg_dir}
fi fi
${csudo} mkdir -p ${pkg_dir} ${csudo} mkdir -p ${pkg_dir}
cd ${pkg_dir} cd ${pkg_dir}
@ -35,7 +56,14 @@ ${csudo} mkdir -p BUILD BUILDROOT RPMS SOURCES SPECS SRPMS
${csudo} rpmbuild --define="_version ${tdengine_ver}" --define="_topdir ${pkg_dir}" --define="_compiledir ${compile_dir}" -bb ${spec_file} ${csudo} rpmbuild --define="_version ${tdengine_ver}" --define="_topdir ${pkg_dir}" --define="_compiledir ${compile_dir}" -bb ${spec_file}
# copy rpm package to output_dir, then clean temp dir # copy rpm package to output_dir, then clean temp dir
#echo "rmpbuild end, cur_dir: $(pwd) " #${csudo} cp -rf RPMS/* ${output_dir}
${csudo} cp -rf RPMS/* ${output_dir} cp_rpm_package ${pkg_dir}/RPMS
if [ "$armver" == "arm64" ]; then
mv ${output_dir}/TDengine-${tdengine_ver}.rpm ${output_dir}/TDengine-${tdengine_ver}-arm64.rpm
elif [ "$armver" == "arm32" ]; then
mv ${output_dir}/TDengine-${tdengine_ver}.rpm ${output_dir}/TDengine-${tdengine_ver}-arm32.rpm
fi
cd .. cd ..
${csudo} rm -rf ${pkg_dir} ${csudo} rm -rf ${pkg_dir}

View File

@ -2,7 +2,7 @@
%define cfg_install_dir /etc/taos %define cfg_install_dir /etc/taos
%define __strip /bin/true %define __strip /bin/true
Name: tdengine Name: TDengine
Version: %{_version} Version: %{_version}
Release: 3%{?dist} Release: 3%{?dist}
Summary: tdengine from taosdata Summary: tdengine from taosdata
@ -39,8 +39,7 @@ echo topdir: %{_topdir}
echo version: %{_version} echo version: %{_version}
echo buildroot: %{buildroot} echo buildroot: %{buildroot}
versioninfo=$(%{_compiledir}/../packaging/tools/get_version.sh ../../src/util/src/version.c) libfile="libtaos.so.%{_version}"
libfile="libtaos.so.${versioninfo}"
# create install path, and cp file # create install path, and cp file
mkdir -p %{buildroot}%{homepath}/bin mkdir -p %{buildroot}%{homepath}/bin
@ -62,6 +61,7 @@ cp %{_compiledir}/build/bin/taosdemo %{buildroot}%{homepath}/bin
cp %{_compiledir}/build/bin/taosdump %{buildroot}%{homepath}/bin cp %{_compiledir}/build/bin/taosdump %{buildroot}%{homepath}/bin
cp %{_compiledir}/build/lib/${libfile} %{buildroot}%{homepath}/driver cp %{_compiledir}/build/lib/${libfile} %{buildroot}%{homepath}/driver
cp %{_compiledir}/../src/inc/taos.h %{buildroot}%{homepath}/include cp %{_compiledir}/../src/inc/taos.h %{buildroot}%{homepath}/include
cp %{_compiledir}/../src/inc/taoserror.h %{buildroot}%{homepath}/include
cp -r %{_compiledir}/../src/connector/grafana %{buildroot}%{homepath}/connector cp -r %{_compiledir}/../src/connector/grafana %{buildroot}%{homepath}/connector
cp -r %{_compiledir}/../src/connector/python %{buildroot}%{homepath}/connector cp -r %{_compiledir}/../src/connector/python %{buildroot}%{homepath}/connector
cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector
@ -79,18 +79,17 @@ fi
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
${csudo} systemctl stop taosd || : ${csudo} systemctl stop taosd || :
elif $(which insserv &> /dev/null); then elif $(which service &> /dev/null); then
${csudo} service taosd stop || :
elif $(which update-rc.d &> /dev/null); then
${csudo} service taosd stop || : ${csudo} service taosd stop || :
else else
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
fi fi
echo "Stop taosd service success!" echo "Stop taosd service success!"
sleep 1 sleep 1
fi fi
# if taos.cfg already softlink, remove it # if taos.cfg already softlink, remove it
if [ -f %{cfg_install_dir}/taos.cfg ]; then if [ -f %{cfg_install_dir}/taos.cfg ]; then
${csudo} rm -f %{homepath}/cfg/taos.cfg || : ${csudo} rm -f %{homepath}/cfg/taos.cfg || :
@ -138,13 +137,16 @@ if [ $1 -eq 0 ];then
${csudo} rm -f ${bin_link_dir}/taosdump || : ${csudo} rm -f ${bin_link_dir}/taosdump || :
${csudo} rm -f ${cfg_link_dir}/* || : ${csudo} rm -f ${cfg_link_dir}/* || :
${csudo} rm -f ${inc_link_dir}/taos.h || : ${csudo} rm -f ${inc_link_dir}/taos.h || :
${csudo} rm -f ${inc_link_dir}/taoserror.h || :
${csudo} rm -f ${lib_link_dir}/libtaos.* || : ${csudo} rm -f ${lib_link_dir}/libtaos.* || :
${csudo} rm -f ${log_link_dir} || : ${csudo} rm -f ${log_link_dir} || :
${csudo} rm -f ${data_link_dir} || : ${csudo} rm -f ${data_link_dir} || :
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
fi fi
fi fi

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# This file is used to install TAOS time-series database on linux systems. The operating system # This file is used to install database on linux systems. The operating system
# is required to use systemd to manage services at boot # is required to use systemd to manage services at boot
set -e set -e
@ -41,19 +41,58 @@ if command -v sudo > /dev/null; then
csudo="sudo" csudo="sudo"
fi fi
initd_mod=0
service_mod=2 service_mod=2
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
service_mod=0 service_mod=0
elif $(which update-rc.d &> /dev/null); then elif $(which service &> /dev/null); then
service_mod=1 service_mod=1
service_config_dir="/etc/init.d" service_config_dir="/etc/init.d"
if $(which chkconfig &> /dev/null); then
initd_mod=1
elif $(which insserv &> /dev/null); then
initd_mod=2
elif $(which update-rc.d &> /dev/null); then
initd_mod=3
else
service_mod=2
fi
else else
service_mod=2 service_mod=2
fi fi
# get the operating system type for using the corresponding init file
# ubuntu/debian(deb), centos/fedora(rpm), others: opensuse, redhat, ..., no verification
#osinfo=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
osinfo=$(cat /etc/os-release | grep "NAME" | cut -d '"' -f2)
#echo "osinfo: ${osinfo}"
os_type=0
if echo $osinfo | grep -qwi "ubuntu" ; then
echo "this is ubuntu system"
os_type=1
elif echo $osinfo | grep -qwi "debian" ; then
echo "this is debian system"
os_type=1
elif echo $osinfo | grep -qwi "Kylin" ; then
echo "this is Kylin system"
os_type=1
elif echo $osinfo | grep -qwi "centos" ; then
echo "this is centos system"
os_type=2
elif echo $osinfo | grep -qwi "fedora" ; then
echo "this is fedora system"
os_type=2
else
echo "this is other linux system"
os_type=0
fi
function kill_taosd() { function kill_taosd() {
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 pid || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
} }
function install_main_path() { function install_main_path() {
@ -81,7 +120,7 @@ function install_bin() {
#Make link #Make link
[ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || : [ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || :
[ -x ${install_main_dir}/bin/taosd ] && ${csudo} ln -s ${install_main_dir}/bin/taosd ${bin_link_dir}/taosd || : [ -x ${install_main_dir}/bin/taosd ] && ${csudo} ln -s ${install_main_dir}/bin/taosd ${bin_link_dir}/taosd || :
[ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || : [ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || :
[ -x ${install_main_dir}/bin/taosdemo ] && ${csudo} ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || : [ -x ${install_main_dir}/bin/taosdemo ] && ${csudo} ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || :
[ -x ${install_main_dir}/bin/remove.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/rmtaos || : [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/rmtaos || :
@ -89,7 +128,7 @@ function install_bin() {
function install_lib() { function install_lib() {
# Remove links # Remove links
${csudo} rm -f ${lib_link_dir}/libtaos.* || : ${csudo} rm -f ${lib_link_dir}/libtaos.* || :
${csudo} cp -rf ${script_dir}/driver/* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/* ${csudo} cp -rf ${script_dir}/driver/* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/*
@ -98,24 +137,26 @@ function install_lib() {
} }
function install_header() { function install_header() {
${csudo} rm -f ${inc_link_dir}/taos.h || : ${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || :
${csudo} cp -f ${script_dir}/inc/* ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/* ${csudo} cp -f ${script_dir}/inc/* ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/*
${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h ${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
} }
function install_config() { function install_config() {
#${csudo} rm -f ${install_main_dir}/cfg/taos.cfg || : #${csudo} rm -f ${install_main_dir}/cfg/taos.cfg || :
if [ ! -f ${cfg_install_dir}/taos.cfg ]; then if [ ! -f ${cfg_install_dir}/taos.cfg ]; then
${csudo} mkdir -p ${cfg_install_dir} ${csudo} mkdir -p ${cfg_install_dir}
[ -f ${script_dir}/cfg/taos.cfg ] && ${csudo} cp ${script_dir}/cfg/taos.cfg ${cfg_install_dir} [ -f ${script_dir}/cfg/taos.cfg ] && ${csudo} cp ${script_dir}/cfg/taos.cfg ${cfg_install_dir}
${csudo} chmod 644 ${cfg_install_dir}/* ${csudo} chmod 644 ${cfg_install_dir}/*
fi fi
${csudo} cp -f ${script_dir}/cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org ${csudo} cp -f ${script_dir}/cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org
${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg ${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg
} }
function install_log() { function install_log() {
${csudo} rm -rf ${log_dir} || : ${csudo} rm -rf ${log_dir} || :
${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir} ${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir}
@ -138,14 +179,26 @@ function install_examples() {
} }
function clean_service_on_sysvinit() { function clean_service_on_sysvinit() {
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" #restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
${csudo} service taosd stop || : ${csudo} service taosd stop || :
fi fi
${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
if ((${initd_mod}==1)); then
${csudo} chkconfig --del taosd || :
elif ((${initd_mod}==2)); then
${csudo} insserv -r taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d -f taosd remove || :
fi
${csudo} rm -f ${service_config_dir}/taosd || : ${csudo} rm -f ${service_config_dir}/taosd || :
${csudo} update-rc.d -f taosd remove || :
${csudo} init q || : if $(which init &> /dev/null); then
${csudo} init q || :
fi
} }
function install_service_on_sysvinit() { function install_service_on_sysvinit() {
@ -154,14 +207,27 @@ function install_service_on_sysvinit() {
sleep 1 sleep 1
# Install taosd service # Install taosd service
${csudo} cp -f ${script_dir}/init.d/taosd ${install_main_dir}/init.d
${csudo} cp ${script_dir}/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
${csudo} grep -q -F "$restart_config_str" /etc/inittab || ${csudo} bash -c "echo '${restart_config_str}' >> /etc/inittab" if ((${os_type}==1)); then
# TODO: for centos, change here ${csudo} cp -f ${script_dir}/init.d/taosd.deb ${install_main_dir}/init.d/taosd
${csudo} update-rc.d taosd defaults ${csudo} cp ${script_dir}/init.d/taosd.deb ${service_config_dir}/taosd && ${csudo} chmod a+x ${service_config_dir}/taosd
# chkconfig mysqld on elif ((${os_type}==2)); then
${csudo} cp -f ${script_dir}/init.d/taosd.rpm ${install_main_dir}/init.d/taosd
${csudo} cp ${script_dir}/init.d/taosd.rpm ${service_config_dir}/taosd && ${csudo} chmod a+x ${service_config_dir}/taosd
fi
#restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} grep -q -F "$restart_config_str" /etc/inittab || ${csudo} bash -c "echo '${restart_config_str}' >> /etc/inittab"
if ((${initd_mod}==1)); then
${csudo} chkconfig --add taosd || :
${csudo} chkconfig --level 2345 taosd on || :
elif ((${initd_mod}==2)); then
${csudo} insserv taosd || :
${csudo} insserv -d taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d taosd defaults || :
fi
} }
function clean_service_on_systemd() { function clean_service_on_systemd() {
@ -211,7 +277,7 @@ function install_service() {
elif ((${service_mod}==1)); then elif ((${service_mod}==1)); then
install_service_on_sysvinit install_service_on_sysvinit
else else
# must manual start taosd # must manual stop taosd
kill_taosd kill_taosd
fi fi
} }
@ -247,9 +313,9 @@ vercomp () {
function is_version_compatible() { function is_version_compatible() {
curr_version=$(${bin_dir}/taosd -V | cut -d ' ' -f 1) curr_version=$(${bin_dir}/taosd -V | head -1 | cut -d ' ' -f 3)
min_compatible_version=$(${script_dir}/bin/taosd -V | cut -d ' ' -f 2) min_compatible_version=$(${script_dir}/bin/taosd -V | head -1 | cut -d ' ' -f 5)
vercomp $curr_version $min_compatible_version vercomp $curr_version $min_compatible_version
case $? in case $? in
@ -265,7 +331,7 @@ function update_TDengine() {
echo "File taos.tar.gz does not exist" echo "File taos.tar.gz does not exist"
exit 1 exit 1
fi fi
tar -zxf taos.tar.gz tar -zxf taos.tar.gz
# Check if version compatible # Check if version compatible
if ! is_version_compatible; then if ! is_version_compatible; then
@ -273,7 +339,7 @@ function update_TDengine() {
return 1 return 1
fi fi
echo -e "${GREEN}Start to update TDEngine...${NC}" echo -e "${GREEN}Start to update TDengine...${NC}"
# Stop the service if running # Stop the service if running
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
if ((${service_mod}==0)); then if ((${service_mod}==0)); then
@ -305,8 +371,7 @@ function update_TDengine() {
if ((${service_mod}==0)); then if ((${service_mod}==0)); then
echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} systemctl start taosd${NC}" echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} systemctl start taosd${NC}"
elif ((${service_mod}==1)); then elif ((${service_mod}==1)); then
echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} update-rc.d taosd default ${RED} for the first time${NC}" echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} service taosd start${NC}"
echo -e " : ${csudo} service taosd start ${RED} after${NC}"
else else
echo -e "${GREEN_DARK}To start TDengine ${NC}: ./taosd${NC}" echo -e "${GREEN_DARK}To start TDengine ${NC}: ./taosd${NC}"
fi fi
@ -315,7 +380,7 @@ function update_TDengine() {
echo echo
echo -e "\033[44;32;1mTDengine is updated successfully!${NC}" echo -e "\033[44;32;1mTDengine is updated successfully!${NC}"
else else
install_bin $1 install_bin
install_config install_config
echo echo
@ -331,9 +396,9 @@ function install_TDengine() {
echo "File taos.tar.gz does not exist" echo "File taos.tar.gz does not exist"
exit 1 exit 1
fi fi
tar -zxf taos.tar.gz tar -zxf taos.tar.gz
echo -e "${GREEN}Start to install TDEngine...${NC}" echo -e "${GREEN}Start to install TDengine...${NC}"
install_main_path install_main_path
@ -361,10 +426,9 @@ function install_TDengine() {
if ((${service_mod}==0)); then if ((${service_mod}==0)); then
echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} systemctl start taosd${NC}" echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} systemctl start taosd${NC}"
elif ((${service_mod}==1)); then elif ((${service_mod}==1)); then
echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} update-rc.d taosd default ${RED} for the first time${NC}" echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} service taosd start${NC}"
echo -e " : ${csudo} service taosd start ${RED} after${NC}"
else else
echo -e "${GREEN_DARK}To start TDengine ${NC}: ./taosd${NC}" echo -e "${GREEN_DARK}To start TDengine ${NC}: taosd${NC}"
fi fi
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}" echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"

View File

@ -1,4 +1,201 @@
#!/bin/bash #!/bin/bash
#
# This file is used to install TDengine client on linux systems. The operating system
# is required to use systemd to manage services at boot
set -e
#set -x
# -----------------------Variables definition---------------------
script_dir=$(dirname $(readlink -m "$0")) script_dir=$(dirname $(readlink -m "$0"))
${script_dir}/install.sh client # Dynamic directory
data_dir="/var/lib/taos"
log_dir="/var/log/taos"
log_link_dir="/usr/local/taos/log"
cfg_install_dir="/etc/taos"
bin_link_dir="/usr/bin"
lib_link_dir="/usr/lib"
inc_link_dir="/usr/include"
#install main path
install_main_dir="/usr/local/taos"
# old bin dir
bin_dir="/usr/local/taos/bin"
# Color setting
RED='\033[0;31m'
GREEN='\033[1;32m'
GREEN_DARK='\033[0;32m'
GREEN_UNDERLINE='\033[4;32m'
NC='\033[0m'
csudo=""
if command -v sudo > /dev/null; then
csudo="sudo"
fi
update_flag=0
function kill_client() {
pid=$(ps -ef | grep "taos" | grep -v "grep" | awk '{print $2}')
if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
}
function install_main_path() {
#create install main dir and all sub dir
${csudo} rm -rf ${install_main_dir} || :
${csudo} mkdir -p ${install_main_dir}
${csudo} mkdir -p ${install_main_dir}/cfg
${csudo} mkdir -p ${install_main_dir}/bin
${csudo} mkdir -p ${install_main_dir}/connector
${csudo} mkdir -p ${install_main_dir}/driver
${csudo} mkdir -p ${install_main_dir}/examples
${csudo} mkdir -p ${install_main_dir}/include
}
function install_bin() {
# Remove links
${csudo} rm -f ${bin_link_dir}/taos || :
${csudo} rm -f ${bin_link_dir}/taosdump || :
${csudo} rm -f ${bin_link_dir}/rmtaos || :
${csudo} cp -r ${script_dir}/bin/* ${install_main_dir}/bin && ${csudo} chmod 0555 ${install_main_dir}/bin/*
#Make link
[ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || :
[ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || :
[ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/rmtaos || :
}
function clean_lib() {
sudo rm -f /usr/lib/libtaos.so || :
sudo rm -rf ${lib_dir} || :
}
function install_lib() {
# Remove links
${csudo} rm -f ${lib_link_dir}/libtaos.* || :
${csudo} cp -rf ${script_dir}/driver/* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/*
${csudo} ln -s ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1
${csudo} ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so
}
function install_header() {
${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || :
${csudo} cp -f ${script_dir}/inc/* ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/*
${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
}
function install_config() {
#${csudo} rm -f ${install_main_dir}/cfg/taos.cfg || :
if [ ! -f ${cfg_install_dir}/taos.cfg ]; then
${csudo} mkdir -p ${cfg_install_dir}
[ -f ${script_dir}/cfg/taos.cfg ] && ${csudo} cp ${script_dir}/cfg/taos.cfg ${cfg_install_dir}
${csudo} chmod 644 ${cfg_install_dir}/*
fi
${csudo} cp -f ${script_dir}/cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org
${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg
}
function install_log() {
${csudo} rm -rf ${log_dir} || :
${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir}
${csudo} ln -s ${log_dir} ${install_main_dir}/log
}
function install_connector() {
${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector
}
function install_examples() {
if [ -d ${script_dir}/examples ]; then
${csudo} cp -rf ${script_dir}/examples/* ${install_main_dir}/examples
fi
}
function update_TDengine() {
# Start to update
if [ ! -e taos.tar.gz ]; then
echo "File taos.tar.gz does not exist"
exit 1
fi
tar -zxf taos.tar.gz
echo -e "${GREEN}Start to update TDengine client...${NC}"
# Stop the client shell if running
if pidof taos &> /dev/null; then
kill_client
sleep 1
fi
install_main_path
install_log
install_header
install_lib
install_connector
install_examples
install_bin
install_config
echo
echo -e "\033[44;32;1mTDengine client is updated successfully!${NC}"
rm -rf $(tar -tf taos.tar.gz)
}
function install_TDengine() {
# Start to install
if [ ! -e taos.tar.gz ]; then
echo "File taos.tar.gz does not exist"
exit 1
fi
tar -zxf taos.tar.gz
echo -e "${GREEN}Start to install TDengine client...${NC}"
install_main_path
install_log
install_header
install_lib
install_connector
install_examples
install_bin
install_config
echo
echo -e "\033[44;32;1mTDengine client is installed successfully!${NC}"
rm -rf $(tar -tf taos.tar.gz)
}
## ==============================Main program starts from here============================
# Install or updata client and client
# if server is already install, don't install client
if [ -e ${bin_dir}/taosd ]; then
echo -e "\033[44;32;1mThere are already installed TDengine server, so don't need install client!${NC}"
exit 0
fi
if [ -x ${bin_dir}/taos ]; then
update_flag=1
update_TDengine
else
install_TDengine
fi

View File

@ -47,21 +47,54 @@ initd_mod=0
service_mod=2 service_mod=2
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
service_mod=0 service_mod=0
elif $(which insserv &> /dev/null); then elif $(which service &> /dev/null); then
service_mod=1 service_mod=1
initd_mod=1 service_config_dir="/etc/init.d"
service_config_dir="/etc/init.d" if $(which chkconfig &> /dev/null); then
elif $(which update-rc.d &> /dev/null); then initd_mod=1
service_mod=1 elif $(which insserv &> /dev/null); then
initd_mod=2 initd_mod=2
service_config_dir="/etc/init.d" elif $(which update-rc.d &> /dev/null); then
initd_mod=3
else
service_mod=2
fi
else else
service_mod=2 service_mod=2
fi fi
# get the operating system type for using the corresponding init file
# ubuntu/debian(deb), centos/fedora(rpm), others: opensuse, redhat, ..., no verification
#osinfo=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
osinfo=$(cat /etc/os-release | grep "NAME" | cut -d '"' -f2)
#echo "osinfo: ${osinfo}"
os_type=0
if echo $osinfo | grep -qwi "ubuntu" ; then
echo "this is ubuntu system"
os_type=1
elif echo $osinfo | grep -qwi "debian" ; then
echo "this is debian system"
os_type=1
elif echo $osinfo | grep -qwi "Kylin" ; then
echo "this is Kylin system"
os_type=1
elif echo $osinfo | grep -qwi "centos" ; then
echo "this is centos system"
os_type=2
elif echo $osinfo | grep -qwi "fedora" ; then
echo "this is fedora system"
os_type=2
else
echo "this is other linux system"
os_type=0
fi
function kill_taosd() { function kill_taosd() {
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
} }
function install_main_path() { function install_main_path() {
@ -109,9 +142,10 @@ function install_lib() {
function install_header() { function install_header() {
${csudo} rm -f ${inc_link_dir}/taos.h || : ${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || :
${csudo} cp -f ${source_dir}/src/inc/taos.h ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/* ${csudo} cp -f ${source_dir}/src/inc/taos.h ${source_dir}/src/inc/taoserror.h ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/*
${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h ${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h
${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h
} }
function install_config() { function install_config() {
@ -152,20 +186,26 @@ function install_examples() {
} }
function clean_service_on_sysvinit() { function clean_service_on_sysvinit() {
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" #restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
${csudo} service taosd stop || : ${csudo} service taosd stop || :
fi fi
${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
${csudo} rm -f ${service_config_dir}/taosd || :
if ((${initd_mod}==1)); then if ((${initd_mod}==1)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} insserv -r taosd || : ${csudo} chkconfig --del taosd || :
elif ((${initd_mod}==2)); then elif ((${initd_mod}==2)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} update-rc.d -f taosd remove || : ${csudo} insserv -r taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d -f taosd remove || :
fi
${csudo} rm -f ${service_config_dir}/taosd || :
if $(which init &> /dev/null); then
${csudo} init q || :
fi fi
# ${csudo} update-rc.d -f taosd remove || :
${csudo} init q || :
} }
function install_service_on_sysvinit() { function install_service_on_sysvinit() {
@ -174,19 +214,26 @@ function install_service_on_sysvinit() {
sleep 1 sleep 1
# Install taosd service # Install taosd service
if ((${os_type}==1)); then
${csudo} cp -f ${script_dir}/../deb/init.d/taosd ${install_main_dir}/init.d ${csudo} cp -f ${script_dir}/../deb/init.d/taosd ${install_main_dir}/init.d
${csudo} cp ${script_dir}/../deb/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd ${csudo} cp ${script_dir}/../deb/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" elif ((${os_type}==2)); then
${csudo} cp -f ${script_dir}/../rpm/init.d/taosd ${install_main_dir}/init.d
${csudo} grep -q -F "$restart_config_str" /etc/inittab || ${csudo} bash -c "echo '${restart_config_str}' >> /etc/inittab" ${csudo} cp ${script_dir}/../rpm/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
# TODO: for centos, change here fi
#restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} grep -q -F "$restart_config_str" /etc/inittab || ${csudo} bash -c "echo '${restart_config_str}' >> /etc/inittab"
if ((${initd_mod}==1)); then if ((${initd_mod}==1)); then
${csudo} insserv taosd || : ${csudo} chkconfig --add taosd || :
${csudo} chkconfig --level 2345 taosd on || :
elif ((${initd_mod}==2)); then elif ((${initd_mod}==2)); then
${csudo} insserv taosd || :
${csudo} insserv -d taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d taosd defaults || : ${csudo} update-rc.d taosd defaults || :
fi fi
# ${csudo} update-rc.d taosd defaults
# chkconfig mysqld on
} }
function clean_service_on_systemd() { function clean_service_on_systemd() {
@ -236,7 +283,7 @@ function install_service() {
elif ((${service_mod}==1)); then elif ((${service_mod}==1)); then
install_service_on_sysvinit install_service_on_sysvinit
else else
# must manual start taosd # must manual stop taosd
kill_taosd kill_taosd
fi fi
} }

78
packaging/tools/makeclient.sh Executable file
View File

@ -0,0 +1,78 @@
#!/bin/bash
#
# Generate tar.gz package for linux client
set -e
set -x
curr_dir=$(pwd)
compile_dir=$1
version=$2
build_time=$3
armver=$4
script_dir="$(dirname $(readlink -f $0))"
top_dir="$(readlink -m ${script_dir}/../..)"
# create compressed install file.
build_dir="${compile_dir}/build"
code_dir="${top_dir}/src"
release_dir="${top_dir}/release"
#package_name='linux'
install_dir="${release_dir}/TDengine-client-${version}"
# Directories and files.
bin_files="${build_dir}/bin/taos ${build_dir}/bin/taosdump ${script_dir}/remove_client.sh"
lib_files="${build_dir}/lib/libtaos.so.${version}"
header_files="${code_dir}/inc/taos.h ${code_dir}/inc/taoserror.h"
cfg_dir="${top_dir}/packaging/cfg"
install_files="${script_dir}/install_client.sh"
# make directories.
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
mkdir -p ${install_dir}/bin && cp ${bin_files} ${install_dir}/bin && chmod a+x ${install_dir}/bin/*
cd ${install_dir}
tar -zcv -f taos.tar.gz * --remove-files || :
cd ${curr_dir}
cp ${install_files} ${install_dir} && chmod a+x ${install_dir}/install*
# Copy example code
mkdir -p ${install_dir}/examples
cp -r ${top_dir}/tests/examples/c ${install_dir}/examples
cp -r ${top_dir}/tests/examples/JDBC ${install_dir}/examples
cp -r ${top_dir}/tests/examples/matlab ${install_dir}/examples
cp -r ${top_dir}/tests/examples/python ${install_dir}/examples
cp -r ${top_dir}/tests/examples/R ${install_dir}/examples
cp -r ${top_dir}/tests/examples/go ${install_dir}/examples
# Copy driver
mkdir -p ${install_dir}/driver
cp ${lib_files} ${install_dir}/driver
# Copy connector
connector_dir="${code_dir}/connector"
mkdir -p ${install_dir}/connector
cp ${build_dir}/lib/*.jar ${install_dir}/connector
cp -r ${connector_dir}/grafana ${install_dir}/connector/
cp -r ${connector_dir}/python ${install_dir}/connector/
cp -r ${connector_dir}/go ${install_dir}/connector
# Copy release note
# cp ${script_dir}/release_note ${install_dir}
# exit 1
cd ${release_dir}
if [ -z "$armver" ]; then
tar -zcv -f "$(basename ${install_dir}).tar.gz" $(basename ${install_dir}) --remove-files
elif [ "$armver" == "arm64" ]; then
tar -zcv -f "$(basename ${install_dir})-arm64.tar.gz" $(basename ${install_dir}) --remove-files
elif [ "$armver" == "arm32" ]; then
tar -zcv -f "$(basename ${install_dir})-arm32.tar.gz" $(basename ${install_dir}) --remove-files
fi
cd ${curr_dir}

View File

@ -6,6 +6,7 @@ curr_dir=$(pwd)
compile_dir=$1 compile_dir=$1
version=$2 version=$2
build_time=$3 build_time=$3
armver=$4
script_dir="$(dirname $(readlink -f $0))" script_dir="$(dirname $(readlink -f $0))"
top_dir="$(readlink -m ${script_dir}/../..)" top_dir="$(readlink -m ${script_dir}/../..)"
@ -15,16 +16,15 @@ build_dir="${compile_dir}/build"
code_dir="${top_dir}/src" code_dir="${top_dir}/src"
release_dir="${top_dir}/release" release_dir="${top_dir}/release"
package_name='linux' #package_name='linux'
install_dir="${release_dir}/taos-${version}-${package_name}-$(echo ${build_time}| tr ': ' -)" install_dir="${release_dir}/TDengine-${version}"
# Directories and files. # Directories and files.
bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdemo ${build_dir}/bin/taosdump ${script_dir}/remove.sh" bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdemo ${build_dir}/bin/taosdump ${script_dir}/remove.sh"
versioninfo=$(${script_dir}/get_version.sh ${code_dir}/util/src/version.c) lib_files="${build_dir}/lib/libtaos.so.${version}"
lib_files="${build_dir}/lib/libtaos.so.${versioninfo}" header_files="${code_dir}/inc/taos.h ${code_dir}/inc/taoserror.h"
header_files="${code_dir}/inc/taos.h" cfg_dir="${top_dir}/packaging/cfg"
cfg_files="${top_dir}/packaging/cfg/*.cfg" install_files="${script_dir}/install.sh"
install_files="${script_dir}/install.sh ${script_dir}/install_client.sh"
# Init file # Init file
#init_dir=${script_dir}/deb #init_dir=${script_dir}/deb
@ -33,29 +33,32 @@ install_files="${script_dir}/install.sh ${script_dir}/install_client.sh"
#fi #fi
#init_files=${init_dir}/taosd #init_files=${init_dir}/taosd
# temp use rpm's taosd. TODO: later modify according to os type # temp use rpm's taosd. TODO: later modify according to os type
init_files=${script_dir}/../rpm/taosd init_file_deb=${script_dir}/../deb/taosd
init_file_rpm=${script_dir}/../rpm/taosd
# make directories. # make directories.
mkdir -p ${install_dir} mkdir -p ${install_dir}
mkdir -p ${install_dir}/inc && cp ${header_files} ${install_dir}/inc mkdir -p ${install_dir}/inc && cp ${header_files} ${install_dir}/inc
mkdir -p ${install_dir}/cfg && cp ${cfg_files} ${install_dir}/cfg mkdir -p ${install_dir}/cfg && cp ${cfg_dir}/taos.cfg ${install_dir}/cfg/taos.cfg
mkdir -p ${install_dir}/bin && cp ${bin_files} ${install_dir}/bin && chmod a+x ${install_dir}/bin/* mkdir -p ${install_dir}/bin && cp ${bin_files} ${install_dir}/bin && chmod a+x ${install_dir}/bin/*
mkdir -p ${install_dir}/init.d && cp ${init_files} ${install_dir}/init.d mkdir -p ${install_dir}/init.d && cp ${init_file_deb} ${install_dir}/init.d/taosd.deb
mkdir -p ${install_dir}/init.d && cp ${init_file_rpm} ${install_dir}/init.d/taosd.rpm
cd ${install_dir} cd ${install_dir}
tar -zcv -f taos.tar.gz * --remove-files || : tar -zcv -f taos.tar.gz * --remove-files || :
cd ${curr_dir} cd ${curr_dir}
cp ${install_files} ${install_dir} && chmod a+x ${install_dir}/install* cp ${install_files} ${install_dir} && chmod a+x ${install_dir}/install*
# Copy example code # Copy example code
mkdir -p ${install_dir}/examples mkdir -p ${install_dir}/examples
cp -r ${top_dir}/tests/examples/c ${install_dir}/examples examples_dir="${top_dir}/tests/examples"
cp -r ${top_dir}/tests/examples/JDBC ${install_dir}/examples cp -r ${examples_dir}/c ${install_dir}/examples
cp -r ${top_dir}/tests/examples/matlab ${install_dir}/examples cp -r ${examples_dir}/JDBC ${install_dir}/examples
cp -r ${top_dir}/tests/examples/python ${install_dir}/examples cp -r ${examples_dir}/matlab ${install_dir}/examples
cp -r ${top_dir}/tests/examples/R ${install_dir}/examples cp -r ${examples_dir}/python ${install_dir}/examples
cp -r ${top_dir}/tests/examples/go ${install_dir}/examples cp -r ${examples_dir}/R ${install_dir}/examples
cp -r ${examples_dir}/go ${install_dir}/examples
# Copy driver # Copy driver
mkdir -p ${install_dir}/driver mkdir -p ${install_dir}/driver
@ -64,18 +67,23 @@ cp ${lib_files} ${install_dir}/driver
# Copy connector # Copy connector
connector_dir="${code_dir}/connector" connector_dir="${code_dir}/connector"
mkdir -p ${install_dir}/connector mkdir -p ${install_dir}/connector
cp ${build_dir}/lib/*.jar ${install_dir}/connector
cp -r ${connector_dir}/grafana ${install_dir}/connector/ cp -r ${connector_dir}/grafana ${install_dir}/connector/
cp -r ${connector_dir}/python ${install_dir}/connector/ cp -r ${connector_dir}/python ${install_dir}/connector/
cp -r ${connector_dir}/go ${install_dir}/connector cp -r ${connector_dir}/go ${install_dir}/connector
cp ${build_dir}/lib/*.jar ${install_dir}/connector
# Copy release note # Copy release note
cp ${script_dir}/release_note ${install_dir} # cp ${script_dir}/release_note ${install_dir}
# exit 1 # exit 1
cd ${release_dir} cd ${release_dir}
tar -zcv -f "$(basename ${install_dir}).tar.gz" $(basename ${install_dir}) --remove-files if [ -z "$armver" ]; then
tar -zcv -f "$(basename ${install_dir}).tar.gz" $(basename ${install_dir}) --remove-files
elif [ "$armver" == "arm64" ]; then
tar -zcv -f "$(basename ${install_dir})-arm64.tar.gz" $(basename ${install_dir}) --remove-files
elif [ "$armver" == "arm32" ]; then
tar -zcv -f "$(basename ${install_dir})-arm32.tar.gz" $(basename ${install_dir}) --remove-files
fi
cd ${curr_dir} cd ${curr_dir}

View File

@ -42,14 +42,18 @@ initd_mod=0
service_mod=2 service_mod=2
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
service_mod=0 service_mod=0
elif $(which insserv &> /dev/null); then elif $(which service &> /dev/null); then
service_mod=1 service_mod=1
initd_mod=1 service_config_dir="/etc/init.d"
service_config_dir="/etc/init.d" if $(which chkconfig &> /dev/null); then
elif $(which update-rc.d &> /dev/null); then initd_mod=1
service_mod=1 elif $(which insserv &> /dev/null); then
initd_mod=2 initd_mod=2
service_config_dir="/etc/init.d" elif $(which update-rc.d &> /dev/null); then
initd_mod=3
else
service_mod=2
fi
else else
service_mod=2 service_mod=2
fi fi
@ -57,12 +61,15 @@ fi
function kill_taosd() { function kill_taosd() {
# ${csudo} pkill -f taosd || : # ${csudo} pkill -f taosd || :
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
} }
function install_include() { function install_include() {
${csudo} rm -f ${inc_link_dir}/taos.h || : ${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h|| :
${csudo} ln -s ${inc_dir}/taos.h ${inc_link_dir}/taos.h ${csudo} ln -s ${inc_dir}/taos.h ${inc_link_dir}/taos.h
${csudo} ln -s ${inc_dir}/taoserror.h ${inc_link_dir}/taoserror.h
} }
function install_lib() { function install_lib() {
@ -102,20 +109,26 @@ function install_config() {
} }
function clean_service_on_sysvinit() { function clean_service_on_sysvinit() {
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" #restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
${csudo} service taosd stop || : ${csudo} service taosd stop || :
fi fi
${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
${csudo} rm -f ${service_config_dir}/taosd || :
if ((${initd_mod}==1)); then if ((${initd_mod}==1)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} insserv -r taosd || : ${csudo} chkconfig --del taosd || :
elif ((${initd_mod}==2)); then elif ((${initd_mod}==2)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} update-rc.d -f taosd remove || : ${csudo} insserv -r taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d -f taosd remove || :
fi
${csudo} rm -f ${service_config_dir}/taosd || :
if $(which init &> /dev/null); then
${csudo} init q || :
fi fi
# ${csudo} update-rc.d -f taosd remove || :
${csudo} init q || :
} }
function install_service_on_sysvinit() { function install_service_on_sysvinit() {
@ -126,18 +139,24 @@ function install_service_on_sysvinit() {
# Install taosd service # Install taosd service
${csudo} cp %{init_d_dir}/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd ${csudo} cp %{init_d_dir}/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" #restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} grep -q -F "$restart_config_str" /etc/inittab || ${csudo} bash -c "echo '${restart_config_str}' >> /etc/inittab"
${csudo} grep -q -F "$restart_config_str" /etc/inittab || ${csudo} bash -c "echo '${restart_config_str}' >> /etc/inittab"
# TODO: for centos, change here if ((${initd_mod}==1)); then
${csudo} update-rc.d taosd defaults ${csudo} chkconfig --add taosd || :
# chkconfig mysqld on ${csudo} chkconfig --level 2345 taosd on || :
elif ((${initd_mod}==2)); then
${csudo} insserv taosd || :
${csudo} insserv -d taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d taosd defaults || :
fi
} }
function clean_service_on_systemd() { function clean_service_on_systemd() {
taosd_service_config="${service_config_dir}/taosd.service" taosd_service_config="${service_config_dir}/taosd.service"
# taosd service already is stoped before install # taosd service already is stoped before install in preinst script
#if systemctl is-active --quiet taosd; then #if systemctl is-active --quiet taosd; then
# echo "TDengine is running, stopping it..." # echo "TDengine is running, stopping it..."
# ${csudo} systemctl stop taosd &> /dev/null || echo &> /dev/null # ${csudo} systemctl stop taosd &> /dev/null || echo &> /dev/null

View File

@ -26,22 +26,27 @@ initd_mod=0
service_mod=2 service_mod=2
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
service_mod=0 service_mod=0
elif $(which insserv &> /dev/null); then elif $(which service &> /dev/null); then
service_mod=1 service_mod=1
initd_mod=1 service_config_dir="/etc/init.d"
service_config_dir="/etc/init.d" if $(which chkconfig &> /dev/null); then
elif $(which update-rc.d &> /dev/null); then initd_mod=1
service_mod=1 elif $(which insserv &> /dev/null); then
initd_mod=2 initd_mod=2
service_config_dir="/etc/init.d" elif $(which update-rc.d &> /dev/null); then
initd_mod=3
else
service_mod=2
fi
else else
service_mod=2 service_mod=2
fi fi
function kill_taosd() { function kill_taosd() {
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
} }
function clean_service_on_systemd() { function clean_service_on_systemd() {
@ -57,20 +62,27 @@ function clean_service_on_systemd() {
} }
function clean_service_on_sysvinit() { function clean_service_on_sysvinit() {
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" #restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
echo "TDengine taosd is running, stopping it..."
${csudo} service taosd stop || : ${csudo} service taosd stop || :
fi fi
${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
${csudo} rm -f ${service_config_dir}/taosd || :
if ((${initd_mod}==1)); then if ((${initd_mod}==1)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} insserv -r taosd || : ${csudo} chkconfig --del taosd || :
elif ((${initd_mod}==2)); then elif ((${initd_mod}==2)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} update-rc.d -f taosd remove || : ${csudo} insserv -r taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d -f taosd remove || :
fi
${csudo} rm -f ${service_config_dir}/taosd || :
if $(which init &> /dev/null); then
${csudo} init q || :
fi fi
# ${csudo} update-rc.d -f taosd remove || :
${csudo} init q || :
} }
function clean_service() { function clean_service() {
@ -79,7 +91,7 @@ function clean_service() {
elif ((${service_mod}==1)); then elif ((${service_mod}==1)); then
clean_service_on_sysvinit clean_service_on_sysvinit
else else
# must manual start taosd # must manual stop taosd
kill_taosd kill_taosd
fi fi
} }
@ -94,6 +106,7 @@ ${csudo} rm -f ${bin_link_dir}/taosdemo || :
${csudo} rm -f ${bin_link_dir}/taosdump || : ${csudo} rm -f ${bin_link_dir}/taosdump || :
${csudo} rm -f ${cfg_link_dir}/* || : ${csudo} rm -f ${cfg_link_dir}/* || :
${csudo} rm -f ${inc_link_dir}/taos.h || : ${csudo} rm -f ${inc_link_dir}/taos.h || :
${csudo} rm -f ${inc_link_dir}/taoserror.h || :
${csudo} rm -f ${lib_link_dir}/libtaos.* || : ${csudo} rm -f ${lib_link_dir}/libtaos.* || :
${csudo} rm -f ${log_link_dir} || : ${csudo} rm -f ${log_link_dir} || :

View File

@ -1,3 +1,14 @@
taos-1.6.4.0 (Release on 2019-12-01)
Bug fixed:
1.Look for possible causes of file corruption and fix them
2.Encapsulate memory allocation functions to reduce the possibility of crashes
3.Increase Arm64 compilation options
4.Remove most of the warnings in the code
5.Provide a variety of connector usage documents
6.Network connection can be selected in udp and tcp
7.Allow the maximum number of Tags to be 32
8.Bugs reported by the user
taos-1.5.2.6 (Release on 2019-05-13) taos-1.5.2.6 (Release on 2019-05-13)
Bug fixed: Bug fixed:
- Nchar strings sometimes were wrongly truncated on Window - Nchar strings sometimes were wrongly truncated on Window

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# Script to stop the service and uninstall tdengine, but retain the config, data and log files. # Script to stop the service and uninstall TDengine, but retain the config, data and log files.
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[1;32m' GREEN='\033[1;32m'
@ -27,21 +27,27 @@ initd_mod=0
service_mod=2 service_mod=2
if pidof systemd &> /dev/null; then if pidof systemd &> /dev/null; then
service_mod=0 service_mod=0
elif $(which insserv &> /dev/null); then elif $(which service &> /dev/null); then
service_mod=1 service_mod=1
initd_mod=1 service_config_dir="/etc/init.d"
service_config_dir="/etc/init.d" if $(which chkconfig &> /dev/null); then
elif $(which update-rc.d &> /dev/null); then initd_mod=1
service_mod=1 elif $(which insserv &> /dev/null); then
initd_mod=2 initd_mod=2
service_config_dir="/etc/init.d" elif $(which update-rc.d &> /dev/null); then
initd_mod=3
else
service_mod=2
fi
else else
service_mod=2 service_mod=2
fi fi
function kill_taosd() { function kill_taosd() {
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
${csudo} kill -9 ${pid} || : if [ -n "$pid" ]; then
${csudo} kill -9 $pid || :
fi
} }
function clean_bin() { function clean_bin() {
@ -61,6 +67,7 @@ function clean_lib() {
function clean_header() { function clean_header() {
# Remove link # Remove link
${csudo} rm -f ${inc_link_dir}/taos.h || : ${csudo} rm -f ${inc_link_dir}/taos.h || :
${csudo} rm -f ${inc_link_dir}/taoserror.h || :
} }
function clean_config() { function clean_config() {
@ -86,20 +93,27 @@ function clean_service_on_systemd() {
} }
function clean_service_on_sysvinit() { function clean_service_on_sysvinit() {
restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start" #restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
#${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
if pidof taosd &> /dev/null; then if pidof taosd &> /dev/null; then
echo "TDengine taosd is running, stopping it..."
${csudo} service taosd stop || : ${csudo} service taosd stop || :
fi fi
${csudo} sed -i "\|${restart_config_str}|d" /etc/inittab || :
${csudo} rm -f ${service_config_dir}/taosd || :
if ((${initd_mod}==1)); then if ((${initd_mod}==1)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} insserv -r taosd || : ${csudo} chkconfig --del taosd || :
elif ((${initd_mod}==2)); then elif ((${initd_mod}==2)); then
${csudo} grep -q -F "taos" /etc/inittab && ${csudo} update-rc.d -f taosd remove || : ${csudo} insserv -r taosd || :
elif ((${initd_mod}==3)); then
${csudo} update-rc.d -f taosd remove || :
fi
${csudo} rm -f ${service_config_dir}/taosd || :
if $(which init &> /dev/null); then
${csudo} init q || :
fi fi
# ${csudo} update-rc.d -f taosd remove || :
${csudo} init q || :
} }
function clean_service() { function clean_service() {
@ -108,7 +122,7 @@ function clean_service() {
elif ((${service_mod}==1)); then elif ((${service_mod}==1)); then
clean_service_on_sysvinit clean_service_on_sysvinit
else else
# must manual start taosd # must manual stop taosd
kill_taosd kill_taosd
fi fi
} }
@ -139,4 +153,4 @@ elif echo $osinfo | grep -qwi "centos" ; then
${csudo} rpm -e --noscripts tdengine || : ${csudo} rpm -e --noscripts tdengine || :
fi fi
echo -e "${GREEN}TDEngine is removed successfully!${NC}" echo -e "${GREEN}TDengine is removed successfully!${NC}"

View File

@ -0,0 +1,75 @@
#!/bin/bash
#
# Script to stop the client and uninstall database, but retain the config and log files.
set -e
# set -x
RED='\033[0;31m'
GREEN='\033[1;32m'
NC='\033[0m'
#install main path
install_main_dir="/usr/local/taos"
log_link_dir="/usr/local/taos/log"
cfg_link_dir="/usr/local/taos/cfg"
bin_link_dir="/usr/bin"
lib_link_dir="/usr/lib"
inc_link_dir="/usr/include"
csudo=""
if command -v sudo > /dev/null; then
csudo="sudo"
fi
function kill_client() {
#pid=$(ps -ef | grep "taos" | grep -v "grep" | awk '{print $2}')
if [ -n "$(pidof taos)" ]; then
${csudo} kill -9 $pid || :
fi
}
function clean_bin() {
# Remove link
${csudo} rm -f ${bin_link_dir}/taos || :
${csudo} rm -f ${bin_link_dir}/taosump || :
${csudo} rm -f ${bin_link_dir}/rmtaos || :
}
function clean_lib() {
# Remove link
${csudo} rm -f ${lib_link_dir}/libtaos.* || :
}
function clean_header() {
# Remove link
${csudo} rm -f ${inc_link_dir}/taos.h || :
${csudo} rm -f ${inc_link_dir}/taoserror.h || :
}
function clean_config() {
# Remove link
${csudo} rm -f ${cfg_link_dir}/* || :
}
function clean_log() {
# Remove link
${csudo} rm -rf ${log_link_dir} || :
}
# Stop client.
kill_client
# Remove binary file and links
clean_bin
# Remove header file.
clean_header
# Remove lib file
clean_lib
# Remove link log directory
clean_log
# Remove link configuration file
clean_config
${csudo} rm -rf ${install_main_dir}
echo -e "${GREEN}TDengine client is removed successfully!${NC}"

View File

@ -7,7 +7,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc)
INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc)
AUX_SOURCE_DIRECTORY(./src SRC) AUX_SOURCE_DIRECTORY(./src SRC)
IF (TD_LINUX_64) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux)
# set the static lib name # set the static lib name

View File

@ -24,9 +24,9 @@ void *taosOpenConnCache(int maxSessions, void (*cleanFp)(void *), void *tmrCtrl,
void taosCloseConnCache(void *handle); void taosCloseConnCache(void *handle);
void *taosAddConnIntoCache(void *handle, void *data, uint32_t ip, short port, char *user); void *taosAddConnIntoCache(void *handle, void *data, uint32_t ip, uint16_t port, char *user);
void *taosGetConnFromCache(void *handle, uint32_t ip, short port, char *user); void *taosGetConnFromCache(void *handle, uint32_t ip, uint16_t port, char *user);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -23,23 +23,10 @@ extern "C" {
#include "taos.h" #include "taos.h"
#include "tsqldef.h" #include "tsqldef.h"
#include "ttypes.h" #include "ttypes.h"
#include "taosmsg.h"
#define TK_SPACE 200
#define TK_COMMENT 201
#define TK_ILLEGAL 202
#define TK_HEX 203 // hex number 0x123
#define TK_OCT 204 // oct number
#define TK_BIN 205 // bin format data 0b111
#define TK_FILE 206
#define TSQL_SO_ASC 1
#define TSQL_SO_DESC 0
#define MAX_TOKEN_LEN 30 #define MAX_TOKEN_LEN 30
#define TSQL_TBNAME "TBNAME"
#define TSQL_TBNAME_L "tbname"
// token type // token type
enum { enum {
TSQL_NODE_TYPE_EXPR = 0x1, TSQL_NODE_TYPE_EXPR = 0x1,
@ -118,6 +105,7 @@ enum TSQL_TYPE {
SHOW_MODULES = 0x6c, SHOW_MODULES = 0x6c,
SHOW_CONNECTIONS = 0x6d, SHOW_CONNECTIONS = 0x6d,
SHOW_GRANTS = 0x6e, SHOW_GRANTS = 0x6e,
SHOW_VNODES = 0x6f,
// create dnode // create dnode
CREATE_DNODE = 0x80, CREATE_DNODE = 0x80,
@ -277,8 +265,7 @@ typedef struct tSQLExpr {
uint32_t nSQLOptr; // TK_FUNCTION: sql function, TK_LE: less than(binary expr) uint32_t nSQLOptr; // TK_FUNCTION: sql function, TK_LE: less than(binary expr)
// the full sql string of function(col, param), which is actually the raw // the full sql string of function(col, param), which is actually the raw
// field name, // field name, since the function name is kept in nSQLOptr already
// since the function name is kept in nSQLOptr already
SSQLToken operand; SSQLToken operand;
struct tSQLExprList *pParam; // function parameters struct tSQLExprList *pParam; // function parameters
@ -345,8 +332,6 @@ tSQLExprList *tSQLExprListAppend(tSQLExprList *pList, tSQLExpr *pNode, SSQLToken
void tSQLExprListDestroy(tSQLExprList *pList); void tSQLExprListDestroy(tSQLExprList *pList);
int32_t tSQLSyntaxNodeToString(tSQLExpr *pNode, char *dst);
SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection, tVariantList *pFrom, tSQLExpr *pWhere, SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection, tVariantList *pFrom, tSQLExpr *pWhere,
tVariantList *pGroupby, tVariantList *pSortOrder, SSQLToken *pInterval, tVariantList *pGroupby, tVariantList *pSortOrder, SSQLToken *pInterval,
SSQLToken *pSliding, tVariantList *pFill, SLimitVal *pLimit, SLimitVal *pGLimit); SSQLToken *pSliding, tVariantList *pFill, SLimitVal *pLimit, SLimitVal *pGLimit);
@ -378,6 +363,7 @@ tDCLSQL *tTokenListAppend(tDCLSQL *pTokenList, SSQLToken *pToken);
void setCreateDBSQL(SSqlInfo *pInfo, int32_t type, SSQLToken *pToken, SCreateDBInfo *pDB, SSQLToken *pIgExists); void setCreateDBSQL(SSqlInfo *pInfo, int32_t type, SSQLToken *pToken, SCreateDBInfo *pDB, SSQLToken *pIgExists);
void setCreateAcctSQL(SSqlInfo *pInfo, int32_t type, SSQLToken *pName, SSQLToken *pPwd, SCreateAcctSQL *pAcctInfo); void setCreateAcctSQL(SSqlInfo *pInfo, int32_t type, SSQLToken *pName, SSQLToken *pPwd, SCreateAcctSQL *pAcctInfo);
void setDefaultCreateDbOption(SCreateDBInfo *pDBInfo);
// prefix show db.tables; // prefix show db.tables;
void setDBName(SSQLToken *pCpxName, SSQLToken *pDB); void setDBName(SSQLToken *pCpxName, SSQLToken *pDB);

View File

@ -94,7 +94,7 @@ typedef struct SRetrieveSupport {
tOrderDescriptor *pOrderDescriptor; tOrderDescriptor *pOrderDescriptor;
tColModel * pFinalColModel; // colModel for final result tColModel * pFinalColModel; // colModel for final result
SSubqueryState * pState; SSubqueryState * pState;
int32_t vnodeIdx; // index of current vnode in vnode list int32_t subqueryIndex; // index of current vnode in vnode list
SSqlObj * pParentSqlObj; SSqlObj * pParentSqlObj;
tFilePage * localBuffer; // temp buffer, there is a buffer for each vnode to tFilePage * localBuffer; // temp buffer, there is a buffer for each vnode to
uint32_t numOfRetry; // record the number of retry times uint32_t numOfRetry; // record the number of retry times

View File

@ -23,17 +23,17 @@ extern "C" {
/* /*
* @date 2018/09/30 * @date 2018/09/30
*/ */
#include <limits.h> #include "os.h"
#include <stdio.h>
#include "textbuffer.h" #include "textbuffer.h"
#include "tscSecondaryMerge.h"
#include "tsclient.h" #include "tsclient.h"
#include "tsdb.h" #include "tsdb.h"
#include "tscSecondaryMerge.h"
#define UTIL_METER_IS_METRIC(cmd) (((cmd)->pMeterMeta != NULL) && ((cmd)->pMeterMeta->meterType == TSDB_METER_METRIC)) #define UTIL_METER_IS_METRIC(metaInfo) \
#define UTIL_METER_IS_NOMRAL_METER(cmd) (!(UTIL_METER_IS_METRIC(cmd))) (((metaInfo)->pMeterMeta != NULL) && ((metaInfo)->pMeterMeta->meterType == TSDB_METER_METRIC))
#define UTIL_METER_IS_CREATE_FROM_METRIC(cmd) \ #define UTIL_METER_IS_NOMRAL_METER(metaInfo) (!(UTIL_METER_IS_METRIC(metaInfo)))
(((cmd)->pMeterMeta != NULL) && ((cmd)->pMeterMeta->meterType == TSDB_METER_MTABLE)) #define UTIL_METER_IS_CREATE_FROM_METRIC(metaInfo) \
(((metaInfo)->pMeterMeta != NULL) && ((metaInfo)->pMeterMeta->meterType == TSDB_METER_MTABLE))
#define TSDB_COL_IS_TAG(f) (((f)&TSDB_COL_TAG) != 0) #define TSDB_COL_IS_TAG(f) (((f)&TSDB_COL_TAG) != 0)
@ -52,7 +52,6 @@ typedef struct SParsedDataColInfo {
typedef struct SJoinSubquerySupporter { typedef struct SJoinSubquerySupporter {
SSubqueryState* pState; SSubqueryState* pState;
SSqlObj* pObj; // parent SqlObj SSqlObj* pObj; // parent SqlObj
bool hasMore; // has data from vnode to fetch
int32_t subqueryIndex; // index of sub query int32_t subqueryIndex; // index of sub query
int64_t interval; // interval time int64_t interval; // interval time
SLimitVal limit; // limit info SLimitVal limit; // limit info
@ -62,28 +61,25 @@ typedef struct SJoinSubquerySupporter {
SFieldInfo fieldsInfo; SFieldInfo fieldsInfo;
STagCond tagCond; STagCond tagCond;
SSqlGroupbyExpr groupbyExpr; SSqlGroupbyExpr groupbyExpr;
struct STSBuf* pTSBuf; // the TSBuf struct that holds the compressed timestamp array
struct STSBuf* pTSBuf; FILE* f; // temporary file in order to create TSBuf
char path[PATH_MAX]; // temporary file path
FILE* f;
char path[PATH_MAX];
} SJoinSubquerySupporter; } SJoinSubquerySupporter;
void tscDestroyDataBlock(STableDataBlocks* pDataBlock); void tscDestroyDataBlock(STableDataBlocks* pDataBlock);
STableDataBlocks* tscCreateDataBlock(int32_t size); STableDataBlocks* tscCreateDataBlock(size_t initialBufSize, int32_t rowSize, int32_t startOffset, const char* name);
void tscAppendDataBlock(SDataBlockList* pList, STableDataBlocks* pBlocks); void tscAppendDataBlock(SDataBlockList* pList, STableDataBlocks* pBlocks);
SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, short bytes, uint32_t offset); SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, short bytes,
uint32_t offset);
SDataBlockList* tscCreateBlockArrayList(); SDataBlockList* tscCreateBlockArrayList();
void* tscDestroyBlockArrayList(SDataBlockList* pList); void* tscDestroyBlockArrayList(SDataBlockList* pList);
int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock); int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock);
void tscFreeUnusedDataBlocks(SDataBlockList* pList); void tscFreeUnusedDataBlocks(SDataBlockList* pList);
int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SDataBlockList* pDataList); int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SDataBlockList* pDataList);
STableDataBlocks* tscGetDataBlockFromList(void* pHashList, SDataBlockList* pDataBlockList, int64_t id, int32_t size, STableDataBlocks* tscGetDataBlockFromList(void* pHashList, SDataBlockList* pDataBlockList, int64_t id, int32_t size,
int32_t startOffset, int32_t rowSize, char* tableId); int32_t startOffset, int32_t rowSize, const char* tableId);
STableDataBlocks* tscCreateDataBlockEx(size_t size, int32_t rowSize, int32_t startOffset, char* name); SVnodeSidList* tscGetVnodeSidList(SMetricMeta* pMetricmeta, int32_t vnodeIdx);
SVnodeSidList* tscGetVnodeSidList(SMetricMeta* pMetricmeta, int32_t vnodeIdx);
SMeterSidExtInfo* tscGetMeterSidInfo(SVnodeSidList* pSidList, int32_t idx); SMeterSidExtInfo* tscGetMeterSidInfo(SVnodeSidList* pSidList, int32_t idx);
/** /**
@ -97,6 +93,8 @@ SMeterSidExtInfo* tscGetMeterSidInfo(SVnodeSidList* pSidList, int32_t idx);
bool tscIsPointInterpQuery(SSqlCmd* pCmd); bool tscIsPointInterpQuery(SSqlCmd* pCmd);
bool tscIsTWAQuery(SSqlCmd* pCmd); bool tscIsTWAQuery(SSqlCmd* pCmd);
bool tscProjectionQueryOnMetric(SSqlCmd* pCmd); bool tscProjectionQueryOnMetric(SSqlCmd* pCmd);
bool tscProjectionQueryOnTable(SSqlCmd* pCmd);
bool tscIsTwoStageMergeMetricQuery(SSqlCmd* pCmd); bool tscIsTwoStageMergeMetricQuery(SSqlCmd* pCmd);
bool tscQueryOnMetric(SSqlCmd* pCmd); bool tscQueryOnMetric(SSqlCmd* pCmd);
bool tscQueryMetricTags(SSqlCmd* pCmd); bool tscQueryMetricTags(SSqlCmd* pCmd);
@ -106,15 +104,9 @@ void tscAddSpecialColumnForSelect(SSqlCmd* pCmd, int32_t outputColIndex, int16_t
SSchema* pColSchema, int16_t isTag); SSchema* pColSchema, int16_t isTag);
void addRequiredTagColumn(SSqlCmd* pCmd, int32_t tagColIndex, int32_t tableIndex); void addRequiredTagColumn(SSqlCmd* pCmd, int32_t tagColIndex, int32_t tableIndex);
void SStringFree(SString* str);
void SStringCopy(SString* pDest, const SString* pSrc);
SString SStringCreate(const char* str);
int32_t SStringAlloc(SString* pStr, int32_t size);
int32_t SStringEnsureRemain(SString* pStr, int32_t size);
int32_t setMeterID(SSqlObj* pSql, SSQLToken* pzTableName, int32_t tableIndex); int32_t setMeterID(SSqlObj* pSql, SSQLToken* pzTableName, int32_t tableIndex);
void tscClearInterpInfo(SSqlCmd* pCmd); void tscClearInterpInfo(SSqlCmd* pCmd);
bool tscIsInsertOrImportData(char* sqlstr); bool tscIsInsertOrImportData(char* sqlstr);
@ -125,7 +117,7 @@ int tscAllocPayload(SSqlCmd* pCmd, int size);
void tscFieldInfoSetValFromSchema(SFieldInfo* pFieldInfo, int32_t index, SSchema* pSchema); void tscFieldInfoSetValFromSchema(SFieldInfo* pFieldInfo, int32_t index, SSchema* pSchema);
void tscFieldInfoSetValFromField(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* pField); void tscFieldInfoSetValFromField(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* pField);
void tscFieldInfoSetValue(SFieldInfo* pFieldInfo, int32_t index, int8_t type, char* name, int16_t bytes); void tscFieldInfoSetValue(SFieldInfo* pFieldInfo, int32_t index, int8_t type, const char* name, int16_t bytes);
void tscFieldInfoUpdateVisible(SFieldInfo* pFieldInfo, int32_t index, bool visible); void tscFieldInfoUpdateVisible(SFieldInfo* pFieldInfo, int32_t index, bool visible);
void tscFieldInfoCalOffset(SSqlCmd* pCmd); void tscFieldInfoCalOffset(SSqlCmd* pCmd);
@ -134,27 +126,29 @@ void tscFieldInfoCopy(SFieldInfo* src, SFieldInfo* dst, const int32_t* indexList
void tscFieldInfoCopyAll(SFieldInfo* src, SFieldInfo* dst); void tscFieldInfoCopyAll(SFieldInfo* src, SFieldInfo* dst);
TAOS_FIELD* tscFieldInfoGetField(SSqlCmd* pCmd, int32_t index); TAOS_FIELD* tscFieldInfoGetField(SSqlCmd* pCmd, int32_t index);
int16_t tscFieldInfoGetOffset(SSqlCmd* pCmd, int32_t index); int16_t tscFieldInfoGetOffset(SSqlCmd* pCmd, int32_t index);
int32_t tscGetResRowLength(SSqlCmd* pCmd); int32_t tscGetResRowLength(SSqlCmd* pCmd);
void tscClearFieldInfo(SFieldInfo* pFieldInfo); void tscClearFieldInfo(SFieldInfo* pFieldInfo);
void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes, int16_t tableIndex); void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes, int16_t tableIndex);
SSqlExpr* tscSqlExprInsert(SSqlCmd* pCmd, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type, SSqlExpr* tscSqlExprInsert(SSqlCmd* pCmd, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
int16_t size, /*int16_t colId,*/ int16_t interSize); int16_t size, int16_t interSize);
SSqlExpr* tscSqlExprInsertEmpty(SSqlCmd* pCmd, int32_t index, int16_t functionId);
SSqlExpr* tscSqlExprUpdate(SSqlCmd* pCmd, int32_t index, int16_t functionId, int16_t srcColumnIndex, int16_t type, SSqlExpr* tscSqlExprUpdate(SSqlCmd* pCmd, int32_t index, int16_t functionId, int16_t srcColumnIndex, int16_t type,
int16_t size); int16_t size);
SSqlExpr* tscSqlExprGet(SSqlCmd* pCmd, int32_t index); SSqlExpr* tscSqlExprGet(SSqlCmd* pCmd, int32_t index);
void tscSqlExprCopy(SSqlExprInfo* dst, const SSqlExprInfo* src, uint64_t uid); void tscSqlExprCopy(SSqlExprInfo* dst, const SSqlExprInfo* src, uint64_t uid);
SColumnBase* tscColumnBaseInfoInsert(SSqlCmd* pCmd, SColumnIndex* colIndex); SColumnBase* tscColumnBaseInfoInsert(SSqlCmd* pCmd, SColumnIndex* colIndex);
void tscColumnFilterInfoCopy(SColumnFilterInfo* dst, const SColumnFilterInfo* src); void tscColumnFilterInfoCopy(SColumnFilterInfo* dst, const SColumnFilterInfo* src);
void tscColumnBaseCopy(SColumnBase* dst, const SColumnBase* src); void tscColumnBaseCopy(SColumnBase* dst, const SColumnBase* src);
void tscColumnBaseInfoCopy(SColumnBaseInfo* dst, const SColumnBaseInfo* src, int16_t tableIndex); void tscColumnBaseInfoCopy(SColumnBaseInfo* dst, const SColumnBaseInfo* src, int16_t tableIndex);
SColumnBase* tscColumnBaseInfoGet(SColumnBaseInfo* pColumnBaseInfo, int32_t index); SColumnBase* tscColumnBaseInfoGet(SColumnBaseInfo* pColumnBaseInfo, int32_t index);
void tscColumnBaseInfoUpdateTableIndex(SColumnBaseInfo* pColList, int16_t tableIndex); void tscColumnBaseInfoUpdateTableIndex(SColumnBaseInfo* pColList, int16_t tableIndex);
void tscColumnBaseInfoReserve(SColumnBaseInfo* pColumnBaseInfo, int32_t size); void tscColumnBaseInfoReserve(SColumnBaseInfo* pColumnBaseInfo, int32_t size);
void tscColumnBaseInfoDestroy(SColumnBaseInfo* pColumnBaseInfo); void tscColumnBaseInfoDestroy(SColumnBaseInfo* pColumnBaseInfo);
@ -167,11 +161,10 @@ bool tscValidateColumnId(SSqlCmd* pCmd, int32_t colId);
// get starter position of metric query condition (query on tags) in SSqlCmd.payload // get starter position of metric query condition (query on tags) in SSqlCmd.payload
SCond* tsGetMetricQueryCondPos(STagCond* pCond, uint64_t tableIndex); SCond* tsGetMetricQueryCondPos(STagCond* pCond, uint64_t tableIndex);
void tsSetMetricQueryCond(STagCond* pTagCond, uint64_t uid, const char* str); void tsSetMetricQueryCond(STagCond* pTagCond, uint64_t uid, const char* str);
void tscTagCondCopy(STagCond* dest, const STagCond* src); void tscTagCondCopy(STagCond* dest, const STagCond* src);
void tscTagCondRelease(STagCond* pCond); void tscTagCondRelease(STagCond* pCond);
void tscTagCondSetQueryCondType(STagCond* pCond, int16_t type);
void tscGetSrcColumnInfo(SSrcColumnInfo* pColInfo, SSqlCmd* pCmd); void tscGetSrcColumnInfo(SSrcColumnInfo* pColInfo, SSqlCmd* pCmd);
@ -180,19 +173,19 @@ bool tscShouldFreeHeatBeat(SSqlObj* pHb);
void tscCleanSqlCmd(SSqlCmd* pCmd); void tscCleanSqlCmd(SSqlCmd* pCmd);
bool tscShouldFreeAsyncSqlObj(SSqlObj* pSql); bool tscShouldFreeAsyncSqlObj(SSqlObj* pSql);
void tscRemoveAllMeterMetaInfo(SSqlCmd* pCmd, bool removeFromCache); void tscRemoveAllMeterMetaInfo(SSqlCmd* pCmd, bool removeFromCache);
SMeterMetaInfo* tscGetMeterMetaInfo(SSqlCmd* pCmd, int32_t index); SMeterMetaInfo* tscGetMeterMetaInfo(SSqlCmd* pCmd, int32_t index);
SMeterMetaInfo* tscGetMeterMetaInfoByUid(SSqlCmd* pCmd, uint64_t uid, int32_t* index); SMeterMetaInfo* tscGetMeterMetaInfoByUid(SSqlCmd* pCmd, uint64_t uid, int32_t* index);
void tscClearMeterMetaInfo(SMeterMetaInfo* pMeterMetaInfo, bool removeFromCache); void tscClearMeterMetaInfo(SMeterMetaInfo* pMeterMetaInfo, bool removeFromCache);
SMeterMetaInfo* tscAddMeterMetaInfo(SSqlCmd* pCmd, const char* name, SMeterMeta* pMeterMeta, SMetricMeta* pMetricMeta, SMeterMetaInfo* tscAddMeterMetaInfo(SSqlCmd* pCmd, const char* name, SMeterMeta* pMeterMeta, SMetricMeta* pMetricMeta,
int16_t numOfTags, int16_t* tags); int16_t numOfTags, int16_t* tags);
SMeterMetaInfo* tscAddEmptyMeterMetaInfo(SSqlCmd* pCmd); SMeterMetaInfo* tscAddEmptyMeterMetaInfo(SSqlCmd* pCmd);
void tscGetMetricMetaCacheKey(SSqlCmd* pCmd, char* keyStr, uint64_t uid); void tscGetMetricMetaCacheKey(SSqlCmd* pCmd, char* keyStr, uint64_t uid);
int tscGetMetricMeta(SSqlObj* pSql); int tscGetMetricMeta(SSqlObj* pSql);
int tscGetMeterMeta(SSqlObj* pSql, char* meterId, int32_t tableIndex); int tscGetMeterMeta(SSqlObj* pSql, char* meterId, int32_t tableIndex);
int tscGetMeterMetaEx(SSqlObj* pSql, char* meterId, bool createIfNotExists); int tscGetMeterMetaEx(SSqlObj* pSql, char* meterId, bool createIfNotExists);
void tscResetForNextRetrieve(SSqlRes* pRes); void tscResetForNextRetrieve(SSqlRes* pRes);
@ -216,18 +209,20 @@ void tscDoQuery(SSqlObj* pSql);
* @param pPrevSql * @param pPrevSql
* @return * @return
*/ */
SSqlObj* createSubqueryObj(SSqlObj* pSql, int32_t vnodeIndex, int16_t tableIndex, void (*fp)(), void* param, SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void* param, SSqlObj* pPrevSql);
SSqlObj* pPrevSql); void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t tableIndex);
void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t tableIndex);
void doAddGroupColumnForSubquery(SSqlCmd* pCmd, int32_t tagIndex); void doAddGroupColumnForSubquery(SSqlCmd* pCmd, int32_t tagIndex);
int16_t tscGetJoinTagColIndexByUid(SSqlCmd* pCmd, uint64_t uid); int16_t tscGetJoinTagColIndexByUid(STagCond* pTagCond, uint64_t uid);
TAOS* taos_connect_a(char* ip, char* user, char* pass, char* db, int port, void (*fp)(void*, TAOS_RES*, int), TAOS* taos_connect_a(char* ip, char* user, char* pass, char* db, uint16_t port, void (*fp)(void*, TAOS_RES*, int),
void* param, void** taos); void* param, void** taos);
void sortRemoveDuplicates(STableDataBlocks* dataBuf); void sortRemoveDuplicates(STableDataBlocks* dataBuf);
void tscPrintSelectClause(SSqlCmd* pCmd);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -34,8 +34,8 @@ extern "C" {
#include "tglobalcfg.h" #include "tglobalcfg.h"
#include "tlog.h" #include "tlog.h"
#include "tscCache.h" #include "tscCache.h"
#include "tscSQLParser.h"
#include "tsdb.h" #include "tsdb.h"
#include "tsql.h"
#include "tsqlfunction.h" #include "tsqlfunction.h"
#include "tutil.h" #include "tutil.h"
@ -92,7 +92,12 @@ enum _sql_cmd {
*/ */
TSDB_SQL_RETRIEVE_EMPTY_RESULT, TSDB_SQL_RETRIEVE_EMPTY_RESULT,
TSDB_SQL_RESET_CACHE, TSDB_SQL_RESET_CACHE, // 40
TSDB_SQL_SERV_STATUS,
TSDB_SQL_CURRENT_DB,
TSDB_SQL_SERV_VERSION,
TSDB_SQL_CLI_VERSION,
TSDB_SQL_CURRENT_USER,
TSDB_SQL_CFG_LOCAL, TSDB_SQL_CFG_LOCAL,
TSDB_SQL_MAX TSDB_SQL_MAX
@ -102,22 +107,25 @@ enum _sql_cmd {
struct SSqlInfo; struct SSqlInfo;
typedef struct SSqlGroupbyExpr { typedef struct SSqlGroupbyExpr {
int16_t tableIndex; int16_t tableIndex;
int16_t numOfGroupCols; int16_t numOfGroupCols;
SColIndexEx columnInfo[TSDB_MAX_TAGS]; // group by columns information SColIndexEx columnInfo[TSDB_MAX_TAGS]; // group by columns information
int16_t orderIndex; // order by column index
int16_t orderIndex; // order by column index int16_t orderType; // order by type: asc/desc
int16_t orderType; // order by type: asc/desc
} SSqlGroupbyExpr; } SSqlGroupbyExpr;
typedef struct SMeterMetaInfo { typedef struct SMeterMetaInfo {
SMeterMeta * pMeterMeta; // metermeta SMeterMeta * pMeterMeta; // metermeta
SMetricMeta *pMetricMeta; // metricmeta SMetricMeta *pMetricMeta; // metricmeta
char name[TSDB_METER_ID_LEN + 1]; /*
int16_t numOfTags; // total required tags in query, including groupby tags * 1. keep the vnode index during the multi-vnode super table projection query
int16_t tagColumnIndex[TSDB_MAX_TAGS]; // clause + tag projection * 2. keep the vnode index for multi-vnode insertion
*/
int32_t vnodeIndex;
char name[TSDB_METER_ID_LEN + 1]; // table(super table) name
int16_t numOfTags; // total required tags in query, including groupby tags
int16_t tagColumnIndex[TSDB_MAX_TAGS]; // clause + tag projection
} SMeterMetaInfo; } SMeterMetaInfo;
/* the structure for sql function in select clause */ /* the structure for sql function in select clause */
@ -183,7 +191,7 @@ typedef struct SString {
typedef struct SCond { typedef struct SCond {
uint64_t uid; uint64_t uid;
SString cond; char * cond;
} SCond; } SCond;
typedef struct SJoinNode { typedef struct SJoinNode {
@ -214,41 +222,46 @@ typedef struct STagCond {
} STagCond; } STagCond;
typedef struct SParamInfo { typedef struct SParamInfo {
int32_t idx; int32_t idx;
char type; char type;
uint8_t timePrec; uint8_t timePrec;
short bytes; short bytes;
uint32_t offset; uint32_t offset;
} SParamInfo; } SParamInfo;
typedef struct STableDataBlocks { typedef struct STableDataBlocks {
char meterId[TSDB_METER_ID_LEN]; char meterId[TSDB_METER_ID_LEN];
int8_t tsSource; int8_t tsSource; // where does the UNIX timestamp come from, server or client
bool ordered; bool ordered; // if current rows are ordered or not
int64_t vgid; // virtual group id
int64_t prevTS; // previous timestamp, recorded to decide if the records array is ts ascending
int32_t numOfMeters; // number of tables in current submit block
int64_t vgid; int32_t rowSize; // row size for current table
int64_t prevTS;
int32_t numOfMeters;
int32_t rowSize;
uint32_t nAllocSize; uint32_t nAllocSize;
uint32_t size; uint32_t size;
/*
* the metermeta for current table, the metermeta will be used during submit stage, keep a ref
* to avoid it to be removed from cache
*/
SMeterMeta* pMeterMeta;
union { union {
char *filename; char *filename;
char *pData; char *pData;
}; };
// for parameter ('?') binding // for parameter ('?') binding
uint32_t numOfAllocedParams; uint32_t numOfAllocedParams;
uint32_t numOfParams; uint32_t numOfParams;
SParamInfo* params; SParamInfo *params;
} STableDataBlocks; } STableDataBlocks;
typedef struct SDataBlockList { typedef struct SDataBlockList {
int32_t idx; int32_t idx;
int32_t nSize; uint32_t nSize;
int32_t nAlloc; uint32_t nAlloc;
char * userParam; /* user assigned parameters for async query */ char * userParam; /* user assigned parameters for async query */
void * udfp; /* user defined function pointer, used in async model */ void * udfp; /* user defined function pointer, used in async model */
STableDataBlocks **pData; STableDataBlocks **pData;
@ -257,18 +270,17 @@ typedef struct SDataBlockList {
typedef struct { typedef struct {
SOrderVal order; SOrderVal order;
int command; int command;
int count; // TODO refactor
// TODO refactor
int count;
int16_t isInsertFromFile; // load data from file or not
union { union {
bool existsCheck; bool existsCheck; // check if the table exists
int8_t showType; int8_t showType; // show command type
}; };
char msgType; int8_t isInsertFromFile; // load data from file or not
uint16_t type; bool import; // import/insert type
uint8_t msgType;
uint16_t type; // query type
char intervalTimeUnit; char intervalTimeUnit;
int64_t etime, stime; int64_t etime, stime;
int64_t nAggTimeInterval; // aggregation time interval int64_t nAggTimeInterval; // aggregation time interval
@ -281,20 +293,19 @@ typedef struct {
* *
* In such cases, allocate the memory dynamically, and need to free the memory * In such cases, allocate the memory dynamically, and need to free the memory
*/ */
uint32_t allocSize; uint32_t allocSize;
char * payload; char * payload;
int payloadLen; int payloadLen;
short numOfCols; short numOfCols;
SColumnBaseInfo colList; SColumnBaseInfo colList;
SFieldInfo fieldsInfo; SFieldInfo fieldsInfo;
SSqlExprInfo exprsInfo; SSqlExprInfo exprsInfo;
SLimitVal limit; SLimitVal limit;
SLimitVal slimit; SLimitVal slimit;
int64_t globalLimit; int64_t globalLimit;
STagCond tagCond; STagCond tagCond;
int16_t vnodeIdx; // vnode index in pMetricMeta for metric query int16_t interpoType; // interpolate type
int16_t interpoType; // interpolate type int16_t numOfTables;
int16_t numOfTables;
// submit data blocks branched according to vnode // submit data blocks branched according to vnode
SDataBlockList * pDataBlocks; SDataBlockList * pDataBlocks;
@ -342,11 +353,11 @@ typedef struct _tsc_obj {
void * signature; void * signature;
void * pTimer; void * pTimer;
char mgmtIp[TSDB_USER_LEN]; char mgmtIp[TSDB_USER_LEN];
short mgmtPort; uint16_t mgmtPort;
char user[TSDB_USER_LEN]; char user[TSDB_USER_LEN];
char pass[TSDB_KEY_LEN]; char pass[TSDB_KEY_LEN];
char acctId[TSDB_DB_NAME_LEN]; char acctId[TSDB_DB_NAME_LEN];
char db[TSDB_DB_NAME_LEN]; char db[TSDB_METER_ID_LEN];
char sversion[TSDB_VERSION_LEN]; char sversion[TSDB_VERSION_LEN];
char writeAuth : 1; char writeAuth : 1;
char superAuth : 1; char superAuth : 1;
@ -362,26 +373,26 @@ typedef struct _sql_obj {
STscObj *pTscObj; STscObj *pTscObj;
void (*fp)(); void (*fp)();
void (*fetchFp)(); void (*fetchFp)();
void * param; void * param;
uint32_t ip; uint32_t ip;
short vnode; short vnode;
int64_t stime; int64_t stime;
uint32_t queryId; uint32_t queryId;
void * thandle; void * thandle;
void * pStream; void * pStream;
char * sqlstr; char * sqlstr;
char retry; char retry;
char maxRetry; char maxRetry;
char index; uint8_t index;
char freed : 4; char freed : 4;
char listed : 4; char listed : 4;
tsem_t rspSem; tsem_t rspSem;
tsem_t emptyRspSem; tsem_t emptyRspSem;
SSqlCmd cmd;
SSqlCmd cmd; SSqlRes res;
SSqlRes res; uint8_t numOfSubs;
char* asyncTblPos;
char numOfSubs; void* pTableHashList;
struct _sql_obj **pSubs; struct _sql_obj **pSubs;
struct _sql_obj * prev, *next; struct _sql_obj * prev, *next;
} SSqlObj; } SSqlObj;
@ -425,11 +436,11 @@ int tsParseSql(SSqlObj *pSql, char *acct, char *db, bool multiVnodeInsertion);
void tscInitMsgs(); void tscInitMsgs();
void *tscProcessMsgFromServer(char *msg, void *ahandle, void *thandle); void *tscProcessMsgFromServer(char *msg, void *ahandle, void *thandle);
int tscProcessSql(SSqlObj *pSql); int tscProcessSql(SSqlObj *pSql);
void tscAsyncInsertMultiVnodesProxy(void *param, TAOS_RES *tres, int numOfRows); void tscAsyncInsertMultiVnodesProxy(void *param, TAOS_RES *tres, int numOfRows);
int tscRenewMeterMeta(SSqlObj *pSql, char *meterId); int tscRenewMeterMeta(SSqlObj *pSql, char *meterId);
void tscQueueAsyncRes(SSqlObj *pSql); void tscQueueAsyncRes(SSqlObj *pSql);
void tscQueueAsyncError(void(*fp), void *param); void tscQueueAsyncError(void(*fp), void *param);
@ -443,18 +454,12 @@ int taos_retrieve(TAOS_RES *res);
* before send query message to vnode * before send query message to vnode
*/ */
int32_t tscTansformSQLFunctionForMetricQuery(SSqlCmd *pCmd); int32_t tscTansformSQLFunctionForMetricQuery(SSqlCmd *pCmd);
void tscRestoreSQLFunctionForMetricQuery(SSqlCmd *pCmd); void tscRestoreSQLFunctionForMetricQuery(SSqlCmd *pCmd);
/**
* release both metric/meter meta information
* @param pCmd SSqlCmd object that contains the metric/meter meta info
*/
void tscClearSqlMetaInfo(SSqlCmd *pCmd);
void tscClearSqlMetaInfoForce(SSqlCmd *pCmd); void tscClearSqlMetaInfoForce(SSqlCmd *pCmd);
int32_t tscCreateResPointerInfo(SSqlCmd *pCmd, SSqlRes *pRes); int32_t tscCreateResPointerInfo(SSqlCmd *pCmd, SSqlRes *pRes);
void tscDestroyResPointerInfo(SSqlRes *pRes); void tscDestroyResPointerInfo(SSqlRes *pRes);
void tscFreeSqlCmdData(SSqlCmd *pCmd); void tscFreeSqlCmdData(SSqlCmd *pCmd);
@ -474,11 +479,14 @@ void tscFreeSqlObj(SSqlObj *pObj);
void tscCloseTscObj(STscObj *pObj); void tscCloseTscObj(STscObj *pObj);
void tscProcessMultiVnodesInsert(SSqlObj *pSql); void tscProcessMultiVnodesInsert(SSqlObj *pSql);
void tscProcessMultiVnodesInsertForFile(SSqlObj *pSql); void tscProcessMultiVnodesInsertForFile(SSqlObj *pSql);
void tscKillMetricQuery(SSqlObj *pSql); void tscKillMetricQuery(SSqlObj *pSql);
void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen); void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen);
int32_t tscBuildResultsForEmptyRetrieval(SSqlObj *pSql); bool tscIsUpdateQuery(STscObj *pObj);
bool tscHasReachLimitation(SSqlObj* pSql);
int32_t tscInvalidSQLErrMsg(char *msg, const char *additionalInfo, const char *sql);
// transfer SSqlInfo to SqlCmd struct // transfer SSqlInfo to SqlCmd struct
int32_t tscToSQLCmd(SSqlObj *pSql, struct SSqlInfo *pInfo); int32_t tscToSQLCmd(SSqlObj *pSql, struct SSqlInfo *pInfo);

View File

@ -9,6 +9,22 @@ extern "C" {
#endif #endif
#undef com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE #undef com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE
#define com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE 0LL #define com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE 0LL
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method:
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp
(JNIEnv *, jclass, jint, jstring, jboolean);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method:
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp
(JNIEnv *, jclass);
/* /*
* Class: com_taosdata_jdbc_TSDBJNIConnector * Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: initImp * Method: initImp

View File

@ -13,8 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdbool.h>
#include "os.h" #include "os.h"
#include "com_taosdata_jdbc_TSDBJNIConnector.h" #include "com_taosdata_jdbc_TSDBJNIConnector.h"
#include "taos.h" #include "taos.h"
@ -63,13 +61,13 @@ jmethodID g_rowdataSetByteArrayFp;
void jniGetGlobalMethod(JNIEnv *env) { void jniGetGlobalMethod(JNIEnv *env) {
// make sure init function executed once // make sure init function executed once
switch (__sync_val_compare_and_swap_32(&__init, 0, 1)) { switch (atomic_val_compare_exchange_32(&__init, 0, 1)) {
case 0: case 0:
break; break;
case 1: case 1:
do { do {
taosMsleep(0); taosMsleep(0);
} while (__sync_val_load_32(&__init) == 1); } while (atomic_load_32(&__init) == 1);
case 2: case 2:
return; return;
} }
@ -109,10 +107,24 @@ void jniGetGlobalMethod(JNIEnv *env) {
g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V"); g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V");
(*env)->DeleteLocalRef(env, rowdataClass); (*env)->DeleteLocalRef(env, rowdataClass);
__sync_val_restore_32(&__init, 2); atomic_store_32(&__init, 2);
jniTrace("native method register finished"); jniTrace("native method register finished");
} }
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp(JNIEnv *env, jobject jobj, jint jMode, jstring jPath, jboolean jAutoDump) {
if (jPath != NULL) {
const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
taosSetAllocMode(jMode, path, !!jAutoDump);
(*env)->ReleaseStringUTFChars(env, jPath, path);
} else {
taosSetAllocMode(jMode, NULL, !!jAutoDump);
}
}
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp(JNIEnv *env, jobject jobj) {
taosDumpMemoryLeak();
}
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *env, jobject jobj, jstring jconfigDir) { JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *env, jobject jobj, jstring jconfigDir) {
if (jconfigDir != NULL) { if (jconfigDir != NULL) {
const char *confDir = (*env)->GetStringUTFChars(env, jconfigDir, NULL); const char *confDir = (*env)->GetStringUTFChars(env, jconfigDir, NULL);
@ -208,10 +220,10 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn
ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, jport); ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, jport);
if (ret == 0) { if (ret == 0) {
jniError("jobj:%p, taos:%p, connect to tdengine failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
(char *)host, (char *)user, (char *)dbname, jport); (char *)host, (char *)user, (char *)dbname, jport);
} else { } else {
jniTrace("jobj:%p, taos:%p, connect to tdengine succeed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, jniTrace("jobj:%p, conn:%p, connect to database succeed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
(char *)host, (char *)user, (char *)dbname, jport); (char *)host, (char *)user, (char *)dbname, jport);
} }
@ -227,12 +239,12 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(J
jbyteArray jsql, jlong con) { jbyteArray jsql, jlong con) {
TAOS *tscon = (TAOS *)con; TAOS *tscon = (TAOS *)con;
if (tscon == NULL) { if (tscon == NULL) {
jniError("jobj:%p, connection is closed", jobj); jniError("jobj:%p, connection is already closed", jobj);
return JNI_CONNECTION_NULL; return JNI_CONNECTION_NULL;
} }
if (jsql == NULL) { if (jsql == NULL) {
jniError("jobj:%p, taos:%p, sql is null", jobj, tscon); jniError("jobj:%p, conn:%p, sql is null", jobj, tscon);
return JNI_SQL_NULL; return JNI_SQL_NULL;
} }
@ -240,6 +252,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(J
char *dst = (char *)calloc(1, sizeof(char) * (len + 1)); char *dst = (char *)calloc(1, sizeof(char) * (len + 1));
if (dst == NULL) { if (dst == NULL) {
jniError("jobj:%p, conn:%p, can not alloc memory", jobj, tscon);
return JNI_OUT_OF_MEMORY; return JNI_OUT_OF_MEMORY;
} }
@ -248,9 +261,11 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(J
//todo handle error //todo handle error
} }
jniTrace("jobj:%p, conn:%p, sql:%s", jobj, tscon, dst);
int code = taos_query(tscon, dst); int code = taos_query(tscon, dst);
if (code != 0) { if (code != 0) {
jniError("jobj:%p, taos:%p, code:%d, msg:%s, sql:%s", jobj, tscon, code, taos_errstr(tscon), dst); jniError("jobj:%p, conn:%p, code:%d, msg:%s", jobj, tscon, code, taos_errstr(tscon));
free(dst); free(dst);
return JNI_TDENGINE_ERROR; return JNI_TDENGINE_ERROR;
} else { } else {
@ -259,9 +274,9 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(J
if (pSql->cmd.command == TSDB_SQL_INSERT) { if (pSql->cmd.command == TSDB_SQL_INSERT) {
affectRows = taos_affected_rows(tscon); affectRows = taos_affected_rows(tscon);
jniTrace("jobj:%p, taos:%p, code:%d, affect rows:%d, sql:%s", jobj, tscon, code, affectRows, dst); jniTrace("jobj:%p, conn:%p, code:%d, affect rows:%d", jobj, tscon, code, affectRows);
} else { } else {
jniTrace("jobj:%p, taos:%p, code:%d, sql:%s", jobj, tscon, code, dst); jniTrace("jobj:%p, conn:%p, code:%d", jobj, tscon, code);
} }
free(dst); free(dst);
@ -291,15 +306,17 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(
return JNI_CONNECTION_NULL; return JNI_CONNECTION_NULL;
} }
int num_fields = taos_field_count(tscon); jlong ret = 0;
if (num_fields != 0) {
jlong ret = (jlong)taos_use_result(tscon); if (tscIsUpdateQuery(tscon)) {
jniTrace("jobj:%p, taos:%p, get resultset:%p", jobj, tscon, (void *)ret); ret = 0; // for update query, no result pointer
return ret; jniTrace("jobj:%p, conn:%p, no resultset", jobj, tscon);
} else {
ret = (jlong) taos_use_result(tscon);
jniTrace("jobj:%p, conn:%p, get resultset:%p", jobj, tscon, (void *) ret);
} }
jniTrace("jobj:%p, taos:%p, no resultset", jobj, tscon); return ret;
return 0;
} }
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con, JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con,
@ -311,12 +328,12 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(
} }
if ((void *)res == NULL) { if ((void *)res == NULL) {
jniError("jobj:%p, taos:%p, resultset is null", jobj, tscon); jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
return JNI_RESULT_SET_NULL; return JNI_RESULT_SET_NULL;
} }
taos_free_result((void *)res); taos_free_result((void *)res);
jniTrace("jobj:%p, taos:%p, free resultset:%p", jobj, tscon, (void *)res); jniTrace("jobj:%p, conn:%p, free resultset:%p", jobj, tscon, (void *)res);
return JNI_SUCCESS; return JNI_SUCCESS;
} }
@ -330,7 +347,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsIm
jint ret = taos_affected_rows(tscon); jint ret = taos_affected_rows(tscon);
jniTrace("jobj:%p, taos:%p, affect rows:%d", jobj, tscon, (void *)con, ret); jniTrace("jobj:%p, conn:%p, affect rows:%d", jobj, tscon, (void *)con, ret);
return ret; return ret;
} }
@ -346,7 +363,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData
TAOS_RES *result = (TAOS_RES *)res; TAOS_RES *result = (TAOS_RES *)res;
if (result == NULL) { if (result == NULL) {
jniError("jobj:%p, taos:%p, resultset is null", jobj, tscon); jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
return JNI_RESULT_SET_NULL; return JNI_RESULT_SET_NULL;
} }
@ -356,10 +373,10 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData
// jobject arrayListObj = (*env)->NewObject(env, g_arrayListClass, g_arrayListConstructFp, ""); // jobject arrayListObj = (*env)->NewObject(env, g_arrayListClass, g_arrayListConstructFp, "");
if (num_fields == 0) { if (num_fields == 0) {
jniError("jobj:%p, taos:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields); jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields);
return JNI_NUM_OF_FIELDS_0; return JNI_NUM_OF_FIELDS_0;
} else { } else {
jniTrace("jobj:%p, taos:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields); jniTrace("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields);
for (int i = 0; i < num_fields; ++i) { for (int i = 0; i < num_fields; ++i) {
jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp); jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp);
(*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type); (*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type);
@ -402,7 +419,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
TAOS_RES *result = (TAOS_RES *)res; TAOS_RES *result = (TAOS_RES *)res;
if (result == NULL) { if (result == NULL) {
jniError("jobj:%p, taos:%p, resultset is null", jobj, tscon); jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon);
return JNI_RESULT_SET_NULL; return JNI_RESULT_SET_NULL;
} }
@ -410,7 +427,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
int num_fields = taos_num_fields(result); int num_fields = taos_num_fields(result);
if (num_fields == 0) { if (num_fields == 0) {
jniError("jobj:%p, taos:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields); jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields);
return JNI_NUM_OF_FIELDS_0; return JNI_NUM_OF_FIELDS_0;
} }
@ -418,10 +435,10 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
if (row == NULL) { if (row == NULL) {
int tserrno = taos_errno(tscon); int tserrno = taos_errno(tscon);
if (tserrno == 0) { if (tserrno == 0) {
jniTrace("jobj:%p, taos:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, res, num_fields); jniTrace("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, res, num_fields);
return JNI_FETCH_END; return JNI_FETCH_END;
} else { } else {
jniTrace("jobj:%p, taos:%p, interruptted query", jobj, tscon); jniTrace("jobj:%p, conn:%p, interruptted query", jobj, tscon);
return JNI_RESULT_SET_NULL; return JNI_RESULT_SET_NULL;
} }
} }
@ -482,10 +499,10 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionIm
jlong con) { jlong con) {
TAOS *tscon = (TAOS *)con; TAOS *tscon = (TAOS *)con;
if (tscon == NULL) { if (tscon == NULL) {
jniError("jobj:%p, connection is closed", jobj); jniError("jobj:%p, connection is already closed", jobj);
return JNI_CONNECTION_NULL; return JNI_CONNECTION_NULL;
} else { } else {
jniTrace("jobj:%p, taos:%p, close connection success", jobj, tscon); jniTrace("jobj:%p, conn:%p, close connection success", jobj, tscon);
taos_close(tscon); taos_close(tscon);
return JNI_SUCCESS; return JNI_SUCCESS;
} }
@ -640,7 +657,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab
} }
if (jsql == NULL) { if (jsql == NULL) {
jniError("jobj:%p, taos:%p, sql is null", jobj, tscon); jniError("jobj:%p, conn:%p, sql is null", jobj, tscon);
return JNI_SQL_NULL; return JNI_SQL_NULL;
} }
@ -661,4 +678,4 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab
JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(JNIEnv *env, jobject jobj) { JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(JNIEnv *env, jobject jobj) {
return (*env)->NewStringUTF(env, (const char *)tsCharset); return (*env)->NewStringUTF(env, (const char *)tsCharset);
} }

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include "os.h" #include "os.h"
#include "taosmsg.h" #include "taosmsg.h"
#include "tast.h" #include "tast.h"
@ -27,8 +21,12 @@
#include "tschemautil.h" #include "tschemautil.h"
#include "tsdb.h" #include "tsdb.h"
#include "tskiplist.h" #include "tskiplist.h"
#include "tsqldef.h"
#include "tsqlfunction.h" #include "tsqlfunction.h"
#include "tstoken.h"
#include "ttypes.h"
#include "tutil.h" #include "tutil.h"
#include "tscSQLParser.h"
/* /*
* *
@ -43,10 +41,10 @@
*/ */
static tSQLSyntaxNode *tSQLSyntaxNodeCreate(SSchema *pSchema, int32_t numOfCols, SSQLToken *pToken); static tSQLSyntaxNode *tSQLSyntaxNodeCreate(SSchema *pSchema, int32_t numOfCols, SSQLToken *pToken);
static void tSQLSyntaxNodeDestroy(tSQLSyntaxNode *pNode, void (*fp)(void *)); static void tSQLSyntaxNodeDestroy(tSQLSyntaxNode *pNode, void (*fp)(void *));
static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *str, int32_t *i); static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *str, int32_t *i);
static void destroySyntaxTree(tSQLSyntaxNode *); static void destroySyntaxTree(tSQLSyntaxNode *);
static uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tSQLSyntaxNode *pLeft, static uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tSQLSyntaxNode *pLeft,
const tSQLSyntaxNode *pRight); const tSQLSyntaxNode *pRight);
@ -110,11 +108,11 @@ static tSQLSyntaxNode *tSQLSyntaxNodeCreate(SSchema *pSchema, int32_t numOfCols,
return NULL; return NULL;
} }
int32_t i = 0;
size_t nodeSize = sizeof(tSQLSyntaxNode); size_t nodeSize = sizeof(tSQLSyntaxNode);
tSQLSyntaxNode *pNode = NULL; tSQLSyntaxNode *pNode = NULL;
if (pToken->type == TK_ID || pToken->type == TK_TBNAME) { if (pToken->type == TK_ID || pToken->type == TK_TBNAME) {
int32_t i = 0;
if (pToken->type == TK_ID) { if (pToken->type == TK_ID) {
do { do {
size_t len = strlen(pSchema[i].name); size_t len = strlen(pSchema[i].name);
@ -261,8 +259,7 @@ static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, cha
t0 = tStrGetToken(str, i, false, 0, NULL); t0 = tStrGetToken(str, i, false, 0, NULL);
if (t0.n == 0 || t0.type == TK_RP) { if (t0.n == 0 || t0.type == TK_RP) {
if (pLeft->nodeType != TSQL_NODE_EXPR) { if (pLeft->nodeType != TSQL_NODE_EXPR) { // if left is not the expr, it is not a legal expr
// if left is not the expr, it is not a legal expr
tSQLSyntaxNodeDestroy(pLeft, NULL); tSQLSyntaxNodeDestroy(pLeft, NULL);
return NULL; return NULL;
} }
@ -271,8 +268,8 @@ static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, cha
} }
// get the operator of expr // get the operator of expr
uint8_t optr = getBinaryExprOptr(&t0); uint8_t optr = getBinaryExprOptr(&t0);
if (optr <= 0) { if (optr == 0) {
pError("not support binary operator:%d", t0.type); pError("not support binary operator:%d", t0.type);
tSQLSyntaxNodeDestroy(pLeft, NULL); tSQLSyntaxNodeDestroy(pLeft, NULL);
return NULL; return NULL;
@ -326,13 +323,14 @@ static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, cha
pn->colId = -1; pn->colId = -1;
return pn; return pn;
} else { } else {
int32_t optr = getBinaryExprOptr(&t0); uint8_t localOptr = getBinaryExprOptr(&t0);
if (optr <= 0) { if (localOptr == 0) {
pError("not support binary operator:%d", t0.type); pError("not support binary operator:%d", t0.type);
free(pBinExpr);
return NULL; return NULL;
} }
return parseRemainStr(str, pBinExpr, pSchema, optr, numOfCols, i); return parseRemainStr(str, pBinExpr, pSchema, localOptr, numOfCols, i);
} }
} }
@ -421,16 +419,17 @@ void tSQLBinaryExprToString(tSQLBinaryExpr *pExpr, char *dst, int32_t *len) {
if (pExpr == NULL) { if (pExpr == NULL) {
*dst = 0; *dst = 0;
*len = 0; *len = 0;
return;
} }
int32_t lhs = tSQLBinaryExprToStringImpl(pExpr->pLeft, dst, pExpr->pLeft->nodeType); int32_t lhs = tSQLBinaryExprToStringImpl(pExpr->pLeft, dst, pExpr->pLeft->nodeType);
dst += lhs; dst += lhs;
*len = lhs; *len = lhs;
char *start = tSQLOptrToString(pExpr->nSQLBinaryOptr, dst); char *start = tSQLOptrToString(pExpr->nSQLBinaryOptr, dst);
*len += (start - dst); *len += (start - dst);
*len += tSQLBinaryExprToStringImpl(pExpr->pRight, start, pExpr->pRight->nodeType); *len += tSQLBinaryExprToStringImpl(pExpr->pRight, start, pExpr->pRight->nodeType);
} }
static void UNUSED_FUNC destroySyntaxTree(tSQLSyntaxNode *pNode) { tSQLSyntaxNodeDestroy(pNode, NULL); } static void UNUSED_FUNC destroySyntaxTree(tSQLSyntaxNode *pNode) { tSQLSyntaxNodeDestroy(pNode, NULL); }
@ -644,16 +643,15 @@ int32_t intersect(tQueryResultset *pLeft, tQueryResultset *pRight, tQueryResults
} }
/* /*
* * traverse the result and apply the function to each item to check if the item is qualified or not
*/ */
void tSQLListTraverseOnResult(struct tSQLBinaryExpr *pExpr, bool (*fp)(tSkipListNode *, void *), static void tSQLListTraverseOnResult(struct tSQLBinaryExpr *pExpr, __result_filter_fn_t fp, tQueryResultset *pResult) {
tQueryResultset * pResult) {
assert(pExpr->pLeft->nodeType == TSQL_NODE_COL && pExpr->pRight->nodeType == TSQL_NODE_VALUE); assert(pExpr->pLeft->nodeType == TSQL_NODE_COL && pExpr->pRight->nodeType == TSQL_NODE_VALUE);
// brutal force search // brutal force scan the result list and check for each item in the list
int64_t num = pResult->num; int64_t num = pResult->num;
for (int32_t i = 0, j = 0; i < pResult->num; ++i) { for (int32_t i = 0, j = 0; i < pResult->num; ++i) {
if (fp == NULL || (fp != NULL && fp(pResult->pRes[i], pExpr->info) == true)) { if (fp == NULL || (fp(pResult->pRes[i], pExpr->info) == true)) {
pResult->pRes[j++] = pResult->pRes[i]; pResult->pRes[j++] = pResult->pRes[i];
} else { } else {
num--; num--;
@ -936,4 +934,4 @@ void tQueryResultClean(tQueryResultset *pRes) {
tfree(pRes->pRes); tfree(pRes->pRes);
pRes->num = 0; pRes->num = 0;
} }

View File

@ -13,8 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #include "os.h"
#include <stdlib.h>
#include "tlog.h" #include "tlog.h"
#include "trpc.h" #include "trpc.h"
@ -23,8 +22,9 @@
#include "tscUtil.h" #include "tscUtil.h"
#include "tsclient.h" #include "tsclient.h"
#include "tsocket.h" #include "tsocket.h"
#include "tsql.h" #include "tscSQLParser.h"
#include "tutil.h" #include "tutil.h"
#include "tnote.h"
void tscProcessFetchRow(SSchedMsg *pMsg); void tscProcessFetchRow(SSchedMsg *pMsg);
void tscProcessAsyncRetrieve(void *param, TAOS_RES *tres, int numOfRows); void tscProcessAsyncRetrieve(void *param, TAOS_RES *tres, int numOfRows);
@ -40,6 +40,7 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
*/ */
static void tscProcessAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOfRows); static void tscProcessAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOfRows);
// TODO return the correct error code to client in tscQueueAsyncError
void taos_query_a(TAOS *taos, const char *sqlstr, void (*fp)(void *, TAOS_RES *, int), void *param) { void taos_query_a(TAOS *taos, const char *sqlstr, void (*fp)(void *, TAOS_RES *, int), void *param) {
STscObj *pObj = (STscObj *)taos; STscObj *pObj = (STscObj *)taos;
if (pObj == NULL || pObj->signature != pObj) { if (pObj == NULL || pObj->signature != pObj) {
@ -50,20 +51,21 @@ void taos_query_a(TAOS *taos, const char *sqlstr, void (*fp)(void *, TAOS_RES *,
} }
int32_t sqlLen = strlen(sqlstr); int32_t sqlLen = strlen(sqlstr);
if (sqlLen > TSDB_MAX_SQL_LEN) { if (sqlLen > tsMaxSQLStringLen) {
tscError("sql string too long"); tscError("sql string too long");
tscQueueAsyncError(fp, param); tscQueueAsyncError(fp, param);
return; return;
} }
SSqlObj *pSql = (SSqlObj *)malloc(sizeof(SSqlObj)); taosNotePrintTsc(sqlstr);
SSqlObj *pSql = (SSqlObj *)calloc(1, sizeof(SSqlObj));
if (pSql == NULL) { if (pSql == NULL) {
tscError("failed to malloc sqlObj"); tscError("failed to malloc sqlObj");
tscQueueAsyncError(fp, param); tscQueueAsyncError(fp, param);
return; return;
} }
memset(pSql, 0, sizeof(SSqlObj));
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
@ -119,7 +121,8 @@ static void tscProcessAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOf
// sequentially retrieve data from remain vnodes first, query vnode specified by vnodeIdx // sequentially retrieve data from remain vnodes first, query vnode specified by vnodeIdx
if (numOfRows == 0 && tscProjectionQueryOnMetric(pCmd)) { if (numOfRows == 0 && tscProjectionQueryOnMetric(pCmd)) {
// vnode is denoted by vnodeIdx, continue to query vnode specified by vnodeIdx // vnode is denoted by vnodeIdx, continue to query vnode specified by vnodeIdx
assert(pCmd->vnodeIdx >= 0); SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
assert(pMeterMetaInfo->vnodeIndex >= 0);
/* reach the maximum number of output rows, abort */ /* reach the maximum number of output rows, abort */
if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) { if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) {
@ -131,8 +134,8 @@ static void tscProcessAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOf
pCmd->limit.limit = pCmd->globalLimit - pRes->numOfTotal; pCmd->limit.limit = pCmd->globalLimit - pRes->numOfTotal;
pCmd->limit.offset = pRes->offset; pCmd->limit.offset = pRes->offset;
if ((++(pCmd->vnodeIdx)) < tscGetMeterMetaInfo(pCmd, 0)->pMetricMeta->numOfVnodes) { if ((++(pMeterMetaInfo->vnodeIndex)) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
tscTrace("%p retrieve data from next vnode:%d", pSql, pCmd->vnodeIdx); tscTrace("%p retrieve data from next vnode:%d", pSql, pMeterMetaInfo->vnodeIndex);
pSql->cmd.command = TSDB_SQL_SELECT; // reset flag to launch query first. pSql->cmd.command = TSDB_SQL_SELECT; // reset flag to launch query first.
@ -155,7 +158,6 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
SSqlObj *pSql = (SSqlObj *)tres; SSqlObj *pSql = (SSqlObj *)tres;
if (pSql == NULL) { // error if (pSql == NULL) { // error
tscError("sql object is NULL"); tscError("sql object is NULL");
tscQueueAsyncError(pSql->fetchFp, param);
return; return;
} }
@ -270,7 +272,8 @@ void tscProcessAsyncRetrieve(void *param, TAOS_RES *tres, int numOfRows) {
/* /*
* vnode is denoted by vnodeIdx, continue to query vnode specified by vnodeIdx till all vnode have been retrieved * vnode is denoted by vnodeIdx, continue to query vnode specified by vnodeIdx till all vnode have been retrieved
*/ */
assert(pCmd->vnodeIdx >= 1); SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
assert(pMeterMetaInfo->vnodeIndex >= 0);
/* reach the maximum number of output rows, abort */ /* reach the maximum number of output rows, abort */
if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) { if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) {
@ -281,7 +284,7 @@ void tscProcessAsyncRetrieve(void *param, TAOS_RES *tres, int numOfRows) {
/* update the limit value according to current retrieval results */ /* update the limit value according to current retrieval results */
pCmd->limit.limit = pCmd->globalLimit - pRes->numOfTotal; pCmd->limit.limit = pCmd->globalLimit - pRes->numOfTotal;
if ((++pCmd->vnodeIdx) <= tscGetMeterMetaInfo(pCmd, 0)->pMetricMeta->numOfVnodes) { if ((++pMeterMetaInfo->vnodeIndex) <= pMeterMetaInfo->pMetricMeta->numOfVnodes) {
pSql->cmd.command = TSDB_SQL_SELECT; // reset flag to launch query first. pSql->cmd.command = TSDB_SQL_SELECT; // reset flag to launch query first.
tscResetForNextRetrieve(pRes); tscResetForNextRetrieve(pRes);
@ -402,9 +405,12 @@ void tscAsyncInsertMultiVnodesProxy(void *param, TAOS_RES *tres, int numOfRows)
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
assert(!pCmd->isInsertFromFile && pSql->signature == pSql); assert(!pCmd->isInsertFromFile && pSql->signature == pSql);
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
assert(pCmd->numOfTables == 1);
SDataBlockList *pDataBlocks = pCmd->pDataBlocks; SDataBlockList *pDataBlocks = pCmd->pDataBlocks;
if (pDataBlocks == NULL || pCmd->vnodeIdx >= pDataBlocks->nSize) { if (pDataBlocks == NULL || pMeterMetaInfo->vnodeIndex >= pDataBlocks->nSize) {
// restore user defined fp // restore user defined fp
pSql->fp = pSql->fetchFp; pSql->fp = pSql->fetchFp;
tscTrace("%p Async insertion completed, destroy data block list", pSql); tscTrace("%p Async insertion completed, destroy data block list", pSql);
@ -416,17 +422,17 @@ void tscAsyncInsertMultiVnodesProxy(void *param, TAOS_RES *tres, int numOfRows)
(*pSql->fp)(pSql->param, tres, numOfRows); (*pSql->fp)(pSql->param, tres, numOfRows);
} else { } else {
do { do {
code = tscCopyDataBlockToPayload(pSql, pDataBlocks->pData[pCmd->vnodeIdx++]); code = tscCopyDataBlockToPayload(pSql, pDataBlocks->pData[pMeterMetaInfo->vnodeIndex++]);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
tscTrace("%p prepare submit data block failed in async insertion, vnodeIdx:%d, total:%d, code:%d", tscTrace("%p prepare submit data block failed in async insertion, vnodeIdx:%d, total:%d, code:%d",
pSql, pCmd->vnodeIdx - 1, pDataBlocks->nSize, code); pSql, pMeterMetaInfo->vnodeIndex - 1, pDataBlocks->nSize, code);
} }
} while (code != TSDB_CODE_SUCCESS && pCmd->vnodeIdx < pDataBlocks->nSize); } while (code != TSDB_CODE_SUCCESS && pMeterMetaInfo->vnodeIndex < pDataBlocks->nSize);
// build submit msg may fail // build submit msg may fail
if (code == TSDB_CODE_SUCCESS) { if (code == TSDB_CODE_SUCCESS) {
tscTrace("%p async insertion, vnodeIdx:%d, total:%d", pSql, pCmd->vnodeIdx - 1, pDataBlocks->nSize); tscTrace("%p async insertion, vnodeIdx:%d, total:%d", pSql, pMeterMetaInfo->vnodeIndex - 1, pDataBlocks->nSize);
tscProcessSql(pSql); tscProcessSql(pSql);
} }
} }
@ -482,11 +488,11 @@ void tscMeterMetaCallBack(void *param, TAOS_RES *res, int code) {
// check if it is a sub-query of metric query first, if true, enter another routine // check if it is a sub-query of metric query first, if true, enter another routine
if ((pSql->cmd.type & TSDB_QUERY_TYPE_STABLE_SUBQUERY) == TSDB_QUERY_TYPE_STABLE_SUBQUERY) { if ((pSql->cmd.type & TSDB_QUERY_TYPE_STABLE_SUBQUERY) == TSDB_QUERY_TYPE_STABLE_SUBQUERY) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0); SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
assert(pMeterMetaInfo->pMeterMeta->numOfTags != 0 && pCmd->vnodeIdx >= 0 && pSql->param != NULL); assert(pMeterMetaInfo->pMeterMeta->numOfTags != 0 && pMeterMetaInfo->vnodeIndex >= 0 && pSql->param != NULL);
SRetrieveSupport *trs = (SRetrieveSupport *)pSql->param; SRetrieveSupport *trs = (SRetrieveSupport *)pSql->param;
SSqlObj * pParObj = trs->pParentSqlObj; SSqlObj * pParObj = trs->pParentSqlObj;
assert(pParObj->signature == pParObj && trs->vnodeIdx == pCmd->vnodeIdx && assert(pParObj->signature == pParObj && trs->subqueryIndex == pMeterMetaInfo->vnodeIndex &&
pMeterMetaInfo->pMeterMeta->numOfTags != 0); pMeterMetaInfo->pMeterMeta->numOfTags != 0);
tscTrace("%p get metricMeta during metric query successfully", pSql); tscTrace("%p get metricMeta during metric query successfully", pSql);

View File

@ -13,14 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h> #include "os.h"
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tglobalcfg.h" #include "tglobalcfg.h"
#include "tlog.h" #include "tlog.h"
@ -32,7 +25,7 @@
typedef struct _c_hash_t { typedef struct _c_hash_t {
uint32_t ip; uint32_t ip;
short port; uint16_t port;
struct _c_hash_t *prev; struct _c_hash_t *prev;
struct _c_hash_t *next; struct _c_hash_t *next;
void * data; void * data;
@ -52,14 +45,14 @@ typedef struct {
void *pTimer; void *pTimer;
} SConnCache; } SConnCache;
int taosHashConn(void *handle, uint32_t ip, short port, char *user) { int taosHashConn(void *handle, uint32_t ip, uint16_t port, char *user) {
SConnCache *pObj = (SConnCache *)handle; SConnCache *pObj = (SConnCache *)handle;
int hash = 0; int hash = 0;
// size_t user_len = strlen(user); // size_t user_len = strlen(user);
hash = ip >> 16; hash = ip >> 16;
hash += (unsigned short)(ip & 0xFFFF); hash += (unsigned short)(ip & 0xFFFF);
hash += (unsigned short)port; hash += port;
while (*user != '\0') { while (*user != '\0') {
hash += *user; hash += *user;
user++; user++;
@ -81,7 +74,7 @@ void taosRemoveExpiredNodes(SConnCache *pObj, SConnHash *pNode, int hash, uint64
pNext = pNode->next; pNext = pNode->next;
pObj->total--; pObj->total--;
pObj->count[hash]--; pObj->count[hash]--;
tscTrace("%p ip:0x%x:%d:%d:%p removed, connections in cache:%d", pNode->data, pNode->ip, pNode->port, hash, pNode, tscTrace("%p ip:0x%x:%hu:%d:%p removed, connections in cache:%d", pNode->data, pNode->ip, pNode->port, hash, pNode,
pObj->count[hash]); pObj->count[hash]);
taosMemPoolFree(pObj->connHashMemPool, (char *)pNode); taosMemPoolFree(pObj->connHashMemPool, (char *)pNode);
pNode = pNext; pNode = pNext;
@ -93,7 +86,7 @@ void taosRemoveExpiredNodes(SConnCache *pObj, SConnHash *pNode, int hash, uint64
pObj->connHashList[hash] = NULL; pObj->connHashList[hash] = NULL;
} }
void *taosAddConnIntoCache(void *handle, void *data, uint32_t ip, short port, char *user) { void *taosAddConnIntoCache(void *handle, void *data, uint32_t ip, uint16_t port, char *user) {
int hash; int hash;
SConnHash * pNode; SConnHash * pNode;
SConnCache *pObj; SConnCache *pObj;
@ -132,7 +125,7 @@ void *taosAddConnIntoCache(void *handle, void *data, uint32_t ip, short port, ch
pthread_mutex_unlock(&pObj->mutex); pthread_mutex_unlock(&pObj->mutex);
tscTrace("%p ip:0x%x:%d:%d:%p added, connections in cache:%d", data, ip, port, hash, pNode, pObj->count[hash]); tscTrace("%p ip:0x%x:%hu:%d:%p added, connections in cache:%d", data, ip, port, hash, pNode, pObj->count[hash]);
return pObj; return pObj;
} }
@ -159,7 +152,7 @@ void taosCleanConnCache(void *handle, void *tmrId) {
taosTmrReset(taosCleanConnCache, pObj->keepTimer * 2, pObj, pObj->tmrCtrl, &pObj->pTimer); taosTmrReset(taosCleanConnCache, pObj->keepTimer * 2, pObj, pObj->tmrCtrl, &pObj->pTimer);
} }
void *taosGetConnFromCache(void *handle, uint32_t ip, short port, char *user) { void *taosGetConnFromCache(void *handle, uint32_t ip, uint16_t port, char *user) {
int hash; int hash;
SConnHash * pNode; SConnHash * pNode;
SConnCache *pObj; SConnCache *pObj;
@ -208,7 +201,7 @@ void *taosGetConnFromCache(void *handle, uint32_t ip, short port, char *user) {
pthread_mutex_unlock(&pObj->mutex); pthread_mutex_unlock(&pObj->mutex);
if (pData) { if (pData) {
tscTrace("%p ip:0x%x:%d:%d:%p retrieved, connections in cache:%d", pData, ip, port, hash, pNode, pObj->count[hash]); tscTrace("%p ip:0x%x:%hu:%d:%p retrieved, connections in cache:%d", pData, ip, port, hash, pNode, pObj->count[hash]);
} }
return pData; return pData;

File diff suppressed because it is too large Load Diff

View File

@ -13,16 +13,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <tsclient.h>
#include <sys/stat.h>
#include "os.h" #include "os.h"
#include "tcache.h"
#include "tscJoinProcess.h" #include "tscJoinProcess.h"
#include "tcache.h"
#include "tscUtil.h" #include "tscUtil.h"
#include "tsclient.h" #include "tsclient.h"
#include "tscompression.h" #include "tscompression.h"
@ -52,8 +45,8 @@ static bool doCompare(int32_t order, int64_t left, int64_t right) {
} }
} }
static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSubquerySupporter* pSupporter1, SJoinSubquerySupporter* pSupporter2, static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSubquerySupporter* pSupporter1,
TSKEY* st, TSKEY* et) { SJoinSubquerySupporter* pSupporter2, TSKEY* st, TSKEY* et) {
STSBuf* output1 = tsBufCreate(true); STSBuf* output1 = tsBufCreate(true);
STSBuf* output2 = tsBufCreate(true); STSBuf* output2 = tsBufCreate(true);
@ -95,7 +88,7 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSubquerySupporter* pSuppor
#ifdef _DEBUG_VIEW #ifdef _DEBUG_VIEW
// for debug purpose // for debug purpose
tscPrint("%lld, tags:%d \t %lld, tags:%d", elem1.ts, elem1.tag, elem2.ts, elem2.tag); tscPrint("%" PRId64 ", tags:%d \t %" PRId64 ", tags:%d", elem1.ts, elem1.tag, elem2.ts, elem2.tag);
#endif #endif
if (elem1.tag < elem2.tag || (elem1.tag == elem2.tag && doCompare(order, elem1.ts, elem2.ts))) { if (elem1.tag < elem2.tag || (elem1.tag == elem2.tag && doCompare(order, elem1.ts, elem2.ts))) {
@ -157,22 +150,21 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSubquerySupporter* pSuppor
tsBufDestory(pSupporter1->pTSBuf); tsBufDestory(pSupporter1->pTSBuf);
tsBufDestory(pSupporter2->pTSBuf); tsBufDestory(pSupporter2->pTSBuf);
tscTrace("%p input1:%lld, input2:%lld, %lld for secondary query after ts blocks intersecting", tscTrace("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " for secondary query after ts blocks intersecting", pSql,
pSql, numOfInput1, numOfInput2, output1->numOfTotal); numOfInput1, numOfInput2, output1->numOfTotal);
return output1->numOfTotal; return output1->numOfTotal;
} }
//todo handle failed to create sub query // todo handle failed to create sub query
SJoinSubquerySupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState, /*int32_t* numOfComplete, int32_t* gc,*/ int32_t index) { SJoinSubquerySupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState,
/*int32_t* numOfComplete, int32_t* gc,*/ int32_t index) {
SJoinSubquerySupporter* pSupporter = calloc(1, sizeof(SJoinSubquerySupporter)); SJoinSubquerySupporter* pSupporter = calloc(1, sizeof(SJoinSubquerySupporter));
if (pSupporter == NULL) { if (pSupporter == NULL) {
return NULL; return NULL;
} }
pSupporter->pObj = pSql; pSupporter->pObj = pSql;
pSupporter->hasMore = true;
pSupporter->pState = pState; pSupporter->pState = pState;
pSupporter->subqueryIndex = index; pSupporter->subqueryIndex = index;
@ -233,12 +225,6 @@ bool needSecondaryQuery(SSqlObj* pSql) {
* launch secondary stage query to fetch the result that contains timestamp in set * launch secondary stage query to fetch the result that contains timestamp in set
*/ */
int32_t tscLaunchSecondSubquery(SSqlObj* pSql) { int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
// TODO not launch secondary stage query
// if (!needSecondaryQuery(pSql)) {
// return;
// }
// sub query may not be necessary
int32_t numOfSub = 0; int32_t numOfSub = 0;
SJoinSubquerySupporter* pSupporter = NULL; SJoinSubquerySupporter* pSupporter = NULL;
@ -246,15 +232,22 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
pSupporter = pSql->pSubs[i]->param; pSupporter = pSql->pSubs[i]->param;
pSupporter->pState->numOfCompleted = 0; pSupporter->pState->numOfCompleted = 0;
/*
* If the columns are not involved in the final select clause, the secondary query will not be launched
* for the subquery.
*/
if (pSupporter->exprsInfo.numOfExprs > 0) { if (pSupporter->exprsInfo.numOfExprs > 0) {
++numOfSub; ++numOfSub;
} }
} }
// scan all subquery, if one sub query has only ts, ignore it // scan all subquery, if one sub query has only ts, ignore it
int32_t j = 0; tscTrace(
tscTrace("%p start to launch secondary subqueries: %d", pSql, pSql->numOfSubs); "%p start to launch secondary subqueries, total:%d, only:%d needs to query, others are not retrieve in "
"select clause",
pSql, pSql->numOfSubs, numOfSub);
int32_t j = 0;
for (int32_t i = 0; i < pSql->numOfSubs; ++i) { for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SSqlObj* pSub = pSql->pSubs[i]; SSqlObj* pSub = pSql->pSubs[i];
pSupporter = pSub->param; pSupporter = pSub->param;
@ -266,15 +259,14 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
continue; continue;
} }
SSqlObj* pNew = createSubqueryObj(pSql, 0, (int16_t)i, tscJoinQueryCallback, pSupporter, NULL); SSqlObj* pNew = createSubqueryObj(pSql, (int16_t)i, tscJoinQueryCallback, pSupporter, NULL);
if (pNew == NULL) { if (pNew == NULL) {
pSql->numOfSubs = i; //revise the number of subquery pSql->numOfSubs = i; // revise the number of subquery
pSupporter->pState->numOfTotal = i; pSupporter->pState->numOfTotal = i;
pSupporter->pState->code = TSDB_CODE_CLI_OUT_OF_MEMORY; pSupporter->pState->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
tscDestroyJoinSupporter(pSupporter); tscDestroyJoinSupporter(pSupporter);
return 0;
return NULL;
} }
tscFreeSqlCmdData(&pNew->cmd); tscFreeSqlCmdData(&pNew->cmd);
@ -289,7 +281,6 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
pNew->cmd.type |= TSDB_QUERY_TYPE_JOIN_SEC_STAGE; pNew->cmd.type |= TSDB_QUERY_TYPE_JOIN_SEC_STAGE;
pNew->cmd.nAggTimeInterval = pSupporter->interval; pNew->cmd.nAggTimeInterval = pSupporter->interval;
pNew->cmd.limit = pSupporter->limit;
pNew->cmd.groupbyExpr = pSupporter->groupbyExpr; pNew->cmd.groupbyExpr = pSupporter->groupbyExpr;
tscColumnBaseInfoCopy(&pNew->cmd.colList, &pSupporter->colList, 0); tscColumnBaseInfoCopy(&pNew->cmd.colList, &pSupporter->colList, 0);
@ -309,18 +300,27 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pNew->cmd, 0); SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pNew->cmd, 0);
/*
* When handling the projection query, the offset value will be modified for table-table join, which is changed
* during the timestamp intersection.
*/
pSupporter->limit = pSql->cmd.limit;
pNew->cmd.limit = pSupporter->limit;
// fetch the join tag column // fetch the join tag column
if (UTIL_METER_IS_METRIC(pMeterMetaInfo)) { if (UTIL_METER_IS_METRIC(pMeterMetaInfo)) {
SSqlExpr* pExpr = tscSqlExprGet(&pNew->cmd, 0); SSqlExpr* pExpr = tscSqlExprGet(&pNew->cmd, 0);
assert(pNew->cmd.tagCond.joinInfo.hasJoin); assert(pNew->cmd.tagCond.joinInfo.hasJoin);
int16_t tagColIndex = tscGetJoinTagColIndexByUid(&pNew->cmd, pMeterMetaInfo->pMeterMeta->uid); int16_t tagColIndex = tscGetJoinTagColIndexByUid(&pNew->cmd.tagCond, pMeterMetaInfo->pMeterMeta->uid);
pExpr->param[0].i64Key = tagColIndex; pExpr->param[0].i64Key = tagColIndex;
pExpr->numOfParams = 1; pExpr->numOfParams = 1;
addRequiredTagColumn(&pNew->cmd, tagColIndex, 0);
} }
#ifdef _DEBUG_VIEW
tscPrintSelectClause(&pNew->cmd);
#endif
tscProcessSql(pNew); tscProcessSql(pNew);
} }
@ -360,7 +360,7 @@ static void doQuitSubquery(SSqlObj* pParentSql) {
} }
static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSubquerySupporter* pSupporter) { static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSubquerySupporter* pSupporter) {
if (__sync_add_and_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) { if (atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) {
pSqlObj->res.code = abs(pSupporter->pState->code); pSqlObj->res.code = abs(pSupporter->pState->code);
tscError("%p all subquery return and query failed, global code:%d", pSqlObj, pSqlObj->res.code); tscError("%p all subquery return and query failed, global code:%d", pSqlObj, pSqlObj->res.code);
@ -391,9 +391,9 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
return; return;
} }
if (numOfRows > 0) { // write the data into disk if (numOfRows > 0) { // write the data into disk
fwrite(pSql->res.data, pSql->res.numOfRows, 1, pSupporter->f); fwrite(pSql->res.data, pSql->res.numOfRows, 1, pSupporter->f);
fflush(pSupporter->f); fclose(pSupporter->f);
STSBuf* pBuf = tsBufCreateFromFile(pSupporter->path, true); STSBuf* pBuf = tsBufCreateFromFile(pSupporter->path, true);
if (pBuf == NULL) { if (pBuf == NULL) {
@ -408,7 +408,10 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
tscTrace("%p create tmp file for ts block:%s", pSql, pBuf->path); tscTrace("%p create tmp file for ts block:%s", pSql, pBuf->path);
pSupporter->pTSBuf = pBuf; pSupporter->pTSBuf = pBuf;
} else { } else {
tsBufMerge(pSupporter->pTSBuf, pBuf, pSql->cmd.vnodeIdx); assert(pSql->cmd.numOfTables == 1); // for subquery, only one metermetaInfo
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, 0);
tsBufMerge(pSupporter->pTSBuf, pBuf, pMeterMetaInfo->vnodeIndex);
tsBufDestory(pBuf); tsBufDestory(pBuf);
} }
@ -418,12 +421,25 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
pSql->res.row = pSql->res.numOfRows; pSql->res.row = pSql->res.numOfRows;
taos_fetch_rows_a(tres, joinRetrieveCallback, param); taos_fetch_rows_a(tres, joinRetrieveCallback, param);
} else if (numOfRows == 0) { // no data from this vnode anymore } else if (numOfRows == 0) { // no data from this vnode anymore
if (__sync_add_and_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) { if (tscProjectionQueryOnMetric(&pParentSql->cmd)) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, 0);
assert(pSql->cmd.numOfTables == 1);
// for projection query, need to try next vnode
if ((++pMeterMetaInfo->vnodeIndex) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
pSql->cmd.command = TSDB_SQL_SELECT;
pSql->fp = tscJoinQueryCallback;
tscProcessSql(pSql);
return;
}
}
if (atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) {
if (pSupporter->pState->code != TSDB_CODE_SUCCESS) { if (pSupporter->pState->code != TSDB_CODE_SUCCESS) {
tscTrace("%p sub:%p, numOfSub:%d, quit from further procedure due to other queries failure", pParentSql, tres, tscTrace("%p sub:%p, numOfSub:%d, quit from further procedure due to other queries failure", pParentSql, tres,
pSupporter->subqueryIndex); pSupporter->subqueryIndex);
doQuitSubquery(pParentSql); doQuitSubquery(pParentSql);
return; return;
} }
@ -458,8 +474,33 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
tscError("%p retrieve failed, code:%d, index:%d", pSql, numOfRows, pSupporter->subqueryIndex); tscError("%p retrieve failed, code:%d, index:%d", pSql, numOfRows, pSupporter->subqueryIndex);
} }
if (__sync_add_and_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) { if (numOfRows >= 0) {
tscTrace("%p secondary retrieve completed, global code:%d", tres, pParentSql->res.code); pSql->res.numOfTotal += pSql->res.numOfRows;
}
if (tscProjectionQueryOnMetric(&pSql->cmd) && numOfRows == 0) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, 0);
assert(pSql->cmd.numOfTables == 1);
// for projection query, need to try next vnode if current vnode is exhausted
if ((++pMeterMetaInfo->vnodeIndex) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
pSupporter->pState->numOfCompleted = 0;
pSupporter->pState->numOfTotal = 1;
pSql->cmd.command = TSDB_SQL_SELECT;
pSql->fp = tscJoinQueryCallback;
tscProcessSql(pSql);
return;
}
}
if (atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) {
assert(pSupporter->pState->numOfCompleted == pSupporter->pState->numOfTotal);
tscTrace("%p all %d secondary retrieves are completed, global code:%d", tres, pSupporter->pState->numOfTotal,
pParentSql->res.code);
if (pSupporter->pState->code != TSDB_CODE_SUCCESS) { if (pSupporter->pState->code != TSDB_CODE_SUCCESS) {
pParentSql->res.code = abs(pSupporter->pState->code); pParentSql->res.code = abs(pSupporter->pState->code);
freeSubqueryObj(pParentSql); freeSubqueryObj(pParentSql);
@ -473,50 +514,68 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
void tscFetchDatablockFromSubquery(SSqlObj* pSql) { void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
int32_t numOfFetch = 0; int32_t numOfFetch = 0;
assert(pSql->numOfSubs >= 1);
for (int32_t i = 0; i < pSql->numOfSubs; ++i) { for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SJoinSubquerySupporter* pSupporter = (SJoinSubquerySupporter*)pSql->pSubs[i]->param; SSqlRes *pRes = &pSql->pSubs[i]->res;
SSqlCmd *pCmd = &pSql->pSubs[i]->cmd;
SSqlRes* pRes = &pSql->pSubs[i]->res;
if (pRes->row >= pRes->numOfRows && pSupporter->hasMore) { SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
numOfFetch++;
} if (tscProjectionQueryOnMetric(pCmd)) {
} if (pRes->row >= pRes->numOfRows && pMeterMetaInfo->vnodeIndex < pMeterMetaInfo->pMetricMeta->numOfVnodes &&
(!tscHasReachLimitation(pSql->pSubs[i]))) {
if (numOfFetch > 0) { numOfFetch++;
tscTrace("%p retrieve data from %d subqueries", pSql, numOfFetch); }
} else {
SJoinSubquerySupporter* pSupporter = (SJoinSubquerySupporter*)pSql->pSubs[0]->param; if (pRes->row >= pRes->numOfRows && (!tscHasReachLimitation(pSql->pSubs[i]))) {
pSupporter->pState->numOfTotal = numOfFetch; // wait for all subqueries completed numOfFetch++;
pSupporter->pState->numOfCompleted = 0;
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SSqlObj* pSql1 = pSql->pSubs[i];
SSqlRes* pRes1 = &pSql1->res;
SSqlCmd* pCmd1 = &pSql1->cmd;
pSupporter = (SJoinSubquerySupporter*)pSql1->param;
// wait for all subqueries completed
pSupporter->pState->numOfTotal = numOfFetch;
if (pRes1->row >= pRes1->numOfRows && pSupporter->hasMore) {
tscTrace("%p subquery:%p retrieve data from vnode, index:%d", pSql, pSql1, pSupporter->subqueryIndex);
tscResetForNextRetrieve(pRes1);
pSql1->fp = joinRetrieveCallback;
if (pCmd1->command < TSDB_SQL_LOCAL) {
pCmd1->command = (pCmd1->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
}
tscProcessSql(pSql1);
} }
} }
// wait for all subquery completed
tsem_wait(&pSql->rspSem);
} }
if (numOfFetch <= 0) {
return ;
}
// TODO multi-vnode retrieve for projection query with limitation has bugs, since the global limiation is not handled
tscTrace("%p retrieve data from %d subqueries", pSql, numOfFetch);
SJoinSubquerySupporter* pSupporter = (SJoinSubquerySupporter*)pSql->pSubs[0]->param;
pSupporter->pState->numOfTotal = numOfFetch; // wait for all subqueries completed
pSupporter->pState->numOfCompleted = 0;
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SSqlObj* pSql1 = pSql->pSubs[i];
SSqlRes* pRes1 = &pSql1->res;
SSqlCmd* pCmd1 = &pSql1->cmd;
pSupporter = (SJoinSubquerySupporter*)pSql1->param;
// wait for all subqueries completed
pSupporter->pState->numOfTotal = numOfFetch;
assert(pRes1->numOfRows >= 0 && pCmd1->numOfTables == 1);
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd1, 0);
if (pRes1->row >= pRes1->numOfRows) {
tscTrace("%p subquery:%p retrieve data from vnode, subquery:%d, vnodeIndex:%d", pSql, pSql1,
pSupporter->subqueryIndex, pMeterMetaInfo->vnodeIndex);
tscResetForNextRetrieve(pRes1);
pSql1->fp = joinRetrieveCallback;
if (pCmd1->command < TSDB_SQL_LOCAL) {
pCmd1->command = (pCmd1->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
}
tscProcessSql(pSql1);
}
}
// wait for all subquery completed
tsem_wait(&pSql->rspSem);
} }
// all subqueries return, set the result output index // all subqueries return, set the result output index
@ -526,6 +585,10 @@ void tscSetupOutputColumnIndex(SSqlObj* pSql) {
tscTrace("%p all subquery response, retrieve data", pSql); tscTrace("%p all subquery response, retrieve data", pSql);
if (pRes->pColumnIndex != NULL) {
return; // the column transfer support struct has been built
}
pRes->pColumnIndex = calloc(1, sizeof(SColumnIndex) * pCmd->fieldsInfo.numOfOutputCols); pRes->pColumnIndex = calloc(1, sizeof(SColumnIndex) * pCmd->fieldsInfo.numOfOutputCols);
for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) {
@ -567,7 +630,7 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
SJoinSubquerySupporter* pSupporter = (SJoinSubquerySupporter*)param; SJoinSubquerySupporter* pSupporter = (SJoinSubquerySupporter*)param;
// if (__sync_add_and_fetch_32(pSupporter->numOfComplete, 1) >= // if (atomic_add_fetch_32(pSupporter->numOfComplete, 1) >=
// pSupporter->numOfTotal) { // pSupporter->numOfTotal) {
// SSqlObj *pParentObj = pSupporter->pObj; // SSqlObj *pParentObj = pSupporter->pObj;
// //
@ -612,23 +675,38 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
quitAllSubquery(pParentSql, pSupporter); quitAllSubquery(pParentSql, pSupporter);
} else { } else {
if (__sync_add_and_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) { if (atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) {
tscSetupOutputColumnIndex(pParentSql); tscSetupOutputColumnIndex(pParentSql);
if (pParentSql->fp == NULL) { SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, 0);
tsem_wait(&pParentSql->emptyRspSem);
tsem_wait(&pParentSql->emptyRspSem);
tsem_post(&pParentSql->rspSem); /**
} else { * if the query is a continue query (vnodeIndex > 0 for projection query) for next vnode, do the retrieval of
// set the command flag must be after the semaphore been correctly set. * data instead of returning to its invoker
// pPObj->cmd.command = TSDB_SQL_RETRIEVE_METRIC; */
// if (pPObj->res.code == TSDB_CODE_SUCCESS) { if (pMeterMetaInfo->vnodeIndex > 0 && tscProjectionQueryOnMetric(&pSql->cmd)) {
// (*pPObj->fp)(pPObj->param, pPObj, 0); assert(pMeterMetaInfo->vnodeIndex < pMeterMetaInfo->pMetricMeta->numOfVnodes);
// } else { pSupporter->pState->numOfCompleted = 0; // reset the record value
// tscQueueAsyncRes(pPObj);
// } pSql->fp = joinRetrieveCallback; // continue retrieve data
assert(0); pSql->cmd.command = TSDB_SQL_FETCH;
tscProcessSql(pSql);
} else { // first retrieve from vnode during the secondary stage sub-query
if (pParentSql->fp == NULL) {
tsem_wait(&pParentSql->emptyRspSem);
tsem_wait(&pParentSql->emptyRspSem);
tsem_post(&pParentSql->rspSem);
} else {
// set the command flag must be after the semaphore been correctly set.
// pPObj->cmd.command = TSDB_SQL_RETRIEVE_METRIC;
// if (pPObj->res.code == TSDB_CODE_SUCCESS) {
// (*pPObj->fp)(pPObj->param, pPObj, 0);
// } else {
// tscQueueAsyncRes(pPObj);
// }
assert(0);
}
} }
} }
} }
@ -738,8 +816,9 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
strncpy(pTSBuf->path, path, PATH_MAX); strncpy(pTSBuf->path, path, PATH_MAX);
pTSBuf->f = fopen(pTSBuf->path, "r"); pTSBuf->f = fopen(pTSBuf->path, "r+");
if (pTSBuf->f == NULL) { if (pTSBuf->f == NULL) {
free(pTSBuf);
return NULL; return NULL;
} }
@ -781,7 +860,8 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
size_t infoSize = sizeof(STSVnodeBlockInfo) * pTSBuf->numOfVnodes; size_t infoSize = sizeof(STSVnodeBlockInfo) * pTSBuf->numOfVnodes;
STSVnodeBlockInfo* buf = (STSVnodeBlockInfo*)calloc(1, infoSize); STSVnodeBlockInfo* buf = (STSVnodeBlockInfo*)calloc(1, infoSize);
int64_t pos = ftell(pTSBuf->f);
//int64_t pos = ftell(pTSBuf->f); //pos not used
fread(buf, infoSize, 1, pTSBuf->f); fread(buf, infoSize, 1, pTSBuf->f);
// the length value for each vnode is not kept in file, so does not set the length value // the length value for each vnode is not kept in file, so does not set the length value
@ -797,13 +877,17 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
struct stat fileStat; struct stat fileStat;
fstat(fileno(pTSBuf->f), &fileStat); fstat(fileno(pTSBuf->f), &fileStat);
pTSBuf->fileSize = (uint32_t) fileStat.st_size; pTSBuf->fileSize = (uint32_t)fileStat.st_size;
tsBufResetPos(pTSBuf); tsBufResetPos(pTSBuf);
// ascending by default // ascending by default
pTSBuf->cur.order = TSQL_SO_ASC; pTSBuf->cur.order = TSQL_SO_ASC;
pTSBuf->autoDelete = autoDelete; pTSBuf->autoDelete = autoDelete;
tscTrace("create tsBuf from file:%s, fd:%d, size:%d, numOfVnode:%d, autoDelete:%d", pTSBuf->path, fileno(pTSBuf->f),
pTSBuf->fileSize, pTSBuf->numOfVnodes, pTSBuf->autoDelete);
return pTSBuf; return pTSBuf;
} }
@ -821,12 +905,22 @@ void tsBufDestory(STSBuf* pTSBuf) {
fclose(pTSBuf->f); fclose(pTSBuf->f);
if (pTSBuf->autoDelete) { if (pTSBuf->autoDelete) {
tscTrace("tsBuf %p destroyed, delete tmp file:%s", pTSBuf, pTSBuf->path);
unlink(pTSBuf->path); unlink(pTSBuf->path);
} else {
tscTrace("tsBuf %p destroyed, tmp file:%s, remains", pTSBuf, pTSBuf->path);
} }
free(pTSBuf); free(pTSBuf);
} }
static STSVnodeBlockInfoEx* tsBufGetLastVnodeInfo(STSBuf* pTSBuf) {
int32_t last = pTSBuf->numOfVnodes - 1;
assert(last >= 0);
return &pTSBuf->pData[last];
}
static STSVnodeBlockInfoEx* addOneVnodeInfo(STSBuf* pTSBuf, int32_t vnodeId) { static STSVnodeBlockInfoEx* addOneVnodeInfo(STSBuf* pTSBuf, int32_t vnodeId) {
if (pTSBuf->numOfAlloc <= pTSBuf->numOfVnodes) { if (pTSBuf->numOfAlloc <= pTSBuf->numOfVnodes) {
uint32_t newSize = (uint32_t)(pTSBuf->numOfAlloc * 1.5); uint32_t newSize = (uint32_t)(pTSBuf->numOfAlloc * 1.5);
@ -843,10 +937,10 @@ static STSVnodeBlockInfoEx* addOneVnodeInfo(STSBuf* pTSBuf, int32_t vnodeId) {
} }
if (pTSBuf->numOfVnodes > 0) { if (pTSBuf->numOfVnodes > 0) {
STSVnodeBlockInfo* pPrevBlockInfo = &pTSBuf->pData[pTSBuf->numOfVnodes - 1].info; STSVnodeBlockInfoEx* pPrevBlockInfoEx = tsBufGetLastVnodeInfo(pTSBuf);
// update prev vnode length info in file // update prev vnode length info in file
TSBufUpdateVnodeInfo(pTSBuf, pTSBuf->numOfVnodes - 1, pPrevBlockInfo); TSBufUpdateVnodeInfo(pTSBuf, pTSBuf->numOfVnodes - 1, &pPrevBlockInfoEx->info);
} }
// set initial value for vnode block // set initial value for vnode block
@ -864,9 +958,9 @@ static STSVnodeBlockInfoEx* addOneVnodeInfo(STSBuf* pTSBuf, int32_t vnodeId) {
// update the header info // update the header info
STSBufFileHeader header = { STSBufFileHeader header = {
.magic = TS_COMP_FILE_MAGIC, .numOfVnode = pTSBuf->numOfVnodes, .tsOrder = pTSBuf->tsOrder}; .magic = TS_COMP_FILE_MAGIC, .numOfVnode = pTSBuf->numOfVnodes, .tsOrder = pTSBuf->tsOrder};
STSBufUpdateHeader(pTSBuf, &header);
return &pTSBuf->pData[pTSBuf->numOfVnodes - 1]; STSBufUpdateHeader(pTSBuf, &header);
return tsBufGetLastVnodeInfo(pTSBuf);
} }
static void shrinkBuffer(STSList* ptsData) { static void shrinkBuffer(STSList* ptsData) {
@ -913,8 +1007,10 @@ static void writeDataToDisk(STSBuf* pTSBuf) {
pTSBuf->tsData.len = 0; pTSBuf->tsData.len = 0;
pTSBuf->pData[pTSBuf->numOfVnodes - 1].info.compLen += blockSize; STSVnodeBlockInfoEx* pVnodeBlockInfoEx = tsBufGetLastVnodeInfo(pTSBuf);
pTSBuf->pData[pTSBuf->numOfVnodes - 1].info.numOfBlocks += 1;
pVnodeBlockInfoEx->info.compLen += blockSize;
pVnodeBlockInfoEx->info.numOfBlocks += 1;
shrinkBuffer(&pTSBuf->tsData); shrinkBuffer(&pTSBuf->tsData);
} }
@ -1015,13 +1111,13 @@ void tsBufAppend(STSBuf* pTSBuf, int32_t vnodeId, int64_t tag, const char* pData
STSVnodeBlockInfoEx* pBlockInfo = NULL; STSVnodeBlockInfoEx* pBlockInfo = NULL;
STSList* ptsData = &pTSBuf->tsData; STSList* ptsData = &pTSBuf->tsData;
if (pTSBuf->numOfVnodes == 0 || pTSBuf->pData[pTSBuf->numOfVnodes - 1].info.vnode != vnodeId) { if (pTSBuf->numOfVnodes == 0 || tsBufGetLastVnodeInfo(pTSBuf)->info.vnode != vnodeId) {
writeDataToDisk(pTSBuf); writeDataToDisk(pTSBuf);
shrinkBuffer(ptsData); shrinkBuffer(ptsData);
pBlockInfo = addOneVnodeInfo(pTSBuf, vnodeId); pBlockInfo = addOneVnodeInfo(pTSBuf, vnodeId);
} else { } else {
pBlockInfo = &pTSBuf->pData[pTSBuf->numOfVnodes - 1]; pBlockInfo = tsBufGetLastVnodeInfo(pTSBuf);
} }
assert(pBlockInfo->info.vnode == vnodeId); assert(pBlockInfo->info.vnode == vnodeId);
@ -1044,6 +1140,8 @@ void tsBufAppend(STSBuf* pTSBuf, int32_t vnodeId, int64_t tag, const char* pData
pTSBuf->numOfTotal += len / TSDB_KEYSIZE; pTSBuf->numOfTotal += len / TSDB_KEYSIZE;
// the size of raw data exceeds the size of the default prepared buffer, so
// during getBufBlock, the output buffer needs to be large enough.
if (ptsData->len >= ptsData->threshold) { if (ptsData->len >= ptsData->threshold) {
writeDataToDisk(pTSBuf); writeDataToDisk(pTSBuf);
shrinkBuffer(ptsData); shrinkBuffer(ptsData);
@ -1060,10 +1158,10 @@ void tsBufFlush(STSBuf* pTSBuf) {
writeDataToDisk(pTSBuf); writeDataToDisk(pTSBuf);
shrinkBuffer(&pTSBuf->tsData); shrinkBuffer(&pTSBuf->tsData);
STSVnodeBlockInfo* pBlockInfo = &pTSBuf->pData[pTSBuf->numOfVnodes - 1].info; STSVnodeBlockInfoEx* pBlockInfoEx = tsBufGetLastVnodeInfo(pTSBuf);
// update prev vnode length info in file // update prev vnode length info in file
TSBufUpdateVnodeInfo(pTSBuf, pTSBuf->numOfVnodes - 1, pBlockInfo); TSBufUpdateVnodeInfo(pTSBuf, pTSBuf->numOfVnodes - 1, &pBlockInfoEx->info);
// save the ts order into header // save the ts order into header
STSBufFileHeader header = { STSBufFileHeader header = {
@ -1164,11 +1262,22 @@ static void tsBufGetBlock(STSBuf* pTSBuf, int32_t vnodeIndex, int32_t blockIndex
} }
STSBlock* pBlock = &pTSBuf->block; STSBlock* pBlock = &pTSBuf->block;
size_t s = pBlock->numOfElem * TSDB_KEYSIZE;
/*
* In order to accommodate all the qualified data, the actual buffer size for one block with identical tags value
* may exceed the maximum allowed size during *tsBufAppend* function by invoking expandBuffer function
*/
if (s > pTSBuf->tsData.allocSize) {
expandBuffer(&pTSBuf->tsData, s);
}
pTSBuf->tsData.len = pTSBuf->tsData.len =
tsDecompressTimestamp(pBlock->payload, pBlock->compLen, pBlock->numOfElem, pTSBuf->tsData.rawBuf, tsDecompressTimestamp(pBlock->payload, pBlock->compLen, pBlock->numOfElem, pTSBuf->tsData.rawBuf,
pTSBuf->tsData.allocSize, TWO_STAGE_COMP, pTSBuf->assistBuf, pTSBuf->bufSize); pTSBuf->tsData.allocSize, TWO_STAGE_COMP, pTSBuf->assistBuf, pTSBuf->bufSize);
assert(pTSBuf->tsData.len / TSDB_KEYSIZE == pBlock->numOfElem); assert((pTSBuf->tsData.len / TSDB_KEYSIZE == pBlock->numOfElem) && (pTSBuf->tsData.allocSize >= pTSBuf->tsData.len));
pCur->vnodeIndex = vnodeIndex; pCur->vnodeIndex = vnodeIndex;
pCur->blockIndex = blockIndex; pCur->blockIndex = blockIndex;
@ -1210,15 +1319,19 @@ bool tsBufNextPos(STSBuf* pTSBuf) {
if (pCur->vnodeIndex == -1) { if (pCur->vnodeIndex == -1) {
if (pCur->order == TSQL_SO_ASC) { if (pCur->order == TSQL_SO_ASC) {
tsBufGetBlock(pTSBuf, 0, 0); tsBufGetBlock(pTSBuf, 0, 0);
// list is empty
if (pTSBuf->block.numOfElem == 0) { if (pTSBuf->block.numOfElem == 0) { // the whole list is empty, return
tsBufResetPos(pTSBuf); tsBufResetPos(pTSBuf);
return false; return false;
} else { } else {
return true; return true;
} }
} else {
} else { // get the last timestamp record in the last block of the last vnode
assert(pTSBuf->numOfVnodes > 0);
int32_t vnodeIndex = pTSBuf->numOfVnodes - 1; int32_t vnodeIndex = pTSBuf->numOfVnodes - 1;
pCur->vnodeIndex = vnodeIndex;
int32_t vnodeId = pTSBuf->pData[pCur->vnodeIndex].info.vnode; int32_t vnodeId = pTSBuf->pData[pCur->vnodeIndex].info.vnode;
STSVnodeBlockInfo* pBlockInfo = tsBufGetVnodeBlockInfo(pTSBuf, vnodeId); STSVnodeBlockInfo* pBlockInfo = tsBufGetVnodeBlockInfo(pTSBuf, vnodeId);
@ -1253,6 +1366,10 @@ bool tsBufNextPos(STSBuf* pTSBuf) {
pCur->vnodeIndex = -1; pCur->vnodeIndex = -1;
return false; return false;
} }
if (pBlockInfo == NULL) {
return false;
}
int32_t blockIndex = pCur->order == TSQL_SO_ASC ? 0 : pBlockInfo->numOfBlocks - 1; int32_t blockIndex = pCur->order == TSQL_SO_ASC ? 0 : pBlockInfo->numOfBlocks - 1;
tsBufGetBlock(pTSBuf, pCur->vnodeIndex + step, blockIndex); tsBufGetBlock(pTSBuf, pCur->vnodeIndex + step, blockIndex);
@ -1321,7 +1438,7 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf, int32_t vnodeId) {
tsBufFlush(pDestBuf); tsBufFlush(pDestBuf);
// compared with the last vnode id // compared with the last vnode id
if (vnodeId != pDestBuf->pData[pDestBuf->numOfVnodes - 1].info.vnode) { if (vnodeId != tsBufGetLastVnodeInfo(pDestBuf)->info.vnode) {
int32_t oldSize = pDestBuf->numOfVnodes; int32_t oldSize = pDestBuf->numOfVnodes;
int32_t newSize = oldSize + pSrcBuf->numOfVnodes; int32_t newSize = oldSize + pSrcBuf->numOfVnodes;
@ -1348,36 +1465,49 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf, int32_t vnodeId) {
pDestBuf->numOfVnodes = newSize; pDestBuf->numOfVnodes = newSize;
} else { } else {
STSVnodeBlockInfoEx* pBlockInfoEx = &pDestBuf->pData[pDestBuf->numOfVnodes - 1]; STSVnodeBlockInfoEx* pBlockInfoEx = tsBufGetLastVnodeInfo(pDestBuf);
pBlockInfoEx->len += pSrcBuf->pData[0].len; pBlockInfoEx->len += pSrcBuf->pData[0].len;
pBlockInfoEx->info.numOfBlocks += pSrcBuf->pData[0].info.numOfBlocks; pBlockInfoEx->info.numOfBlocks += pSrcBuf->pData[0].info.numOfBlocks;
pBlockInfoEx->info.compLen += pSrcBuf->pData[0].info.compLen; pBlockInfoEx->info.compLen += pSrcBuf->pData[0].info.compLen;
pBlockInfoEx->info.vnode = vnodeId; pBlockInfoEx->info.vnode = vnodeId;
} }
int64_t r = fseek(pDestBuf->f, 0, SEEK_END); int32_t r = fseek(pDestBuf->f, 0, SEEK_END);
assert(r == 0); assert(r == 0);
int64_t offset = getDataStartOffset(); int64_t offset = getDataStartOffset();
int32_t size = pSrcBuf->fileSize - offset; int32_t size = pSrcBuf->fileSize - offset;
#ifdef LINUX #ifdef LINUX
ssize_t rc = sendfile(fileno(pDestBuf->f), fileno(pSrcBuf->f), &offset, size); ssize_t rc = tsendfile(fileno(pDestBuf->f), fileno(pSrcBuf->f), &offset, size);
#else #else
ssize_t rc = fsendfile(pDestBuf->f, pSrcBuf->f, &offset, size); ssize_t rc = fsendfile(pDestBuf->f, pSrcBuf->f, &offset, size);
#endif #endif
if (rc == -1) { if (rc == -1) {
printf("%s\n", strerror(errno)); tscError("failed to merge tsBuf from:%s to %s, reason:%s\n", pSrcBuf->path, pDestBuf->path, strerror(errno));
return -1; return -1;
} }
if (rc != size) { if (rc != size) {
printf("%s\n", strerror(errno)); tscError("failed to merge tsBuf from:%s to %s, reason:%s\n", pSrcBuf->path, pDestBuf->path, strerror(errno));
return -1; return -1;
} }
pDestBuf->numOfTotal += pSrcBuf->numOfTotal; pDestBuf->numOfTotal += pSrcBuf->numOfTotal;
int32_t oldSize = pDestBuf->fileSize;
struct stat fileStat;
fstat(fileno(pDestBuf->f), &fileStat);
pDestBuf->fileSize = (uint32_t)fileStat.st_size;
assert(pDestBuf->fileSize == oldSize + size);
tscTrace("tsBuf merge success, %p, path:%s, fd:%d, file size:%d, numOfVnode:%d, autoDelete:%d", pDestBuf,
pDestBuf->path, fileno(pDestBuf->f), pDestBuf->fileSize, pDestBuf->numOfVnodes, pDestBuf->autoDelete);
return 0; return 0;
} }
@ -1394,7 +1524,7 @@ STSBuf* tsBufCreateFromCompBlocks(const char* pData, int32_t numOfBlocks, int32_
TSBufUpdateVnodeInfo(pTSBuf, pTSBuf->numOfVnodes - 1, pBlockInfo); TSBufUpdateVnodeInfo(pTSBuf, pTSBuf->numOfVnodes - 1, pBlockInfo);
fseek(pTSBuf->f, pBlockInfo->offset, SEEK_SET); fseek(pTSBuf->f, pBlockInfo->offset, SEEK_SET);
fwrite((void*) pData, 1, len, pTSBuf->f); fwrite((void*)pData, 1, len, pTSBuf->f);
pTSBuf->fileSize += len; pTSBuf->fileSize += len;
pTSBuf->tsOrder = order; pTSBuf->tsOrder = order;
@ -1488,7 +1618,7 @@ void tsBufDisplay(STSBuf* pTSBuf) {
while (tsBufNextPos(pTSBuf)) { while (tsBufNextPos(pTSBuf)) {
STSElem elem = tsBufGetElem(pTSBuf); STSElem elem = tsBufGetElem(pTSBuf);
printf("%d-%lld-%lld\n", elem.vnode, elem.tag, elem.ts); printf("%d-%" PRId64 "-%" PRId64 "\n", elem.vnode, *(int64_t*) elem.tag, elem.ts);
} }
pTSBuf->cur.order = old; pTSBuf->cur.order = old;

View File

@ -13,9 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include "os.h"
#include <stdio.h>
#include <stdlib.h>
#include "taosmsg.h" #include "taosmsg.h"
#include "tcache.h" #include "tcache.h"
@ -28,7 +26,9 @@
#include "tschemautil.h" #include "tschemautil.h"
#include "tsocket.h" #include "tsocket.h"
static int32_t getToStringLength(char *pData, int32_t length, int32_t type) { static void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnName, size_t valueLength);
static int32_t getToStringLength(const char *pData, int32_t length, int32_t type) {
char buf[512] = {0}; char buf[512] = {0};
int32_t len = 0; int32_t len = 0;
@ -41,7 +41,7 @@ static int32_t getToStringLength(char *pData, int32_t length, int32_t type) {
case TSDB_DATA_TYPE_DOUBLE: { case TSDB_DATA_TYPE_DOUBLE: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
double dv = 0; double dv = 0;
*(int64_t*)(&dv) = *(int64_t*)pData; *(int64_t *)(&dv) = *(int64_t *)pData;
len = sprintf(buf, "%f", dv); len = sprintf(buf, "%f", dv);
#else #else
len = sprintf(buf, "%lf", *(double *)pData); len = sprintf(buf, "%lf", *(double *)pData);
@ -49,12 +49,11 @@ static int32_t getToStringLength(char *pData, int32_t length, int32_t type) {
if (strncasecmp("nan", buf, 3) == 0) { if (strncasecmp("nan", buf, 3) == 0) {
len = 4; len = 4;
} }
} } break;
break;
case TSDB_DATA_TYPE_FLOAT: { case TSDB_DATA_TYPE_FLOAT: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
float fv = 0; float fv = 0;
*(int32_t*)(&fv) = *(int32_t*)pData; *(int32_t *)(&fv) = *(int32_t *)pData;
len = sprintf(buf, "%f", fv); len = sprintf(buf, "%f", fv);
#else #else
len = sprintf(buf, "%f", *(float *)pData); len = sprintf(buf, "%f", *(float *)pData);
@ -62,11 +61,10 @@ static int32_t getToStringLength(char *pData, int32_t length, int32_t type) {
if (strncasecmp("nan", buf, 3) == 0) { if (strncasecmp("nan", buf, 3) == 0) {
len = 4; len = 4;
} }
} } break;
break;
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP:
case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_BIGINT:
len = sprintf(buf, "%lld", *(int64_t *)pData); len = sprintf(buf, "%" PRId64 "", *(int64_t *)pData);
break; break;
case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_BOOL:
len = MAX_BOOL_TYPE_LENGTH; len = MAX_BOOL_TYPE_LENGTH;
@ -205,23 +203,21 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
case TSDB_DATA_TYPE_FLOAT: { case TSDB_DATA_TYPE_FLOAT: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
float fv = 0; float fv = 0;
*(int32_t*)(&fv) = *(int32_t*)pTagValue; *(int32_t *)(&fv) = *(int32_t *)pTagValue;
sprintf(target, "%f", fv); sprintf(target, "%f", fv);
#else #else
sprintf(target, "%f", *(float *)pTagValue); sprintf(target, "%f", *(float *)pTagValue);
#endif #endif
} } break;
break;
case TSDB_DATA_TYPE_DOUBLE: { case TSDB_DATA_TYPE_DOUBLE: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
double dv = 0; double dv = 0;
*(int64_t*)(&dv) = *(int64_t*)pTagValue; *(int64_t *)(&dv) = *(int64_t *)pTagValue;
sprintf(target, "%lf", dv); sprintf(target, "%lf", dv);
#else #else
sprintf(target, "%lf", *(double *)pTagValue); sprintf(target, "%lf", *(double *)pTagValue);
#endif #endif
} } break;
break;
case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_TINYINT:
sprintf(target, "%d", *(int8_t *)pTagValue); sprintf(target, "%d", *(int8_t *)pTagValue);
break; break;
@ -232,7 +228,7 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
sprintf(target, "%d", *(int32_t *)pTagValue); sprintf(target, "%d", *(int32_t *)pTagValue);
break; break;
case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_BIGINT:
sprintf(target, "%lld", *(int64_t *)pTagValue); sprintf(target, "%" PRId64 "", *(int64_t *)pTagValue);
break; break;
case TSDB_DATA_TYPE_BOOL: { case TSDB_DATA_TYPE_BOOL: {
char *val = (*((int8_t *)pTagValue) == 0) ? "false" : "true"; char *val = (*((int8_t *)pTagValue) == 0) ? "false" : "true";
@ -393,6 +389,68 @@ static int tscProcessQueryTags(SSqlObj *pSql) {
} }
} }
static void tscProcessCurrentUser(SSqlObj *pSql) {
SSqlExpr* pExpr = tscSqlExprGet(&pSql->cmd, 0);
tscSetLocalQueryResult(pSql, pSql->pTscObj->user, pExpr->aliasName, TSDB_USER_LEN);
}
static void tscProcessCurrentDB(SSqlObj *pSql) {
char db[TSDB_DB_NAME_LEN + 1] = {0};
extractDBName(pSql->pTscObj->db, db);
// no use db is invoked before.
if (strlen(db) == 0) {
setNull(db, TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN);
}
SSqlExpr* pExpr = tscSqlExprGet(&pSql->cmd, 0);
tscSetLocalQueryResult(pSql, db, pExpr->aliasName, TSDB_DB_NAME_LEN);
}
static void tscProcessServerVer(SSqlObj *pSql) {
const char* v = pSql->pTscObj->sversion;
SSqlExpr* pExpr = tscSqlExprGet(&pSql->cmd, 0);
tscSetLocalQueryResult(pSql, v, pExpr->aliasName, tListLen(pSql->pTscObj->sversion));
}
static void tscProcessClientVer(SSqlObj *pSql) {
SSqlExpr* pExpr = tscSqlExprGet(&pSql->cmd, 0);
tscSetLocalQueryResult(pSql, version, pExpr->aliasName, strlen(version));
}
static void tscProcessServStatus(SSqlObj *pSql) {
STscObj* pObj = pSql->pTscObj;
if (pObj->pHb != NULL) {
if (pObj->pHb->res.code == TSDB_CODE_NETWORK_UNAVAIL) {
pSql->res.code = TSDB_CODE_NETWORK_UNAVAIL;
return;
}
} else {
if (pSql->res.code == TSDB_CODE_NETWORK_UNAVAIL) {
return;
}
}
SSqlExpr* pExpr = tscSqlExprGet(&pSql->cmd, 0);
tscSetLocalQueryResult(pSql, "1", pExpr->aliasName, 2);
}
void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnName, size_t valueLength) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
pCmd->numOfCols = 1;
pCmd->order.order = TSQL_SO_ASC;
tscFieldInfoSetValue(&pCmd->fieldsInfo, 0, TSDB_DATA_TYPE_BINARY, columnName, valueLength);
tscInitResObjForLocalQuery(pSql, 1, valueLength);
TAOS_FIELD *pField = tscFieldInfoGetField(pCmd, 0);
strncpy(pRes->data, val, pField->bytes);
}
int tscProcessLocalCmd(SSqlObj *pSql) { int tscProcessLocalCmd(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
@ -404,13 +462,23 @@ int tscProcessLocalCmd(SSqlObj *pSql) {
pSql->res.code = (uint8_t)tscProcessQueryTags(pSql); pSql->res.code = (uint8_t)tscProcessQueryTags(pSql);
} else if (pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT) { } else if (pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT) {
/* /*
* pass the qhandle check, in order to call partial release function to * set the qhandle to be 1 in order to pass the qhandle check, and to call partial release function to
* free allocated resources and remove the SqlObj from linked list * free allocated resources and remove the SqlObj from sql query linked list
*/ */
pSql->res.qhandle = 0x1; // pass the qhandle check pSql->res.qhandle = 0x1;
pSql->res.numOfRows = 0; pSql->res.numOfRows = 0;
} else if (pCmd->command == TSDB_SQL_RESET_CACHE) { } else if (pCmd->command == TSDB_SQL_RESET_CACHE) {
taosClearDataCache(tscCacheHandle); taosClearDataCache(tscCacheHandle);
} else if (pCmd->command == TSDB_SQL_SERV_VERSION) {
tscProcessServerVer(pSql);
} else if (pCmd->command == TSDB_SQL_CLI_VERSION) {
tscProcessClientVer(pSql);
} else if (pCmd->command == TSDB_SQL_CURRENT_USER) {
tscProcessCurrentUser(pSql);
} else if (pCmd->command == TSDB_SQL_CURRENT_DB) {
tscProcessCurrentDB(pSql);
} else if (pCmd->command == TSDB_SQL_SERV_STATUS) {
tscProcessServStatus(pSql);
} else { } else {
pSql->res.code = TSDB_CODE_INVALID_SQL; pSql->res.code = TSDB_CODE_INVALID_SQL;
tscError("%p not support command:%d", pSql, pCmd->command); tscError("%p not support command:%d", pSql, pCmd->command);

View File

@ -18,25 +18,8 @@
#define _XOPEN_SOURCE #define _XOPEN_SOURCE
#pragma GCC diagnostic ignored "-Woverflow"
#pragma GCC diagnostic ignored "-Wunused-variable"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <assert.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include "ihash.h"
#include "os.h" #include "os.h"
#include "ihash.h"
#include "tscSecondaryMerge.h" #include "tscSecondaryMerge.h"
#include "tscUtil.h" #include "tscUtil.h"
#include "tschemautil.h" #include "tschemautil.h"
@ -48,18 +31,11 @@
#include "tstoken.h" #include "tstoken.h"
#include "ttime.h" #include "ttime.h"
#define INVALID_SQL_RET_MSG(p, ...) \
do { \
sprintf(p, __VA_ARGS__); \
return TSDB_CODE_INVALID_SQL; \
} while (0)
enum { enum {
TSDB_USE_SERVER_TS = 0, TSDB_USE_SERVER_TS = 0,
TSDB_USE_CLI_TS = 1, TSDB_USE_CLI_TS = 1,
}; };
static void setErrMsg(char *msg, const char *sql);
static int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize); static int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize);
static int32_t tscToInteger(SSQLToken *pToken, int64_t *value, char **endPtr) { static int32_t tscToInteger(SSQLToken *pToken, int64_t *value, char **endPtr) {
@ -77,6 +53,7 @@ static int32_t tscToInteger(SSQLToken *pToken, int64_t *value, char **endPtr) {
radix = 2; radix = 2;
} }
errno = 0;
*value = strtoll(pToken->z, endPtr, radix); *value = strtoll(pToken->z, endPtr, radix);
return numType; return numType;
@ -87,13 +64,15 @@ static int32_t tscToDouble(SSQLToken *pToken, double *value, char **endPtr) {
if (TK_ILLEGAL == numType) { if (TK_ILLEGAL == numType) {
return numType; return numType;
} }
errno = 0;
*value = strtod(pToken->z, endPtr); *value = strtod(pToken->z, endPtr);
return numType; return numType;
} }
int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec) { int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec) {
char * token; //char * token; //fang not used
int tokenlen; //int tokenlen; //fang not used
int32_t index = 0; int32_t index = 0;
SSQLToken sToken; SSQLToken sToken;
int64_t interval; int64_t interval;
@ -111,7 +90,7 @@ int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int1
} else { } else {
// strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm); // strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);
if (taosParseTime(pToken->z, time, pToken->n, timePrec) != TSDB_CODE_SUCCESS) { if (taosParseTime(pToken->z, time, pToken->n, timePrec) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL; return tscInvalidSQLErrMsg(error, "invalid timestamp format", pToken->z);
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
@ -136,18 +115,21 @@ int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int1
index = 0; index = 0;
sToken = tStrGetToken(pTokenEnd, &index, false, 0, NULL); sToken = tStrGetToken(pTokenEnd, &index, false, 0, NULL);
pTokenEnd += index; pTokenEnd += index;
if (sToken.type == TK_MINUS || sToken.type == TK_PLUS) { if (sToken.type == TK_MINUS || sToken.type == TK_PLUS) {
index = 0; index = 0;
valueToken = tStrGetToken(pTokenEnd, &index, false, 0, NULL); valueToken = tStrGetToken(pTokenEnd, &index, false, 0, NULL);
pTokenEnd += index; pTokenEnd += index;
if (valueToken.n < 2) { if (valueToken.n < 2) {
strcpy(error, "value is expected"); return tscInvalidSQLErrMsg(error, "value expected in timestamp", sToken.z);
return TSDB_CODE_INVALID_SQL;
} }
if (getTimestampInUsFromStr(valueToken.z, valueToken.n, &interval) != TSDB_CODE_SUCCESS) { if (getTimestampInUsFromStr(valueToken.z, valueToken.n, &interval) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL; return TSDB_CODE_INVALID_SQL;
} }
if (timePrec == TSDB_TIME_PRECISION_MILLI) { if (timePrec == TSDB_TIME_PRECISION_MILLI) {
interval /= 1000; interval /= 1000;
} }
@ -170,8 +152,8 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
int64_t iv; int64_t iv;
int32_t numType; int32_t numType;
char * endptr = NULL; char * endptr = NULL;
errno = 0; // reset global error code errno = 0; // clear the previous existed error information
switch (pSchema->type) { switch (pSchema->type) {
case TSDB_DATA_TYPE_BOOL: { // bool case TSDB_DATA_TYPE_BOOL: { // bool
if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) { if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) {
@ -182,7 +164,7 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} else if (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0) { } else if (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0) {
*(uint8_t *)payload = TSDB_DATA_BOOL_NULL; *(uint8_t *)payload = TSDB_DATA_BOOL_NULL;
} else { } else {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "invalid bool data", pToken->z);
} }
} else if (pToken->type == TK_INTEGER) { } else if (pToken->type == TK_INTEGER) {
iv = strtoll(pToken->z, NULL, 10); iv = strtoll(pToken->z, NULL, 10);
@ -193,7 +175,7 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} else if (pToken->type == TK_NULL) { } else if (pToken->type == TK_NULL) {
*(uint8_t *)payload = TSDB_DATA_BOOL_NULL; *(uint8_t *)payload = TSDB_DATA_BOOL_NULL;
} else { } else {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "invalid bool data", pToken->z);
} }
break; break;
} }
@ -205,13 +187,13 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
*((int8_t *)payload) = TSDB_DATA_TINYINT_NULL; *((int8_t *)payload) = TSDB_DATA_TINYINT_NULL;
} else { } else {
numType = tscToInteger(pToken, &iv, &endptr); numType = tscToInteger(pToken, &iv, &endptr);
if (errno == ERANGE || iv > INT8_MAX || iv <= INT8_MIN) { if (TK_ILLEGAL == numType) {
INVALID_SQL_RET_MSG(msg, "data is overflow"); return tscInvalidSQLErrMsg(msg, "invalid tinyint data", pToken->z);
} else if (TK_ILLEGAL == numType) { } else if (errno == ERANGE || iv > INT8_MAX || iv <= INT8_MIN) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "tinyint data overflow", pToken->z);
} }
*((int8_t *)payload) = (int8_t)iv; *((int8_t *)payload) = (int8_t) iv;
} }
break; break;
@ -224,10 +206,10 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
*((int16_t *)payload) = TSDB_DATA_SMALLINT_NULL; *((int16_t *)payload) = TSDB_DATA_SMALLINT_NULL;
} else { } else {
numType = tscToInteger(pToken, &iv, &endptr); numType = tscToInteger(pToken, &iv, &endptr);
if (errno == ERANGE || iv > INT16_MAX || iv <= INT16_MIN) { if (TK_ILLEGAL == numType) {
INVALID_SQL_RET_MSG(msg, "data is overflow"); return tscInvalidSQLErrMsg(msg, "invalid smallint data", pToken->z);
} else if (TK_ILLEGAL == numType) { } else if (errno == ERANGE || iv > INT16_MAX || iv <= INT16_MIN) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "smallint data overflow", pToken->z);
} }
*((int16_t *)payload) = (int16_t)iv; *((int16_t *)payload) = (int16_t)iv;
@ -242,10 +224,10 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
*((int32_t *)payload) = TSDB_DATA_INT_NULL; *((int32_t *)payload) = TSDB_DATA_INT_NULL;
} else { } else {
numType = tscToInteger(pToken, &iv, &endptr); numType = tscToInteger(pToken, &iv, &endptr);
if (errno == ERANGE || iv > INT32_MAX || iv <= INT32_MIN) { if (TK_ILLEGAL == numType) {
INVALID_SQL_RET_MSG(msg, "data is overflow"); return tscInvalidSQLErrMsg(msg, "invalid int data", pToken->z);
} else if (TK_ILLEGAL == numType) { } else if (errno == ERANGE || iv > INT32_MAX || iv <= INT32_MIN) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "int data overflow", pToken->z);
} }
*((int32_t *)payload) = (int32_t)iv; *((int32_t *)payload) = (int32_t)iv;
@ -261,10 +243,10 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
*((int64_t *)payload) = TSDB_DATA_BIGINT_NULL; *((int64_t *)payload) = TSDB_DATA_BIGINT_NULL;
} else { } else {
numType = tscToInteger(pToken, &iv, &endptr); numType = tscToInteger(pToken, &iv, &endptr);
if (errno == ERANGE || iv > INT64_MAX || iv <= INT64_MIN) { if (TK_ILLEGAL == numType) {
INVALID_SQL_RET_MSG(msg, "data is overflow"); return tscInvalidSQLErrMsg(msg, "invalid bigint data", pToken->z);
} else if (TK_ILLEGAL == numType) { } else if (errno == ERANGE || iv > INT64_MAX || iv <= INT64_MIN) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "bigint data overflow", pToken->z);
} }
*((int64_t *)payload) = iv; *((int64_t *)payload) = iv;
@ -280,12 +262,12 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} else { } else {
double dv; double dv;
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) { if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "illegal float data", pToken->z);
} }
float fv = (float)dv; float fv = (float)dv;
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || (fv > FLT_MAX || fv < -FLT_MAX)) { if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || (fv > FLT_MAX || fv < -FLT_MAX)) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "illegal float data", pToken->z);
} }
if (isinf(fv) || isnan(fv)) { if (isinf(fv) || isnan(fv)) {
@ -305,11 +287,11 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} else { } else {
double dv; double dv;
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) { if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "illegal double data", pToken->z);
} }
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || (dv > DBL_MAX || dv < -DBL_MAX)) { if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || (dv > DBL_MAX || dv < -DBL_MAX)) {
INVALID_SQL_RET_MSG(msg, "data is illegal"); return tscInvalidSQLErrMsg(msg, "illegal double data", pToken->z);
} }
if (isinf(dv) || isnan(dv)) { if (isinf(dv) || isnan(dv)) {
@ -324,11 +306,11 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
// binary data cannot be null-terminated char string, otherwise the last char of the string is lost // binary data cannot be null-terminated char string, otherwise the last char of the string is lost
if (pToken->type == TK_NULL) { if (pToken->type == TK_NULL) {
*payload = TSDB_DATA_BINARY_NULL; *payload = TSDB_DATA_BINARY_NULL;
} else { } else { // too long values will return invalid sql, not be truncated automatically
// too long values will return invalid sql, not be truncated automatically
if (pToken->n > pSchema->bytes) { if (pToken->n > pSchema->bytes) {
INVALID_SQL_RET_MSG(msg, "value too long"); return tscInvalidSQLErrMsg(msg, "string data overflow", pToken->z);
} }
strncpy(payload, pToken->z, pToken->n); strncpy(payload, pToken->z, pToken->n);
} }
@ -340,8 +322,10 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} else { } else {
// if the converted output len is over than pSchema->bytes, return error: 'Argument list too long' // if the converted output len is over than pSchema->bytes, return error: 'Argument list too long'
if (!taosMbsToUcs4(pToken->z, pToken->n, payload, pSchema->bytes)) { if (!taosMbsToUcs4(pToken->z, pToken->n, payload, pSchema->bytes)) {
sprintf(msg, "%s", strerror(errno)); char buf[512] = {0};
return TSDB_CODE_INVALID_SQL; snprintf(buf, 512, "%s", strerror(errno));
return tscInvalidSQLErrMsg(msg, buf, pToken->z);
} }
} }
break; break;
@ -356,8 +340,9 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} else { } else {
int64_t temp; int64_t temp;
if (tsParseTime(pToken, &temp, str, msg, timePrec) != TSDB_CODE_SUCCESS) { if (tsParseTime(pToken, &temp, str, msg, timePrec) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL; return tscInvalidSQLErrMsg(msg, "invalid timestamp", pToken->z);
} }
*((int64_t *)payload) = temp; *((int64_t *)payload) = temp;
} }
@ -365,18 +350,7 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
} }
} }
return 0; return TSDB_CODE_SUCCESS;
}
// todo merge the error msg function with tSQLParser
static void setErrMsg(char *msg, const char *sql) {
const char * msgFormat = "near \"%s\" syntax error";
const int32_t BACKWARD_CHAR_STEP = 15;
// only extract part of sql string,avoid too long sql string cause stack over flow
char buf[64] = {0};
strncpy(buf, (sql - BACKWARD_CHAR_STEP), tListLen(buf) - 1);
sprintf(msg, msgFormat, buf);
} }
/* /*
@ -399,7 +373,8 @@ static int32_t tsCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start
} }
} else { } else {
if (pDataBlocks->tsSource == TSDB_USE_SERVER_TS) { if (pDataBlocks->tsSource == TSDB_USE_SERVER_TS) {
return -1; return -1; // client time/server time can not be mixed
} else if (pDataBlocks->tsSource == -1) { } else if (pDataBlocks->tsSource == -1) {
pDataBlocks->tsSource = TSDB_USE_CLI_TS; pDataBlocks->tsSource = TSDB_USE_CLI_TS;
} }
@ -414,10 +389,10 @@ static int32_t tsCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start
} }
int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[], SParsedDataColInfo *spd, char *error, int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[], SParsedDataColInfo *spd, char *error,
int16_t timePrec) { int16_t timePrec, int32_t *code, char* tmpTokenBuf) {
int32_t index = 0; int32_t index = 0;
bool isPrevOptr; //bool isPrevOptr; //fang, never used
SSQLToken sToken; SSQLToken sToken = {0};
char * payload = pDataBlocks->pData + pDataBlocks->size; char * payload = pDataBlocks->pData + pDataBlocks->size;
// 1. set the parsed value from sql string // 1. set the parsed value from sql string
@ -438,30 +413,55 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[
if (tscAddParamToDataBlock(pDataBlocks, pSchema->type, (uint8_t)timePrec, pSchema->bytes, offset) != NULL) { if (tscAddParamToDataBlock(pDataBlocks, pSchema->type, (uint8_t)timePrec, pSchema->bytes, offset) != NULL) {
continue; continue;
} }
strcpy(error, "client out of memory"); strcpy(error, "client out of memory");
*code = TSDB_CODE_CLI_OUT_OF_MEMORY;
return -1; return -1;
} }
if (((sToken.type != TK_NOW) && (sToken.type != TK_INTEGER) && (sToken.type != TK_STRING) && if (((sToken.type != TK_NOW) && (sToken.type != TK_INTEGER) && (sToken.type != TK_STRING) &&
(sToken.type != TK_FLOAT) && (sToken.type != TK_BOOL) && (sToken.type != TK_NULL)) || (sToken.type != TK_FLOAT) && (sToken.type != TK_BOOL) && (sToken.type != TK_NULL)) ||
(sToken.n == 0) || (sToken.type == TK_RP)) { (sToken.n == 0) || (sToken.type == TK_RP)) {
setErrMsg(error, *str); tscInvalidSQLErrMsg(error, "invalid data or symbol", sToken.z);
*code = TSDB_CODE_INVALID_SQL;
return -1; return -1;
} }
// Remove quotation marks // Remove quotation marks
if (TK_STRING == sToken.type) { if (TK_STRING == sToken.type) {
sToken.z++; // delete escape character: \\, \', \"
sToken.n -= 2; char delim = sToken.z[0];
int32_t cnt = 0;
int32_t j = 0;
for (int32_t k = 1; k < sToken.n - 1; ++k) {
if (sToken.z[k] == delim || sToken.z[k] == '\\') {
if (sToken.z[k + 1] == delim) {
cnt++;
tmpTokenBuf[j] = sToken.z[k + 1];
j++;
k++;
continue;
}
}
tmpTokenBuf[j] = sToken.z[k];
j++;
}
tmpTokenBuf[j] = 0;
sToken.z = tmpTokenBuf;
sToken.n -= 2 + cnt;
} }
bool isPrimaryKey = (colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX); bool isPrimaryKey = (colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX);
int32_t ret = tsParseOneColumnData(pSchema, &sToken, start, error, str, isPrimaryKey, timePrec); int32_t ret = tsParseOneColumnData(pSchema, &sToken, start, error, str, isPrimaryKey, timePrec);
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
*code = TSDB_CODE_INVALID_SQL;
return -1; // NOTE: here 0 mean error! return -1; // NOTE: here 0 mean error!
} }
if (isPrimaryKey && tsCheckTimestamp(pDataBlocks, start) != TSDB_CODE_SUCCESS) { if (isPrimaryKey && tsCheckTimestamp(pDataBlocks, start) != TSDB_CODE_SUCCESS) {
tscInvalidSQLErrMsg(error, "client time/server time can not be mixed up", sToken.z);
*code = TSDB_CODE_INVALID_TIME_STAMP;
return -1; return -1;
} }
} }
@ -471,8 +471,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[
char *ptr = payload; char *ptr = payload;
for (int32_t i = 0; i < spd->numOfCols; ++i) { for (int32_t i = 0; i < spd->numOfCols; ++i) {
if (!spd->hasVal[i]) { if (!spd->hasVal[i]) { // current column do not have any value to insert, set it to null
// current column do not have any value to insert, set it to null
setNull(ptr, schema[i].type, schema[i].bytes); setNull(ptr, schema[i].type, schema[i].bytes);
} }
@ -497,7 +496,7 @@ static int32_t rowDataCompar(const void *lhs, const void *rhs) {
} }
int tsParseValues(char **str, STableDataBlocks *pDataBlock, SMeterMeta *pMeterMeta, int maxRows, int tsParseValues(char **str, STableDataBlocks *pDataBlock, SMeterMeta *pMeterMeta, int maxRows,
SParsedDataColInfo *spd, char *error) { SParsedDataColInfo *spd, char *error, int32_t *code, char* tmpTokenBuf) {
int32_t index = 0; int32_t index = 0;
SSQLToken sToken; SSQLToken sToken;
@ -508,6 +507,7 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, SMeterMeta *pMeterMe
if (spd->hasVal[0] == false) { if (spd->hasVal[0] == false) {
strcpy(error, "primary timestamp column can not be null"); strcpy(error, "primary timestamp column can not be null");
*code = TSDB_CODE_INVALID_SQL;
return -1; return -1;
} }
@ -519,16 +519,17 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, SMeterMeta *pMeterMe
*str += index; *str += index;
if (numOfRows >= maxRows || pDataBlock->size + pMeterMeta->rowSize >= pDataBlock->nAllocSize) { if (numOfRows >= maxRows || pDataBlock->size + pMeterMeta->rowSize >= pDataBlock->nAllocSize) {
int32_t tSize = tscAllocateMemIfNeed(pDataBlock, pMeterMeta->rowSize); int32_t tSize = tscAllocateMemIfNeed(pDataBlock, pMeterMeta->rowSize);
if (0 == tSize) { if (0 == tSize) { //TODO pass the correct error code to client
strcpy(error, "client out of memory"); strcpy(error, "client out of memory");
*code = TSDB_CODE_CLI_OUT_OF_MEMORY;
return -1; return -1;
} }
maxRows += tSize; maxRows += tSize;
} }
int32_t len = tsParseOneRowData(str, pDataBlock, pSchema, spd, error, precision); int32_t len = tsParseOneRowData(str, pDataBlock, pSchema, spd, error, precision, code, tmpTokenBuf);
if (len <= 0) { if (len <= 0) { // error message has been set in tsParseOneRowData
setErrMsg(error, *str);
return -1; return -1;
} }
@ -538,7 +539,8 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, SMeterMeta *pMeterMe
sToken = tStrGetToken(*str, &index, false, 0, NULL); sToken = tStrGetToken(*str, &index, false, 0, NULL);
*str += index; *str += index;
if (sToken.n == 0 || sToken.type != TK_RP) { if (sToken.n == 0 || sToken.type != TK_RP) {
setErrMsg(error, *str); tscInvalidSQLErrMsg(error, ") expected", *str);
*code = TSDB_CODE_INVALID_SQL;
return -1; return -1;
} }
@ -547,6 +549,7 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, SMeterMeta *pMeterMe
if (numOfRows <= 0) { if (numOfRows <= 0) {
strcpy(error, "no any data points"); strcpy(error, "no any data points");
*code = TSDB_CODE_INVALID_SQL;
return -1; return -1;
} else { } else {
return numOfRows; return numOfRows;
@ -658,10 +661,17 @@ static int32_t doParseInsertStatement(SSqlObj *pSql, void *pTableHashList, char
if (0 == maxNumOfRows) { if (0 == maxNumOfRows) {
return TSDB_CODE_CLI_OUT_OF_MEMORY; return TSDB_CODE_CLI_OUT_OF_MEMORY;
} }
int32_t code = TSDB_CODE_INVALID_SQL;
char* tmpTokenBuf = calloc(1, 4096); // used for deleting Escape character: \\, \', \"
if (NULL == tmpTokenBuf) {
return TSDB_CODE_CLI_OUT_OF_MEMORY;
}
int32_t numOfRows = tsParseValues(str, dataBuf, pMeterMeta, maxNumOfRows, spd, pCmd->payload); int32_t numOfRows = tsParseValues(str, dataBuf, pMeterMeta, maxNumOfRows, spd, pCmd->payload, &code, tmpTokenBuf);
free(tmpTokenBuf);
if (numOfRows <= 0) { if (numOfRows <= 0) {
return TSDB_CODE_INVALID_SQL; return code;
} }
for (uint32_t i = 0; i < dataBuf->numOfParams; ++i) { for (uint32_t i = 0; i < dataBuf->numOfParams; ++i) {
@ -733,8 +743,7 @@ static int32_t tscParseSqlForCreateTableOnDemand(char **sqlstr, SSqlObj *pSql) {
return TSDB_CODE_INVALID_SQL; return TSDB_CODE_INVALID_SQL;
} }
if (sToken.type == TK_USING) { if (sToken.type == TK_USING) { // create table if not exists
// create table if not exists
index = 0; index = 0;
sToken = tStrGetToken(sql, &index, false, 0, NULL); sToken = tStrGetToken(sql, &index, false, 0, NULL);
sql += index; sql += index;
@ -750,25 +759,87 @@ static int32_t tscParseSqlForCreateTableOnDemand(char **sqlstr, SSqlObj *pSql) {
} }
if (!UTIL_METER_IS_METRIC(pMeterMetaInfo)) { if (!UTIL_METER_IS_METRIC(pMeterMetaInfo)) {
strcpy(pCmd->payload, "create table only from super table is allowed"); return tscInvalidSQLErrMsg(pCmd->payload, "create table only from super table is allowed", sToken.z);
return TSDB_CODE_INVALID_SQL;
} }
char * tagVal = pTag->data;
SSchema *pTagSchema = tsGetTagSchema(pMeterMetaInfo->pMeterMeta); SSchema *pTagSchema = tsGetTagSchema(pMeterMetaInfo->pMeterMeta);
index = 0; index = 0;
sToken = tStrGetToken(sql, &index, false, 0, NULL); sToken = tStrGetToken(sql, &index, false, 0, NULL);
sql += index; sql += index;
SParsedDataColInfo spd = {0};
uint8_t numOfTags = pMeterMetaInfo->pMeterMeta->numOfTags;
spd.numOfCols = numOfTags;
// if specify some tags column
if (sToken.type != TK_LP) {
tscSetAssignedColumnInfo(&spd, pTagSchema, numOfTags);
} else {
/* insert into tablename (col1, col2,..., coln) using superTableName (tagName1, tagName2, ..., tagNamen) tags(tagVal1, tagVal2, ..., tagValn) values(v1, v2,... vn); */
int16_t offset[TSDB_MAX_COLUMNS] = {0};
for (int32_t t = 1; t < numOfTags; ++t) {
offset[t] = offset[t - 1] + pTagSchema[t - 1].bytes;
}
while (1) {
index = 0;
sToken = tStrGetToken(sql, &index, false, 0, NULL);
sql += index;
if (TK_STRING == sToken.type) {
sToken.n = strdequote(sToken.z);
strtrim(sToken.z);
sToken.n = (uint32_t)strlen(sToken.z);
}
if (sToken.type == TK_RP) {
break;
}
bool findColumnIndex = false;
// todo speedup by using hash list
for (int32_t t = 0; t < numOfTags; ++t) {
if (strncmp(sToken.z, pTagSchema[t].name, sToken.n) == 0 && strlen(pTagSchema[t].name) == sToken.n) {
SParsedColElem *pElem = &spd.elems[spd.numOfAssignedCols++];
pElem->offset = offset[t];
pElem->colIndex = t;
if (spd.hasVal[t] == true) {
return tscInvalidSQLErrMsg(pCmd->payload, "duplicated tag name", sToken.z);
}
spd.hasVal[t] = true;
findColumnIndex = true;
break;
}
}
if (!findColumnIndex) {
return tscInvalidSQLErrMsg(pCmd->payload, "invalid tag name", sToken.z);
}
}
if (spd.numOfAssignedCols == 0 || spd.numOfAssignedCols > numOfTags) {
return tscInvalidSQLErrMsg(pCmd->payload, "tag name expected", sToken.z);
}
index = 0;
sToken = tStrGetToken(sql, &index, false, 0, NULL);
sql += index;
}
if (sToken.type != TK_TAGS) { if (sToken.type != TK_TAGS) {
setErrMsg(pCmd->payload, sql); return tscInvalidSQLErrMsg(pCmd->payload, "keyword TAGS expected", sToken.z);
return TSDB_CODE_INVALID_SQL;
} }
int32_t numOfTagValues = 0;
uint32_t ignoreTokenTypes = TK_LP; uint32_t ignoreTokenTypes = TK_LP;
uint32_t numOfIgnoreToken = 1; uint32_t numOfIgnoreToken = 1;
while (1) { for (int i = 0; i < spd.numOfAssignedCols; ++i) {
char* tagVal = pTag->data + spd.elems[i].offset;
int16_t colIndex = spd.elems[i].colIndex;
index = 0; index = 0;
sToken = tStrGetToken(sql, &index, true, numOfIgnoreToken, &ignoreTokenTypes); sToken = tStrGetToken(sql, &index, true, numOfIgnoreToken, &ignoreTokenTypes);
sql += index; sql += index;
@ -784,31 +855,39 @@ static int32_t tscParseSqlForCreateTableOnDemand(char **sqlstr, SSqlObj *pSql) {
sToken.n -= 2; sToken.n -= 2;
} }
code = tsParseOneColumnData(&pTagSchema[numOfTagValues], &sToken, tagVal, pCmd->payload, &sql, false, code = tsParseOneColumnData(&pTagSchema[colIndex], &sToken, tagVal, pCmd->payload, &sql, false, pMeterMetaInfo->pMeterMeta->precision);
pMeterMetaInfo->pMeterMeta->precision);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
setErrMsg(pCmd->payload, sql); return code;
return TSDB_CODE_INVALID_SQL;
} }
if ((pTagSchema[numOfTagValues].type == TSDB_DATA_TYPE_BINARY || if ((pTagSchema[colIndex].type == TSDB_DATA_TYPE_BINARY ||
pTagSchema[numOfTagValues].type == TSDB_DATA_TYPE_NCHAR) && pTagSchema[colIndex].type == TSDB_DATA_TYPE_NCHAR) && sToken.n > pTagSchema[colIndex].bytes) {
sToken.n > pTagSchema[numOfTagValues].bytes) { return tscInvalidSQLErrMsg(pCmd->payload, "string too long", sToken.z);
strcpy(pCmd->payload, "tag value too long");
return TSDB_CODE_INVALID_SQL;
} }
tagVal += pTagSchema[numOfTagValues++].bytes;
} }
if (numOfTagValues != pMeterMetaInfo->pMeterMeta->numOfTags) { index = 0;
setErrMsg(pCmd->payload, sql); sToken = tStrGetToken(sql, &index, false, 0, NULL);
return TSDB_CODE_INVALID_SQL; sql += index;
if (sToken.n == 0 || sToken.type != TK_RP) {
return tscInvalidSQLErrMsg(pCmd->payload, ") expected", sToken.z);
}
// 2. set the null value for the columns that do not assign values
if (spd.numOfAssignedCols < spd.numOfCols) {
char *ptr = pTag->data;
for (int32_t i = 0; i < spd.numOfCols; ++i) {
if (!spd.hasVal[i]) { // current tag column do not have any value to insert, set it to null
setNull(ptr, pTagSchema[i].type, pTagSchema[i].bytes);
}
ptr += pTagSchema[i].bytes;
}
} }
if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) { if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) {
setErrMsg(pCmd->payload, sql); return tscInvalidSQLErrMsg(pCmd->payload, "invalid table name", *sqlstr);
return TSDB_CODE_INVALID_SQL;
} }
int32_t ret = setMeterID(pSql, &tableToken, 0); int32_t ret = setMeterID(pSql, &tableToken, 0);
@ -858,27 +937,29 @@ int validateTableName(char *tblName, int len) {
* @param pSql * @param pSql
* @return * @return
*/ */
int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) { int doParserInsertSql(SSqlObj *pSql, char *str) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
pCmd->command = TSDB_SQL_INSERT; int32_t code = TSDB_CODE_INVALID_SQL;
pCmd->isInsertFromFile = -1;
pCmd->count = 0;
pSql->res.numOfRows = 0;
int32_t totalNum = 0; int32_t totalNum = 0;
int code = TSDB_CODE_INVALID_SQL;
SMeterMetaInfo *pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pCmd); SMeterMetaInfo *pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pCmd);
if ((code = tscAllocPayload(pCmd, TSDB_PAYLOAD_SIZE)) != TSDB_CODE_SUCCESS) { if ((code = tscAllocPayload(pCmd, TSDB_PAYLOAD_SIZE)) != TSDB_CODE_SUCCESS) {
return code; return code;
} }
void *pTableHashList = taosInitIntHash(128, sizeof(void *), taosHashInt); if ((NULL == pSql->asyncTblPos) && (NULL == pSql->pTableHashList)) {
pSql->pTableHashList = taosInitIntHash(128, POINTER_BYTES, taosHashInt);
pSql->cmd.pDataBlocks = tscCreateBlockArrayList(); pSql->cmd.pDataBlocks = tscCreateBlockArrayList();
if (NULL == pSql->pTableHashList || NULL == pSql->cmd.pDataBlocks) {
code = TSDB_CODE_CLI_OUT_OF_MEMORY;
goto _error_clean;
}
} else {
str = pSql->asyncTblPos;
}
tscTrace("%p create data block list for submit data, %p", pSql, pSql->cmd.pDataBlocks); tscTrace("%p create data block list for submit data, %p", pSql, pSql->cmd.pDataBlocks);
while (1) { while (1) {
@ -897,13 +978,15 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
} }
} }
pSql->asyncTblPos = sToken.z;
// Check if the table name available or not // Check if the table name available or not
if (validateTableName(sToken.z, sToken.n) != TSDB_CODE_SUCCESS) { if (validateTableName(sToken.z, sToken.n) != TSDB_CODE_SUCCESS) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "table name invalid", sToken.z);
sprintf(pCmd->payload, "table name is invalid");
goto _error_clean; goto _error_clean;
} }
//TODO refactor
if ((code = setMeterID(pSql, &sToken, 0)) != TSDB_CODE_SUCCESS) { if ((code = setMeterID(pSql, &sToken, 0)) != TSDB_CODE_SUCCESS) {
goto _error_clean; goto _error_clean;
} }
@ -911,7 +994,8 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
void *fp = pSql->fp; void *fp = pSql->fp;
if ((code = tscParseSqlForCreateTableOnDemand(&str, pSql)) != TSDB_CODE_SUCCESS) { if ((code = tscParseSqlForCreateTableOnDemand(&str, pSql)) != TSDB_CODE_SUCCESS) {
if (fp != NULL) { if (fp != NULL) {
goto _clean; //goto _clean;
return code;
} else { } else {
/* /*
* for async insert, the free data block operations, which is tscDestroyBlockArrayList, * for async insert, the free data block operations, which is tscDestroyBlockArrayList,
@ -923,8 +1007,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
} }
if (UTIL_METER_IS_METRIC(pMeterMetaInfo)) { if (UTIL_METER_IS_METRIC(pMeterMetaInfo)) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "insert data into super table is not supported", NULL);
sprintf(pCmd->payload, "insert data into metric is not supported");
goto _error_clean; goto _error_clean;
} }
@ -932,8 +1015,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
sToken = tStrGetToken(str, &index, false, 0, NULL); sToken = tStrGetToken(str, &index, false, 0, NULL);
str += index; str += index;
if (sToken.n == 0) { if (sToken.n == 0) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "keyword VALUES or FILE are required", sToken.z);
sprintf(pCmd->payload, "keyword VALUES or FILE are required");
goto _error_clean; goto _error_clean;
} }
@ -947,8 +1029,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
pCmd->isInsertFromFile = 0; pCmd->isInsertFromFile = 0;
} else { } else {
if (pCmd->isInsertFromFile == 1) { if (pCmd->isInsertFromFile == 1) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "keyword VALUES and FILE are not allowed to mix up", sToken.z);
sprintf(pCmd->payload, "keyword VALUES and FILE are not allowed to mix up");
goto _error_clean; goto _error_clean;
} }
} }
@ -957,18 +1038,16 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
* app here insert data in different vnodes, so we need to set the following * app here insert data in different vnodes, so we need to set the following
* data in another submit procedure using async insert routines * data in another submit procedure using async insert routines
*/ */
code = doParseInsertStatement(pSql, pTableHashList, &str, &spd, &totalNum); code = doParseInsertStatement(pSql, pSql->pTableHashList, &str, &spd, &totalNum);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
goto _error_clean; goto _error_clean;
} }
} else if (sToken.type == TK_FILE) { } else if (sToken.type == TK_FILE) {
if (pCmd->isInsertFromFile == -1) { if (pCmd->isInsertFromFile == -1) {
pCmd->isInsertFromFile = 1; pCmd->isInsertFromFile = 1;
} else { } else {
if (pCmd->isInsertFromFile == 0) { if (pCmd->isInsertFromFile == 0) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "keyword VALUES and FILE are not allowed to mix up", sToken.z);
sprintf(pCmd->payload, "keyword VALUES and FILE are not allowed to mix up");
goto _error_clean; goto _error_clean;
} }
} }
@ -977,8 +1056,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
sToken = tStrGetToken(str, &index, false, 0, NULL); sToken = tStrGetToken(str, &index, false, 0, NULL);
str += index; str += index;
if (sToken.n == 0) { if (sToken.n == 0) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "file path is required following keyword FILE", sToken.z);
sprintf(pCmd->payload, "file path is required following keyword FILE");
goto _error_clean; goto _error_clean;
} }
@ -988,14 +1066,13 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
wordexp_t full_path; wordexp_t full_path;
if (wordexp(fname, &full_path, 0) != 0) { if (wordexp(fname, &full_path, 0) != 0) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "invalid filename", sToken.z);
sprintf(pCmd->payload, "invalid filename");
goto _error_clean; goto _error_clean;
} }
strcpy(fname, full_path.we_wordv[0]); strcpy(fname, full_path.we_wordv[0]);
wordfree(&full_path); wordfree(&full_path);
STableDataBlocks *pDataBlock = tscCreateDataBlockEx(PATH_MAX, pMeterMetaInfo->pMeterMeta->rowSize, STableDataBlocks *pDataBlock = tscCreateDataBlock(PATH_MAX, pMeterMetaInfo->pMeterMeta->rowSize,
sizeof(SShellSubmitBlock), pMeterMetaInfo->name); sizeof(SShellSubmitBlock), pMeterMetaInfo->name);
tscAppendDataBlock(pCmd->pDataBlocks, pDataBlock); tscAppendDataBlock(pCmd->pDataBlocks, pDataBlock);
@ -1008,8 +1085,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
if (pCmd->isInsertFromFile == -1) { if (pCmd->isInsertFromFile == -1) {
pCmd->isInsertFromFile = 0; pCmd->isInsertFromFile = 0;
} else if (pCmd->isInsertFromFile == 1) { } else if (pCmd->isInsertFromFile == 1) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "keyword VALUES and FILE are not allowed to mix up", sToken.z);
sprintf(pCmd->payload, "keyword VALUES and FILE are not allowed to mix up");
goto _error_clean; goto _error_clean;
} }
@ -1046,8 +1122,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
pElem->colIndex = t; pElem->colIndex = t;
if (spd.hasVal[t] == true) { if (spd.hasVal[t] == true) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "duplicated column name", sToken.z);
sprintf(pCmd->payload, "duplicated column name");
goto _error_clean; goto _error_clean;
} }
@ -1058,15 +1133,13 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
} }
if (!findColumnIndex) { if (!findColumnIndex) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "invalid column name", sToken.z);
sprintf(pCmd->payload, "invalid column name");
goto _error_clean; goto _error_clean;
} }
} }
if (spd.numOfAssignedCols == 0 || spd.numOfAssignedCols > pMeterMeta->numOfColumns) { if (spd.numOfAssignedCols == 0 || spd.numOfAssignedCols > pMeterMeta->numOfColumns) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "column name expected", sToken.z);
sprintf(pCmd->payload, "column name expected");
goto _error_clean; goto _error_clean;
} }
@ -1075,18 +1148,16 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
str += index; str += index;
if (sToken.type != TK_VALUES) { if (sToken.type != TK_VALUES) {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "keyword VALUES is expected", sToken.z);
sprintf(pCmd->payload, "keyword VALUES is expected");
goto _error_clean; goto _error_clean;
} }
code = doParseInsertStatement(pSql, pTableHashList, &str, &spd, &totalNum); code = doParseInsertStatement(pSql, pSql->pTableHashList, &str, &spd, &totalNum);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
goto _error_clean; goto _error_clean;
} }
} else { } else {
code = TSDB_CODE_INVALID_SQL; code = tscInvalidSQLErrMsg(pCmd->payload, "keyword VALUES or FILE are required", sToken.z);
sprintf(pCmd->payload, "keyword VALUES or FILE are required");
goto _error_clean; goto _error_clean;
} }
} }
@ -1095,7 +1166,7 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
if (pCmd->numOfParams > 0) { if (pCmd->numOfParams > 0) {
goto _clean; goto _clean;
} }
// submit to more than one vnode // submit to more than one vnode
if (pCmd->pDataBlocks->nSize > 0) { if (pCmd->pDataBlocks->nSize > 0) {
// merge according to vgid // merge according to vgid
@ -1108,8 +1179,10 @@ int tsParseInsertStatement(SSqlObj *pSql, char *str, char *acct, char *db) {
goto _error_clean; goto _error_clean;
} }
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
// set the next sent data vnode index in data block arraylist // set the next sent data vnode index in data block arraylist
pCmd->vnodeIdx = 1; pMeterMetaInfo->vnodeIndex = 1;
} else { } else {
pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks); pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks);
} }
@ -1121,7 +1194,8 @@ _error_clean:
pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks); pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks);
_clean: _clean:
taosCleanUpIntHash(pTableHashList); taosCleanUpIntHash(pSql->pTableHashList);
pSql->pTableHashList = NULL;
return code; return code;
} }
@ -1130,29 +1204,25 @@ int tsParseInsertSql(SSqlObj *pSql, char *sql, char *acct, char *db) {
return TSDB_CODE_NO_RIGHTS; return TSDB_CODE_NO_RIGHTS;
} }
int32_t index = 0; int32_t index = 0;
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSQLToken sToken = tStrGetToken(sql, &index, false, 0, NULL); SSQLToken sToken = tStrGetToken(sql, &index, false, 0, NULL);
if (sToken.type == TK_IMPORT) {
pCmd->order.order = TSQL_SO_ASC; assert(sToken.type == TK_INSERT || sToken.type == TK_IMPORT);
} else if (sToken.type != TK_INSERT) { pCmd->import = (sToken.type == TK_IMPORT);
if (sToken.n) {
sToken.z[sToken.n] = 0;
sprintf(pCmd->payload, "invalid keyword:%s", sToken.z);
} else {
strcpy(pCmd->payload, "no any keywords");
}
return TSDB_CODE_INVALID_SQL;
}
sToken = tStrGetToken(sql, &index, false, 0, NULL); sToken = tStrGetToken(sql, &index, false, 0, NULL);
if (sToken.type != TK_INTO) { if (sToken.type != TK_INTO) {
strcpy(pCmd->payload, "keyword INTO is expected"); return tscInvalidSQLErrMsg(pCmd->payload, "keyword INTO is expected", sToken.z);
return TSDB_CODE_INVALID_SQL;
} }
return tsParseInsertStatement(pSql, sql + index, acct, db); pCmd->count = 0;
pCmd->command = TSDB_SQL_INSERT;
pCmd->isInsertFromFile = -1;
pSql->res.numOfRows = 0;
return doParserInsertSql(pSql, sql + index);
} }
int tsParseSql(SSqlObj *pSql, char *acct, char *db, bool multiVnodeInsertion) { int tsParseSql(SSqlObj *pSql, char *acct, char *db, bool multiVnodeInsertion) {
@ -1160,7 +1230,11 @@ int tsParseSql(SSqlObj *pSql, char *acct, char *db, bool multiVnodeInsertion) {
// must before clean the sqlcmd object // must before clean the sqlcmd object
tscRemoveAllMeterMetaInfo(&pSql->cmd, false); tscRemoveAllMeterMetaInfo(&pSql->cmd, false);
tscCleanSqlCmd(&pSql->cmd);
if (NULL == pSql->asyncTblPos) {
tscTrace("continue parse sql: %s", pSql->asyncTblPos);
tscCleanSqlCmd(&pSql->cmd);
}
if (tscIsInsertOrImportData(pSql->sqlstr)) { if (tscIsInsertOrImportData(pSql->sqlstr)) {
/* /*
@ -1225,7 +1299,7 @@ static int doPackSendDataBlock(SSqlObj *pSql, int32_t numOfRows, STableDataBlock
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static int tscInsertDataFromFile(SSqlObj *pSql, FILE *fp) { static int tscInsertDataFromFile(SSqlObj *pSql, FILE *fp, char *tmpTokenBuf) {
size_t readLen = 0; size_t readLen = 0;
char * line = NULL; char * line = NULL;
size_t n = 0; size_t n = 0;
@ -1240,8 +1314,8 @@ static int tscInsertDataFromFile(SSqlObj *pSql, FILE *fp) {
int32_t rowSize = pMeterMeta->rowSize; int32_t rowSize = pMeterMeta->rowSize;
pCmd->pDataBlocks = tscCreateBlockArrayList(); pCmd->pDataBlocks = tscCreateBlockArrayList();
STableDataBlocks *pTableDataBlock = STableDataBlocks *pTableDataBlock = tscCreateDataBlock(TSDB_PAYLOAD_SIZE, pMeterMeta->rowSize,
tscCreateDataBlockEx(TSDB_PAYLOAD_SIZE, pMeterMeta->rowSize, sizeof(SShellSubmitBlock), pMeterMetaInfo->name); sizeof(SShellSubmitBlock), pMeterMetaInfo->name);
tscAppendDataBlock(pCmd->pDataBlocks, pTableDataBlock); tscAppendDataBlock(pCmd->pDataBlocks, pTableDataBlock);
@ -1257,7 +1331,7 @@ static int tscInsertDataFromFile(SSqlObj *pSql, FILE *fp) {
while ((readLen = getline(&line, &n, fp)) != -1) { while ((readLen = getline(&line, &n, fp)) != -1) {
// line[--readLen] = '\0'; // line[--readLen] = '\0';
if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) line[--readLen] = 0; if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) line[--readLen] = 0;
if (readLen <= 0) continue; if (readLen == 0) continue; //fang, <= to ==
char *lineptr = line; char *lineptr = line;
strtolower(line, line); strtolower(line, line);
@ -1268,11 +1342,12 @@ static int tscInsertDataFromFile(SSqlObj *pSql, FILE *fp) {
maxRows += tSize; maxRows += tSize;
} }
len = tsParseOneRowData(&lineptr, pTableDataBlock, pSchema, &spd, pCmd->payload, pMeterMeta->precision); len = tsParseOneRowData(&lineptr, pTableDataBlock, pSchema, &spd, pCmd->payload, pMeterMeta->precision, &code, tmpTokenBuf);
if (len <= 0 || pTableDataBlock->numOfParams > 0) { if (len <= 0 || pTableDataBlock->numOfParams > 0) {
pSql->res.code = TSDB_CODE_INVALID_SQL; pSql->res.code = code;
return -1; return (-code);
} }
pTableDataBlock->size += len; pTableDataBlock->size += len;
count++; count++;
@ -1330,19 +1405,19 @@ void tscProcessMultiVnodesInsert(SSqlObj *pSql) {
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
/* the first block has been sent to server in processSQL function */ /* the first block has been sent to server in processSQL function */
assert(pCmd->isInsertFromFile != -1 && pCmd->vnodeIdx >= 1 && pCmd->pDataBlocks != NULL); assert(pCmd->isInsertFromFile != -1 && pMeterMetaInfo->vnodeIndex >= 1 && pCmd->pDataBlocks != NULL);
if (pCmd->vnodeIdx < pCmd->pDataBlocks->nSize) { if (pMeterMetaInfo->vnodeIndex < pCmd->pDataBlocks->nSize) {
SDataBlockList *pDataBlocks = pCmd->pDataBlocks; SDataBlockList *pDataBlocks = pCmd->pDataBlocks;
for (int32_t i = pCmd->vnodeIdx; i < pDataBlocks->nSize; ++i) { for (int32_t i = pMeterMetaInfo->vnodeIndex; i < pDataBlocks->nSize; ++i) {
pDataBlock = pDataBlocks->pData[i]; pDataBlock = pDataBlocks->pData[i];
if (pDataBlock == NULL) { if (pDataBlock == NULL) {
continue; continue;
} }
if ((code = tscCopyDataBlockToPayload(pSql, pDataBlock)) != TSDB_CODE_SUCCESS) { if ((code = tscCopyDataBlockToPayload(pSql, pDataBlock)) != TSDB_CODE_SUCCESS) {
tscTrace("%p build submit data block failed, vnodeIdx:%d, total:%d", pSql, pCmd->vnodeIdx, pDataBlocks->nSize); tscTrace("%p build submit data block failed, vnodeIdx:%d, total:%d", pSql, pMeterMetaInfo->vnodeIndex, pDataBlocks->nSize);
continue; continue;
} }
@ -1399,8 +1474,16 @@ void tscProcessMultiVnodesInsertForFile(SSqlObj *pSql) {
tscError("%p get meter meta failed, abort", pSql); tscError("%p get meter meta failed, abort", pSql);
continue; continue;
} }
char* tmpTokenBuf = calloc(1, 4096); // used for deleting Escape character: \\, \', \"
if (NULL == tmpTokenBuf) {
tscError("%p calloc failed", pSql);
continue;
}
int nrows = tscInsertDataFromFile(pSql, fp); int nrows = tscInsertDataFromFile(pSql, fp, tmpTokenBuf);
free(tmpTokenBuf);
pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks); pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks);
if (nrows < 0) { if (nrows < 0) {

View File

@ -13,12 +13,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include "taos.h" #include "taos.h"
#include "tsclient.h" #include "tsclient.h"
#include "tsql.h" #include "tscSQLParser.h"
#include "tscUtil.h" #include "tscUtil.h"
#include "ttimer.h" #include "ttimer.h"
#include "taosmsg.h" #include "taosmsg.h"
@ -78,7 +75,6 @@ static int normalStmtAddPart(SNormalStmt* stmt, bool isParam, char* str, uint32_
if (isParam) { if (isParam) {
++stmt->numParams; ++stmt->numParams;
} }
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
@ -412,7 +408,9 @@ static int insertStmtReset(STscStmt* pStmt) {
} }
} }
pCmd->batchSize = 0; pCmd->batchSize = 0;
pCmd->vnodeIdx = 0;
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
pMeterMetaInfo->vnodeIndex = 0;
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
@ -425,6 +423,8 @@ static int insertStmtExecute(STscStmt* stmt) {
++pCmd->batchSize; ++pCmd->batchSize;
} }
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
if (pCmd->pDataBlocks->nSize > 0) { if (pCmd->pDataBlocks->nSize > 0) {
// merge according to vgid // merge according to vgid
int code = tscMergeTableDataBlocks(stmt->pSql, pCmd->pDataBlocks); int code = tscMergeTableDataBlocks(stmt->pSql, pCmd->pDataBlocks);
@ -439,7 +439,7 @@ static int insertStmtExecute(STscStmt* stmt) {
} }
// set the next sent data vnode index in data block arraylist // set the next sent data vnode index in data block arraylist
pCmd->vnodeIdx = 1; pMeterMetaInfo->vnodeIndex = 1;
} else { } else {
pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks); pCmd->pDataBlocks = tscDestroyBlockArrayList(pCmd->pDataBlocks);
} }

View File

@ -13,9 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include "os.h" #include "os.h"
#include "tlog.h" #include "tlog.h"
#include "tsclient.h" #include "tsclient.h"
@ -23,6 +20,27 @@
#include "ttimer.h" #include "ttimer.h"
#include "tutil.h" #include "tutil.h"
void tscSaveSlowQueryFp(void *handle, void *tmrId);
void *tscSlowQueryConn = NULL;
bool tscSlowQueryConnInitialized = false;
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
void *param, void **taos);
void tscInitConnCb(void *param, TAOS_RES *result, int code) {
char *sql = param;
if (code < 0) {
tscError("taos:%p, slow query connect failed, code:%d", tscSlowQueryConn, code);
taos_close(tscSlowQueryConn);
tscSlowQueryConn = NULL;
tscSlowQueryConnInitialized = false;
free(sql);
} else {
tscTrace("taos:%p, slow query connect success, code:%d", tscSlowQueryConn, code);
tscSlowQueryConnInitialized = true;
tscSaveSlowQueryFp(sql, NULL);
}
}
void tscAddIntoSqlList(SSqlObj *pSql) { void tscAddIntoSqlList(SSqlObj *pSql) {
static uint32_t queryId = 1; static uint32_t queryId = 1;
@ -47,36 +65,38 @@ void tscAddIntoSqlList(SSqlObj *pSql) {
void tscSaveSlowQueryFpCb(void *param, TAOS_RES *result, int code) { void tscSaveSlowQueryFpCb(void *param, TAOS_RES *result, int code) {
if (code < 0) { if (code < 0) {
tscError("failed to save slowquery, code:%d", code); tscError("failed to save slow query, code:%d", code);
} else {
tscTrace("success to save slow query, code:%d", code);
} }
} }
void tscSaveSlowQueryFp(void *handle, void *tmrId) { void tscSaveSlowQueryFp(void *handle, void *tmrId) {
char *sql = handle; char *sql = handle;
static void *taos = NULL; if (!tscSlowQueryConnInitialized) {
if (taos == NULL) { if (tscSlowQueryConn == NULL) {
taos = taos_connect(NULL, "monitor", tsInternalPass, NULL, 0); tscTrace("start to init slow query connect");
if (taos == NULL) { taos_connect_a(NULL, "monitor", tsInternalPass, "", 0, tscInitConnCb, sql, &tscSlowQueryConn);
tscError("failed to save slow query, can't connect to server"); } else {
tscError("taos:%p, slow query connect is already initialized", tscSlowQueryConn);
free(sql); free(sql);
return;
} }
} else {
tscTrace("taos:%p, save slow query:%s", tscSlowQueryConn, sql);
taos_query_a(tscSlowQueryConn, sql, tscSaveSlowQueryFpCb, NULL);
free(sql);
} }
tscTrace("save slow query:sql", sql);
taos_query_a(taos, sql, tscSaveSlowQueryFpCb, NULL);
free(sql);
} }
void tscSaveSlowQuery(SSqlObj *pSql) { void tscSaveSlowQuery(SSqlObj *pSql) {
const static int64_t SLOW_QUERY_INTERVAL = 3000000L; const static int64_t SLOW_QUERY_INTERVAL = 3000000L;
if (pSql->res.useconds < SLOW_QUERY_INTERVAL) return; if (pSql->res.useconds < SLOW_QUERY_INTERVAL) return;
tscTrace("%p query time:%ld sql:%s", pSql, pSql->res.useconds, pSql->sqlstr); tscTrace("%p query time:%" PRId64 " sql:%s", pSql, pSql->res.useconds, pSql->sqlstr);
char *sql = malloc(200); char *sql = malloc(200);
int len = snprintf(sql, 200, "insert into %s.slowquery values(now, '%s', %lld, %lld, '", tsMonitorDbName, int len = snprintf(sql, 200, "insert into %s.slowquery values(now, '%s', %" PRId64 ", %" PRId64 ", '", tsMonitorDbName,
pSql->pTscObj->user, pSql->stime, pSql->res.useconds); pSql->pTscObj->user, pSql->stime, pSql->res.useconds);
int sqlLen = snprintf(sql + len, TSDB_SHOW_SQL_LEN, "%s", pSql->sqlstr); int sqlLen = snprintf(sql + len, TSDB_SHOW_SQL_LEN, "%s", pSql->sqlstr);
if (sqlLen > TSDB_SHOW_SQL_LEN - 1) { if (sqlLen > TSDB_SHOW_SQL_LEN - 1) {
@ -177,8 +197,10 @@ void tscKillStream(STscObj *pObj, uint32_t killId) {
} }
pthread_mutex_unlock(&pObj->mutex); pthread_mutex_unlock(&pObj->mutex);
tscTrace("%p stream:%p is killed, streamId:%d", pStream->pSql, pStream, killId); if (pStream) {
tscTrace("%p stream:%p is killed, streamId:%d", pStream->pSql, pStream, killId);
}
taos_close_stream(pStream); taos_close_stream(pStream);
if (pStream->callback) { if (pStream->callback) {

File diff suppressed because it is too large Load Diff

View File

@ -13,16 +13,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include "os.h" #include "os.h"
#include "taosmsg.h"
#include "tglobalcfg.h" #include "tglobalcfg.h"
#include "tsql.h" #include "tlog.h"
#include "tscSQLParser.h"
#include "tstoken.h" #include "tstoken.h"
#include "ttime.h" #include "ttime.h"
#include "tutil.h" #include "tutil.h"
@ -507,7 +502,7 @@ void tSQLSetColumnType(TAOS_FIELD *pField, SSQLToken *type) {
SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection, tVariantList *pFrom, tSQLExpr *pWhere, SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection, tVariantList *pFrom, tSQLExpr *pWhere,
tVariantList *pGroupby, tVariantList *pSortOrder, SSQLToken *pInterval, tVariantList *pGroupby, tVariantList *pSortOrder, SSQLToken *pInterval,
SSQLToken *pSliding, tVariantList *pFill, SLimitVal *pLimit, SLimitVal *pGLimit) { SSQLToken *pSliding, tVariantList *pFill, SLimitVal *pLimit, SLimitVal *pGLimit) {
assert(pSelection != NULL && pFrom != NULL && pInterval != NULL && pLimit != NULL && pGLimit != NULL); assert(pSelection != NULL);
SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL)); SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL));
pQuery->selectToken = *pSelectToken; pQuery->selectToken = *pSelectToken;
@ -519,13 +514,23 @@ SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection,
pQuery->pSortOrder = pSortOrder; pQuery->pSortOrder = pSortOrder;
pQuery->pWhere = pWhere; pQuery->pWhere = pWhere;
pQuery->limit = *pLimit; if (pLimit != NULL) {
pQuery->slimit = *pGLimit; pQuery->limit = *pLimit;
}
if (pGLimit != NULL) {
pQuery->slimit = *pGLimit;
}
if (pInterval != NULL) {
pQuery->interval = *pInterval;
}
if (pSliding != NULL) {
pQuery->sliding = *pSliding;
}
pQuery->interval = *pInterval;
pQuery->sliding = *pSliding;
pQuery->fillType = pFill; pQuery->fillType = pFill;
return pQuery; return pQuery;
} }
@ -739,3 +744,22 @@ void setCreateAcctSQL(SSqlInfo *pInfo, int32_t type, SSQLToken *pName, SSQLToken
tTokenListAppend(pInfo->pDCLInfo, pPwd); tTokenListAppend(pInfo->pDCLInfo, pPwd);
} }
} }
void setDefaultCreateDbOption(SCreateDBInfo *pDBInfo) {
pDBInfo->numOfBlocksPerTable = 50;
pDBInfo->compressionLevel = -1;
pDBInfo->commitLog = -1;
pDBInfo->commitTime = -1;
pDBInfo->tablesPerVnode = -1;
pDBInfo->numOfAvgCacheBlocks = -1;
pDBInfo->cacheBlockSize = -1;
pDBInfo->rowPerFileBlock = -1;
pDBInfo->daysPerFile = -1;
pDBInfo->replica = -1;
pDBInfo->keep = NULL;
memset(&pDBInfo->precision, 0, sizeof(SSQLToken));
}

View File

@ -13,10 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "os.h" #include "os.h"
#include "taosmsg.h" #include "taosmsg.h"
#include "tschemautil.h" #include "tschemautil.h"
@ -87,6 +83,13 @@ struct SSchema* tsGetColumnSchema(SMeterMeta* pMeta, int32_t startCol) {
return (SSchema*)(((char*)pMeta + sizeof(SMeterMeta)) + startCol * sizeof(SSchema)); return (SSchema*)(((char*)pMeta + sizeof(SMeterMeta)) + startCol * sizeof(SSchema));
} }
struct SSchema tsGetTbnameColumnSchema() {
struct SSchema s = {.colId = TSDB_TBNAME_COLUMN_INDEX, .type = TSDB_DATA_TYPE_BINARY, .bytes = TSDB_METER_NAME_LEN};
strcpy(s.name, TSQL_TBNAME_L);
return s;
}
/** /**
* the MeterMeta data format in memory is as follows: * the MeterMeta data format in memory is as follows:
* *
@ -127,35 +130,40 @@ bool tsMeterMetaIdentical(SMeterMeta* p1, SMeterMeta* p2) {
return memcmp(p1, p2, size) == 0; return memcmp(p1, p2, size) == 0;
} }
static FORCE_INLINE char* skipSegments(char* input, char delimiter, int32_t num) { // todo refactor
static FORCE_INLINE char* skipSegments(char* input, char delim, int32_t num) {
for (int32_t i = 0; i < num; ++i) { for (int32_t i = 0; i < num; ++i) {
while (*input != 0 && *input++ != delimiter) { while (*input != 0 && *input++ != delim) {
}; };
} }
return input; return input;
} }
static FORCE_INLINE void copySegment(char* dst, char* src, char delimiter) { static FORCE_INLINE size_t copy(char* dst, const char* src, char delimiter) {
size_t len = 0;
while (*src != delimiter && *src != 0) { while (*src != delimiter && *src != 0) {
*dst++ = *src++; *dst++ = *src++;
len++;
} }
return len;
} }
/** /**
* extract meter name from meterid, which the format of userid.dbname.metername * extract table name from meterid, which the format of userid.dbname.metername
* @param meterId * @param meterId
* @return * @return
*/ */
void extractMeterName(char* meterId, char* name) { void extractTableName(char* meterId, char* name) {
char* r = skipSegments(meterId, TS_PATH_DELIMITER[0], 2); char* r = skipSegments(meterId, TS_PATH_DELIMITER[0], 2);
copySegment(name, r, TS_PATH_DELIMITER[0]); copy(name, r, TS_PATH_DELIMITER[0]);
} }
SSQLToken extractDBName(char* meterId, char* name) { SSQLToken extractDBName(char* meterId, char* name) {
char* r = skipSegments(meterId, TS_PATH_DELIMITER[0], 1); char* r = skipSegments(meterId, TS_PATH_DELIMITER[0], 1);
copySegment(name, r, TS_PATH_DELIMITER[0]); size_t len = copy(name, r, TS_PATH_DELIMITER[0]);
SSQLToken token = {.z = name, .n = strlen(name), .type = TK_STRING}; SSQLToken token = {.z = name, .n = len, .type = TK_STRING};
return token; return token;
} }

View File

@ -13,13 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h> #include "os.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <tsclient.h>
#include "tlosertree.h"
#include "tlosertree.h" #include "tlosertree.h"
#include "tscSecondaryMerge.h" #include "tscSecondaryMerge.h"
#include "tscUtil.h" #include "tscUtil.h"
@ -437,11 +431,10 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
// there is no more result, so we release all allocated resource // there is no more result, so we release all allocated resource
SLocalReducer *pLocalReducer = SLocalReducer *pLocalReducer = (SLocalReducer*)atomic_exchange_ptr(&pRes->pLocalReducer, NULL);
(SLocalReducer *)__sync_val_compare_and_swap_64(&pRes->pLocalReducer, pRes->pLocalReducer, 0);
if (pLocalReducer != NULL) { if (pLocalReducer != NULL) {
int32_t status = 0; int32_t status = 0;
while ((status = __sync_val_compare_and_swap_32(&pLocalReducer->status, TSC_LOCALREDUCE_READY, while ((status = atomic_val_compare_exchange_32(&pLocalReducer->status, TSC_LOCALREDUCE_READY,
TSC_LOCALREDUCE_TOBE_FREED)) == TSC_LOCALREDUCE_IN_PROGRESS) { TSC_LOCALREDUCE_TOBE_FREED)) == TSC_LOCALREDUCE_IN_PROGRESS) {
taosMsleep(100); taosMsleep(100);
tscTrace("%p waiting for delete procedure, status: %d", pSql, status); tscTrace("%p waiting for delete procedure, status: %d", pSql, status);
@ -1321,8 +1314,10 @@ int32_t tscLocalDoReduce(SSqlObj *pSql) {
tscTrace("%s call the drop local reducer", __FUNCTION__); tscTrace("%s call the drop local reducer", __FUNCTION__);
tscDestroyLocalReducer(pSql); tscDestroyLocalReducer(pSql);
pRes->numOfRows = 0; if (pRes) {
pRes->row = 0; pRes->numOfRows = 0;
pRes->row = 0;
}
return 0; return 0;
} }
@ -1333,7 +1328,7 @@ int32_t tscLocalDoReduce(SSqlObj *pSql) {
// set the data merge in progress // set the data merge in progress
int32_t prevStatus = int32_t prevStatus =
__sync_val_compare_and_swap_32(&pLocalReducer->status, TSC_LOCALREDUCE_READY, TSC_LOCALREDUCE_IN_PROGRESS); atomic_val_compare_exchange_32(&pLocalReducer->status, TSC_LOCALREDUCE_READY, TSC_LOCALREDUCE_IN_PROGRESS);
if (prevStatus != TSC_LOCALREDUCE_READY || pLocalReducer == NULL) { if (prevStatus != TSC_LOCALREDUCE_READY || pLocalReducer == NULL) {
assert(prevStatus == TSC_LOCALREDUCE_TOBE_FREED); // it is in tscDestroyLocalReducer function already assert(prevStatus == TSC_LOCALREDUCE_TOBE_FREED); // it is in tscDestroyLocalReducer function already
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;

File diff suppressed because it is too large Load Diff

View File

@ -13,26 +13,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include "os.h" #include "os.h"
#include "tcache.h" #include "tcache.h"
#include "tlog.h" #include "tlog.h"
#include "tnote.h"
#include "trpc.h" #include "trpc.h"
#include "tscJoinProcess.h" #include "tscJoinProcess.h"
#include "tscProfile.h" #include "tscProfile.h"
#include "tscSQLParser.h"
#include "tscSecondaryMerge.h" #include "tscSecondaryMerge.h"
#include "tscUtil.h" #include "tscUtil.h"
#include "tsclient.h" #include "tsclient.h"
#include "tscompression.h" #include "tscompression.h"
#include "tsocket.h" #include "tsocket.h"
#include "tsql.h"
#include "ttimer.h" #include "ttimer.h"
#include "tutil.h" #include "tutil.h"
TAOS *taos_connect_imp(const char *ip, const char *user, const char *pass, const char *db, int port, void (*fp)(void *, TAOS_RES *, int), TAOS *taos_connect_imp(const char *ip, const char *user, const char *pass, const char *db, uint16_t port,
void *param, void **taos) { void (*fp)(void *, TAOS_RES *, int), void *param, void **taos) {
STscObj *pObj; STscObj *pObj;
taos_init(); taos_init();
@ -66,10 +64,6 @@ TAOS *taos_connect_imp(const char *ip, const char *user, const char *pass, const
#ifdef CLUSTER #ifdef CLUSTER
if (ip && ip[0]) { if (ip && ip[0]) {
tscMgmtIpList.numOfIps = 2;
strcpy(tscMgmtIpList.ipstr[0], ip);
tscMgmtIpList.ip[0] = inet_addr(ip);
strcpy(tscMgmtIpList.ipstr[1], ip); strcpy(tscMgmtIpList.ipstr[1], ip);
tscMgmtIpList.ip[1] = inet_addr(ip); tscMgmtIpList.ip[1] = inet_addr(ip);
} }
@ -87,7 +81,7 @@ TAOS *taos_connect_imp(const char *ip, const char *user, const char *pass, const
globalCode = TSDB_CODE_CLI_OUT_OF_MEMORY; globalCode = TSDB_CODE_CLI_OUT_OF_MEMORY;
return NULL; return NULL;
} }
memset(pObj, 0, sizeof(STscObj)); memset(pObj, 0, sizeof(STscObj));
pObj->signature = pObj; pObj->signature = pObj;
@ -119,7 +113,7 @@ TAOS *taos_connect_imp(const char *ip, const char *user, const char *pass, const
free(pObj); free(pObj);
return NULL; return NULL;
} }
memset(pSql, 0, sizeof(SSqlObj)); memset(pSql, 0, sizeof(SSqlObj));
pSql->pTscObj = pObj; pSql->pTscObj = pObj;
pSql->signature = pSql; pSql->signature = pSql;
@ -156,10 +150,10 @@ TAOS *taos_connect_imp(const char *ip, const char *user, const char *pass, const
return pObj; return pObj;
} }
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, int port) { TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
if (ip != NULL && (strcmp("127.0.0.1", ip) == 0 || strcasecmp("localhost", ip) == 0)) { if (ip == NULL || (ip != NULL && (strcmp("127.0.0.1", ip) == 0 || strcasecmp("localhost", ip) == 0))) {
#ifdef CLUSTER #ifdef CLUSTER
ip = tsPrivateIp; ip = tsMasterIp;
#else #else
ip = tsServerIpStr; ip = tsServerIpStr;
#endif #endif
@ -168,47 +162,21 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha
void *taos = taos_connect_imp(ip, user, pass, db, port, NULL, NULL, NULL); void *taos = taos_connect_imp(ip, user, pass, db, port, NULL, NULL, NULL);
if (taos != NULL) { if (taos != NULL) {
STscObj* pObj = (STscObj*) taos; STscObj *pObj = (STscObj *)taos;
// version compare only requires the first 3 segments of the version string // version compare only requires the first 3 segments of the version string
int32_t comparedSegments = 3; int code = taosCheckVersion(version, taos_get_server_info(taos), 3);
char client_version[64] = {0}; if (code != 0) {
char server_version[64] = {0}; pObj->pSql->res.code = code;
int clientVersionNumber[4] = {0};
int serverVersionNumber[4] = {0};
strcpy(client_version, version);
strcpy(server_version, taos_get_server_info(taos));
if (!taosGetVersionNumber(client_version, clientVersionNumber)) {
tscError("taos:%p, invalid client version:%s", taos, client_version);
pObj->pSql->res.code = TSDB_CODE_INVALID_CLIENT_VERSION;
taos_close(taos); taos_close(taos);
return NULL; return NULL;
} }
if (!taosGetVersionNumber(server_version, serverVersionNumber)) {
tscError("taos:%p, invalid server version:%s", taos, server_version);
pObj->pSql->res.code = TSDB_CODE_INVALID_CLIENT_VERSION;
taos_close(taos);
return NULL;
}
for(int32_t i = 0; i < comparedSegments; ++i) {
if (clientVersionNumber[i] != serverVersionNumber[i]) {
tscError("taos:%p, the %d-th number of server version:%s not matched with client version:%s, close connection",
taos, i, server_version, version);
pObj->pSql->res.code = TSDB_CODE_INVALID_CLIENT_VERSION;
taos_close(taos);
return NULL;
}
}
} }
return taos; return taos;
} }
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, int port, void (*fp)(void *, TAOS_RES *, int), TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
void *param, void **taos) { void *param, void **taos) {
#ifndef CLUSTER #ifndef CLUSTER
if (ip == NULL) { if (ip == NULL) {
@ -231,11 +199,17 @@ void taos_close(TAOS *taos) {
} }
} }
int taos_query_imp(STscObj* pObj, SSqlObj* pSql) { int taos_query_imp(STscObj *pObj, SSqlObj *pSql) {
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
pRes->numOfRows = 1; pRes->numOfRows = 1;
pRes->numOfTotal = 0; pRes->numOfTotal = 0;
pSql->asyncTblPos = NULL;
if (NULL != pSql->pTableHashList) {
taosCleanUpIntHash(pSql->pTableHashList);
pSql->pTableHashList = NULL;
}
tscTrace("%p SQL: %s pObj:%p", pSql, pSql->sqlstr, pObj); tscTrace("%p SQL: %s pObj:%p", pSql, pSql->sqlstr, pObj);
pRes->code = (uint8_t)tsParseSql(pSql, pObj->acctId, pObj->db, false); pRes->code = (uint8_t)tsParseSql(pSql, pObj->acctId, pObj->db, false);
@ -248,11 +222,16 @@ int taos_query_imp(STscObj* pObj, SSqlObj* pSql) {
pRes->qhandle = 0; pRes->qhandle = 0;
pSql->thandle = NULL; pSql->thandle = NULL;
if (pRes->code != TSDB_CODE_SUCCESS) return pRes->code; if (pRes->code == TSDB_CODE_SUCCESS) {
tscDoQuery(pSql);
}
tscDoQuery(pSql); if (pRes->code == TSDB_CODE_SUCCESS) {
tscTrace("%p SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pObj), pObj);
} else {
tscError("%p SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pObj), pObj);
}
tscTrace("%p SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pObj), pObj);
if (pRes->code != TSDB_CODE_SUCCESS) { if (pRes->code != TSDB_CODE_SUCCESS) {
tscFreeSqlObjPartial(pSql); tscFreeSqlObjPartial(pSql);
} }
@ -271,17 +250,22 @@ int taos_query(TAOS *taos, const char *sqlstr) {
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
size_t sqlLen = strlen(sqlstr); size_t sqlLen = strlen(sqlstr);
if (sqlLen > TSDB_MAX_SQL_LEN) { if (sqlLen > tsMaxSQLStringLen) {
tscError("%p sql too long", pSql); pRes->code =
pRes->code = TSDB_CODE_INVALID_SQL; tscInvalidSQLErrMsg(pSql->cmd.payload, "sql too long", NULL); // set the additional error msg for invalid sql
tscError("%p SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
return pRes->code; return pRes->code;
} }
taosNotePrintTsc(sqlstr);
void *sql = realloc(pSql->sqlstr, sqlLen + 1); void *sql = realloc(pSql->sqlstr, sqlLen + 1);
if (sql == NULL) { if (sql == NULL) {
pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY; pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
tscError("%p failed to malloc sql string buffer", pSql); tscError("%p failed to malloc sql string buffer, reason:%s", pSql, strerror(errno));
tscTrace("%p SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
tscError("%p SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
return pRes->code; return pRes->code;
} }
@ -448,25 +432,56 @@ static void **getOneRowFromBuf(SSqlObj *pSql) {
return pRes->tsrow; return pRes->tsrow;
} }
static bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
bool hasData = true;
SSqlCmd *pCmd = &pSql->cmd;
if (tscProjectionQueryOnMetric(pCmd)) {
bool allSubqueryExhausted = true;
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SSqlRes *pRes1 = &pSql->pSubs[i]->res;
SSqlCmd *pCmd1 = &pSql->pSubs[i]->cmd;
SMeterMetaInfo *pMetaInfo = tscGetMeterMetaInfo(pCmd1, 0);
assert(pCmd1->numOfTables == 1);
/*
* if the global limitation is not reached, and current result has not exhausted, or next more vnodes are
* available, go on
*/
if (pMetaInfo->vnodeIndex < pMetaInfo->pMetricMeta->numOfVnodes && pRes1->row < pRes1->numOfRows &&
(!tscHasReachLimitation(pSql->pSubs[i]))) {
allSubqueryExhausted = false;
break;
}
}
hasData = !allSubqueryExhausted;
} else { // otherwise, in case inner join, if any subquery exhausted, query completed.
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SSqlRes *pRes1 = &pSql->pSubs[i]->res;
if ((pRes1->row >= pRes1->numOfRows && tscHasReachLimitation(pSql->pSubs[i]) &&
tscProjectionQueryOnTable(&pSql->pSubs[i]->cmd)) ||
(pRes1->numOfRows == 0)) {
hasData = false;
break;
}
}
}
return hasData;
}
static void **tscJoinResultsetFromBuf(SSqlObj *pSql) { static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
while (1) { while (1) {
bool hasData = true; if (!tscHashRemainDataInSubqueryResultSet(pSql)) { // free all sub sqlobj
tscTrace("%p at least one subquery exhausted, free all other %d subqueries", pSql, pSql->numOfSubs - 1);
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
SSqlRes *pRes1 = &pSql->pSubs[i]->res;
// in case inner join, if any subquery exhausted, query completed
if (pRes1->numOfRows == 0) {
hasData = false;
break;
}
}
if (!hasData) { // free all sub sqlobj
tscTrace("%p one subquery exhausted, free other %d subquery", pSql, pSql->numOfSubs - 1);
SSubqueryState *pState = NULL; SSubqueryState *pState = NULL;
@ -484,41 +499,32 @@ static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
} }
if (pRes->tsrow == NULL) { if (pRes->tsrow == NULL) {
pRes->tsrow = malloc(sizeof(void *) * pCmd->exprsInfo.numOfExprs); pRes->tsrow = malloc(POINTER_BYTES * pCmd->exprsInfo.numOfExprs);
} }
bool success = false; bool success = false;
if (pSql->numOfSubs >= 2) { if (pSql->numOfSubs >= 2) { // do merge result
// do merge result
SSqlRes *pRes1 = &pSql->pSubs[0]->res; SSqlRes *pRes1 = &pSql->pSubs[0]->res;
SSqlRes *pRes2 = &pSql->pSubs[1]->res; SSqlRes *pRes2 = &pSql->pSubs[1]->res;
while (pRes1->row < pRes1->numOfRows && pRes2->row < pRes2->numOfRows) { if (pRes1->row < pRes1->numOfRows && pRes2->row < pRes2->numOfRows) {
doSetResultRowData(pSql->pSubs[0]); doSetResultRowData(pSql->pSubs[0]);
doSetResultRowData(pSql->pSubs[1]); doSetResultRowData(pSql->pSubs[1]);
// TSKEY key1 = *(TSKEY *)pRes1->tsrow[0];
TSKEY key1 = *(TSKEY *)pRes1->tsrow[0]; // TSKEY key2 = *(TSKEY *)pRes2->tsrow[0];
TSKEY key2 = *(TSKEY *)pRes2->tsrow[0]; // printf("first:%" PRId64 ", second:%" PRId64 "\n", key1, key2);
success = true;
if (key1 == key2) { pRes1->row++;
success = true; pRes2->row++;
pRes1->row++;
pRes2->row++;
break;
} else if (key1 < key2) {
pRes1->row++;
} else if (key1 > key2) {
pRes2->row++;
}
} }
} else { } else { // only one subquery
SSqlRes *pRes1 = &pSql->pSubs[0]->res; SSqlRes *pRes1 = &pSql->pSubs[0]->res;
doSetResultRowData(pSql->pSubs[0]); doSetResultRowData(pSql->pSubs[0]);
success = (pRes1->row++ < pRes1->numOfRows); success = (pRes1->row++ < pRes1->numOfRows);
} }
if (success) { if (success) { // current row of final output has been built, return to app
for (int32_t i = 0; i < pCmd->exprsInfo.numOfExprs; ++i) { for (int32_t i = 0; i < pCmd->exprsInfo.numOfExprs; ++i) {
int32_t tableIndex = pRes->pColumnIndex[i].tableIndex; int32_t tableIndex = pRes->pColumnIndex[i].tableIndex;
int32_t columnIndex = pRes->pColumnIndex[i].columnIndex; int32_t columnIndex = pRes->pColumnIndex[i].columnIndex;
@ -528,7 +534,7 @@ static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
} }
break; break;
} else { } else { // continue retrieve data from vnode
tscFetchDatablockFromSubquery(pSql); tscFetchDatablockFromSubquery(pSql);
if (pRes->code != TSDB_CODE_SUCCESS) { if (pRes->code != TSDB_CODE_SUCCESS) {
return NULL; return NULL;
@ -550,9 +556,12 @@ TAOS_ROW taos_fetch_row_impl(TAOS_RES *res) {
if (pCmd->command == TSDB_SQL_METRIC_JOIN_RETRIEVE) { if (pCmd->command == TSDB_SQL_METRIC_JOIN_RETRIEVE) {
tscFetchDatablockFromSubquery(pSql); tscFetchDatablockFromSubquery(pSql);
if (pRes->code == TSDB_CODE_SUCCESS) { if (pRes->code == TSDB_CODE_SUCCESS) {
tscTrace("%p data from all subqueries have been retrieved to client", pSql);
return tscJoinResultsetFromBuf(pSql); return tscJoinResultsetFromBuf(pSql);
} else { } else {
tscTrace("%p retrieve data from subquery failed, code:%d", pSql, pRes->code);
return NULL; return NULL;
} }
@ -593,7 +602,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0); SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
// reach the maximum number of output rows, abort // reach the maximum number of output rows, abort
if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) { if (tscHasReachLimitation(pSql)) {
return NULL; return NULL;
} }
@ -606,7 +615,15 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
assert((pRes->offset >= 0 && pRes->numOfRows == 0) || (pRes->offset == 0 && pRes->numOfRows >= 0)); assert((pRes->offset >= 0 && pRes->numOfRows == 0) || (pRes->offset == 0 && pRes->numOfRows >= 0));
if ((++pCmd->vnodeIdx) < pMeterMetaInfo->pMetricMeta->numOfVnodes) { /*
* For project query with super table join, the numOfSub is equalled to the number of all subqueries, so
* we need to reset the value of numOfSubs to be 0.
*
* For super table join with projection query, if anyone of the subquery is exhausted, the query completed.
*/
pSql->numOfSubs = 0;
if ((++pMeterMetaInfo->vnodeIndex) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
pCmd->command = TSDB_SQL_SELECT; pCmd->command = TSDB_SQL_SELECT;
assert(pSql->fp == NULL); assert(pSql->fp == NULL);
tscProcessSql(pSql); tscProcessSql(pSql);
@ -614,7 +631,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
} }
// check!!! // check!!!
if (rows != NULL || pCmd->vnodeIdx >= pMeterMetaInfo->pMetricMeta->numOfVnodes) { if (rows != NULL || pMeterMetaInfo->vnodeIndex >= pMeterMetaInfo->pMetricMeta->numOfVnodes) {
break; break;
} }
} }
@ -640,7 +657,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
nRows = taos_fetch_block_impl(res, rows); nRows = taos_fetch_block_impl(res, rows);
while (*rows == NULL && tscProjectionQueryOnMetric(pCmd)) { while (*rows == NULL && tscProjectionQueryOnMetric(pCmd)) {
/* reach the maximum number of output rows, abort */ /* reach the maximum number of output rows, abort */
if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) { if (tscHasReachLimitation(pSql)) {
return 0; return 0;
} }
@ -650,11 +667,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
pCmd->limit.limit = pSql->cmd.globalLimit - pRes->numOfTotal; pCmd->limit.limit = pSql->cmd.globalLimit - pRes->numOfTotal;
pCmd->limit.offset = pRes->offset; pCmd->limit.offset = pRes->offset;
#ifdef CLUSTER if ((++pMeterMetaInfo->vnodeIndex) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
if ((++pSql->cmd.vnodeIdx) <= pMeterMetaInfo->pMetricMeta->numOfVnodes) {
#else
if ((++pSql->cmd.vnodeIdx) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
#endif
pSql->cmd.command = TSDB_SQL_SELECT; pSql->cmd.command = TSDB_SQL_SELECT;
assert(pSql->fp == NULL); assert(pSql->fp == NULL);
tscProcessSql(pSql); tscProcessSql(pSql);
@ -662,7 +675,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
} }
// check!!! // check!!!
if (*rows != NULL || pCmd->vnodeIdx >= pMeterMetaInfo->pMetricMeta->numOfVnodes) { if (*rows != NULL || pMeterMetaInfo->vnodeIndex >= pMeterMetaInfo->pMetricMeta->numOfVnodes) {
break; break;
} }
} }
@ -784,9 +797,8 @@ int taos_errno(TAOS *taos) {
} }
char *taos_errstr(TAOS *taos) { char *taos_errstr(TAOS *taos) {
STscObj * pObj = (STscObj *)taos; STscObj *pObj = (STscObj *)taos;
unsigned char code; uint8_t code;
char temp[256] = {0};
if (pObj == NULL || pObj->signature != pObj) return tsError[globalCode]; if (pObj == NULL || pObj->signature != pObj) return tsError[globalCode];
@ -795,12 +807,15 @@ char *taos_errstr(TAOS *taos) {
else else
code = pObj->pSql->res.code; code = pObj->pSql->res.code;
// for invalid sql, additional information is attached to explain why the sql is invalid
if (code == TSDB_CODE_INVALID_SQL) { if (code == TSDB_CODE_INVALID_SQL) {
snprintf(temp, tListLen(temp), "invalid SQL: %s", pObj->pSql->cmd.payload);
strcpy(pObj->pSql->cmd.payload, temp);
return pObj->pSql->cmd.payload; return pObj->pSql->cmd.payload;
} else { } else {
return tsError[code]; if (code < 0 || code > TSDB_CODE_MAX_ERROR_CODE) {
return tsError[TSDB_CODE_SUCCESS];
} else {
return tsError[code];
}
} }
} }
@ -868,7 +883,7 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
break; break;
case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_BIGINT:
len += sprintf(str + len, "%lld ", *((int64_t *)row[i])); len += sprintf(str + len, "%" PRId64 " ", *((int64_t *)row[i]));
break; break;
case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_FLOAT:
@ -886,15 +901,14 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
size_t xlen = strlen(row[i]); size_t xlen = strlen(row[i]);
size_t trueLen = MIN(xlen, fields[i].bytes); size_t trueLen = MIN(xlen, fields[i].bytes);
memcpy(str + len, (char*) row[i], trueLen); memcpy(str + len, (char *)row[i], trueLen);
str[len + trueLen] = ' '; str[len + trueLen] = ' ';
len += (trueLen + 1); len += (trueLen + 1);
} } break;
break;
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP:
len += sprintf(str + len, "%lld ", *((int64_t *)row[i])); len += sprintf(str + len, "%" PRId64 " ", *((int64_t *)row[i]));
break; break;
case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_BOOL:
@ -923,7 +937,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
tscTrace("%p Valid SQL: %s pObj:%p", pSql, sql, pObj); tscTrace("%p Valid SQL: %s pObj:%p", pSql, sql, pObj);
int32_t sqlLen = strlen(sql); int32_t sqlLen = strlen(sql);
if (sqlLen > TSDB_MAX_SQL_LEN) { if (sqlLen > tsMaxSQLStringLen) {
tscError("%p sql too long", pSql); tscError("%p sql too long", pSql);
pRes->code = TSDB_CODE_INVALID_SQL; pRes->code = TSDB_CODE_INVALID_SQL;
return pRes->code; return pRes->code;
@ -939,6 +953,12 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
strtolower(pSql->sqlstr, sql); strtolower(pSql->sqlstr, sql);
pSql->asyncTblPos = NULL;
if (NULL != pSql->pTableHashList) {
taosCleanUpIntHash(pSql->pTableHashList);
pSql->pTableHashList = NULL;
}
pRes->code = (uint8_t)tsParseSql(pSql, pObj->acctId, pObj->db, false); pRes->code = (uint8_t)tsParseSql(pSql, pObj->acctId, pObj->db, false);
int code = pRes->code; int code = pRes->code;
@ -948,7 +968,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
return code; return code;
} }
static int tscParseTblNameList(SSqlObj *pSql, const char* tblNameList, int32_t tblListLen) { static int tscParseTblNameList(SSqlObj *pSql, const char *tblNameList, int32_t tblListLen) {
// must before clean the sqlcmd object // must before clean the sqlcmd object
tscRemoveAllMeterMetaInfo(&pSql->cmd, false); tscRemoveAllMeterMetaInfo(&pSql->cmd, false);
tscCleanSqlCmd(&pSql->cmd); tscCleanSqlCmd(&pSql->cmd);
@ -959,11 +979,11 @@ static int tscParseTblNameList(SSqlObj *pSql, const char* tblNameList, int32_t t
pCmd->count = 0; pCmd->count = 0;
int code = TSDB_CODE_INVALID_METER_ID; int code = TSDB_CODE_INVALID_METER_ID;
char *str = (char*) tblNameList; char *str = (char *)tblNameList;
SMeterMetaInfo *pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pCmd); SMeterMetaInfo *pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pCmd);
if ((code = tscAllocPayload(pCmd, tblListLen+16)) != TSDB_CODE_SUCCESS) { if ((code = tscAllocPayload(pCmd, tblListLen + 16)) != TSDB_CODE_SUCCESS) {
return code; return code;
} }
@ -985,7 +1005,7 @@ static int tscParseTblNameList(SSqlObj *pSql, const char* tblNameList, int32_t t
strtrim(tblName); strtrim(tblName);
len = (uint32_t)strlen(tblName); len = (uint32_t)strlen(tblName);
SSQLToken sToken = {.n = len, .type = TK_ID, .z = tblName}; SSQLToken sToken = {.n = len, .type = TK_ID, .z = tblName};
tSQLGetToken(tblName, &sToken.type); tSQLGetToken(tblName, &sToken.type);
@ -1029,7 +1049,7 @@ static int tscParseTblNameList(SSqlObj *pSql, const char* tblNameList, int32_t t
} }
int taos_load_table_info(TAOS *taos, const char *tableNameList) { int taos_load_table_info(TAOS *taos, const char *tableNameList) {
const int32_t MAX_TABLE_NAME_LENGTH = 12*1024*1024; // 12MB list const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024; // 12MB list
STscObj *pObj = (STscObj *)taos; STscObj *pObj = (STscObj *)taos;
if (pObj == NULL || pObj->signature != pObj) { if (pObj == NULL || pObj->signature != pObj) {
@ -1053,7 +1073,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
return pRes->code; return pRes->code;
} }
char* str = calloc(1, tblListLen + 1); char *str = calloc(1, tblListLen + 1);
if (str == NULL) { if (str == NULL) {
pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY; pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
tscError("%p failed to malloc sql string buffer", pSql); tscError("%p failed to malloc sql string buffer", pSql);
@ -1061,7 +1081,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
} }
strtolower(str, tableNameList); strtolower(str, tableNameList);
pRes->code = (uint8_t) tscParseTblNameList(pSql, str, tblListLen); pRes->code = (uint8_t)tscParseTblNameList(pSql, str, tblListLen);
/* /*
* set the qhandle to 0 before return in order to erase the qhandle value assigned in the previous successful query. * set the qhandle to 0 before return in order to erase the qhandle value assigned in the previous successful query.

View File

@ -15,7 +15,7 @@
#include "os.h" #include "os.h"
#include "tlog.h" #include "tlog.h"
#include "tsql.h" #include "tscSQLParser.h"
#include "ttime.h" #include "ttime.h"
#include "ttimer.h" #include "ttimer.h"
#include "tutil.h" #include "tutil.h"
@ -85,7 +85,7 @@ static void tscProcessStreamLaunchQuery(SSchedMsg *pMsg) {
// failed to get meter/metric meta, retry in 10sec. // failed to get meter/metric meta, retry in 10sec.
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
int64_t retryDelayTime = tscGetRetryDelayTime(pStream->slidingTime, pStream->precision); int64_t retryDelayTime = tscGetRetryDelayTime(pStream->slidingTime, pStream->precision);
tscError("%p stream:%p,get metermeta failed, retry in %lldms", pStream->pSql, pStream, retryDelayTime); tscError("%p stream:%p,get metermeta failed, retry in %" PRId64 "ms", pStream->pSql, pStream, retryDelayTime);
tscSetRetryTimer(pStream, pSql, retryDelayTime); tscSetRetryTimer(pStream, pSql, retryDelayTime);
return; return;
@ -136,7 +136,7 @@ static void tscProcessStreamQueryCallback(void *param, TAOS_RES *tres, int numOf
SSqlStream *pStream = (SSqlStream *)param; SSqlStream *pStream = (SSqlStream *)param;
if (tres == NULL || numOfRows < 0) { if (tres == NULL || numOfRows < 0) {
int64_t retryDelay = tscGetRetryDelayTime(pStream->slidingTime, pStream->precision); int64_t retryDelay = tscGetRetryDelayTime(pStream->slidingTime, pStream->precision);
tscError("%p stream:%p, query data failed, code:%d, retry in %lldms", pStream->pSql, pStream, numOfRows, tscError("%p stream:%p, query data failed, code:%d, retry in %" PRId64 "ms", pStream->pSql, pStream, numOfRows,
retryDelay); retryDelay);
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pStream->pSql->cmd, 0); SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pStream->pSql->cmd, 0);
@ -158,7 +158,7 @@ static void tscSetTimestampForRes(SSqlStream *pStream, SSqlObj *pSql) {
if (timestamp != actualTimestamp) { if (timestamp != actualTimestamp) {
// reset the timestamp of each agg point by using start time of each interval // reset the timestamp of each agg point by using start time of each interval
*((int64_t *)pRes->data) = actualTimestamp; *((int64_t *)pRes->data) = actualTimestamp;
tscWarn("%p stream:%p, timestamp of points is:%lld, reset to %lld", pSql, pStream, timestamp, actualTimestamp); tscWarn("%p stream:%p, timestamp of points is:%" PRId64 ", reset to %" PRId64 "", pSql, pStream, timestamp, actualTimestamp);
} }
} }
@ -169,7 +169,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
if (pSql == NULL || numOfRows < 0) { if (pSql == NULL || numOfRows < 0) {
int64_t retryDelayTime = tscGetRetryDelayTime(pStream->slidingTime, pStream->precision); int64_t retryDelayTime = tscGetRetryDelayTime(pStream->slidingTime, pStream->precision);
tscError("%p stream:%p, retrieve data failed, code:%d, retry in %lldms", pSql, pStream, numOfRows, retryDelayTime); tscError("%p stream:%p, retrieve data failed, code:%d, retry in %" PRId64 "ms", pSql, pStream, numOfRows, retryDelayTime);
tscClearMeterMetaInfo(pMeterMetaInfo, true); tscClearMeterMetaInfo(pMeterMetaInfo, true);
tscSetRetryTimer(pStream, pStream->pSql, retryDelayTime); tscSetRetryTimer(pStream, pStream->pSql, retryDelayTime);
@ -235,7 +235,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
/* no resuls in the query range, retry */ /* no resuls in the query range, retry */
// todo set retry dynamic time // todo set retry dynamic time
int32_t retry = tsProjectExecInterval; int32_t retry = tsProjectExecInterval;
tscError("%p stream:%p, retrieve no data, code:%d, retry in %lldms", pSql, pStream, numOfRows, retry); tscError("%p stream:%p, retrieve no data, code:%d, retry in %" PRId64 "ms", pSql, pStream, numOfRows, retry);
tscClearSqlMetaInfoForce(&(pStream->pSql->cmd)); tscClearSqlMetaInfoForce(&(pStream->pSql->cmd));
tscSetRetryTimer(pStream, pStream->pSql, retry); tscSetRetryTimer(pStream, pStream->pSql, retry);
@ -265,7 +265,7 @@ static void tscSetRetryTimer(SSqlStream *pStream, SSqlObj *pSql, int64_t timer)
/* /*
* current time window will be closed, since it too early to exceed the maxRetentWindow value * current time window will be closed, since it too early to exceed the maxRetentWindow value
*/ */
tscTrace("%p stream:%p, etime:%lld is too old, exceeds the max retention time window:%lld, stop the stream", tscTrace("%p stream:%p, etime:%" PRId64 " is too old, exceeds the max retention time window:%" PRId64 ", stop the stream",
pStream->pSql, pStream, pStream->stime, pStream->etime); pStream->pSql, pStream, pStream->stime, pStream->etime);
// TODO : How to terminate stream here // TODO : How to terminate stream here
taos_close_stream(pStream); taos_close_stream(pStream);
@ -276,10 +276,10 @@ static void tscSetRetryTimer(SSqlStream *pStream, SSqlObj *pSql, int64_t timer)
return; return;
} }
tscTrace("%p stream:%p, next query start at %lld, in %lldms. query range %lld-%lld", pStream->pSql, pStream, tscTrace("%p stream:%p, next query start at %" PRId64 ", in %" PRId64 "ms. query range %" PRId64 "-%" PRId64 "", pStream->pSql, pStream,
now + timer, timer, pStream->stime, etime); now + timer, timer, pStream->stime, etime);
} else { } else {
tscTrace("%p stream:%p, next query start at %lld, in %lldms. query range %lld-%lld", pStream->pSql, pStream, tscTrace("%p stream:%p, next query start at %" PRId64 ", in %" PRId64 "ms. query range %" PRId64 "-%" PRId64 "", pStream->pSql, pStream,
pStream->stime, timer, pStream->stime - pStream->interval, pStream->stime - 1); pStream->stime, timer, pStream->stime - pStream->interval, pStream->stime - 1);
} }
@ -299,7 +299,7 @@ static void tscSetNextLaunchTimer(SSqlStream *pStream, SSqlObj *pSql) {
*/ */
timer = pStream->slidingTime; timer = pStream->slidingTime;
if (pStream->stime > pStream->etime) { if (pStream->stime > pStream->etime) {
tscTrace("%p stream:%p, stime:%lld is larger than end time: %lld, stop the stream", pStream->pSql, pStream, tscTrace("%p stream:%p, stime:%" PRId64 " is larger than end time: %" PRId64 ", stop the stream", pStream->pSql, pStream,
pStream->stime, pStream->etime); pStream->stime, pStream->etime);
// TODO : How to terminate stream here // TODO : How to terminate stream here
taos_close_stream(pStream); taos_close_stream(pStream);
@ -353,7 +353,7 @@ static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
int64_t minIntervalTime = int64_t minIntervalTime =
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinIntervalTime * 1000L : tsMinIntervalTime; (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinIntervalTime * 1000L : tsMinIntervalTime;
if (pCmd->nAggTimeInterval < minIntervalTime) { if (pCmd->nAggTimeInterval < minIntervalTime) {
tscWarn("%p stream:%p, original sample interval:%ld too small, reset to:%lld", pSql, pStream, tscWarn("%p stream:%p, original sample interval:%ld too small, reset to:%" PRId64 "", pSql, pStream,
pCmd->nAggTimeInterval, minIntervalTime); pCmd->nAggTimeInterval, minIntervalTime);
pCmd->nAggTimeInterval = minIntervalTime; pCmd->nAggTimeInterval = minIntervalTime;
} }
@ -368,14 +368,14 @@ static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinSlidingTime * 1000L : tsMinSlidingTime; (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinSlidingTime * 1000L : tsMinSlidingTime;
if (pCmd->nSlidingTime < minSlidingTime) { if (pCmd->nSlidingTime < minSlidingTime) {
tscWarn("%p stream:%p, original sliding value:%lld too small, reset to:%lld", pSql, pStream, pCmd->nSlidingTime, tscWarn("%p stream:%p, original sliding value:%" PRId64 " too small, reset to:%" PRId64 "", pSql, pStream, pCmd->nSlidingTime,
minSlidingTime); minSlidingTime);
pCmd->nSlidingTime = minSlidingTime; pCmd->nSlidingTime = minSlidingTime;
} }
if (pCmd->nSlidingTime > pCmd->nAggTimeInterval) { if (pCmd->nSlidingTime > pCmd->nAggTimeInterval) {
tscWarn("%p stream:%p, sliding value:%lld can not be larger than interval range, reset to:%lld", pSql, pStream, tscWarn("%p stream:%p, sliding value:%" PRId64 " can not be larger than interval range, reset to:%" PRId64 "", pSql, pStream,
pCmd->nSlidingTime, pCmd->nAggTimeInterval); pCmd->nSlidingTime, pCmd->nAggTimeInterval);
pCmd->nSlidingTime = pCmd->nAggTimeInterval; pCmd->nSlidingTime = pCmd->nAggTimeInterval;
@ -401,11 +401,11 @@ static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, in
} else { // timewindow based aggregation stream } else { // timewindow based aggregation stream
if (stime == 0) { // no data in meter till now if (stime == 0) { // no data in meter till now
stime = ((int64_t)taosGetTimestamp(pStream->precision) / pStream->interval) * pStream->interval; stime = ((int64_t)taosGetTimestamp(pStream->precision) / pStream->interval) * pStream->interval;
tscWarn("%p stream:%p, last timestamp:0, reset to:%lld", pSql, pStream, stime); tscWarn("%p stream:%p, last timestamp:0, reset to:%" PRId64 "", pSql, pStream, stime);
} else { } else {
int64_t newStime = (stime / pStream->interval) * pStream->interval; int64_t newStime = (stime / pStream->interval) * pStream->interval;
if (newStime != stime) { if (newStime != stime) {
tscWarn("%p stream:%p, last timestamp:%lld, reset to:%lld", pSql, pStream, stime, newStime); tscWarn("%p stream:%p, last timestamp:%" PRId64 ", reset to:%" PRId64 "", pSql, pStream, stime, newStime);
stime = newStime; stime = newStime;
} }
} }
@ -447,7 +447,10 @@ static void setErrorInfo(STscObj* pObj, int32_t code, char* info) {
SSqlCmd* pCmd = &pObj->pSql->cmd; SSqlCmd* pCmd = &pObj->pSql->cmd;
pObj->pSql->res.code = code; pObj->pSql->res.code = code;
strncpy(pCmd->payload, info, pCmd->payloadLen);
if (info != NULL) {
strncpy(pCmd->payload, info, pCmd->payloadLen);
}
} }
TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row), TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row),
@ -537,7 +540,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
int64_t starttime = tscGetLaunchTimestamp(pStream); int64_t starttime = tscGetLaunchTimestamp(pStream);
taosTmrReset(tscProcessStreamTimer, starttime, pStream, tscTmr, &pStream->pTimer); taosTmrReset(tscProcessStreamTimer, starttime, pStream, tscTmr, &pStream->pTimer);
tscTrace("%p stream:%p is opened, query on:%s, interval:%lld, sliding:%lld, first launched in:%lld, sql:%s", pSql, tscTrace("%p stream:%p is opened, query on:%s, interval:%" PRId64 ", sliding:%" PRId64 ", first launched in:%" PRId64 ", sql:%s", pSql,
pStream, pMeterMetaInfo->name, pStream->interval, pStream->slidingTime, starttime, sqlstr); pStream, pMeterMetaInfo->name, pStream->interval, pStream->slidingTime, starttime, sqlstr);
return pStream; return pStream;
@ -546,7 +549,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
void taos_close_stream(TAOS_STREAM *handle) { void taos_close_stream(TAOS_STREAM *handle) {
SSqlStream *pStream = (SSqlStream *)handle; SSqlStream *pStream = (SSqlStream *)handle;
SSqlObj *pSql = (SSqlObj *)__sync_val_compare_and_swap_64(&pStream->pSql, pStream->pSql, 0); SSqlObj *pSql = (SSqlObj *)atomic_exchange_ptr(&pStream->pSql, 0);
if (pSql == NULL) { if (pSql == NULL) {
return; return;
} }

View File

@ -13,7 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <signal.h> #include "os.h"
#include "shash.h" #include "shash.h"
#include "taos.h" #include "taos.h"
@ -56,7 +56,7 @@ TAOS_SUB *taos_subscribe(const char *host, const char *user, const char *pass, c
if (pSub->taos == NULL) { if (pSub->taos == NULL) {
tfree(pSub); tfree(pSub);
} else { } else {
char qstr[128]; char qstr[256] = {0};
sprintf(qstr, "use %s", db); sprintf(qstr, "use %s", db);
int res = taos_query(pSub->taos, qstr); int res = taos_query(pSub->taos, qstr);
if (res != 0) { if (res != 0) {
@ -64,7 +64,7 @@ TAOS_SUB *taos_subscribe(const char *host, const char *user, const char *pass, c
taos_close(pSub->taos); taos_close(pSub->taos);
tfree(pSub); tfree(pSub);
} else { } else {
sprintf(qstr, "select * from %s where _c0 > now+1000d", pSub->name); snprintf(qstr, tListLen(qstr), "select * from %s where _c0 > now+1000d", pSub->name);
if (taos_query(pSub->taos, qstr)) { if (taos_query(pSub->taos, qstr)) {
tscTrace("failed to select, reason:%s", taos_errstr(pSub->taos)); tscTrace("failed to select, reason:%s", taos_errstr(pSub->taos));
taos_close(pSub->taos); taos_close(pSub->taos);
@ -106,7 +106,7 @@ TAOS_ROW taos_consume(TAOS_SUB *tsub) {
pSub->stime = taosGetTimestampMs(); pSub->stime = taosGetTimestampMs();
sprintf(qstr, "select * from %s where _c0 > %lld order by _c0 asc", pSub->name, pSub->lastKey); sprintf(qstr, "select * from %s where _c0 > %" PRId64 " order by _c0 asc", pSub->name, pSub->lastKey);
if (taos_query(pSub->taos, qstr)) { if (taos_query(pSub->taos, qstr)) {
tscTrace("failed to select, reason:%s", taos_errstr(pSub->taos)); tscTrace("failed to select, reason:%s", taos_errstr(pSub->taos));
return NULL; return NULL;

View File

@ -13,13 +13,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h> #include "os.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "tscSyntaxtreefunction.h" #include "tscSyntaxtreefunction.h"
#include "tsql.h" #include "tscSQLParser.h"
#include "ttypes.h" #include "ttypes.h"
#include "tutil.h" #include "tutil.h"

View File

@ -13,15 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <locale.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include "os.h" #include "os.h"
#include "taosmsg.h" #include "taosmsg.h"
#include "tcache.h" #include "tcache.h"
@ -54,6 +45,10 @@ extern int tscEmbedded;
int tscNumOfThreads; int tscNumOfThreads;
static pthread_once_t tscinit = PTHREAD_ONCE_INIT; static pthread_once_t tscinit = PTHREAD_ONCE_INIT;
extern int tsTscEnableRecordSql;
extern int tsNumOfLogLines;
void taosInitNote(int numOfNoteLines, int maxNotes, char* lable);
void tscCheckDiskUsage(void *para, void *unused) { void tscCheckDiskUsage(void *para, void *unused) {
taosGetDisk(); taosGetDisk();
taosTmrReset(tscCheckDiskUsage, 1000, NULL, tscTmr, &tscCheckDiskUsageTmr); taosTmrReset(tscCheckDiskUsage, 1000, NULL, tscTmr, &tscCheckDiskUsageTmr);
@ -92,6 +87,12 @@ void taos_init_imp() {
tscTrace("Local IP address is:%s", tsLocalIp); tscTrace("Local IP address is:%s", tsLocalIp);
} }
taosSetCoreDump();
if (tsTscEnableRecordSql != 0) {
taosInitNote(tsNumOfLogLines / 10, 1, (char*)"tsc_note");
}
#ifdef CLUSTER #ifdef CLUSTER
tscMgmtIpList.numOfIps = 2; tscMgmtIpList.numOfIps = 2;
strcpy(tscMgmtIpList.ipstr[0], tsMasterIp); strcpy(tscMgmtIpList.ipstr[0], tsMasterIp);
@ -185,57 +186,57 @@ void taos_init_imp() {
tscConnCache = taosOpenConnCache(tsMaxMeterConnections * 2, taosCloseRpcConn, tscTmr, tsShellActivityTimer * 1000); tscConnCache = taosOpenConnCache(tsMaxMeterConnections * 2, taosCloseRpcConn, tscTmr, tsShellActivityTimer * 1000);
initialized = 1; initialized = 1;
tscTrace("taos client is initialized successfully"); tscTrace("client is initialized successfully");
tsInsertHeadSize = tsRpcHeadSize + sizeof(SShellSubmitMsg); tsInsertHeadSize = tsRpcHeadSize + sizeof(SShellSubmitMsg);
} }
void taos_init() { pthread_once(&tscinit, taos_init_imp); } void taos_init() { pthread_once(&tscinit, taos_init_imp); }
int taos_options(TSDB_OPTION option, const void *arg, ...) { static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
char * pStr = NULL; SGlobalConfig *cfg = NULL;
SGlobalConfig *cfg_configDir = tsGetConfigOption("configDir");
SGlobalConfig *cfg_activetimer = tsGetConfigOption("shellActivityTimer");
SGlobalConfig *cfg_locale = tsGetConfigOption("locale");
SGlobalConfig *cfg_charset = tsGetConfigOption("charset");
SGlobalConfig *cfg_timezone = tsGetConfigOption("timezone");
SGlobalConfig *cfg_socket = tsGetConfigOption("sockettype");
switch (option) { switch (option) {
case TSDB_OPTION_CONFIGDIR: case TSDB_OPTION_CONFIGDIR:
pStr = (char *)arg; cfg = tsGetConfigOption("configDir");
if (cfg_configDir && cfg_configDir->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) { assert(cfg != NULL);
if (cfg->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) {
strncpy(configDir, pStr, TSDB_FILENAME_LEN); strncpy(configDir, pStr, TSDB_FILENAME_LEN);
cfg_configDir->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
tscPrint("set config file directory:%s", pStr); tscPrint("set config file directory:%s", pStr);
} else { } else {
tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg_configDir->option, pStr, tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg->option, pStr,
tsCfgStatusStr[cfg_configDir->cfgStatus], (char *)cfg_configDir->ptr); tsCfgStatusStr[cfg->cfgStatus], (char *)cfg->ptr);
} }
break; break;
case TSDB_OPTION_SHELL_ACTIVITY_TIMER: case TSDB_OPTION_SHELL_ACTIVITY_TIMER:
if (cfg_activetimer && cfg_activetimer->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) { cfg = tsGetConfigOption("shellActivityTimer");
tsShellActivityTimer = atoi((char *)arg); assert(cfg != NULL);
if (cfg->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) {
tsShellActivityTimer = atoi(pStr);
if (tsShellActivityTimer < 1) tsShellActivityTimer = 1; if (tsShellActivityTimer < 1) tsShellActivityTimer = 1;
if (tsShellActivityTimer > 3600) tsShellActivityTimer = 3600; if (tsShellActivityTimer > 3600) tsShellActivityTimer = 3600;
cfg_activetimer->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
tscPrint("set shellActivityTimer:%d", tsShellActivityTimer); tscPrint("set shellActivityTimer:%d", tsShellActivityTimer);
} else { } else {
tscWarn("config option:%s, input value:%s, is configured by %s, use %d", cfg_activetimer->option, pStr, tscWarn("config option:%s, input value:%s, is configured by %s, use %d", cfg->option, pStr,
tsCfgStatusStr[cfg_activetimer->cfgStatus], (int32_t *)cfg_activetimer->ptr); tsCfgStatusStr[cfg->cfgStatus], (int32_t *)cfg->ptr);
} }
break; break;
case TSDB_OPTION_LOCALE: { // set locale case TSDB_OPTION_LOCALE: { // set locale
pStr = (char *)arg; cfg = tsGetConfigOption("locale");
assert(cfg != NULL);
size_t len = strlen(pStr); size_t len = strlen(pStr);
if (len == 0 || len > TSDB_LOCALE_LEN) { if (len == 0 || len > TSDB_LOCALE_LEN) {
tscPrint("Invalid locale:%s, use default", pStr); tscPrint("Invalid locale:%s, use default", pStr);
return -1; return -1;
} }
if (cfg_locale && cfg_charset && cfg_locale->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) { if (cfg->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) {
char sep = '.'; char sep = '.';
if (strlen(tsLocale) == 0) { // locale does not set yet if (strlen(tsLocale) == 0) { // locale does not set yet
@ -248,7 +249,7 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
if (locale != NULL) { if (locale != NULL) {
tscPrint("locale set, prev locale:%s, new locale:%s", tsLocale, locale); tscPrint("locale set, prev locale:%s, new locale:%s", tsLocale, locale);
cfg_locale->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
} else { // set the user-specified localed failed, use default LC_CTYPE as current locale } else { // set the user-specified localed failed, use default LC_CTYPE as current locale
locale = setlocale(LC_CTYPE, tsLocale); locale = setlocale(LC_CTYPE, tsLocale);
tscPrint("failed to set locale:%s, current locale:%s", pStr, tsLocale); tscPrint("failed to set locale:%s, current locale:%s", pStr, tsLocale);
@ -270,7 +271,7 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
} }
strncpy(tsCharset, charset, tListLen(tsCharset)); strncpy(tsCharset, charset, tListLen(tsCharset));
cfg_charset->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
} else { } else {
tscPrint("charset:%s is not valid in locale, charset remains:%s", charset, tsCharset); tscPrint("charset:%s is not valid in locale, charset remains:%s", charset, tsCharset);
@ -281,23 +282,24 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
tscPrint("charset remains:%s", tsCharset); tscPrint("charset remains:%s", tsCharset);
} }
} else { } else {
tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg_locale->option, pStr, tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg->option, pStr,
tsCfgStatusStr[cfg_locale->cfgStatus], (char *)cfg_locale->ptr); tsCfgStatusStr[cfg->cfgStatus], (char *)cfg->ptr);
} }
break; break;
} }
case TSDB_OPTION_CHARSET: { case TSDB_OPTION_CHARSET: {
/* set charset will override the value of charset, assigned during system locale changed */ /* set charset will override the value of charset, assigned during system locale changed */
pStr = (char *)arg; cfg = tsGetConfigOption("charset");
assert(cfg != NULL);
size_t len = strlen(pStr); size_t len = strlen(pStr);
if (len == 0 || len > TSDB_LOCALE_LEN) { if (len == 0 || len > TSDB_LOCALE_LEN) {
tscPrint("failed to set charset:%s", pStr); tscPrint("failed to set charset:%s", pStr);
return -1; return -1;
} }
if (cfg_charset && cfg_charset->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) { if (cfg->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) {
if (taosValidateEncodec(pStr)) { if (taosValidateEncodec(pStr)) {
if (strlen(tsCharset) == 0) { if (strlen(tsCharset) == 0) {
tscPrint("charset is set:%s", pStr); tscPrint("charset is set:%s", pStr);
@ -306,48 +308,71 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
} }
strncpy(tsCharset, pStr, tListLen(tsCharset)); strncpy(tsCharset, pStr, tListLen(tsCharset));
cfg_charset->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
} else { } else {
tscPrint("charset:%s not valid", pStr); tscPrint("charset:%s not valid", pStr);
} }
} else { } else {
tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg_charset->option, pStr, tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg->option, pStr,
tsCfgStatusStr[cfg_charset->cfgStatus], (char *)cfg_charset->ptr); tsCfgStatusStr[cfg->cfgStatus], (char *)cfg->ptr);
} }
break; break;
} }
case TSDB_OPTION_TIMEZONE: case TSDB_OPTION_TIMEZONE:
pStr = (char *)arg; cfg = tsGetConfigOption("timezone");
if (cfg_timezone && cfg_timezone->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) { assert(cfg != NULL);
if (cfg->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) {
strcpy(tsTimezone, pStr); strcpy(tsTimezone, pStr);
tsSetTimeZone(); tsSetTimeZone();
cfg_timezone->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
tscTrace("timezone set:%s, input:%s by taos_options", tsTimezone, pStr); tscTrace("timezone set:%s, input:%s by taos_options", tsTimezone, pStr);
} else { } else {
tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg_timezone->option, pStr, tscWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg->option, pStr,
tsCfgStatusStr[cfg_timezone->cfgStatus], (char *)cfg_timezone->ptr); tsCfgStatusStr[cfg->cfgStatus], (char *)cfg->ptr);
} }
break; break;
case TSDB_OPTION_SOCKET_TYPE: case TSDB_OPTION_SOCKET_TYPE:
if (cfg_socket && cfg_socket->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) { cfg = tsGetConfigOption("sockettype");
if (strcasecmp(arg, TAOS_SOCKET_TYPE_NAME_UDP) != 0 && strcasecmp(arg, TAOS_SOCKET_TYPE_NAME_TCP) != 0) { assert(cfg != NULL);
if (cfg->cfgStatus <= TSDB_CFG_CSTATUS_OPTION) {
if (strcasecmp(pStr, TAOS_SOCKET_TYPE_NAME_UDP) != 0 && strcasecmp(pStr, TAOS_SOCKET_TYPE_NAME_TCP) != 0) {
tscError("only 'tcp' or 'udp' allowed for configuring the socket type"); tscError("only 'tcp' or 'udp' allowed for configuring the socket type");
return -1; return -1;
} }
strncpy(tsSocketType, arg, tListLen(tsSocketType)); strncpy(tsSocketType, pStr, tListLen(tsSocketType));
cfg_socket->cfgStatus = TSDB_CFG_CSTATUS_OPTION; cfg->cfgStatus = TSDB_CFG_CSTATUS_OPTION;
tscPrint("socket type is set:%s", tsSocketType); tscPrint("socket type is set:%s", tsSocketType);
} }
break; break;
default: default:
// TODO return the correct error code to client in the format for taos_errstr()
tscError("Invalid option %d", option); tscError("Invalid option %d", option);
return -1; return -1;
} }
return 0; return 0;
} }
int taos_options(TSDB_OPTION option, const void *arg, ...) {
static int32_t lock = 0;
for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
if (i % 1000 == 0) {
tscPrint("haven't acquire lock after spin %d times.", i);
sched_yield();
}
}
int ret = taos_options_imp(option, (const char*)arg);
atomic_store_32(&lock, 0);
return ret;
}

View File

@ -13,10 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h>
#include <math.h>
#include <time.h>
#include "os.h" #include "os.h"
#include "ihash.h" #include "ihash.h"
#include "taosmsg.h" #include "taosmsg.h"
@ -55,7 +51,6 @@ void tscGetMetricMetaCacheKey(SSqlCmd* pCmd, char* str, uint64_t uid) {
assert(len < tListLen(tagIdBuf)); assert(len < tListLen(tagIdBuf));
const int32_t maxKeySize = TSDB_MAX_TAGS_LEN; // allowed max key size const int32_t maxKeySize = TSDB_MAX_TAGS_LEN; // allowed max key size
char* tmp = calloc(1, TSDB_MAX_SQL_LEN);
SCond* cond = tsGetMetricQueryCondPos(pTagCond, uid); SCond* cond = tsGetMetricQueryCondPos(pTagCond, uid);
@ -64,12 +59,24 @@ void tscGetMetricMetaCacheKey(SSqlCmd* pCmd, char* str, uint64_t uid) {
sprintf(join, "%s,%s", pTagCond->joinInfo.left.meterId, pTagCond->joinInfo.right.meterId); sprintf(join, "%s,%s", pTagCond->joinInfo.left.meterId, pTagCond->joinInfo.right.meterId);
} }
int32_t keyLen = // estimate the buffer size
snprintf(tmp, TSDB_MAX_SQL_LEN, "%s,%s,%s,%d,%s,[%s],%d", pMeterMetaInfo->name, size_t tbnameCondLen = pTagCond->tbnameCond.cond != NULL? strlen(pTagCond->tbnameCond.cond):0;
(cond != NULL ? cond->cond.z : NULL), pTagCond->tbnameCond.cond.n > 0 ? pTagCond->tbnameCond.cond.z : NULL, size_t redundantLen = 20;
size_t bufSize = strlen(pMeterMetaInfo->name) + tbnameCondLen + strlen(join) + strlen(tagIdBuf);
if (cond != NULL) {
bufSize += strlen(cond->cond);
}
bufSize = (size_t) ((bufSize + redundantLen) * 1.5);
char* tmp = calloc(1, bufSize);
int32_t keyLen = snprintf(tmp, bufSize, "%s,%s,%s,%d,%s,[%s],%d", pMeterMetaInfo->name,
(cond != NULL ? cond->cond : NULL),
(tbnameCondLen > 0 ? pTagCond->tbnameCond.cond : NULL),
pTagCond->relType, join, tagIdBuf, pCmd->groupbyExpr.orderType); pTagCond->relType, join, tagIdBuf, pCmd->groupbyExpr.orderType);
assert(keyLen <= TSDB_MAX_SQL_LEN); assert(keyLen <= bufSize);
if (keyLen < maxKeySize) { if (keyLen < maxKeySize) {
strcpy(str, tmp); strcpy(str, tmp);
@ -103,7 +110,7 @@ void tsSetMetricQueryCond(STagCond* pTagCond, uint64_t uid, const char* str) {
SCond* pDest = &pTagCond->cond[pTagCond->numOfTagCond]; SCond* pDest = &pTagCond->cond[pTagCond->numOfTagCond];
pDest->uid = uid; pDest->uid = uid;
pDest->cond = SStringCreate(str); pDest->cond = strdup(str);
pTagCond->numOfTagCond += 1; pTagCond->numOfTagCond += 1;
} }
@ -146,7 +153,6 @@ bool tscIsSelectivityWithTagQuery(SSqlCmd* pCmd) {
return false; return false;
} }
void tscGetDBInfoFromMeterId(char* meterId, char* db) { void tscGetDBInfoFromMeterId(char* meterId, char* db) {
char* st = strstr(meterId, TS_PATH_DELIMITER); char* st = strstr(meterId, TS_PATH_DELIMITER);
if (st != NULL) { if (st != NULL) {
@ -238,10 +244,9 @@ bool tscProjectionQueryOnMetric(SSqlCmd* pCmd) {
//for project query, only the following two function is allowed //for project query, only the following two function is allowed
for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pCmd, i); int32_t functionId = tscSqlExprGet(pCmd, i)->functionId;
int32_t functionId = pExpr->functionId;
if (functionId != TSDB_FUNC_PRJ && functionId != TSDB_FUNC_TAGPRJ && if (functionId != TSDB_FUNC_PRJ && functionId != TSDB_FUNC_TAGPRJ &&
functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TS) { functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_ARITHM) {
return false; return false;
} }
} }
@ -249,6 +254,17 @@ bool tscProjectionQueryOnMetric(SSqlCmd* pCmd) {
return true; return true;
} }
bool tscProjectionQueryOnTable(SSqlCmd* pCmd) {
for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) {
int32_t functionId = tscSqlExprGet(pCmd, i)->functionId;
if (functionId != TSDB_FUNC_PRJ && functionId != TSDB_FUNC_TS) {
return false;
}
}
return true;
}
bool tscIsPointInterpQuery(SSqlCmd* pCmd) { bool tscIsPointInterpQuery(SSqlCmd* pCmd) {
for (int32_t i = 0; i < pCmd->exprsInfo.numOfExprs; ++i) { for (int32_t i = 0; i < pCmd->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pCmd, i); SSqlExpr* pExpr = tscSqlExprGet(pCmd, i);
@ -269,7 +285,7 @@ bool tscIsPointInterpQuery(SSqlCmd* pCmd) {
} }
bool tscIsTWAQuery(SSqlCmd* pCmd) { bool tscIsTWAQuery(SSqlCmd* pCmd) {
for(int32_t i = 0; i < pCmd->exprsInfo.numOfExprs; ++i) { for (int32_t i = 0; i < pCmd->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pCmd, i); SSqlExpr* pExpr = tscSqlExprGet(pCmd, i);
if (pExpr == NULL) { if (pExpr == NULL) {
continue; continue;
@ -435,15 +451,6 @@ void tscFreeSqlObj(SSqlObj* pSql) {
free(pSql); free(pSql);
} }
STableDataBlocks* tscCreateDataBlock(int32_t size) {
STableDataBlocks* dataBuf = (STableDataBlocks*)calloc(1, sizeof(STableDataBlocks));
dataBuf->nAllocSize = (uint32_t)size;
dataBuf->pData = calloc(1, dataBuf->nAllocSize);
dataBuf->ordered = true;
dataBuf->prevTS = INT64_MIN;
return dataBuf;
}
void tscDestroyDataBlock(STableDataBlocks* pDataBlock) { void tscDestroyDataBlock(STableDataBlocks* pDataBlock) {
if (pDataBlock == NULL) { if (pDataBlock == NULL) {
return; return;
@ -451,10 +458,14 @@ void tscDestroyDataBlock(STableDataBlocks* pDataBlock) {
tfree(pDataBlock->pData); tfree(pDataBlock->pData);
tfree(pDataBlock->params); tfree(pDataBlock->params);
// free the refcount for metermeta
taosRemoveDataFromCache(tscCacheHandle, (void**) &(pDataBlock->pMeterMeta), false);
tfree(pDataBlock); tfree(pDataBlock);
} }
SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, short bytes, uint32_t offset) { SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, short bytes,
uint32_t offset) {
uint32_t needed = pDataBlock->numOfParams + 1; uint32_t needed = pDataBlock->numOfParams + 1;
if (needed > pDataBlock->numOfAllocedParams) { if (needed > pDataBlock->numOfAllocedParams) {
needed *= 2; needed *= 2;
@ -494,13 +505,13 @@ SDataBlockList* tscCreateBlockArrayList() {
return pDataBlockArrayList; return pDataBlockArrayList;
} }
void tscAppendDataBlock(SDataBlockList *pList, STableDataBlocks *pBlocks) { void tscAppendDataBlock(SDataBlockList* pList, STableDataBlocks* pBlocks) {
if (pList->nSize >= pList->nAlloc) { if (pList->nSize >= pList->nAlloc) {
pList->nAlloc = pList->nAlloc << 1; pList->nAlloc = (pList->nAlloc) << 1U;
pList->pData = realloc(pList->pData, sizeof(void *) * (size_t)pList->nAlloc); pList->pData = realloc(pList->pData, POINTER_BYTES * (size_t)pList->nAlloc);
// reset allocated memory // reset allocated memory
memset(pList->pData + pList->nSize, 0, sizeof(void *) * (pList->nAlloc - pList->nSize)); memset(pList->pData + pList->nSize, 0, POINTER_BYTES * (pList->nAlloc - pList->nSize));
} }
pList->pData[pList->nSize++] = pBlocks; pList->pData[pList->nSize++] = pBlocks;
@ -522,29 +533,43 @@ void* tscDestroyBlockArrayList(SDataBlockList* pList) {
} }
int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock) { int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock) {
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
assert(pDataBlock->pMeterMeta != NULL);
pCmd->count = pDataBlock->numOfMeters; pCmd->count = pDataBlock->numOfMeters;
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0); SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, 0);
strcpy(pMeterMetaInfo->name, pDataBlock->meterId);
//set the correct metermeta object, the metermeta has been locked in pDataBlocks, so it must be in the cache
if (pMeterMetaInfo->pMeterMeta != pDataBlock->pMeterMeta) {
strcpy(pMeterMetaInfo->name, pDataBlock->meterId);
taosRemoveDataFromCache(tscCacheHandle, (void**) &(pMeterMetaInfo->pMeterMeta), false);
pMeterMetaInfo->pMeterMeta = pDataBlock->pMeterMeta;
pDataBlock->pMeterMeta = NULL; // delegate the ownership of metermeta to pMeterMetaInfo
} else {
assert(strncmp(pMeterMetaInfo->name, pDataBlock->meterId, tListLen(pDataBlock->meterId)) == 0);
}
/* /*
* the submit message consists of : [RPC header|message body|digest] * the submit message consists of : [RPC header|message body|digest]
* the dataBlock only includes the RPC Header buffer and actual submit messsage body, space for digest needs * the dataBlock only includes the RPC Header buffer and actual submit messsage body, space for digest needs
* additional space. * additional space.
*/ */
int ret = tscAllocPayload(pCmd, pDataBlock->nAllocSize + sizeof(STaosDigest)); int ret = tscAllocPayload(pCmd, pDataBlock->nAllocSize + sizeof(STaosDigest));
if (TSDB_CODE_SUCCESS != ret) return ret; if (TSDB_CODE_SUCCESS != ret) {
return ret;
}
memcpy(pCmd->payload, pDataBlock->pData, pDataBlock->nAllocSize); memcpy(pCmd->payload, pDataBlock->pData, pDataBlock->nAllocSize);
/* /*
* the payloadLen should be actual message body size * the payloadLen should be actual message body size
* the old value of payloadLen is the allocated payload size * the old value of payloadLen is the allocated payload size
*/ */
pCmd->payloadLen = pDataBlock->nAllocSize - tsRpcHeadSize; pCmd->payloadLen = pDataBlock->nAllocSize - tsRpcHeadSize;
assert(pCmd->allocSize >= pCmd->payloadLen + tsRpcHeadSize + sizeof(STaosDigest)); assert(pCmd->allocSize >= pCmd->payloadLen + tsRpcHeadSize + sizeof(STaosDigest));
return tscGetMeterMeta(pSql, pMeterMetaInfo->name, 0); return TSDB_CODE_SUCCESS;
} }
void tscFreeUnusedDataBlocks(SDataBlockList* pList) { void tscFreeUnusedDataBlocks(SDataBlockList* pList) {
@ -556,19 +581,38 @@ void tscFreeUnusedDataBlocks(SDataBlockList* pList) {
} }
} }
STableDataBlocks* tscCreateDataBlockEx(size_t size, int32_t rowSize, int32_t startOffset, char* name) { /**
STableDataBlocks *dataBuf = tscCreateDataBlock(size); * create the in-memory buffer for each table to keep the submitted data block
* @param initialSize
* @param rowSize
* @param startOffset
* @param name
* @param pMeterMeta the ownership of pMeterMeta should be transfer to STableDataBlocks
* @return
*/
STableDataBlocks* tscCreateDataBlock(size_t initialSize, int32_t rowSize, int32_t startOffset, const char* name) {
STableDataBlocks* dataBuf = (STableDataBlocks*)calloc(1, sizeof(STableDataBlocks));
dataBuf->nAllocSize = (uint32_t) initialSize;
dataBuf->pData = calloc(1, dataBuf->nAllocSize);
dataBuf->ordered = true;
dataBuf->prevTS = INT64_MIN;
dataBuf->rowSize = rowSize; dataBuf->rowSize = rowSize;
dataBuf->size = startOffset; dataBuf->size = startOffset;
dataBuf->tsSource = -1; dataBuf->tsSource = -1;
strncpy(dataBuf->meterId, name, TSDB_METER_ID_LEN); strncpy(dataBuf->meterId, name, TSDB_METER_ID_LEN);
// sure that the metermeta must be in the local client cache
dataBuf->pMeterMeta = taosGetDataFromCache(tscCacheHandle, dataBuf->meterId);
assert(dataBuf->pMeterMeta != NULL && initialSize > 0);
return dataBuf; return dataBuf;
} }
STableDataBlocks* tscGetDataBlockFromList(void* pHashList, SDataBlockList* pDataBlockList, int64_t id, int32_t size, STableDataBlocks* tscGetDataBlockFromList(void* pHashList, SDataBlockList* pDataBlockList, int64_t id, int32_t size,
int32_t startOffset, int32_t rowSize, char* tableId) { int32_t startOffset, int32_t rowSize, const char* tableId) {
STableDataBlocks* dataBuf = NULL; STableDataBlocks* dataBuf = NULL;
STableDataBlocks** t1 = (STableDataBlocks**)taosGetIntHashData(pHashList, id); STableDataBlocks** t1 = (STableDataBlocks**)taosGetIntHashData(pHashList, id);
@ -577,7 +621,7 @@ STableDataBlocks* tscGetDataBlockFromList(void* pHashList, SDataBlockList* pData
} }
if (dataBuf == NULL) { if (dataBuf == NULL) {
dataBuf = tscCreateDataBlockEx((size_t) size, rowSize, startOffset, tableId); dataBuf = tscCreateDataBlock((size_t)size, rowSize, startOffset, tableId);
dataBuf = *(STableDataBlocks**)taosAddIntHash(pHashList, id, (char*)&dataBuf); dataBuf = *(STableDataBlocks**)taosAddIntHash(pHashList, id, (char*)&dataBuf);
tscAppendDataBlock(pDataBlockList, dataBuf); tscAppendDataBlock(pDataBlockList, dataBuf);
} }
@ -608,7 +652,7 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SDataBlockList* pTableDataBlockLi
if (tmp != NULL) { if (tmp != NULL) {
dataBuf->pData = tmp; dataBuf->pData = tmp;
memset(dataBuf->pData + dataBuf->size, 0, dataBuf->nAllocSize - dataBuf->size); memset(dataBuf->pData + dataBuf->size, 0, dataBuf->nAllocSize - dataBuf->size);
} else { // failed to allocate memory, free already allocated memory and return error code } else { // failed to allocate memory, free already allocated memory and return error code
tscError("%p failed to allocate memory for merging submit block, size:%d", pSql, dataBuf->nAllocSize); tscError("%p failed to allocate memory for merging submit block, size:%d", pSql, dataBuf->nAllocSize);
taosCleanUpIntHash(pVnodeDataBlockHashList); taosCleanUpIntHash(pVnodeDataBlockHashList);
@ -677,7 +721,7 @@ int tscAllocPayload(SSqlCmd* pCmd, int size) {
pCmd->allocSize = size; pCmd->allocSize = size;
} else { } else {
if (pCmd->allocSize < size) { if (pCmd->allocSize < size) {
char* b = realloc(pCmd->payload, size); char* b = realloc(pCmd->payload, size);
if (b == NULL) return TSDB_CODE_CLI_OUT_OF_MEMORY; if (b == NULL) return TSDB_CODE_CLI_OUT_OF_MEMORY;
pCmd->payload = b; pCmd->payload = b;
pCmd->allocSize = size; pCmd->allocSize = size;
@ -724,7 +768,7 @@ static void evic(SFieldInfo* pFieldInfo, int32_t index) {
} }
} }
static void setValueImpl(TAOS_FIELD* pField, int8_t type, char* name, int16_t bytes) { static void setValueImpl(TAOS_FIELD* pField, int8_t type, const char* name, int16_t bytes) {
pField->type = type; pField->type = type;
strncpy(pField->name, name, TSDB_COL_NAME_LEN); strncpy(pField->name, name, TSDB_COL_NAME_LEN);
pField->bytes = bytes; pField->bytes = bytes;
@ -768,7 +812,7 @@ void tscFieldInfoUpdateVisible(SFieldInfo* pFieldInfo, int32_t index, bool visib
} }
} }
void tscFieldInfoSetValue(SFieldInfo* pFieldInfo, int32_t index, int8_t type, char* name, int16_t bytes) { void tscFieldInfoSetValue(SFieldInfo* pFieldInfo, int32_t index, int8_t type, const char* name, int16_t bytes) {
ensureSpace(pFieldInfo, pFieldInfo->numOfOutputCols + 1); ensureSpace(pFieldInfo, pFieldInfo->numOfOutputCols + 1);
evic(pFieldInfo, index); evic(pFieldInfo, index);
@ -873,11 +917,11 @@ void tscClearFieldInfo(SFieldInfo* pFieldInfo) {
static void _exprCheckSpace(SSqlExprInfo* pExprInfo, int32_t size) { static void _exprCheckSpace(SSqlExprInfo* pExprInfo, int32_t size) {
if (size > pExprInfo->numOfAlloc) { if (size > pExprInfo->numOfAlloc) {
int32_t oldSize = pExprInfo->numOfAlloc; uint32_t oldSize = pExprInfo->numOfAlloc;
int32_t newSize = (oldSize <= 0) ? 8 : (oldSize << 1); uint32_t newSize = (oldSize <= 0) ? 8 : (oldSize << 1U);
while (newSize < size) { while (newSize < size) {
newSize = (newSize << 1); newSize = (newSize << 1U);
} }
if (newSize > TSDB_MAX_COLUMNS) { if (newSize > TSDB_MAX_COLUMNS) {
@ -900,6 +944,19 @@ static void _exprEvic(SSqlExprInfo* pExprInfo, int32_t index) {
} }
} }
SSqlExpr* tscSqlExprInsertEmpty(SSqlCmd* pCmd, int32_t index, int16_t functionId) {
SSqlExprInfo* pExprInfo = &pCmd->exprsInfo;
_exprCheckSpace(pExprInfo, pExprInfo->numOfExprs + 1);
_exprEvic(pExprInfo, index);
SSqlExpr* pExpr = &pExprInfo->pExprs[index];
pExpr->functionId = functionId;
pExprInfo->numOfExprs++;
return pExpr;
}
SSqlExpr* tscSqlExprInsert(SSqlCmd* pCmd, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type, SSqlExpr* tscSqlExprInsert(SSqlCmd* pCmd, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type,
int16_t size, int16_t interSize) { int16_t size, int16_t interSize) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pColIndex->tableIndex); SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pColIndex->tableIndex);
@ -1108,7 +1165,8 @@ void tscColumnFilterInfoCopy(SColumnFilterInfo* dst, const SColumnFilterInfo* sr
*dst = *src; *dst = *src;
if (dst->filterOnBinary) { if (dst->filterOnBinary) {
size_t len = (size_t) dst->len + 1; size_t len = (size_t) dst->len + 1;
dst->pz = calloc(1, len); char* pTmp = calloc(1, len);
dst->pz = (int64_t) pTmp;
memcpy((char*) dst->pz, (char*) src->pz, (size_t) len); memcpy((char*) dst->pz, (char*) src->pz, (size_t) len);
} }
} }
@ -1165,14 +1223,15 @@ void tscColumnBaseInfoDestroy(SColumnBaseInfo* pColumnBaseInfo) {
assert(pColumnBaseInfo->numOfCols <= TSDB_MAX_COLUMNS); assert(pColumnBaseInfo->numOfCols <= TSDB_MAX_COLUMNS);
for (int32_t i = 0; i < pColumnBaseInfo->numOfCols; ++i) { for (int32_t i = 0; i < pColumnBaseInfo->numOfCols; ++i) {
SColumnBase *pColBase = &(pColumnBaseInfo->pColList[i]); SColumnBase* pColBase = &(pColumnBaseInfo->pColList[i]);
if (pColBase->numOfFilters > 0) { if (pColBase->numOfFilters > 0) {
for (int32_t j = 0; j < pColBase->numOfFilters; ++j) { for (int32_t j = 0; j < pColBase->numOfFilters; ++j) {
assert(pColBase->filterInfo[j].filterOnBinary == 0 || pColBase->filterInfo[j].filterOnBinary == 1); assert(pColBase->filterInfo[j].filterOnBinary == 0 || pColBase->filterInfo[j].filterOnBinary == 1);
if (pColBase->filterInfo[j].filterOnBinary) { if (pColBase->filterInfo[j].filterOnBinary) {
tfree(pColBase->filterInfo[j].pz); free((char*) pColBase->filterInfo[j].pz);
pColBase->filterInfo[j].pz = 0;
} }
} }
} }
@ -1183,8 +1242,9 @@ void tscColumnBaseInfoDestroy(SColumnBaseInfo* pColumnBaseInfo) {
tfree(pColumnBaseInfo->pColList); tfree(pColumnBaseInfo->pColList);
} }
void tscColumnBaseInfoReserve(SColumnBaseInfo* pColumnBaseInfo, int32_t size) {
void tscColumnBaseInfoReserve(SColumnBaseInfo* pColumnBaseInfo, int32_t size) { _cf_ensureSpace(pColumnBaseInfo, size); } _cf_ensureSpace(pColumnBaseInfo, size);
}
/* /*
* 1. normal name, not a keyword or number * 1. normal name, not a keyword or number
@ -1232,16 +1292,16 @@ int32_t tscValidateName(SSQLToken* pToken) {
int len = tSQLGetToken(pToken->z, &pToken->type); int len = tSQLGetToken(pToken->z, &pToken->type);
// single token, validate it // single token, validate it
if (len == pToken->n){ if (len == pToken->n) {
return validateQuoteToken(pToken); return validateQuoteToken(pToken);
} else { } else {
sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true); sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true);
if (sep == NULL) { if (sep == NULL) {
return TSDB_CODE_INVALID_SQL; return TSDB_CODE_INVALID_SQL;
} }
return tscValidateName(pToken); return tscValidateName(pToken);
} }
} else { } else {
if (isNumber(pToken)) { if (isNumber(pToken)) {
return TSDB_CODE_INVALID_SQL; return TSDB_CODE_INVALID_SQL;
@ -1284,8 +1344,7 @@ int32_t tscValidateName(SSQLToken* pToken) {
// re-build the whole name string // re-build the whole name string
if (pStr[firstPartLen] == TS_PATH_DELIMITER[0]) { if (pStr[firstPartLen] == TS_PATH_DELIMITER[0]) {
// first part do not have quote // first part do not have quote do nothing
// do nothing
} else { } else {
pStr[firstPartLen] = TS_PATH_DELIMITER[0]; pStr[firstPartLen] = TS_PATH_DELIMITER[0];
memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n); memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n);
@ -1331,14 +1390,20 @@ bool tscValidateColumnId(SSqlCmd* pCmd, int32_t colId) {
void tscTagCondCopy(STagCond* dest, const STagCond* src) { void tscTagCondCopy(STagCond* dest, const STagCond* src) {
memset(dest, 0, sizeof(STagCond)); memset(dest, 0, sizeof(STagCond));
if (src->tbnameCond.cond != NULL) {
dest->tbnameCond.cond = strdup(src->tbnameCond.cond);
}
SStringCopy(&dest->tbnameCond.cond, &src->tbnameCond.cond);
dest->tbnameCond.uid = src->tbnameCond.uid; dest->tbnameCond.uid = src->tbnameCond.uid;
memcpy(&dest->joinInfo, &src->joinInfo, sizeof(SJoinInfo)); memcpy(&dest->joinInfo, &src->joinInfo, sizeof(SJoinInfo));
for (int32_t i = 0; i < src->numOfTagCond; ++i) { for (int32_t i = 0; i < src->numOfTagCond; ++i) {
SStringCopy(&dest->cond[i].cond, &src->cond[i].cond); if (src->cond[i].cond != NULL) {
dest->cond[i].cond = strdup(src->cond[i].cond);
}
dest->cond[i].uid = src->cond[i].uid; dest->cond[i].uid = src->cond[i].uid;
} }
@ -1347,10 +1412,9 @@ void tscTagCondCopy(STagCond* dest, const STagCond* src) {
} }
void tscTagCondRelease(STagCond* pCond) { void tscTagCondRelease(STagCond* pCond) {
SStringFree(&pCond->tbnameCond.cond); free(pCond->tbnameCond.cond);
for (int32_t i = 0; i < pCond->numOfTagCond; ++i) { for (int32_t i = 0; i < pCond->numOfTagCond; ++i) {
SStringFree(&pCond->cond[i].cond); free(pCond->cond[i].cond);
} }
memset(pCond, 0, sizeof(STagCond)); memset(pCond, 0, sizeof(STagCond));
@ -1449,7 +1513,11 @@ bool tscShouldFreeAsyncSqlObj(SSqlObj* pSql) {
* data blocks have been submit to vnode. * data blocks have been submit to vnode.
*/ */
SDataBlockList* pDataBlocks = pCmd->pDataBlocks; SDataBlockList* pDataBlocks = pCmd->pDataBlocks;
if (pDataBlocks == NULL || pCmd->vnodeIdx >= pDataBlocks->nSize) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, 0);
assert(pSql->cmd.numOfTables == 1);
if (pDataBlocks == NULL || pMeterMetaInfo->vnodeIndex >= pDataBlocks->nSize) {
tscTrace("%p object should be release since all data blocks have been submit", pSql); tscTrace("%p object should be release since all data blocks have been submit", pSql);
return true; return true;
} else { } else {
@ -1462,10 +1530,11 @@ bool tscShouldFreeAsyncSqlObj(SSqlObj* pSql) {
} }
SMeterMetaInfo* tscGetMeterMetaInfo(SSqlCmd* pCmd, int32_t index) { SMeterMetaInfo* tscGetMeterMetaInfo(SSqlCmd* pCmd, int32_t index) {
if (pCmd == NULL || index >= pCmd->numOfTables || index < 0) { if (pCmd == NULL || pCmd->numOfTables == 0) {
return NULL; return NULL;
} }
assert(index >= 0 && index <= pCmd->numOfTables && pCmd->pMeterInfo != NULL);
return pCmd->pMeterInfo[index]; return pCmd->pMeterInfo[index];
} }
@ -1508,7 +1577,7 @@ SMeterMetaInfo* tscAddMeterMetaInfo(SSqlCmd* pCmd, const char* name, SMeterMeta*
pMeterMetaInfo->numOfTags = numOfTags; pMeterMetaInfo->numOfTags = numOfTags;
if (tags != NULL) { if (tags != NULL) {
memcpy(pMeterMetaInfo->tagColumnIndex, tags, sizeof(int16_t) * numOfTags); memcpy(pMeterMetaInfo->tagColumnIndex, tags, sizeof(pMeterMetaInfo->tagColumnIndex[0]) * numOfTags);
} }
pCmd->numOfTables += 1; pCmd->numOfTables += 1;
@ -1562,130 +1631,13 @@ void tscResetForNextRetrieve(SSqlRes* pRes) {
pRes->numOfRows = 0; pRes->numOfRows = 0;
} }
SString SStringCreate(const char* str) { SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void* param, SSqlObj* pPrevSql) {
size_t len = strlen(str);
SString dest = {.n = len, .alloc = len + 1};
dest.z = calloc(1, dest.alloc);
strcpy(dest.z, str);
return dest;
}
void SStringCopy(SString* pDest, const SString* pSrc) {
if (pSrc->n > 0) {
pDest->n = pSrc->n;
pDest->alloc = pDest->n + 1; // one additional space for null terminate
pDest->z = calloc(1, pDest->alloc);
memcpy(pDest->z, pSrc->z, pDest->n);
} else {
memset(pDest, 0, sizeof(SString));
}
}
void SStringFree(SString* pStr) {
if (pStr->alloc > 0) {
tfree(pStr->z);
pStr->alloc = 0;
}
}
void SStringShrink(SString* pStr) {
if (pStr->alloc > (pStr->n + 1) && pStr->alloc > (pStr->n * 2)) {
pStr->z = realloc(pStr->z, pStr->n + 1);
assert(pStr->z != NULL);
pStr->alloc = pStr->n + 1;
}
}
int32_t SStringAlloc(SString* pStr, int32_t size) {
if (pStr->alloc >= size) {
return TSDB_CODE_SUCCESS;
}
size = ALIGN8(size);
char* tmp = NULL;
if (pStr->z != NULL) {
tmp = realloc(pStr->z, size);
memset(pStr->z + pStr->n, 0, size - pStr->n);
} else {
tmp = calloc(1, size);
}
if (tmp == NULL) {
#ifdef WINDOWS
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, 0, NULL);
tscTrace("failed to allocate memory, reason:%s", lpMsgBuf);
LocalFree(lpMsgBuf);
#else
char errmsg[256] = {0};
strerror_r(errno, errmsg, tListLen(errmsg));
tscTrace("failed to allocate memory, reason:%s", errmsg);
#endif
return TSDB_CODE_CLI_OUT_OF_MEMORY;
}
pStr->z = tmp;
pStr->alloc = size;
return TSDB_CODE_SUCCESS;
}
#define MIN_ALLOC_SIZE 8
int32_t SStringEnsureRemain(SString* pStr, int32_t size) {
if (pStr->alloc - pStr->n > size) {
return TSDB_CODE_SUCCESS;
}
// remain space is insufficient, allocate more spaces
int32_t inc = (size < MIN_ALLOC_SIZE) ? size : MIN_ALLOC_SIZE;
if (inc < (pStr->alloc >> 1)) {
inc = (pStr->alloc >> 1);
}
// get the new size
int32_t newsize = pStr->alloc + inc;
char* tmp = realloc(pStr->z, newsize);
if (tmp == NULL) {
#ifdef WINDOWS
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, 0, NULL);
tscTrace("failed to allocate memory, reason:%s", lpMsgBuf);
LocalFree(lpMsgBuf);
#else
char errmsg[256] = {0};
strerror_r(errno, errmsg, tListLen(errmsg));
tscTrace("failed to allocate memory, reason:%s", errmsg);
#endif
return TSDB_CODE_CLI_OUT_OF_MEMORY;
}
memset(tmp + pStr->n, 0, inc);
pStr->z = tmp;
return TSDB_CODE_SUCCESS;
}
SSqlObj* createSubqueryObj(SSqlObj* pSql, int32_t vnodeIndex, int16_t tableIndex, void (*fp)(), void* param,
SSqlObj* pPrevSql) {
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, tableIndex);
SSqlObj* pNew = (SSqlObj*)calloc(1, sizeof(SSqlObj)); SSqlObj* pNew = (SSqlObj*)calloc(1, sizeof(SSqlObj));
if (pNew == NULL) { if (pNew == NULL) {
tscError("%p new subquery failed, vnodeIdx:%d, tableIndex:%d", pSql, vnodeIndex, tableIndex); tscError("%p new subquery failed, tableIndex:%d, vnodeIndex:%d", pSql, tableIndex, pMeterMetaInfo->vnodeIndex);
return NULL; return NULL;
} }
@ -1694,7 +1646,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int32_t vnodeIndex, int16_t tableIndex
pNew->sqlstr = strdup(pSql->sqlstr); pNew->sqlstr = strdup(pSql->sqlstr);
if (pNew->sqlstr == NULL) { if (pNew->sqlstr == NULL) {
tscError("%p new subquery failed, vnodeIdx:%d, tableIndex:%d", pSql, vnodeIndex, tableIndex); tscError("%p new subquery failed, tableIndex:%d, vnodeIndex:%d", pSql, tableIndex, pMeterMetaInfo->vnodeIndex);
free(pNew); free(pNew);
return NULL; return NULL;
@ -1719,20 +1671,18 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int32_t vnodeIndex, int16_t tableIndex
tscTagCondCopy(&pNew->cmd.tagCond, &pCmd->tagCond); tscTagCondCopy(&pNew->cmd.tagCond, &pCmd->tagCond);
if (tscAllocPayload(&pNew->cmd, TSDB_DEFAULT_PAYLOAD_SIZE) != TSDB_CODE_SUCCESS) { if (tscAllocPayload(&pNew->cmd, TSDB_DEFAULT_PAYLOAD_SIZE) != TSDB_CODE_SUCCESS) {
tscError("%p new subquery failed, vnodeIdx:%d, tableIndex:%d", pSql, vnodeIndex, tableIndex); tscError("%p new subquery failed, tableIndex:%d, vnodeIndex:%d", pSql, tableIndex, pMeterMetaInfo->vnodeIndex);
tscFreeSqlObj(pNew); tscFreeSqlObj(pNew);
return NULL; return NULL;
} }
tscColumnBaseInfoCopy(&pNew->cmd.colList, &pCmd->colList, (int16_t)tableIndex); tscColumnBaseInfoCopy(&pNew->cmd.colList, &pCmd->colList, (int16_t)tableIndex);
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, tableIndex);
// set the correct query type // set the correct query type
if (pPrevSql != NULL) { if (pPrevSql != NULL) {
pNew->cmd.type = pPrevSql->cmd.type; pNew->cmd.type = pPrevSql->cmd.type;
} else { } else {
pNew->cmd.type |= TSDB_QUERY_TYPE_SUBQUERY; // it must be the subquery pNew->cmd.type |= TSDB_QUERY_TYPE_SUBQUERY; // it must be the subquery
} }
uint64_t uid = pMeterMetaInfo->pMeterMeta->uid; uint64_t uid = pMeterMetaInfo->pMeterMeta->uid;
@ -1756,15 +1706,16 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int32_t vnodeIndex, int16_t tableIndex
} }
pNew->fp = fp; pNew->fp = fp;
pNew->param = param; pNew->param = param;
pNew->cmd.vnodeIdx = vnodeIndex;
SMeterMetaInfo* pMetermetaInfo = tscGetMeterMetaInfo(pCmd, tableIndex);
char key[TSDB_MAX_TAGS_LEN + 1] = {0}; char key[TSDB_MAX_TAGS_LEN + 1] = {0};
tscGetMetricMetaCacheKey(pCmd, key, pMetermetaInfo->pMeterMeta->uid); tscGetMetricMetaCacheKey(pCmd, key, uid);
char* name = pMeterMetaInfo->name; #ifdef _DEBUG_VIEW
printf("the metricmeta key is:%s\n", key);
#endif
char* name = pMeterMetaInfo->name;
SMeterMetaInfo* pFinalInfo = NULL; SMeterMetaInfo* pFinalInfo = NULL;
if (pPrevSql == NULL) { if (pPrevSql == NULL) {
@ -1772,28 +1723,29 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int32_t vnodeIndex, int16_t tableIndex
SMetricMeta* pMetricMeta = taosGetDataFromCache(tscCacheHandle, key); SMetricMeta* pMetricMeta = taosGetDataFromCache(tscCacheHandle, key);
pFinalInfo = tscAddMeterMetaInfo(&pNew->cmd, name, pMeterMeta, pMetricMeta, pMeterMetaInfo->numOfTags, pFinalInfo = tscAddMeterMetaInfo(&pNew->cmd, name, pMeterMeta, pMetricMeta, pMeterMetaInfo->numOfTags,
pMeterMetaInfo->tagColumnIndex); pMeterMetaInfo->tagColumnIndex);
} else { } else {
SMeterMetaInfo* pPrevInfo = tscGetMeterMetaInfo(&pPrevSql->cmd, 0); SMeterMetaInfo* pPrevInfo = tscGetMeterMetaInfo(&pPrevSql->cmd, 0);
pFinalInfo = tscAddMeterMetaInfo(&pNew->cmd, name, pPrevInfo->pMeterMeta, pPrevInfo->pMetricMeta, pMeterMetaInfo->numOfTags, pFinalInfo = tscAddMeterMetaInfo(&pNew->cmd, name, pPrevInfo->pMeterMeta, pPrevInfo->pMetricMeta,
pMeterMetaInfo->tagColumnIndex); pMeterMetaInfo->numOfTags, pMeterMetaInfo->tagColumnIndex);
pPrevInfo->pMeterMeta = NULL; pPrevInfo->pMeterMeta = NULL;
pPrevInfo->pMetricMeta = NULL; pPrevInfo->pMetricMeta = NULL;
} }
assert(pFinalInfo->pMeterMeta != NULL); assert(pFinalInfo->pMeterMeta != NULL);
if (UTIL_METER_IS_METRIC(pMetermetaInfo)) { if (UTIL_METER_IS_METRIC(pMeterMetaInfo)) {
assert(pFinalInfo->pMetricMeta != NULL); assert(pFinalInfo->pMetricMeta != NULL);
} }
tscTrace("%p new subquery %p, vnodeIdx:%d, tableIndex:%d, type:%d", pSql, pNew, vnodeIndex, tableIndex, pNew->cmd.type); tscTrace("%p new subquery %p, tableIndex:%d, vnodeIdx:%d, type:%d", pSql, pNew, tableIndex,
pMeterMetaInfo->vnodeIndex, pNew->cmd.type);
return pNew; return pNew;
} }
void tscDoQuery(SSqlObj* pSql) { void tscDoQuery(SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
void* fp = pSql->fp; void* fp = pSql->fp;
if (pCmd->command > TSDB_SQL_LOCAL) { if (pCmd->command > TSDB_SQL_LOCAL) {
tscProcessLocalCmd(pSql); tscProcessLocalCmd(pSql);
@ -1812,12 +1764,56 @@ void tscDoQuery(SSqlObj* pSql) {
} }
} }
int16_t tscGetJoinTagColIndexByUid(SSqlCmd* pCmd, uint64_t uid) { int16_t tscGetJoinTagColIndexByUid(STagCond* pTagCond, uint64_t uid) {
STagCond* pTagCond = &pCmd->tagCond;
if (pTagCond->joinInfo.left.uid == uid) { if (pTagCond->joinInfo.left.uid == uid) {
return pTagCond->joinInfo.left.tagCol; return pTagCond->joinInfo.left.tagCol;
} else { } else {
return pTagCond->joinInfo.right.tagCol; return pTagCond->joinInfo.right.tagCol;
} }
} }
bool tscIsUpdateQuery(STscObj* pObj) {
if (pObj == NULL || pObj->signature != pObj) {
globalCode = TSDB_CODE_DISCONNECTED;
return TSDB_CODE_DISCONNECTED;
}
SSqlCmd* pCmd = &pObj->pSql->cmd;
return ((pCmd->command >= TSDB_SQL_INSERT && pCmd->command <= TSDB_SQL_DROP_DNODE) ||
TSDB_SQL_USE_DB == pCmd->command) ? 1 : 0;
}
int32_t tscInvalidSQLErrMsg(char *msg, const char *additionalInfo, const char *sql) {
const char *msgFormat1 = "invalid SQL: %s";
const char *msgFormat2 = "invalid SQL: syntax error near \"%s\" (%s)";
const char *msgFormat3 = "invalid SQL: syntax error near \"%s\"";
const int32_t BACKWARD_CHAR_STEP = 0;
if (sql == NULL) {
assert(additionalInfo != NULL);
sprintf(msg, msgFormat1, additionalInfo);
return TSDB_CODE_INVALID_SQL;
}
char buf[64] = {0}; // only extract part of sql string
strncpy(buf, (sql - BACKWARD_CHAR_STEP), tListLen(buf) - 1);
if (additionalInfo != NULL) {
sprintf(msg, msgFormat2, buf, additionalInfo);
} else {
sprintf(msg, msgFormat3, buf); // no additional information for invalid sql error
}
return TSDB_CODE_INVALID_SQL;
}
bool tscHasReachLimitation(SSqlObj* pSql) {
assert(pSql != NULL && pSql->cmd.globalLimit != 0);
SSqlCmd* pCmd = &pSql->cmd;
SSqlRes* pRes = &pSql->res;
return (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit);
}

View File

@ -118,14 +118,15 @@ func (rows *taosSqlRows) ColumnTypeScanType(i int) reflect.Type {
return rows.rs.columns[i].scanType() return rows.rs.columns[i].scanType()
} }
func (rows *taosSqlRows) Close() (err error) { func (rows *taosSqlRows) Close() error {
mc := rows.mc if rows.mc != nil {
if mc == nil { result := C.taos_use_result(rows.mc.taos)
return nil if result != nil {
C.taos_free_result(result)
}
rows.mc = nil
} }
return nil
rows.mc = nil
return err
} }
func (rows *taosSqlRows) HasNextResultSet() (b bool) { func (rows *taosSqlRows) HasNextResultSet() (b bool) {

View File

@ -29,46 +29,47 @@ import (
"unsafe" "unsafe"
) )
func (mc *taosConn) taosConnect(ip, user, pass, db string, port int) (taos unsafe.Pointer, err error){ func (mc *taosConn) taosConnect(ip, user, pass, db string, port int) (taos unsafe.Pointer, err error) {
cuser := C.CString(user) cuser := C.CString(user)
cpass := C.CString(pass) cpass := C.CString(pass)
cip := C.CString(ip) cip := C.CString(ip)
cdb := C.CString(db) cdb := C.CString(db)
defer C.free(unsafe.Pointer(cip)) defer C.free(unsafe.Pointer(cip))
defer C.free(unsafe.Pointer(cuser)) defer C.free(unsafe.Pointer(cuser))
defer C.free(unsafe.Pointer(cpass)) defer C.free(unsafe.Pointer(cpass))
defer C.free(unsafe.Pointer(cdb)) defer C.free(unsafe.Pointer(cdb))
taosObj := C.taos_connect(cip, cuser, cpass, cdb, (C.int)(port)) taosObj := C.taos_connect(cip, cuser, cpass, cdb, (C.ushort)(port))
if taosObj == nil { if taosObj == nil {
return nil, errors.New("taos_connect() fail!") return nil, errors.New("taos_connect() fail!")
} }
return (unsafe.Pointer)(taosObj), nil return (unsafe.Pointer)(taosObj), nil
} }
func (mc *taosConn) taosQuery(sqlstr string) (int, error) { func (mc *taosConn) taosQuery(sqlstr string) (int, error) {
taosLog.Printf("taosQuery() input sql:%s\n", sqlstr) //taosLog.Printf("taosQuery() input sql:%s\n", sqlstr)
csqlstr := C.CString(sqlstr) csqlstr := C.CString(sqlstr)
defer C.free(unsafe.Pointer(csqlstr)) defer C.free(unsafe.Pointer(csqlstr))
code := int(C.taos_query(mc.taos, csqlstr)) code := int(C.taos_query(mc.taos, csqlstr))
if 0 != code { if 0 != code {
mc.taos_error() mc.taos_error()
errStr := C.GoString(C.taos_errstr(mc.taos)) errStr := C.GoString(C.taos_errstr(mc.taos))
taosLog.Println("taos_query() failed:", errStr) taosLog.Println("taos_query() failed:", errStr)
return 0, errors.New(errStr) taosLog.Printf("taosQuery() input sql:%s\n", sqlstr)
} return 0, errors.New(errStr)
}
// read result and save into mc struct // read result and save into mc struct
num_fields := int(C.taos_field_count(mc.taos)) num_fields := int(C.taos_field_count(mc.taos))
if 0 == num_fields { // there are no select and show kinds of commands if 0 == num_fields { // there are no select and show kinds of commands
mc.affectedRows = int(C.taos_affected_rows(mc.taos)) mc.affectedRows = int(C.taos_affected_rows(mc.taos))
mc.insertId = 0 mc.insertId = 0
} }
return num_fields, nil return num_fields, nil
} }
func (mc *taosConn) taos_close() { func (mc *taosConn) taos_close() {
@ -76,8 +77,8 @@ func (mc *taosConn) taos_close() {
} }
func (mc *taosConn) taos_error() { func (mc *taosConn) taos_error() {
// free local resouce: allocated memory/metric-meta refcnt // free local resouce: allocated memory/metric-meta refcnt
//var pRes unsafe.Pointer //var pRes unsafe.Pointer
pRes := C.taos_use_result(mc.taos) pRes := C.taos_use_result(mc.taos)
C.taos_free_result(pRes) C.taos_free_result(pRes)
} }

View File

@ -12,15 +12,25 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package taosSql package taosSql
/*
#cgo CFLAGS : -I/usr/include
#include <stdlib.h>
#cgo LDFLAGS: -L/usr/lib -ltaos
void taosSetAllocMode(int mode, const char* path, _Bool autoDump);
void taosDumpMemoryLeak();
*/
import "C"
import ( import (
"database/sql/driver" "database/sql/driver"
"errors" "errors"
"fmt" "fmt"
"sync/atomic" "sync/atomic"
"time" "time"
"unsafe"
) )
// Returns the bool value of the input. // Returns the bool value of the input.
@ -398,3 +408,15 @@ func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
} }
/******************************************************************************
* Utils for C memory issues debugging *
******************************************************************************/
func SetAllocMode(mode int32, path string) {
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
C.taosSetAllocMode(C.int(mode), cpath, false)
}
func DumpMemoryLeak() {
C.taosDumpMemoryLeak()
}

View File

@ -0,0 +1,329 @@
## TAOS-JDBCDriver 概述
TDengine 为了方便 Java 应用使用,提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现。目前可以通过 [Sonatype Repository][1] 搜索并下载。
由于 TDengine 是使用 c 语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
* libtaos.so
在 linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so该目录包含在 Linux 自动扫描路径上,无需单独指定。
* taos.dll
在 windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
> 注意:在 windows 环境开发时需要安装 TDengine 对应的 windows 版本客户端,由于目前没有提供 Linux 环境单独的客户端,需要安装 TDengine 才能使用。
TDengine 的 JDBC 驱动实现尽可能的与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征的差异导致 taos-jdbcdriver 并未完全实现 JDBC 标准规范。在使用时需要注意以下几点:
* TDengine 不提供针对单条数据记录的删除和修改的操作,驱动中也没有支持相关方法。
* 由于不支持删除和修改,所以也不支持事务操作。
* 目前不支持表间的 union 操作。
* 目前不支持嵌套查询(nested query)`对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet还没关闭的情况下执行了新的查询TSDBJDBCDriver 则会自动关闭上一个 ResultSet`。
## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| --- | --- | --- |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
## TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
| TDengine DataType | Java DataType |
| --- | --- |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| SMALLINT, TINYINT |java.lang.Short |
| BOOL | java.lang.Boolean |
| BINARY, NCHAR | java.lang.String |
## 如何获取 TAOS-JDBCDriver
### maven 仓库
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。
* [sonatype][8]
* [mvnrepository][9]
* [maven.aliyun][10]
maven 项目中使用如下 pom.xml 配置即可:
```xml
<dependencies>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>1.0.3</version>
</dependency>
</dependencies>
```
### 源码编译打包
下载 [TDengine][3] 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package` 即可生成相应 jar 包。
## 使用说明
### 获取连接
如下所示配置即可获取 TDengine Connection
```java
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://127.0.0.1:6030/log?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl);
```
> 端口 6030 为默认连接端口JDBC URL 中的 log 为系统本身的监控数据库。
TDengine 的 JDBC URL 规范格式为:
`jdbc:TSDB://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
其中,`{}` 中的内容必须,`[]` 中为可选。配置参数说明如下:
* user登录 TDengine 用户名,默认值 root。
* password用户登录密码默认值 taosdata。
* charset客户端使用的字符集默认值为系统字符集。
* cfgdir客户端配置文件目录路径Linux OS 上默认值 /etc/taos Windows OS 上默认值 C:/TDengine/cfg。
* locale客户端语言环境默认值系统当前 locale。
* timezone客户端使用的时区默认值为系统当前时区。
以上参数可以在 3 处配置,`优先级由高到低`分别如下:
1. JDBC URL 参数
如上所述,可以在 JDBC URL 的参数中指定。
2. java.sql.DriverManager.getConnection(String jdbcUrl, Properties connProps)
```java
public Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://127.0.0.1:0/log?user=root&password=taosdata";
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "/etc/taos");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
return conn;
}
```
3. 客户端配置文件 taos.cfg
linux 系统默认配置文件为 /var/lib/taos/taos.cfgwindows 系统默认配置文件路径为 C:\TDengine\cfg\taos.cfg。
```properties
# client default username
# defaultUser root
# client default password
# defaultPass taosdata
# default system charset
# charset UTF-8
# system locale
# locale en_US.UTF-8
```
> 更多详细配置请参考[客户端配置][13]
### 创建数据库和表
```java
Statement stmt = conn.createStatement();
// create database
stmt.executeUpdate("create database if not exists db");
// use database
stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
```
> 注意:如果不使用 `use db` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 db.tb。
### 插入数据
```java
// insert data
int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now + 1s, 20, 9.3)");
System.out.println("insert " + affectedRows + " rows.");
```
> now 为系统内部函数,默认为服务器当前时间。
> `now + 1s` 代表服务器当前时间往后加 1 秒数字后面代表时间单位a(毫秒), s(秒), m(分), h(小时), d(天)w(周), n(月), y(年)。
### 查询数据
```java
// query data
ResultSet resultSet = stmt.executeQuery("select * from tb");
Timestamp ts = null;
int temperature = 0;
float humidity = 0;
while(resultSet.next()){
ts = resultSet.getTimestamp(1);
temperature = resultSet.getInt(2);
humidity = resultSet.getFloat("humidity");
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
```
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。
### 关闭资源
```java
resultSet.close();
stmt.close();
conn.close();
```
> `注意务必要将 connection 进行关闭`,否则会出现连接泄露。
## 与连接池使用
**HikariCP**
* 引入相应 HikariCP maven 依赖:
```xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.1</version>
</dependency>
```
* 使用示例如下:
```java
public static void main(String[] args) throws SQLException {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:TAOS://127.0.0.1:6030/log");
config.setUsername("root");
config.setPassword("taosdata");
config.setMinimumIdle(3); //minimum number of idle connection
config.setMaximumPoolSize(10); //maximum number of connection in the pool
config.setConnectionTimeout(10000); //maximum wait milliseconds for get connection from pool
config.setIdleTimeout(60000); // max idle time for recycle idle connection
config.setConnectionTestQuery("describe log.dn"); //validation query
config.setValidationTimeout(3000); //validation query timeout
HikariDataSource ds = new HikariDataSource(config); //create datasource
Connection connection = ds.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to conneciton pool
}
```
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
> 更多 HikariCP 使用问题请查看[官方说明][5]
**Druid**
* 引入相应 Druid maven 依赖:
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
```
* 使用示例如下:
```java
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("driverClassName","com.taosdata.jdbc.TSDBDriver");
properties.put("url","jdbc:TAOS://127.0.0.1:6030/log");
properties.put("username","root");
properties.put("password","taosdata");
properties.put("maxActive","10"); //maximum number of connection in the pool
properties.put("initialSize","3");//initial number of connection
properties.put("maxWait","10000");//maximum wait milliseconds for get connection from pool
properties.put("minIdle","3");//minimum number of connection in the pool
properties.put("timeBetweenEvictionRunsMillis","3000");// the interval milliseconds to test connection
properties.put("minEvictableIdleTimeMillis","60000");//the minimum milliseconds to keep idle
properties.put("maxEvictableIdleTimeMillis","90000");//the maximum milliseconds to keep idle
properties.put("validationQuery","describe log.dn"); //validation query
properties.put("testWhileIdle","true"); // test connection while idle
properties.put("testOnBorrow","false"); // don't need while testWhileIdle is true
properties.put("testOnReturn","false"); // don't need while testWhileIdle is true
//create druid datasource
DataSource ds = DruidDataSourceFactory.createDataSource(properties);
Connection connection = ds.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to conneciton pool
}
```
> 更多 druid 使用问题请查看[官方说明][6]
**注意事项**
* TDengine `v1.6.4.1` 版本开始提供了一个专门用于心跳检测的函数 `select server_status()`,所以在使用连接池时推荐使用 `select server_status()` 进行 Validation Query。
如下所示,`select server_status()` 执行成功会返回 `1`
```shell
taos> select server_status();
server_status()|
================
1 |
Query OK, 1 row(s) in set (0.000141s)
```
## 与框架使用
* Spring JdbcTemplate 中使用 taos-jdbcdriver可参考 [SpringJdbcTemplate][11]
* Springboot + Mybatis 中使用,可参考 [springbootdemo][12]
## 常见问题
* java.lang.UnsatisfiedLinkError: no taos in java.library.path
**原因**:程序没有找到依赖的本地函数库 taos。
**解决方法**windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下linux 下将建立如下软链 ` ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。
* java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
**原因**:目前 TDengine 只支持 64 位 JDK。
**解决方法**:重新安装 64 位 JDK。
* 其它问题请参考 [Issues][7]
[1]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[2]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[3]: https://github.com/taosdata/TDengine
[4]: https://www.taosdata.com/blog/2019/12/03/jdbcdriver%e6%89%be%e4%b8%8d%e5%88%b0%e5%8a%a8%e6%80%81%e9%93%be%e6%8e%a5%e5%ba%93/
[5]: https://github.com/brettwooldridge/HikariCP
[6]: https://github.com/alibaba/druid
[7]: https://github.com/taosdata/TDengine/issues
[8]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[9]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[10]: https://maven.aliyun.com/mvn/search
[11]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate
[12]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo
[13]: https://www.taosdata.com/cn/documentation/administrator/#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE

View File

@ -273,6 +273,9 @@ public class TSDBDriver implements java.sql.Driver {
String user = ""; String user = "";
for (String queryStr : queryStrings) { for (String queryStr : queryStrings) {
String[] kvPair = queryStr.trim().split("="); String[] kvPair = queryStr.trim().split("=");
if (kvPair.length < 2){
continue;
}
switch (kvPair[0].toLowerCase()) { switch (kvPair[0].toLowerCase()) {
case PROPERTY_KEY_USER: case PROPERTY_KEY_USER:
urlProps.setProperty(PROPERTY_KEY_USER, kvPair[1]); urlProps.setProperty(PROPERTY_KEY_USER, kvPair[1]);

View File

@ -134,7 +134,7 @@ public class TSDBJNIConnector {
} }
} }
// Try retrieving result set for the executed SQLusing the current connection pointer. If the executed // Try retrieving result set for the executed SQL using the current connection pointer. If the executed
// SQL is a DML/DDL which doesn't return a result set, then taosResultSetPointer should be 0L. Otherwise, // SQL is a DML/DDL which doesn't return a result set, then taosResultSetPointer should be 0L. Otherwise,
// taosResultSetPointer should be a non-zero value. // taosResultSetPointer should be a non-zero value.
taosResultSetPointer = this.getResultSetImp(this.taos); taosResultSetPointer = this.getResultSetImp(this.taos);

View File

@ -23,10 +23,10 @@ extern "C" {
#include "taosmsg.h" #include "taosmsg.h"
#include "tsdb.h" #include "tsdb.h"
extern short sdbPeerPort; extern uint16_t tsMgmtMgmtPort;
extern short sdbSyncPort; extern uint16_t tsMgmtSyncPort;
extern int sdbMaxNodes; extern int sdbMaxNodes;
extern int sdbHbTimer; // seconds extern int tsMgmtPeerHBTimer; // seconds
extern char sdbZone[]; extern char sdbZone[];
extern char sdbMasterIp[]; extern char sdbMasterIp[];
extern char sdbPrivateIp[]; extern char sdbPrivateIp[];
@ -105,7 +105,7 @@ extern SSdbPeer *sdbPeer[];
#endif #endif
void *sdbOpenTable(int maxRows, int32_t maxRowSize, char *name, char keyType, char *directory, void *sdbOpenTable(int maxRows, int32_t maxRowSize, char *name, uint8_t keyType, char *directory,
void *(*appTool)(char, void *, char *, int, int *)); void *(*appTool)(char, void *, char *, int, int *));
void *sdbGetRow(void *handle, void *key); void *sdbGetRow(void *handle, void *key);

View File

@ -26,8 +26,7 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
#include "tscSQLParser.h"
#include "tsql.h"
#include "tutil.h" #include "tutil.h"
} }
@ -74,6 +73,9 @@ cmd ::= SHOW CONFIGS. { setDCLSQLElems(pInfo, SHOW_CONFIGS, 0); }
cmd ::= SHOW SCORES. { setDCLSQLElems(pInfo, SHOW_SCORES, 0); } cmd ::= SHOW SCORES. { setDCLSQLElems(pInfo, SHOW_SCORES, 0); }
cmd ::= SHOW GRANTS. { setDCLSQLElems(pInfo, SHOW_GRANTS, 0); } cmd ::= SHOW GRANTS. { setDCLSQLElems(pInfo, SHOW_GRANTS, 0); }
cmd ::= SHOW VNODES. { setDCLSQLElems(pInfo, SHOW_VNODES, 0); }
cmd ::= SHOW VNODES IPTOKEN(X). { setDCLSQLElems(pInfo, SHOW_VNODES, 1, &X); }
%type dbPrefix {SSQLToken} %type dbPrefix {SSQLToken}
dbPrefix(A) ::=. {A.n = 0;} dbPrefix(A) ::=. {A.n = 0;}
dbPrefix(A) ::= ids(X) DOT. {A = X; } dbPrefix(A) ::= ids(X) DOT. {A = X; }
@ -113,7 +115,7 @@ cmd ::= DROP TABLE ifexists(Y) ids(X) cpxName(Z). {
} }
cmd ::= DROP DATABASE ifexists(Y) ids(X). { setDCLSQLElems(pInfo, DROP_DATABASE, 2, &X, &Y); } cmd ::= DROP DATABASE ifexists(Y) ids(X). { setDCLSQLElems(pInfo, DROP_DATABASE, 2, &X, &Y); }
cmd ::= DROP DNODE IP(X). { setDCLSQLElems(pInfo, DROP_DNODE, 1, &X); } cmd ::= DROP DNODE IPTOKEN(X). { setDCLSQLElems(pInfo, DROP_DNODE, 1, &X); }
cmd ::= DROP USER ids(X). { setDCLSQLElems(pInfo, DROP_USER, 1, &X); } cmd ::= DROP USER ids(X). { setDCLSQLElems(pInfo, DROP_USER, 1, &X); }
cmd ::= DROP ACCOUNT ids(X). { setDCLSQLElems(pInfo, DROP_ACCOUNT, 1, &X); } cmd ::= DROP ACCOUNT ids(X). { setDCLSQLElems(pInfo, DROP_ACCOUNT, 1, &X); }
@ -129,8 +131,8 @@ cmd ::= DESCRIBE ids(X) cpxName(Y). {
/////////////////////////////////THE ALTER STATEMENT//////////////////////////////////////// /////////////////////////////////THE ALTER STATEMENT////////////////////////////////////////
cmd ::= ALTER USER ids(X) PASS ids(Y). { setDCLSQLElems(pInfo, ALTER_USER_PASSWD, 2, &X, &Y); } cmd ::= ALTER USER ids(X) PASS ids(Y). { setDCLSQLElems(pInfo, ALTER_USER_PASSWD, 2, &X, &Y); }
cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setDCLSQLElems(pInfo, ALTER_USER_PRIVILEGES, 2, &X, &Y);} cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setDCLSQLElems(pInfo, ALTER_USER_PRIVILEGES, 2, &X, &Y);}
cmd ::= ALTER DNODE IP(X) ids(Y). { setDCLSQLElems(pInfo, ALTER_DNODE, 2, &X, &Y); } cmd ::= ALTER DNODE IPTOKEN(X) ids(Y). { setDCLSQLElems(pInfo, ALTER_DNODE, 2, &X, &Y); }
cmd ::= ALTER DNODE IP(X) ids(Y) ids(Z). { setDCLSQLElems(pInfo, ALTER_DNODE, 3, &X, &Y, &Z); } cmd ::= ALTER DNODE IPTOKEN(X) ids(Y) ids(Z). { setDCLSQLElems(pInfo, ALTER_DNODE, 3, &X, &Y, &Z); }
cmd ::= ALTER LOCAL ids(X). { setDCLSQLElems(pInfo, ALTER_LOCAL, 1, &X); } cmd ::= ALTER LOCAL ids(X). { setDCLSQLElems(pInfo, ALTER_LOCAL, 1, &X); }
cmd ::= ALTER LOCAL ids(X) ids(Y). { setDCLSQLElems(pInfo, ALTER_LOCAL, 2, &X, &Y); } cmd ::= ALTER LOCAL ids(X) ids(Y). { setDCLSQLElems(pInfo, ALTER_LOCAL, 2, &X, &Y); }
cmd ::= ALTER DATABASE ids(X) alter_db_optr(Y). { SSQLToken t = {0}; setCreateDBSQL(pInfo, ALTER_DATABASE, &X, &Y, &t);} cmd ::= ALTER DATABASE ids(X) alter_db_optr(Y). { SSQLToken t = {0}; setCreateDBSQL(pInfo, ALTER_DATABASE, &X, &Y, &t);}
@ -155,7 +157,7 @@ ifnotexists(X) ::= . {X.n = 0;}
/////////////////////////////////THE CREATE STATEMENT/////////////////////////////////////// /////////////////////////////////THE CREATE STATEMENT///////////////////////////////////////
//create option for dnode/db/user/account //create option for dnode/db/user/account
cmd ::= CREATE DNODE IP(X). { setDCLSQLElems(pInfo, CREATE_DNODE, 1, &X);} cmd ::= CREATE DNODE IPTOKEN(X). { setDCLSQLElems(pInfo, CREATE_DNODE, 1, &X);}
cmd ::= CREATE ACCOUNT ids(X) PASS ids(Y) acct_optr(Z). cmd ::= CREATE ACCOUNT ids(X) PASS ids(Y) acct_optr(Z).
{ setCreateAcctSQL(pInfo, CREATE_ACCOUNT, &X, &Y, &Z);} { setCreateAcctSQL(pInfo, CREATE_ACCOUNT, &X, &Y, &Z);}
cmd ::= CREATE DATABASE ifnotexists(Z) ids(X) db_optr(Y). { setCreateDBSQL(pInfo, CREATE_DATABASE, &X, &Y, &Z);} cmd ::= CREATE DATABASE ifnotexists(Z) ids(X) db_optr(Y). { setCreateDBSQL(pInfo, CREATE_DATABASE, &X, &Y, &Z);}
@ -219,7 +221,8 @@ comp(Y) ::= COMP INTEGER(X). { Y = X; }
prec(Y) ::= PRECISION STRING(X). { Y = X; } prec(Y) ::= PRECISION STRING(X). { Y = X; }
%type db_optr {SCreateDBInfo} %type db_optr {SCreateDBInfo}
db_optr ::= . {} db_optr(Y) ::= . {setDefaultCreateDbOption(&Y);}
db_optr(Y) ::= db_optr(Z) tables(X). { Y = Z; Y.tablesPerVnode = strtol(X.z, NULL, 10); } db_optr(Y) ::= db_optr(Z) tables(X). { Y = Z; Y.tablesPerVnode = strtol(X.z, NULL, 10); }
db_optr(Y) ::= db_optr(Z) cache(X). { Y = Z; Y.cacheBlockSize = strtol(X.z, NULL, 10); } db_optr(Y) ::= db_optr(Z) cache(X). { Y = Z; Y.cacheBlockSize = strtol(X.z, NULL, 10); }
db_optr(Y) ::= db_optr(Z) replica(X). { Y = Z; Y.replica = strtol(X.z, NULL, 10); } db_optr(Y) ::= db_optr(Z) replica(X). { Y = Z; Y.replica = strtol(X.z, NULL, 10); }
@ -234,7 +237,7 @@ db_optr(Y) ::= db_optr(Z) prec(X). { Y = Z; Y.precision = X; }
db_optr(Y) ::= db_optr(Z) keep(X). { Y = Z; Y.keep = X; } db_optr(Y) ::= db_optr(Z) keep(X). { Y = Z; Y.keep = X; }
%type alter_db_optr {SCreateDBInfo} %type alter_db_optr {SCreateDBInfo}
alter_db_optr(Y) ::= . { memset(&Y, 0, sizeof(SCreateDBInfo));} alter_db_optr(Y) ::= . { setDefaultCreateDbOption(&Y);}
alter_db_optr(Y) ::= alter_db_optr(Z) replica(X). { Y = Z; Y.replica = strtol(X.z, NULL, 10); } alter_db_optr(Y) ::= alter_db_optr(Z) replica(X). { Y = Z; Y.replica = strtol(X.z, NULL, 10); }
alter_db_optr(Y) ::= alter_db_optr(Z) tables(X). { Y = Z; Y.tablesPerVnode = strtol(X.z, NULL, 10); } alter_db_optr(Y) ::= alter_db_optr(Z) tables(X). { Y = Z; Y.tablesPerVnode = strtol(X.z, NULL, 10); }
@ -350,6 +353,14 @@ select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) fill_
A = tSetQuerySQLElems(&T, W, X, Y, P, Z, &K, &S, F, &L, &G); A = tSetQuerySQLElems(&T, W, X, Y, P, Z, &K, &S, F, &L, &G);
} }
// Support for the SQL exprssion without from & where subclauses, e.g.,
// select current_database(),
// select server_version(), select client_version(),
// select server_state();
select(A) ::= SELECT(T) selcollist(W). {
A = tSetQuerySQLElems(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
// selcollist is a list of expressions that are to become the return // selcollist is a list of expressions that are to become the return
// values of the SELECT statement. The "*" in statements like // values of the SELECT statement. The "*" in statements like
// "SELECT * FROM ..." is encoded as a special expression with an opcode of TK_ALL. // "SELECT * FROM ..." is encoded as a special expression with an opcode of TK_ALL.
@ -392,7 +403,7 @@ tmvar(A) ::= VARIABLE(X). {A = X;}
%type interval_opt {SSQLToken} %type interval_opt {SSQLToken}
interval_opt(N) ::= INTERVAL LP tmvar(E) RP. {N = E; } interval_opt(N) ::= INTERVAL LP tmvar(E) RP. {N = E; }
interval_opt(N) ::= . {N.n = 0; } interval_opt(N) ::= . {N.n = 0; N.z = NULL; N.type = 0; }
%type fill_opt {tVariantList*} %type fill_opt {tVariantList*}
%destructor fill_opt {tVariantListDestroy($$);} %destructor fill_opt {tVariantListDestroy($$);}
@ -413,7 +424,7 @@ fill_opt(N) ::= FILL LP ID(Y) RP. {
%type sliding_opt {SSQLToken} %type sliding_opt {SSQLToken}
sliding_opt(K) ::= SLIDING LP tmvar(E) RP. {K = E; } sliding_opt(K) ::= SLIDING LP tmvar(E) RP. {K = E; }
sliding_opt(K) ::= . {K.n = 0; } sliding_opt(K) ::= . {K.n = 0; K.z = NULL; K.type = 0; }
%type orderby_opt {tVariantList*} %type orderby_opt {tVariantList*}
%destructor orderby_opt {tVariantListDestroy($$);} %destructor orderby_opt {tVariantListDestroy($$);}
@ -642,12 +653,12 @@ cmd ::= ALTER TABLE ids(X) cpxName(F) SET TAG ids(Y) EQ tagitem(Z). {
} }
////////////////////////////////////////kill statement/////////////////////////////////////// ////////////////////////////////////////kill statement///////////////////////////////////////
cmd ::= KILL CONNECTION IP(X) COLON(Z) INTEGER(Y). {X.n += (Z.n + Y.n); setDCLSQLElems(pInfo, KILL_CONNECTION, 1, &X);} cmd ::= KILL CONNECTION IPTOKEN(X) COLON(Z) INTEGER(Y). {X.n += (Z.n + Y.n); setDCLSQLElems(pInfo, KILL_CONNECTION, 1, &X);}
cmd ::= KILL STREAM IP(X) COLON(Z) INTEGER(Y) COLON(K) INTEGER(F). {X.n += (Z.n + Y.n + K.n + F.n); setDCLSQLElems(pInfo, KILL_STREAM, 1, &X);} cmd ::= KILL STREAM IPTOKEN(X) COLON(Z) INTEGER(Y) COLON(K) INTEGER(F). {X.n += (Z.n + Y.n + K.n + F.n); setDCLSQLElems(pInfo, KILL_STREAM, 1, &X);}
cmd ::= KILL QUERY IP(X) COLON(Z) INTEGER(Y) COLON(K) INTEGER(F). {X.n += (Z.n + Y.n + K.n + F.n); setDCLSQLElems(pInfo, KILL_QUERY, 1, &X);} cmd ::= KILL QUERY IPTOKEN(X) COLON(Z) INTEGER(Y) COLON(K) INTEGER(F). {X.n += (Z.n + Y.n + K.n + F.n); setDCLSQLElems(pInfo, KILL_QUERY, 1, &X);}
%fallback ID ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CLUSTER CONFLICT COPY DATABASE DEFERRED %fallback ID ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CLUSTER CONFLICT COPY DATABASE DEFERRED
DELIMITERS DESC DETACH EACH END EXPLAIN FAIL FOR GLOB IGNORE IMMEDIATE INITIALLY INSTEAD DELIMITERS DESC DETACH EACH END EXPLAIN FAIL FOR GLOB IGNORE IMMEDIATE INITIALLY INSTEAD
LIKE MATCH KEY OF OFFSET RAISE REPLACE RESTRICT ROW STATEMENT TRIGGER VIEW ALL LIKE MATCH KEY OF OFFSET RAISE REPLACE RESTRICT ROW STATEMENT TRIGGER VIEW ALL
COUNT SUM AVG MIN MAX FIRST LAST TOP BOTTOM STDDEV PERCENTILE APERCENTILE LEASTSQUARES HISTOGRAM DIFF COUNT SUM AVG MIN MAX FIRST LAST TOP BOTTOM STDDEV PERCENTILE APERCENTILE LEASTSQUARES HISTOGRAM DIFF
SPREAD TWA INTERP LAST_ROW NOW IP SEMI NONE PREV LINEAR IMPORT METRIC TBNAME JOIN METRICS STABLE. SPREAD TWA INTERP LAST_ROW NOW IPTOKEN SEMI NONE PREV LINEAR IMPORT METRIC TBNAME JOIN METRICS STABLE NULL.

View File

@ -59,7 +59,7 @@ typedef struct taosField {
void taos_init(); void taos_init();
int taos_options(TSDB_OPTION option, const void *arg, ...); int taos_options(TSDB_OPTION option, const void *arg, ...);
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, int port); TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port);
void taos_close(TAOS *taos); void taos_close(TAOS *taos);
typedef struct TAOS_BIND { typedef struct TAOS_BIND {
@ -122,9 +122,6 @@ void taos_close_stream(TAOS_STREAM *tstr);
int taos_load_table_info(TAOS *taos, const char* tableNameList); int taos_load_table_info(TAOS *taos, const char* tableNameList);
// TODO: `configDir` should not be declared here
extern char configDir[]; // the path to global configuration
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

147
src/inc/taoserror.h Normal file
View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TAOSERROR_H
#define TDENGINE_TAOSERROR_H
#ifdef __cplusplus
extern "C" {
#endif
#define TSDB_CODE_SUCCESS 0
#define TSDB_CODE_ACTION_IN_PROGRESS 1
#define TSDB_CODE_LAST_SESSION_NOT_FINISHED 5
#define TSDB_CODE_INVALID_SESSION_ID 6
#define TSDB_CODE_INVALID_TRAN_ID 7
#define TSDB_CODE_INVALID_MSG_TYPE 8
#define TSDB_CODE_ALREADY_PROCESSED 9
#define TSDB_CODE_AUTH_FAILURE 10
#define TSDB_CODE_WRONG_MSG_SIZE 11
#define TSDB_CODE_UNEXPECTED_RESPONSE 12
#define TSDB_CODE_INVALID_RESPONSE_TYPE 13
#define TSDB_CODE_NO_RESOURCE 14
#define TSDB_CODE_INVALID_TIME_STAMP 15
#define TSDB_CODE_MISMATCHED_METER_ID 16
#define TSDB_CODE_ACTION_TRANS_NOT_FINISHED 17
#define TSDB_CODE_ACTION_NOT_ONLINE 18
#define TSDB_CODE_ACTION_SEND_FAILD 19
#define TSDB_CODE_NOT_ACTIVE_SESSION 20
#define TSDB_CODE_INVALID_VNODE_ID 21
#define TSDB_CODE_APP_ERROR 22
#define TSDB_CODE_INVALID_IE 23
#define TSDB_CODE_INVALID_VALUE 24
#define TSDB_CODE_REDIRECT 25
#define TSDB_CODE_ALREADY_THERE 26
#define TSDB_CODE_INVALID_METER_ID 27
#define TSDB_CODE_INVALID_SQL 28
#define TSDB_CODE_NETWORK_UNAVAIL 29
#define TSDB_CODE_INVALID_MSG_LEN 30
#define TSDB_CODE_INVALID_DB 31
#define TSDB_CODE_INVALID_TABLE 32
#define TSDB_CODE_DB_ALREADY_EXIST 33
#define TSDB_CODE_TABLE_ALREADY_EXIST 34
#define TSDB_CODE_INVALID_USER 35
#define TSDB_CODE_INVALID_ACCT 36
#define TSDB_CODE_INVALID_PASS 37
#define TSDB_CODE_DB_NOT_SELECTED 38
#define TSDB_CODE_MEMORY_CORRUPTED 39
#define TSDB_CODE_USER_ALREADY_EXIST 40
#define TSDB_CODE_NO_RIGHTS 41
#define TSDB_CODE_DISCONNECTED 42
#define TSDB_CODE_NO_MASTER 43
#define TSDB_CODE_NOT_CONFIGURED 44
#define TSDB_CODE_INVALID_OPTION 45
#define TSDB_CODE_NODE_OFFLINE 46
#define TSDB_CODE_SYNC_REQUIRED 47
#define TSDB_CODE_NO_ENOUGH_DNODES 48
#define TSDB_CODE_UNSYNCED 49
#define TSDB_CODE_TOO_SLOW 50
#define TSDB_CODE_OTHERS 51
#define TSDB_CODE_NO_REMOVE_MASTER 52
#define TSDB_CODE_WRONG_SCHEMA 53
#define TSDB_CODE_NOT_ACTIVE_VNODE 54
#define TSDB_CODE_TOO_MANY_USERS 55
#define TSDB_CODE_TOO_MANY_DATABSES 56
#define TSDB_CODE_TOO_MANY_TABLES 57
#define TSDB_CODE_TOO_MANY_DNODES 58
#define TSDB_CODE_TOO_MANY_ACCTS 59
#define TSDB_CODE_ACCT_ALREADY_EXIST 60
#define TSDB_CODE_DNODE_ALREADY_EXIST 61
#define TSDB_CODE_SDB_ERROR 62
#define TSDB_CODE_METRICMETA_EXPIRED 63 // local cached metric-meta expired causes error in metric query
#define TSDB_CODE_NOT_READY 64 // peer is not ready to process data
#define TSDB_CODE_MAX_SESSIONS 65 // too many sessions
#define TSDB_CODE_MAX_CONNECTIONS 66 // too many connections
#define TSDB_CODE_SESSION_ALREADY_EXIST 67
#define TSDB_CODE_NO_QSUMMARY 68
#define TSDB_CODE_SERV_OUT_OF_MEMORY 69
#define TSDB_CODE_INVALID_QHANDLE 70
#define TSDB_CODE_RELATED_TABLES_EXIST 71
#define TSDB_CODE_MONITOR_DB_FORBEIDDEN 72
#define TSDB_CODE_VG_COMMITLOG_INIT_FAILED 73
#define TSDB_CODE_VG_INIT_FAILED 74
#define TSDB_CODE_DATA_ALREADY_IMPORTED 75
#define TSDB_CODE_OPS_NOT_SUPPORT 76
#define TSDB_CODE_INVALID_QUERY_ID 77
#define TSDB_CODE_INVALID_STREAM_ID 78
#define TSDB_CODE_INVALID_CONNECTION 79
#define TSDB_CODE_ACTION_NOT_BALANCED 80
#define TSDB_CODE_CLI_OUT_OF_MEMORY 81
#define TSDB_CODE_DATA_OVERFLOW 82
#define TSDB_CODE_QUERY_CANCELLED 83
#define TSDB_CODE_GRANT_TIMESERIES_LIMITED 84
#define TSDB_CODE_GRANT_EXPIRED 85
#define TSDB_CODE_CLI_NO_DISKSPACE 86
#define TSDB_CODE_FILE_CORRUPTED 87
#define TSDB_CODE_INVALID_CLIENT_VERSION 88
#define TSDB_CODE_INVALID_ACCT_PARAMETER 89
#define TSDB_CODE_NOT_ENOUGH_TIME_SERIES 90
#define TSDB_CODE_NO_WRITE_ACCESS 91
#define TSDB_CODE_NO_READ_ACCESS 92
#define TSDB_CODE_GRANT_DB_LIMITED 93
#define TSDB_CODE_GRANT_USER_LIMITED 94
#define TSDB_CODE_GRANT_CONN_LIMITED 95
#define TSDB_CODE_GRANT_STREAM_LIMITED 96
#define TSDB_CODE_GRANT_SPEED_LIMITED 97
#define TSDB_CODE_GRANT_STORAGE_LIMITED 98
#define TSDB_CODE_GRANT_QUERYTIME_LIMITED 99
#define TSDB_CODE_GRANT_ACCT_LIMITED 100
#define TSDB_CODE_GRANT_DNODE_LIMITED 101
#define TSDB_CODE_GRANT_CPU_LIMITED 102
#define TSDB_CODE_SESSION_NOT_READY 103 // table NOT in ready state
#define TSDB_CODE_BATCH_SIZE_TOO_BIG 104
#define TSDB_CODE_TIMESTAMP_OUT_OF_RANGE 105
#define TSDB_CODE_INVALID_QUERY_MSG 106 // failed to validate the sql expression msg by vnode
#define TSDB_CODE_CACHE_BLOCK_TS_DISORDERED 107 // time stamp in cache block is disordered
#define TSDB_CODE_FILE_BLOCK_TS_DISORDERED 108 // time stamp in file block is disordered
#define TSDB_CODE_INVALID_COMMIT_LOG 109 // commit log init failed
#define TSDB_CODE_SERV_NO_DISKSPACE 110
#define TSDB_CODE_NOT_SUPER_TABLE 111 // operation only available for super table
#define TSDB_CODE_DUPLICATE_TAGS 112 // tags value for join not unique
#define TSDB_CODE_INVALID_SUBMIT_MSG 113
#define TSDB_CODE_NOT_ACTIVE_TABLE 114
#define TSDB_CODE_INVALID_TABLE_ID 115
#define TSDB_CODE_INVALID_VNODE_STATUS 116
#define TSDB_CODE_FAILED_TO_LOCK_RESOURCES 117
#define TSDB_CODE_TABLE_ID_MISMATCH 118
#define TSDB_CODE_MAX_ERROR_CODE 119
#ifdef __cplusplus
}
#endif
#endif //TDENGINE_TAOSERROR_H

View File

@ -21,119 +21,7 @@ extern "C" {
#endif #endif
#include "tsdb.h" #include "tsdb.h"
#include "taoserror.h"
#define TSDB_CODE_SUCCESS 0
#define TSDB_CODE_ACTION_IN_PROGRESS 1
#define TSDB_CODE_LAST_SESSION_NOT_FINISHED 5
#define TSDB_CODE_INVALID_SESSION_ID 6
#define TSDB_CODE_INVALID_TRAN_ID 7
#define TSDB_CODE_INVALID_MSG_TYPE 8
#define TSDB_CODE_ALREADY_PROCESSED 9
#define TSDB_CODE_AUTH_FAILURE 10
#define TSDB_CODE_WRONG_MSG_SIZE 11
#define TSDB_CODE_UNEXPECTED_RESPONSE 12
#define TSDB_CODE_INVALID_RESPONSE_TYPE 13
#define TSDB_CODE_NO_RESOURCE 14
#define TSDB_CODE_INVALID_TIME_STAMP 15
#define TSDB_CODE_MISMATCHED_METER_ID 16
#define TSDB_CODE_ACTION_TRANS_NOT_FINISHED 17
#define TSDB_CODE_ACTION_NOT_ONLINE 18
#define TSDB_CODE_ACTION_SEND_FAILD 19
#define TSDB_CODE_NOT_ACTIVE_SESSION 20
#define TSDB_CODE_INSERT_FAILED 21
#define TSDB_CODE_APP_ERROR 22
#define TSDB_CODE_INVALID_IE 23
#define TSDB_CODE_INVALID_VALUE 24
#define TSDB_CODE_REDIRECT 25
#define TSDB_CODE_ALREADY_THERE 26
#define TSDB_CODE_INVALID_METER_ID 27
#define TSDB_CODE_INVALID_SQL 28
#define TSDB_CODE_NETWORK_UNAVAIL 29
#define TSDB_CODE_INVALID_MSG_LEN 30
#define TSDB_CODE_INVALID_DB 31
#define TSDB_CODE_INVALID_TABLE 32
#define TSDB_CODE_DB_ALREADY_EXIST 33
#define TSDB_CODE_TABLE_ALREADY_EXIST 34
#define TSDB_CODE_INVALID_USER 35
#define TSDB_CODE_INVALID_ACCT 36
#define TSDB_CODE_INVALID_PASS 37
#define TSDB_CODE_DB_NOT_SELECTED 38
#define TSDB_CODE_MEMORY_CORRUPTED 39
#define TSDB_CODE_USER_ALREADY_EXIST 40
#define TSDB_CODE_NO_RIGHTS 41
#define TSDB_CODE_DISCONNECTED 42
#define TSDB_CODE_NO_MASTER 43
#define TSDB_CODE_NOT_CONFIGURED 44
#define TSDB_CODE_INVALID_OPTION 45
#define TSDB_CODE_NODE_OFFLINE 46
#define TSDB_CODE_SYNC_REQUIRED 47
#define TSDB_CODE_NO_ENOUGH_DNODES 48
#define TSDB_CODE_UNSYNCED 49
#define TSDB_CODE_TOO_SLOW 50
#define TSDB_CODE_OTHERS 51
#define TSDB_CODE_NO_REMOVE_MASTER 52
#define TSDB_CODE_WRONG_SCHEMA 53
#define TSDB_CODE_NO_RESULT 54
#define TSDB_CODE_TOO_MANY_USERS 55
#define TSDB_CODE_TOO_MANY_DATABSES 56
#define TSDB_CODE_TOO_MANY_TABLES 57
#define TSDB_CODE_TOO_MANY_DNODES 58
#define TSDB_CODE_TOO_MANY_ACCTS 59
#define TSDB_CODE_ACCT_ALREADY_EXIST 60
#define TSDB_CODE_DNODE_ALREADY_EXIST 61
#define TSDB_CODE_SDB_ERROR 62
#define TSDB_CODE_METRICMETA_EXPIRED 63 // local cached metric-meta expired causes error in metric query
#define TSDB_CODE_NOT_READY 64 // peer is not ready to process data
#define TSDB_CODE_MAX_SESSIONS 65 // too many sessions
#define TSDB_CODE_MAX_CONNECTIONS 66 // too many connections
#define TSDB_CODE_SESSION_ALREADY_EXIST 67
#define TSDB_CODE_NO_QSUMMARY 68
#define TSDB_CODE_SERV_OUT_OF_MEMORY 69
#define TSDB_CODE_INVALID_QHANDLE 70
#define TSDB_CODE_RELATED_TABLES_EXIST 71
#define TSDB_CODE_MONITOR_DB_FORBEIDDEN 72
#define TSDB_CODE_VG_COMMITLOG_INIT_FAILED 73
#define TSDB_CODE_VG_INIT_FAILED 74
#define TSDB_CODE_DATA_ALREADY_IMPORTED 75
#define TSDB_CODE_OPS_NOT_SUPPORT 76
#define TSDB_CODE_INVALID_QUERY_ID 77
#define TSDB_CODE_INVALID_STREAM_ID 78
#define TSDB_CODE_INVALID_CONNECTION 79
#define TSDB_CODE_ACTION_NOT_BALANCED 80
#define TSDB_CODE_CLI_OUT_OF_MEMORY 81
#define TSDB_CODE_DATA_OVERFLOW 82
#define TSDB_CODE_QUERY_CANCELLED 83
#define TSDB_CODE_GRANT_TIMESERIES_LIMITED 84
#define TSDB_CODE_GRANT_EXPIRED 85
#define TSDB_CODE_CLI_NO_DISKSPACE 86
#define TSDB_CODE_FILE_CORRUPTED 87
#define TSDB_CODE_INVALID_CLIENT_VERSION 88
#define TSDB_CODE_INVALID_ACCT_PARAMETER 89
#define TSDB_CODE_NOT_ENOUGH_TIME_SERIES 90
#define TSDB_CODE_NO_WRITE_ACCESS 91
#define TSDB_CODE_NO_READ_ACCESS 92
#define TSDB_CODE_GRANT_DB_LIMITED 93
#define TSDB_CODE_GRANT_USER_LIMITED 94
#define TSDB_CODE_GRANT_CONN_LIMITED 95
#define TSDB_CODE_GRANT_STREAM_LIMITED 96
#define TSDB_CODE_GRANT_SPEED_LIMITED 97
#define TSDB_CODE_GRANT_STORAGE_LIMITED 98
#define TSDB_CODE_GRANT_QUERYTIME_LIMITED 99
#define TSDB_CODE_GRANT_ACCT_LIMITED 100
#define TSDB_CODE_GRANT_DNODE_LIMITED 101
#define TSDB_CODE_GRANT_CPU_LIMITED 102
#define TSDB_CODE_SESSION_NOT_READY 103 // table NOT in ready state
#define TSDB_CODE_BATCH_SIZE_TOO_BIG 104
#define TSDB_CODE_TIMESTAMP_OUT_OF_RANGE 105
#define TSDB_CODE_INVALID_QUERY_MSG 106 // failed to validate the sql expression msg by vnode
#define TSDB_CODE_CACHE_BLOCK_TS_DISORDERED 107 // time stamp in cache block is disordered
#define TSDB_CODE_FILE_BLOCK_TS_DISORDERED 108 // time stamp in file block is disordered
#define TSDB_CODE_INVALID_COMMIT_LOG 109 // commit log init failed
#define TSDB_CODE_SERVER_NO_SPACE 110
#define TSDB_CODE_NOT_SUPER_TABLE 111 //
#define TSDB_CODE_DUPLICATE_TAGS 112 // tags value for join not unique
#define TSDB_CODE_INVALID_SUBMIT_MSG 113
// message type // message type
#define TSDB_MSG_TYPE_REG 1 #define TSDB_MSG_TYPE_REG 1
@ -270,6 +158,7 @@ enum _mgmt_table {
TSDB_MGMT_TABLE_CONNS, TSDB_MGMT_TABLE_CONNS,
TSDB_MGMT_TABLE_SCORES, TSDB_MGMT_TABLE_SCORES,
TSDB_MGMT_TABLE_GRANTS, TSDB_MGMT_TABLE_GRANTS,
TSDB_MGMT_TABLE_VNODES,
TSDB_MGMT_TABLE_MAX, TSDB_MGMT_TABLE_MAX,
}; };
@ -333,10 +222,11 @@ typedef struct {
// internal part // internal part
uint32_t destId; uint32_t destId;
uint32_t destIp;
char meterId[TSDB_UNI_LEN]; char meterId[TSDB_UNI_LEN];
short port; // for UDP only uint16_t port; // for UDP only
char empty[1]; char empty[1];
char msgType; uint8_t msgType;
int32_t msgLen; int32_t msgLen;
uint8_t content[0]; uint8_t content[0];
} STaosHeader; } STaosHeader;
@ -390,7 +280,7 @@ typedef struct {
} SShellSubmitMsg; } SShellSubmitMsg;
typedef struct SSchema { typedef struct SSchema {
char type; uint8_t type;
char name[TSDB_COL_NAME_LEN]; char name[TSDB_COL_NAME_LEN];
short colId; short colId;
short bytes; short bytes;
@ -421,7 +311,7 @@ typedef struct {
} SCreateMsg; } SCreateMsg;
typedef struct { typedef struct {
char db[TSDB_DB_NAME_LEN]; char db[TSDB_METER_ID_LEN];
short ignoreNotExists; short ignoreNotExists;
} SDropDbMsg, SUseDbMsg; } SDropDbMsg, SUseDbMsg;
@ -461,6 +351,7 @@ typedef struct {
} SAlterTableMsg; } SAlterTableMsg;
typedef struct { typedef struct {
char clientVersion[TSDB_VERSION_LEN];
char db[TSDB_METER_ID_LEN]; char db[TSDB_METER_ID_LEN];
} SConnectMsg; } SConnectMsg;
@ -598,7 +489,7 @@ typedef struct SColumnInfo {
*/ */
typedef struct SMeterSidExtInfo { typedef struct SMeterSidExtInfo {
int32_t sid; int32_t sid;
void * pObj; int64_t uid;
char tags[]; char tags[];
} SMeterSidExtInfo; } SMeterSidExtInfo;
@ -673,13 +564,12 @@ typedef struct {
typedef struct { typedef struct {
uint64_t qhandle; uint64_t qhandle;
int16_t free; uint16_t free;
} SRetrieveMeterMsg; } SRetrieveMeterMsg;
typedef struct { typedef struct {
int32_t numOfRows; int32_t numOfRows;
int16_t precision; int16_t precision;
int16_t compress;
int64_t offset; // updated offset value for multi-vnode projection query int64_t offset; // updated offset value for multi-vnode projection query
int64_t useconds; int64_t useconds;
char data[]; char data[];
@ -695,7 +585,7 @@ typedef struct {
int64_t compStorage; int64_t compStorage;
int64_t pointsWritten; int64_t pointsWritten;
uint8_t syncStatus; uint8_t syncStatus;
uint8_t reserved; uint8_t reserved[15];
} SVnodeLoad; } SVnodeLoad;
typedef struct { typedef struct {
@ -706,6 +596,11 @@ typedef struct {
// NOTE: sizeof(SVnodeCfg) < TSDB_FILE_HEADER_LEN/4 // NOTE: sizeof(SVnodeCfg) < TSDB_FILE_HEADER_LEN/4
typedef struct { typedef struct {
char acct[TSDB_USER_LEN]; char acct[TSDB_USER_LEN];
/*
* the message is too large, so it may will overwrite the cfg information in meterobj.v*
* recover to origin codes
*/
//char db[TSDB_METER_ID_LEN+2]; // 8bytes align
char db[TSDB_DB_NAME_LEN]; char db[TSDB_DB_NAME_LEN];
uint32_t vgId; uint32_t vgId;
int32_t maxSessions; int32_t maxSessions;
@ -729,7 +624,7 @@ typedef struct {
char repStrategy; char repStrategy;
char loadLatest; // load into mem or not char loadLatest; // load into mem or not
char precision; // time resoluation uint8_t precision; // time resolution
char reserved[16]; char reserved[16];
} SVnodeCfg, SCreateDbMsg, SDbCfg, SAlterDbMsg; } SVnodeCfg, SCreateDbMsg, SDbCfg, SAlterDbMsg;
@ -769,9 +664,10 @@ typedef struct {
// internal message // internal message
typedef struct { typedef struct {
uint32_t destId; uint32_t destId;
uint32_t destIp;
char meterId[TSDB_UNI_LEN]; char meterId[TSDB_UNI_LEN];
char empty[3]; char empty[3];
char msgType; uint8_t msgType;
int32_t msgLen; int32_t msgLen;
uint8_t content[0]; uint8_t content[0];
} SIntMsg; } SIntMsg;
@ -831,9 +727,7 @@ typedef struct {
int32_t numOfMeters; int32_t numOfMeters;
int32_t join; int32_t join;
int32_t joinCondLen; // for join condition int32_t joinCondLen; // for join condition
int32_t metaElem[TSDB_MAX_JOIN_TABLE_NUM]; int32_t metaElem[TSDB_MAX_JOIN_TABLE_NUM];
} SMetricMetaMsg; } SMetricMetaMsg;
typedef struct { typedef struct {

View File

@ -25,7 +25,7 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
#include "taosmsg.h" #include "taosmsg.h"
#include "tsql.h" #include "ttypes.h"
struct tSQLBinaryExpr; struct tSQLBinaryExpr;
struct SSchema; struct SSchema;
@ -49,7 +49,7 @@ typedef struct tQueryInfo {
int32_t offset; // offset value in tags int32_t offset; // offset value in tags
int32_t colIdx; // index of column in schema int32_t colIdx; // index of column in schema
uint8_t optr; // expression operator uint8_t optr; // expression operator
SSchema sch; // schema of tags SSchema sch; // schema of tags
tVariant q; // query condition value on the specific schema, filter expression tVariant q; // query condition value on the specific schema, filter expression
__compar_fn_t compare; // filter function __compar_fn_t compare; // filter function
} tQueryInfo; } tQueryInfo;

View File

@ -57,12 +57,12 @@ extern char scriptDir[];
extern char tsMasterIp[]; extern char tsMasterIp[];
extern char tsSecondIp[]; extern char tsSecondIp[];
extern short tsMgmtVnodePort; extern uint16_t tsMgmtVnodePort;
extern short tsMgmtShellPort; extern uint16_t tsMgmtShellPort;
extern short tsVnodeShellPort; extern uint16_t tsVnodeShellPort;
extern short tsVnodeVnodePort; extern uint16_t tsVnodeVnodePort;
extern short tsMgmtMgmtPort; extern uint16_t tsMgmtMgmtPort;
extern short tsMgmtSyncPort; extern uint16_t tsMgmtSyncPort;
extern int tsStatusInterval; extern int tsStatusInterval;
extern int tsShellActivityTimer; extern int tsShellActivityTimer;
@ -74,13 +74,13 @@ extern int tsMetricMetaKeepTimer;
extern float tsNumOfThreadsPerCore; extern float tsNumOfThreadsPerCore;
extern float tsRatioOfQueryThreads; extern float tsRatioOfQueryThreads;
extern char tsPublicIp[]; extern char tsPublicIp[];
extern char tsInternalIp[];
extern char tsPrivateIp[]; extern char tsPrivateIp[];
extern char tsServerIpStr[]; extern char tsServerIpStr[];
extern short tsNumOfVnodesPerCore; extern short tsNumOfVnodesPerCore;
extern short tsNumOfTotalVnodes; extern short tsNumOfTotalVnodes;
extern short tsCheckHeaderFile; extern short tsCheckHeaderFile;
extern uint32_t tsServerIp; extern uint32_t tsServerIp;
extern uint32_t tsPublicIpInt;
extern int tsSessionsPerVnode; extern int tsSessionsPerVnode;
extern int tsAverageCacheBlocks; extern int tsAverageCacheBlocks;
@ -106,7 +106,6 @@ extern int tsMaxDbs;
extern int tsMaxTables; extern int tsMaxTables;
extern int tsMaxDnodes; extern int tsMaxDnodes;
extern int tsMaxVGroups; extern int tsMaxVGroups;
extern int tsShellActivityTimer;
extern char tsMgmtZone[]; extern char tsMgmtZone[];
extern char tsLocalIp[]; extern char tsLocalIp[];
@ -127,6 +126,7 @@ extern int tsEnableHttpModule;
extern int tsEnableMonitorModule; extern int tsEnableMonitorModule;
extern int tsRestRowLimit; extern int tsRestRowLimit;
extern int tsCompressMsgSize; extern int tsCompressMsgSize;
extern int tsMaxSQLStringLen;
extern char tsSocketType[4]; extern char tsSocketType[4];
@ -141,7 +141,7 @@ extern int tsProjectExecInterval;
extern int64_t tsMaxRetentWindow; extern int64_t tsMaxRetentWindow;
extern char tsHttpIp[]; extern char tsHttpIp[];
extern short tsHttpPort; extern uint16_t tsHttpPort;
extern int tsHttpCacheSessions; extern int tsHttpCacheSessions;
extern int tsHttpSessionExpire; extern int tsHttpSessionExpire;
extern int tsHttpMaxThreads; extern int tsHttpMaxThreads;
@ -150,6 +150,10 @@ extern int tsHttpEnableRecordSql;
extern int tsTelegrafUseFieldNum; extern int tsTelegrafUseFieldNum;
extern int tsAdminRowLimit; extern int tsAdminRowLimit;
extern int tsTscEnableRecordSql;
extern int tsAnyIp;
extern int tsIsCluster;
extern char tsMonitorDbName[]; extern char tsMonitorDbName[];
extern char tsInternalPass[]; extern char tsInternalPass[];
extern int tsMonitorInterval; extern int tsMonitorInterval;
@ -169,12 +173,15 @@ extern uint32_t debugFlag;
extern uint32_t odbcdebugFlag; extern uint32_t odbcdebugFlag;
extern uint32_t qdebugFlag; extern uint32_t qdebugFlag;
extern uint32_t taosMaxTmrCtrl;
extern int tsRpcTimer; extern int tsRpcTimer;
extern int tsRpcMaxTime; extern int tsRpcMaxTime;
extern int tsUdpDelay; extern int tsUdpDelay;
extern char version[]; extern char version[];
extern char compatible_version[]; extern char compatible_version[];
extern char gitinfo[]; extern char gitinfo[];
extern char gitinfoOfInternal[];
extern char buildinfo[]; extern char buildinfo[];
extern char tsTimezone[64]; extern char tsTimezone[64];
@ -245,13 +252,15 @@ typedef struct {
extern SGlobalConfig *tsGlobalConfig; extern SGlobalConfig *tsGlobalConfig;
extern int tsGlobalConfigNum; extern int tsGlobalConfigNum;
extern char * tsCfgStatusStr[]; extern char * tsCfgStatusStr[];
SGlobalConfig *tsGetConfigOption(char *option); SGlobalConfig *tsGetConfigOption(const char *option);
#define TSDB_CFG_MAX_NUM 110 #define TSDB_CFG_MAX_NUM 110
#define TSDB_CFG_PRINT_LEN 23 #define TSDB_CFG_PRINT_LEN 23
#define TSDB_CFG_OPTION_LEN 24 #define TSDB_CFG_OPTION_LEN 24
#define TSDB_CFG_VALUE_LEN 41 #define TSDB_CFG_VALUE_LEN 41
#define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

63
src/inc/tnote.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TNOTE_H
#define TDENGINE_TNOTE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "os.h"
#include "tutil.h"
#include "tglobalcfg.h"
#define MAX_NOTE_LINE_SIZE 66000
#define NOTE_FILE_NAME_LEN 300
typedef struct _taosNoteInfo {
int taosNoteFileNum ;
int taosNoteMaxLines;
int taosNoteLines;
char taosNoteName[NOTE_FILE_NAME_LEN];
int taosNoteFlag;
int taosNoteFd;
int taosNoteOpenInProgress;
pthread_mutex_t taosNoteMutex;
}taosNoteInfo;
void taosNotePrint(taosNoteInfo * pNote, const char * const format, ...);
extern taosNoteInfo m_HttpNote;
extern taosNoteInfo m_TscNote;
extern int tsHttpEnableRecordSql;
extern int tsTscEnableRecordSql;
#define taosNotePrintHttp(...) \
if (tsHttpEnableRecordSql) { \
taosNotePrint(&m_HttpNote, __VA_ARGS__); \
}
#define taosNotePrintTsc(...) \
if (tsTscEnableRecordSql) { \
taosNotePrint(&m_TscNote, __VA_ARGS__); \
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -25,7 +25,6 @@ extern "C" {
#define TAOS_CONN_UDPS 0 #define TAOS_CONN_UDPS 0
#define TAOS_CONN_UDPC 1 #define TAOS_CONN_UDPC 1
#define TAOS_CONN_UDP 1
#define TAOS_CONN_TCPS 2 #define TAOS_CONN_TCPS 2
#define TAOS_CONN_TCPC 3 #define TAOS_CONN_TCPC 3
#define TAOS_CONN_HTTPS 4 #define TAOS_CONN_HTTPS 4
@ -39,7 +38,7 @@ extern "C" {
#define TAOS_ID_REALLOCATE 2 #define TAOS_ID_REALLOCATE 2
#define TAOS_CONN_SOCKET_TYPE_S() ((strcasecmp(tsSocketType, TAOS_SOCKET_TYPE_NAME_UDP) == 0)? TAOS_CONN_UDPS:TAOS_CONN_TCPS) #define TAOS_CONN_SOCKET_TYPE_S() ((strcasecmp(tsSocketType, TAOS_SOCKET_TYPE_NAME_UDP) == 0)? TAOS_CONN_UDPS:TAOS_CONN_TCPS)
#define TAOS_CONN_SOCKET_TYPE_C() ((strcasecmp(tsSocketType, TAOS_SOCKET_TYPE_NAME_UDP) == 0)? TAOS_CONN_UDP:TAOS_CONN_TCPC) #define TAOS_CONN_SOCKET_TYPE_C() ((strcasecmp(tsSocketType, TAOS_SOCKET_TYPE_NAME_UDP) == 0)? TAOS_CONN_UDPC:TAOS_CONN_TCPC)
#define taosSendMsgToPeer(x, y, z) taosSendMsgToPeerH(x, y, z, NULL) #define taosSendMsgToPeer(x, y, z) taosSendMsgToPeerH(x, y, z, NULL)
#define taosOpenRpcChann(x, y, z) taosOpenRpcChannWithQ(x,y,z,NULL) #define taosOpenRpcChann(x, y, z) taosOpenRpcChannWithQ(x,y,z,NULL)
@ -48,7 +47,7 @@ extern "C" {
typedef struct { typedef struct {
char *localIp; // local IP used char *localIp; // local IP used
short localPort; // local port uint16_t localPort; // local port
char *label; // for debug purpose char *label; // for debug purpose
int numOfThreads; // number of threads to handle connections int numOfThreads; // number of threads to handle connections
void *(*fp)(char *, void *, void *); // function to process the incoming msg void *(*fp)(char *, void *, void *); // function to process the incoming msg
@ -73,7 +72,7 @@ typedef struct {
void * shandle; // pointer returned by taosOpenRpc void * shandle; // pointer returned by taosOpenRpc
void * ahandle; // handle provided by app void * ahandle; // handle provided by app
char * peerIp; // peer IP string char * peerIp; // peer IP string
short peerPort; // peer port uint16_t peerPort; // peer port
char spi; // security parameter index char spi; // security parameter index
char encrypt; // encrypt algorithm char encrypt; // encrypt algorithm
char * secret; // key for authentication char * secret; // key for authentication
@ -108,7 +107,7 @@ int taosSendSimpleRsp(void *thandle, char rsptype, char code);
int taosSetSecurityInfo(int cid, int sid, char *id, int spi, int encrypt, char *secret, char *ckey); int taosSetSecurityInfo(int cid, int sid, char *id, int spi, int encrypt, char *secret, char *ckey);
void taosGetRpcConnInfo(void *thandle, uint32_t *peerId, uint32_t *peerIp, short *peerPort, int *cid, int *sid); void taosGetRpcConnInfo(void *thandle, uint32_t *peerId, uint32_t *peerIp, uint16_t *peerPort, int *cid, int *sid);
int taosGetOutType(void *thandle); int taosGetOutType(void *thandle);

View File

@ -32,6 +32,8 @@ typedef struct _sched_msg {
void *taosInitScheduler(int queueSize, int numOfThreads, const char *label); void *taosInitScheduler(int queueSize, int numOfThreads, const char *label);
void *taosInitSchedulerWithInfo(int queueSize, int numOfThreads, const char *label, void *tmrCtrl);
int taosScheduleTask(void *qhandle, SSchedMsg *pMsg); int taosScheduleTask(void *qhandle, SSchedMsg *pMsg);
void taosCleanUpScheduler(void *param); void taosCleanUpScheduler(void *param);

View File

@ -47,12 +47,13 @@ struct SSchema *tsGetSchema(SMeterMeta *pMeta);
struct SSchema *tsGetTagSchema(SMeterMeta *pMeta); struct SSchema *tsGetTagSchema(SMeterMeta *pMeta);
struct SSchema *tsGetColumnSchema(SMeterMeta *pMeta, int32_t startCol); struct SSchema *tsGetColumnSchema(SMeterMeta *pMeta, int32_t startCol);
struct SSchema tsGetTbnameColumnSchema();
char *tsGetTagsValue(SMeterMeta *pMeta); char *tsGetTagsValue(SMeterMeta *pMeta);
bool tsMeterMetaIdentical(SMeterMeta *p1, SMeterMeta *p2); bool tsMeterMetaIdentical(SMeterMeta *p1, SMeterMeta *p2);
void extractMeterName(char *meterId, char *name); void extractTableName(char *meterId, char *name);
SSQLToken extractDBName(char *meterId, char *name); SSQLToken extractDBName(char *meterId, char *name);

View File

@ -44,22 +44,6 @@ extern "C" {
#define TSDB_TIME_PRECISION_MILLI_STR "ms" #define TSDB_TIME_PRECISION_MILLI_STR "ms"
#define TSDB_TIME_PRECISION_MICRO_STR "us" #define TSDB_TIME_PRECISION_MICRO_STR "us"
enum _status {
TSDB_STATUS_OFFLINE,
TSDB_STATUS_CREATING,
TSDB_STATUS_UNSYNCED,
TSDB_STATUS_SLAVE,
TSDB_STATUS_MASTER,
TSDB_STATUS_READY,
};
enum _syncstatus {
STDB_SSTATUS_INIT,
TSDB_SSTATUS_SYNCING,
TSDB_SSTATUS_SYNC_CACHE,
TSDB_SSTATUS_SYNC_FILE,
};
#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes #define TSDB_DATA_TYPE_BOOL 1 // 1 bytes
#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte #define TSDB_DATA_TYPE_TINYINT 2 // 1 byte
#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes #define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes
@ -116,6 +100,7 @@ enum _syncstatus {
#define TSDB_COL_NAME_LEN 64 #define TSDB_COL_NAME_LEN 64
#define TSDB_MAX_SAVED_SQL_LEN TSDB_MAX_COLUMNS * 16 #define TSDB_MAX_SAVED_SQL_LEN TSDB_MAX_COLUMNS * 16
#define TSDB_MAX_SQL_LEN TSDB_PAYLOAD_SIZE #define TSDB_MAX_SQL_LEN TSDB_PAYLOAD_SIZE
#define TSDB_MAX_ALLOWED_SQL_LEN (8*1024*1024U) // sql length should be less than 6mb
#define TSDB_MAX_BYTES_PER_ROW TSDB_MAX_COLUMNS * 16 #define TSDB_MAX_BYTES_PER_ROW TSDB_MAX_COLUMNS * 16
#define TSDB_MAX_TAGS_LEN 512 #define TSDB_MAX_TAGS_LEN 512
@ -162,8 +147,11 @@ enum _syncstatus {
#define TSDB_MAX_MPEERS 5 #define TSDB_MAX_MPEERS 5
#define TSDB_MAX_MGMT_IPS (TSDB_MAX_MPEERS+1) #define TSDB_MAX_MGMT_IPS (TSDB_MAX_MPEERS+1)
//#define TSDB_REPLICA_MAX_NUM 3
#define TSDB_REPLICA_MIN_NUM 1 #define TSDB_REPLICA_MIN_NUM 1
/*
* this is defined in CMakeList.txt
*/
//#define TSDB_REPLICA_MAX_NUM 3
#define TSDB_TBNAME_COLUMN_INDEX (-1) #define TSDB_TBNAME_COLUMN_INDEX (-1)
#define TSDB_MULTI_METERMETA_MAX_NUM 100000 // maximum batch size allowed to load metermeta #define TSDB_MULTI_METERMETA_MAX_NUM 100000 // maximum batch size allowed to load metermeta
@ -178,9 +166,6 @@ enum _syncstatus {
#define TSDB_MIN_COMPRESSION_LEVEL 0 #define TSDB_MIN_COMPRESSION_LEVEL 0
#define TSDB_MAX_COMPRESSION_LEVEL 2 #define TSDB_MAX_COMPRESSION_LEVEL 2
#define TSDB_MIN_CACHE_BLOCKS_PER_METER 32
#define TSDB_MAX_CACHE_BLOCKS_PER_METER 40960
#define TSDB_MIN_COMMIT_TIME_INTERVAL 30 #define TSDB_MIN_COMMIT_TIME_INTERVAL 30
#define TSDB_MAX_COMMIT_TIME_INTERVAL 40960 #define TSDB_MAX_COMMIT_TIME_INTERVAL 40960
@ -193,7 +178,9 @@ enum _syncstatus {
#define TSDB_MIN_CACHE_BLOCKS 100 #define TSDB_MIN_CACHE_BLOCKS 100
#define TSDB_MAX_CACHE_BLOCKS 409600 #define TSDB_MAX_CACHE_BLOCKS 409600
#define TSDB_MIN_AVG_BLOCKS 2
#define TSDB_MAX_AVG_BLOCKS 2048 #define TSDB_MAX_AVG_BLOCKS 2048
#define TSDB_DEFAULT_AVG_BLOCKS 4
#define TSDB_MIN_TABLES_PER_VNODE 1 #define TSDB_MIN_TABLES_PER_VNODE 1
#define TSDB_MAX_TABLES_PER_VNODE 220000 #define TSDB_MAX_TABLES_PER_VNODE 220000
@ -220,21 +207,24 @@ enum _syncstatus {
#define TSDB_MAX_RPC_THREADS 5 #define TSDB_MAX_RPC_THREADS 5
#define TSDB_QUERY_TYPE_QUERY 0 // normal query #define TSDB_QUERY_TYPE_QUERY 0 // normal query
#define TSDB_QUERY_TYPE_FREE_RESOURCE 0x1 // free qhandle at vnode #define TSDB_QUERY_TYPE_FREE_RESOURCE 0x01U // free qhandle at vnode
/* /*
* 1. ordinary sub query for select * from super_table * 1. ordinary sub query for select * from super_table
* 2. all sqlobj generated by createSubqueryObj with this flag * 2. all sqlobj generated by createSubqueryObj with this flag
*/ */
#define TSDB_QUERY_TYPE_SUBQUERY 0x2 #define TSDB_QUERY_TYPE_SUBQUERY 0x02U
#define TSDB_QUERY_TYPE_STABLE_SUBQUERY 0x4 // two-stage subquery for super table #define TSDB_QUERY_TYPE_STABLE_SUBQUERY 0x04U // two-stage subquery for super table
#define TSDB_QUERY_TYPE_TABLE_QUERY 0x8 // query ordinary table; below only apply to client side #define TSDB_QUERY_TYPE_TABLE_QUERY 0x08U // query ordinary table; below only apply to client side
#define TSDB_QUERY_TYPE_STABLE_QUERY 0x10 // query on super table #define TSDB_QUERY_TYPE_STABLE_QUERY 0x10U // query on super table
#define TSDB_QUERY_TYPE_JOIN_QUERY 0x20 // join query #define TSDB_QUERY_TYPE_JOIN_QUERY 0x20U // join query
#define TSDB_QUERY_TYPE_PROJECTION_QUERY 0x40 // select *,columns... query #define TSDB_QUERY_TYPE_PROJECTION_QUERY 0x40U // select *,columns... query
#define TSDB_QUERY_TYPE_JOIN_SEC_STAGE 0x80 // join sub query at the second stage #define TSDB_QUERY_TYPE_JOIN_SEC_STAGE 0x80U // join sub query at the second stage
#define TSQL_SO_ASC 1
#define TSQL_SO_DESC 0
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -33,19 +33,19 @@ int taosWriteMsg(int fd, void *ptr, int nbytes);
int taosReadMsg(int fd, void *ptr, int nbytes); int taosReadMsg(int fd, void *ptr, int nbytes);
int taosOpenUdpSocket(char *ip, short port); int taosOpenUdpSocket(char *ip, uint16_t port);
int taosOpenTcpClientSocket(char *ip, short port, char *localIp); int taosOpenTcpClientSocket(char *ip, uint16_t port, char *localIp);
int taosOpenTcpServerSocket(char *ip, short port); int taosOpenTcpServerSocket(char *ip, uint16_t port);
int taosKeepTcpAlive(int sockFd); int taosKeepTcpAlive(int sockFd);
void taosCloseTcpSocket(int sockFd); void taosCloseTcpSocket(int sockFd);
int taosOpenUDServerSocket(char *ip, short port); int taosOpenUDServerSocket(char *ip, uint16_t port);
int taosOpenUDClientSocket(char *ip, short port); int taosOpenUDClientSocket(char *ip, uint16_t port);
int taosOpenRawSocket(char *ip); int taosOpenRawSocket(char *ip);

View File

@ -72,146 +72,144 @@
#define TK_CONFIGS 54 #define TK_CONFIGS 54
#define TK_SCORES 55 #define TK_SCORES 55
#define TK_GRANTS 56 #define TK_GRANTS 56
#define TK_DOT 57 #define TK_VNODES 57
#define TK_TABLES 58 #define TK_IPTOKEN 58
#define TK_STABLES 59 #define TK_DOT 59
#define TK_VGROUPS 60 #define TK_TABLES 60
#define TK_DROP 61 #define TK_STABLES 61
#define TK_TABLE 62 #define TK_VGROUPS 62
#define TK_DATABASE 63 #define TK_DROP 63
#define TK_DNODE 64 #define TK_TABLE 64
#define TK_IP 65 #define TK_DATABASE 65
#define TK_USER 66 #define TK_DNODE 66
#define TK_ACCOUNT 67 #define TK_USER 67
#define TK_USE 68 #define TK_ACCOUNT 68
#define TK_DESCRIBE 69 #define TK_USE 69
#define TK_ALTER 70 #define TK_DESCRIBE 70
#define TK_PASS 71 #define TK_ALTER 71
#define TK_PRIVILEGE 72 #define TK_PASS 72
#define TK_LOCAL 73 #define TK_PRIVILEGE 73
#define TK_IF 74 #define TK_LOCAL 74
#define TK_EXISTS 75 #define TK_IF 75
#define TK_CREATE 76 #define TK_EXISTS 76
#define TK_PPS 77 #define TK_CREATE 77
#define TK_TSERIES 78 #define TK_PPS 78
#define TK_DBS 79 #define TK_TSERIES 79
#define TK_STORAGE 80 #define TK_DBS 80
#define TK_QTIME 81 #define TK_STORAGE 81
#define TK_CONNS 82 #define TK_QTIME 82
#define TK_STATE 83 #define TK_CONNS 83
#define TK_KEEP 84 #define TK_STATE 84
#define TK_CACHE 85 #define TK_KEEP 85
#define TK_REPLICA 86 #define TK_CACHE 86
#define TK_DAYS 87 #define TK_REPLICA 87
#define TK_ROWS 88 #define TK_DAYS 88
#define TK_ABLOCKS 89 #define TK_ROWS 89
#define TK_TBLOCKS 90 #define TK_ABLOCKS 90
#define TK_CTIME 91 #define TK_TBLOCKS 91
#define TK_CLOG 92 #define TK_CTIME 92
#define TK_COMP 93 #define TK_CLOG 93
#define TK_PRECISION 94 #define TK_COMP 94
#define TK_LP 95 #define TK_PRECISION 95
#define TK_RP 96 #define TK_LP 96
#define TK_TAGS 97 #define TK_RP 97
#define TK_USING 98 #define TK_TAGS 98
#define TK_AS 99 #define TK_USING 99
#define TK_COMMA 100 #define TK_AS 100
#define TK_NULL 101 #define TK_COMMA 101
#define TK_SELECT 102 #define TK_NULL 102
#define TK_FROM 103 #define TK_SELECT 103
#define TK_VARIABLE 104 #define TK_FROM 104
#define TK_INTERVAL 105 #define TK_VARIABLE 105
#define TK_FILL 106 #define TK_INTERVAL 106
#define TK_SLIDING 107 #define TK_FILL 107
#define TK_ORDER 108 #define TK_SLIDING 108
#define TK_BY 109 #define TK_ORDER 109
#define TK_ASC 110 #define TK_BY 110
#define TK_DESC 111 #define TK_ASC 111
#define TK_GROUP 112 #define TK_DESC 112
#define TK_HAVING 113 #define TK_GROUP 113
#define TK_LIMIT 114 #define TK_HAVING 114
#define TK_OFFSET 115 #define TK_LIMIT 115
#define TK_SLIMIT 116 #define TK_OFFSET 116
#define TK_SOFFSET 117 #define TK_SLIMIT 117
#define TK_WHERE 118 #define TK_SOFFSET 118
#define TK_NOW 119 #define TK_WHERE 119
#define TK_INSERT 120 #define TK_NOW 120
#define TK_INTO 121 #define TK_INSERT 121
#define TK_VALUES 122 #define TK_INTO 122
#define TK_RESET 123 #define TK_VALUES 123
#define TK_QUERY 124 #define TK_RESET 124
#define TK_ADD 125 #define TK_QUERY 125
#define TK_COLUMN 126 #define TK_ADD 126
#define TK_TAG 127 #define TK_COLUMN 127
#define TK_CHANGE 128 #define TK_TAG 128
#define TK_SET 129 #define TK_CHANGE 129
#define TK_KILL 130 #define TK_SET 130
#define TK_CONNECTION 131 #define TK_KILL 131
#define TK_COLON 132 #define TK_CONNECTION 132
#define TK_STREAM 133 #define TK_COLON 133
#define TK_ABORT 134 #define TK_STREAM 134
#define TK_AFTER 135 #define TK_ABORT 135
#define TK_ATTACH 136 #define TK_AFTER 136
#define TK_BEFORE 137 #define TK_ATTACH 137
#define TK_BEGIN 138 #define TK_BEFORE 138
#define TK_CASCADE 139 #define TK_BEGIN 139
#define TK_CLUSTER 140 #define TK_CASCADE 140
#define TK_CONFLICT 141 #define TK_CLUSTER 141
#define TK_COPY 142 #define TK_CONFLICT 142
#define TK_DEFERRED 143 #define TK_COPY 143
#define TK_DELIMITERS 144 #define TK_DEFERRED 144
#define TK_DETACH 145 #define TK_DELIMITERS 145
#define TK_EACH 146 #define TK_DETACH 146
#define TK_END 147 #define TK_EACH 147
#define TK_EXPLAIN 148 #define TK_END 148
#define TK_FAIL 149 #define TK_EXPLAIN 149
#define TK_FOR 150 #define TK_FAIL 150
#define TK_IGNORE 151 #define TK_FOR 151
#define TK_IMMEDIATE 152 #define TK_IGNORE 152
#define TK_INITIALLY 153 #define TK_IMMEDIATE 153
#define TK_INSTEAD 154 #define TK_INITIALLY 154
#define TK_MATCH 155 #define TK_INSTEAD 155
#define TK_KEY 156 #define TK_MATCH 156
#define TK_OF 157 #define TK_KEY 157
#define TK_RAISE 158 #define TK_OF 158
#define TK_REPLACE 159 #define TK_RAISE 159
#define TK_RESTRICT 160 #define TK_REPLACE 160
#define TK_ROW 161 #define TK_RESTRICT 161
#define TK_STATEMENT 162 #define TK_ROW 162
#define TK_TRIGGER 163 #define TK_STATEMENT 163
#define TK_VIEW 164 #define TK_TRIGGER 164
#define TK_ALL 165 #define TK_VIEW 165
#define TK_COUNT 166 #define TK_ALL 166
#define TK_SUM 167 #define TK_COUNT 167
#define TK_AVG 168 #define TK_SUM 168
#define TK_MIN 169 #define TK_AVG 169
#define TK_MAX 170 #define TK_MIN 170
#define TK_FIRST 171 #define TK_MAX 171
#define TK_LAST 172 #define TK_FIRST 172
#define TK_TOP 173 #define TK_LAST 173
#define TK_BOTTOM 174 #define TK_TOP 174
#define TK_STDDEV 175 #define TK_BOTTOM 175
#define TK_PERCENTILE 176 #define TK_STDDEV 176
#define TK_APERCENTILE 177 #define TK_PERCENTILE 177
#define TK_LEASTSQUARES 178 #define TK_APERCENTILE 178
#define TK_HISTOGRAM 179 #define TK_LEASTSQUARES 179
#define TK_DIFF 180 #define TK_HISTOGRAM 180
#define TK_SPREAD 181 #define TK_DIFF 181
#define TK_TWA 182 #define TK_SPREAD 182
#define TK_INTERP 183 #define TK_TWA 183
#define TK_LAST_ROW 184 #define TK_INTERP 184
#define TK_SEMI 185 #define TK_LAST_ROW 185
#define TK_NONE 186 #define TK_SEMI 186
#define TK_PREV 187 #define TK_NONE 187
#define TK_LINEAR 188 #define TK_PREV 188
#define TK_IMPORT 189 #define TK_LINEAR 189
#define TK_METRIC 190 #define TK_IMPORT 190
#define TK_TBNAME 191 #define TK_METRIC 191
#define TK_JOIN 192 #define TK_TBNAME 192
#define TK_METRICS 193 #define TK_JOIN 193
#define TK_STABLE 194 #define TK_METRICS 194
#define TK_QUESTION 195 #define TK_STABLE 195
#endif #endif

View File

@ -24,7 +24,6 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include "trpc.h" #include "trpc.h"
#include "tsql.h"
#include "ttypes.h" #include "ttypes.h"
#define TSDB_FUNC_INVALID_ID -1 #define TSDB_FUNC_INVALID_ID -1
@ -228,8 +227,6 @@ typedef struct SPatternCompareInfo {
int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type, int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type,
int16_t *len, int16_t *interResBytes, int16_t extLength, bool isSuperTable); int16_t *len, int16_t *interResBytes, int16_t extLength, bool isSuperTable);
SResultInfo *getResultSupportInfo(SQLFunctionCtx *pCtx);
int patternMatch(const char *zPattern, const char *zString, size_t size, const SPatternCompareInfo *pInfo); int patternMatch(const char *zPattern, const char *zString, size_t size, const SPatternCompareInfo *pInfo);
int WCSPatternMatch(const wchar_t *zPattern, const wchar_t *zString, size_t size, const SPatternCompareInfo *pInfo); int WCSPatternMatch(const wchar_t *zPattern, const wchar_t *zString, size_t size, const SPatternCompareInfo *pInfo);

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TSTATUS_H
#define TDENGINE_TSTATUS_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *sdbDnodeStatusStr[];
extern char *sdbDnodeBalanceStateStr[];
extern char *sdbVnodeDropStateStr[];
extern char *sdbVnodeSyncStatusStr[];
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_TSTATUS_H

View File

@ -22,6 +22,18 @@ extern "C" {
#include <stdbool.h> #include <stdbool.h>
#define TK_SPACE 200
#define TK_COMMENT 201
#define TK_ILLEGAL 202
#define TK_HEX 203 // hex number 0x123
#define TK_OCT 204 // oct number
#define TK_BIN 205 // bin format data 0b111
#define TK_FILE 206
#define TK_QUESTION 207 // denoting the placeholder of "?",when invoking statement bind query
#define TSQL_TBNAME "TBNAME"
#define TSQL_TBNAME_L "tbname"
// used to denote the minimum unite in sql parsing // used to denote the minimum unite in sql parsing
typedef struct SSQLToken { typedef struct SSQLToken {
uint32_t n; uint32_t n;
@ -29,10 +41,6 @@ typedef struct SSQLToken {
char * z; char * z;
} SSQLToken; } SSQLToken;
#if 0
char *tscGetToken(char *string, char **token, int *tokenLen);
#endif
/** /**
* tokenizer for sql string * tokenizer for sql string
* @param z * @param z

View File

@ -21,40 +21,41 @@ extern "C" {
#endif #endif
typedef void *tmr_h; typedef void *tmr_h;
typedef void (*TAOS_TMR_CALLBACK)(void *, void *);
extern uint32_t tmrDebugFlag; extern uint32_t tmrDebugFlag;
extern int taosTmrThreads; extern int taosTmrThreads;
extern uint32_t taosMaxTmrCtrl;
#define tmrError(...) \ #define tmrError(...) \
if (tmrDebugFlag & DEBUG_ERROR) { \ do { if (tmrDebugFlag & DEBUG_ERROR) { \
tprintf("ERROR TMR ", tmrDebugFlag, __VA_ARGS__); \ tprintf("ERROR TMR ", tmrDebugFlag, __VA_ARGS__); \
} } } while(0)
#define tmrWarn(...) \
if (tmrDebugFlag & DEBUG_WARN) { \ #define tmrWarn(...) \
tprintf("WARN TMR ", tmrDebugFlag, __VA_ARGS__); \ do { if (tmrDebugFlag & DEBUG_WARN) { \
} tprintf("WARN TMR ", tmrDebugFlag, __VA_ARGS__); \
#define tmrTrace(...) \ } } while(0)
if (tmrDebugFlag & DEBUG_TRACE) { \
tprintf("TMR ", tmrDebugFlag, __VA_ARGS__); \ #define tmrTrace(...) \
} do { if (tmrDebugFlag & DEBUG_TRACE) { \
tprintf("TMR ", tmrDebugFlag, __VA_ARGS__); \
} } while(0)
#define MAX_NUM_OF_TMRCTL 512
#define MSECONDS_PER_TICK 5 #define MSECONDS_PER_TICK 5
void *taosTmrInit(int maxTmr, int resoultion, int longest, char *label); void *taosTmrInit(int maxTmr, int resoultion, int longest, const char *label);
tmr_h taosTmrStart(void (*fp)(void *, void *), int mseconds, void *param1, void *handle); tmr_h taosTmrStart(TAOS_TMR_CALLBACK fp, int mseconds, void *param, void *handle);
void taosTmrStop(tmr_h tmrId); bool taosTmrStop(tmr_h tmrId);
void taosTmrStopA(tmr_h *timerId); bool taosTmrStopA(tmr_h *timerId);
void taosTmrReset(void (*fp)(void *, void *), int mseconds, void *param1, void *handle, tmr_h *pTmrId); bool taosTmrReset(TAOS_TMR_CALLBACK fp, int mseconds, void *param, void *handle, tmr_h *pTmrId);
void taosTmrCleanUp(void *handle); void taosTmrCleanUp(void *handle);
void taosTmrList(void *handle);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -50,7 +50,7 @@ bool isNull(const char *val, int32_t type);
void setNull(char *val, int32_t type, int32_t bytes); void setNull(char *val, int32_t type, int32_t bytes);
void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems); void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems);
void assignVal(char *val, char *src, int32_t len, int32_t type); void assignVal(char *val, const char *src, int32_t len, int32_t type);
void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size); void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size);
// variant, each number/string/field_id has a corresponding struct during parsing sql // variant, each number/string/field_id has a corresponding struct during parsing sql

View File

@ -26,17 +26,19 @@ extern "C" {
#include "tsdb.h" #include "tsdb.h"
#ifndef STDERR_FILENO #ifndef STDERR_FILENO
#define VALIDFD(x) ((x) > 2) #define STDERR_FILENO (2)
#else
#define VALIDFD(x) ((x) > STDERR_FILENO)
#endif #endif
#define FD_VALID(x) ((x) > STDERR_FILENO)
#define FD_INITIALIZER ((int32_t)-1)
#define WCHAR wchar_t #define WCHAR wchar_t
#define tfree(x) \ #define tfree(x) \
{ \ { \
if (x) { \ if (x) { \
free(x); \ free((void*)(x)); \
x = NULL; \ x = 0; \
} \ } \
} }
@ -89,7 +91,7 @@ extern "C" {
} else { \ } else { \
return (x) < (y) ? -1 : 1; \ return (x) < (y) ? -1 : 1; \
} \ } \
} while (0); } while (0)
#define GET_INT8_VAL(x) (*(int8_t *)(x)) #define GET_INT8_VAL(x) (*(int8_t *)(x))
#define GET_INT16_VAL(x) (*(int16_t *)(x)) #define GET_INT16_VAL(x) (*(int16_t *)(x))
@ -169,13 +171,11 @@ int32_t taosInitTimer(void (*callback)(int), int32_t ms);
*/ */
uint32_t MurmurHash3_32(const void *key, int32_t len); uint32_t MurmurHash3_32(const void *key, int32_t len);
bool taosCheckDbName(char *db, char *monitordb);
bool taosMbsToUcs4(char *mbs, int32_t mbs_len, char *ucs4, int32_t ucs4_max_len); bool taosMbsToUcs4(char *mbs, int32_t mbs_len, char *ucs4, int32_t ucs4_max_len);
bool taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs); bool taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs);
bool taosValidateEncodec(char *encodec); bool taosValidateEncodec(const char *encodec);
bool taosGetVersionNumber(char *versionStr, int *versionNubmer); bool taosGetVersionNumber(char *versionStr, int *versionNubmer);
@ -187,20 +187,41 @@ static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, unsigned int inLen, cha
memcpy(target, context.digest, TSDB_KEY_LEN); memcpy(target, context.digest, TSDB_KEY_LEN);
} }
int taosCheckVersion(char *input_client_version, char *input_server_version, int compared_segments);
char *taosIpStr(uint32_t ipInt); char *taosIpStr(uint32_t ipInt);
#ifdef _TAOS_MEM_TEST_ uint32_t ip2uint(const char *const ip_addr);
// Use during test to simulate the success and failure scenarios of memory allocation
extern void* taos_malloc(unsigned int size, char* _func);
extern void* taos_calloc(unsigned int num, unsigned int size, char* _func);
extern void* taos_realloc(void* ptr, unsigned int size, char* _func);
extern void taos_free(void* ptr);
#define malloc(size) taos_malloc(size, __FUNCTION__)
#define calloc(num, size) taos_calloc(num, size, __FUNCTION__)
#define realloc(ptr, size) taos_realloc(ptr, size, __FUNCTION__)
#define free(ptr) taos_free(ptr)
#endif
#define TAOS_ALLOC_MODE_DEFAULT 0
#define TAOS_ALLOC_MODE_RANDOM_FAIL 1
#define TAOS_ALLOC_MODE_DETECT_LEAK 2
void taosSetAllocMode(int mode, const char* path, bool autoDump);
void taosDumpMemoryLeak();
#ifdef TAOS_MEM_CHECK
void * taos_malloc(size_t size, const char *file, uint32_t line);
void * taos_calloc(size_t num, size_t size, const char *file, uint32_t line);
void * taos_realloc(void *ptr, size_t size, const char *file, uint32_t line);
void taos_free(void *ptr, const char *file, uint32_t line);
char * taos_strdup(const char *str, const char *file, uint32_t line);
char * taos_strndup(const char *str, size_t size, const char *file, uint32_t line);
ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char *file, uint32_t line);
#ifndef TAOS_MEM_CHECK_IMPL
#define malloc(size) taos_malloc(size, __FILE__, __LINE__)
#define calloc(num, size) taos_calloc(num, size, __FILE__, __LINE__)
#define realloc(ptr, size) taos_realloc(ptr, size, __FILE__, __LINE__)
#define free(ptr) taos_free(ptr, __FILE__, __LINE__)
#define strdup(str) taos_strdup(str, __FILE__, __LINE__)
#define strndup(str, size) taos_strndup(str, size, __FILE__, __LINE__)
#define getline(lineptr, n, stream) taos_getline(lineptr, n, stream, __FILE__, __LINE__)
#endif // TAOS_MEM_CHECK_IMPL
#endif // TAOS_MEM_CHECK
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc)
INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(inc)
IF (TD_LINUX_64) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
AUX_SOURCE_DIRECTORY(./src SRC) AUX_SOURCE_DIRECTORY(./src SRC)
LIST(REMOVE_ITEM SRC ./src/shellWindows.c) LIST(REMOVE_ITEM SRC ./src/shellWindows.c)
ADD_EXECUTABLE(shell ${SRC}) ADD_EXECUTABLE(shell ${SRC})

View File

@ -58,6 +58,8 @@ struct arguments {
bool is_raw_time; bool is_raw_time;
bool is_use_passwd; bool is_use_passwd;
char file[TSDB_FILENAME_LEN]; char file[TSDB_FILENAME_LEN];
char dir[TSDB_FILENAME_LEN];
int threadNum;
char* commands; char* commands;
int abort; int abort;
}; };
@ -74,12 +76,14 @@ void shellRunCommandOnServer(TAOS* con, char command[]);
void read_history(); void read_history();
void write_history(); void write_history();
void source_file(TAOS* con, char* fptr); void source_file(TAOS* con, char* fptr);
void source_dir(TAOS* con, struct arguments* args);
void get_history_path(char* history); void get_history_path(char* history);
void cleanup_handler(void* arg); void cleanup_handler(void* arg);
void exitShell(); void exitShell();
int shellDumpResult(TAOS* con, char* fname, int* error_no, bool printMode); int shellDumpResult(TAOS* con, char* fname, int* error_no, bool printMode);
void shellPrintNChar(char* str, int width, bool printMode); void shellPrintNChar(char* str, int width, bool printMode);
void shellGetGrantInfo(void *con); void shellGetGrantInfo(void *con);
int isCommentLine(char *line);
#define max(a, b) ((int)(a) < (int)(b) ? (int)(b) : (int)(a)) #define max(a, b) ((int)(a) < (int)(b) ? (int)(b) : (int)(a))
/**************** Global variable declarations ****************/ /**************** Global variable declarations ****************/

View File

@ -13,20 +13,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define __USE_XOPEN #define __USE_XOPEN
#include <wchar.h>
#include "os.h" #include "os.h"
#include "shell.h" #include "shell.h"
#include "shellCommand.h" #include "shellCommand.h"
extern int wcwidth(wchar_t c);
extern int wcswidth(const wchar_t *s, size_t n);
typedef struct { typedef struct {
char widthInString; char widthInString;
char widthOnScreen; char widthOnScreen;

View File

@ -16,21 +16,13 @@
#define _XOPEN_SOURCE #define _XOPEN_SOURCE
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include <assert.h> #include <inttypes.h>
#include <pthread.h>
#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "os.h" #include "os.h"
#include "shell.h" #include "shell.h"
#include "shellCommand.h" #include "shellCommand.h"
#include "ttime.h" #include "ttime.h"
#include "tutil.h" #include "tutil.h"
#include <regex.h>
/**************** Global variables ****************/ /**************** Global variables ****************/
#ifdef WINDOWS #ifdef WINDOWS
@ -38,9 +30,19 @@
#elif defined(DARWIN) #elif defined(DARWIN)
char CLIENT_VERSION[] = "Welcome to the TDengine shell from mac, client version:%s "; char CLIENT_VERSION[] = "Welcome to the TDengine shell from mac, client version:%s ";
#else #else
char CLIENT_VERSION[] = "Welcome to the TDengine shell from linux, client version:%s "; #ifdef CLUSTER
char CLIENT_VERSION[] = "Welcome to the TDengine shell from linux, enterprise client version:%s ";
#else
char CLIENT_VERSION[] = "Welcome to the TDengine shell from linux, community client version:%s ";
#endif
#endif #endif
char SERVER_VERSION[] = "server version:%s\nCopyright (c) 2017 by TAOS Data, Inc. All rights reserved.\n\n";
#ifdef CLUSTER
char SERVER_VERSION[] = "enterprise server version:%s\nCopyright (c) 2017 by TAOS Data, Inc. All rights reserved.\n\n";
#else
char SERVER_VERSION[] = "community server version:%s\nCopyright (c) 2017 by TAOS Data, Inc. All rights reserved.\n\n";
#endif
char PROMPT_HEADER[] = "taos> "; char PROMPT_HEADER[] = "taos> ";
char CONTINUE_PROMPT[] = " -> "; char CONTINUE_PROMPT[] = " -> ";
int prompt_size = 6; int prompt_size = 6;
@ -109,6 +111,14 @@ TAOS *shellInit(struct arguments *args) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
#ifdef LINUX
if (args->dir[0] != 0) {
source_dir(con, args);
taos_close(con);
exit(EXIT_SUCCESS);
}
#endif
printf(SERVER_VERSION, taos_get_server_info(con)); printf(SERVER_VERSION, taos_get_server_info(con));
return con; return con;
@ -150,6 +160,8 @@ void shellReplaceCtrlChar(char *str) {
} }
break; break;
default: default:
*pstr = *str;
pstr++;
break; break;
} }
ctrlOn = false; ctrlOn = false;
@ -254,7 +266,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) {
return; return;
} }
if (regex_match(command, "^\\s*use\\s+[a-zA-Z0-9]+\\s*;\\s*$", REG_EXTENDED | REG_ICASE)) { if (regex_match(command, "^\\s*use\\s+[a-zA-Z0-9_]+\\s*;\\s*$", REG_EXTENDED | REG_ICASE)) {
fprintf(stdout, "Database changed.\n\n"); fprintf(stdout, "Database changed.\n\n");
fflush(stdout); fflush(stdout);
return; return;
@ -443,9 +455,9 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
printf("%*d|", l[i], *((int *)row[i])); printf("%*d|", l[i], *((int *)row[i]));
break; break;
case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_BIGINT:
printf("%*lld|", l[i], *((int64_t *)row[i])); printf("%*" PRId64 "|", l[i], *((int64_t *)row[i]));
break; break;
case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_FLOAT: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
float fv = 0; float fv = 0;
//memcpy(&fv, row[i], sizeof(float)); //memcpy(&fv, row[i], sizeof(float));
@ -454,8 +466,9 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
#else #else
printf("%*.5f|", l[i], *((float *)row[i])); printf("%*.5f|", l[i], *((float *)row[i]));
#endif #endif
}
break; break;
case TSDB_DATA_TYPE_DOUBLE: case TSDB_DATA_TYPE_DOUBLE: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
double dv = 0; double dv = 0;
//memcpy(&dv, row[i], sizeof(double)); //memcpy(&dv, row[i], sizeof(double));
@ -464,6 +477,7 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
#else #else
printf("%*.9f|", l[i], *((double *)row[i])); printf("%*.9f|", l[i], *((double *)row[i]));
#endif #endif
}
break; break;
case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR:
@ -476,7 +490,7 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
break; break;
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP:
if (args.is_raw_time) { if (args.is_raw_time) {
printf(" %lld|", *(int64_t *)row[i]); printf(" %" PRId64 "|", *(int64_t *)row[i]);
} else { } else {
if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) {
tt = (time_t)((*(int64_t *)row[i]) / 1000000); tt = (time_t)((*(int64_t *)row[i]) / 1000000);
@ -526,9 +540,9 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
printf("%d\n", *((int *)row[i])); printf("%d\n", *((int *)row[i]));
break; break;
case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_BIGINT:
printf("%lld\n", *((int64_t *)row[i])); printf("%" PRId64 "\n", *((int64_t *)row[i]));
break; break;
case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_FLOAT: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
float fv = 0; float fv = 0;
//memcpy(&fv, row[i], sizeof(float)); //memcpy(&fv, row[i], sizeof(float));
@ -537,8 +551,9 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
#else #else
printf("%.5f\n", *((float *)row[i])); printf("%.5f\n", *((float *)row[i]));
#endif #endif
}
break; break;
case TSDB_DATA_TYPE_DOUBLE: case TSDB_DATA_TYPE_DOUBLE: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
double dv = 0; double dv = 0;
//memcpy(&dv, row[i], sizeof(double)); //memcpy(&dv, row[i], sizeof(double));
@ -547,7 +562,8 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
#else #else
printf("%.9f\n", *((double *)row[i])); printf("%.9f\n", *((double *)row[i]));
#endif #endif
break; }
break;
case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR:
memset(t_str, 0, TSDB_MAX_BYTES_PER_ROW); memset(t_str, 0, TSDB_MAX_BYTES_PER_ROW);
@ -557,7 +573,7 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
break; break;
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP:
if (args.is_raw_time) { if (args.is_raw_time) {
printf("%lld\n", *(int64_t *)row[i]); printf("%" PRId64 "\n", *(int64_t *)row[i]);
} else { } else {
if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) {
tt = (time_t)((*(int64_t *)row[i]) / 1000000); tt = (time_t)((*(int64_t *)row[i]) / 1000000);
@ -612,9 +628,9 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
fprintf(fp, "%d", *((int *)row[i])); fprintf(fp, "%d", *((int *)row[i]));
break; break;
case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_BIGINT:
fprintf(fp, "%lld", *((int64_t *)row[i])); fprintf(fp, "%" PRId64, *((int64_t *)row[i]));
break; break;
case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_FLOAT: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
float fv = 0; float fv = 0;
//memcpy(&fv, row[i], sizeof(float)); //memcpy(&fv, row[i], sizeof(float));
@ -623,8 +639,9 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
#else #else
fprintf(fp, "%.5f", *((float *)row[i])); fprintf(fp, "%.5f", *((float *)row[i]));
#endif #endif
}
break; break;
case TSDB_DATA_TYPE_DOUBLE: case TSDB_DATA_TYPE_DOUBLE: {
#ifdef _TD_ARM_32_ #ifdef _TD_ARM_32_
double dv = 0; double dv = 0;
//memcpy(&dv, row[i], sizeof(double)); //memcpy(&dv, row[i], sizeof(double));
@ -633,6 +650,7 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
#else #else
fprintf(fp, "%.9f", *((double *)row[i])); fprintf(fp, "%.9f", *((double *)row[i]));
#endif #endif
}
break; break;
case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_NCHAR:
@ -642,7 +660,7 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) {
break; break;
case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_TIMESTAMP:
if (args.is_raw_time) { if (args.is_raw_time) {
fprintf(fp, "%lld", *(int64_t *)row[i]); fprintf(fp, "%" PRId64, *(int64_t *)row[i]);
} else { } else {
if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) {
tt = (time_t)((*(int64_t *)row[i]) / 1000000); tt = (time_t)((*(int64_t *)row[i]) / 1000000);
@ -755,7 +773,7 @@ void taos_error(TAOS *con) {
taos_free_result(pRes); taos_free_result(pRes);
} }
static int isCommentLine(char *line) { int isCommentLine(char *line) {
if (line == NULL) return 1; if (line == NULL) return 1;
return regex_match(line, "^\\s*#.*", REG_EXTENDED); return regex_match(line, "^\\s*#.*", REG_EXTENDED);
@ -771,6 +789,7 @@ void source_file(TAOS *con, char *fptr) {
if (wordexp(fptr, &full_path, 0) != 0) { if (wordexp(fptr, &full_path, 0) != 0) {
fprintf(stderr, "ERROR: illegal file name\n"); fprintf(stderr, "ERROR: illegal file name\n");
free(cmd);
return; return;
} }
@ -779,6 +798,7 @@ void source_file(TAOS *con, char *fptr) {
if (access(fname, R_OK) == -1) { if (access(fname, R_OK) == -1) {
fprintf(stderr, "ERROR: file %s is not readable\n", fptr); fprintf(stderr, "ERROR: file %s is not readable\n", fptr);
wordfree(&full_path); wordfree(&full_path);
free(cmd);
return; return;
} }
@ -786,6 +806,7 @@ void source_file(TAOS *con, char *fptr) {
if (f == NULL) { if (f == NULL) {
fprintf(stderr, "ERROR: failed to open file %s\n", fname); fprintf(stderr, "ERROR: failed to open file %s\n", fname);
wordfree(&full_path); wordfree(&full_path);
free(cmd);
return; return;
} }
@ -840,7 +861,7 @@ void shellGetGrantInfo(void *con) {
TAOS_FIELD *fields = taos_fetch_fields(result); TAOS_FIELD *fields = taos_fetch_fields(result);
TAOS_ROW row = taos_fetch_row(result); TAOS_ROW row = taos_fetch_row(result);
if (row == NULL) { if (row == NULL) {
fprintf(stderr, "\nGrant information is empty.\n"); fprintf(stderr, "\nFailed to get grant information from server. Abort.\n");
exit(0); exit(0);
} }

View File

@ -0,0 +1,266 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _XOPEN_SOURCE
#define _DEFAULT_SOURCE
#include "os.h"
#include "shell.h"
#include "shellCommand.h"
#include "ttime.h"
#include "tutil.h"
static char **shellSQLFiles = NULL;
static int32_t shellSQLFileNum = 0;
static char shellTablesSQLFile[TSDB_FILENAME_LEN] = {0};
typedef struct {
pthread_t threadID;
int threadIndex;
int totalThreads;
void *taos;
} ShellThreadObj;
static int shellGetFilesNum(const char *directoryName, const char *prefix)
{
char cmd[1024] = { 0 };
sprintf(cmd, "ls %s/*.%s | wc -l ", directoryName, prefix);
FILE *fp = popen(cmd, "r");
if (fp == NULL) {
fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno));
exit(0);
}
int fileNum = 0;
if (fscanf(fp, "%d", &fileNum) != 1) {
fprintf(stderr, "ERROR: failed to execute:%s, parse result error\n", cmd);
exit(0);
}
if (fileNum <= 0) {
fprintf(stderr, "ERROR: directory:%s is empry\n", directoryName);
exit(0);
}
pclose(fp);
return fileNum;
}
static void shellParseDirectory(const char *directoryName, const char *prefix, char **fileArray, int totalFiles)
{
char cmd[1024] = { 0 };
sprintf(cmd, "ls %s/*.%s | sort", directoryName, prefix);
FILE *fp = popen(cmd, "r");
if (fp == NULL) {
fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno));
exit(0);
}
int fileNum = 0;
while (fscanf(fp, "%s", fileArray[fileNum++])) {
if (strcmp(fileArray[fileNum-1], shellTablesSQLFile) == 0) {
fileNum--;
}
if (fileNum >= totalFiles) {
break;
}
}
if (fileNum != totalFiles) {
fprintf(stderr, "ERROR: directory:%s changed while read\n", directoryName);
exit(0);
}
pclose(fp);
}
static void shellCheckTablesSQLFile(const char *directoryName)
{
char cmd[1024] = { 0 };
sprintf(cmd, "ls %s/tables.sql", directoryName);
FILE *fp = popen(cmd, "r");
if (fp == NULL) {
fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno));
exit(0);
}
while (fscanf(fp, "%s", shellTablesSQLFile)) {
break;
}
pclose(fp);
}
static void shellMallocSQLFiles()
{
shellSQLFiles = (char**)calloc(shellSQLFileNum, sizeof(char*));
for (int i = 0; i < shellSQLFileNum; i++) {
shellSQLFiles[i] = calloc(1, TSDB_FILENAME_LEN);
}
}
static void shellGetDirectoryFileList(char *inputDir)
{
struct stat fileStat;
if (stat(inputDir, &fileStat) < 0) {
fprintf(stderr, "ERROR: %s not exist\n", inputDir);
exit(0);
}
if (fileStat.st_mode & S_IFDIR) {
shellCheckTablesSQLFile(inputDir);
shellSQLFileNum = shellGetFilesNum(inputDir, "sql");
int totalSQLFileNum = shellSQLFileNum;
if (shellTablesSQLFile[0] != 0) {
shellSQLFileNum--;
}
shellMallocSQLFiles();
shellParseDirectory(inputDir, "sql", shellSQLFiles, shellSQLFileNum);
fprintf(stdout, "\nstart to dispose %d files in %s\n", totalSQLFileNum, inputDir);
}
else {
fprintf(stderr, "ERROR: %s is not a directory\n", inputDir);
exit(0);
}
}
static void shellSourceFile(TAOS *con, char *fptr) {
wordexp_t full_path;
int read_len = 0;
char * cmd = malloc(MAX_COMMAND_SIZE);
size_t cmd_len = 0;
char * line = NULL;
size_t line_len = 0;
if (wordexp(fptr, &full_path, 0) != 0) {
fprintf(stderr, "ERROR: illegal file name\n");
return;
}
char *fname = full_path.we_wordv[0];
if (access(fname, R_OK) == -1) {
fprintf(stderr, "ERROR: file %s is not readable\n", fptr);
wordfree(&full_path);
return;
}
FILE *f = fopen(fname, "r");
if (f == NULL) {
fprintf(stderr, "ERROR: failed to open file %s\n", fname);
wordfree(&full_path);
return;
}
fprintf(stdout, "begin import file:%s\n", fname);
int lineNo = 0;
while ((read_len = getline(&line, &line_len, f)) != -1) {
++lineNo;
if (read_len >= MAX_COMMAND_SIZE) continue;
line[--read_len] = '\0';
if (read_len == 0 || isCommentLine(line)) { // line starts with #
continue;
}
if (line[read_len - 1] == '\\') {
line[read_len - 1] = ' ';
memcpy(cmd + cmd_len, line, read_len);
cmd_len += read_len;
continue;
}
memcpy(cmd + cmd_len, line, read_len);
if (taos_query(con, cmd)) {
fprintf(stderr, "DB error: %s: %s (%d)\n", taos_errstr(con), fname, lineNo);
/* free local resouce: allocated memory/metric-meta refcnt */
TAOS_RES *pRes = taos_use_result(con);
taos_free_result(pRes);
}
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd_len = 0;
}
free(cmd);
if (line) free(line);
wordfree(&full_path);
fclose(f);
}
void* shellImportThreadFp(void *arg)
{
ShellThreadObj *pThread = (ShellThreadObj*)arg;
for (int f = 0; f < shellSQLFileNum; ++f) {
if (f % pThread->totalThreads == pThread->threadIndex) {
char *SQLFileName = shellSQLFiles[f];
shellSourceFile(pThread->taos, SQLFileName);
}
}
return NULL;
}
static void shellRunImportThreads(struct arguments* args)
{
pthread_attr_t thattr;
ShellThreadObj *threadObj = (ShellThreadObj *)calloc(args->threadNum, sizeof(ShellThreadObj));
for (int t = 0; t < args->threadNum; ++t) {
ShellThreadObj *pThread = threadObj + t;
pThread->threadIndex = t;
pThread->totalThreads = args->threadNum;
pThread->taos = taos_connect(args->host, args->user, args->password, args->database, tsMgmtShellPort);
if (pThread->taos == NULL) {
fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taos));
exit(0);
}
pthread_attr_init(&thattr);
pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
if (pthread_create(&(pThread->threadID), &thattr, shellImportThreadFp, (void*)pThread) != 0) {
fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex);
exit(0);
}
}
for (int t = 0; t < args->threadNum; ++t) {
pthread_join(threadObj[t].threadID, NULL);
}
for (int t = 0; t < args->threadNum; ++t) {
taos_close(threadObj[t].taos);
}
free(threadObj);
}
void source_dir(TAOS* con, struct arguments* args) {
shellGetDirectoryFileList(args->dir);
int64_t start = taosGetTimestampMs();
if (shellTablesSQLFile[0] != 0) {
shellSourceFile(con, shellTablesSQLFile);
int64_t end = taosGetTimestampMs();
fprintf(stdout, "import %s finished, time spent %.2f seconds\n", shellTablesSQLFile, (end - start) / 1000.0);
}
shellRunImportThreads(args);
int64_t end = taosGetTimestampMs();
fprintf(stdout, "import %s finished, time spent %.2f seconds\n", args->dir, (end - start) / 1000.0);
}

View File

@ -13,27 +13,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <argp.h>
#include <assert.h>
#include <assert.h>
#include <error.h>
#include <pwd.h>
#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <wordexp.h>
#define __USE_XOPEN #define __USE_XOPEN
#include <wchar.h> #include "os.h"
#include "shell.h" #include "shell.h"
#include "shellCommand.h" #include "shellCommand.h"
@ -44,6 +26,7 @@
int indicator = 1; int indicator = 1;
struct termios oldtio; struct termios oldtio;
extern int wcwidth(wchar_t c);
void insertChar(Command *cmd, char *c, int size); void insertChar(Command *cmd, char *c, int size);
const char *argp_program_version = version; const char *argp_program_version = version;
const char *argp_program_bug_address = "<support@taosdata.com>"; const char *argp_program_bug_address = "<support@taosdata.com>";
@ -58,6 +41,8 @@ static struct argp_option options[] = {
{"commands", 's', "COMMANDS", 0, "Commands to run without enter the shell."}, {"commands", 's', "COMMANDS", 0, "Commands to run without enter the shell."},
{"raw-time", 'r', 0, 0, "Output time as uint64_t."}, {"raw-time", 'r', 0, 0, "Output time as uint64_t."},
{"file", 'f', "FILE", 0, "Script to run without enter the shell."}, {"file", 'f', "FILE", 0, "Script to run without enter the shell."},
{"directory", 'D', "DIRECTORY", 0, "Use multi-thread to import all SQL files in the directory separately."},
{"thread", 'T', "THREADNUM", 0, "Number of threads when using multi-thread to import data."},
{"database", 'd', "DATABASE", 0, "Database to use when connecting to the server."}, {"database", 'd', "DATABASE", 0, "Database to use when connecting to the server."},
{"timezone", 't', "TIMEZONE", 0, "Time zone of the shell, default is local."}, {"timezone", 't', "TIMEZONE", 0, "Time zone of the shell, default is local."},
{0}}; {0}};
@ -107,6 +92,17 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
strcpy(arguments->file, full_path.we_wordv[0]); strcpy(arguments->file, full_path.we_wordv[0]);
wordfree(&full_path); wordfree(&full_path);
break; break;
case 'D':
if (wordexp(arg, &full_path, 0) != 0) {
fprintf(stderr, "Invalid path %s\n", arg);
return -1;
}
strcpy(arguments->dir, full_path.we_wordv[0]);
wordfree(&full_path);
break;
case 'T':
arguments->threadNum = atoi(arg);
break;
case 'd': case 'd':
arguments->database = arg; arguments->database = arg;
break; break;
@ -123,6 +119,15 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
static struct argp argp = {options, parse_opt, args_doc, doc}; static struct argp argp = {options, parse_opt, args_doc, doc};
void shellParseArgument(int argc, char *argv[], struct arguments *arguments) { void shellParseArgument(int argc, char *argv[], struct arguments *arguments) {
char verType[32] = {0};
#ifdef CLUSTER
sprintf(verType, "enterprise version: %s\n", version);
#else
sprintf(verType, "community version: %s\n", version);
#endif
argp_program_version = verType;
argp_parse(&argp, argc, argv, 0, 0, arguments); argp_parse(&argp, argc, argv, 0, 0, arguments);
if (arguments->abort) { if (arguments->abort) {
error(10, 0, "ABORTED"); error(10, 0, "ABORTED");
@ -286,7 +291,10 @@ void *shellLoopQuery(void *arg) {
pthread_cleanup_push(cleanup_handler, NULL); pthread_cleanup_push(cleanup_handler, NULL);
char *command = malloc(MAX_COMMAND_SIZE); char *command = malloc(MAX_COMMAND_SIZE);
if (command == NULL){
tscError("failed to malloc command");
return NULL;
}
while (1) { while (1) {
// Read command from shell. // Read command from shell.
@ -295,10 +303,8 @@ void *shellLoopQuery(void *arg) {
shellReadCommand(con, command); shellReadCommand(con, command);
reset_terminal_mode(); reset_terminal_mode();
if (command != NULL) { // Run the command
// Run the command shellRunCommand(con, command);
shellRunCommand(con, command);
}
} }
pthread_cleanup_pop(1); pthread_cleanup_pop(1);

View File

@ -13,13 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <locale.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "os.h" #include "os.h"
#include "shell.h" #include "shell.h"
#include "tsclient.h" #include "tsclient.h"
@ -69,7 +62,19 @@ int checkVersion() {
} }
// Global configurations // Global configurations
struct arguments args = {NULL, NULL, NULL, NULL, NULL, false, false, "\0", NULL}; struct arguments args = {
.host = NULL,
.password = NULL,
.user = NULL,
.database = NULL,
.timezone = NULL,
.is_raw_time = false,
.is_use_passwd = false,
.file = "\0",
.dir = "\0",
.threadNum = 5,
.commands = NULL
};
/* /*
* Main function. * Main function.

View File

@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc)
INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(inc)
IF (TD_LINUX_64) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
AUX_SOURCE_DIRECTORY(. SRC) AUX_SOURCE_DIRECTORY(. SRC)
ADD_EXECUTABLE(taosdemo ${SRC}) ADD_EXECUTABLE(taosdemo ${SRC})
TARGET_LINK_LIBRARIES(taosdemo taos_static) TARGET_LINK_LIBRARIES(taosdemo taos_static)

View File

@ -30,7 +30,8 @@
#include <wordexp.h> #include <wordexp.h>
#include "taos.h" #include "taos.h"
#pragma GCC diagnostic ignored "-Wmissing-braces"
extern char configDir[];
#define BUFFER_SIZE 65536 #define BUFFER_SIZE 65536
#define MAX_DB_NAME_SIZE 64 #define MAX_DB_NAME_SIZE 64
@ -64,7 +65,7 @@ static struct argp_option options[] = {
/* Used by main to communicate with parse_opt. */ /* Used by main to communicate with parse_opt. */
struct arguments { struct arguments {
char *host; char *host;
int port; uint16_t port;
char *user; char *user;
char *password; char *password;
char *database; char *database;
@ -176,7 +177,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
fprintf(stderr, "Invalid path %s\n", arg); fprintf(stderr, "Invalid path %s\n", arg);
return -1; return -1;
} }
strcpy(configDir, full_path.we_wordv[0]); taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
wordfree(&full_path); wordfree(&full_path);
break; break;
case OPT_ABORT: case OPT_ABORT:
@ -264,30 +265,35 @@ double getCurrentTime();
void callBack(void *param, TAOS_RES *res, int code); void callBack(void *param, TAOS_RES *res, int code);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
struct arguments arguments = {NULL, struct arguments arguments = {NULL, // host
0, 0, // port
"root", "root", // user
"taosdata", "taosdata", // password
"test", "test", // database
"t", "t", // tb_prefix
false, false, // use_metric
false, false, // insert_only
"./output.txt", "./output.txt", // output_file
0, 0, // mode
"int", {
"int", // datatype
"", "",
"", "",
"", "",
"", "",
"", "",
"", "",
"", ""
8, },
1, 8, // len_of_binary
1, 1, // num_of_CPR
1, 1, // num_of_connections
1, 1, // num_of_RPR
50000}; 1, // num_of_tables
50000, // num_of_DPT
0, // abort
NULL // arg_list
};
/* Parse our arguments; every option seen by parse_opt will be /* Parse our arguments; every option seen by parse_opt will be
reflected in arguments. */ reflected in arguments. */
@ -307,7 +313,7 @@ int main(int argc, char *argv[]) {
enum MODE query_mode = arguments.mode; enum MODE query_mode = arguments.mode;
char *ip_addr = arguments.host; char *ip_addr = arguments.host;
int port = arguments.port; uint16_t port = arguments.port;
char *user = arguments.user; char *user = arguments.user;
char *pass = arguments.password; char *pass = arguments.password;
char *db_name = arguments.database; char *db_name = arguments.database;
@ -340,7 +346,7 @@ int main(int argc, char *argv[]) {
struct tm tm = *localtime(&tTime); struct tm tm = *localtime(&tTime);
fprintf(fp, "###################################################################\n"); fprintf(fp, "###################################################################\n");
fprintf(fp, "# Server IP: %s:%d\n", ip_addr == NULL ? "localhost" : ip_addr, port); fprintf(fp, "# Server IP: %s:%hu\n", ip_addr == NULL ? "localhost" : ip_addr, port);
fprintf(fp, "# User: %s\n", user); fprintf(fp, "# User: %s\n", user);
fprintf(fp, "# Password: %s\n", pass); fprintf(fp, "# Password: %s\n", pass);
fprintf(fp, "# Use metric: %s\n", use_metric ? "true" : "false"); fprintf(fp, "# Use metric: %s\n", use_metric ? "true" : "false");

View File

@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc)
INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(inc)
IF (TD_LINUX_64) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
AUX_SOURCE_DIRECTORY(. SRC) AUX_SOURCE_DIRECTORY(. SRC)
ADD_EXECUTABLE(taosdump ${SRC}) ADD_EXECUTABLE(taosdump ${SRC})
TARGET_LINK_LIBRARIES(taosdump taos_static) TARGET_LINK_LIBRARIES(taosdump taos_static)

View File

@ -172,7 +172,7 @@ struct arguments {
char *host; char *host;
char *user; char *user;
char *password; char *password;
int port; uint16_t port;
// output file // output file
char output[TSDB_FILENAME_LEN + 1]; char output[TSDB_FILENAME_LEN + 1];
char input[TSDB_FILENAME_LEN + 1]; char input[TSDB_FILENAME_LEN + 1];

View File

@ -1,7 +1,7 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(TDengine) PROJECT(TDengine)
IF (TD_LINUX_64) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc)

Some files were not shown because too many files have changed in this diff Show More