diff --git a/.gitignore b/.gitignore index 39c7a7ee5df39742619cd0e25cbbff1d9ac1a02f..3eda69f60de91638ef0190283d092e9b6e0229a2 100644 --- a/.gitignore +++ b/.gitignore @@ -87,7 +87,7 @@ tests/comparisonTest/opentsdb/opentsdbtest/.settings/ tests/examples/JDBC/JDBCDemo/.classpath tests/examples/JDBC/JDBCDemo/.project tests/examples/JDBC/JDBCDemo/.settings/ -source/libs/parser/inc/new_sql.* +source/libs/parser/inc/sql.* # Emacs # -*- mode: gitignore; -*- diff --git a/.gitmodules b/.gitmodules index e9af594edc7523e3226bd9a5a24203bae0644eda..bc38453f19280d94c5c950e650dc0a96abffde62 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,9 @@ [submodule "deps/TSZ"] path = deps/TSZ url = https://github.com/taosdata/TSZ.git +[submodule "examples/rust"] + path = examples/rust + url = https://github.com/songtianyi/tdengine-rust-bindings.git +[submodule "tools/taos-tools"] + path = tools/taos-tools + url = https://github.com/taosdata/taos-tools diff --git a/CMakeLists.txt b/CMakeLists.txt index df3aab5cb30c1836881db1aa1403b4573b4eac6c..2e37a14143c3c7e2521692ac0e95d6753f372109 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,12 @@ project( set(CMAKE_SUPPORT_DIR "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_CONTRIB_DIR "${CMAKE_SOURCE_DIR}/contrib") + +include(${CMAKE_SUPPORT_DIR}/cmake.platform) +include(${CMAKE_SUPPORT_DIR}/cmake.define) include(${CMAKE_SUPPORT_DIR}/cmake.options) include(${CMAKE_SUPPORT_DIR}/cmake.version) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -fPIC -gdwarf-2 -msse4.2 -mfma -g3") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -fPIC -gdwarf-2 -msse4.2 -mfma -g3") - # contrib add_subdirectory(contrib) @@ -26,6 +26,7 @@ if(${BUILD_TEST}) include(CTest) enable_testing() endif(${BUILD_TEST}) + add_subdirectory(source) add_subdirectory(tools) add_subdirectory(tests) diff --git a/cmake/cmake.define b/cmake/cmake.define new file mode 100644 index 0000000000000000000000000000000000000000..b97c10a4b7ddc2ce1c99283538c76b49bf01e2b3 --- /dev/null +++ b/cmake/cmake.define @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.16) + +IF ("${BUILD_TOOLS}" STREQUAL "") + IF (TD_LINUX) + IF (TD_ARM_32) + SET(BUILD_TOOLS "false") + ELSEIF (TD_ARM_64) + SET(BUILD_TOOLS "false") + ELSE () + SET(BUILD_TOOLS "false") + ENDIF () + ELSEIF (TD_DARWIN) + SET(BUILD_TOOLS "false") + ELSE () + SET(BUILD_TOOLS "false") + ENDIF () +ENDIF () + +IF ("${BUILD_TOOLS}" MATCHES "false") + MESSAGE("${Yellow} Will _not_ build taos_tools! ${ColourReset}") + SET(TD_TAOS_TOOLS FALSE) +ELSE () + MESSAGE("") + MESSAGE("${Green} Will build taos_tools! ${ColourReset}") + MESSAGE("") + SET(TD_TAOS_TOOLS TRUE) +ENDIF () + +IF (TD_WINDOWS) + MESSAGE("${Yellow} set compiler flag for Windows! ${ColourReset}") + SET(CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE) + SET(COMMON_FLAGS "/nologo /WX /wd4018 /wd4999 /Oi /Oy- /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Gd /errorReport:prompt /analyze-") + + IF (MSVC AND (MSVC_VERSION GREATER_EQUAL 1900)) + SET(COMMON_FLAGS "${COMMON_FLAGS} /Wv:18") + ENDIF () + +ELSE () + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -fPIC -gdwarf-2 -msse4.2 -mfma -g3") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -fPIC -gdwarf-2 -msse4.2 -mfma -g3") + +ENDIF () diff --git a/cmake/cmake.options b/cmake/cmake.options index e19c10f6b2658e506f3ffb16e604686f61de2696..1a1a5b5d785007692fcc5982558024f4bf05b893 100644 --- a/cmake/cmake.options +++ b/cmake/cmake.options @@ -1,12 +1,35 @@ # ========================================================= # Deps options # ========================================================= + +IF(${TD_WINDOWS}) + + MESSAGE("build pthread Win32") + option( + BUILD_PTHREAD + "If build pthread on Windows" + ON + ) + + MESSAGE("build gnu regex for Windows") + option( + BUILD_GNUREGEX + "If build gnu regex on Windows" + ON + ) + +ENDIF () + +IF(${TD_LINUX} MATCHES TRUE) + option( BUILD_TEST "If build unit tests using googletest" ON ) +ENDIF () + option( BUILD_WITH_LEVELDB "If build with leveldb" @@ -25,11 +48,16 @@ option( OFF ) -option( - BUILD_WITH_BDB - "If build with BerkleyDB" - ON -) +IF(${TD_WINDOWS}) + MESSAGE("Not build BDB on Windows") +ELSE () + option( + BUILD_WITH_BDB + "If build with BerkleyDB" + ON + ) + +ENDIF () option( BUILD_WITH_LUCENE @@ -68,12 +96,16 @@ option( OFF ) +IF(${TD_LINUX} MATCHES TRUE) + option( BUILD_DEPENDENCY_TESTS "If build dependency tests" ON ) +ENDIF () + option( BUILD_DOCS "If use doxygen build documents" diff --git a/cmake/cmake.platform b/cmake/cmake.platform new file mode 100644 index 0000000000000000000000000000000000000000..7ef259ba541582baf012e1de4dfbbf3c4f91d5ab --- /dev/null +++ b/cmake/cmake.platform @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.16) + +MESSAGE("Current system is ${CMAKE_SYSTEM_NAME}") + +# init +SET(TD_LINUX FALSE) +SET(TD_WINDOWS FALSE) +SET(TD_DARWIN FALSE) + +IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + + SET(TD_LINUX TRUE) + SET(OSTYPE "Linux") + ADD_DEFINITIONS("-DLINUX") + + IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) + SET(TD_LINUX_64 TRUE) + ELSE () + SET(TD_LINUX_32 TRUE) + ENDIF () + +ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + SET(TD_DARWIN TRUE) + SET(OSTYPE "macOS") + ADD_DEFINITIONS("-DDARWIN") + IF (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64") + MESSAGE("Current system arch is arm64") + SET(TD_DARWIN_64 TRUE) + ADD_DEFINITIONS("-D_TD_DARWIN_64") + ENDIF () + + ADD_DEFINITIONS("-DHAVE_UNISTD_H") + +ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + + SET(TD_WINDOWS TRUE) + SET(OSTYPE "Windows") + ADD_DEFINITIONS("-DWINDOWS") + + IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) + SET(TD_WINDOWS_64 TRUE) + ADD_DEFINITIONS("-D_TD_WINDOWS_64") + ELSE () + SET(TD_WINDOWS_32 TRUE) + ADD_DEFINITIONS("-D_TD_WINDOWS_32") + ENDIF () +ENDIF() + +MESSAGE("C Compiler ID: ${CMAKE_C_COMPILER_ID}") +MESSAGE("CXX Compiler ID: ${CMAKE_CXX_COMPILER_ID}") diff --git a/cmake/gnuregex_CMakeLists.txt.in b/cmake/gnuregex_CMakeLists.txt.in new file mode 100644 index 0000000000000000000000000000000000000000..e0c07fe3baf00be29f8ca202596ed5baf1f2377b --- /dev/null +++ b/cmake/gnuregex_CMakeLists.txt.in @@ -0,0 +1,13 @@ + +# gnuregex +ExternalProject_Add(gnuregex + URL https://launchpad.net/gnuregex/trunk/2.9/+download/libgnurx-src-2.9.zip + DOWNLOAD_NAME libgnurx-src.zip + SOURCE_DIR "${CMAKE_CONTRIB_DIR}/gnuregex" + BINARY_DIR "" + #BUILD_IN_SOURCE TRUE + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/cmake/pthread_CMakeLists.txt.in b/cmake/pthread_CMakeLists.txt.in new file mode 100644 index 0000000000000000000000000000000000000000..ee6d0691550eb1ea9f9fe6cd7fee99a5a4ebfe20 --- /dev/null +++ b/cmake/pthread_CMakeLists.txt.in @@ -0,0 +1,13 @@ + +# pthread +ExternalProject_Add(pthread + GIT_REPOSITORY https://github.com/GerHobbelt/pthread-win32 + GIT_TAG v3.0.3.1 + SOURCE_DIR "${CMAKE_CONTRIB_DIR}/pthread-win32" + BINARY_DIR "" + #BUILD_IN_SOURCE TRUE + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 21b8b661df9809d8631cf1e7e915eb78c500671e..5e2bfc52e1cd9952a76ab2d3709161b9246419aa 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -9,6 +9,16 @@ endfunction(cat IN_FILE OUT_FILE) set(CONTRIB_TMP_FILE "${CMAKE_BINARY_DIR}/deps_tmp_CMakeLists.txt.in") configure_file("${CMAKE_SUPPORT_DIR}/deps_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) +# pthread +if(${BUILD_PTHREAD}) + cat("${CMAKE_SUPPORT_DIR}/pthread_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) +endif() + +# gnu regex +if(${BUILD_GNUREGEX}) + cat("${CMAKE_SUPPORT_DIR}/gnuregex_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) +endif() + # googletest if(${BUILD_TEST}) cat("${CMAKE_SUPPORT_DIR}/gtest_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) @@ -193,7 +203,10 @@ endif(${BUILD_WITH_TRAFT}) # LIBUV if(${BUILD_WITH_UV}) - add_compile_options(-Wno-sign-compare) + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") + MESSAGE("Windows need set no-sign-compare") + add_compile_options(-Wno-sign-compare) + endif () add_subdirectory(libuv) endif(${BUILD_WITH_UV}) @@ -224,6 +237,7 @@ if(${BUILD_WITH_SQLITE}) ) endif(${BUILD_WITH_SQLITE}) +# pthread # ================================================================================================ diff --git a/contrib/test/craft/raftMain.c b/contrib/test/craft/raftMain.c index b28adfaaca4426873d1c12c250ae1c55bc002938..12be3deb2e33aba9be9b45acd1595a749ab1b2c5 100644 --- a/contrib/test/craft/raftMain.c +++ b/contrib/test/craft/raftMain.c @@ -377,7 +377,7 @@ void printConf(SRaftServerConfig *pConf) { int main(int argc, char **argv) { - srand(time(NULL)); + taosSeedRand(time(NULL)); int32_t ret; exe_name = argv[0]; diff --git a/contrib/test/craft/simulate_vnode.c b/contrib/test/craft/simulate_vnode.c index 668fe638b719bacfb9f320b40767eac4fe6da71a..7ee9b9f8f01f14e48da956059e5b12422eba3f4f 100644 --- a/contrib/test/craft/simulate_vnode.c +++ b/contrib/test/craft/simulate_vnode.c @@ -132,7 +132,7 @@ static void proposeValue(struct raft *r) { buf.base = raft_malloc(buf.len); // mock ts value - int vid = rand() % VNODE_COUNT; + int vid = taosRand() % VNODE_COUNT; snprintf(buf.base, buf.len, "%d:value_%ld", vid, time(NULL)); printf("propose value: %s \n", (char*)buf.base); @@ -174,7 +174,7 @@ void usage() { } int main(int argc, char **argv) { - srand(time(NULL)); + taosSeedRand(time(NULL)); exe_name = argv[0]; if (argc < 2) { diff --git a/examples/c/schemaless.c b/examples/c/schemaless.c index 21f39213cd557f3784a9c1b83172b978e3982683..99aa361b0a8801ff72467ed6f644262998f3c5b4 100644 --- a/examples/c/schemaless.c +++ b/examples/c/schemaless.c @@ -19,7 +19,7 @@ void shuffle(char**lines, size_t n) size_t i; for (i = 0; i < n - 1; i++) { - size_t j = i + rand() / (RAND_MAX / (n - i) + 1); + size_t j = i + taosRand() / (RAND_MAX / (n - i) + 1); char* t = lines[j]; lines[j] = lines[i]; lines[i] = t; diff --git a/examples/rust b/examples/rust new file mode 160000 index 0000000000000000000000000000000000000000..1c8924dc668e6aa848214c2fc54e3ace3f5bf8df --- /dev/null +++ b/examples/rust @@ -0,0 +1 @@ +Subproject commit 1c8924dc668e6aa848214c2fc54e3ace3f5bf8df diff --git a/include/client/taos.h b/include/client/taos.h index 8b1517c6fffc7613b9366d2f0943520243cba5d7..66e3c491c775791d6a67129f0bd402f5aa1aa898 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -31,26 +31,27 @@ typedef void TAOS_SUB; typedef void **TAOS_ROW; // Data type definition -#define TSDB_DATA_TYPE_NULL 0 // 1 bytes -#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes -#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte -#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes -#define TSDB_DATA_TYPE_INT 4 // 4 bytes -#define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes -#define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes -#define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes -#define TSDB_DATA_TYPE_BINARY 8 // string, alias for varchar -#define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes -#define TSDB_DATA_TYPE_NCHAR 10 // unicode string -#define TSDB_DATA_TYPE_UTINYINT 11 // 1 byte -#define TSDB_DATA_TYPE_USMALLINT 12 // 2 bytes -#define TSDB_DATA_TYPE_UINT 13 // 4 bytes -#define TSDB_DATA_TYPE_UBIGINT 14 // 8 bytes -#define TSDB_DATA_TYPE_VARCHAR 15 // string -#define TSDB_DATA_TYPE_VARBINARY 16 // binary -#define TSDB_DATA_TYPE_JSON 17 // json -#define TSDB_DATA_TYPE_DECIMAL 18 // decimal -#define TSDB_DATA_TYPE_BLOB 19 // binary +#define TSDB_DATA_TYPE_NULL 0 // 1 bytes +#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes +#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte +#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes +#define TSDB_DATA_TYPE_INT 4 // 4 bytes +#define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes +#define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes +#define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes +#define TSDB_DATA_TYPE_VARCHAR 8 // string, alias for varchar +#define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes +#define TSDB_DATA_TYPE_NCHAR 10 // unicode string +#define TSDB_DATA_TYPE_UTINYINT 11 // 1 byte +#define TSDB_DATA_TYPE_USMALLINT 12 // 2 bytes +#define TSDB_DATA_TYPE_UINT 13 // 4 bytes +#define TSDB_DATA_TYPE_UBIGINT 14 // 8 bytes +#define TSDB_DATA_TYPE_JSON 15 // json string +#define TSDB_DATA_TYPE_VARBINARY 16 // binary +#define TSDB_DATA_TYPE_DECIMAL 17 // decimal +#define TSDB_DATA_TYPE_BLOB 18 // binary +#define TSDB_DATA_TYPE_MEDIUMBLOB 19 +#define TSDB_DATA_TYPE_BINARY TSDB_DATA_TYPE_VARCHAR // string typedef enum { TSDB_OPTION_LOCALE, @@ -256,6 +257,10 @@ DLL_EXPORT void tmq_conf_set_offset_commit_cb(tmq_conf_t *conf, tmq_co void tmqShowMsg(tmq_message_t *tmq_message); int32_t tmqGetSkipLogNum(tmq_message_t *tmq_message); +typedef void (*TAOS_SUBSCRIBE_CALLBACK)(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code); + +DLL_EXPORT int taos_stmt_affected_rows(TAOS_STMT* stmt); + #ifdef __cplusplus } #endif diff --git a/include/common/taosdef.h b/include/common/taosdef.h index 1584fcb4bf74e1bbf65565c876f5176148ed2d1b..39d08f2e868667296c3fd39961cb3c080b48ab2a 100644 --- a/include/common/taosdef.h +++ b/include/common/taosdef.h @@ -61,8 +61,21 @@ typedef enum { TSDB_STATIS_NONE = 1, // statis part not exist } ETsdbStatisStatus; +typedef enum { + TSDB_SMA_STAT_OK = 0, // ready to provide service + TSDB_SMA_STAT_EXPIRED = 1, // not ready or expired +} ETsdbSmaStat; + +typedef enum { + TSDB_SMA_TYPE_BLOCK = 0, // Block-wise SMA + TSDB_SMA_TYPE_TIME_RANGE = 1, // Time-range-wise SMA + TSDB_SMA_TYPE_ROLLUP = 2, // Rollup SMA +} ETsdbSmaType; + extern char *qtypeStr[]; +#define TSDB_PORT_HTTP 11 + #ifdef __cplusplus } #endif diff --git a/include/common/tcommon.h b/include/common/tcommon.h index 3eb9e88ff5845cba77fb3e4a20d12c410ed544df..23dd3498610810363ebe4cc8ad69b90881936673 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -56,8 +56,9 @@ typedef struct SColumnDataAgg { typedef struct SDataBlockInfo { STimeWindow window; int32_t rows; + int32_t rowSize; int32_t numOfCols; - int64_t uid; + union {int64_t uid; int64_t blockId;}; } SDataBlockInfo; typedef struct SConstantItem { @@ -69,10 +70,10 @@ typedef struct SConstantItem { // info.numOfCols = taosArrayGetSize(pDataBlock) + taosArrayGetSize(pConstantList); typedef struct SSDataBlock { - SColumnDataAgg* pBlockAgg; - SArray* pDataBlock; // SArray - SArray* pConstantList; // SArray, it is a constant/tags value of the corresponding result value. - SDataBlockInfo info; + SColumnDataAgg *pBlockAgg; + SArray *pDataBlock; // SArray + SArray *pConstantList; // SArray, it is a constant/tags value of the corresponding result value. + SDataBlockInfo info; } SSDataBlock; typedef struct SVarColAttr { @@ -108,7 +109,7 @@ static FORCE_INLINE int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlo SColumnInfoData* pColData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i); tlen += taosEncodeFixedI16(buf, pColData->info.colId); tlen += taosEncodeFixedI16(buf, pColData->info.type); - tlen += taosEncodeFixedI16(buf, pColData->info.bytes); + tlen += taosEncodeFixedI32(buf, pColData->info.bytes); int32_t colSz = rows * pColData->info.bytes; tlen += taosEncodeBinary(buf, pColData->pData, colSz); } @@ -127,7 +128,7 @@ static FORCE_INLINE void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock) SColumnInfoData data = {0}; buf = taosDecodeFixedI16(buf, &data.info.colId); buf = taosDecodeFixedI16(buf, &data.info.type); - buf = taosDecodeFixedI16(buf, &data.info.bytes); + buf = taosDecodeFixedI32(buf, &data.info.bytes); int32_t colSz = pBlock->info.rows * data.info.bytes; buf = taosDecodeBinary(buf, (void**)&data.pData, colSz); taosArrayPush(pBlock->pDataBlock, &data); @@ -208,10 +209,22 @@ static FORCE_INLINE void tDeleteSMqConsumeRsp(SMqPollRsp* pRsp) { //====================================================================================================================== // the following structure shared by parser and executor typedef struct SColumn { - uint64_t uid; - char name[TSDB_COL_NAME_LEN]; - int8_t flag; // column type: normal column, tag, or user-input column (integer/float/string) - SColumnInfo info; + union { + uint64_t uid; + int64_t dataBlockId; + }; + + union { + int16_t colId; + int16_t slotId; + }; + + char name[TSDB_COL_NAME_LEN]; + int8_t flag; // column type: normal column, tag, or user-input column (integer/float/string) + int16_t type; + int32_t bytes; + uint8_t precision; + uint8_t scale; } SColumn; typedef struct SLimit { @@ -229,21 +242,32 @@ typedef struct SGroupbyExpr { bool groupbyTag; // group by tag or column } SGroupbyExpr; -// the structure for sql function in select clause -typedef struct SSqlExpr { - char token[TSDB_COL_NAME_LEN]; // original token - SSchema resSchema; +typedef struct SFunctParam { + int32_t type; + SColumn *pCol; + SVariant param; +} SFunctParam; - int32_t numOfCols; - SColumn* pColumns; // data columns that are required by query - int32_t interBytes; // inter result buffer size - int16_t numOfParams; // argument value of each function - SVariant param[3]; // parameters are not more than 3 -} SSqlExpr; +// the structure for sql function in select clause +typedef struct SResSchame { + int8_t type; + int32_t colId; + int32_t bytes; + int32_t precision; + int32_t scale; + char name[TSDB_COL_NAME_LEN]; +} SResSchema; + +// TODO move away to executor.h +typedef struct SExprBasicInfo { + SResSchema resSchema; + int16_t numOfParams; // argument value of each function + SFunctParam *pParam; +} SExprBasicInfo; typedef struct SExprInfo { - struct SSqlExpr base; - struct tExprNode* pExpr; + struct SExprBasicInfo base; + struct tExprNode *pExpr; } SExprInfo; typedef struct SStateWindow { diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h index 602df8ca53c7eab4e7881598286b27a934a675dc..c2249f408aeb9eadb2b6ecac577e4d8b9a0a1508 100644 --- a/include/common/tdatablock.h +++ b/include/common/tdatablock.h @@ -94,8 +94,8 @@ int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock); int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows); void colDataTrim(SColumnInfoData* pColumnInfoData); -size_t colDataGetNumOfCols(const SSDataBlock* pBlock); -size_t colDataGetNumOfRows(const SSDataBlock* pBlock); +size_t blockDataGetNumOfCols(const SSDataBlock* pBlock); +size_t blockDataGetNumOfRows(const SSDataBlock* pBlock); int32_t blockDataMerge(SSDataBlock* pDest, const SSDataBlock* pSrc); int32_t blockDataSplitRows(SSDataBlock* pBlock, bool hasVarCol, int32_t startIndex, int32_t* stopIndex, diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 221cf28f237c82b16435079d10bdebdfd552e234..a3e35e18741cb764f2a0d65c9c1fab007a876a90 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -140,6 +140,8 @@ typedef enum _mgmt_table { #define TSDB_KILL_MSG_LEN 30 +#define TSDB_TABLE_NUM_UNIT 100000 + #define TSDB_VN_READ_ACCCESS ((char)0x1) #define TSDB_VN_WRITE_ACCCESS ((char)0x2) #define TSDB_VN_ALL_ACCCESS (TSDB_VN_READ_ACCCESS | TSDB_VN_WRITE_ACCCESS) @@ -169,6 +171,7 @@ typedef struct { char db[TSDB_DB_FNAME_LEN]; int64_t dbId; int32_t vgVersion; + int32_t numOfTable; // unit is TSDB_TABLE_NUM_UNIT } SBuildUseDBInput; typedef struct SField { @@ -419,10 +422,15 @@ typedef struct { * But for data in vnode side, we need all the following information. */ typedef struct { - int16_t colId; - int16_t type; - int16_t bytes; - SColumnFilterList flist; + union { + int16_t colId; + int16_t slotId; + }; + + int16_t type; + int32_t bytes; + uint8_t precision; + uint8_t scale; } SColumnInfo; typedef struct { @@ -452,57 +460,6 @@ typedef struct { int64_t offset; } SInterval; -typedef struct { - SMsgHead head; - char version[TSDB_VERSION_LEN]; - - bool stableQuery; // super table query or not - bool topBotQuery; // TODO used bitwise flag - bool interpQuery; // interp query or not - bool groupbyColumn; // denote if this is a groupby normal column query - bool hasTagResults; // if there are tag values in final result or not - bool timeWindowInterpo; // if the time window start/end required interpolation - bool queryBlockDist; // if query data block distribution - bool stabledev; // super table stddev query - bool tsCompQuery; // is tscomp query - bool simpleAgg; - bool pointInterpQuery; // point interpolation query - bool needReverseScan; // need reverse scan - bool stateWindow; // state window flag - - STimeWindow window; - int32_t numOfTables; - int16_t order; - int16_t orderColId; - int16_t numOfCols; // the number of columns will be load from vnode - SInterval interval; - // SSessionWindow sw; // session window - int16_t tagCondLen; // tag length in current query - int16_t colCondLen; // column length in current query - int16_t numOfGroupCols; // num of group by columns - int16_t orderByIdx; - int16_t orderType; // used in group by xx order by xxx - int64_t vgroupLimit; // limit the number of rows for each table, used in order by + limit in stable projection query. - int16_t prjOrder; // global order in super table projection query. - int64_t limit; - int64_t offset; - int32_t queryType; // denote another query process - int16_t numOfOutput; // final output columns numbers - int16_t fillType; // interpolate type - int64_t fillVal; // default value array list - int32_t secondStageOutput; - STsBufInfo tsBuf; // tsBuf info - int32_t numOfTags; // number of tags columns involved - int32_t sqlstrLen; // sql query string - int32_t prevResultLen; // previous result length - int32_t numOfOperator; - int32_t tableScanOperator; // table scan operator. -1 means no scan operator - int32_t udfNum; // number of udf function - int32_t udfContentOffset; - int32_t udfContentLen; - SColumnInfo tableCols[]; -} SQueryTableReq; - typedef struct { int32_t code; } SQueryTableRsp; @@ -569,6 +526,7 @@ typedef struct { char db[TSDB_DB_FNAME_LEN]; int64_t dbId; int32_t vgVersion; + int32_t numOfTable; // unit is TSDB_TABLE_NUM_UNIT } SUseDbReq; int32_t tSerializeSUseDbReq(void* buf, int32_t bufLen, SUseDbReq* pReq); @@ -587,6 +545,23 @@ int32_t tSerializeSUseDbRsp(void* buf, int32_t bufLen, SUseDbRsp* pRsp); int32_t tDeserializeSUseDbRsp(void* buf, int32_t bufLen, SUseDbRsp* pRsp); void tFreeSUsedbRsp(SUseDbRsp* pRsp); +typedef struct { + int32_t rowNum; +} SQnodeListReq; + +int32_t tSerializeSQnodeListReq(void* buf, int32_t bufLen, SQnodeListReq* pReq); +int32_t tDeserializeSQnodeListReq(void* buf, int32_t bufLen, SQnodeListReq* pReq); + +typedef struct { + SArray *epSetList; // SArray +} SQnodeListRsp; + +int32_t tSerializeSQnodeListRsp(void* buf, int32_t bufLen, SQnodeListRsp* pRsp); +int32_t tDeserializeSQnodeListRsp(void* buf, int32_t bufLen, SQnodeListRsp* pRsp); +void tFreeSQnodeListRsp(SQnodeListRsp* pRsp); + + + typedef struct { SArray* pArray; // Array of SUseDbRsp } SUseDbBatchRsp; @@ -799,8 +774,10 @@ typedef struct SVgroupInfo { uint32_t hashBegin; uint32_t hashEnd; SEpSet epSet; + int32_t numOfTable; // unit is TSDB_TABLE_NUM_UNIT } SVgroupInfo; + typedef struct { int32_t numOfVgroups; SVgroupInfo vgroups[]; @@ -879,6 +856,8 @@ int32_t tDeserializeSShowRsp(void* buf, int32_t bufLen, SShowRsp* pRsp); void tFreeSShowRsp(SShowRsp* pRsp); typedef struct { + int32_t type; + char db[TSDB_DB_FNAME_LEN]; int64_t showId; int8_t free; } SRetrieveTableReq; @@ -906,6 +885,8 @@ int32_t tDeserializeSCreateDnodeReq(void* buf, int32_t bufLen, SCreateDnodeReq* typedef struct { int32_t dnodeId; + char fqdn[TSDB_FQDN_LEN]; + int32_t port; } SDropDnodeReq; int32_t tSerializeSDropDnodeReq(void* buf, int32_t bufLen, SDropDnodeReq* pReq); @@ -1029,6 +1010,7 @@ typedef struct SSubQueryMsg { uint64_t sId; uint64_t queryId; uint64_t taskId; + int64_t refId; int8_t taskType; uint32_t sqlLen; // the query sql, uint32_t phyLen; @@ -1075,19 +1057,57 @@ typedef struct { typedef struct { uint64_t queryId; uint64_t taskId; + int64_t refId; int8_t status; } STaskStatus; typedef struct { - uint32_t num; - STaskStatus status[]; + int64_t refId; + SArray *taskStatus; //SArray } SSchedulerStatusRsp; +typedef struct { + uint64_t queryId; + uint64_t taskId; + int8_t action; +} STaskAction; + + +typedef struct SQueryNodeEpId { + int32_t nodeId; // vgId or qnodeId + SEp ep; +} SQueryNodeEpId; + + +typedef struct { + SMsgHead header; + uint64_t sId; + SQueryNodeEpId epId; + SArray *taskAction; //SArray +} SSchedulerHbReq; + +int32_t tSerializeSSchedulerHbReq(void *buf, int32_t bufLen, SSchedulerHbReq *pReq); +int32_t tDeserializeSSchedulerHbReq(void *buf, int32_t bufLen, SSchedulerHbReq *pReq); +void tFreeSSchedulerHbReq(SSchedulerHbReq *pReq); + + +typedef struct { + uint64_t seqId; + SQueryNodeEpId epId; + SArray *taskStatus; //SArray +} SSchedulerHbRsp; + +int32_t tSerializeSSchedulerHbRsp(void *buf, int32_t bufLen, SSchedulerHbRsp *pRsp); +int32_t tDeserializeSSchedulerHbRsp(void *buf, int32_t bufLen, SSchedulerHbRsp *pRsp); +void tFreeSSchedulerHbRsp(SSchedulerHbRsp *pRsp); + + typedef struct { SMsgHead header; uint64_t sId; uint64_t queryId; uint64_t taskId; + int64_t refId; } STaskCancelReq; typedef struct { @@ -1099,6 +1119,7 @@ typedef struct { uint64_t sId; uint64_t queryId; uint64_t taskId; + int64_t refId; } STaskDropReq; typedef struct { @@ -1349,6 +1370,7 @@ typedef struct SVCreateTbReq { } SVCreateTbReq, SVUpdateTbReq; typedef struct { + int tmp; // TODO: to avoid compile error } SVCreateTbRsp, SVUpdateTbRsp; int32_t tSerializeSVCreateTbReq(void** buf, SVCreateTbReq* pReq); @@ -1360,6 +1382,7 @@ typedef struct { } SVCreateTbBatchReq; typedef struct { + int tmp; // TODO: to avoid compile error } SVCreateTbBatchRsp; int32_t tSerializeSVCreateTbBatchReq(void** buf, SVCreateTbBatchReq* pReq); @@ -1373,6 +1396,7 @@ typedef struct { } SVDropTbReq; typedef struct { + int tmp; // TODO: to avoid compile error } SVDropTbRsp; int32_t tSerializeSVDropTbReq(void** buf, SVDropTbReq* pReq); @@ -1886,19 +1910,22 @@ typedef enum { TD_TIME_UNIT_MICROSEC = 9, TD_TIME_UNIT_NANOSEC = 10 } ETDTimeUnit; + typedef struct { - uint8_t version; // for compatibility - uint8_t intervalUnit; - uint8_t slidingUnit; - char indexName[TSDB_INDEX_NAME_LEN + 1]; - col_id_t numOfColIds; - uint16_t numOfFuncIds; - uint64_t tableUid; // super/common table uid - int64_t interval; - int64_t sliding; - col_id_t* colIds; // sorted column ids - uint16_t* funcIds; // sorted sma function ids -} STSma; // Time-range-wise SMA + int8_t version; // for compatibility(default 0) + int8_t intervalUnit; + int8_t slidingUnit; + char indexName[TSDB_INDEX_NAME_LEN]; + char timezone[TD_TIMEZONE_LEN]; // sma data is invalid if timezone change. + uint16_t exprLen; + uint16_t tagsFilterLen; + int64_t indexUid; + tb_uid_t tableUid; // super/child/common table uid + int64_t interval; + int64_t sliding; + char* expr; // sma expression + char* tagsFilter; +} STSma; // Time-range-wise SMA typedef struct { int64_t ver; // use a general definition @@ -1907,15 +1934,17 @@ typedef struct { typedef struct { int8_t type; // 0 status report, 1 update data - char indexName[TSDB_INDEX_NAME_LEN + 1]; // + char indexName[TSDB_INDEX_NAME_LEN]; // STimeWindow windows; } STSmaMsg; typedef struct { int64_t ver; // use a general definition - char indexName[TSDB_INDEX_NAME_LEN + 1]; + char indexName[TSDB_INDEX_NAME_LEN]; } SVDropTSmaReq; + typedef struct { + int tmp; // TODO: to avoid compile error } SVCreateTSmaRsp, SVDropTSmaRsp; int32_t tSerializeSVCreateTSmaReq(void** buf, SVCreateTSmaReq* pReq); @@ -1924,24 +1953,30 @@ int32_t tSerializeSVDropTSmaReq(void** buf, SVDropTSmaReq* pReq); void* tDeserializeSVDropTSmaReq(void* buf, SVDropTSmaReq* pReq); typedef struct { - STimeWindow tsWindow; // [skey, ekey] - uint64_t tableUid; // sub/common table uid - int32_t numOfBlocks; // number of sma blocks for each column, total number is numOfBlocks*numOfColId - int32_t dataLen; // total data length - col_id_t* colIds; // e.g. 2,4,9,10 - col_id_t numOfColIds; // e.g. 4 - char data[]; // the sma blocks -} STSmaData; - -// TODO: move to the final location afte schema of STSma/STSmaData defined -static FORCE_INLINE void tdDestroySmaData(STSmaData* pSmaData) { - if (pSmaData) { - if (pSmaData->colIds) { - tfree(pSmaData->colIds); - } - tfree(pSmaData); - } -} + col_id_t colId; + uint16_t blockSize; // sma data block size + char data[]; +} STSmaColData; + +typedef struct { + tb_uid_t tableUid; // super/child/normal table uid + int32_t dataLen; // not including head + char data[]; +} STSmaTbData; + +typedef struct { + int64_t indexUid; + TSKEY skey; // startTS of one interval/sliding + int64_t interval; + int32_t dataLen; // not including head + int8_t intervalUnit; + char data[]; +} STSmaDataWrapper; // sma data for a interval/sliding window + +// interval/sliding => window + +// => window->table->colId +// => 当一个window下所有的表均计算完成时,流计算告知tsdb清除window的过期标记 // RSma: Rollup SMA typedef struct { @@ -1964,8 +1999,8 @@ typedef struct { static FORCE_INLINE void tdDestroyTSma(STSma* pSma) { if (pSma) { - tfree(pSma->colIds); - tfree(pSma->funcIds); + tfree(pSma->expr); + tfree(pSma->tagsFilter); } } @@ -1983,22 +2018,24 @@ static FORCE_INLINE void tdDestroyTSmaWrapper(STSmaWrapper* pSW) { static FORCE_INLINE int32_t tEncodeTSma(void** buf, const STSma* pSma) { int32_t tlen = 0; - tlen += taosEncodeFixedU8(buf, pSma->version); - tlen += taosEncodeFixedU8(buf, pSma->intervalUnit); - tlen += taosEncodeFixedU8(buf, pSma->slidingUnit); + tlen += taosEncodeFixedI8(buf, pSma->version); + tlen += taosEncodeFixedI8(buf, pSma->intervalUnit); + tlen += taosEncodeFixedI8(buf, pSma->slidingUnit); tlen += taosEncodeString(buf, pSma->indexName); - tlen += taosEncodeFixedU16(buf, pSma->numOfColIds); - tlen += taosEncodeFixedU16(buf, pSma->numOfFuncIds); - tlen += taosEncodeFixedU64(buf, pSma->tableUid); + tlen += taosEncodeString(buf, pSma->timezone); + tlen += taosEncodeFixedU16(buf, pSma->exprLen); + tlen += taosEncodeFixedU16(buf, pSma->tagsFilterLen); + tlen += taosEncodeFixedI64(buf, pSma->indexUid); + tlen += taosEncodeFixedI64(buf, pSma->tableUid); tlen += taosEncodeFixedI64(buf, pSma->interval); tlen += taosEncodeFixedI64(buf, pSma->sliding); - - for (col_id_t i = 0; i < pSma->numOfColIds; ++i) { - tlen += taosEncodeFixedU16(buf, *(pSma->colIds + i)); + + if (pSma->exprLen > 0) { + tlen += taosEncodeString(buf, pSma->expr); } - for (uint16_t i = 0; i < pSma->numOfFuncIds; ++i) { - tlen += taosEncodeFixedU16(buf, *(pSma->funcIds + i)); + if (pSma->tagsFilterLen > 0) { + tlen += taosEncodeString(buf, pSma->tagsFilter); } return tlen; @@ -2015,38 +2052,43 @@ static FORCE_INLINE int32_t tEncodeTSmaWrapper(void** buf, const STSmaWrapper* p } static FORCE_INLINE void* tDecodeTSma(void* buf, STSma* pSma) { - buf = taosDecodeFixedU8(buf, &pSma->version); - buf = taosDecodeFixedU8(buf, &pSma->intervalUnit); - buf = taosDecodeFixedU8(buf, &pSma->slidingUnit); + buf = taosDecodeFixedI8(buf, &pSma->version); + buf = taosDecodeFixedI8(buf, &pSma->intervalUnit); + buf = taosDecodeFixedI8(buf, &pSma->slidingUnit); buf = taosDecodeStringTo(buf, pSma->indexName); - buf = taosDecodeFixedU16(buf, &pSma->numOfColIds); - buf = taosDecodeFixedU16(buf, &pSma->numOfFuncIds); - buf = taosDecodeFixedU64(buf, &pSma->tableUid); + buf = taosDecodeStringTo(buf, pSma->timezone); + buf = taosDecodeFixedU16(buf, &pSma->exprLen); + buf = taosDecodeFixedU16(buf, &pSma->tagsFilterLen); + buf = taosDecodeFixedI64(buf, &pSma->indexUid); + buf = taosDecodeFixedI64(buf, &pSma->tableUid); buf = taosDecodeFixedI64(buf, &pSma->interval); buf = taosDecodeFixedI64(buf, &pSma->sliding); - if (pSma->numOfColIds > 0) { - pSma->colIds = (col_id_t*)calloc(pSma->numOfColIds, sizeof(STSma)); - if (pSma->colIds == NULL) { + + if (pSma->exprLen > 0) { + pSma->expr = (char*)calloc(pSma->exprLen, 1); + if (pSma->expr != NULL) { + buf = taosDecodeStringTo(buf, pSma->expr); + } else { + tdDestroyTSma(pSma); return NULL; } - for (uint16_t i = 0; i < pSma->numOfColIds; ++i) { - buf = taosDecodeFixedU16(buf, pSma->colIds + i); - } + } else { - pSma->colIds = NULL; + pSma->expr = NULL; } - if (pSma->numOfFuncIds > 0) { - pSma->funcIds = (uint16_t*)calloc(pSma->numOfFuncIds, sizeof(STSma)); - if (pSma->funcIds == NULL) { + if (pSma->tagsFilterLen > 0) { + pSma->tagsFilter = (char*)calloc(pSma->tagsFilterLen, 1); + if (pSma->tagsFilter != NULL) { + buf = taosDecodeStringTo(buf, pSma->tagsFilter); + } else { + tdDestroyTSma(pSma); return NULL; } - for (uint16_t i = 0; i < pSma->numOfFuncIds; ++i) { - buf = taosDecodeFixedU16(buf, pSma->funcIds + i); - } + } else { - pSma->funcIds = NULL; + pSma->tagsFilter = NULL; } return buf; diff --git a/include/common/tmsgdef.h b/include/common/tmsgdef.h index 6a27db89c6cefaf9bcae23f2715f0bee529e443b..03f8daad42e1106b2acecfc2097c456fc049c7af 100644 --- a/include/common/tmsgdef.h +++ b/include/common/tmsgdef.h @@ -129,11 +129,13 @@ enum { TD_DEF_MSG_TYPE(TDMT_MND_DROP_STB, "mnode-drop-stb", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_TABLE_META, "mnode-table-meta", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_VGROUP_LIST, "mnode-vgroup-list", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_MND_QNODE_LIST, "mnode-qnode-list", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_KILL_QUERY, "mnode-kill-query", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_KILL_CONN, "mnode-kill-conn", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_HEARTBEAT, "mnode-heartbeat", SClientHbBatchReq, SClientHbBatchRsp) TD_DEF_MSG_TYPE(TDMT_MND_SHOW, "mnode-show", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_SHOW_RETRIEVE, "mnode-retrieve", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_MND_SYSTABLE_RETRIEVE, "mnode-systable-retrieve", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_STATUS, "mnode-status", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_TRANS_TIMER, "mnode-trans-tmr", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_KILL_TRANS, "mnode-kill-trans", NULL, NULL) @@ -183,6 +185,7 @@ enum { TD_DEF_MSG_TYPE(TDMT_VND_SHOW_TABLES, "vnode-show-tables", SVShowTablesReq, SVShowTablesRsp) TD_DEF_MSG_TYPE(TDMT_VND_SHOW_TABLES_FETCH, "vnode-show-tables-fetch", SVShowTablesFetchReq, SVShowTablesFetchRsp) TD_DEF_MSG_TYPE(TDMT_VND_QUERY_CONTINUE, "vnode-query-continue", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_VND_QUERY_HEARTBEAT, "vnode-query-heartbeat", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_SUBSCRIBE, "vnode-subscribe", SMVSubscribeReq, SMVSubscribeRsp) TD_DEF_MSG_TYPE(TDMT_VND_CONSUME, "vnode-consume", SMqCVConsumeReq, SMqCVConsumeRsp) diff --git a/include/common/trow.h b/include/common/trow.h index ef30796d787528aeb4ec37e1811e310f2d46993a..4dd3daba4dc13aa15a764206ab8fdb19b45e4dcc 100644 --- a/include/common/trow.h +++ b/include/common/trow.h @@ -103,6 +103,7 @@ typedef struct { typedef struct { // TODO + int tmp; // TODO: to avoid compile error } STpRow; // tuple #pragma pack(push, 1) @@ -1098,4 +1099,4 @@ const STSRow *tRowBatchIterNext(STSRowBatchIter *pRowBatchIter); } #endif -#endif /*_TD_COMMON_ROW_H_*/ \ No newline at end of file +#endif /*_TD_COMMON_ROW_H_*/ diff --git a/include/common/ttokendef.h b/include/common/ttokendef.h index f86cbff700c97bcaabad867ce05b705a85efcff5..2121b3175aae0d98a98368dd2274669c55fec018 100644 --- a/include/common/ttokendef.h +++ b/include/common/ttokendef.h @@ -16,279 +16,159 @@ #ifndef _TD_COMMON_TOKEN_H_ #define _TD_COMMON_TOKEN_H_ -#define TK_ID 1 -#define TK_BOOL 2 -#define TK_INTEGER 3 -#define TK_FLOAT 4 -#define TK_STRING 5 -#define TK_TIMESTAMP 6 -#define TK_OR 7 -#define TK_AND 8 -#define TK_NOT 9 -#define TK_EQ 10 -#define TK_NE 11 -#define TK_ISNULL 12 -#define TK_NOTNULL 13 -#define TK_IS 14 -#define TK_LIKE 15 -#define TK_MATCH 16 -#define TK_NMATCH 17 -#define TK_GLOB 18 -#define TK_BETWEEN 19 -#define TK_IN 20 -#define TK_GT 21 -#define TK_GE 22 -#define TK_LT 23 -#define TK_LE 24 -#define TK_BITAND 25 -#define TK_BITOR 26 -#define TK_LSHIFT 27 -#define TK_RSHIFT 28 -#define TK_PLUS 29 -#define TK_MINUS 30 -#define TK_DIVIDE 31 -#define TK_TIMES 32 -#define TK_STAR 33 -#define TK_SLASH 34 -#define TK_REM 35 -#define TK_CONCAT 36 -#define TK_UMINUS 37 -#define TK_UPLUS 38 -#define TK_BITNOT 39 -#define TK_SHOW 40 -#define TK_DATABASES 41 -#define TK_TOPICS 42 -#define TK_FUNCTIONS 43 -#define TK_MNODES 44 -#define TK_DNODES 45 -#define TK_ACCOUNTS 46 -#define TK_USERS 47 -#define TK_MODULES 48 -#define TK_QUERIES 49 -#define TK_CONNECTIONS 50 -#define TK_STREAMS 51 -#define TK_VARIABLES 52 -#define TK_SCORES 53 -#define TK_GRANTS 54 -#define TK_VNODES 55 -#define TK_DOT 56 -#define TK_CREATE 57 -#define TK_TABLE 58 -#define TK_STABLE 59 -#define TK_DATABASE 60 -#define TK_TABLES 61 -#define TK_STABLES 62 -#define TK_VGROUPS 63 -#define TK_DROP 64 -#define TK_TOPIC 65 -#define TK_FUNCTION 66 -#define TK_DNODE 67 -#define TK_USER 68 -#define TK_ACCOUNT 69 -#define TK_USE 70 -#define TK_DESCRIBE 71 -#define TK_DESC 72 -#define TK_ALTER 73 -#define TK_PASS 74 -#define TK_PRIVILEGE 75 -#define TK_LOCAL 76 -#define TK_COMPACT 77 -#define TK_LP 78 -#define TK_RP 79 -#define TK_IF 80 -#define TK_EXISTS 81 -#define TK_PORT 82 -#define TK_IPTOKEN 83 -#define TK_AS 84 -#define TK_OUTPUTTYPE 85 -#define TK_AGGREGATE 86 -#define TK_BUFSIZE 87 -#define TK_PPS 88 -#define TK_TSERIES 89 -#define TK_DBS 90 -#define TK_STORAGE 91 -#define TK_QTIME 92 -#define TK_CONNS 93 -#define TK_STATE 94 -#define TK_COMMA 95 -#define TK_KEEP 96 -#define TK_CACHE 97 -#define TK_REPLICA 98 -#define TK_QUORUM 99 -#define TK_DAYS 100 -#define TK_MINROWS 101 -#define TK_MAXROWS 102 -#define TK_BLOCKS 103 -#define TK_CTIME 104 -#define TK_WAL 105 -#define TK_FSYNC 106 -#define TK_COMP 107 -#define TK_PRECISION 108 -#define TK_UPDATE 109 -#define TK_CACHELAST 110 -#define TK_STREAM 111 -#define TK_MODE 112 -#define TK_UNSIGNED 113 -#define TK_TAGS 114 -#define TK_USING 115 -#define TK_NULL 116 -#define TK_NOW 117 -#define TK_SELECT 118 -#define TK_UNION 119 -#define TK_ALL 120 -#define TK_DISTINCT 121 -#define TK_FROM 122 -#define TK_VARIABLE 123 -#define TK_INTERVAL 124 -#define TK_EVERY 125 -#define TK_SESSION 126 -#define TK_STATE_WINDOW 127 -#define TK_FILL 128 -#define TK_SLIDING 129 -#define TK_ORDER 130 -#define TK_BY 131 -#define TK_ASC 132 -#define TK_GROUP 133 -#define TK_HAVING 134 -#define TK_LIMIT 135 -#define TK_OFFSET 136 -#define TK_SLIMIT 137 -#define TK_SOFFSET 138 -#define TK_WHERE 139 -#define TK_RESET 140 -#define TK_QUERY 141 -#define TK_SYNCDB 142 -#define TK_ADD 143 -#define TK_COLUMN 144 -#define TK_MODIFY 145 -#define TK_TAG 146 -#define TK_CHANGE 147 -#define TK_SET 148 -#define TK_KILL 149 -#define TK_CONNECTION 150 -#define TK_COLON 151 -#define TK_ABORT 152 -#define TK_AFTER 153 -#define TK_ATTACH 154 -#define TK_BEFORE 155 -#define TK_BEGIN 156 -#define TK_CASCADE 157 -#define TK_CLUSTER 158 -#define TK_CONFLICT 159 -#define TK_COPY 160 -#define TK_DEFERRED 161 -#define TK_DELIMITERS 162 -#define TK_DETACH 163 -#define TK_EACH 164 -#define TK_END 165 -#define TK_EXPLAIN 166 -#define TK_FAIL 167 -#define TK_FOR 168 -#define TK_IGNORE 169 -#define TK_IMMEDIATE 170 -#define TK_INITIALLY 171 -#define TK_INSTEAD 172 -#define TK_KEY 173 -#define TK_OF 174 -#define TK_RAISE 175 -#define TK_REPLACE 176 -#define TK_RESTRICT 177 -#define TK_ROW 178 -#define TK_STATEMENT 179 -#define TK_TRIGGER 180 -#define TK_VIEW 181 -#define TK_SEMI 182 -#define TK_NONE 183 -#define TK_PREV 184 -#define TK_LINEAR 185 -#define TK_IMPORT 186 -#define TK_TBNAME 187 -#define TK_JOIN 188 -#define TK_INSERT 189 -#define TK_INTO 190 -#define TK_VALUES 191 +#define TK_OR 1 +#define TK_AND 2 +#define TK_UNION 3 +#define TK_ALL 4 +#define TK_MINUS 5 +#define TK_EXCEPT 6 +#define TK_INTERSECT 7 +#define TK_NK_BITAND 8 +#define TK_NK_BITOR 9 +#define TK_NK_LSHIFT 10 +#define TK_NK_RSHIFT 11 +#define TK_NK_PLUS 12 +#define TK_NK_MINUS 13 +#define TK_NK_STAR 14 +#define TK_NK_SLASH 15 +#define TK_NK_REM 16 +#define TK_NK_CONCAT 17 +#define TK_CREATE 18 +#define TK_USER 19 +#define TK_PASS 20 +#define TK_NK_STRING 21 +#define TK_ALTER 22 +#define TK_PRIVILEGE 23 +#define TK_DROP 24 +#define TK_SHOW 25 +#define TK_USERS 26 +#define TK_DNODE 27 +#define TK_PORT 28 +#define TK_NK_INTEGER 29 +#define TK_DNODES 30 +#define TK_NK_ID 31 +#define TK_NK_IPTOKEN 32 +#define TK_DATABASE 33 +#define TK_DATABASES 34 +#define TK_USE 35 +#define TK_IF 36 +#define TK_NOT 37 +#define TK_EXISTS 38 +#define TK_BLOCKS 39 +#define TK_CACHE 40 +#define TK_CACHELAST 41 +#define TK_COMP 42 +#define TK_DAYS 43 +#define TK_FSYNC 44 +#define TK_MAXROWS 45 +#define TK_MINROWS 46 +#define TK_KEEP 47 +#define TK_PRECISION 48 +#define TK_QUORUM 49 +#define TK_REPLICA 50 +#define TK_TTL 51 +#define TK_WAL 52 +#define TK_VGROUPS 53 +#define TK_SINGLE_STABLE 54 +#define TK_STREAM_MODE 55 +#define TK_TABLE 56 +#define TK_NK_LP 57 +#define TK_NK_RP 58 +#define TK_STABLE 59 +#define TK_TABLES 60 +#define TK_STABLES 61 +#define TK_USING 62 +#define TK_TAGS 63 +#define TK_NK_DOT 64 +#define TK_NK_COMMA 65 +#define TK_COMMENT 66 +#define TK_BOOL 67 +#define TK_TINYINT 68 +#define TK_SMALLINT 69 +#define TK_INT 70 +#define TK_INTEGER 71 +#define TK_BIGINT 72 +#define TK_FLOAT 73 +#define TK_DOUBLE 74 +#define TK_BINARY 75 +#define TK_TIMESTAMP 76 +#define TK_NCHAR 77 +#define TK_UNSIGNED 78 +#define TK_JSON 79 +#define TK_VARCHAR 80 +#define TK_MEDIUMBLOB 81 +#define TK_BLOB 82 +#define TK_VARBINARY 83 +#define TK_DECIMAL 84 +#define TK_SMA 85 +#define TK_MNODES 86 +#define TK_NK_FLOAT 87 +#define TK_NK_BOOL 88 +#define TK_NK_VARIABLE 89 +#define TK_BETWEEN 90 +#define TK_IS 91 +#define TK_NULL 92 +#define TK_NK_LT 93 +#define TK_NK_GT 94 +#define TK_NK_LE 95 +#define TK_NK_GE 96 +#define TK_NK_NE 97 +#define TK_NK_EQ 98 +#define TK_LIKE 99 +#define TK_MATCH 100 +#define TK_NMATCH 101 +#define TK_IN 102 +#define TK_FROM 103 +#define TK_AS 104 +#define TK_JOIN 105 +#define TK_ON 106 +#define TK_INNER 107 +#define TK_SELECT 108 +#define TK_DISTINCT 109 +#define TK_WHERE 110 +#define TK_PARTITION 111 +#define TK_BY 112 +#define TK_SESSION 113 +#define TK_STATE_WINDOW 114 +#define TK_INTERVAL 115 +#define TK_SLIDING 116 +#define TK_FILL 117 +#define TK_VALUE 118 +#define TK_NONE 119 +#define TK_PREV 120 +#define TK_LINEAR 121 +#define TK_NEXT 122 +#define TK_GROUP 123 +#define TK_HAVING 124 +#define TK_ORDER 125 +#define TK_SLIMIT 126 +#define TK_SOFFSET 127 +#define TK_LIMIT 128 +#define TK_OFFSET 129 +#define TK_ASC 130 +#define TK_DESC 131 +#define TK_NULLS 132 +#define TK_FIRST 133 +#define TK_LAST 134 -#define NEW_TK_OR 1 -#define NEW_TK_AND 2 -#define NEW_TK_UNION 3 -#define NEW_TK_ALL 4 -#define NEW_TK_MINUS 5 -#define NEW_TK_EXCEPT 6 -#define NEW_TK_INTERSECT 7 -#define NEW_TK_NK_PLUS 8 -#define NEW_TK_NK_MINUS 9 -#define NEW_TK_NK_STAR 10 -#define NEW_TK_NK_SLASH 11 -#define NEW_TK_NK_REM 12 -#define NEW_TK_SHOW 13 -#define NEW_TK_DATABASES 14 -#define NEW_TK_NK_INTEGER 15 -#define NEW_TK_NK_FLOAT 16 -#define NEW_TK_NK_STRING 17 -#define NEW_TK_NK_BOOL 18 -#define NEW_TK_TIMESTAMP 19 -#define NEW_TK_NK_VARIABLE 20 -#define NEW_TK_NK_COMMA 21 -#define NEW_TK_NK_ID 22 -#define NEW_TK_NK_LP 23 -#define NEW_TK_NK_RP 24 -#define NEW_TK_NK_DOT 25 -#define NEW_TK_BETWEEN 26 -#define NEW_TK_NOT 27 -#define NEW_TK_IS 28 -#define NEW_TK_NULL 29 -#define NEW_TK_NK_LT 30 -#define NEW_TK_NK_GT 31 -#define NEW_TK_NK_LE 32 -#define NEW_TK_NK_GE 33 -#define NEW_TK_NK_NE 34 -#define NEW_TK_NK_EQ 35 -#define NEW_TK_LIKE 36 -#define NEW_TK_MATCH 37 -#define NEW_TK_NMATCH 38 -#define NEW_TK_IN 39 -#define NEW_TK_FROM 40 -#define NEW_TK_AS 41 -#define NEW_TK_JOIN 42 -#define NEW_TK_ON 43 -#define NEW_TK_INNER 44 -#define NEW_TK_SELECT 45 -#define NEW_TK_DISTINCT 46 -#define NEW_TK_WHERE 47 -#define NEW_TK_PARTITION 48 -#define NEW_TK_BY 49 -#define NEW_TK_SESSION 50 -#define NEW_TK_STATE_WINDOW 51 -#define NEW_TK_INTERVAL 52 -#define NEW_TK_SLIDING 53 -#define NEW_TK_FILL 54 -#define NEW_TK_VALUE 55 -#define NEW_TK_NONE 56 -#define NEW_TK_PREV 57 -#define NEW_TK_LINEAR 58 -#define NEW_TK_NEXT 59 -#define NEW_TK_GROUP 60 -#define NEW_TK_HAVING 61 -#define NEW_TK_ORDER 62 -#define NEW_TK_SLIMIT 63 -#define NEW_TK_SOFFSET 64 -#define NEW_TK_LIMIT 65 -#define NEW_TK_OFFSET 66 -#define NEW_TK_ASC 67 -#define NEW_TK_DESC 68 -#define NEW_TK_NULLS 69 -#define NEW_TK_FIRST 70 -#define NEW_TK_LAST 71 +#define TK_NK_SPACE 300 +#define TK_NK_COMMENT 301 +#define TK_NK_ILLEGAL 302 +#define TK_NK_HEX 303 // hex number 0x123 +#define TK_NK_OCT 304 // oct number +#define TK_NK_BIN 305 // bin format data 0b111 +#define TK_NK_FILE 306 +#define TK_NK_QUESTION 307 // denoting the placeholder of "?",when invoking statement bind query -#define TK_SPACE 300 -#define TK_COMMENT 301 -#define TK_ILLEGAL 302 -#define TK_HEX 303 // hex number 0x123 -#define TK_OCT 304 // oct number -#define TK_BIN 305 // bin format data 0b111 -#define TK_FILE 306 -#define TK_QUESTION 307 // denoting the placeholder of "?",when invoking statement bind query +#define TK_NK_COLON 500 +#define TK_NK_BITNOT 501 +#define TK_INSERT 502 +#define TK_INTO 503 +#define TK_NOW 504 +#define TK_VALUES 507 +#define TK_IMPORT 507 +#define TK_NK_SEMI 508 -#define TK_NIL 65535 +#define TK_NK_NIL 65535 #endif /*_TD_COMMON_TOKEN_H_*/ diff --git a/include/libs/catalog/catalog.h b/include/libs/catalog/catalog.h index c6183780f906606ea0542f2a367093dc0ad860dc..f217277b805dd0fefdd1746daf499d1d6a6db680 100644 --- a/include/libs/catalog/catalog.h +++ b/include/libs/catalog/catalog.h @@ -51,7 +51,7 @@ typedef struct SMetaData { SArray *pTableMeta; // STableMeta array SArray *pVgroupInfo; // SVgroupInfo list SArray *pUdfList; // udf info list - SEpSet *pEpSet; // qnode epset list + SArray *pEpSetList; // qnode epset list, SArray } SMetaData; typedef struct SCatalogCfg { @@ -74,9 +74,9 @@ typedef struct SDbVgVersion { char dbFName[TSDB_DB_FNAME_LEN]; int64_t dbId; int32_t vgVersion; + int32_t numOfTable; // unit is TSDB_TABLE_NUM_UNIT } SDbVgVersion; - int32_t catalogInit(SCatalogCfg *cfg); /** @@ -95,7 +95,7 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle); */ void catalogFreeHandle(SCatalog* pCatalog); -int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId); +int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId, int32_t *tableNum); /** * Get a DB's all vgroup info. diff --git a/include/libs/executor/dataSinkMgt.h b/include/libs/executor/dataSinkMgt.h index 19438b5dd4bfcdbe5997314c87f4be980ebe9534..293e7ae52f55d72ff4b6af8166c8f84d6eb37f97 100644 --- a/include/libs/executor/dataSinkMgt.h +++ b/include/libs/executor/dataSinkMgt.h @@ -23,6 +23,7 @@ extern "C" { #include "os.h" #include "thash.h" #include "executor.h" +#include "plannodes.h" #define DS_BUF_LOW 1 #define DS_BUF_FULL 2 @@ -40,7 +41,6 @@ int32_t dsDataSinkMgtInit(SDataSinkMgtCfg *cfg); typedef struct SInputData { const struct SSDataBlock* pData; - SHashObj* pTableRetrieveTsMap; } SInputData; typedef struct SOutputData { @@ -59,7 +59,7 @@ typedef struct SOutputData { * @param pHandle output * @return error code */ -int32_t dsCreateDataSinker(const struct SDataSink *pDataSink, DataSinkHandle* pHandle); +int32_t dsCreateDataSinker(const SDataSinkNode* pDataSink, DataSinkHandle* pHandle); /** * Put the result set returned by the executor into datasinker. diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 62063ef99a67b961b852a3870600d4d4b850ed7b..c01e267c42c418aedcca7599c13c95f83c4ff9a4 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -20,9 +20,30 @@ extern "C" { #endif +#include "tbuffer.h" #include "tcommon.h" #include "tvariant.h" -#include "tbuffer.h" + +struct SqlFunctionCtx; +struct SResultRowEntryInfo; + +typedef struct SFunctionNode SFunctionNode; + +typedef struct SFuncExecEnv { + int32_t calcMemSize; +} SFuncExecEnv; + +typedef bool (*FExecGetEnv)(SFunctionNode* pFunc, SFuncExecEnv* pEnv); +typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); +typedef void (*FExecProcess)(struct SqlFunctionCtx *pCtx); +typedef void (*FExecFinalize)(struct SqlFunctionCtx *pCtx); + +typedef struct SFuncExecFuncs { + FExecGetEnv getEnv; + FExecInit init; + FExecProcess process; + FExecFinalize finalize; +} SFuncExecFuncs; #define MAX_INTERVAL_TIME_WINDOW 1000000 // maximum allowed time windows in final results @@ -111,64 +132,65 @@ struct SqlFunctionCtx; struct SResultRowEntryInfo; //for selectivity query, the corresponding tag value is assigned if the data is qualified -typedef struct SExtTagsInfo { - int16_t tagsLen; // keep the tags data for top/bottom query result - int16_t numOfTagCols; - struct SqlFunctionCtx **pTagCtxList; -} SExtTagsInfo; +typedef struct SSubsidiaryResInfo { + int16_t bufLen; // keep the tags data for top/bottom query result + int16_t numOfCols; + struct SqlFunctionCtx **pCtx; +} SSubsidiaryResInfo; typedef struct SResultDataInfo { + int16_t precision; + int16_t scale; int16_t type; int16_t bytes; - int32_t intermediateBytes; + int32_t interBufSize; } SResultDataInfo; #define GET_RES_INFO(ctx) ((ctx)->resultInfo) -typedef struct SFunctionFpSet { - bool (*init)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment - void (*addInput)(struct SqlFunctionCtx *pCtx); - - // finalizer must be called after all exec has been executed to generated final result. - void (*finalize)(struct SqlFunctionCtx *pCtx); - void (*combine)(struct SqlFunctionCtx *pCtx); -} SFunctionFpSet; - -extern SFunctionFpSet fpSet[1]; +typedef struct SInputColumnInfoData { + int32_t totalRows; // total rows in current columnar data + int32_t startRowIndex; // handle started row index + int32_t numOfRows; // the number of rows needs to be handled + int32_t numOfInputCols; // PTS is not included + bool colDataAggIsSet;// if agg is set or not + SColumnInfoData *pPTS; // primary timestamp column + SColumnInfoData **pData; + SColumnDataAgg **pColumnDataAgg; +} SInputColumnInfoData; // sql function runtime context typedef struct SqlFunctionCtx { - int32_t startRow; - int32_t size; // number of rows + SInputColumnInfoData input; + SResultDataInfo resDataInfo; + uint32_t order; // asc|desc + //////////////////////////////////////////////////////////////// + int32_t startRow; // start row index + int32_t size; // handled processed row number SColumnInfoData* pInput; - - uint32_t order; // asc|desc - int16_t inputType; - int16_t inputBytes; - - SResultDataInfo resDataInfo; - bool hasNull; // null value exist in current block - bool requireNull; // require null in some function - bool stableQuery; - int16_t functionId; // function id - char * pOutput; // final result output buffer, point to sdata->data - uint8_t currentStage; // record current running step, default: 0 - int64_t startTs; // timestamp range of current query when function is executed on a specific data block - int32_t numOfParams; - SVariant param[4]; // input parameter, e.g., top(k, 20), the number of results for top query is kept in param - int64_t *ptsList; // corresponding timestamp array list - void *ptsOutputBuf; // corresponding output buffer for timestamp of each result, e.g., top/bottom*/ - SVariant tag; - - bool isAggSet; - SColumnDataAgg agg; + SColumnDataAgg agg; + int16_t inputType; // TODO remove it + int16_t inputBytes; // TODO remove it + bool hasNull; // null value exist in current block, TODO remove it + bool requireNull; // require null in some function, TODO remove it + int32_t columnIndex; // TODO remove it + uint8_t currentStage; // record current running step, default: 0 + bool isAggSet; + ///////////////////////////////////////////////////////////////// + bool stableQuery; + int16_t functionId; // function id + char * pOutput; // final result output buffer, point to sdata->data + int64_t startTs; // timestamp range of current query when function is executed on a specific data block + int32_t numOfParams; + SVariant param[4]; // input parameter, e.g., top(k, 20), the number of results for top query is kept in param + int64_t *ptsList; // corresponding timestamp array list + void *ptsOutputBuf; // corresponding output buffer for timestamp of each result, e.g., top/bottom*/ + SVariant tag; struct SResultRowEntryInfo *resultInfo; - SExtTagsInfo tagInfo; - SPoint1 start; - SPoint1 end; - - int32_t columnIndex; - SFunctionFpSet* fpSet; + SSubsidiaryResInfo subsidiaryRes; + SPoint1 start; + SPoint1 end; + SFuncExecFuncs fpSet; } SqlFunctionCtx; enum { @@ -194,9 +216,10 @@ typedef struct tExprNode { struct SVariant *pVal; // value node struct {// function node - char functionName[FUNCTIONS_NAME_MAX_LENGTH]; + char functionName[FUNCTIONS_NAME_MAX_LENGTH]; // todo refactor + int32_t functionId; int32_t num; - + SFunctionNode *pFunctNode; // Note that the attribute of pChild is not the parameter of function, it is the columns that involved in the // calculation instead. // E.g., Cov(col1, col2), the column information, w.r.t. the col1 and col2, is kept in pChild nodes. @@ -207,7 +230,6 @@ typedef struct tExprNode { }; } tExprNode; -//TODO create? void exprTreeToBinary(SBufferWriter* bw, tExprNode* pExprTree); void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *)); @@ -294,7 +316,7 @@ tExprNode* exprdup(tExprNode* pTree); void resetResultRowEntryResult(SqlFunctionCtx* pCtx, int32_t num); void cleanupResultRowEntry(struct SResultRowEntryInfo* pCell); -int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num); +int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num, SSDataBlock* pResBlock); bool isRowEntryCompleted(struct SResultRowEntryInfo* pEntry); bool isRowEntryInitialized(struct SResultRowEntryInfo* pEntry); diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index e77ccaa225e16195e4ce4758deedee2ddf3eead2..35832fa298b2328b74a7836338957b1ae7e96471 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -102,22 +102,6 @@ struct SqlFunctionCtx; struct SResultRowEntryInfo; struct STimeWindow; -typedef struct SFuncExecEnv { - int32_t calcMemSize; -} SFuncExecEnv; - -typedef bool (*FExecGetEnv)(SFunctionNode* pFunc, SFuncExecEnv* pEnv); -typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); -typedef void (*FExecProcess)(struct SqlFunctionCtx *pCtx); -typedef void (*FExecFinalize)(struct SqlFunctionCtx *pCtx); - -typedef struct SFuncExecFuncs { - FExecGetEnv getEnv; - FExecInit init; - FExecProcess process; - FExecFinalize finalize; -} SFuncExecFuncs; - typedef int32_t (*FScalarExecProcess)(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); typedef struct SScalarFuncExecFuncs { @@ -127,6 +111,8 @@ typedef struct SScalarFuncExecFuncs { int32_t fmFuncMgtInit(); +void fmFuncMgtDestroy(); + int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType); int32_t fmGetFuncResultType(SFunctionNode* pFunc); diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h new file mode 100644 index 0000000000000000000000000000000000000000..084258e48f0890b520f528b6a0d8874094ab279d --- /dev/null +++ b/include/libs/nodes/cmdnodes.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#ifndef _TD_CMD_NODES_H_ +#define _TD_CMD_NODES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "querynodes.h" + +typedef struct SDatabaseOptions { + int32_t numOfBlocks; + int32_t cacheBlockSize; + int8_t cachelast; + int32_t compressionLevel; + int32_t daysPerFile; + int32_t fsyncPeriod; + int32_t maxRowsPerBlock; + int32_t minRowsPerBlock; + int32_t keep; + int32_t precision; + int32_t quorum; + int32_t replica; + int32_t ttl; + int32_t walLevel; + int32_t numOfVgroups; + int8_t singleStable; + int8_t streamMode; +} SDatabaseOptions; + +typedef struct SCreateDatabaseStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + bool ignoreExists; + SDatabaseOptions options; +} SCreateDatabaseStmt; + +typedef struct SUseDatabaseStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; +} SUseDatabaseStmt; + +typedef struct SDropDatabaseStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + bool ignoreNotExists; +} SDropDatabaseStmt; + +typedef struct STableOptions { + int32_t keep; + int32_t ttl; + char comments[TSDB_STB_COMMENT_LEN]; + SNodeList* pSma; +} STableOptions; + +typedef struct SColumnDefNode { + ENodeType type; + char colName[TSDB_COL_NAME_LEN]; + SDataType dataType; + char comments[TSDB_STB_COMMENT_LEN]; +} SColumnDefNode; + +typedef struct SCreateTableStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + bool ignoreExists; + SNodeList* pCols; + SNodeList* pTags; + STableOptions options; +} SCreateTableStmt; + +typedef struct SCreateSubTableClause { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + char useDbName[TSDB_DB_NAME_LEN]; + char useTableName[TSDB_TABLE_NAME_LEN]; + bool ignoreExists; + SNodeList* pSpecificTags; + SNodeList* pValsOfTags; +} SCreateSubTableClause; + +typedef struct SCreateMultiTableStmt { + ENodeType type; + SNodeList* pSubTables; +} SCreateMultiTableStmt; + +typedef struct SDropTableClause { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + bool ignoreNotExists; +} SDropTableClause; + +typedef struct SDropTableStmt { + ENodeType type; + SNodeList* pTables; +} SDropTableStmt; + +typedef struct SDropSuperTableStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + bool ignoreNotExists; +} SDropSuperTableStmt; + +typedef struct SCreateUserStmt { + ENodeType type; + char useName[TSDB_USER_LEN]; + char password[TSDB_USET_PASSWORD_LEN]; +} SCreateUserStmt; + +typedef struct SAlterUserStmt { + ENodeType type; + char useName[TSDB_USER_LEN]; + char password[TSDB_USET_PASSWORD_LEN]; + int8_t alterType; +} SAlterUserStmt; + +typedef struct SDropUserStmt { + ENodeType type; + char useName[TSDB_USER_LEN]; +} SDropUserStmt; + +typedef struct SCreateDnodeStmt { + ENodeType type; + char fqdn[TSDB_FQDN_LEN]; + int32_t port; +} SCreateDnodeStmt; + +typedef struct SDropDnodeStmt { + ENodeType type; + int32_t dnodeId; + char fqdn[TSDB_FQDN_LEN]; + int32_t port; +} SDropDnodeStmt; + +typedef struct SShowStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; +} SShowStmt; + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_CMD_NODES_H_*/ diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h index 96815ac29fe583b430e22afe094f3fa6ec25aeaf..3a9dd3c713b09d627243e76884a5e5db887b3116 100644 --- a/include/libs/nodes/nodes.h +++ b/include/libs/nodes/nodes.h @@ -65,24 +65,62 @@ typedef enum ENodeType { QUERY_NODE_TARGET, QUERY_NODE_DATABLOCK_DESC, QUERY_NODE_SLOT_DESC, + QUERY_NODE_COLUMN_DEF, + QUERY_NODE_DOWNSTREAM_SOURCE, // Statement nodes are used in parser and planner module. QUERY_NODE_SET_OPERATOR, QUERY_NODE_SELECT_STMT, - QUERY_NODE_SHOW_STMT, + QUERY_NODE_VNODE_MODIF_STMT, + QUERY_NODE_CREATE_DATABASE_STMT, + QUERY_NODE_DROP_DATABASE_STMT, + QUERY_NODE_SHOW_DATABASES_STMT, // temp + QUERY_NODE_CREATE_TABLE_STMT, + QUERY_NODE_CREATE_SUBTABLE_CLAUSE, + QUERY_NODE_CREATE_MULTI_TABLE_STMT, + QUERY_NODE_DROP_TABLE_CLAUSE, + QUERY_NODE_DROP_TABLE_STMT, + QUERY_NODE_DROP_SUPER_TABLE_STMT, + QUERY_NODE_SHOW_TABLES_STMT, // temp + QUERY_NODE_SHOW_STABLES_STMT, + QUERY_NODE_CREATE_USER_STMT, + QUERY_NODE_ALTER_USER_STMT, + QUERY_NODE_DROP_USER_STMT, + QUERY_NODE_SHOW_USERS_STMT, + QUERY_NODE_USE_DATABASE_STMT, + QUERY_NODE_CREATE_DNODE_STMT, + QUERY_NODE_DROP_DNODE_STMT, + QUERY_NODE_SHOW_DNODES_STMT, + QUERY_NODE_SHOW_VGROUPS_STMT, + QUERY_NODE_SHOW_MNODES_STMT, // logic plan node QUERY_NODE_LOGIC_PLAN_SCAN, QUERY_NODE_LOGIC_PLAN_JOIN, QUERY_NODE_LOGIC_PLAN_AGG, QUERY_NODE_LOGIC_PLAN_PROJECT, + QUERY_NODE_LOGIC_PLAN_VNODE_MODIF, + QUERY_NODE_LOGIC_PLAN_EXCHANGE, + QUERY_NODE_LOGIC_PLAN_WINDOW, + QUERY_NODE_LOGIC_SUBPLAN, + QUERY_NODE_LOGIC_PLAN, // physical plan node QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, + QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, + QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, + QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN, QUERY_NODE_PHYSICAL_PLAN_PROJECT, QUERY_NODE_PHYSICAL_PLAN_JOIN, - QUERY_NODE_PHYSICAL_PLAN_AGG + QUERY_NODE_PHYSICAL_PLAN_AGG, + QUERY_NODE_PHYSICAL_PLAN_EXCHANGE, + QUERY_NODE_PHYSICAL_PLAN_SORT, + QUERY_NODE_PHYSICAL_PLAN_INTERVAL, + QUERY_NODE_PHYSICAL_PLAN_DISPATCH, + QUERY_NODE_PHYSICAL_PLAN_INSERT, + QUERY_NODE_PHYSICAL_SUBPLAN, + QUERY_NODE_PHYSICAL_PLAN } ENodeType; /** @@ -105,15 +143,20 @@ typedef struct SNodeList { SListCell* pTail; } SNodeList; -SNode* nodesMakeNode(ENodeType type); -void nodesDestroyNode(SNode* pNode); +#define SNodeptr void* + +SNodeptr nodesMakeNode(ENodeType type); +void nodesDestroyNode(SNodeptr pNode); SNodeList* nodesMakeList(); -int32_t nodesListAppend(SNodeList* pList, SNode* pNode); +int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode); +int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode); int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc); SListCell* nodesListErase(SNodeList* pList, SListCell* pCell); -SNode* nodesListGetNode(SNodeList* pList, int32_t index); +SNodeptr nodesListGetNode(SNodeList* pList, int32_t index); void nodesDestroyList(SNodeList* pList); +// Only clear the linked list structure, without releasing the elements inside +void nodesClearList(SNodeList* pList); typedef enum EDealRes { DEAL_RES_CONTINUE = 1, @@ -122,9 +165,9 @@ typedef enum EDealRes { } EDealRes; typedef EDealRes (*FNodeWalker)(SNode* pNode, void* pContext); -void nodesWalkNode(SNode* pNode, FNodeWalker walker, void* pContext); +void nodesWalkNode(SNodeptr pNode, FNodeWalker walker, void* pContext); void nodesWalkList(SNodeList* pList, FNodeWalker walker, void* pContext); -void nodesWalkNodePostOrder(SNode* pNode, FNodeWalker walker, void* pContext); +void nodesWalkNodePostOrder(SNodeptr pNode, FNodeWalker walker, void* pContext); void nodesWalkListPostOrder(SNodeList* pList, FNodeWalker walker, void* pContext); typedef EDealRes (*FNodeRewriter)(SNode** pNode, void* pContext); @@ -133,12 +176,13 @@ void nodesRewriteList(SNodeList* pList, FNodeRewriter rewriter, void* pContext); void nodesRewriteNodePostOrder(SNode** pNode, FNodeRewriter rewriter, void* pContext); void nodesRewriteListPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* pContext); -bool nodesEqualNode(const SNode* a, const SNode* b); +bool nodesEqualNode(const SNodeptr a, const SNodeptr b); -SNode* nodesCloneNode(const SNode* pNode); +SNodeptr nodesCloneNode(const SNodeptr pNode); SNodeList* nodesCloneList(const SNodeList* pList); -int32_t nodesNodeToString(const SNode* pNode, bool format, char** pStr, int32_t* pLen); +const char* nodesNodeName(ENodeType type); +int32_t nodesNodeToString(const SNodeptr pNode, bool format, char** pStr, int32_t* pLen); int32_t nodesStringToNode(const char* pStr, SNode** pNode); #ifdef __cplusplus diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index 608146e3df99942bafdab181c9cc484a781e0f26..c028c4a1b99663abaa80b4c8ab4a8a4b4d1b1f48 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -21,7 +21,8 @@ extern "C" { #endif #include "querynodes.h" -#include "tmsg.h" +#include "query.h" +#include "tname.h" typedef struct SLogicNode { ENodeType type; @@ -43,9 +44,11 @@ typedef struct SScanLogicNode { SLogicNode node; SNodeList* pScanCols; struct STableMeta* pMeta; + SVgroupsInfo* pVgroupList; EScanType scanType; uint8_t scanFlag; // denotes reversed scan of data or not STimeWindow scanRange; + SName tableName; } SScanLogicNode; typedef struct SJoinLogicNode { @@ -65,6 +68,65 @@ typedef struct SProjectLogicNode { SNodeList* pProjections; } SProjectLogicNode; +typedef struct SVnodeModifLogicNode { + SLogicNode node;; + int32_t msgType; + SArray* pDataBlocks; + SVgDataBlocks* pVgDataBlocks; +} SVnodeModifLogicNode; + +typedef struct SExchangeLogicNode { + SLogicNode node; + int32_t srcGroupId; +} SExchangeLogicNode; + +typedef enum EWindowType { + WINDOW_TYPE_INTERVAL = 1, + WINDOW_TYPE_SESSION, + WINDOW_TYPE_STATE +} EWindowType; + +typedef struct SWindowLogicNode { + SLogicNode node; + EWindowType winType; + SNodeList* pFuncs; + int64_t interval; + int64_t offset; + int64_t sliding; + SFillNode* pFill; +} SWindowLogicNode; + +typedef enum ESubplanType { + SUBPLAN_TYPE_MERGE = 1, + SUBPLAN_TYPE_PARTIAL, + SUBPLAN_TYPE_SCAN, + SUBPLAN_TYPE_MODIFY +} ESubplanType; + +typedef struct SSubplanId { + uint64_t queryId; + int32_t groupId; + int32_t subplanId; +} SSubplanId; + +typedef struct SSubLogicPlan { + ENodeType type; + SSubplanId id; + SNodeList* pChildren; + SNodeList* pParents; + SLogicNode* pNode; + ESubplanType subplanType; + SVgroupsInfo* pVgroupList; + int32_t level; + int32_t splitFlag; +} SSubLogicPlan; + +typedef struct SQueryLogicPlan { + ENodeType type;; + int32_t totalLevel; + SNodeList* pTopSubplans; +} SQueryLogicPlan; + typedef struct SSlotDescNode { ENodeType type; int16_t slotId; @@ -78,11 +140,13 @@ typedef struct SDataBlockDescNode { ENodeType type; int16_t dataBlockId; SNodeList* pSlots; + int32_t resultRowSize; + int16_t precision; } SDataBlockDescNode; typedef struct SPhysiNode { ENodeType type; - SDataBlockDescNode outputDataBlockDesc; + SDataBlockDescNode* pOutputDataBlockDesc; SNode* pConditions; SNodeList* pChildren; struct SPhysiNode* pParent; @@ -96,6 +160,7 @@ typedef struct SScanPhysiNode { int32_t order; // scan order: TSDB_ORDER_ASC|TSDB_ORDER_DESC int32_t count; // repeat count int32_t reverse; // reverse scan count + SName tableName; } SScanPhysiNode; typedef SScanPhysiNode SSystemTableScanPhysiNode; @@ -129,6 +194,66 @@ typedef struct SAggPhysiNode { SNodeList* pAggFuncs; } SAggPhysiNode; +typedef struct SDownstreamSourceNode { + ENodeType type; + SQueryNodeAddr addr; + uint64_t taskId; + uint64_t schedId; +} SDownstreamSourceNode; + +typedef struct SExchangePhysiNode { + SPhysiNode node; + int32_t srcGroupId; // group id of datasource suplans + SNodeList* pSrcEndPoints; // element is SDownstreamSource, scheduler fill by calling qSetSuplanExecutionNode +} SExchangePhysiNode; + +typedef struct SIntervalPhysiNode { + SPhysiNode node; + SNodeList* pExprs; // these are expression list of parameter expression of function + SNodeList* pFuncs; + int64_t interval; + int64_t offset; + int64_t sliding; + SFillNode* pFill; +} SIntervalPhysiNode; + +typedef struct SDataSinkNode { + ENodeType type; + SDataBlockDescNode* pInputDataBlockDesc; +} SDataSinkNode; + +typedef struct SDataDispatcherNode { + SDataSinkNode sink; +} SDataDispatcherNode; + +typedef struct SDataInserterNode { + SDataSinkNode sink; + int32_t numOfTables; + uint32_t size; + char *pData; +} SDataInserterNode; + +typedef struct SSubplan { + ENodeType type; + SSubplanId id; // unique id of the subplan + ESubplanType subplanType; + int32_t msgType; // message type for subplan, used to denote the send message type to vnode. + int32_t level; // the execution level of current subplan, starting from 0 in a top-down manner. + SQueryNodeAddr execNode; // for the scan/modify subplan, the optional execution node + SQueryNodeStat execNodeStat; // only for scan subplan + SNodeList* pChildren; // the datasource subplan,from which to fetch the result + SNodeList* pParents; // the data destination subplan, get data from current subplan + SPhysiNode* pNode; // physical plan of current subplan + SDataSinkNode* pDataSink; // data of the subplan flow into the datasink +} SSubplan; + +typedef struct SQueryPlan { + ENodeType type;; + uint64_t queryId; + int32_t numOfSubplans; + SNodeList* pSubplans; // Element is SNodeListNode. The execution level of subplan, starting from 0. +} SQueryPlan; + #ifdef __cplusplus } #endif diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 42f9310ef1d4221aba543651fdd9bcf8f278b18f..6a6d50809695f2edbc9a66825100dae86e00777e 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -21,6 +21,7 @@ extern "C" { #endif #include "nodes.h" +#include "tmsg.h" typedef struct SRawExprNode { ENodeType nodeType; @@ -73,6 +74,7 @@ typedef struct SValueNode { SExprNode node; // QUERY_NODE_VALUE char* literal; bool isDuration; + bool translate; union { bool b; int64_t i; @@ -122,6 +124,7 @@ struct STableMeta; typedef struct SRealTableNode { STableNode table; // QUERY_NODE_REAL_TABLE struct STableMeta* pMeta; + SVgroupsInfo* pVgroupList; } SRealTableNode; typedef struct STempTableNode { @@ -248,6 +251,29 @@ typedef enum ESqlClause { SQL_CLAUSE_ORDER_BY } ESqlClause; + +typedef enum { + PAYLOAD_TYPE_KV = 0, + PAYLOAD_TYPE_RAW = 1, +} EPayloadType; + +typedef struct SVgDataBlocks { + SVgroupInfo vg; + int32_t numOfTables; // number of tables in current submit block + uint32_t size; + char *pData; // SMsgDesc + SSubmitReq + SSubmitBlk + ... +} SVgDataBlocks; + +typedef struct SVnodeModifOpStmt { + ENodeType nodeType; + ENodeType sqlNodeType; + SArray* pDataBlocks; // data block for each vgroup, SArray. + int8_t schemaAttache; // denote if submit block is built with table schema or not + uint8_t payloadType; // EPayloadType. 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert + uint32_t insertType; // insert data from [file|sql statement| bound statement] + const char* sql; // current sql statement position +} SVnodeModifOpStmt; + void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext); void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext); diff --git a/include/libs/parser/parsenodes.h b/include/libs/parser/parsenodes.h deleted file mode 100644 index 0d209a7f4d579b834c50cb14808c20bd63576827..0000000000000000000000000000000000000000 --- a/include/libs/parser/parsenodes.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef _TD_PARSENODES_H_ -#define _TD_PARSENODES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "catalog.h" -#include "tcommon.h" -#include "function.h" -#include "tmsgtype.h" -#include "tname.h" -#include "tvariant.h" - -/** - * The first field of a node of any type is guaranteed to be the int16_t. - * Hence the type of any node can be gotten by casting it to SQueryNode. - */ -typedef struct SQueryNode { - int16_t type; -} SQueryNode; - -#define queryNodeType(nodeptr) (((const SQueryNode*)(nodeptr))->type) - -typedef struct SFieldInfo { - int16_t numOfOutput; // number of column in result - SField *final; - SArray *internalField; // SArray -} SFieldInfo; - -typedef struct SCond { - uint64_t uid; - int32_t len; // length of tag query condition data - char * cond; -} SCond; - -typedef struct SJoinNode { - uint64_t uid; - int16_t tagColId; - SArray* tsJoin; - SArray* tagJoin; -} SJoinNode; - -typedef struct SJoinInfo { - bool hasJoin; - SJoinNode *joinTables[TSDB_MAX_JOIN_TABLE_NUM]; -} SJoinInfo; - -typedef struct STagCond { - int16_t relType; // relation between tbname list and query condition, including : TK_AND or TK_OR - SCond tbnameCond; // tbname query condition, only support tbname query condition on one table - SJoinInfo joinInfo; // join condition, only support two tables join currently - SArray *pCond; // for different table, the query condition must be seperated -} STagCond; - -typedef struct STableMetaInfo { - STableMeta *pTableMeta; // table meta, cached in client side and acquired by name - SVgroupsInfo *vgroupList; - SName name; - char aliasName[TSDB_TABLE_NAME_LEN]; // alias name of table specified in query sql - SArray *tagColList; // SArray, involved tag columns -} STableMetaInfo; - -typedef struct SColumnIndex { - int16_t tableIndex; - int16_t columnIndex; - int16_t type; // normal column/tag/ user input constant column -} SColumnIndex; - -// select statement -typedef struct SQueryStmtInfo { - int16_t command; // the command may be different for each subclause, so keep it seperately. - uint32_t type; // query/insert type - STimeWindow window; // the whole query time window - SInterval interval; // tumble time window - SSessionWindow sessionWindow; // session time window - SStateWindow stateWindow; // state window query - SGroupbyExpr groupbyExpr; // groupby tags info - SArray * colList; // SArray - SFieldInfo fieldsInfo; - SArray** exprList; // SArray - SLimit limit; - SLimit slimit; - STagCond tagCond; - SArray * colCond; - SArray * order; - int16_t numOfTables; - int16_t curTableIdx; - STableMetaInfo **pTableMetaInfo; - struct STSBuf *tsBuf; - - int16_t fillType; // final result fill type - int64_t * fillVal; // default value for fill - int32_t numOfFillVal; // fill value size - - char * msg; // pointer to the pCmd->payload to keep error message temporarily - int64_t clauseLimit; // limit for current sub clause - - int64_t prjOffset; // offset value in the original sql expression, only applied at client side - int64_t vgroupLimit; // table limit in case of super table projection query + global order + limit - - int32_t udColumnId; // current user-defined constant output field column id, monotonically decreases from TSDB_UD_COLUMN_INDEX - int32_t bufLen; - char* buf; - SArray *pUdfInfo; - - struct SQueryStmtInfo *sibling; // sibling - SMultiFunctionsDesc info; - SArray *pDownstream; // SArray - int32_t havingFieldNum; - int32_t exprListLevelIndex; -} SQueryStmtInfo; - -typedef enum { - PAYLOAD_TYPE_KV = 0, - PAYLOAD_TYPE_RAW = 1, -} EPayloadType; - -typedef struct SVgDataBlocks { - SVgroupInfo vg; - int32_t numOfTables; // number of tables in current submit block - uint32_t size; - char *pData; // SMsgDesc + SSubmitReq + SSubmitBlk + ... -} SVgDataBlocks; - -typedef struct SVnodeModifOpStmtInfo { - int16_t nodeType; - SArray* pDataBlocks; // data block for each vgroup, SArray. - int8_t schemaAttache; // denote if submit block is built with table schema or not - uint8_t payloadType; // EPayloadType. 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert - uint32_t insertType; // insert data from [file|sql statement| bound statement] - const char* sql; // current sql statement position -} SVnodeModifOpStmtInfo; - -typedef struct SDclStmtInfo { - int16_t nodeType; - int16_t msgType; - SEpSet epSet; - char* pMsg; - int32_t msgLen; - void* pExtension; // todo remove it soon -} SDclStmtInfo; - -#ifdef __cplusplus -} -#endif - -#endif /*_TD_PARSENODES_H_*/ diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 1d193888c9c8ba5bc6348bcb4d34a6d68e4adb29..bf0c963059cf189a011a3cf0f10c4d53fb14999e 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -20,7 +20,7 @@ extern "C" { #endif -#include "parsenodes.h" +#include "querynodes.h" typedef struct SParseContext { uint64_t requestId; @@ -32,67 +32,30 @@ typedef struct SParseContext { size_t sqlLen; // length of the sql string char *pMsg; // extended error message if exists to help identifying the problem in sql statement. int32_t msgLen; // max length of the msg - struct SCatalog *pCatalog; } SParseContext; -/** - * Parse the sql statement and then return the SQueryStmtInfo as the result of bounded AST. - * @param pSql sql string - * @param length length of the sql string - * @param id operator id, generated by uuid generator - * @param msg extended error message if exists. - * @return error code - */ -int32_t qParseQuerySql(SParseContext* pContext, SQueryNode** pQueryNode); - -/** - * Return true if it is a ddl/dcl sql statement - * @param pQuery - * @return - */ -bool qIsDdlQuery(const SQueryNode* pQueryNode); - -/** - * Destroy logic query plan - * @param pQueryNode - */ -void qDestroyQuery(SQueryNode* pQueryNode); - -/** - * Convert a normal sql statement to only query tags information to enable that the subscribe client can be aware quickly of the true vgroup ids that - * involved in the subscribe procedure. - * @param pSql - * @param length - * @param pConvertSql - * @return - */ -int32_t qParserConvertSql(const char* pStr, size_t length, char** pConvertSql); - -void assignExprInfo(SExprInfo* dst, const SExprInfo* src); -void columnListCopy(SArray* dst, const SArray* src, uint64_t uid); -void columnListDestroy(SArray* pColumnList); - -void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel); -void dropOneLevelExprInfo(SArray* pExprInfo); - -typedef struct SSourceParam { - SArray *pExprNodeList; //Array - SArray *pColumnList; //Array - int32_t num; -} SSourceParam; - -SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, const char* funcName, SSourceParam* pSource, SSchema* pResSchema, int16_t interSize); -int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy); -int32_t copyAllExprInfo(SArray* dst, const SArray* src, bool deepcopy); -int32_t getExprFunctionLevel(const SQueryStmtInfo* pQueryInfo); - -STableMetaInfo* getMetaInfo(const SQueryStmtInfo* pQueryInfo, int32_t tableIndex); -SSchema *getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex); - -int32_t getNewResColId(); -void addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn); -SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema); +typedef struct SCmdMsgInfo { + int16_t msgType; + SEpSet epSet; + void* pMsg; + int32_t msgLen; + void* pExtension; // todo remove it soon +} SCmdMsgInfo; + +typedef struct SQuery { + bool directRpc; + bool haveResultSet; + SNode* pRoot; + int32_t numOfResCols; + SSchema* pResSchema; + SCmdMsgInfo* pCmdMsg; + int32_t msgType; +} SQuery; + +int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery); + +void qDestroyQuery(SQuery* pQueryNode); #ifdef __cplusplus } diff --git a/include/libs/planner/planner.h b/include/libs/planner/planner.h index 126cee390c9eed90d6620e88e339d5506d6b6998..07579e0a7dab8b63711e7598d725113851f1d729 100644 --- a/include/libs/planner/planner.h +++ b/include/libs/planner/planner.h @@ -20,192 +20,31 @@ extern "C" { #endif -#include "query.h" -#include "tmsg.h" -#include "tarray.h" -#include "trpc.h" +#include "plannodes.h" -#define QUERY_TYPE_MERGE 1 -#define QUERY_TYPE_PARTIAL 2 -#define QUERY_TYPE_SCAN 3 -#define QUERY_TYPE_MODIFY 4 - -enum OPERATOR_TYPE_E { - OP_Unknown, -#define INCLUDE_AS_ENUM -#include "plannerOp.h" -#undef INCLUDE_AS_ENUM - OP_TotalNum -}; - -enum DATASINK_TYPE_E { - DSINK_Unknown, - DSINK_Dispatch, - DSINK_Insert, - DSINK_TotalNum -}; - -struct SEpSet; -struct SQueryStmtInfo; - -typedef SSchema SSlotSchema; - -typedef struct SDataBlockSchema { - SSlotSchema *pSchema; - int32_t numOfCols; // number of columns - int32_t resultRowSize; - int16_t precision; -} SDataBlockSchema; - -typedef struct SQueryNodeBasicInfo { - int32_t type; // operator type - const char *name; // operator name -} SQueryNodeBasicInfo; - -typedef struct SDataSink { - SQueryNodeBasicInfo info; - SDataBlockSchema schema; -} SDataSink; - -typedef struct SDataDispatcher { - SDataSink sink; -} SDataDispatcher; - -typedef struct SDataInserter { - SDataSink sink; - int32_t numOfTables; - uint32_t size; - char *pData; -} SDataInserter; - -typedef struct SPhyNode { - SQueryNodeBasicInfo info; - SArray *pTargets; // target list to be computed or scanned at this node - SArray *pConditions; // implicitly-ANDed qual conditions - SDataBlockSchema targetSchema; - // children plan to generated result for current node to process - // in case of join, multiple plan nodes exist. - SArray *pChildren; - struct SPhyNode *pParent; -} SPhyNode; - -typedef struct SScanPhyNode { - SPhyNode node; - uint64_t uid; // unique id of the table - int8_t tableType; - int32_t order; // scan order: TSDB_ORDER_ASC|TSDB_ORDER_DESC - int32_t count; // repeat count - int32_t reverse; // reverse scan count -} SScanPhyNode; - -typedef SScanPhyNode SSystemTableScanPhyNode; -typedef SScanPhyNode STagScanPhyNode; - -typedef struct STableScanPhyNode { - SScanPhyNode scan; - uint8_t scanFlag; // denotes reversed scan of data or not - STimeWindow window; - SArray *pTagsConditions; // implicitly-ANDed tag qual conditions -} STableScanPhyNode; - -typedef STableScanPhyNode STableSeqScanPhyNode; - -typedef struct SProjectPhyNode { - SPhyNode node; -} SProjectPhyNode; - -typedef struct SDownstreamSource { - SQueryNodeAddr addr; - uint64_t taskId; - uint64_t schedId; -} SDownstreamSource; - -typedef struct SExchangePhyNode { - SPhyNode node; - uint64_t srcTemplateId; // template id of datasource suplans - SArray *pSrcEndPoints; // SArray, scheduler fill by calling qSetSuplanExecutionNode -} SExchangePhyNode; - -typedef enum EAggAlgo { - AGG_ALGO_PLAIN = 1, // simple agg across all input rows - AGG_ALGO_SORTED, // grouped agg, input must be sorted - AGG_ALGO_HASHED // grouped agg, use internal hashtable -} EAggAlgo; - -typedef enum EAggSplit { - AGG_SPLIT_PRE = 1, // first level agg, maybe don't need calculate the final result - AGG_SPLIT_FINAL // second level agg, must calculate the final result -} EAggSplit; - -typedef struct SAggPhyNode { - SPhyNode node; - EAggAlgo aggAlgo; // algorithm used by agg operator - EAggSplit aggSplit; // distributed splitting mode - SArray *pExprs; // SExprInfo list, these are expression list of group_by_clause and parameter expression of aggregate function - SArray *pGroupByList; // SColIndex list, but these must be column node -} SAggPhyNode; - -typedef struct SSubplanId { +typedef struct SPlanContext { uint64_t queryId; - uint64_t templateId; - uint64_t subplanId; -} SSubplanId; + int32_t acctId; + SNode* pAstRoot; +} SPlanContext; -typedef struct SSubplan { - SSubplanId id; // unique id of the subplan - int32_t type; // QUERY_TYPE_MERGE|QUERY_TYPE_PARTIAL|QUERY_TYPE_SCAN|QUERY_TYPE_MODIFY - int32_t msgType; // message type for subplan, used to denote the send message type to vnode. - int32_t level; // the execution level of current subplan, starting from 0 in a top-down manner. - SQueryNodeAddr execNode; // for the scan/modify subplan, the optional execution node - SArray *pChildren; // the datasource subplan,from which to fetch the result - SArray *pParents; // the data destination subplan, get data from current subplan - SPhyNode *pNode; // physical plan of current subplan - SDataSink *pDataSink; // data of the subplan flow into the datasink -} SSubplan; - -typedef struct SQueryDag { - uint64_t queryId; - int32_t numOfSubplans; - SArray *pSubplans; // SArray*>. The execution level of subplan, starting from 0. -} SQueryDag; - -struct SQueryNode; - - /** - * Create the physical plan for the query, according to the AST. - * @param pQueryInfo - * @param pDag - * @param requestId - * @return - */ - int32_t qCreateQueryDag(const struct SQueryNode* pNode, struct SQueryDag** pDag, SSchema** pResSchema, int32_t* numOfCols, SArray* pNodeList, uint64_t requestId); +// Create the physical plan for the query, according to the AST. +int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNodeList); // Set datasource of this subplan, multiple calls may be made to a subplan. -// @subplan subplan to be schedule -// @templateId templateId of a group of datasource subplans of this @subplan -// @ep one execution location of this group of datasource subplans -void qSetSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource); +// @pSubplan subplan to be schedule +// @groupId id of a group of datasource subplans of this @pSubplan +// @pSource one execution location of this group of datasource subplans +int32_t qSetSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId, SDownstreamSourceNode* pSource); -int32_t qExplainQuery(const struct SQueryNode* pQueryInfo, struct SEpSet* pQnode, char** str); - -/** - * Convert to subplan to string for the scheduler to send to the executor - */ -int32_t qSubPlanToString(const SSubplan* subplan, char** str, int32_t* len); +// Convert to subplan to string for the scheduler to send to the executor +int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen); +int32_t qStringToSubplan(const char* pStr, SSubplan** pSubplan); -int32_t qStringToSubplan(const char* str, SSubplan** subplan); - -void qDestroySubplan(SSubplan* pSubplan); - -/** - * Destroy the physical plan. - * @param pQueryPhyNode - * @return - */ -void qDestroyQueryDag(SQueryDag* pDag); +char* qQueryPlanToString(const SQueryPlan* pPlan); +SQueryPlan* qStringToQueryPlan(const char* pStr); -char* qDagToString(const SQueryDag* pDag); -SQueryDag* qStringToDag(const char* pStr); +void qDestroyQueryPlan(SQueryPlan* pPlan); #ifdef __cplusplus } diff --git a/include/libs/planner/plannerOp.h b/include/libs/planner/plannerOp.h deleted file mode 100644 index af8a7dccd45c2e4bc7370b6b077d4653943b4371..0000000000000000000000000000000000000000 --- a/include/libs/planner/plannerOp.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#if defined(INCLUDE_AS_ENUM) // enum define mode - #undef OP_ENUM_MACRO - #define OP_ENUM_MACRO(op) OP_##op, -#elif defined(INCLUDE_AS_NAME) // comment define mode - #undef OP_ENUM_MACRO - #define OP_ENUM_MACRO(op) #op, -#else - #error To use this include file, first define either INCLUDE_AS_ENUM or INCLUDE_AS_NAME -#endif - -OP_ENUM_MACRO(StreamScan) -OP_ENUM_MACRO(TableScan) -OP_ENUM_MACRO(TableSeqScan) -OP_ENUM_MACRO(TagScan) -OP_ENUM_MACRO(SystemTableScan) -OP_ENUM_MACRO(StreamBlockScan) -OP_ENUM_MACRO(Aggregate) -OP_ENUM_MACRO(Project) -// OP_ENUM_MACRO(Groupby) -OP_ENUM_MACRO(Limit) -OP_ENUM_MACRO(SLimit) -OP_ENUM_MACRO(TimeWindow) -OP_ENUM_MACRO(SessionWindow) -OP_ENUM_MACRO(StateWindow) -OP_ENUM_MACRO(Fill) -OP_ENUM_MACRO(MultiTableAggregate) -OP_ENUM_MACRO(MultiTableTimeInterval) -OP_ENUM_MACRO(Filter) -OP_ENUM_MACRO(Distinct) -OP_ENUM_MACRO(Join) -OP_ENUM_MACRO(AllTimeWindow) -OP_ENUM_MACRO(AllMultiTableTimeInterval) -OP_ENUM_MACRO(Order) -OP_ENUM_MACRO(Exchange) -OP_ENUM_MACRO(SortedMerge) - -//OP_ENUM_MACRO(TableScan) diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 5d5ab74ba9c73e1b57d0b9fc8d0367ccecfbf49a..c8df40aedcaa2333f7153cebb94954e4d0e63587 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -35,7 +35,6 @@ enum { JOB_TASK_STATUS_CANCELLING, JOB_TASK_STATUS_CANCELLED, JOB_TASK_STATUS_DROPPING, - JOB_TASK_STATUS_FREEING, }; enum { @@ -85,7 +84,8 @@ typedef struct STableMeta { typedef struct SDBVgInfo { int32_t vgVersion; int8_t hashMethod; - SHashObj* vgHash; // key:vgId, value:SVgroupInfo + int32_t numOfTable; // DB's table num, unit is TSDB_TABLE_NUM_UNIT + SHashObj *vgHash; //key:vgId, value:SVgroupInfo } SDBVgInfo; typedef struct SUseDbOutput { @@ -129,6 +129,11 @@ typedef struct SQueryNodeAddr { SEpSet epSet; } SQueryNodeAddr; + +typedef struct SQueryNodeStat { + int32_t tableNum; // vg table number, unit is TSDB_TABLE_NUM_UNIT +} SQueryNodeStat; + int32_t initTaskQueue(); int32_t cleanupTaskQueue(); diff --git a/include/libs/qworker/qworker.h b/include/libs/qworker/qworker.h index 5e3320ffdb0a1307123473157c767f16b9dc23d1..dd3103edf1baf4f161f7dd7781934c818a919059 100644 --- a/include/libs/qworker/qworker.h +++ b/include/libs/qworker/qworker.h @@ -72,6 +72,8 @@ int32_t qWorkerProcessCancelMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg); int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg); +int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg); + int32_t qWorkerProcessShowMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg); int32_t qWorkerProcessShowFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg); diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h index b2080cb65553765ae5c547d91a8762f531b9ff7c..56da9ece6fe8b5131d27fd47c81cc21888f4bf23 100644 --- a/include/libs/scheduler/scheduler.h +++ b/include/libs/scheduler/scheduler.h @@ -25,6 +25,7 @@ extern "C" { typedef struct SSchedulerCfg { uint32_t maxJobNum; + int32_t maxNodeTableNum; } SSchedulerCfg; typedef struct SQueryProfileSummary { @@ -70,7 +71,7 @@ int32_t schedulerInit(SSchedulerCfg *cfg); * @param nodeList Qnode/Vnode address list, element is SQueryNodeAddr * @return */ -int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, int64_t *pJob, const char* sql, SQueryResult *pRes); +int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryPlan* pDag, int64_t* pJob, const char* sql, SQueryResult *pRes); /** * Process the query job, generated according to the query physical plan. @@ -78,7 +79,7 @@ int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, int * @param pNodeList Qnode/Vnode address list, element is SQueryNodeAddr * @return */ -int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryDag* pDag, const char* sql, int64_t *pJob); +int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryPlan* pDag, const char* sql, int64_t *pJob); /** * Fetch query result from the remote query executor @@ -110,7 +111,7 @@ void schedulerDestroy(void); * @param pTasks SArray** * @return */ -int32_t schedulerConvertDagToTaskList(SQueryDag* pDag, SArray **pTasks); +int32_t schedulerConvertDagToTaskList(SQueryPlan* pDag, SArray **pTasks); /** * make one task info's multiple copies diff --git a/include/libs/sync/sync.h b/include/libs/sync/sync.h index fddf18c571f2c54f0cb9c79b98a4a173a4c55066..68ca9eff17acc03c0500997f51b3f7a3172a91c8 100644 --- a/include/libs/sync/sync.h +++ b/include/libs/sync/sync.h @@ -24,6 +24,7 @@ extern "C" { #include #include "taosdef.h" #include "trpc.h" +#include "wal.h" typedef uint64_t SyncNodeId; typedef int32_t SyncGroupId; @@ -31,9 +32,9 @@ typedef int64_t SyncIndex; typedef uint64_t SyncTerm; typedef enum { - TAOS_SYNC_STATE_FOLLOWER = 0, - TAOS_SYNC_STATE_CANDIDATE = 1, - TAOS_SYNC_STATE_LEADER = 2, + TAOS_SYNC_STATE_FOLLOWER = 100, + TAOS_SYNC_STATE_CANDIDATE = 101, + TAOS_SYNC_STATE_LEADER = 102, } ESyncState; typedef struct SSyncBuffer { @@ -87,25 +88,22 @@ typedef struct SSyncFSM { } SSyncFSM; +struct SSyncRaftEntry; +typedef struct SSyncRaftEntry SSyncRaftEntry; + // abstract definition of log store in raft // SWal implements it typedef struct SSyncLogStore { void* data; // append one log entry - int32_t (*appendEntry)(struct SSyncLogStore* pLogStore, SRpcMsg* pBuf); - - // get one log entry, user need to free pBuf->data - int32_t (*getEntry)(struct SSyncLogStore* pLogStore, SyncIndex index, SRpcMsg* pBuf); + int32_t (*appendEntry)(struct SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry); - // update log store commit index with "index" - int32_t (*updateCommitIndex)(struct SSyncLogStore* pLogStore, SyncIndex index); + // get one log entry, user need to free pEntry->pCont + SSyncRaftEntry* (*getEntry)(struct SSyncLogStore* pLogStore, SyncIndex index); - // truncate log with index, entries after the given index (>index) will be deleted - int32_t (*truncate)(struct SSyncLogStore* pLogStore, SyncIndex index); - - // return commit index of log - SyncIndex (*getCommitIndex)(struct SSyncLogStore* pLogStore); + // truncate log with index, entries after the given index (>=index) will be deleted + int32_t (*truncate)(struct SSyncLogStore* pLogStore, SyncIndex fromIndex); // return index of last entry SyncIndex (*getLastIndex)(struct SSyncLogStore* pLogStore); @@ -113,6 +111,12 @@ typedef struct SSyncLogStore { // return term of last entry SyncTerm (*getLastTerm)(struct SSyncLogStore* pLogStore); + // update log store commit index with "index" + int32_t (*updateCommitIndex)(struct SSyncLogStore* pLogStore, SyncIndex index); + + // return commit index of log + SyncIndex (*getCommitIndex)(struct SSyncLogStore* pLogStore); + } SSyncLogStore; // raft need to persist two variables in storage: currentTerm, voteFor @@ -134,6 +138,7 @@ typedef struct SSyncInfo { SyncGroupId vgId; SSyncCfg syncCfg; char path[TSDB_FILENAME_LEN]; + SWal* pWal; SSyncFSM* pFsm; void* rpcClient; @@ -152,7 +157,7 @@ void syncCleanUp(); int64_t syncStart(const SSyncInfo* pSyncInfo); void syncStop(int64_t rid); int32_t syncReconfig(int64_t rid, const SSyncCfg* pSyncCfg); -int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pBuf, bool isWeak); +int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pMsg, bool isWeak); ESyncState syncGetMyRole(int64_t rid); void syncGetNodesRole(int64_t rid, SNodesRole* pNodeRole); diff --git a/include/libs/transport/trpc.h b/include/libs/transport/trpc.h index 5e3860822ec161ef52eece2931b7c71dee4fb40d..8dfd736df6f3984f823b73d2703f154f68803afc 100644 --- a/include/libs/transport/trpc.h +++ b/include/libs/transport/trpc.h @@ -29,7 +29,6 @@ extern "C" { extern int tsRpcHeadSize; -typedef struct SRpcPush SRpcPush; typedef struct SRpcConnInfo { uint32_t clientIp; @@ -45,16 +44,8 @@ typedef struct SRpcMsg { int32_t code; void * handle; // rpc handle returned to app void * ahandle; // app handle set by client - int persist; // keep handle or not, default 0 - - SRpcPush *push; - } SRpcMsg; -typedef struct SRpcPush { - void *arg; - int (*callback)(void *arg, SRpcMsg *rpcMsg); -} SRpcPush; typedef struct SRpcInit { uint16_t localPort; // local port @@ -64,7 +55,6 @@ typedef struct SRpcInit { int8_t connType; // TAOS_CONN_UDP, TAOS_CONN_TCPC, TAOS_CONN_TCPS int idleTime; // milliseconds, 0 means idle timer is disabled - bool noPool; // create conn pool or not // the following is for client app ecurity only char *user; // user name char spi; // security parameter index @@ -81,12 +71,16 @@ typedef struct SRpcInit { // call back to keep conn or not bool (*pfp)(void *parent, tmsg_t msgType); + // to support Send messages multiple times on a link + // + void* (*mfp)(void *parent, tmsg_t msgType); + void *parent; } SRpcInit; int32_t rpcInit(); void rpcCleanup(); -void *rpcOpen(const SRpcInit *pRpc); +void * rpcOpen(const SRpcInit *pRpc); void rpcClose(void *); void * rpcMallocCont(int contLen); void rpcFreeCont(void *pCont); @@ -99,6 +93,12 @@ void rpcSendRecv(void *shandle, SEpSet *pEpSet, SRpcMsg *pReq, SRpcMsg *pRsp) int rpcReportProgress(void *pConn, char *pCont, int contLen); void rpcCancelRequest(int64_t rid); +// just release client conn to rpc instance, no close sock +void rpcReleaseHandle(void *handle); + +void rpcRefHandle(void *handle, int8_t type); +void rpcUnrefHandle(void *handle, int8_t type); + #ifdef __cplusplus } #endif diff --git a/include/os/os.h b/include/os/os.h index a58e798d381803bdf2b4e91bbba4865c6baee11d..fd272b15a308222cf980b92b56b86780e232b1fa 100644 --- a/include/os/os.h +++ b/include/os/os.h @@ -22,7 +22,22 @@ extern "C" { #include #include + +#if !defined(WINDOWS) +#include #include +#include +#include +#include +#include + +#include +#include +#include +#include + +#endif + #include #include #include @@ -30,8 +45,6 @@ extern "C" { #include #include #include -#include -#include #include #include #include @@ -43,16 +56,9 @@ extern "C" { #include #include #include -#include -#include -#include #include #include -#include -#include -#include -#include #include "osAtomic.h" #include "osDef.h" diff --git a/include/os/osDef.h b/include/os/osDef.h index 339bf13343a9b98d7fa9b3814bdb2a361b0b912c..fcc96c19b46eb51da82ea5fcc0d87b7a4b90d742 100644 --- a/include/os/osDef.h +++ b/include/os/osDef.h @@ -49,7 +49,7 @@ extern "C" { #endif -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#if defined(WINDOWS) char *stpcpy (char *dest, const char *src); char *stpncpy (char *dest, const char *src, size_t n); @@ -63,16 +63,46 @@ extern "C" { #define strtok_r strtok_s #define snprintf _snprintf #define in_addr_t unsigned long - #define socklen_t int +// #define socklen_t int - struct tm *localtime_r(const time_t *timep, struct tm *result); - char * strptime(const char *buf, const char *fmt, struct tm *tm); char * strsep(char **stringp, const char *delim); char * getpass(const char *prefix); char * strndup(const char *s, size_t n); - -#endif + int gettimeofday(struct timeval *ptv, void *pTimeZone); + // for send function in tsocket.c + #define MSG_NOSIGNAL 0 + #define SO_NO_CHECK 0x1234 + #define SOL_TCP 0x1234 + + #define SHUT_RDWR SD_BOTH + #define SHUT_RD SD_RECEIVE + #define SHUT_WR SD_SEND + + #define LOCK_EX 1 + #define LOCK_NB 2 + #define LOCK_UN 3 + + #ifndef PATH_MAX + #define PATH_MAX 256 + #endif + + typedef struct { + int we_wordc; + char *we_wordv[1]; + int we_offs; + char wordPos[1025]; + } wordexp_t; + int wordexp(char *words, wordexp_t *pwordexp, int flags); + void wordfree(wordexp_t *pwordexp); + + #define openlog(a, b, c) + #define closelog() + #define LOG_ERR 0 + #define LOG_INFO 1 + void syslog(int unused, const char *format, ...); +#endif // WINDOWS + #ifndef WINDOWS #ifndef O_BINARY #define O_BINARY 0 @@ -166,7 +196,7 @@ extern "C" { #define PRIzu "zu" #endif -#if defined(_TD_LINUX_64) || defined(_TD_LINUX_32) || defined(_TD_MIPS_64) || defined(_TD_ARM_32) || defined(_TD_ARM_64) || defined(_TD_DARWIN_64) +#if !defined(WINDOWS) #if defined(_TD_DARWIN_64) // MacOS #if !defined(_GNU_SOURCE) @@ -181,8 +211,7 @@ extern "C" { #endif #else // Windows -// #define setThreadName(name) -#define setThreadName(name) do { prctl(PR_SET_NAME, (name)); } while (0) + #define setThreadName(name) #endif #if defined(_WIN32) @@ -199,4 +228,4 @@ extern "C" { } #endif -#endif /*_TD_OS_DEF_H_*/ \ No newline at end of file +#endif /*_TD_OS_DEF_H_*/ diff --git a/include/os/osDir.h b/include/os/osDir.h index 223c6033526f5e213213a2a813552924256048ad..6cf28fb8789013c64440917b25ed86825782f753 100644 --- a/include/os/osDir.h +++ b/include/os/osDir.h @@ -16,10 +16,24 @@ #ifndef _TD_OS_DIR_H_ #define _TD_OS_DIR_H_ +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define opendir OPENDIR_FUNC_TAOS_FORBID + #define readdir READDIR_FUNC_TAOS_FORBID + #define closedir CLOSEDIR_FUNC_TAOS_FORBID + #define dirname DIRNAME_FUNC_TAOS_FORBID + #undef basename + #define basename BASENAME_FUNC_TAOS_FORBID +#endif + #ifdef __cplusplus extern "C" { #endif +typedef struct TdDir *TdDirPtr; +typedef struct TdDirEntry *TdDirEntryPtr; + + void taosRemoveDir(const char *dirname); bool taosDirExist(char *dirname); int32_t taosMkDir(const char *dirname); @@ -27,6 +41,14 @@ void taosRemoveOldFiles(const char *dirname, int32_t keepDays); int32_t taosExpandDir(const char *dirname, char *outname, int32_t maxlen); int32_t taosRealPath(char *dirname, int32_t maxlen); bool taosIsDir(const char *dirname); +char* taosDirName(char *dirname); +char* taosDirEntryBaseName(char *dirname); + +TdDirPtr taosOpenDir(const char *dirname); +TdDirEntryPtr taosReadDir(TdDirPtr pDir); +bool taosDirEntryIsDir(TdDirEntryPtr pDirEntry); +char* taosGetDirEntryName(TdDirEntryPtr pDirEntry); +int32_t taosCloseDir(TdDirPtr pDir); #ifdef __cplusplus } diff --git a/include/os/osFile.h b/include/os/osFile.h index 703ba196efb14ebdae7fe2070c0b640ff2dde52b..b0e97e7b54902eb9c05f13486b8c44b40e533b9c 100644 --- a/include/os/osFile.h +++ b/include/os/osFile.h @@ -22,6 +22,15 @@ extern "C" { #include "osSocket.h" +#if defined(WINDOWS) +typedef int32_t FileFd; +typedef SOCKET SocketFd; +#else +typedef int32_t FileFd; +typedef int32_t SocketFd; +#endif + +int64_t taosRead(FileFd fd, void *buf, int64_t count); // If the error is in a third-party library, place this header file under the third-party library header file. #ifndef ALLOW_FORBID_FUNC #define open OPEN_FUNC_TAOS_FORBID @@ -76,7 +85,13 @@ int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count); int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset); int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count); void taosFprintfFile(TdFilePtr pFile, const char *format, ...); + +#if defined(WINDOWS) +#define __restrict__ +#endif // WINDOWS + int64_t taosGetLineFile(TdFilePtr pFile, char ** __restrict__ ptrBuf); + int32_t taosEOFFile(TdFilePtr pFile); int64_t taosCloseFile(TdFilePtr *ppFile); diff --git a/include/os/osLocale.h b/include/os/osLocale.h index 6e313eb8cde14e67f56a9e8334239ca714b88afd..ddafd2e93c5f549beb30304d17d96dfe408ae518 100644 --- a/include/os/osLocale.h +++ b/include/os/osLocale.h @@ -17,12 +17,16 @@ #define _TD_OS_LOCALE_H_ #include "os.h" -#include "osString.h" #ifdef __cplusplus extern "C" { #endif +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define setlocale SETLOCALE_FUNC_TAOS_FORBID +#endif + char *taosCharsetReplace(char *charsetstr); void taosGetSystemLocale(char *outLocale, char *outCharset); void taosSetSystemLocale(const char *inLocale, const char *inCharSet); diff --git a/include/os/osRand.h b/include/os/osRand.h index 422ea92a71feabfae497e319879704af89bd655d..09e1f1b41d36dceac1530c961775c77ba6d20fdb 100644 --- a/include/os/osRand.h +++ b/include/os/osRand.h @@ -20,7 +20,16 @@ extern "C" { #endif +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define rand RAND_FUNC_TAOS_FORBID + #define srand SRAND_FUNC_TAOS_FORBID + #define rand_r RANDR_FUNC_TAOS_FORBID +#endif + +void taosSeedRand(uint32_t seed); uint32_t taosRand(void); +uint32_t taosRandR(uint32_t *pSeed); void taosRandStr(char* str, int32_t size); uint32_t taosSafeRand(void); diff --git a/include/os/osSemaphore.h b/include/os/osSemaphore.h index 7fb9a2202d38760e5f1c760fe9d7f8eaa4096f46..9904170d61f152f6cbc047f52c65d0deb960edb8 100644 --- a/include/os/osSemaphore.h +++ b/include/os/osSemaphore.h @@ -16,12 +16,13 @@ #ifndef _TD_OS_SEMPHONE_H_ #define _TD_OS_SEMPHONE_H_ -#include - #ifdef __cplusplus extern "C" { #endif +#include +#include + #if defined (_TD_DARWIN_64) typedef struct tsem_s *tsem_t; int tsem_init(tsem_t *sem, int pshared, unsigned int value); diff --git a/include/os/osSleep.h b/include/os/osSleep.h index 686bdd292e376f55182caea52189a678bfdc3b14..feb94729954e73cc74e1a6b33ec8621a9be10a44 100644 --- a/include/os/osSleep.h +++ b/include/os/osSleep.h @@ -20,7 +20,17 @@ extern "C" { #endif +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define Sleep SLEEP_FUNC_TAOS_FORBID + #define sleep SLEEP_FUNC_TAOS_FORBID + #define usleep USLEEP_FUNC_TAOS_FORBID + #define nanosleep NANOSLEEP_FUNC_TAOS_FORBID +#endif + +void taosSsleep(int32_t s); void taosMsleep(int32_t ms); +void taosUsleep(int32_t us); #ifdef __cplusplus } diff --git a/include/os/osSocket.h b/include/os/osSocket.h index da1a9651e924388b3a144d9717a898e8ee104809..3faed855bad7fa42e23ceac0133d870501926a45 100644 --- a/include/os/osSocket.h +++ b/include/os/osSocket.h @@ -21,10 +21,13 @@ #define socket SOCKET_FUNC_TAOS_FORBID #define bind BIND_FUNC_TAOS_FORBID #define listen LISTEN_FUNC_TAOS_FORBID - // #define accept ACCEPT_FUNC_TAOS_FORBID + #define accept ACCEPT_FUNC_TAOS_FORBID + #define epoll_create EPOLL_CREATE_FUNC_TAOS_FORBID + #define epoll_ctl EPOLL_CTL_FUNC_TAOS_FORBID + #define epoll_wait EPOLL_WAIT_FUNC_TAOS_FORBID #endif -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#if defined(WINDOWS) #include "winsock2.h" #include #include @@ -38,31 +41,6 @@ extern "C" { #endif -#define TAOS_EPOLL_WAIT_TIME 500 -typedef int32_t SOCKET; -typedef SOCKET EpollFd; -#define EpollClose(pollFd) taosCloseSocket(pollFd) - -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) -typedef SOCKET SocketFd; -#else -typedef int32_t SocketFd; -#endif - -int32_t taosSendto(SocketFd fd, void * msg, int len, unsigned int flags, const struct sockaddr * to, int tolen); -int32_t taosWriteSocket(SocketFd fd, void *msg, int len); -int32_t taosReadSocket(SocketFd fd, void *msg, int len); -int32_t taosCloseSocketNoCheck(SocketFd fd); -int32_t taosCloseSocket(SocketFd fd); -void taosShutDownSocketRD(SOCKET fd); -void taosShutDownSocketWR(SOCKET fd); -int32_t taosSetNonblocking(SOCKET sock, int32_t on); -int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t optlen); -int32_t taosGetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t *optlen); - -uint32_t taosInetAddr(const char *ipAddr); -const char *taosInetNtoa(struct in_addr ipInt); - #if (defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) #define htobe64 htonll #if defined(_TD_GO_DLL_) @@ -74,25 +52,54 @@ const char *taosInetNtoa(struct in_addr ipInt); #define htobe64 htonll #endif -int32_t taosReadn(SOCKET sock, char *buffer, int32_t len); -int32_t taosWriteMsg(SOCKET fd, void *ptr, int32_t nbytes); -int32_t taosReadMsg(SOCKET fd, void *ptr, int32_t nbytes); -int32_t taosNonblockwrite(SOCKET fd, char *ptr, int32_t nbytes); -int64_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len); -int32_t taosSetNonblocking(SOCKET sock, int32_t on); +#define TAOS_EPOLL_WAIT_TIME 500 + +typedef struct TdSocketServer *TdSocketServerPtr; +typedef struct TdSocket *TdSocketPtr; +typedef struct TdEpoll *TdEpollPtr; + +int32_t taosSendto(TdSocketPtr pSocket, void * msg, int len, unsigned int flags, const struct sockaddr * to, int tolen); +int32_t taosWriteSocket(TdSocketPtr pSocket, void *msg, int len); +int32_t taosReadSocket(TdSocketPtr pSocket, void *msg, int len); +int32_t taosReadFromSocket(TdSocketPtr pSocket, void *buf, int32_t len, int32_t flags, struct sockaddr *destAddr, socklen_t *addrLen); +int32_t taosCloseSocket(TdSocketPtr *ppSocket); +int32_t taosCloseSocketServer(TdSocketServerPtr *ppSocketServer); +int32_t taosShutDownSocketRD(TdSocketPtr pSocket); +int32_t taosShutDownSocketServerRD(TdSocketServerPtr pSocketServer); +int32_t taosShutDownSocketWR(TdSocketPtr pSocket); +int32_t taosShutDownSocketServerWR(TdSocketServerPtr pSocketServer); +int32_t taosShutDownSocketRDWR(TdSocketPtr pSocket); +int32_t taosShutDownSocketServerRDWR(TdSocketServerPtr pSocketServer); +int32_t taosSetNonblocking(TdSocketPtr pSocket, int32_t on); +int32_t taosSetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t optlen); +int32_t taosGetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t *optlen); +int32_t taosWriteMsg(TdSocketPtr pSocket, void *ptr, int32_t nbytes); +int32_t taosReadMsg(TdSocketPtr pSocket, void *ptr, int32_t nbytes); +int32_t taosNonblockwrite(TdSocketPtr pSocket, char *ptr, int32_t nbytes); +int64_t taosCopyFds(TdSocketPtr pSrcSocket, TdSocketPtr pDestSocket, int64_t len); -SOCKET taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); -SOCKET taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp); -SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port); -int32_t taosKeepTcpAlive(SOCKET sockFd); +TdSocketPtr taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); +TdSocketPtr taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp); +TdSocketServerPtr taosOpenTcpServerSocket(uint32_t ip, uint16_t port); +int32_t taosKeepTcpAlive(TdSocketPtr pSocket); +TdSocketPtr taosAcceptTcpConnectSocket(TdSocketServerPtr pServerSocket, struct sockaddr *destAddr, socklen_t *addrLen); -void taosBlockSIGPIPE(); +int32_t taosGetSocketName(TdSocketPtr pSocket,struct sockaddr *destAddr, socklen_t *addrLen); + +void taosBlockSIGPIPE(); uint32_t taosGetIpv4FromFqdn(const char *); int32_t taosGetFqdn(char *); void tinet_ntoa(char *ipstr, uint32_t ip); uint32_t ip2uint(const char *const ip_addr); -void taosIgnSIGPIPE(); -void taosSetMaskSIGPIPE(); +void taosIgnSIGPIPE(); +void taosSetMaskSIGPIPE(); +uint32_t taosInetAddr(const char *ipAddr); +const char *taosInetNtoa(struct in_addr ipInt); + +TdEpollPtr taosCreateEpoll(int32_t size); +int32_t taosCtlEpoll(TdEpollPtr pEpoll, int32_t epollOperate, TdSocketPtr pSocket, struct epoll_event *event); +int32_t taosWaitEpoll(TdEpollPtr pEpoll, struct epoll_event *event, int32_t maxEvents, int32_t timeout); +int32_t taosCloseEpoll(TdEpollPtr *ppEpoll); #ifdef __cplusplus } diff --git a/include/os/osSysinfo.h b/include/os/osSysinfo.h index 1ebad370b5d1d9dee443d105f7201cdb96fd4cd5..d7cf05a59464a867f09f046e44dd6c8face37dcc 100644 --- a/include/os/osSysinfo.h +++ b/include/os/osSysinfo.h @@ -33,6 +33,7 @@ typedef struct { SDiskSize size; } SDiskSpace; +bool taosCheckSystemIsSmallEnd(); void taosGetSystemInfo(); int32_t taosGetEmail(char *email, int32_t maxLen); int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen); @@ -46,12 +47,18 @@ int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize); int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes); int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes); -int32_t taosSystem(const char *cmd); void taosKillSystem(); int32_t taosGetSystemUUID(char *uid, int32_t uidlen); char *taosGetCmdlineByPID(int32_t pid); void taosSetCoreDump(bool enable); +#if defined(WINDOWS) + +#define _UTSNAME_LENGTH 65 +#define _UTSNAME_MACHINE_LENGTH _UTSNAME_LENGTH + +#endif // WINDOWS + typedef struct { char sysname[_UTSNAME_MACHINE_LENGTH]; char nodename[_UTSNAME_MACHINE_LENGTH]; diff --git a/include/os/osSystem.h b/include/os/osSystem.h index 8554c4ad12f8737aac63a1815b63acf9cf0f69ff..f130e9d8f19c76171c44361fc8676b10bc650080 100644 --- a/include/os/osSystem.h +++ b/include/os/osSystem.h @@ -20,11 +20,23 @@ extern "C" { #endif +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define popen POPEN_FUNC_TAOS_FORBID + #define pclose PCLOSE_FUNC_TAOS_FORBID + #define tcsetattr TCSETATTR_FUNC_TAOS_FORBID + #define tcgetattr TCGETATTR_FUNC_TAOS_FORBID +#endif + +int32_t taosSystem(const char *cmd, char *buf, int32_t bufSize); void* taosLoadDll(const char* filename); void* taosLoadSym(void* handle, char* name); void taosCloseDll(void* handle); int32_t taosSetConsoleEcho(bool on); +void setTerminalMode(); +int32_t getOldTerminalMode(); +void resetTerminalMode(); #ifdef __cplusplus } diff --git a/include/os/osTime.h b/include/os/osTime.h index 62ecd5477f4d27c0214140f014aa95fc8b5ef605..4904eb9b514ca349cffc1be2e1574d706a3ccf4d 100644 --- a/include/os/osTime.h +++ b/include/os/osTime.h @@ -20,7 +20,19 @@ extern "C" { #endif +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define strptime STRPTIME_FUNC_TAOS_FORBID + #define gettimeofday GETTIMEOFDAY_FUNC_TAOS_FORBID + #define localtime_s LOCALTIMES_FUNC_TAOS_FORBID + #define localtime_r LOCALTIMER_FUNC_TAOS_FORBID + #define time TIME_FUNC_TAOS_FORBID +#endif + #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + + #define CLOCK_REALTIME 0 + #ifdef _TD_GO_DLL_ #define MILLISECOND_PER_SECOND (1000LL) #else @@ -61,6 +73,9 @@ static FORCE_INLINE int64_t taosGetTimestampNs() { return (int64_t)systemTime.tv_sec * 1000000000L + (int64_t)systemTime.tv_nsec; } +char *taosStrpTime(const char *buf, const char *fmt, struct tm *tm); +struct tm *taosLocalTime(const time_t *timep, struct tm *result); + #ifdef __cplusplus } #endif diff --git a/include/os/osTimer.h b/include/os/osTimer.h index 4b5db895a2f4d190138c1c79c873336f163382e2..9040113b232e6b10cf73b960e636112f8e2edf01 100644 --- a/include/os/osTimer.h +++ b/include/os/osTimer.h @@ -20,6 +20,15 @@ extern "C" { #endif +// If the error is in a third-party library, place this header file under the third-party library header file. +#ifndef ALLOW_FORBID_FUNC + #define timer_create TIMER_CREATE_FUNC_TAOS_FORBID + #define timer_settime TIMER_SETTIME_FUNC_TAOS_FORBID + #define timer_delete TIMER_DELETE_FUNC_TAOS_FORBID + #define timeSetEvent TIMESETEVENT_SETTIME_FUNC_TAOS_FORBID + #define timeKillEvent TIMEKILLEVENT_SETTIME_FUNC_TAOS_FORBID +#endif + #define MSECONDS_PER_TICK 5 int32_t taosInitTimer(void (*callback)(int32_t), int32_t ms); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 56ad1eea3bd317a4344d1b7630d4b682a1aa5e5e..1c61d738b5d70f013f292ecaf03c70e4ceddb13b 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -353,6 +353,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_TDB_MESSED_MSG TAOS_DEF_ERROR_CODE(0, 0x0614) #define TSDB_CODE_TDB_IVLD_TAG_VAL TAOS_DEF_ERROR_CODE(0, 0x0615) #define TSDB_CODE_TDB_NO_CACHE_LAST_ROW TAOS_DEF_ERROR_CODE(0, 0x0616) +#define TSDB_CODE_TDB_NO_SMA_INDEX_IN_META TAOS_DEF_ERROR_CODE(0, 0x0617) // query #define TSDB_CODE_QRY_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0700) @@ -460,6 +461,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_SCH_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2502) //parser +#define TSDB_CODE_PAR_SYNTAX_ERROR TAOS_DEF_ERROR_CODE(0, 0x2600) #define TSDB_CODE_PAR_INVALID_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2601) #define TSDB_CODE_PAR_TABLE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x2602) #define TSDB_CODE_PAR_AMBIGUOUS_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2603) @@ -472,6 +474,13 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260A) #define TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260B) #define TSDB_CODE_PAR_NOT_SINGLE_GROUP TAOS_DEF_ERROR_CODE(0, 0x260C) +#define TSDB_CODE_PAR_TAGS_NOT_MATCHED TAOS_DEF_ERROR_CODE(0, 0x260D) +#define TSDB_CODE_PAR_INVALID_TAG_NAME TAOS_DEF_ERROR_CODE(0, 0x260E) +#define TSDB_CODE_PAR_INCOMPLETE_SQL TAOS_DEF_ERROR_CODE(0, 0x260F) +#define TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG TAOS_DEF_ERROR_CODE(0, 0x2610) +#define TSDB_CODE_PAR_PASSWD_EMPTY TAOS_DEF_ERROR_CODE(0, 0x2611) +#define TSDB_CODE_PAR_INVALID_PORT TAOS_DEF_ERROR_CODE(0, 0x2612) +#define TSDB_CODE_PAR_INVALID_ENDPOINT TAOS_DEF_ERROR_CODE(0, 0x2613) #ifdef __cplusplus } diff --git a/include/util/tdef.h b/include/util/tdef.h index ed88fa5535c24e6c66ea88c20e3e17e629091e66..a53b81894a360c410b80c269b8bf0572a6c29e47 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -207,7 +207,7 @@ typedef enum ELogicConditionType { #define TSDB_FUNC_TYPE_AGGREGATE 2 #define TSDB_FUNC_MAX_RETRIEVE 1024 -#define TSDB_INDEX_NAME_LEN 32 +#define TSDB_INDEX_NAME_LEN 33 // 32 + 1 '\0' #define TSDB_TYPE_STR_MAX_LEN 32 #define TSDB_TABLE_FNAME_LEN (TSDB_DB_FNAME_LEN + TSDB_TABLE_NAME_LEN + TSDB_NAME_DELIMITER_LEN) #define TSDB_TOPIC_FNAME_LEN TSDB_TABLE_FNAME_LEN @@ -345,6 +345,20 @@ typedef enum ELogicConditionType { #define TSDB_MAX_DB_QUORUM_OPTION 2 #define TSDB_DEFAULT_DB_QUORUM_OPTION 1 +#define TSDB_MIN_DB_TTL_OPTION 1 +#define TSDB_DEFAULT_DB_TTL_OPTION 0 + +#define TSDB_MIN_DB_SINGLE_STABLE_OPTION 0 +#define TSDB_MAX_DB_SINGLE_STABLE_OPTION 1 +#define TSDB_DEFAULT_DB_SINGLE_STABLE_OPTION 0 + +#define TSDB_MIN_DB_STREAM_MODE_OPTION 0 +#define TSDB_MAX_DB_STREAM_MODE_OPTION 1 +#define TSDB_DEFAULT_DB_STREAM_MODE_OPTION 0 + +#define TSDB_MAX_JOIN_TABLE_NUM 10 +#define TSDB_MAX_UNION_CLAUSE 5 + #define TSDB_MIN_DB_UPDATE 0 #define TSDB_MAX_DB_UPDATE 2 #define TSDB_DEFAULT_DB_UPDATE_OPTION 0 diff --git a/include/util/tjson.h b/include/util/tjson.h index 2d9f433ab2a89fc2f4613a50a81eb3c3bfe613c9..335ff0d4bada0ca1a4cdb89081171b915bf02664 100644 --- a/include/util/tjson.h +++ b/include/util/tjson.h @@ -54,10 +54,12 @@ typedef int32_t (*FToJson)(const void* pObj, SJson* pJson); int32_t tjsonAddObject(SJson* pJson, const char* pName, FToJson func, const void* pObj); int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj); +int32_t tjsonAddArray(SJson* pJson, const char* pName, FToJson func, const void* pArray, int32_t itemSize, int32_t num); typedef int32_t (*FToObject)(const SJson* pJson, void* pObj); int32_t tjsonToObject(const SJson* pJson, const char* pName, FToObject func, void* pObj); +int32_t tjsonToArray(const SJson* pJson, const char* pName, FToObject func, void* pArray, int32_t itemSize); char* tjsonToString(const SJson* pJson); char* tjsonToUnformattedString(const SJson* pJson); diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 3210c0c6de50889721279cebdf13c67d2e5474e5..a632337d4af61304b6cb9e3ebe3315367aaf0722 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -8,7 +8,7 @@ target_include_directories( target_link_libraries( taos INTERFACE api - PRIVATE os util common transport parser planner catalog scheduler function qcom + PRIVATE os util common transport nodes parser planner catalog scheduler function qcom ) if(${BUILD_TEST}) diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 0e1b564b03ea70f656800e0bfc4443f7a6620da1..321e8ab77bd5eadd0539acf6331b4394192784e9 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -163,13 +163,13 @@ typedef struct SShowReqInfo { } SShowReqInfo; typedef struct SRequestSendRecvBody { - tsem_t rspSem; // not used now - void* fp; - SShowReqInfo showInfo; // todo this attribute will be removed after the query framework being completed. - SDataBuf requestMsg; - int64_t queryJob; // query job, created according to sql query DAG. - struct SQueryDag* pDag; // the query dag, generated according to the sql statement. - SReqResultInfo resInfo; + tsem_t rspSem; // not used now + void* fp; + SShowReqInfo showInfo; // todo this attribute will be removed after the query framework being completed. + SDataBuf requestMsg; + int64_t queryJob; // query job, created according to sql query DAG. + struct SQueryPlan* pDag; // the query dag, generated according to the sql statement. + SReqResultInfo resInfo; } SRequestSendRecvBody; #define ERROR_MSG_BUF_DEFAULT_SIZE 512 @@ -228,7 +228,7 @@ void setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32_t int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj** pRequest); -int32_t parseSql(SRequestObj* pRequest, SQueryNode** pQuery); +int32_t parseSql(SRequestObj* pRequest, SQuery** pQuery); // --- heartbeat // global, called by mgmt diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c index 08285c9d26f923c7ebfb420e7221c182e728313d..525c5f9fb88503c9237cf6db24701fcf3ee03a23 100644 --- a/source/client/src/clientEnv.c +++ b/source/client/src/clientEnv.c @@ -72,8 +72,6 @@ static void deregisterRequest(SRequestObj *pRequest) { taosReleaseRef(clientConnRefPool, pTscObj->id); } - - // todo close the transporter properly void closeTransporter(STscObj *pTscObj) { if (pTscObj == NULL || pTscObj->pAppInfo->pTransporter == NULL) { @@ -184,7 +182,7 @@ static void doDestroyRequest(void *p) { tfree(pRequest->pInfo); doFreeReqResultInfo(&pRequest->body.resInfo); - qDestroyQueryDag(pRequest->body.pDag); + qDestroyQueryPlan(pRequest->body.pDag); if (pRequest->body.showInfo.pArray != NULL) { taosArrayDestroy(pRequest->body.showInfo.pArray); @@ -208,7 +206,7 @@ void taos_init_imp(void) { atexit(taos_cleanup); errno = TSDB_CODE_SUCCESS; - srand(taosGetTimestampSec()); + taosSeedRand(taosGetTimestampSec()); deltaToUtcInitOnce(); @@ -241,6 +239,7 @@ void taos_init_imp(void) { clientConnRefPool = taosOpenRef(200, destroyTscObj); clientReqRefPool = taosOpenRef(40960, doDestroyRequest); + // transDestroyBuffer(&conn->readBuf); taosGetAppName(appInfo.appName, NULL); pthread_mutex_init(&appInfo.mutex, NULL); diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c index b1e9de8000cbdbceed961d9d91a59dccda560d26..71634447196f640ee8fc5d4358876e15000c5534 100644 --- a/source/client/src/clientHb.c +++ b/source/client/src/clientHb.c @@ -224,6 +224,7 @@ int32_t hbGetExpiredDBInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, SCl SDbVgVersion *db = &dbs[i]; db->dbId = htobe64(db->dbId); db->vgVersion = htonl(db->vgVersion); + db->numOfTable = htonl(db->numOfTable); } SKv kv = { @@ -434,11 +435,11 @@ static int32_t hbCreateThread() { pthread_attr_init(&thAttr); pthread_attr_setdetachstate(&thAttr, PTHREAD_CREATE_JOINABLE); - if (pthread_create(&clientHbMgr.thread, &thAttr, hbThreadFunc, NULL) != 0) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } - pthread_attr_destroy(&thAttr); +// if (pthread_create(&clientHbMgr.thread, &thAttr, hbThreadFunc, NULL) != 0) { +// terrno = TAOS_SYSTEM_ERROR(errno); +// return -1; +// } +// pthread_attr_destroy(&thAttr); return 0; } @@ -449,7 +450,7 @@ static void hbStopThread() { } while (2 != atomic_load_8(&clientHbMgr.threadStop)) { - usleep(10); + taosUsleep(10); } tscDebug("hb thread stopped"); diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index e9febef7e2edb7a0aa050e7775a9018be26e6ac3..646b443fb748ccb3106fa87b25f8737d693594aa 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -139,7 +139,7 @@ int32_t buildRequest(STscObj* pTscObj, const char* sql, int sqlLen, SRequestObj* return TSDB_CODE_SUCCESS; } -int32_t parseSql(SRequestObj* pRequest, SQueryNode** pQuery) { +int32_t parseSql(SRequestObj* pRequest, SQuery** pQuery) { STscObj* pTscObj = pRequest->pTscObj; SParseContext cxt = { @@ -161,54 +161,41 @@ int32_t parseSql(SRequestObj* pRequest, SQueryNode** pQuery) { } code = qParseQuerySql(&cxt, pQuery); + if (TSDB_CODE_SUCCESS == code && ((*pQuery)->haveResultSet)) { + setResSchemaInfo(&pRequest->body.resInfo, (*pQuery)->pResSchema, (*pQuery)->numOfResCols); + } tfree(cxt.db); return code; } -int32_t execDdlQuery(SRequestObj* pRequest, SQueryNode* pQuery) { - SDclStmtInfo* pDcl = (SDclStmtInfo*)pQuery; - pRequest->type = pDcl->msgType; - pRequest->body.requestMsg = (SDataBuf){.pData = pDcl->pMsg, .len = pDcl->msgLen, .handle = NULL}; +int32_t execDdlQuery(SRequestObj* pRequest, SQuery* pQuery) { + SCmdMsgInfo* pMsgInfo = pQuery->pCmdMsg; + pRequest->type = pMsgInfo->msgType; + pRequest->body.requestMsg = (SDataBuf){.pData = pMsgInfo->pMsg, .len = pMsgInfo->msgLen, .handle = NULL}; + pMsgInfo->pMsg = NULL; // pMsg transferred to SMsgSendInfo management STscObj* pTscObj = pRequest->pTscObj; SMsgSendInfo* pSendMsg = buildMsgInfoImpl(pRequest); - int64_t transporterId = 0; - if (pDcl->msgType == TDMT_VND_CREATE_TABLE || pDcl->msgType == TDMT_VND_SHOW_TABLES) { - if (pDcl->msgType == TDMT_VND_SHOW_TABLES) { - SShowReqInfo* pShowReqInfo = &pRequest->body.showInfo; - if (pShowReqInfo->pArray == NULL) { - pShowReqInfo->currentIndex = 0; // set the first vnode/ then iterate the next vnode - pShowReqInfo->pArray = pDcl->pExtension; - } + if (pMsgInfo->msgType == TDMT_VND_SHOW_TABLES) { + SShowReqInfo* pShowReqInfo = &pRequest->body.showInfo; + if (pShowReqInfo->pArray == NULL) { + pShowReqInfo->currentIndex = 0; // set the first vnode/ then iterate the next vnode + pShowReqInfo->pArray = pMsgInfo->pExtension; } - asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pDcl->epSet, &transporterId, pSendMsg); - } else { - asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pDcl->epSet, &transporterId, pSendMsg); } + int64_t transporterId = 0; + asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &pMsgInfo->epSet, &transporterId, pSendMsg); tsem_wait(&pRequest->body.rspSem); return TSDB_CODE_SUCCESS; } -int32_t getPlan(SRequestObj* pRequest, SQueryNode* pQueryNode, SQueryDag** pDag, SArray* pNodeList) { - pRequest->type = pQueryNode->type; - - SSchema* pSchema = NULL; - int32_t numOfCols = 0; - int32_t code = qCreateQueryDag(pQueryNode, pDag, &pSchema, &numOfCols, pNodeList, pRequest->requestId); - if (code != 0) { - return code; - } - - if (pQueryNode->type == TSDB_SQL_SELECT) { - setResSchemaInfo(&pRequest->body.resInfo, pSchema, numOfCols); - pRequest->type = TDMT_VND_QUERY; - } - - tfree(pSchema); - return code; +int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArray* pNodeList) { + pRequest->type = pQuery->msgType; + SPlanContext cxt = { .queryId = pRequest->requestId, .pAstRoot = pQuery->pRoot, .acctId = pRequest->pTscObj->acctId }; + return qCreateQueryPlan(&cxt, pPlan, pNodeList); } void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols) { @@ -224,8 +211,10 @@ void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t } } -int32_t scheduleQuery(SRequestObj* pRequest, SQueryDag* pDag, SArray* pNodeList) { + +int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) { void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter; + SQueryResult res = {.code = 0, .numOfRows = 0, .msgSize = ERROR_MSG_BUF_DEFAULT_SIZE, .msg = pRequest->msgBuf}; int32_t code = schedulerExecJob(pTransporter, pNodeList, pDag, &pRequest->body.queryJob, pRequest->sqlstr, &res); if (code != TSDB_CODE_SUCCESS) { @@ -237,14 +226,14 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryDag* pDag, SArray* pNodeList) return pRequest->code; } - if (TSDB_SQL_INSERT == pRequest->type || TSDB_SQL_CREATE_TABLE == pRequest->type) { + if (TDMT_VND_SUBMIT == pRequest->type || TDMT_VND_CREATE_TABLE == pRequest->type) { pRequest->body.resInfo.numOfRows = res.numOfRows; - + if (pRequest->body.queryJob != 0) { schedulerFreeJob(pRequest->body.queryJob); } } - + pRequest->code = res.code; return pRequest->code; } @@ -258,24 +247,24 @@ TAOS_RES* taos_query_l(TAOS* taos, const char* sql, int sqlLen) { } SRequestObj* pRequest = NULL; - SQueryNode* pQueryNode = NULL; - SArray* pNodeList = taosArrayInit(4, sizeof(struct SQueryNodeAddr)); + SQuery* pQuery = NULL; + SArray* pNodeList = taosArrayInit(4, sizeof(struct SQueryNodeAddr)); terrno = TSDB_CODE_SUCCESS; CHECK_CODE_GOTO(buildRequest(pTscObj, sql, sqlLen, &pRequest), _return); - CHECK_CODE_GOTO(parseSql(pRequest, &pQueryNode), _return); + CHECK_CODE_GOTO(parseSql(pRequest, &pQuery), _return); - if (qIsDdlQuery(pQueryNode)) { - CHECK_CODE_GOTO(execDdlQuery(pRequest, pQueryNode), _return); + if (pQuery->directRpc) { + CHECK_CODE_GOTO(execDdlQuery(pRequest, pQuery), _return); } else { - CHECK_CODE_GOTO(getPlan(pRequest, pQueryNode, &pRequest->body.pDag, pNodeList), _return); + CHECK_CODE_GOTO(getPlan(pRequest, pQuery, &pRequest->body.pDag, pNodeList), _return); CHECK_CODE_GOTO(scheduleQuery(pRequest, pRequest->body.pDag, pNodeList), _return); pRequest->code = terrno; } _return: taosArrayDestroy(pNodeList); - qDestroyQuery(pQueryNode); + qDestroyQuery(pQuery); if (NULL != pRequest && TSDB_CODE_SUCCESS != terrno) { pRequest->code = terrno; } diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 5bcc287116d2de8a9f713f26cfdbed74c7a52fd9..09a0233e04a702c1122f79d8f989793233c8ea20 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -343,3 +343,77 @@ void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { // TODO } + +TAOS_SUB *taos_subscribe(TAOS *taos, int restart, const char* topic, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval) { + // TODO + return NULL; +} + +TAOS_RES *taos_consume(TAOS_SUB *tsub) { + // TODO + return NULL; +} + +void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) { + // TODO +} + +TAOS_STMT* taos_stmt_init(TAOS* taos) { + // TODO + return NULL; +} + +int taos_stmt_close(TAOS_STMT* stmt) { + // TODO + return -1; +} + +int taos_stmt_execute(TAOS_STMT* stmt) { + // TODO + return -1; +} + +char *taos_stmt_errstr(TAOS_STMT *stmt) { + // TODO + return NULL; +} + +int taos_stmt_affected_rows(TAOS_STMT* stmt) { + // TODO + return -1; +} + +TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int protocol, int precision) { + // TODO + return NULL; +} + +int taos_stmt_bind_param(TAOS_STMT* stmt, TAOS_BIND* bind) { + // TODO + return -1; +} + +int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { + // TODO + return -1; +} + +int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags) { + // TODO + return -1; +} + +int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) { + // TODO + return -1; +} + +int taos_stmt_add_batch(TAOS_STMT* stmt) { + // TODO + return -1; +} + +int taos_stmt_bind_param_batch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind) { + // TODO + return -1; +} diff --git a/source/client/src/tmq.c b/source/client/src/tmq.c index 197f2e37c53c8f783a7bd76e3fff459016334e94..846329f0f4d995d657f995e65b510ec4e11d0932 100644 --- a/source/client/src/tmq.c +++ b/source/client/src/tmq.c @@ -459,7 +459,7 @@ void tmq_conf_set_offset_commit_cb(tmq_conf_t* conf, tmq_commit_cb* cb) { conf-> TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, int sqlLen) { STscObj* pTscObj = (STscObj*)taos; SRequestObj* pRequest = NULL; - SQueryNode* pQueryNode = NULL; + SQuery* pQueryNode = NULL; char* pStr = NULL; terrno = TSDB_CODE_SUCCESS; @@ -482,7 +482,7 @@ TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, i } tscDebug("start to create topic, %s", topicName); - +#if 0 CHECK_CODE_GOTO(buildRequest(pTscObj, sql, sqlLen, &pRequest), _return); CHECK_CODE_GOTO(parseSql(pRequest, &pQueryNode), _return); @@ -538,7 +538,7 @@ TAOS_RES* tmq_create_topic(TAOS* taos, const char* topicName, const char* sql, i asyncSendMsgToServer(pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo); tsem_wait(&pRequest->body.rspSem); - +#endif _return: qDestroyQuery(pQueryNode); /*if (sendInfo != NULL) {*/ @@ -1146,13 +1146,13 @@ tmq_message_t* tmq_consumer_poll(tmq_t* tmq, int64_t blocking_time) { if (taosArrayGetSize(tmq->clientTopics) == 0) { tscDebug("consumer:%ld poll but not assigned", tmq->consumerId); /*printf("over1\n");*/ - usleep(blocking_time * 1000); + taosMsleep(blocking_time); return NULL; } SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, tmq->nextTopicIdx); if (taosArrayGetSize(pTopic->vgs) == 0) { /*printf("over2\n");*/ - usleep(blocking_time * 1000); + taosMsleep(blocking_time); return NULL; } @@ -1165,14 +1165,14 @@ tmq_message_t* tmq_consumer_poll(tmq_t* tmq, int64_t blocking_time) { SMqConsumeReq* pReq = tmqBuildConsumeReqImpl(tmq, blocking_time, pTopic, pVg); if (pReq == NULL) { ASSERT(false); - usleep(blocking_time * 1000); + taosMsleep(blocking_time); return NULL; } SMqPollCbParam* param = malloc(sizeof(SMqPollCbParam)); if (param == NULL) { ASSERT(false); - usleep(blocking_time * 1000); + taosMsleep(blocking_time); return NULL; } param->tmq = tmq; @@ -1204,7 +1204,7 @@ tmq_message_t* tmq_consumer_poll(tmq_t* tmq, int64_t blocking_time) { if (tmq_message == NULL) { if (beginVgIdx == pTopic->nextVgIdx) { - usleep(blocking_time * 1000); + taosMsleep(blocking_time); } else { continue; } diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index 7bba0935882bcac5b784dee40a6b4b8f24bc6ae9..1a155beb90c9eb1d14eebb0d465b837ba35501b2 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -53,7 +53,6 @@ TEST(testCase, driverInit_Test) { // taos_init(); } -#if 1 TEST(testCase, connect_Test) { // taos_options(TSDB_OPTION_CONFIGDIR, "/home/ubuntu/first/cfg"); @@ -564,20 +563,18 @@ TEST(testCase, insert_test) { taos_free_result(pRes); taos_close(pConn); } -#endif - TEST(testCase, projection_query_tables) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); - TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 2"); - if (taos_errno(pRes) != 0) { - printf("error in create db, reason:%s\n", taos_errstr(pRes)); - } - taos_free_result(pRes); +// TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 2"); +// if (taos_errno(pRes) != 0) { +// printf("error in create db, reason:%s\n", taos_errstr(pRes)); +// } +// taos_free_result(pRes); - pRes = taos_query(pConn, "use abc1"); + TAOS_RES* pRes = taos_query(pConn, "use abc1"); taos_free_result(pRes); pRes = taos_query(pConn, "create stable st1 (ts timestamp, k int) tags(a int)"); @@ -592,7 +589,7 @@ TEST(testCase, projection_query_tables) { } taos_free_result(pRes); - for(int32_t i = 0; i < 10000000; ++i) { + for(int32_t i = 0; i < 10000; ++i) { char sql[512] = {0}; sprintf(sql, "insert into tu values(now+%da, %d)", i, i); TAOS_RES* p = taos_query(pConn, sql); @@ -623,7 +620,6 @@ TEST(testCase, projection_query_tables) { taos_free_result(pRes); taos_close(pConn); } -#if 0 TEST(testCase, projection_query_stables) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); @@ -686,6 +682,5 @@ TEST(testCase, agg_query_tables) { taos_free_result(pRes); taos_close(pConn); } -#endif #pragma GCC diagnostic pop diff --git a/source/common/CMakeLists.txt b/source/common/CMakeLists.txt index 1e4ad95504e18dd2bf1dbc337f73156c8926e8c0..1344b5b58c4e3ae86d4a99ab9d6d56a391d0a87a 100644 --- a/source/common/CMakeLists.txt +++ b/source/common/CMakeLists.txt @@ -4,6 +4,10 @@ target_include_directories( common PUBLIC "${CMAKE_SOURCE_DIR}/include/common" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" +IF(${TD_WINDOWS}) + PRIVATE "${CMAKE_SOURCE_DIR}/contrib/pthread-win32" + PRIVATE "${CMAKE_SOURCE_DIR}/contrib/gnuregex" +ENDIF () ) target_link_libraries( common diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 5b7557b749cc1b7f1565fd5577758812f0642058..4070224ab83313f03c3821edf4945b090352f1cc 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -239,7 +239,7 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, co return numOfRow1 + numOfRow2; } -size_t colDataGetNumOfCols(const SSDataBlock* pBlock) { +size_t blockDataGetNumOfCols(const SSDataBlock* pBlock) { ASSERT(pBlock); size_t constantCols = (pBlock->pConstantList != NULL)? taosArrayGetSize(pBlock->pConstantList):0; @@ -247,7 +247,7 @@ size_t colDataGetNumOfCols(const SSDataBlock* pBlock) { return pBlock->info.numOfCols; } -size_t colDataGetNumOfRows(const SSDataBlock* pBlock) { +size_t blockDataGetNumOfRows(const SSDataBlock* pBlock) { return pBlock->info.rows; } diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index 26861e1ff8e7936cbed69ce8d36c344fcf96385e..f26f19f3b2b6c1bc122fac359442a5481b265bd7 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -1007,11 +1007,32 @@ int32_t tDeserializeSMCreateDropQSBNodeReq(void *buf, int32_t bufLen, SMCreateQn } int32_t tSerializeSDropDnodeReq(void *buf, int32_t bufLen, SDropDnodeReq *pReq) { - return tSerializeSMCreateDropQSBNodeReq(buf, bufLen, (SMCreateQnodeReq *)pReq); + SCoder encoder = {0}; + tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI32(&encoder, pReq->dnodeId) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->fqdn) < 0) return -1; + if (tEncodeI32(&encoder, pReq->port) < 0) return -1; + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tCoderClear(&encoder); + return tlen; } int32_t tDeserializeSDropDnodeReq(void *buf, int32_t bufLen, SDropDnodeReq *pReq) { - return tDeserializeSMCreateDropQSBNodeReq(buf, bufLen, (SMCreateQnodeReq *)pReq); + SCoder decoder = {0}; + tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->dnodeId) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->fqdn) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->port) < 0) return -1; + tEndDecode(&decoder); + + tCoderClear(&decoder); + return 0; } int32_t tSerializeSMCreateDropMnodeReq(void *buf, int32_t bufLen, SMCreateMnodeReq *pReq) { @@ -1423,6 +1444,7 @@ int32_t tSerializeSUseDbReq(void *buf, int32_t bufLen, SUseDbReq *pReq) { if (tEncodeCStr(&encoder, pReq->db) < 0) return -1; if (tEncodeI64(&encoder, pReq->dbId) < 0) return -1; if (tEncodeI32(&encoder, pReq->vgVersion) < 0) return -1; + if (tEncodeI32(&encoder, pReq->numOfTable) < 0) return -1; tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -1438,12 +1460,77 @@ int32_t tDeserializeSUseDbReq(void *buf, int32_t bufLen, SUseDbReq *pReq) { if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1; if (tDecodeI64(&decoder, &pReq->dbId) < 0) return -1; if (tDecodeI32(&decoder, &pReq->vgVersion) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->numOfTable) < 0) return -1; + tEndDecode(&decoder); + + tCoderClear(&decoder); + return 0; +} + + +int32_t tSerializeSQnodeListReq(void* buf, int32_t bufLen, SQnodeListReq* pReq) { + SCoder encoder = {0}; + tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI32(&encoder, pReq->rowNum) < 0) return -1; + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tCoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSQnodeListReq(void *buf, int32_t bufLen, SQnodeListReq *pReq) { + SCoder decoder = {0}; + tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->rowNum) < 0) return -1; tEndDecode(&decoder); tCoderClear(&decoder); return 0; } +int32_t tSerializeSQnodeListRsp(void *buf, int32_t bufLen, SQnodeListRsp *pRsp) { + SCoder encoder = {0}; + tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); + + if (tStartEncode(&encoder) < 0) return -1; + int32_t num = taosArrayGetSize(pRsp->epSetList); + if (tEncodeI32(&encoder, num) < 0) return -1; + for (int32_t i = 0; i < num; ++i) { + SEpSet *epSet = taosArrayGet(pRsp->epSetList, i); + if (tEncodeSEpSet(&encoder, epSet) < 0) return -1; + } + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tCoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSQnodeListRsp(void *buf, int32_t bufLen, SQnodeListRsp *pRsp) { + SCoder decoder = {0}; + tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); + + if (tStartDecode(&decoder) < 0) return -1; + int32_t num = 0; + if (tDecodeI32(&decoder, &num) < 0) return -1; + pRsp->epSetList = taosArrayInit(num, sizeof(SEpSet)); + if (NULL == pRsp->epSetList) return -1; + for (int32_t i = 0; i < num; ++i) { + if (tDecodeSEpSet(&decoder, TARRAY_GET_ELEM(pRsp->epSetList, i)) < 0) return -1; + } + tEndDecode(&decoder); + + tCoderClear(&decoder); + return 0; +} + +void tFreeSQnodeListRsp(SQnodeListRsp *pRsp) { taosArrayDestroy(pRsp->epSetList); } + int32_t tSerializeSSyncDbReq(void *buf, int32_t bufLen, SSyncDbReq *pReq) { SCoder encoder = {0}; tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); @@ -1482,6 +1569,7 @@ static int32_t tSerializeSUseDbRspImp(SCoder *pEncoder, SUseDbRsp *pRsp) { if (tEncodeU32(pEncoder, pVgInfo->hashBegin) < 0) return -1; if (tEncodeU32(pEncoder, pVgInfo->hashEnd) < 0) return -1; if (tEncodeSEpSet(pEncoder, &pVgInfo->epSet) < 0) return -1; + if (tEncodeI32(pEncoder, pVgInfo->numOfTable) < 0) return -1; } return 0; @@ -1542,6 +1630,7 @@ int32_t tDeserializeSUseDbRspImp(SCoder *pDecoder, SUseDbRsp *pRsp) { if (tDecodeU32(pDecoder, &vgInfo.hashBegin) < 0) return -1; if (tDecodeU32(pDecoder, &vgInfo.hashEnd) < 0) return -1; if (tDecodeSEpSet(pDecoder, &vgInfo.epSet) < 0) return -1; + if (tDecodeI32(pDecoder, &vgInfo.numOfTable) < 0) return -1; taosArrayPush(pRsp->pVgroupInfos, &vgInfo); } @@ -2391,6 +2480,149 @@ int32_t tDecodeSMqCMCommitOffsetReq(SCoder *decoder, SMqCMCommitOffsetReq *pReq) return 0; } +int32_t tSerializeSSchedulerHbReq(void *buf, int32_t bufLen, SSchedulerHbReq *pReq) { + int32_t headLen = sizeof(SMsgHead); + if (buf != NULL) { + buf = (char *)buf + headLen; + bufLen -= headLen; + } + + SCoder encoder = {0}; + tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeU64(&encoder, pReq->sId) < 0) return -1; + if (tEncodeI32(&encoder, pReq->epId.nodeId) < 0) return -1; + if (tEncodeU16(&encoder, pReq->epId.ep.port) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->epId.ep.fqdn) < 0) return -1; + if (pReq->taskAction) { + int32_t num = taosArrayGetSize(pReq->taskAction); + if (tEncodeI32(&encoder, num) < 0) return -1; + for (int32_t i = 0; i < num; ++i) { + STaskAction *action = taosArrayGet(pReq->taskAction, i); + if (tEncodeU64(&encoder, action->queryId) < 0) return -1; + if (tEncodeU64(&encoder, action->taskId) < 0) return -1; + if (tEncodeI8(&encoder, action->action) < 0) return -1; + } + } else { + if (tEncodeI32(&encoder, 0) < 0) return -1; + } + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tCoderClear(&encoder); + + if (buf != NULL) { + SMsgHead *pHead = (SMsgHead *)((char *)buf - headLen); + pHead->vgId = htonl(pReq->header.vgId); + pHead->contLen = htonl(tlen + headLen); + } + + return tlen + headLen; +} + +int32_t tDeserializeSSchedulerHbReq(void *buf, int32_t bufLen, SSchedulerHbReq *pReq) { + int32_t headLen = sizeof(SMsgHead); + + SMsgHead *pHead = buf; + pHead->vgId = pReq->header.vgId; + pHead->contLen = pReq->header.contLen; + + SCoder decoder = {0}; + tCoderInit(&decoder, TD_LITTLE_ENDIAN, (char *)buf + headLen, bufLen - headLen, TD_DECODER); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeU64(&decoder, &pReq->sId) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->epId.nodeId) < 0) return -1; + if (tDecodeU16(&decoder, &pReq->epId.ep.port) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->epId.ep.fqdn) < 0) return -1; + int32_t num = 0; + if (tDecodeI32(&decoder, &num) < 0) return -1; + if (num > 0) { + pReq->taskAction = taosArrayInit(num, sizeof(STaskStatus)); + if (NULL == pReq->taskAction) return -1; + for (int32_t i = 0; i < num; ++i) { + STaskAction action = {0}; + if (tDecodeU64(&decoder, &action.queryId) < 0) return -1; + if (tDecodeU64(&decoder, &action.taskId) < 0) return -1; + if (tDecodeI8(&decoder, &action.action) < 0) return -1; + taosArrayPush(pReq->taskAction, &action); + } + } else { + pReq->taskAction = NULL; + } + tEndDecode(&decoder); + + tCoderClear(&decoder); + return 0; +} + +void tFreeSSchedulerHbReq(SSchedulerHbReq *pReq) { taosArrayDestroy(pReq->taskAction); } + + + +int32_t tSerializeSSchedulerHbRsp(void *buf, int32_t bufLen, SSchedulerHbRsp *pRsp) { + SCoder encoder = {0}; + tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeU64(&encoder, pRsp->seqId) < 0) return -1; + if (tEncodeI32(&encoder, pRsp->epId.nodeId) < 0) return -1; + if (tEncodeU16(&encoder, pRsp->epId.ep.port) < 0) return -1; + if (tEncodeCStr(&encoder, pRsp->epId.ep.fqdn) < 0) return -1; + if (pRsp->taskStatus) { + int32_t num = taosArrayGetSize(pRsp->taskStatus); + if (tEncodeI32(&encoder, num) < 0) return -1; + for (int32_t i = 0; i < num; ++i) { + STaskStatus *status = taosArrayGet(pRsp->taskStatus, i); + if (tEncodeU64(&encoder, status->queryId) < 0) return -1; + if (tEncodeU64(&encoder, status->taskId) < 0) return -1; + if (tEncodeI64(&encoder, status->refId) < 0) return -1; + if (tEncodeI8(&encoder, status->status) < 0) return -1; + } + } else { + if (tEncodeI32(&encoder, 0) < 0) return -1; + } + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tCoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSSchedulerHbRsp(void *buf, int32_t bufLen, SSchedulerHbRsp *pRsp) { + SCoder decoder = {0}; + tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeU64(&decoder, &pRsp->seqId) < 0) return -1; + if (tDecodeI32(&decoder, &pRsp->epId.nodeId) < 0) return -1; + if (tDecodeU16(&decoder, &pRsp->epId.ep.port) < 0) return -1; + if (tDecodeCStrTo(&decoder, pRsp->epId.ep.fqdn) < 0) return -1; + int32_t num = 0; + if (tDecodeI32(&decoder, &num) < 0) return -1; + if (num > 0) { + pRsp->taskStatus = taosArrayInit(num, sizeof(STaskStatus)); + if (NULL == pRsp->taskStatus) return -1; + for (int32_t i = 0; i < num; ++i) { + STaskStatus status = {0}; + if (tDecodeU64(&decoder, &status.queryId) < 0) return -1; + if (tDecodeU64(&decoder, &status.taskId) < 0) return -1; + if (tDecodeI64(&decoder, &status.refId) < 0) return -1; + if (tDecodeI8(&decoder, &status.status) < 0) return -1; + taosArrayPush(pRsp->taskStatus, &status); + } + } else { + pRsp->taskStatus = NULL; + } + tEndDecode(&decoder); + + tCoderClear(&decoder); + return 0; +} + +void tFreeSSchedulerHbRsp(SSchedulerHbRsp *pRsp) { taosArrayDestroy(pRsp->taskStatus); } + int32_t tSerializeSVCreateTSmaReq(void **buf, SVCreateTSmaReq *pReq) { int32_t tlen = 0; diff --git a/source/common/src/tname.c b/source/common/src/tname.c index fb77417cacada36969672621fa78daff8ed29ebb..a97792de663ae25600ae07a9c01f7bea19888eaa 100644 --- a/source/common/src/tname.c +++ b/source/common/src/tname.c @@ -61,7 +61,7 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, in } struct tm tm; time_t t = (time_t)start; - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index 7a318c2eb8debb2857787dec5c97662b949c3183..22c10f62b4ee11df24af06b8131b4dde89e9be27 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -69,7 +69,7 @@ static int64_t m_deltaUtc = 0; void deltaToUtcInitOnce() { struct tm tm = {0}; - (void)strptime("1970-01-01 00:00:00", (const char*)("%Y-%m-%d %H:%M:%S"), &tm); + (void)taosStrpTime("1970-01-01 00:00:00", (const char*)("%Y-%m-%d %H:%M:%S"), &tm); m_deltaUtc = (int64_t)mktime(&tm); // printf("====delta:%lld\n\n", seconds); } @@ -236,9 +236,9 @@ int32_t parseTimeWithTz(const char* timestr, int64_t* time, int32_t timePrec, ch char* str; if (delim == 'T') { - str = strptime(timestr, "%Y-%m-%dT%H:%M:%S", &tm); + str = taosStrpTime(timestr, "%Y-%m-%dT%H:%M:%S", &tm); } else if (delim == 0) { - str = strptime(timestr, "%Y-%m-%d %H:%M:%S", &tm); + str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm); } else { str = NULL; } @@ -303,7 +303,7 @@ int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec) { *time = 0; struct tm tm = {0}; - char* str = strptime(timestr, "%Y-%m-%d %H:%M:%S", &tm); + char* str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm); if (str == NULL) { return -1; } @@ -338,7 +338,7 @@ int32_t parseLocaltimeDst(char* timestr, int64_t* time, int32_t timePrec) { struct tm tm = {0}; tm.tm_isdst = -1; - char* str = strptime(timestr, "%Y-%m-%d %H:%M:%S", &tm); + char* str = taosStrpTime(timestr, "%Y-%m-%d %H:%M:%S", &tm); if (str == NULL) { return -1; } @@ -466,7 +466,7 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) { struct tm tm; time_t tt = (time_t)(t / TSDB_TICK_PER_SECOND(precision)); - localtime_r(&tt, &tm); + taosLocalTime(&tt, &tm); int32_t mon = tm.tm_year * 12 + tm.tm_mon + (int32_t)duration; tm.tm_year = mon / 12; tm.tm_mon = mon % 12; @@ -489,11 +489,11 @@ int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char struct tm tm; time_t t = (time_t)skey; - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); int32_t smon = tm.tm_year * 12 + tm.tm_mon; t = (time_t)ekey; - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); int32_t emon = tm.tm_year * 12 + tm.tm_mon; if (unit == 'y') { @@ -514,7 +514,7 @@ int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precisio start /= (int64_t)(TSDB_TICK_PER_SECOND(precision)); struct tm tm; time_t tt = (time_t)start; - localtime_r(&tt, &tm); + taosLocalTime(&tt, &tm); tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; @@ -597,13 +597,13 @@ const char* fmtts(int64_t ts) { if (ts > -62135625943 && ts < 32503651200) { time_t t = (time_t)ts; - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); pos += strftime(buf + pos, sizeof(buf), "s=%Y-%m-%d %H:%M:%S", &tm); } if (ts > -62135625943000 && ts < 32503651200000) { time_t t = (time_t)(ts / 1000); - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); if (pos > 0) { buf[pos++] = ' '; buf[pos++] = '|'; @@ -615,7 +615,7 @@ const char* fmtts(int64_t ts) { { time_t t = (time_t)(ts / 1000000); - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); if (pos > 0) { buf[pos++] = ' '; buf[pos++] = '|'; diff --git a/source/common/src/tvariant.c b/source/common/src/tvariant.c index e885d842d77442edc72a83b86458770001b52a06..af6152d3f437ba673d9f7969101c6631ffa4eb7c 100644 --- a/source/common/src/tvariant.c +++ b/source/common/src/tvariant.c @@ -94,11 +94,11 @@ void taosVariantCreate(SVariant *pVar, const char *z, int32_t n, int32_t type) { bool sign = true; int32_t base = 10; - if (type == TK_HEX) { + if (type == TK_NK_HEX) { base = 16; - } else if (type == TK_OCT) { + } else if (type == TK_NK_OCT) { base = 8; - } else if (type == TK_BIN) { + } else if (type == TK_NK_BIN) { base = 2; } diff --git a/source/common/test/commonTests.cpp b/source/common/test/commonTests.cpp index 7d54e5150c6c86b0bb909e7e8962ca36700997d5..d5fb61929a94109331e955e492cb3333b09c961a 100644 --- a/source/common/test/commonTests.cpp +++ b/source/common/test/commonTests.cpp @@ -160,8 +160,8 @@ TEST(testCase, Datablock_test) { printf("binary column length:%d\n", *(int32_t*) p1->pData); - ASSERT_EQ(colDataGetNumOfCols(b), 2); - ASSERT_EQ(colDataGetNumOfRows(b), 40); + ASSERT_EQ(blockDataGetNumOfCols(b), 2); + ASSERT_EQ(blockDataGetNumOfRows(b), 40); char* pData = colDataGetData(p1, 3); printf("the second row of binary:%s, length:%d\n", (char*)varDataVal(pData), varDataLen(pData)); diff --git a/source/dnode/mgmt/daemon/src/dmnMain.c b/source/dnode/mgmt/daemon/src/dmnMain.c index df705898ca4532759ff083810f98546f2af206f8..7ba272453ca247600024411c106af17a1dc6cd25 100644 --- a/source/dnode/mgmt/daemon/src/dmnMain.c +++ b/source/dnode/mgmt/daemon/src/dmnMain.c @@ -97,6 +97,11 @@ int32_t dmnRunDnode() { } int main(int argc, char const *argv[]) { + if (!taosCheckSystemIsSmallEnd()) { + uError("TDengine does not run on non-small-end machines."); + return -1; + } + if (dmnParseOption(argc, argv) != 0) { return -1; } diff --git a/source/dnode/mgmt/impl/src/dndTransport.c b/source/dnode/mgmt/impl/src/dndTransport.c index 157bad26a6a33493920e1cbb3875f91ffbca74ec..15db36477d27f845bf4ca3bb1d03d9050c911f38 100644 --- a/source/dnode/mgmt/impl/src/dndTransport.c +++ b/source/dnode/mgmt/impl/src/dndTransport.c @@ -25,8 +25,8 @@ #include "dndMnode.h" #include "dndVnodes.h" -#define INTERNAL_USER "_dnd" -#define INTERNAL_CKEY "_key" +#define INTERNAL_USER "_dnd" +#define INTERNAL_CKEY "_key" #define INTERNAL_SECRET "_pwd" static void dndInitMsgFp(STransMgmt *pMgmt) { @@ -152,10 +152,11 @@ static void dndInitMsgFp(STransMgmt *pMgmt) { pMgmt->msgFp[TMSG_INDEX(TDMT_VND_MQ_REB)] = dndProcessVnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_VND_MQ_SET_CUR)] = dndProcessVnodeFetchMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_VND_CONSUME)] = dndProcessVnodeFetchMsg; + pMgmt->msgFp[TMSG_INDEX(TDMT_VND_QUERY_HEARTBEAT)] = dndProcessVnodeFetchMsg; } static void dndProcessResponse(void *parent, SRpcMsg *pRsp, SEpSet *pEpSet) { - SDnode *pDnode = parent; + SDnode * pDnode = parent; STransMgmt *pMgmt = &pDnode->tmgmt; tmsg_t msgType = pRsp->msgType; @@ -193,7 +194,6 @@ static int32_t dndInitClient(SDnode *pDnode) { rpcInit.ckey = INTERNAL_CKEY; rpcInit.spi = 1; rpcInit.parent = pDnode; - rpcInit.noPool = true; char pass[TSDB_PASSWORD_LEN + 1] = {0}; taosEncryptPass_c((uint8_t *)(INTERNAL_SECRET), strlen(INTERNAL_SECRET), pass); @@ -219,7 +219,7 @@ static void dndCleanupClient(SDnode *pDnode) { } static void dndProcessRequest(void *param, SRpcMsg *pReq, SEpSet *pEpSet) { - SDnode *pDnode = param; + SDnode * pDnode = param; STransMgmt *pMgmt = &pDnode->tmgmt; tmsg_t msgType = pReq->msgType; @@ -313,7 +313,7 @@ static int32_t dndRetrieveUserAuthInfo(void *parent, char *user, char *spi, char SAuthReq authReq = {0}; tstrncpy(authReq.user, user, TSDB_USER_LEN); int32_t contLen = tSerializeSAuthReq(NULL, 0, &authReq); - void *pReq = rpcMallocCont(contLen); + void * pReq = rpcMallocCont(contLen); tSerializeSAuthReq(pReq, contLen, &authReq); SRpcMsg rpcMsg = {.pCont = pReq, .contLen = contLen, .msgType = TDMT_MND_AUTH, .ahandle = (void *)9528}; diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index 490a63333f927d9d72f677b949cd9d14c6241b98..9ed6104140ab0b475e27daf60311a30a383b4e88 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -354,6 +354,23 @@ typedef struct { char payload[]; } SShowObj; +typedef struct { + int64_t id; + int8_t type; + int8_t replica; + int16_t numOfColumns; + int32_t rowSize; + int32_t numOfRows; + int32_t numOfReads; + int32_t payloadLen; + void* pIter; + SMnode* pMnode; + char db[TSDB_DB_FNAME_LEN]; + int16_t offset[TSDB_MAX_COLUMNS]; + int32_t bytes[TSDB_MAX_COLUMNS]; + char payload[]; +} SSysTableRetrieveObj; + typedef struct { int32_t vgId; // -1 for unassigned int32_t status; diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index 9cde9201eda26dd07d23e89244e68214d2c6c7f0..a17a45d46a970f960a497448bca262b975aefdd2 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -885,6 +885,29 @@ DROP_DB_OVER: return code; } +void mndGetDBTableNum(SDbObj *pDb, SMnode *pMnode, int32_t *num) { + int32_t vindex = 0; + SSdb *pSdb = pMnode->pSdb; + + void *pIter = NULL; + while (vindex < pDb->cfg.numOfVgroups) { + SVgObj *pVgroup = NULL; + pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup); + if (pIter == NULL) break; + + if (pVgroup->dbUid == pDb->uid) { + *num += pVgroup->numOfTables / TSDB_TABLE_NUM_UNIT; + + vindex++; + } + + sdbRelease(pSdb, pVgroup); + } + + sdbCancelFetch(pSdb, pIter); +} + + static void mndBuildDBVgroupInfo(SDbObj *pDb, SMnode *pMnode, SArray *pVgList) { int32_t vindex = 0; SSdb *pSdb = pMnode->pSdb; @@ -900,6 +923,7 @@ static void mndBuildDBVgroupInfo(SDbObj *pDb, SMnode *pMnode, SArray *pVgList) { vgInfo.vgId = pVgroup->vgId; vgInfo.hashBegin = pVgroup->hashBegin; vgInfo.hashEnd = pVgroup->hashEnd; + vgInfo.numOfTable = pVgroup->numOfTables / TSDB_TABLE_NUM_UNIT; vgInfo.epSet.numOfEps = pVgroup->replica; for (int32_t gid = 0; gid < pVgroup->replica; ++gid) { SVnodeGid *pVgid = &pVgroup->vnodeGid[gid]; @@ -967,7 +991,10 @@ static int32_t mndProcessUseDbReq(SMnodeMsg *pReq) { goto USE_DB_OVER; } - if (usedbReq.vgVersion < pDb->vgVersion || usedbReq.dbId != pDb->uid) { + int32_t numOfTable = 0; + mndGetDBTableNum(pDb, pMnode, &numOfTable); + + if (usedbReq.vgVersion < pDb->vgVersion || usedbReq.dbId != pDb->uid || numOfTable != usedbReq.numOfTable) { mndBuildDBVgroupInfo(pDb, pMnode, usedbRsp.pVgroupInfos); } @@ -1017,6 +1044,7 @@ int32_t mndValidateDbInfo(SMnode *pMnode, SDbVgVersion *pDbs, int32_t numOfDbs, SDbVgVersion *pDbVgVersion = &pDbs[i]; pDbVgVersion->dbId = htobe64(pDbVgVersion->dbId); pDbVgVersion->vgVersion = htonl(pDbVgVersion->vgVersion); + pDbVgVersion->numOfTable = htonl(pDbVgVersion->numOfTable); SUseDbRsp usedbRsp = {0}; @@ -1027,28 +1055,34 @@ int32_t mndValidateDbInfo(SMnode *pMnode, SDbVgVersion *pDbs, int32_t numOfDbs, usedbRsp.uid = pDbVgVersion->dbId; usedbRsp.vgVersion = -1; taosArrayPush(batchUseRsp.pArray, &usedbRsp); - } else if (pDbVgVersion->vgVersion >= pDb->vgVersion) { - mDebug("db:%s, version not changed", pDbVgVersion->dbFName); - mndReleaseDb(pMnode, pDb); continue; - } else { - usedbRsp.pVgroupInfos = taosArrayInit(pDb->cfg.numOfVgroups, sizeof(SVgroupInfo)); - if (usedbRsp.pVgroupInfos == NULL) { - mndReleaseDb(pMnode, pDb); - mError("db:%s, failed to malloc usedb response", pDb->name); - continue; - } + } - mndBuildDBVgroupInfo(pDb, pMnode, usedbRsp.pVgroupInfos); - memcpy(usedbRsp.db, pDb->name, TSDB_DB_FNAME_LEN); - usedbRsp.uid = pDb->uid; - usedbRsp.vgVersion = pDb->vgVersion; - usedbRsp.vgNum = (int32_t)taosArrayGetSize(usedbRsp.pVgroupInfos); - usedbRsp.hashMethod = pDb->hashMethod; + int32_t numOfTable = 0; + mndGetDBTableNum(pDb, pMnode, &numOfTable); - taosArrayPush(batchUseRsp.pArray, &usedbRsp); + if (pDbVgVersion->vgVersion >= pDb->vgVersion && numOfTable == pDbVgVersion->numOfTable) { + mDebug("db:%s, version & numOfTable not changed", pDbVgVersion->dbFName); mndReleaseDb(pMnode, pDb); + continue; } + + usedbRsp.pVgroupInfos = taosArrayInit(pDb->cfg.numOfVgroups, sizeof(SVgroupInfo)); + if (usedbRsp.pVgroupInfos == NULL) { + mndReleaseDb(pMnode, pDb); + mError("db:%s, failed to malloc usedb response", pDb->name); + continue; + } + + mndBuildDBVgroupInfo(pDb, pMnode, usedbRsp.pVgroupInfos); + memcpy(usedbRsp.db, pDb->name, TSDB_DB_FNAME_LEN); + usedbRsp.uid = pDb->uid; + usedbRsp.vgVersion = pDb->vgVersion; + usedbRsp.vgNum = (int32_t)taosArrayGetSize(usedbRsp.pVgroupInfos); + usedbRsp.hashMethod = pDb->hashMethod; + + taosArrayPush(batchUseRsp.pArray, &usedbRsp); + mndReleaseDb(pMnode, pDb); } int32_t rspLen = tSerializeSUseDbBatchRsp(NULL, 0, &batchUseRsp); diff --git a/source/dnode/mnode/impl/src/mndQnode.c b/source/dnode/mnode/impl/src/mndQnode.c index 0c227b0db9def38096fc636a40ba627d9a6acc17..980e1a5a3fb35ccf4ab14fd4f46dc662db052615 100644 --- a/source/dnode/mnode/impl/src/mndQnode.c +++ b/source/dnode/mnode/impl/src/mndQnode.c @@ -36,6 +36,7 @@ static int32_t mndProcessDropQnodeRsp(SMnodeMsg *pRsp); static int32_t mndGetQnodeMeta(SMnodeMsg *pReq, SShowObj *pShow, STableMetaRsp *pMeta); static int32_t mndRetrieveQnodes(SMnodeMsg *pReq, SShowObj *pShow, char *data, int32_t rows); static void mndCancelGetNextQnode(SMnode *pMnode, void *pIter); +static int32_t mndProcessQnodeListReq(SMnodeMsg *pReq); int32_t mndInitQnode(SMnode *pMnode) { SSdbTable table = {.sdbType = SDB_QNODE, @@ -48,6 +49,7 @@ int32_t mndInitQnode(SMnode *pMnode) { mndSetMsgHandle(pMnode, TDMT_MND_CREATE_QNODE, mndProcessCreateQnodeReq); mndSetMsgHandle(pMnode, TDMT_MND_DROP_QNODE, mndProcessDropQnodeReq); + mndSetMsgHandle(pMnode, TDMT_MND_QNODE_LIST, mndProcessQnodeListReq); mndSetMsgHandle(pMnode, TDMT_DND_CREATE_QNODE_RSP, mndProcessCreateQnodeRsp); mndSetMsgHandle(pMnode, TDMT_DND_DROP_QNODE_RSP, mndProcessDropQnodeRsp); @@ -430,6 +432,69 @@ DROP_QNODE_OVER: return code; } + +static int32_t mndProcessQnodeListReq(SMnodeMsg *pReq) { + int32_t code = -1; + SQnodeListReq qlistReq = {0}; + int32_t numOfRows = 0; + SMnode *pMnode = pReq->pMnode; + SSdb *pSdb = pMnode->pSdb; + SQnodeObj *pObj = NULL; + SQnodeListRsp qlistRsp = {0}; + + if (tDeserializeSQnodeListReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &qlistReq) != 0) { + mError("invalid qnode list msg"); + terrno = TSDB_CODE_INVALID_MSG; + goto QNODE_LIST_OVER; + } + + qlistRsp.epSetList = taosArrayInit(5, sizeof(SEpSet)); + if (NULL == qlistRsp.epSetList) { + mError("taosArrayInit epSet failed"); + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto QNODE_LIST_OVER; + } + + while (true) { + void *pIter = sdbFetch(pSdb, SDB_QNODE, NULL, (void **)&pObj); + if (pIter == NULL) break; + + SEpSet epSet = {0}; + strcpy(epSet.eps[0].fqdn, pObj->pDnode->fqdn); + epSet.eps[0].port = pObj->pDnode->port; + epSet.numOfEps = 1; + + taosArrayPush(qlistRsp.epSetList, &epSet); + + numOfRows++; + sdbRelease(pSdb, pObj); + + if (qlistReq.rowNum > 0 && numOfRows >= qlistReq.rowNum) { + break; + } + } + + int32_t rspLen = tSerializeSQnodeListRsp(NULL, 0, &qlistRsp); + void *pRsp = malloc(rspLen); + if (pRsp == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto QNODE_LIST_OVER; + } + + tSerializeSQnodeListRsp(pRsp, rspLen, &qlistRsp); + + pReq->contLen = rspLen; + pReq->pCont = pRsp; + code = 0; + +QNODE_LIST_OVER: + + tFreeSQnodeListRsp(&qlistRsp); + + return code; +} + + static int32_t mndProcessCreateQnodeRsp(SMnodeMsg *pRsp) { mndTransProcessRsp(pRsp); return 0; diff --git a/source/dnode/mnode/impl/src/mndScheduler.c b/source/dnode/mnode/impl/src/mndScheduler.c index ce288d33f78f468f1618a5d6b0b53cb04832c21a..e827810cc9850f9007a1c6b037fc85f9b0b5fa30 100644 --- a/source/dnode/mnode/impl/src/mndScheduler.c +++ b/source/dnode/mnode/impl/src/mndScheduler.c @@ -32,30 +32,30 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscribeObj* pSub) { SSdb* pSdb = pMnode->pSdb; SVgObj* pVgroup = NULL; - SQueryDag* pDag = qStringToDag(pTopic->physicalPlan); - if (pDag == NULL) { + SQueryPlan* pPlan = qStringToQueryPlan(pTopic->physicalPlan); + if (pPlan == NULL) { terrno = TSDB_CODE_QRY_INVALID_INPUT; return -1; } ASSERT(pSub->vgNum == 0); - int32_t levelNum = taosArrayGetSize(pDag->pSubplans); + int32_t levelNum = LIST_LENGTH(pPlan->pSubplans); if (levelNum != 1) { - qDestroyQueryDag(pDag); + qDestroyQueryPlan(pPlan); terrno = TSDB_CODE_MND_UNSUPPORTED_TOPIC; return -1; } - SArray* plans = taosArrayGetP(pDag->pSubplans, 0); + SNodeListNode* inner = nodesListGetNode(pPlan->pSubplans, 0); - int32_t opNum = taosArrayGetSize(plans); + int32_t opNum = LIST_LENGTH(inner->pNodeList); if (opNum != 1) { - qDestroyQueryDag(pDag); + qDestroyQueryPlan(pPlan); terrno = TSDB_CODE_MND_UNSUPPORTED_TOPIC; return -1; } - SSubplan* plan = taosArrayGetP(plans, 0); + SSubplan* plan = nodesListGetNode(inner->pNodeList, 0); void* pIter = NULL; while (1) { @@ -78,14 +78,14 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib int32_t msgLen; if (qSubPlanToString(plan, &consumerEp.qmsg, &msgLen) < 0) { sdbRelease(pSdb, pVgroup); - qDestroyQueryDag(pDag); + qDestroyQueryPlan(pPlan); terrno = TSDB_CODE_QRY_INVALID_INPUT; return -1; } taosArrayPush(pSub->unassignedVg, &consumerEp); } - qDestroyQueryDag(pDag); + qDestroyQueryPlan(pPlan); return 0; } diff --git a/source/dnode/mnode/impl/src/mndShow.c b/source/dnode/mnode/impl/src/mndShow.c index 8fd0c282e15224a051225f04d911a98d2191e0a0..ad97888ac5b06d3492c505fdbc696689a72bfc24 100644 --- a/source/dnode/mnode/impl/src/mndShow.c +++ b/source/dnode/mnode/impl/src/mndShow.c @@ -25,6 +25,7 @@ static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove); static int32_t mndProcessShowReq(SMnodeMsg *pReq); static int32_t mndProcessRetrieveReq(SMnodeMsg *pReq); static bool mndCheckRetrieveFinished(SShowObj *pShow); +static int32_t mndProcessRetrieveSysTableReq(SMnodeMsg *pReq); int32_t mndInitShow(SMnode *pMnode) { SShowMgmt *pMgmt = &pMnode->showMgmt; @@ -38,6 +39,7 @@ int32_t mndInitShow(SMnode *pMnode) { mndSetMsgHandle(pMnode, TDMT_MND_SHOW, mndProcessShowReq); mndSetMsgHandle(pMnode, TDMT_MND_SHOW_RETRIEVE, mndProcessRetrieveReq); + mndSetMsgHandle(pMnode, TDMT_MND_SYSTABLE_RETRIEVE, mndProcessRetrieveSysTableReq); return 0; } @@ -261,6 +263,106 @@ static int32_t mndProcessRetrieveReq(SMnodeMsg *pReq) { return TSDB_CODE_SUCCESS; } +static int32_t mndProcessRetrieveSysTableReq(SMnodeMsg *pReq) { + SMnode *pMnode = pReq->pMnode; + SShowMgmt *pMgmt = &pMnode->showMgmt; + int32_t rowsToRead = 0; + int32_t size = 0; + int32_t rowsRead = 0; + + SRetrieveTableReq retrieveReq = {0}; + if (tDeserializeSRetrieveTableReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &retrieveReq) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + return -1; + } + + SShowObj* pShow = NULL; + + if (retrieveReq.showId == 0) { + SShowReq req = {0}; + req.type = retrieveReq.type; + strncpy(req.db, retrieveReq.db, tListLen(req.db)); + + pShow = mndCreateShowObj(pMnode, &req); + if (pShow == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + mError("failed to process show-meta req since %s", terrstr()); + return -1; + } + } else { + pShow = mndAcquireShowObj(pMnode, retrieveReq.showId); + if (pShow == NULL) { + terrno = TSDB_CODE_MND_INVALID_SHOWOBJ; + mError("failed to process show-retrieve req:%p since %s", pShow, terrstr()); + return -1; + } + } + + ShowRetrieveFp retrieveFp = pMgmt->retrieveFps[pShow->type]; + if (retrieveFp == NULL) { + mndReleaseShowObj((SShowObj*) pShow, false); + terrno = TSDB_CODE_MSG_NOT_PROCESSED; + mError("show:0x%" PRIx64 ", failed to retrieve data since %s", pShow->id, terrstr()); + return -1; + } + + mDebug("show:0x%" PRIx64 ", start retrieve data, numOfReads:%d numOfRows:%d type:%s", pShow->id, pShow->numOfReads, + pShow->numOfRows, mndShowStr(pShow->type)); + + if (mndCheckRetrieveFinished((SShowObj*) pShow)) { + mDebug("show:0x%" PRIx64 ", read finished, numOfReads:%d numOfRows:%d", pShow->id, pShow->numOfReads, + pShow->numOfRows); + pShow->numOfReads = pShow->numOfRows; + } + + if ((retrieveReq.free & TSDB_QUERY_TYPE_FREE_RESOURCE) != TSDB_QUERY_TYPE_FREE_RESOURCE) { + rowsToRead = pShow->numOfRows - pShow->numOfReads; + } + + /* return no more than 100 tables in one round trip */ + if (rowsToRead > SHOW_STEP_SIZE) rowsToRead = SHOW_STEP_SIZE; + + /* + * the actual number of table may be larger than the value of pShow->numOfRows, if a query is + * issued during a continuous create table operation. Therefore, rowToRead may be less than 0. + */ + if (rowsToRead < 0) rowsToRead = 0; + size = pShow->rowSize * rowsToRead; + + size += SHOW_STEP_SIZE; + SRetrieveTableRsp *pRsp = rpcMallocCont(size); + if (pRsp == NULL) { + mndReleaseShowObj((SShowObj*) pShow, false); + terrno = TSDB_CODE_OUT_OF_MEMORY; + mError("show:0x%" PRIx64 ", failed to retrieve data since %s", pShow->id, terrstr()); + return -1; + } + + // if free flag is set, client wants to clean the resources + if ((retrieveReq.free & TSDB_QUERY_TYPE_FREE_RESOURCE) != TSDB_QUERY_TYPE_FREE_RESOURCE) { + rowsRead = (*retrieveFp)(pReq, (SShowObj*) pShow, pRsp->data, rowsToRead); + } + + mDebug("show:0x%" PRIx64 ", stop retrieve data, rowsRead:%d rowsToRead:%d", pShow->id, rowsRead, rowsToRead); + + pRsp->numOfRows = htonl(rowsRead); + pRsp->precision = TSDB_TIME_PRECISION_MILLI; // millisecond time precision + + pReq->pCont = pRsp; + pReq->contLen = size; + + if (rowsRead == 0 || rowsToRead == 0 || (rowsRead == rowsToRead && pShow->numOfRows == pShow->numOfReads)) { + pRsp->completed = 1; + mDebug("show:0x%" PRIx64 ", retrieve completed", pShow->id); + mndReleaseShowObj((SShowObj*) pShow, true); + } else { + mDebug("show:0x%" PRIx64 ", retrieve not completed yet", pShow->id); + mndReleaseShowObj((SShowObj*) pShow, false); + } + + return TSDB_CODE_SUCCESS; +} + char *mndShowStr(int32_t showType) { switch (showType) { case TSDB_MGMT_TABLE_ACCT: diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c index 1d964c4383a668370aa8c41e226890fc1f46187c..fa4fed59d09732462a67df20bead3324f23f8299 100644 --- a/source/dnode/mnode/impl/src/mndSubscribe.c +++ b/source/dnode/mnode/impl/src/mndSubscribe.c @@ -773,10 +773,10 @@ static int32_t mndProcessDoRebalanceMsg(SMnodeMsg *pMsg) { static int32_t mndInitUnassignedVg(SMnode *pMnode, const SMqTopicObj *pTopic, SMqSubscribeObj *pSub) { SSdb *pSdb = pMnode->pSdb; SVgObj *pVgroup = NULL; - SQueryDag *pDag = qStringToDag(pTopic->physicalPlan); + SQueryPlan *pPlan = qStringToQueryPlan(pTopic->physicalPlan); SArray *pArray = NULL; - SArray *inner = taosArrayGet(pDag->pSubplans, 0); - SSubplan *plan = taosArrayGetP(inner, 0); + SNodeListNode *inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0); + SSubplan *plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0); SArray *unassignedVg = pSub->unassignedVg; void *pIter = NULL; @@ -792,7 +792,7 @@ static int32_t mndInitUnassignedVg(SMnode *pMnode, const SMqTopicObj *pTopic, SM plan->execNode.nodeId = pVgroup->vgId; plan->execNode.epset = mndGetVgroupEpset(pMnode, pVgroup); - if (schedulerConvertDagToTaskList(pDag, &pArray) < 0) { + if (schedulerConvertDagToTaskList(pPlan, &pArray) < 0) { terrno = TSDB_CODE_MND_UNSUPPORTED_TOPIC; mError("unsupport topic: %s, sql: %s", pTopic->name, pTopic->sql); return -1; diff --git a/source/dnode/qnode/CMakeLists.txt b/source/dnode/qnode/CMakeLists.txt index 92cd8fcb5ce166b7318b6750277802bca421f986..32e3e85d90c35d88a6832bb86474c509ad883fad 100644 --- a/source/dnode/qnode/CMakeLists.txt +++ b/source/dnode/qnode/CMakeLists.txt @@ -11,4 +11,7 @@ target_link_libraries( PRIVATE os PRIVATE common PRIVATE util + PRIVATE qworker + PRIVATE qcom + PRIVATE executor ) \ No newline at end of file diff --git a/source/dnode/qnode/inc/qndInt.h b/source/dnode/qnode/inc/qndInt.h index 0f8e65de7ec300a289fe2c07a1c6d5cedec3d003..357a62052aea7c096c5ac87465c126af9de8338f 100644 --- a/source/dnode/qnode/inc/qndInt.h +++ b/source/dnode/qnode/inc/qndInt.h @@ -28,12 +28,16 @@ extern "C" { #endif +typedef struct SQWorkerMgmt SQHandle; + typedef struct SQnode { + int32_t qndId; SQnodeOpt opt; + SQHandle* pQuery; } SQnode; #ifdef __cplusplus } #endif -#endif /*_TD_QNODE_INT_H_*/ \ No newline at end of file +#endif /*_TD_QNODE_INT_H_*/ diff --git a/source/dnode/qnode/src/qnode.c b/source/dnode/qnode/src/qnode.c index 8d2a72b2683f916145bd9aaf52181b68dc1cd571..a1c3f5b0d42925d86d28a7e21dfd5dcb4cd8ae96 100644 --- a/source/dnode/qnode/src/qnode.c +++ b/source/dnode/qnode/src/qnode.c @@ -14,13 +14,35 @@ */ #include "qndInt.h" +#include "query.h" +#include "qworker.h" +#include "executor.h" + +int32_t qnodePutReqToVQueryQ(SQnode* pQnode, struct SRpcMsg* pReq) {} +void qnodeSendReqToDnode(SQnode* pQnode, struct SEpSet* epSet, struct SRpcMsg* pReq) {} + SQnode *qndOpen(const SQnodeOpt *pOption) { SQnode *pQnode = calloc(1, sizeof(SQnode)); + if (NULL == pQnode) { + qError("calloc SQnode failed"); + return NULL; + } + + if (qWorkerInit(NODE_TYPE_QNODE, pQnode->qndId, NULL, (void **)&pQnode->pQuery, pQnode, + (putReqToQueryQFp)qnodePutReqToVQueryQ, (sendReqToDnodeFp)qnodeSendReqToDnode)) { + tfree(pQnode); + return NULL; + } + return pQnode; } -void qndClose(SQnode *pQnode) { free(pQnode); } +void qndClose(SQnode *pQnode) { + qWorkerDestroy((void **)&pQnode->pQuery); + + free(pQnode); +} int32_t qndGetLoad(SQnode *pQnode, SQnodeLoad *pLoad) { return 0; } @@ -29,3 +51,51 @@ int32_t qndProcessMsg(SQnode *pQnode, SRpcMsg *pMsg, SRpcMsg **pRsp) { return 0; } +int qnodeProcessQueryMsg(SQnode *pQnode, SRpcMsg *pMsg) { + qTrace("message in query queue is processing"); + SReadHandle handle = {0}; + + switch (pMsg->msgType) { + case TDMT_VND_QUERY:{ + return qWorkerProcessQueryMsg(&handle, pQnode->pQuery, pMsg); + } + case TDMT_VND_QUERY_CONTINUE: + return qWorkerProcessCQueryMsg(&handle, pQnode->pQuery, pMsg); + default: + qError("unknown msg type:%d in query queue", pMsg->msgType); + return TSDB_CODE_VND_APP_ERROR; + } +} + +int qnodeProcessFetchMsg(SQnode *pQnode, SRpcMsg *pMsg) { + qTrace("message in fetch queue is processing"); + switch (pMsg->msgType) { + case TDMT_VND_FETCH: + return qWorkerProcessFetchMsg(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_FETCH_RSP: + return qWorkerProcessFetchRsp(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_RES_READY: + return qWorkerProcessReadyMsg(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_TASKS_STATUS: + return qWorkerProcessStatusMsg(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_CANCEL_TASK: + return qWorkerProcessCancelMsg(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_DROP_TASK: + return qWorkerProcessDropMsg(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_SHOW_TABLES: + return qWorkerProcessShowMsg(pQnode, pQnode->pQuery, pMsg); + case TDMT_VND_SHOW_TABLES_FETCH: + //return vnodeGetTableList(pQnode, pMsg); + case TDMT_VND_TABLE_META: + //return vnodeGetTableMeta(pQnode, pMsg); + case TDMT_VND_CONSUME: + //return tqProcessConsumeReq(pQnode->pTq, pMsg); + default: + qError("unknown msg type:%d in fetch queue", pMsg->msgType); + return TSDB_CODE_VND_APP_ERROR; + } +} + + + + diff --git a/source/dnode/vnode/inc/meta.h b/source/dnode/vnode/inc/meta.h index 2d747d0e8000e82eef84c9dc1b27bafcb96981d2..05749884d3107f8c5079b75313435fc4585ac029 100644 --- a/source/dnode/vnode/inc/meta.h +++ b/source/dnode/vnode/inc/meta.h @@ -58,8 +58,8 @@ STbCfg * metaGetTbInfoByUid(SMeta *pMeta, tb_uid_t uid); STbCfg * metaGetTbInfoByName(SMeta *pMeta, char *tbname, tb_uid_t *uid); SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, bool isinline); STSchema * metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver); -STSma * metaGetSmaInfoByName(SMeta *pMeta, const char *indexName); -STSmaWrapper * metaGetSmaInfoByUid(SMeta *pMeta, tb_uid_t uid); +STSma * metaGetSmaInfoByIndex(SMeta *pMeta, int64_t indexUid); +STSmaWrapper * metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid); SArray * metaGetSmaTbUids(SMeta *pMeta, bool isDup); SMTbCursor *metaOpenTbCursor(SMeta *pMeta); diff --git a/source/dnode/vnode/inc/tsdb.h b/source/dnode/vnode/inc/tsdb.h index 5513742c73da9aadfaa61ee82411170bb5ddf101..87edfb8dde59deabdb28b8d6b03ae7bf1a67cb6c 100644 --- a/source/dnode/vnode/inc/tsdb.h +++ b/source/dnode/vnode/inc/tsdb.h @@ -89,23 +89,27 @@ int tsdbCommit(STsdb *pTsdb); /** * @brief Insert tSma(Time-range-wise SMA) data from stream computing engine - * - * @param pTsdb - * @param param - * @param pData - * @return int32_t + * + * @param pTsdb + * @param msg + * @return int32_t */ -int32_t tsdbInsertTSmaData(STsdb *pTsdb, STSma *param, STSmaData *pData); +int32_t tsdbInsertTSmaData(STsdb *pTsdb, char *msg); +int32_t tsdbUpdateSmaWindow(STsdb *pTsdb, int8_t smaType, char *msg); /** * @brief Insert RSma(Time-range-wise Rollup SMA) data. - * - * @param pTsdb - * @param param - * @param pData - * @return int32_t + * + * @param pTsdb + * @param msg + * @return int32_t */ -int32_t tsdbInsertRSmaData(STsdb *pTsdb, SRSma *param, STSmaData *pData); +int32_t tsdbInsertRSmaData(STsdb *pTsdb, char *msg); + +// TODO: This is the basic params, and should wrap the params to a queryHandle. +int32_t tsdbGetTSmaData(STsdb *pTsdb, STSmaDataWrapper *pData, int64_t indexUid, int64_t interval, + int8_t intervalUnit, tb_uid_t tableUid, col_id_t colId, TSKEY querySkey, + int32_t nMaxResult); // STsdbCfg diff --git a/source/libs/parser/inc/astCreateContext.h b/source/dnode/vnode/src/inc/tsdbDBDef.h similarity index 54% rename from source/libs/parser/inc/astCreateContext.h rename to source/dnode/vnode/src/inc/tsdbDBDef.h index a0bac9ea7bcb33ce90aaa467ae91a976c39d1282..2e37b0ba45132a92e4de5b7e0a21e680564256bc 100644 --- a/source/libs/parser/inc/astCreateContext.h +++ b/source/dnode/vnode/src/inc/tsdbDBDef.h @@ -13,28 +13,32 @@ * along with this program. If not, see . */ -#ifndef _TD_AST_CREATER_H_ -#define _TD_AST_CREATER_H_ +#ifndef _TD_TSDB_DB_DEF_H_ +#define _TD_TSDB_DB_DEF_H_ + +#include "db.h" #ifdef __cplusplus extern "C" { #endif -#include "nodes.h" -#include "parser.h" +typedef struct SDBFile SDBFile; +typedef DB_ENV* TDBEnv; -typedef struct SAstCreateContext { - SParseContext* pQueryCxt; - bool notSupport; - bool valid; - SNode* pRootNode; -} SAstCreateContext; +struct SDBFile { + DB* pDB; + char* path; +}; -int32_t createAstCreateContext(SParseContext* pQueryCxt, SAstCreateContext* pCxt); -int32_t destroyAstCreateContext(SAstCreateContext* pCxt); +int32_t tsdbOpenDBF(TDBEnv pEnv, SDBFile* pDBF); +void tsdbCloseDBF(SDBFile* pDBF); +int32_t tsdbOpenBDBEnv(DB_ENV** ppEnv, const char* path); +void tsdbCloseBDBEnv(DB_ENV* pEnv); +int32_t tsdbSaveSmaToDB(SDBFile* pDBF, void* key, uint32_t keySize, void* data, uint32_t dataSize); +void* tsdbGetSmaDataByKey(SDBFile* pDBF, void* key, uint32_t keySize, uint32_t* valueSize); #ifdef __cplusplus } #endif -#endif /*_TD_AST_CREATER_H_*/ +#endif /*_TD_TSDB_DB_DEF_H_*/ diff --git a/source/dnode/vnode/src/inc/tsdbDef.h b/source/dnode/vnode/src/inc/tsdbDef.h index 96a76ea7d4a0c7bd24b587afa7f98129f0855ac4..6f91b4d3abb4bf608c50ca15973f83b19fb1dbf6 100644 --- a/source/dnode/vnode/src/inc/tsdbDef.h +++ b/source/dnode/vnode/src/inc/tsdbDef.h @@ -27,6 +27,7 @@ #include "ttime.h" #include "tsdb.h" +#include "tsdbDBDef.h" #include "tsdbCommit.h" #include "tsdbFS.h" #include "tsdbFile.h" @@ -37,12 +38,15 @@ #include "tsdbReadImpl.h" #include "tsdbSma.h" + #ifdef __cplusplus extern "C" { #endif struct STsdb { int32_t vgId; + bool repoLocked; + pthread_mutex_t mutex; char * path; STsdbCfg config; STsdbMemTable * mem; @@ -52,11 +56,17 @@ struct STsdb { STsdbFS * fs; SMeta * pMeta; STfs * pTfs; + SSmaEnv * pTSmaEnv; + SSmaEnv * pRSmaEnv; }; -#define REPO_ID(r) ((r)->vgId) -#define REPO_CFG(r) (&(r)->config) -#define REPO_FS(r) (r)->fs +#define REPO_ID(r) ((r)->vgId) +#define REPO_CFG(r) (&(r)->config) +#define REPO_FS(r) (r)->fs +#define IS_REPO_LOCKED(r) (r)->repoLocked + +int tsdbLockRepo(STsdb *pTsdb); +int tsdbUnlockRepo(STsdb *pTsdb); static FORCE_INLINE STSchema *tsdbGetTableSchemaImpl(STable *pTable, bool lock, bool copy, int32_t version) { return pTable->pSchema; diff --git a/source/dnode/vnode/src/inc/tsdbFS.h b/source/dnode/vnode/src/inc/tsdbFS.h index 641255a294f36da5d8b437662066d7b99ff57f66..96c5f8468f2ac97d047683220acbae6cf2e8dc8a 100644 --- a/source/dnode/vnode/src/inc/tsdbFS.h +++ b/source/dnode/vnode/src/inc/tsdbFS.h @@ -42,9 +42,27 @@ typedef struct { typedef struct { STsdbFSMeta meta; // FS meta SArray * df; // data file array - SArray * smaf; // sma data file array + SArray * sf; // sma data file array v2(t|r)1900.index_name_1 } SFSStatus; +/** + * @brief Directory structure of .tsma data files. + * + * /vnode2/tsdb $ tree .sma/ + * .sma/ + * ├── v2t100.index_name_1 + * ├── v2t101.index_name_1 + * ├── v2t102.index_name_1 + * ├── v2t1900.index_name_3 + * ├── v2t1901.index_name_3 + * ├── v2t1902.index_name_3 + * ├── v2t200.index_name_2 + * ├── v2t201.index_name_2 + * └── v2t202.index_name_2 + * + * 0 directories, 9 files + */ + typedef struct { pthread_rwlock_t lock; diff --git a/source/dnode/vnode/src/inc/tsdbFile.h b/source/dnode/vnode/src/inc/tsdbFile.h index 1034ae015a098362703a684fb809c751a4ab911c..e65ef72623f9b12803765c80d63de07f13bbda07 100644 --- a/source/dnode/vnode/src/inc/tsdbFile.h +++ b/source/dnode/vnode/src/inc/tsdbFile.h @@ -56,10 +56,11 @@ typedef enum { TSDB_FILE_SMAL, // .smal(Block-wise SMA) TSDB_FILE_MAX, // TSDB_FILE_META, // meta - TSDB_FILE_TSMA, // .tsma.${sma_index_name}, Time-range-wise SMA - TSDB_FILE_RSMA, // .rsma.${sma_index_name}, Time-range-wise Rollup SMA -} TSDB_FILE_T; + TSDB_FILE_TSMA, // v2t100.${sma_index_name}, Time-range-wise SMA + TSDB_FILE_RSMA, // v2r100.${sma_index_name}, Time-range-wise Rollup SMA +} E_TSDB_FILE_T; +typedef int32_t TSDB_FILE_T; typedef enum { TSDB_FS_VER_0 = 0, TSDB_FS_VER_MAX, @@ -328,12 +329,25 @@ static FORCE_INLINE int tsdbCopyDFile(SDFile* pSrc, SDFile* pDest) { // =============== SDFileSet typedef struct { int fid; - int8_t state; // -128~127 - uint8_t ver; // 0~255, DFileSet version + int8_t state; // -128~127 + uint8_t ver; // 0~255, DFileSet version uint16_t reserve; SDFile files[TSDB_FILE_MAX]; } SDFileSet; +typedef struct { + int fid; + int8_t state; + uint8_t ver; + uint16_t reserve; +#if 0 + SDFInfo info; +#endif + STfsFile f; + TdFilePtr pFile; + +} SSFile; // files split by days with fid + #define TSDB_LATEST_FSET_VER 0 #define TSDB_FSET_FID(s) ((s)->fid) diff --git a/source/dnode/vnode/src/inc/tsdbSma.h b/source/dnode/vnode/src/inc/tsdbSma.h index e4de7a668558c66aa1db07b9eddd4624809ab188..649b5a2d47a102ee7fdf34b649609ffc7a08d4c2 100644 --- a/source/dnode/vnode/src/inc/tsdbSma.h +++ b/source/dnode/vnode/src/inc/tsdbSma.h @@ -16,29 +16,63 @@ #ifndef _TD_TSDB_SMA_H_ #define _TD_TSDB_SMA_H_ -// insert/update interface -int32_t tsdbInsertTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData); -int32_t tsdbInsertRSmaDataImpl(STsdb *pTsdb, SRSma *param, STSmaData *pData); +typedef struct SSmaStat SSmaStat; +typedef struct SSmaEnv SSmaEnv; +struct SSmaEnv { + pthread_rwlock_t lock; + TDBEnv dbEnv; + char * path; + SSmaStat * pStat; +}; -// query interface -// TODO: This is the basic params, and should wrap the params to a queryHandle. -int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData, STimeWindow *queryWin, int32_t nMaxResult); +#define SMA_ENV_LOCK(env) ((env)->lock) +#define SMA_ENV_ENV(env) ((env)->dbEnv) +#define SMA_ENV_PATH(env) ((env)->path) +#define SMA_ENV_STAT(env) ((env)->pStat) +#define SMA_ENV_STAT_ITEMS(env) ((env)->pStat->smaStatItems) -// management interface -int32_t tsdbGetTSmaStatus(STsdb *pTsdb, STSma *param, void* result); +void tsdbDestroySmaEnv(SSmaEnv *pSmaEnv); +void *tsdbFreeSmaEnv(SSmaEnv *pSmaEnv); +#if 0 +int32_t tsdbGetTSmaStatus(STsdb *pTsdb, STSma *param, void *result); int32_t tsdbRemoveTSmaData(STsdb *pTsdb, STSma *param, STimeWindow *pWin); - - - +#endif // internal func -static FORCE_INLINE int32_t tsdbEncodeTSmaKey(uint64_t tableUid, col_id_t colId, TSKEY tsKey, void **pData) { +static FORCE_INLINE int32_t tsdbEncodeTSmaKey(tb_uid_t tableUid, col_id_t colId, TSKEY tsKey, void **pData) { int32_t len = 0; - len += taosEncodeFixedU64(pData, tableUid); + len += taosEncodeFixedI64(pData, tableUid); len += taosEncodeFixedU16(pData, colId); len += taosEncodeFixedI64(pData, tsKey); return len; } +static FORCE_INLINE int tsdbRLockSma(SSmaEnv *pEnv) { + int code = pthread_rwlock_rdlock(&(pEnv->lock)); + if (code != 0) { + terrno = TAOS_SYSTEM_ERROR(code); + return -1; + } + return 0; +} + +static FORCE_INLINE int tsdbWLockSma(SSmaEnv *pEnv) { + int code = pthread_rwlock_wrlock(&(pEnv->lock)); + if (code != 0) { + terrno = TAOS_SYSTEM_ERROR(code); + return -1; + } + return 0; +} + +static FORCE_INLINE int tsdbUnLockSma(SSmaEnv *pEnv) { + int code = pthread_rwlock_unlock(&(pEnv->lock)); + if (code != 0) { + terrno = TAOS_SYSTEM_ERROR(code); + return -1; + } + return 0; +} + #endif /* _TD_TSDB_SMA_H_ */ \ No newline at end of file diff --git a/source/dnode/vnode/src/inc/vnodeQuery.h b/source/dnode/vnode/src/inc/vnodeQuery.h index 51c93b5ad7a8361ea97394a90293a32a5155c322..7816b4eb46d6a9c97b17bf63d37102167baaa423 100644 --- a/source/dnode/vnode/src/inc/vnodeQuery.h +++ b/source/dnode/vnode/src/inc/vnodeQuery.h @@ -26,6 +26,7 @@ extern "C" { typedef struct SQWorkerMgmt SQHandle; int vnodeQueryOpen(SVnode *pVnode); +void vnodeQueryClose(SVnode *pVnode); #ifdef __cplusplus } diff --git a/source/dnode/vnode/src/meta/metaBDBImpl.c b/source/dnode/vnode/src/meta/metaBDBImpl.c index f49515412b28bf9ff20f2a6eeda3a4381473fa37..a729288e34dff33dde6e0e9f8764bdd7a4a937b3 100644 --- a/source/dnode/vnode/src/meta/metaBDBImpl.c +++ b/source/dnode/vnode/src/meta/metaBDBImpl.c @@ -227,28 +227,35 @@ int metaRemoveTableFromDb(SMeta *pMeta, tb_uid_t uid) { } int metaSaveSmaToDB(SMeta *pMeta, STSma *pSmaCfg) { - char buf[512] = {0}; // TODO: may overflow - void *pBuf = NULL; + // char buf[512] = {0}; // TODO: may overflow + void *pBuf = NULL, *qBuf = NULL; DBT key1 = {0}, value1 = {0}; - { - // save sma info - pBuf = buf; + // save sma info + int32_t len = tEncodeTSma(NULL, pSmaCfg); + pBuf = calloc(len, 1); + if (pBuf == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } - key1.data = pSmaCfg->indexName; - key1.size = strlen(key1.data); + key1.data = (void *)&pSmaCfg->indexUid; + key1.size = sizeof(pSmaCfg->indexUid); - tEncodeTSma(&pBuf, pSmaCfg); + qBuf = pBuf; + tEncodeTSma(&qBuf, pSmaCfg); - value1.data = buf; - value1.size = POINTER_DISTANCE(pBuf, buf); - value1.app_data = pSmaCfg; - } + value1.data = pBuf; + value1.size = POINTER_DISTANCE(qBuf, pBuf); + value1.app_data = pSmaCfg; metaDBWLock(pMeta->pDB); pMeta->pDB->pSmaDB->put(pMeta->pDB->pSmaDB, NULL, &key1, &value1, 0); metaDBULock(pMeta->pDB); + // release + tfree(pBuf); + return 0; } @@ -609,7 +616,7 @@ STbCfg *metaGetTbInfoByName(SMeta *pMeta, char *tbname, tb_uid_t *uid) { return pTbCfg; } -STSma *metaGetSmaInfoByName(SMeta *pMeta, const char *indexName) { +STSma *metaGetSmaInfoByIndex(SMeta *pMeta, int64_t indexUid) { STSma * pCfg = NULL; SMetaDB *pDB = pMeta->pDB; DBT key = {0}; @@ -617,8 +624,8 @@ STSma *metaGetSmaInfoByName(SMeta *pMeta, const char *indexName) { int ret; // Set key/value - key.data = (void *)indexName; - key.size = strlen(indexName); + key.data = (void *)&indexUid; + key.size = sizeof(indexUid); // Query metaDBRLock(pDB); @@ -634,7 +641,10 @@ STSma *metaGetSmaInfoByName(SMeta *pMeta, const char *indexName) { return NULL; } - tDecodeTSma(value.data, pCfg); + if (tDecodeTSma(value.data, pCfg) == NULL) { + tfree(pCfg); + return NULL; + } return pCfg; } @@ -871,7 +881,7 @@ const char *metaSmaCursorNext(SMSmaCursor *pCur) { } } -STSmaWrapper *metaGetSmaInfoByUid(SMeta *pMeta, tb_uid_t uid) { +STSmaWrapper *metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid) { STSmaWrapper *pSW = NULL; pSW = calloc(sizeof(*pSW), 1); @@ -923,6 +933,7 @@ SArray *metaGetSmaTbUids(SMeta *pMeta, bool isDup) { SMetaDB *pDB = pMeta->pDB; DBC * pCur = NULL; DBT pkey = {0}, pval = {0}; + uint32_t mode = isDup ? DB_NEXT_DUP : DB_NEXT_NODUP; int ret; pUids = taosArrayInit(16, sizeof(tb_uid_t)); @@ -941,13 +952,8 @@ SArray *metaGetSmaTbUids(SMeta *pMeta, bool isDup) { void *pBuf = NULL; // TODO: lock? - while (true) { - ret = pCur->get(pCur, &pkey, &pval, isDup ? DB_NEXT_DUP : DB_NEXT_NODUP); - if(ret == 0) { + while ((ret = pCur->get(pCur, &pkey, &pval, mode)) == 0) { taosArrayPush(pUids, pkey.data); - continue; - } - break; } if (pCur) { diff --git a/source/dnode/vnode/src/tsdb/tsdbBDBImpl.c b/source/dnode/vnode/src/tsdb/tsdbBDBImpl.c new file mode 100644 index 0000000000000000000000000000000000000000..cf3351c5d892c9c884a3a1050d9e9e92c3977251 --- /dev/null +++ b/source/dnode/vnode/src/tsdb/tsdbBDBImpl.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#define ALLOW_FORBID_FUNC +#include "db.h" + +#include "taoserror.h" +#include "tcoding.h" +#include "thash.h" +#include "tsdbDBDef.h" +#include "tsdbLog.h" + +#define IMPL_WITH_LOCK 1 + +static int tsdbOpenBDBDb(DB **ppDB, DB_ENV *pEnv, const char *pFName, bool isDup); +static void tsdbCloseBDBDb(DB *pDB); + +#define BDB_PERR(info, code) fprintf(stderr, "%s:%d " info " reason: %s\n", __FILE__, __LINE__, db_strerror(code)) + +int32_t tsdbOpenDBF(TDBEnv pEnv, SDBFile *pDBF) { + // TDBEnv is shared by a group of SDBFile + if (!pEnv) { + terrno = TSDB_CODE_INVALID_PTR; + return -1; + } + + // Open DBF + if (tsdbOpenBDBDb(&(pDBF->pDB), pEnv, pDBF->path, false) < 0) { + terrno = TSDB_CODE_TDB_INIT_FAILED; + tsdbCloseBDBDb(pDBF->pDB); + return -1; + } + + return 0; +} + +void tsdbCloseDBF(SDBFile *pDBF) { + if (pDBF->pDB) { + tsdbCloseBDBDb(pDBF->pDB); + pDBF->pDB = NULL; + } + tfree(pDBF->path); +} + +int32_t tsdbOpenBDBEnv(DB_ENV **ppEnv, const char *path) { + int ret = 0; + DB_ENV *pEnv = NULL; + + if (path == NULL) return 0; + + ret = db_env_create(&pEnv, 0); + if (ret != 0) { + BDB_PERR("Failed to create tsdb env", ret); + return -1; + } + + ret = pEnv->open(pEnv, path, DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL, 0); + if (ret != 0) { + // BDB_PERR("Failed to open tsdb env", ret); + tsdbWarn("Failed to open tsdb env for path %s since %d", path ? path : "NULL", ret); + return -1; + } + + *ppEnv = pEnv; + + return 0; +} + +void tsdbCloseBDBEnv(DB_ENV *pEnv) { + if (pEnv) { + pEnv->close(pEnv, 0); + } +} + +static int tsdbOpenBDBDb(DB **ppDB, DB_ENV *pEnv, const char *pFName, bool isDup) { + int ret; + DB *pDB; + + ret = db_create(&(pDB), pEnv, 0); + if (ret != 0) { + BDB_PERR("Failed to create DBP", ret); + return -1; + } + + if (isDup) { + ret = pDB->set_flags(pDB, DB_DUPSORT); + if (ret != 0) { + BDB_PERR("Failed to set DB flags", ret); + return -1; + } + } + + ret = pDB->open(pDB, NULL, pFName, NULL, DB_BTREE, DB_CREATE, 0); + if (ret) { + BDB_PERR("Failed to open DBF", ret); + return -1; + } + + *ppDB = pDB; + + return 0; +} + +static void tsdbCloseBDBDb(DB *pDB) { + if (pDB) { + pDB->close(pDB, 0); + } +} + +int32_t tsdbSaveSmaToDB(SDBFile *pDBF, void *key, uint32_t keySize, void *data, uint32_t dataSize) { + int ret; + DBT key1 = {0}, value1 = {0}; + + key1.data = key; + key1.size = keySize; + + value1.data = data; + value1.size = dataSize; + + // TODO: lock + ret = pDBF->pDB->put(pDBF->pDB, NULL, &key1, &value1, 0); + if (ret) { + BDB_PERR("Failed to put data to DBF", ret); + // TODO: unlock + return -1; + } + // TODO: unlock + + return 0; +} + +void *tsdbGetSmaDataByKey(SDBFile *pDBF, void* key, uint32_t keySize, uint32_t *valueSize) { + void *result = NULL; + DBT key1 = {0}; + DBT value1 = {0}; + int ret; + + // Set key/value + key1.data = key; + key1.size = keySize; + + // Query + // TODO: lock + ret = pDBF->pDB->get(pDBF->pDB, NULL, &key1, &value1, 0); + // TODO: unlock + if (ret != 0) { + return NULL; + } + + result = calloc(1, value1.size); + + if (result == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + *valueSize = value1.size; + memcpy(result, value1.data, value1.size); + + return result; +} \ No newline at end of file diff --git a/source/dnode/vnode/src/tsdb/tsdbFile.c b/source/dnode/vnode/src/tsdb/tsdbFile.c index 74fb8c1c1fab8cb808416335a3f76bfc2632e042..b756cc9862efe60e496d3d43e995398af8719024 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFile.c +++ b/source/dnode/vnode/src/tsdb/tsdbFile.c @@ -23,8 +23,8 @@ static const char *TSDB_FNAME_SUFFIX[] = { "smal", // TSDB_FILE_SMAL "", // TSDB_FILE_MAX "meta", // TSDB_FILE_META - "tsma", // TSDB_FILE_TSMA - "rsma", // TSDB_FILE_RSMA + "sma", // TSDB_FILE_TSMA(directory name) + "sma", // TSDB_FILE_RSMA(directory name) }; static void tsdbGetFilename(int vid, int fid, uint32_t ver, TSDB_FILE_T ftype, char *fname); @@ -365,7 +365,7 @@ int tsdbCreateDFile(STsdb *pRepo, SDFile *pDFile, bool updateHeader, TSDB_FILE_T if (errno == ENOENT) { // Try to create directory recursively char *s = strdup(TSDB_FILE_REL_NAME(pDFile)); - if (tfsMkdirRecurAt(pRepo->pTfs, dirname(s), TSDB_FILE_DID(pDFile)) < 0) { + if (tfsMkdirRecurAt(pRepo->pTfs, taosDirName(s), TSDB_FILE_DID(pDFile)) < 0) { tfree(s); return -1; } diff --git a/source/dnode/vnode/src/tsdb/tsdbMain.c b/source/dnode/vnode/src/tsdb/tsdbMain.c index 2d8c4701132a9c9818775654df8751b5b4a2ec75..afa8921c004aa37282d86ff44f2d1f4850f2dfdc 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMain.c +++ b/source/dnode/vnode/src/tsdb/tsdbMain.c @@ -80,6 +80,8 @@ static STsdb *tsdbNew(const char *path, int32_t vgId, const STsdbCfg *pTsdbCfg, pTsdb->pmaf = pMAF; pTsdb->pMeta = pMeta; pTsdb->pTfs = pTfs; + pTsdb->pTSmaEnv = NULL; + pTsdb->pRSmaEnv = NULL; pTsdb->fs = tsdbNewFS(pTsdbCfg); @@ -88,6 +90,8 @@ static STsdb *tsdbNew(const char *path, int32_t vgId, const STsdbCfg *pTsdbCfg, static void tsdbFree(STsdb *pTsdb) { if (pTsdb) { + tsdbFreeSmaEnv(pTsdb->pRSmaEnv); + tsdbFreeSmaEnv(pTsdb->pTSmaEnv); tsdbFreeFS(pTsdb->fs); tfree(pTsdb->path); free(pTsdb); @@ -104,6 +108,30 @@ static void tsdbCloseImpl(STsdb *pTsdb) { tsdbCloseFS(pTsdb); // TODO } + +int tsdbLockRepo(STsdb *pTsdb) { + int code = pthread_mutex_lock(&pTsdb->mutex); + if (code != 0) { + tsdbError("vgId:%d failed to lock tsdb since %s", REPO_ID(pTsdb), strerror(errno)); + terrno = TAOS_SYSTEM_ERROR(code); + return -1; + } + pTsdb->repoLocked = true; + return 0; +} + +int tsdbUnlockRepo(STsdb *pTsdb) { + ASSERT(IS_REPO_LOCKED(pTsdb)); + pTsdb->repoLocked = false; + int code = pthread_mutex_unlock(&pTsdb->mutex); + if (code != 0) { + tsdbError("vgId:%d failed to unlock tsdb since %s", REPO_ID(pTsdb), strerror(errno)); + terrno = TAOS_SYSTEM_ERROR(code); + return -1; + } + return 0; +} + #if 0 /* * Copyright (c) 2019 TAOS Data, Inc. diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c index 4bd0ee959e0db8e9b84e7e02566e497e15dcb066..97c52f44ebbbb56181717ab4a308d0efda9ed8f9 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead.c @@ -13,18 +13,19 @@ * along with this program. If not, see . */ +#include +#include "os.h" +#include "talgo.h" +#include "tcompare.h" +#include "tdataformat.h" +#include "texception.h" #include "tsdb.h" #include "tsdbDef.h" #include "tsdbFS.h" #include "tsdbLog.h" #include "tsdbReadImpl.h" -#include "ttime.h" -#include "texception.h" -#include "os.h" -#include "talgo.h" -#include "tcompare.h" -#include "tdataformat.h" #include "tskiplist.h" +#include "ttime.h" #include "taosdef.h" #include "tlosertree.h" @@ -1472,6 +1473,8 @@ static int32_t doCopyRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, int32_t return numOfRows + num; } +// TODO fix bug for reverse copy data +// TODO handle the null data // Note: row1 always has high priority static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows, STSRow* row1, STSRow* row2, int32_t numOfCols, uint64_t uid, STSchema* pSchema1, STSchema* pSchema2, @@ -1515,7 +1518,6 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit } } - int32_t i = 0, j = 0, k = 0; while(i < numOfCols && (j < numOfColsOfRow1 || k < numOfColsOfRow2)) { SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i); @@ -1586,7 +1588,6 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit tdSKvRowGetVal(row, colId, offset, chosen_itr, &sVal); } - if (colId == pColInfo->info.colId) { if (tdValTypeIsNorm(sVal.valType)) { switch (pColInfo->info.type) { @@ -1594,7 +1595,6 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit case TSDB_DATA_TYPE_NCHAR: memcpy(pData, sVal.val, varDataTLen(sVal.val)); break; - case TSDB_DATA_TYPE_NULL: case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_UTINYINT: @@ -1625,11 +1625,7 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit memcpy(pData, sVal.val, pColInfo->info.bytes); } } else if (forceSetNull) { - if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { - setVardataNull(pData, pColInfo->info.type); - } else { - setNull(pData, pColInfo->info.type, pColInfo->info.bytes); - } + colDataAppend(pColInfo, numOfRows, NULL, true); } i++; @@ -1640,11 +1636,7 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit } } else { if(forceSetNull) { - if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { - setVardataNull(pData, pColInfo->info.type); - } else { - setNull(pData, pColInfo->info.type, pColInfo->info.bytes); - } + colDataAppend(pColInfo, numOfRows, NULL, true); } i++; } @@ -1653,18 +1645,7 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit if(forceSetNull) { while (i < numOfCols) { // the remain columns are all null data SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i); - if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) { - pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; - } else { - pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; - } - - if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { - setVardataNull(pData, pColInfo->info.type); - } else { - setNull(pData, pColInfo->info.type, pColInfo->info.bytes); - } - + colDataAppend(pColInfo, numOfRows, NULL, true); i++; } } diff --git a/source/dnode/vnode/src/tsdb/tsdbSma.c b/source/dnode/vnode/src/tsdb/tsdbSma.c index b465dc3a88d2e56f716cf595a391c0f0985372c4..7335e4f58543d00ded7227d54a1be0606cf81de5 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSma.c +++ b/source/dnode/vnode/src/tsdb/tsdbSma.c @@ -15,54 +15,358 @@ #include "tsdbDef.h" +#undef SMA_PRINT_DEBUG_LOG #define SMA_STORAGE_TSDB_DAYS 30 +#define SMA_STORAGE_TSDB_TIMES 30 #define SMA_STORAGE_SPLIT_HOURS 24 #define SMA_KEY_LEN 18 // tableUid_colId_TSKEY 8+2+8 -#define SMA_STORE_SINGLE_BLOCKS // store SMA data by single block or multiple blocks +#define SMA_STATE_HASH_SLOT 4 +#define SMA_STATE_ITEM_HASH_SLOT 32 +#define SMA_TEST_INDEX_NAME "smaTestIndexName" // TODO: just for test +#define SMA_TEST_INDEX_UID 2000000001 // TODO: just for test typedef enum { - SMA_STORAGE_LEVEL_TSDB = 0, // store TSma in dir e.g. vnode${N}/tsdb/.tsma - SMA_STORAGE_LEVEL_DFILESET = 1 // store TSma in file e.g. vnode${N}/tsdb/v2f1900.tsma.${sma_index_name} + SMA_STORAGE_LEVEL_TSDB = 0, // use days of self-defined e.g. vnode${N}/tsdb/tsma/sma_index_uid/v2t200.dat + SMA_STORAGE_LEVEL_DFILESET = 1 // use days of TS data e.g. vnode${N}/tsdb/rsma/sma_index_uid/v2r200.dat } ESmaStorageLevel; typedef struct { STsdb * pTsdb; - char * pDFile; // TODO: use the real DFile type, not char* - int32_t interval; // interval with the precision of DB - int32_t blockSize; // size of SMA block item - // TODO + SDBFile dFile; + int32_t interval; // interval with the precision of DB } STSmaWriteH; typedef struct { int32_t iter; + int32_t fid; } SmaFsIter; typedef struct { STsdb * pTsdb; - char * pDFile; // TODO: use the real DFile type, not char* + SDBFile dFile; int32_t interval; // interval with the precision of DB int32_t blockSize; // size of SMA block item int8_t storageLevel; int8_t days; SmaFsIter smaFsIter; - // TODO } STSmaReadH; +typedef struct { + /** + * @brief The field 'state' is here to demonstrate if one smaIndex is ready to provide service. + * - TSDB_SMA_STAT_EXPIRED: 1) If sma calculation of history TS data is not finished; 2) Or if the TSDB is open, + * without information about its previous state. + * - TSDB_SMA_STAT_OK: 1) The sma calculation of history data is finished; 2) Or recevied information from + * Streaming Module or TSDB local persistence. + */ + int8_t state; // ETsdbSmaStat + SHashObj *expiredWindows; // key: skey of time window, value: N/A + STSma * pSma; +} SSmaStatItem; + +struct SSmaStat { + SHashObj *smaStatItems; // key: indexName, value: SSmaStatItem +}; + // declaration of static functions -static int32_t tsdbInitTSmaWriteH(STSmaWriteH *pSmaH, STsdb *pTsdb, STSma *param, STSmaData *pData); -static int32_t tsdbInitTSmaReadH(STSmaReadH *pSmaH, STsdb *pTsdb, STSma *param, STSmaData *pData); -static int32_t tsdbJudgeStorageLevel(int64_t interval, int8_t intervalUnit); -static int32_t tsdbInsertTSmaDataSection(STSmaWriteH *pSmaH, STSmaData *pData, int32_t sectionDataLen, int32_t nBlocks); -static int32_t tsdbInsertTSmaBlocks(void *bTree, const char *smaKey, const char *pData, int32_t dataLen); -static int32_t tsdbTSmaDataSplit(STSmaWriteH *pSmaH, STSma *param, STSmaData *pData, int32_t days, int32_t nOffset, - int32_t fid, int32_t *nSmaBlocks); +static int32_t tsdbInsertTSmaDataImpl(STsdb *pTsdb, char *msg); +static int32_t tsdbInsertRSmaDataImpl(STsdb *pTsdb, char *msg); +// TODO: This is the basic params, and should wrap the params to a queryHandle. +static int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSmaDataWrapper *pData, int64_t indexUid, int64_t interval, + int8_t intervalUnit, tb_uid_t tableUid, col_id_t colId, TSKEY querySkey, + int32_t nMaxResult); +static int32_t tsdbUpdateExpiredWindow(STsdb *pTsdb, int8_t smaType, char *msg); + +static int32_t tsdbInitSmaStat(SSmaStat **pSmaStat); +static int32_t tsdbDestroySmaState(SSmaStat *pSmaStat); +static SSmaEnv *tsdbNewSmaEnv(const STsdb *pTsdb, const char *path); +static int32_t tsdbInitSmaEnv(STsdb *pTsdb, const char *path, SSmaEnv **pEnv); +static int32_t tsdbInitTSmaWriteH(STSmaWriteH *pSmaH, STsdb *pTsdb, STSmaDataWrapper *pData); +static void tsdbDestroyTSmaWriteH(STSmaWriteH *pSmaH); +static int32_t tsdbInitTSmaReadH(STSmaReadH *pSmaH, STsdb *pTsdb, int64_t interval, int8_t intervalUnit); +static int32_t tsdbGetSmaStorageLevel(int64_t interval, int8_t intervalUnit); +static int32_t tsdbInsertTSmaDataSection(STSmaWriteH *pSmaH, STSmaDataWrapper *pData); +static int32_t tsdbInsertTSmaBlocks(STSmaWriteH *pSmaH, void *smaKey, uint32_t keyLen, void *pData, uint32_t dataLen); + static int64_t tsdbGetIntervalByPrecision(int64_t interval, uint8_t intervalUnit, int8_t precision); -static int32_t tsdbSetTSmaDataFile(STSmaWriteH *pSmaH, STSma *param, STSmaData *pData, int32_t storageLevel, - int32_t fid); +static int32_t tsdbGetTSmaDays(STsdb *pTsdb, int64_t interval, int32_t storageLevel); +static int32_t tsdbSetTSmaDataFile(STSmaWriteH *pSmaH, STSmaDataWrapper *pData, int32_t storageLevel, int32_t fid); +static int32_t tsdbInitTSmaFile(STSmaReadH *pSmaH, TSKEY skey); +static bool tsdbSetAndOpenTSmaFile(STSmaReadH *pReadH, TSKEY *queryKey); + +static SSmaEnv *tsdbNewSmaEnv(const STsdb *pTsdb, const char *path) { + SSmaEnv *pEnv = NULL; + + pEnv = (SSmaEnv *)calloc(1, sizeof(SSmaEnv)); + if (pEnv == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + int code = pthread_rwlock_init(&(pEnv->lock), NULL); + if (code) { + terrno = TAOS_SYSTEM_ERROR(code); + free(pEnv); + return NULL; + } + + ASSERT(path && (strlen(path) > 0)); + pEnv->path = strdup(path); + if (pEnv->path == NULL) { + tsdbFreeSmaEnv(pEnv); + return NULL; + } + + if (tsdbInitSmaStat(&pEnv->pStat) != TSDB_CODE_SUCCESS) { + tsdbFreeSmaEnv(pEnv); + return NULL; + } + + if (tsdbOpenBDBEnv(&pEnv->dbEnv, pEnv->path) != TSDB_CODE_SUCCESS) { + tsdbFreeSmaEnv(pEnv); + return NULL; + } + + return pEnv; +} -static int32_t tsdbInitTSmaReadH(STSmaReadH *pSmaH, STsdb *pTsdb, STSma *param, STSmaData *pData); -static int32_t tsdbInitTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWindow *queryWin); -static bool tsdbSetAndOpenTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWindow *queryWin); +static int32_t tsdbInitSmaEnv(STsdb *pTsdb, const char *path, SSmaEnv **pEnv) { + if (!pEnv) { + terrno = TSDB_CODE_INVALID_PTR; + return TSDB_CODE_FAILED; + } + + if (pEnv && *pEnv) { + return TSDB_CODE_SUCCESS; + } + + if (tsdbLockRepo(pTsdb) != 0) { + return TSDB_CODE_FAILED; + } + + if (*pEnv == NULL) { + if ((*pEnv = tsdbNewSmaEnv(pTsdb, path)) == NULL) { + tsdbUnlockRepo(pTsdb); + return TSDB_CODE_FAILED; + } + } + + if (tsdbUnlockRepo(pTsdb) != 0) { + tsdbFreeSmaEnv(*pEnv); + return TSDB_CODE_FAILED; + } + + return TSDB_CODE_SUCCESS; +} + +/** + * @brief Release resources allocated for its member fields, not including itself. + * + * @param pSmaEnv + * @return int32_t + */ +void tsdbDestroySmaEnv(SSmaEnv *pSmaEnv) { + if (pSmaEnv) { + tsdbDestroySmaState(pSmaEnv->pStat); + tfree(pSmaEnv->pStat); + tfree(pSmaEnv->path); + pthread_rwlock_destroy(&(pSmaEnv->lock)); + tsdbCloseBDBEnv(pSmaEnv->dbEnv); + } +} + +void *tsdbFreeSmaEnv(SSmaEnv *pSmaEnv) { + tsdbDestroySmaEnv(pSmaEnv); + tfree(pSmaEnv); + return NULL; +} + +static int32_t tsdbInitSmaStat(SSmaStat **pSmaStat) { + ASSERT(pSmaStat != NULL); + + if (*pSmaStat != NULL) { // no lock + return TSDB_CODE_SUCCESS; + } + + // TODO: lock. lazy mode when update expired window, or hungry mode during tsdbNew. + if (*pSmaStat == NULL) { + *pSmaStat = (SSmaStat *)calloc(1, sizeof(SSmaStat)); + if (*pSmaStat == NULL) { + // TODO: unlock + terrno = TSDB_CODE_OUT_OF_MEMORY; + return TSDB_CODE_FAILED; + } + + (*pSmaStat)->smaStatItems = + taosHashInit(SMA_STATE_HASH_SLOT, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + + if ((*pSmaStat)->smaStatItems == NULL) { + tfree(*pSmaStat); + // TODO: unlock + return TSDB_CODE_FAILED; + } + } + // TODO: unlock + return TSDB_CODE_SUCCESS; +} + +static SSmaStatItem *tsdbNewSmaStatItem(int8_t state) { + SSmaStatItem *pItem = NULL; + + pItem = (SSmaStatItem *)calloc(1, sizeof(SSmaStatItem)); + if (pItem) { + pItem->state = state; + pItem->expiredWindows = taosHashInit(SMA_STATE_ITEM_HASH_SLOT, taosGetDefaultHashFunction(TSDB_DATA_TYPE_TIMESTAMP), + true, HASH_ENTRY_LOCK); + if (!pItem->expiredWindows) { + tfree(pItem); + } + } + return pItem; +} + +/** + * @brief Release resources allocated for its member fields, not including itself. + * + * @param pSmaStat + * @return int32_t + */ +int32_t tsdbDestroySmaState(SSmaStat *pSmaStat) { + if (pSmaStat) { + // TODO: use taosHashSetFreeFp when taosHashSetFreeFp is ready. + SSmaStatItem *item = taosHashIterate(pSmaStat->smaStatItems, NULL); + while (item != NULL) { + tfree(item->pSma); + taosHashCleanup(item->expiredWindows); + item = taosHashIterate(pSmaStat->smaStatItems, item); + } + taosHashCleanup(pSmaStat->smaStatItems); + } +} + +/** + * @brief Update expired window according to msg from stream computing module. + * + * @param pTsdb + * @param smaType ETsdbSmaType + * @param msg + * @return int32_t + */ +int32_t tsdbUpdateExpiredWindow(STsdb *pTsdb, int8_t smaType, char *msg) { + STsdbCfg *pCfg = REPO_CFG(pTsdb); + SSmaEnv * pEnv = NULL; + + if (!msg || !pTsdb->pMeta) { + terrno = TSDB_CODE_INVALID_PTR; + return TSDB_CODE_FAILED; + } + + char smaPath[TSDB_FILENAME_LEN] = "/proj/.sma/"; + if (tsdbInitSmaEnv(pTsdb, smaPath, &pEnv) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_FAILED; + } + + if (smaType == TSDB_SMA_TYPE_TIME_RANGE) { + pTsdb->pTSmaEnv = pEnv; + } else if (smaType == TSDB_SMA_TYPE_ROLLUP) { + pTsdb->pRSmaEnv = pEnv; + } else { + ASSERT(0); + } + + // TODO: decode the msg => start + int64_t indexUid = SMA_TEST_INDEX_UID; + // const char * indexName = SMA_TEST_INDEX_NAME; + const int32_t SMA_TEST_EXPIRED_WINDOW_SIZE = 10; + TSKEY expiredWindows[SMA_TEST_EXPIRED_WINDOW_SIZE]; + int64_t now = taosGetTimestampMs(); + for (int32_t i = 0; i < SMA_TEST_EXPIRED_WINDOW_SIZE; ++i) { + expiredWindows[i] = now + i; + } + + // TODO: decode the msg <= end + SHashObj *pItemsHash = SMA_ENV_STAT_ITEMS(pEnv); + + SSmaStatItem *pItem = (SSmaStatItem *)taosHashGet(pItemsHash, &indexUid, sizeof(indexUid)); + if (pItem == NULL) { + pItem = tsdbNewSmaStatItem(TSDB_SMA_STAT_EXPIRED); // TODO use the real state + if (pItem == NULL) { + // Response to stream computing: OOM + // For query, if the indexName not found, the TSDB should tell query module to query raw TS data. + return TSDB_CODE_FAILED; + } + + // cache smaMeta + STSma *pSma = metaGetSmaInfoByIndex(pTsdb->pMeta, indexUid); + if (pSma == NULL) { + terrno = TSDB_CODE_TDB_NO_SMA_INDEX_IN_META; + taosHashCleanup(pItem->expiredWindows); + free(pItem); + tsdbWarn("vgId:%d update expired window failed for smaIndex %" PRIi64 " since %s", REPO_ID(pTsdb), indexUid, + tstrerror(terrno)); + return TSDB_CODE_FAILED; + } + pItem->pSma = pSma; + + // TODO: change indexName to indexUid + if (taosHashPut(pItemsHash, &indexUid, sizeof(indexUid), &pItem, sizeof(pItem)) != 0) { + // If error occurs during put smaStatItem, free the resources of pItem + taosHashCleanup(pItem->expiredWindows); + free(pItem); + return TSDB_CODE_FAILED; + } + } +#if 0 + SSmaStatItem *pItem1 = (SSmaStatItem *)taosHashGet(pItemsHash, &indexUid, sizeof(indexUid)); + int size1 = taosHashGetSize(pItem1->expiredWindows); + tsdbWarn("vgId:%d smaIndex %" PRIi64 " size is %d before hashPut", REPO_ID(pTsdb), indexUid, size1); +#endif + + int8_t state = TSDB_SMA_STAT_EXPIRED; + for (int32_t i = 0; i < SMA_TEST_EXPIRED_WINDOW_SIZE; ++i) { + if (taosHashPut(pItem->expiredWindows, &expiredWindows[i], sizeof(TSKEY), &state, sizeof(state)) != 0) { + // If error occurs during taosHashPut expired windows, remove the smaIndex from pTsdb->pSmaStat, thus TSDB would + // tell query module to query raw TS data. + // N.B. + // 1) It is assumed to be extemely little probability event of fail to taosHashPut. + // 2) This would solve the inconsistency to some extent, but not completely, unless we record all expired + // windows failed to put into hash table. + taosHashCleanup(pItem->expiredWindows); + tfree(pItem->pSma); + taosHashRemove(pItemsHash, &indexUid, sizeof(indexUid)); + return TSDB_CODE_FAILED; + } + } + +#if 0 + SSmaStatItem *pItem2 = (SSmaStatItem *)taosHashGet(pItemsHash, &indexUid, sizeof(indexUid)); + int size2 = taosHashGetSize(pItem1->expiredWindows); + tsdbWarn("vgId:%d smaIndex %" PRIi64 " size is %d after hashPut", REPO_ID(pTsdb), indexUid, size2); +#endif + + return TSDB_CODE_SUCCESS; +} + +static int32_t tsdbResetExpiredWindow(SSmaStat *pStat, int64_t indexUid, TSKEY skey) { + SSmaStatItem *pItem = NULL; + + // TODO: If HASH_ENTRY_LOCK used, whether rwlock needed to handle cases of removing hashNode? + if (pStat && pStat->smaStatItems) { + pItem = (SSmaStatItem *)taosHashGet(pStat->smaStatItems, &indexUid, sizeof(indexUid)); + } +#if 0 + if (pItem != NULL) { + // TODO: reset time window for the sma data blocks + if (taosHashRemove(pItem->expiredWindows, &skey, sizeof(TSKEY)) != 0) { + // error handling + } + + } else { + // error handling + } +#endif + return TSDB_CODE_SUCCESS; +} /** * @brief Judge the tSma storage level @@ -71,7 +375,7 @@ static bool tsdbSetAndOpenTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWin * @param intervalUnit * @return int32_t */ -static int32_t tsdbJudgeStorageLevel(int64_t interval, int8_t intervalUnit) { +static int32_t tsdbGetSmaStorageLevel(int64_t interval, int8_t intervalUnit) { // TODO: configurable for SMA_STORAGE_SPLIT_HOURS? switch (intervalUnit) { case TD_TIME_UNIT_HOUR: @@ -111,18 +415,35 @@ static int32_t tsdbJudgeStorageLevel(int64_t interval, int8_t intervalUnit) { } /** - * @brief Insert TSma data blocks to B+Tree + * @brief Insert TSma data blocks to DB File build by B+Tree * - * @param bTree + * @param pSmaH * @param smaKey + * @param keyLen * @param pData * @param dataLen * @return int32_t */ -static int32_t tsdbInsertTSmaBlocks(void *bTree, const char *smaKey, const char *pData, int32_t dataLen) { +static int32_t tsdbInsertTSmaBlocks(STSmaWriteH *pSmaH, void *smaKey, uint32_t keyLen, void *pData, uint32_t dataLen) { + SDBFile *pDBFile = &pSmaH->dFile; + // TODO: insert sma data blocks into B+Tree - printf("insert sma data blocks into B+Tree: smaKey %" PRIx64 "-%" PRIu16 "-%" PRIx64 ", dataLen %d\n", - *(uint64_t *)smaKey, *(uint16_t *)POINTER_SHIFT(smaKey, 8), *(int64_t *)POINTER_SHIFT(smaKey, 10), dataLen); + tsdbDebug("vgId:%d insert sma data blocks into %s: smaKey %" PRIx64 "-%" PRIu16 "-%" PRIx64 ", dataLen %d", + REPO_ID(pSmaH->pTsdb), pDBFile->path, *(tb_uid_t *)smaKey, *(uint16_t *)POINTER_SHIFT(smaKey, 8), + *(int64_t *)POINTER_SHIFT(smaKey, 10), dataLen); + + if (tsdbSaveSmaToDB(pDBFile, smaKey, keyLen, pData, dataLen) != 0) { + return TSDB_CODE_FAILED; + } + +#ifdef SMA_PRINT_DEBUG_LOG + uint32_t valueSize = 0; + void * data = tsdbGetSmaDataByKey(pDBFile, smaKey, keyLen, &valueSize); + ASSERT(data != NULL); + for (uint32_t v = 0; v < valueSize; v += 8) { + tsdbWarn("vgId:%d sma data - val[%d] is %" PRIi64, REPO_ID(pSmaH->pTsdb), v, *(int64_t *)POINTER_SHIFT(data, v)); + } +#endif return TSDB_CODE_SUCCESS; } @@ -154,41 +475,41 @@ static int64_t tsdbGetIntervalByPrecision(int64_t interval, uint8_t intervalUnit } } - switch (intervalUnit) { - case TD_TIME_UNIT_MILLISEC: - if (TSDB_TIME_PRECISION_MILLI == precision) { + switch (precision) { + case TSDB_TIME_PRECISION_MILLI: + if (TD_TIME_UNIT_MICROSEC == intervalUnit) { // us + return interval / 1e3; + } else if (TD_TIME_UNIT_NANOSEC == intervalUnit) { // nano second + return interval / 1e6; + } else { return interval; - } else if (TSDB_TIME_PRECISION_MICRO == precision) { - return interval * 1e3; - } else { // nano second - return interval * 1e6; } break; - case TD_TIME_UNIT_MICROSEC: - if (TSDB_TIME_PRECISION_MILLI == precision) { - return interval / 1e3; - } else if (TSDB_TIME_PRECISION_MICRO == precision) { + case TSDB_TIME_PRECISION_MICRO: + if (TD_TIME_UNIT_MICROSEC == intervalUnit) { // us return interval; - } else { // nano second + } else if (TD_TIME_UNIT_NANOSEC == intervalUnit) { // nano second + return interval / 1e3; + } else { return interval * 1e3; } break; - case TD_TIME_UNIT_NANOSEC: - if (TSDB_TIME_PRECISION_MILLI == precision) { - return interval / 1e6; - } else if (TSDB_TIME_PRECISION_MICRO == precision) { - return interval / 1e3; - } else { // nano second + case TSDB_TIME_PRECISION_NANO: + if (TD_TIME_UNIT_MICROSEC == intervalUnit) { + return interval * 1e3; + } else if (TD_TIME_UNIT_NANOSEC == intervalUnit) { // nano second return interval; + } else { + return interval * 1e6; } break; - default: - if (TSDB_TIME_PRECISION_MILLI == precision) { - return interval * 1e3; - } else if (TSDB_TIME_PRECISION_MICRO == precision) { - return interval * 1e6; - } else { // nano second - return interval * 1e9; + default: // ms + if (TD_TIME_UNIT_MICROSEC == intervalUnit) { // us + return interval / 1e3; + } else if (TD_TIME_UNIT_NANOSEC == intervalUnit) { // nano second + return interval / 1e6; + } else { + return interval; } break; } @@ -204,84 +525,85 @@ static int64_t tsdbGetIntervalByPrecision(int64_t interval, uint8_t intervalUnit * @param nBlocks The nBlocks with the same fid since nOffset. * @return int32_t */ -static int32_t tsdbInsertTSmaDataSection(STSmaWriteH *pSmaH, STSmaData *pData, int32_t nOffset, int32_t nBlocks) { +static int32_t tsdbInsertTSmaDataSection(STSmaWriteH *pSmaH, STSmaDataWrapper *pData) { STsdb *pTsdb = pSmaH->pTsdb; - TASSERT(pData->colIds != NULL); - - tsdbDebug("tsdbInsertTSmaDataSection: nOffset %d, nBlocks %d", nOffset, nBlocks); - printf("tsdbInsertTSmaDataSection: nOffset %d, nBlocks %d\n", nOffset, nBlocks); - - int32_t colDataLen = pData->dataLen / pData->numOfColIds; - int32_t sectionDataLen = pSmaH->blockSize * nBlocks; - - for (col_id_t i = 0; i < pData->numOfColIds; ++i) { - // param: pointer of B+Tree, key, value, dataLen - void *bTree = pSmaH->pDFile; -#ifndef SMA_STORE_SINGLE_BLOCKS - // save tSma data blocks as a whole - char smaKey[SMA_KEY_LEN] = {0}; - void *pSmaKey = &smaKey; - tsdbEncodeTSmaKey(pData->tableUid, *(pData->colIds + i), pData->tsWindow.skey + nOffset * pSmaH->interval, - (void **)&pSmaKey); - if (tsdbInsertTSmaBlocks(bTree, smaKey, pData->data + i * colDataLen + nOffset * pSmaH->blockSize, sectionDataLen) < - 0) { - tsdbWarn("vgId:%d insert tSma blocks failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + tsdbDebug("tsdbInsertTSmaDataSection: index %" PRIi64 ", skey %" PRIi64, pData->indexUid, pData->skey); + + // TODO: check the data integrity + + int32_t len = 0; + while (true) { + if (len >= pData->dataLen) { + break; } -#else - // save tSma data blocks separately - for (int32_t n = 0; n < nBlocks; ++n) { - char smaKey[SMA_KEY_LEN] = {0}; - void *pSmaKey = &smaKey; - tsdbEncodeTSmaKey(pData->tableUid, *(pData->colIds + i), pData->tsWindow.skey + (nOffset + n) * pSmaH->interval, - (void **)&pSmaKey); - if (tsdbInsertTSmaBlocks(bTree, smaKey, pData->data + i * colDataLen + (nOffset + n) * pSmaH->blockSize, - pSmaH->blockSize) < 0) { + assert(pData->dataLen > 0); + STSmaTbData *pTbData = (STSmaTbData *)POINTER_SHIFT(pData->data, len); + + int32_t tbLen = 0; + while (true) { + if (tbLen >= pTbData->dataLen) { + break; + } + assert(pTbData->dataLen > 0); + STSmaColData *pColData = (STSmaColData *)POINTER_SHIFT(pTbData->data, tbLen); + char smaKey[SMA_KEY_LEN] = {0}; + void * pSmaKey = &smaKey; +#if 0 + printf("tsdbInsertTSmaDataSection: index %" PRIi64 ", skey %" PRIi64 " table[%" PRIi64 "]col[%" PRIu16 "]\n", + pData->indexUid, pData->skey, pTbData->tableUid, pColData->colId); +#endif + tsdbEncodeTSmaKey(pTbData->tableUid, pColData->colId, pData->skey, (void **)&pSmaKey); + if (tsdbInsertTSmaBlocks(pSmaH, smaKey, SMA_KEY_LEN, pColData->data, pColData->blockSize) < 0) { tsdbWarn("vgId:%d insert tSma blocks failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); } + tbLen += (sizeof(STSmaColData) + pColData->blockSize); } -#endif + len += (sizeof(STSmaTbData) + pTbData->dataLen); } + return TSDB_CODE_SUCCESS; } -static int32_t tsdbInitTSmaWriteH(STSmaWriteH *pSmaH, STsdb *pTsdb, STSma *param, STSmaData *pData) { +static int32_t tsdbInitTSmaWriteH(STSmaWriteH *pSmaH, STsdb *pTsdb, STSmaDataWrapper *pData) { pSmaH->pTsdb = pTsdb; - pSmaH->interval = tsdbGetIntervalByPrecision(param->interval, param->intervalUnit, REPO_CFG(pTsdb)->precision); - pSmaH->blockSize = param->numOfFuncIds * sizeof(int64_t); + pSmaH->interval = tsdbGetIntervalByPrecision(pData->interval, pData->intervalUnit, REPO_CFG(pTsdb)->precision); + return TSDB_CODE_SUCCESS; } -static int32_t tsdbSetTSmaDataFile(STSmaWriteH *pSmaH, STSma *param, STSmaData *pData, int32_t storageLevel, - int32_t fid) { - // TODO - pSmaH->pDFile = "tSma_interval_file_name"; +static void tsdbDestroyTSmaWriteH(STSmaWriteH *pSmaH) { + if (pSmaH) { + tsdbCloseDBF(&pSmaH->dFile); + } +} +static int32_t tsdbSetTSmaDataFile(STSmaWriteH *pSmaH, STSmaDataWrapper *pData, int32_t storageLevel, int32_t fid) { + STsdb *pTsdb = pSmaH->pTsdb; + ASSERT(pSmaH->dFile.path == NULL && pSmaH->dFile.pDB == NULL); + char tSmaFile[TSDB_FILENAME_LEN] = {0}; + snprintf(tSmaFile, TSDB_FILENAME_LEN, "v%df%d.tsma", REPO_ID(pTsdb), fid); + pSmaH->dFile.path = strdup(tSmaFile); return TSDB_CODE_SUCCESS; -} /** - * @brief Split the sma data blocks by fid. - * - * @param pSmaH - * @param param - * @param pData - * @param nOffset - * @param fid - * @param nSmaBlocks - * @return int32_t - */ -static int32_t tsdbTSmaDataSplit(STSmaWriteH *pSmaH, STSma *param, STSmaData *pData, int32_t days, int32_t nOffset, - int32_t fid, int32_t *nSmaBlocks) { - STsdbCfg *pCfg = REPO_CFG(pSmaH->pTsdb); - - // TODO: use binary search - for (int32_t n = nOffset + 1; n < pData->numOfBlocks; ++n) { - // TODO: The tsWindow.skey should use the precision of DB. - int32_t tFid = (int32_t)(TSDB_KEY_FID(pData->tsWindow.skey + pSmaH->interval * n, days, pCfg->precision)); - if (tFid > fid) { - *nSmaBlocks = n - nOffset; - break; - } +} + +/** + * @brief + * + * @param pTsdb + * @param interval Interval calculated by DB's precision + * @param storageLevel + * @return int32_t + */ +static int32_t tsdbGetTSmaDays(STsdb *pTsdb, int64_t interval, int32_t storageLevel) { + STsdbCfg *pCfg = REPO_CFG(pTsdb); + int32_t daysPerFile = pCfg->daysPerFile; + + if (storageLevel == SMA_STORAGE_LEVEL_TSDB) { + int32_t days = SMA_STORAGE_TSDB_TIMES * (interval / tsTickPerDay[pCfg->precision]); + daysPerFile = days > SMA_STORAGE_TSDB_DAYS ? days : SMA_STORAGE_TSDB_DAYS; } - return TSDB_CODE_SUCCESS; + + return daysPerFile; } /** @@ -293,150 +615,136 @@ static int32_t tsdbTSmaDataSplit(STSmaWriteH *pSmaH, STSma *param, STSmaData *pD * - The destination file of one data block for some interval is determined by its start TS key. * * @param pTsdb - * @param param - * @param pData + * @param msg * @return int32_t */ -int32_t tsdbInsertTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData) { - STsdbCfg * pCfg = REPO_CFG(pTsdb); - STSmaData * curData = pData; - STSmaWriteH tSmaH = {0}; +static int32_t tsdbInsertTSmaDataImpl(STsdb *pTsdb, char *msg) { + STsdbCfg * pCfg = REPO_CFG(pTsdb); + STSmaDataWrapper *pData = (STSmaDataWrapper *)msg; - tsdbInitTSmaWriteH(&tSmaH, pTsdb, param, pData); + if (!pTsdb->pTSmaEnv) { + terrno = TSDB_CODE_INVALID_PTR; + tsdbWarn("vgId:%d insert tSma data failed since pTSmaEnv is NULL", REPO_ID(pTsdb)); + return terrno; + } - if (pData->numOfBlocks <= 0 || pData->numOfColIds <= 0 || pData->dataLen <= 0) { + if (pData->dataLen <= 0) { TASSERT(0); terrno = TSDB_CODE_INVALID_PARA; - return terrno; + return TSDB_CODE_FAILED; } - // Step 1: Judge the storage level - int32_t storageLevel = tsdbJudgeStorageLevel(param->interval, param->intervalUnit); - int32_t daysPerFile = storageLevel == SMA_STORAGE_LEVEL_TSDB ? SMA_STORAGE_TSDB_DAYS : pCfg->daysPerFile; - - // Step 2: Set the DFile for storage of SMA index, and iterate/split the TSma data and store to B+Tree index file - // - Set and open the DFile or the B+Tree file + STSmaWriteH tSmaH = {0}; - int32_t minFid = (int32_t)(TSDB_KEY_FID(pData->tsWindow.skey, daysPerFile, pCfg->precision)); - int32_t maxFid = (int32_t)(TSDB_KEY_FID(pData->tsWindow.ekey, daysPerFile, pCfg->precision)); - - if (minFid == maxFid) { - // Save all the TSma data to one file - // TODO: tsdbStartTSmaCommit(); - tsdbSetTSmaDataFile(&tSmaH, param, pData, storageLevel, minFid); - tsdbInsertTSmaDataSection(&tSmaH, pData, 0, pData->numOfBlocks); - // TODO:tsdbEndTSmaCommit(); - } else if (minFid < maxFid) { - // Split the TSma data and save to multiple files. As there is limit for the span, it can't span more than 2 files - // actually. - // TODO: tsdbStartTSmaCommit(); - int32_t tFid = minFid; - int32_t nOffset = 0; - int32_t nSmaBlocks = 0; - do { - tsdbTSmaDataSplit(&tSmaH, param, pData, daysPerFile, nOffset, tFid, &nSmaBlocks); - tsdbSetTSmaDataFile(&tSmaH, param, pData, storageLevel, tFid); - if (tsdbInsertTSmaDataSection(&tSmaH, pData, nOffset, nSmaBlocks) < 0) { - return terrno; - } + if (tsdbInitTSmaWriteH(&tSmaH, pTsdb, pData) != 0) { + return TSDB_CODE_FAILED; + } - ++tFid; - nOffset += nSmaBlocks; + // Step 1: Judge the storage level and days + int32_t storageLevel = tsdbGetSmaStorageLevel(pData->interval, pData->intervalUnit); + int32_t daysPerFile = tsdbGetTSmaDays(pTsdb, tSmaH.interval, storageLevel); + int32_t fid = (int32_t)(TSDB_KEY_FID(pData->skey, daysPerFile, pCfg->precision)); - if (tFid == maxFid) { - tsdbSetTSmaDataFile(&tSmaH, param, pData, storageLevel, tFid); - tsdbInsertTSmaDataSection(&tSmaH, pData, nOffset, pData->numOfBlocks - nOffset); - break; - } - } while (true); + // Step 2: Set the DFile for storage of SMA index, and iterate/split the TSma data and store to B+Tree index file + // - Set and open the DFile or the B+Tree file + // TODO: tsdbStartTSmaCommit(); + tsdbSetTSmaDataFile(&tSmaH, pData, storageLevel, fid); + if (tsdbOpenDBF(pTsdb->pTSmaEnv->dbEnv, &tSmaH.dFile) != 0) { + tsdbWarn("vgId:%d open DB file %s failed since %s", REPO_ID(pTsdb), + tSmaH.dFile.path ? tSmaH.dFile.path : "path is NULL", tstrerror(terrno)); + tsdbDestroyTSmaWriteH(&tSmaH); + return TSDB_CODE_FAILED; + } - // TODO:tsdbEndTSmaCommit(); - } else { - terrno = TSDB_CODE_INVALID_PARA; - return terrno; + if (tsdbInsertTSmaDataSection(&tSmaH, pData) != 0) { + tsdbWarn("vgId:%d insert tSma data section failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + tsdbDestroyTSmaWriteH(&tSmaH); + return TSDB_CODE_FAILED; } + // TODO:tsdbEndTSmaCommit(); + + // Step 3: reset the SSmaStat + tsdbResetExpiredWindow(SMA_ENV_STAT(pTsdb->pTSmaEnv), pData->indexUid, pData->skey); + tsdbDestroyTSmaWriteH(&tSmaH); return TSDB_CODE_SUCCESS; } -static int32_t tsdbSetRSmaDataFile(STSmaWriteH *pSmaH, SRSma *param, STSmaData *pData, int32_t fid) { - // TODO - pSmaH->pDFile = "rSma_interval_file_name"; +static int32_t tsdbSetRSmaDataFile(STSmaWriteH *pSmaH, STSmaDataWrapper *pData, int32_t fid) { + STsdb *pTsdb = pSmaH->pTsdb; + + char tSmaFile[TSDB_FILENAME_LEN] = {0}; + snprintf(tSmaFile, TSDB_FILENAME_LEN, "v%df%d.rsma", REPO_ID(pTsdb), fid); + pSmaH->dFile.path = strdup(tSmaFile); return TSDB_CODE_SUCCESS; } -int32_t tsdbInsertRSmaDataImpl(STsdb *pTsdb, SRSma *param, STSmaData *pData) { - STsdbCfg * pCfg = REPO_CFG(pTsdb); - STSma * tParam = ¶m->tsma; - STSmaData * curData = pData; - STSmaWriteH tSmaH = {0}; +static int32_t tsdbInsertRSmaDataImpl(STsdb *pTsdb, char *msg) { + STsdbCfg * pCfg = REPO_CFG(pTsdb); + STSmaDataWrapper *pData = (STSmaDataWrapper *)msg; + STSmaWriteH tSmaH = {0}; - tsdbInitTSmaWriteH(&tSmaH, pTsdb, tParam, pData); - - int32_t nSmaBlocks = pData->numOfBlocks; - int32_t colDataLen = pData->dataLen / nSmaBlocks; - - // Step 2.2: Storage of SMA_STORAGE_LEVEL_DFILESET - // TODO: Use the daysPerFile for rSma data, not for TS data. - // TODO: The lifecycle of rSma data should be processed like the TS data files. - int32_t minFid = (int32_t)(TSDB_KEY_FID(pData->tsWindow.skey, pCfg->daysPerFile, pCfg->precision)); - int32_t maxFid = (int32_t)(TSDB_KEY_FID(pData->tsWindow.ekey, pCfg->daysPerFile, pCfg->precision)); - - if (minFid == maxFid) { - // Save all the TSma data to one file - tsdbSetRSmaDataFile(&tSmaH, param, pData, minFid); - // TODO: tsdbStartTSmaCommit(); - tsdbInsertTSmaDataSection(&tSmaH, pData, colDataLen, nSmaBlocks); - // TODO:tsdbEndTSmaCommit(); - } else if (minFid < maxFid) { - // Split the TSma data and save to multiple files. As there is limit for the span, it can't span more than 2 files - // actually. - // TODO: tsdbStartTSmaCommit(); - int32_t tmpFid = 0; - int32_t step = 0; - for (int32_t n = 0; n < pData->numOfBlocks; ++n) { - } - tsdbInsertTSmaDataSection(&tSmaH, pData, colDataLen, nSmaBlocks); - // TODO:tsdbEndTSmaCommit(); - } else { + tsdbInitTSmaWriteH(&tSmaH, pTsdb, pData); + + if (pData->dataLen <= 0) { TASSERT(0); - return TSDB_CODE_INVALID_PARA; + terrno = TSDB_CODE_INVALID_PARA; + return terrno; } - // Step 4: finish + + // Step 1: Judge the storage level + int32_t storageLevel = tsdbGetSmaStorageLevel(pData->interval, pData->intervalUnit); + int32_t daysPerFile = storageLevel == SMA_STORAGE_LEVEL_TSDB ? SMA_STORAGE_TSDB_DAYS : pCfg->daysPerFile; + + // Step 2: Set the DFile for storage of SMA index, and iterate/split the TSma data and store to B+Tree index file + // - Set and open the DFile or the B+Tree file + + int32_t fid = (int32_t)(TSDB_KEY_FID(pData->skey, daysPerFile, pCfg->precision)); + + // Save all the TSma data to one file + // TODO: tsdbStartTSmaCommit(); + tsdbSetTSmaDataFile(&tSmaH, pData, storageLevel, fid); + + tsdbInsertTSmaDataSection(&tSmaH, pData); + // TODO:tsdbEndTSmaCommit(); + + // reset the SSmaStat + tsdbResetExpiredWindow(SMA_ENV_STAT(pTsdb->pRSmaEnv), pData->indexUid, pData->skey); + return TSDB_CODE_SUCCESS; } /** - * @brief Init of tSma ReadH + * @brief * * @param pSmaH * @param pTsdb - * @param param - * @param pData + * @param interval + * @param intervalUnit * @return int32_t */ -static int32_t tsdbInitTSmaReadH(STSmaReadH *pSmaH, STsdb *pTsdb, STSma *param, STSmaData *pData) { +static int32_t tsdbInitTSmaReadH(STSmaReadH *pSmaH, STsdb *pTsdb, int64_t interval, int8_t intervalUnit) { pSmaH->pTsdb = pTsdb; - pSmaH->interval = tsdbGetIntervalByPrecision(param->interval, param->intervalUnit, REPO_CFG(pTsdb)->precision); - pSmaH->blockSize = param->numOfFuncIds * sizeof(int64_t); + pSmaH->interval = tsdbGetIntervalByPrecision(interval, intervalUnit, REPO_CFG(pTsdb)->precision); + pSmaH->storageLevel = tsdbGetSmaStorageLevel(interval, intervalUnit); + pSmaH->days = tsdbGetTSmaDays(pTsdb, pSmaH->interval, pSmaH->storageLevel); } /** * @brief Init of tSma FS * * @param pReadH - * @param param - * @param queryWin + * @param skey * @return int32_t */ -static int32_t tsdbInitTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWindow *queryWin) { - int32_t storageLevel = tsdbJudgeStorageLevel(param->interval, param->intervalUnit); - int32_t daysPerFile = - storageLevel == SMA_STORAGE_LEVEL_TSDB ? SMA_STORAGE_TSDB_DAYS : REPO_CFG(pReadH->pTsdb)->daysPerFile; - pReadH->storageLevel = storageLevel; - pReadH->days = daysPerFile; - pReadH->smaFsIter.iter = 0; +static int32_t tsdbInitTSmaFile(STSmaReadH *pSmaH, TSKEY skey) { + int32_t fid = (int32_t)(TSDB_KEY_FID(skey, pSmaH->days, REPO_CFG(pSmaH->pTsdb)->precision)); + char tSmaFile[TSDB_FILENAME_LEN] = {0}; + snprintf(tSmaFile, TSDB_FILENAME_LEN, "v%df%d.tsma", REPO_ID(pSmaH->pTsdb), fid); + pSmaH->dFile.path = strdup(tSmaFile); + pSmaH->smaFsIter.iter = 0; + pSmaH->smaFsIter.fid = fid; } /** @@ -448,17 +756,18 @@ static int32_t tsdbInitTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWindow *q * @return true * @return false */ -static bool tsdbSetAndOpenTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWindow *queryWin) { - SArray *smaFs = pReadH->pTsdb->fs->cstatus->smaf; +static bool tsdbSetAndOpenTSmaFile(STSmaReadH *pReadH, TSKEY *queryKey) { + SArray *smaFs = pReadH->pTsdb->fs->cstatus->sf; int32_t nSmaFs = taosArrayGetSize(smaFs); - pReadH->pDFile = NULL; + tsdbCloseDBF(&pReadH->dFile); +#if 0 while (pReadH->smaFsIter.iter < nSmaFs) { void *pSmaFile = taosArrayGet(smaFs, pReadH->smaFsIter.iter); if (pSmaFile) { // match(indexName, queryWindow) // TODO: select the file by index_name ... - pReadH->pDFile = pSmaFile; + pReadH->dFile = pSmaFile; ++pReadH->smaFsIter.iter; break; } @@ -469,26 +778,83 @@ static bool tsdbSetAndOpenTSmaFile(STSmaReadH *pReadH, STSma *param, STimeWindow tsdbDebug("vg%d: smaFile %s matched", REPO_ID(pReadH->pTsdb), "[pSmaFile dir]"); return true; } +#endif return false; } /** - * @brief Return the data between queryWin and fill the pData. + * @brief * - * @param pTsdb - * @param param + * @param pTsdb Return the data between queryWin and fill the pData. * @param pData - * @param queryWin + * @param indexUid + * @param interval + * @param intervalUnit + * @param tableUid + * @param colId + * @param pQuerySKey * @param nMaxResult The query invoker should control the nMaxResult need to return to avoid OOM. * @return int32_t */ -int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData, STimeWindow *queryWin, int32_t nMaxResult) { +static int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSmaDataWrapper *pData, int64_t indexUid, int64_t interval, + int8_t intervalUnit, tb_uid_t tableUid, col_id_t colId, TSKEY querySkey, + int32_t nMaxResult) { + SSmaStatItem *pItem = (SSmaStatItem *)taosHashGet(SMA_ENV_STAT_ITEMS(pTsdb->pTSmaEnv), &indexUid, sizeof(indexUid)); + if (pItem == NULL) { + // mark all window as expired and notify query module to query raw TS data. + return TSDB_CODE_SUCCESS; + } + +#if 0 + int32_t nQueryWin = taosArrayGetSize(pQuerySKey); + for (int32_t n = 0; n < nQueryWin; ++n) { + TSKEY skey = taosArrayGet(pQuerySKey, n); + if (taosHashGet(pItem->expiredWindows, &skey, sizeof(TSKEY)) != NULL) { + // TODO: mark this window as expired. + } + } +#endif +#if 0 + if (taosHashGet(pItem->expiredWindows, &querySkey, sizeof(TSKEY)) != NULL) { + // TODO: mark this window as expired. + } +#endif STSmaReadH tReadH = {0}; - tsdbInitTSmaReadH(&tReadH, pTsdb, param, pData); + tsdbInitTSmaReadH(&tReadH, pTsdb, interval, intervalUnit); + tsdbCloseDBF(&tReadH.dFile); - tsdbInitTSmaFile(&tReadH, param, queryWin); + tsdbInitTSmaFile(&tReadH, querySkey); + if (tsdbOpenDBF(SMA_ENV_ENV(pTsdb->pTSmaEnv), &tReadH.dFile) != 0) { + tsdbWarn("vgId:%d open DBF %s failed since %s", REPO_ID(pTsdb), tReadH.dFile.path, tstrerror(terrno)); + return TSDB_CODE_FAILED; + } + char smaKey[SMA_KEY_LEN] = {0}; + void *pSmaKey = &smaKey; + tsdbEncodeTSmaKey(tableUid, colId, querySkey, (void **)&pSmaKey); + + tsdbDebug("vgId:%d get sma data from %s: smaKey %" PRIx64 "-%" PRIu16 "-%" PRIx64 ", keyLen %d", REPO_ID(pTsdb), + tReadH.dFile.path, *(tb_uid_t *)smaKey, *(uint16_t *)POINTER_SHIFT(smaKey, 8), + *(int64_t *)POINTER_SHIFT(smaKey, 10), SMA_KEY_LEN); + + void * result = NULL; + uint32_t valueSize = 0; + if ((result = tsdbGetSmaDataByKey(&tReadH.dFile, smaKey, SMA_KEY_LEN, &valueSize)) == NULL) { + tsdbWarn("vgId:%d get sma data failed from smaIndex %" PRIi64 ", smaKey %" PRIx64 "-%" PRIu16 "-%" PRIx64 + " since %s", + REPO_ID(pTsdb), indexUid, *(tb_uid_t *)smaKey, *(uint16_t *)POINTER_SHIFT(smaKey, 8), + *(int64_t *)POINTER_SHIFT(smaKey, 10), tstrerror(terrno)); + tsdbCloseDBF(&tReadH.dFile); + return TSDB_CODE_FAILED; + } + tfree(result); +#ifdef SMA_PRINT_DEBUG_LOG + for (uint32_t v = 0; v < valueSize; v += 8) { + tsdbWarn("vgId:%d v[%d]=%" PRIi64, REPO_ID(pTsdb), v, *(int64_t *)POINTER_SHIFT(result, v)); + } +#endif +#if 0 int32_t nResult = 0; int64_t lastKey = 0; @@ -498,7 +864,7 @@ int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData, STimeW } // set and open the file according to the STSma param - if (tsdbSetAndOpenTSmaFile(&tReadH, param, queryWin)) { + if (tsdbSetAndOpenTSmaFile(&tReadH, queryWin)) { char bTree[100] = "\0"; while (strncmp(bTree, "has more nodes", 100) == 0) { if (nResult >= nMaxResult) { @@ -510,11 +876,13 @@ int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData, STimeW } } } - +#endif // read data from file and fill the result + tsdbCloseDBF(&tReadH.dFile); return TSDB_CODE_SUCCESS; } +#if 0 /** * @brief Get the start TS key of the last data block of one interval/sliding. * @@ -525,7 +893,7 @@ int32_t tsdbGetTSmaDataImpl(STsdb *pTsdb, STSma *param, STSmaData *pData, STimeW * 1) Return 0 and fill the result if the check procedure is normal; * 2) Return -1 if error occurs during the check procedure. */ -int32_t tsdbGetTSmaStatus(STsdb *pTsdb, STSma *param, void *result) { +int32_t tsdbGetTSmaStatus(STsdb *pTsdb, void *smaIndex, void *result) { const char *procedure = ""; if (strncmp(procedure, "get the start TS key of the last data block", 100) != 0) { return -1; @@ -542,9 +910,61 @@ int32_t tsdbGetTSmaStatus(STsdb *pTsdb, STSma *param, void *result) { * @param pWin * @return int32_t */ -int32_t tsdbRemoveTSmaData(STsdb *pTsdb, STSma *param, STimeWindow *pWin) { +int32_t tsdbRemoveTSmaData(STsdb *pTsdb, void *smaIndex, STimeWindow *pWin) { // for ("tSmaFiles of param-interval-sliding between pWin") { // // remove the tSmaFile // } return TSDB_CODE_SUCCESS; +} +#endif + +/** + * @brief Insert/Update tSma(Time-range-wise SMA) data from stream computing engine + * + * @param pTsdb + * @param param + * @param msg + * @return int32_t + * TODO: Who is responsible for resource allocate and release? + */ +int32_t tsdbInsertTSmaData(STsdb *pTsdb, char *msg) { + int32_t code = TSDB_CODE_SUCCESS; + if ((code = tsdbInsertTSmaDataImpl(pTsdb, msg)) < 0) { + tsdbWarn("vgId:%d insert tSma data failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + } + return code; +} + +int32_t tsdbUpdateSmaWindow(STsdb *pTsdb, int8_t smaType, char *msg) { + int32_t code = TSDB_CODE_SUCCESS; + if ((code = tsdbUpdateExpiredWindow(pTsdb, smaType, msg)) < 0) { + tsdbWarn("vgId:%d update expired sma window failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + } + return code; +} + +/** + * @brief Insert Time-range-wise Rollup Sma(RSma) data + * + * @param pTsdb + * @param param + * @param msg + * @return int32_t + */ +int32_t tsdbInsertRSmaData(STsdb *pTsdb, char *msg) { + int32_t code = TSDB_CODE_SUCCESS; + if ((code = tsdbInsertRSmaDataImpl(pTsdb, msg)) < 0) { + tsdbWarn("vgId:%d insert rSma data failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + } + return code; +} + +int32_t tsdbGetTSmaData(STsdb *pTsdb, STSmaDataWrapper *pData, int64_t indexUid, int64_t interval, int8_t intervalUnit, + tb_uid_t tableUid, col_id_t colId, TSKEY querySkey, int32_t nMaxResult) { + int32_t code = TSDB_CODE_SUCCESS; + if ((code = tsdbGetTSmaDataImpl(pTsdb, pData, indexUid, interval, intervalUnit, tableUid, colId, querySkey, + nMaxResult)) < 0) { + tsdbWarn("vgId:%d get tSma data failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + } + return code; } \ No newline at end of file diff --git a/source/dnode/vnode/src/tsdb/tsdbWrite.c b/source/dnode/vnode/src/tsdb/tsdbWrite.c index ba8eea809ed05a74c7cd1bff04993b666cb58f7d..3ccb483fe48c459b52dcd783ec62ee45ad9e4112 100644 --- a/source/dnode/vnode/src/tsdb/tsdbWrite.c +++ b/source/dnode/vnode/src/tsdb/tsdbWrite.c @@ -34,35 +34,46 @@ int tsdbInsertData(STsdb *pTsdb, SSubmitReq *pMsg, SSubmitRsp *pRsp) { return tsdbMemTableInsert(pTsdb, pTsdb->mem, pMsg, NULL); } +#if 0 /** * @brief Insert/Update tSma(Time-range-wise SMA) data from stream computing engine * * @param pTsdb * @param param - * @param pData + * @param msg * @return int32_t * TODO: Who is responsible for resource allocate and release? */ -int32_t tsdbInsertTSmaData(STsdb *pTsdb, STSma *param, STSmaData *pData) { +int32_t tsdbInsertTSmaData(STsdb *pTsdb, char *msg) { int32_t code = TSDB_CODE_SUCCESS; - if ((code = tsdbInsertTSmaDataImpl(pTsdb, param, pData)) < 0) { + if ((code = tsdbInsertTSmaDataImpl(pTsdb, msg)) < 0) { tsdbWarn("vgId:%d insert tSma data failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); } return code; } +int32_t tsdbUpdateSmaWindow(STsdb *pTsdb, int8_t smaType, char *msg) { + int32_t code = TSDB_CODE_SUCCESS; + if ((code = tsdbUpdateExpiredWindow(pTsdb, smaType, msg)) < 0) { + tsdbWarn("vgId:%d update expired sma window failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); + } + return code; +} + /** * @brief Insert Time-range-wise Rollup Sma(RSma) data * * @param pTsdb * @param param - * @param pData + * @param msg * @return int32_t */ -int32_t tsdbInsertRSmaData(STsdb *pTsdb, SRSma *param, STSmaData *pData) { +int32_t tsdbInsertRSmaData(STsdb *pTsdb, char *msg) { int32_t code = TSDB_CODE_SUCCESS; - if ((code = tsdbInsertRSmaDataImpl(pTsdb, param, pData)) < 0) { + if ((code = tsdbInsertRSmaDataImpl(pTsdb, msg)) < 0) { tsdbWarn("vgId:%d insert rSma data failed since %s", REPO_ID(pTsdb), tstrerror(terrno)); } return code; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/source/dnode/vnode/src/vnd/vnodeMain.c b/source/dnode/vnode/src/vnd/vnodeMain.c index ba346064ae6216b92b62435a3ba1ec995d2cec52..2a3862c7cbf37de74506bdf217fe62ccdcfd6e52 100644 --- a/source/dnode/vnode/src/vnd/vnodeMain.c +++ b/source/dnode/vnode/src/vnd/vnodeMain.c @@ -154,5 +154,6 @@ static void vnodeCloseImpl(SVnode *pVnode) { tsdbClose(pVnode->pTsdb); tqClose(pVnode->pTq); walClose(pVnode->pWal); + vnodeQueryClose(pVnode); } } diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c index ccb59c26de2a1a69f6a351b8c683b063f22fbd13..e8bc6873ab0a34ed56d1455857be81c26a2ade54 100644 --- a/source/dnode/vnode/src/vnd/vnodeQuery.c +++ b/source/dnode/vnode/src/vnd/vnodeQuery.c @@ -24,6 +24,10 @@ int vnodeQueryOpen(SVnode *pVnode) { (putReqToQueryQFp)vnodePutReqToVQueryQ, (sendReqToDnodeFp)vnodeSendReqToDnode); } +void vnodeQueryClose(SVnode *pVnode) { + qWorkerDestroy((void **)&pVnode->pQuery); +} + int vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) { vTrace("message in query queue is processing"); SReadHandle handle = {.reader = pVnode->pTsdb, .meta = pVnode->pMeta}; @@ -64,6 +68,8 @@ int vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg) { return vnodeGetTableMeta(pVnode, pMsg); case TDMT_VND_CONSUME: return tqProcessPollReq(pVnode->pTq, pMsg); + case TDMT_VND_QUERY_HEARTBEAT: + return qWorkerProcessHbMsg(pVnode, pVnode->pQuery, pMsg); default: vError("unknown msg type:%d in fetch queue", pMsg->msgType); return TSDB_CODE_VND_APP_ERROR; diff --git a/source/dnode/vnode/test/tqMetaTest.cpp b/source/dnode/vnode/test/tqMetaTest.cpp index d3c9b50e4abd884903f50b2bf5d10bd8ec71eb00..4f1518525476127241401741c371f0a8071dc6d9 100644 --- a/source/dnode/vnode/test/tqMetaTest.cpp +++ b/source/dnode/vnode/test/tqMetaTest.cpp @@ -168,10 +168,10 @@ TEST_F(TqMetaUpdateAppendTest, intxnPersist) { } TEST_F(TqMetaUpdateAppendTest, multiplePage) { - srand(0); + taosSeedRand(0); std::vector v; for (int i = 0; i < 1000; i++) { - v.push_back(rand()); + v.push_back(taosRand()); Foo foo; foo.a = v[i]; tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo)); @@ -202,10 +202,10 @@ TEST_F(TqMetaUpdateAppendTest, multiplePage) { } TEST_F(TqMetaUpdateAppendTest, multipleRewrite) { - srand(0); + taosSeedRand(0); std::vector v; for (int i = 0; i < 1000; i++) { - v.push_back(rand()); + v.push_back(taosRand()); Foo foo; foo.a = v[i]; tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo)); @@ -213,14 +213,14 @@ TEST_F(TqMetaUpdateAppendTest, multipleRewrite) { for (int i = 0; i < 500; i++) { tqHandleCommit(pMeta, i); - v[i] = rand(); + v[i] = taosRand(); Foo foo; foo.a = v[i]; tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo)); } for (int i = 500; i < 1000; i++) { - v[i] = rand(); + v[i] = taosRand(); Foo foo; foo.a = v[i]; tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo)); @@ -235,7 +235,7 @@ TEST_F(TqMetaUpdateAppendTest, multipleRewrite) { ASSERT(pMeta); for (int i = 500; i < 1000; i++) { - v[i] = rand(); + v[i] = taosRand(); Foo foo; foo.a = v[i]; tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo)); @@ -250,10 +250,10 @@ TEST_F(TqMetaUpdateAppendTest, multipleRewrite) { } TEST_F(TqMetaUpdateAppendTest, dupCommit) { - srand(0); + taosSeedRand(0); std::vector v; for (int i = 0; i < 1000; i++) { - v.push_back(rand()); + v.push_back(taosRand()); Foo foo; foo.a = v[i]; tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo)); diff --git a/source/dnode/vnode/test/tsdbSmaTest.cpp b/source/dnode/vnode/test/tsdbSmaTest.cpp index f3a61bdfa4213bf6a8c135e6c92dd24df4ad0fea..18dca33bdaf73e4ebcd95a1623960514b26667a3 100644 --- a/source/dnode/vnode/test/tsdbSmaTest.cpp +++ b/source/dnode/vnode/test/tsdbSmaTest.cpp @@ -20,6 +20,7 @@ #include #include +#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wwrite-strings" @@ -32,7 +33,7 @@ int main(int argc, char **argv) { return RUN_ALL_TESTS(); } -TEST(testCase, tSmaEncodeDecodeTest) { +TEST(testCase, tSma_Meta_Encode_Decode_Test) { // encode STSma tSma = {0}; tSma.version = 0; @@ -41,18 +42,9 @@ TEST(testCase, tSmaEncodeDecodeTest) { tSma.slidingUnit = TD_TIME_UNIT_HOUR; tSma.sliding = 0; tstrncpy(tSma.indexName, "sma_index_test", TSDB_INDEX_NAME_LEN); + tstrncpy(tSma.timezone, "Asia/Shanghai", TD_TIMEZONE_LEN); + tSma.indexUid = 2345678910; tSma.tableUid = 1234567890; - tSma.numOfColIds = 2; - tSma.numOfFuncIds = 5; // sum/min/max/avg/last - tSma.colIds = (col_id_t *)calloc(tSma.numOfColIds, sizeof(col_id_t)); - tSma.funcIds = (uint16_t *)calloc(tSma.numOfFuncIds, sizeof(uint16_t)); - - for (int32_t i = 0; i < tSma.numOfColIds; ++i) { - *(tSma.colIds + i) = (i + PRIMARYKEY_TIMESTAMP_COL_ID); - } - for (int32_t i = 0; i < tSma.numOfFuncIds; ++i) { - *(tSma.funcIds + i) = (i + 2); - } STSmaWrapper tSmaWrapper = {.number = 1, .tSma = &tSma}; uint32_t bufLen = tEncodeTSmaWrapper(NULL, &tSmaWrapper); @@ -80,17 +72,15 @@ TEST(testCase, tSmaEncodeDecodeTest) { EXPECT_EQ(pSma->intervalUnit, qSma->intervalUnit); EXPECT_EQ(pSma->slidingUnit, qSma->slidingUnit); EXPECT_STRCASEEQ(pSma->indexName, qSma->indexName); - EXPECT_EQ(pSma->numOfColIds, qSma->numOfColIds); - EXPECT_EQ(pSma->numOfFuncIds, qSma->numOfFuncIds); + EXPECT_STRCASEEQ(pSma->timezone, qSma->timezone); + EXPECT_EQ(pSma->indexUid, qSma->indexUid); EXPECT_EQ(pSma->tableUid, qSma->tableUid); EXPECT_EQ(pSma->interval, qSma->interval); EXPECT_EQ(pSma->sliding, qSma->sliding); - for (uint32_t j = 0; j < pSma->numOfColIds; ++j) { - EXPECT_EQ(*(col_id_t *)(pSma->colIds + j), *(col_id_t *)(qSma->colIds + j)); - } - for (uint32_t j = 0; j < pSma->numOfFuncIds; ++j) { - EXPECT_EQ(*(uint16_t *)(pSma->funcIds + j), *(uint16_t *)(qSma->funcIds + j)); - } + EXPECT_EQ(pSma->exprLen, qSma->exprLen); + EXPECT_STRCASEEQ(pSma->expr, qSma->expr); + EXPECT_EQ(pSma->tagsFilterLen, qSma->tagsFilterLen); + EXPECT_STRCASEEQ(pSma->tagsFilter, qSma->tagsFilter); } // resource release @@ -98,11 +88,17 @@ TEST(testCase, tSmaEncodeDecodeTest) { tdDestroyTSmaWrapper(&dstTSmaWrapper); } -TEST(testCase, tSma_DB_Put_Get_Del_Test) { - const char *smaIndexName1 = "sma_index_test_1"; - const char *smaIndexName2 = "sma_index_test_2"; - const char *smaTestDir = "./smaTest"; - const uint64_t tbUid = 1234567890; +#if 1 +TEST(testCase, tSma_metaDB_Put_Get_Del_Test) { + const char * smaIndexName1 = "sma_index_test_1"; + const char * smaIndexName2 = "sma_index_test_2"; + const char * timezone = "Asia/Shanghai"; + const char * expr = "select count(a,b, top 20), from table interval 1d, sliding 1h;"; + const char * tagsFilter = "I'm tags filter"; + const char * smaTestDir = "./smaTest"; + const tb_uid_t tbUid = 1234567890; + const int64_t indexUid1 = 2000000001; + const int64_t indexUid2 = 2000000002; const uint32_t nCntTSma = 2; // encode STSma tSma = {0}; @@ -111,22 +107,21 @@ TEST(testCase, tSma_DB_Put_Get_Del_Test) { tSma.interval = 1; tSma.slidingUnit = TD_TIME_UNIT_HOUR; tSma.sliding = 0; + tSma.indexUid = indexUid1; tstrncpy(tSma.indexName, smaIndexName1, TSDB_INDEX_NAME_LEN); + tstrncpy(tSma.timezone, timezone, TD_TIMEZONE_LEN); tSma.tableUid = tbUid; - tSma.numOfColIds = 2; - tSma.numOfFuncIds = 5; // sum/min/max/avg/last - tSma.colIds = (col_id_t *)calloc(tSma.numOfColIds, sizeof(col_id_t)); - tSma.funcIds = (uint16_t *)calloc(tSma.numOfFuncIds, sizeof(uint16_t)); - for (int32_t i = 0; i < tSma.numOfColIds; ++i) { - *(tSma.colIds + i) = (i + PRIMARYKEY_TIMESTAMP_COL_ID); - } - for (int32_t i = 0; i < tSma.numOfFuncIds; ++i) { - *(tSma.funcIds + i) = (i + 2); - } + tSma.exprLen = strlen(expr); + tSma.expr = (char *)calloc(tSma.exprLen + 1, 1); + tstrncpy(tSma.expr, expr, tSma.exprLen + 1); + + tSma.tagsFilterLen = strlen(tagsFilter); + tSma.tagsFilter = (char *)calloc(tSma.tagsFilterLen + 1, 1); + tstrncpy(tSma.tagsFilter, tagsFilter, tSma.tagsFilterLen + 1); SMeta * pMeta = NULL; - STSma * pSmaCfg = &tSma; + STSma * pSmaCfg = &tSma; const SMetaCfg *pMetaCfg = &defaultMetaOptions; taosRemoveDir(smaTestDir); @@ -134,8 +129,9 @@ TEST(testCase, tSma_DB_Put_Get_Del_Test) { pMeta = metaOpen(smaTestDir, pMetaCfg, NULL); assert(pMeta != NULL); // save index 1 - metaSaveSmaToDB(pMeta, pSmaCfg); + EXPECT_EQ(metaSaveSmaToDB(pMeta, pSmaCfg), 0); + pSmaCfg->indexUid = indexUid2; tstrncpy(pSmaCfg->indexName, smaIndexName2, TSDB_INDEX_NAME_LEN); pSmaCfg->version = 1; pSmaCfg->intervalUnit = TD_TIME_UNIT_HOUR; @@ -144,21 +140,27 @@ TEST(testCase, tSma_DB_Put_Get_Del_Test) { pSmaCfg->sliding = 5; // save index 2 - metaSaveSmaToDB(pMeta, pSmaCfg); + EXPECT_EQ(metaSaveSmaToDB(pMeta, pSmaCfg), 0); // get value by indexName STSma *qSmaCfg = NULL; - qSmaCfg = metaGetSmaInfoByName(pMeta, smaIndexName1); + qSmaCfg = metaGetSmaInfoByIndex(pMeta, indexUid1); assert(qSmaCfg != NULL); printf("name1 = %s\n", qSmaCfg->indexName); + printf("timezone1 = %s\n", qSmaCfg->timezone); + printf("expr1 = %s\n", qSmaCfg->expr != NULL ? qSmaCfg->expr : ""); + printf("tagsFilter1 = %s\n", qSmaCfg->tagsFilter != NULL ? qSmaCfg->tagsFilter : ""); EXPECT_STRCASEEQ(qSmaCfg->indexName, smaIndexName1); EXPECT_EQ(qSmaCfg->tableUid, tSma.tableUid); tdDestroyTSma(qSmaCfg); tfree(qSmaCfg); - qSmaCfg = metaGetSmaInfoByName(pMeta, smaIndexName2); + qSmaCfg = metaGetSmaInfoByIndex(pMeta, indexUid2); assert(qSmaCfg != NULL); printf("name2 = %s\n", qSmaCfg->indexName); + printf("timezone2 = %s\n", qSmaCfg->timezone); + printf("expr2 = %s\n", qSmaCfg->expr != NULL ? qSmaCfg->expr : ""); + printf("tagsFilter2 = %s\n", qSmaCfg->tagsFilter != NULL ? qSmaCfg->tagsFilter : ""); EXPECT_STRCASEEQ(qSmaCfg->indexName, smaIndexName2); EXPECT_EQ(qSmaCfg->interval, tSma.interval); tdDestroyTSma(qSmaCfg); @@ -169,7 +171,7 @@ TEST(testCase, tSma_DB_Put_Get_Del_Test) { assert(pSmaCur != NULL); uint32_t indexCnt = 0; while (1) { - const char* indexName = metaSmaCursorNext(pSmaCur); + const char *indexName = metaSmaCursorNext(pSmaCur); if (indexName == NULL) { break; } @@ -180,14 +182,22 @@ TEST(testCase, tSma_DB_Put_Get_Del_Test) { metaCloseSmaCurosr(pSmaCur); // get wrapper by table uid - STSmaWrapper *pSW = metaGetSmaInfoByUid(pMeta, tbUid); + STSmaWrapper *pSW = metaGetSmaInfoByTable(pMeta, tbUid); assert(pSW != NULL); EXPECT_EQ(pSW->number, nCntTSma); EXPECT_STRCASEEQ(pSW->tSma->indexName, smaIndexName1); - EXPECT_EQ(pSW->tSma->tableUid, tSma.tableUid); + EXPECT_STRCASEEQ(pSW->tSma->timezone, timezone); + EXPECT_STRCASEEQ(pSW->tSma->expr, expr); + EXPECT_STRCASEEQ(pSW->tSma->tagsFilter, tagsFilter); + EXPECT_EQ(pSW->tSma->indexUid, indexUid1); + EXPECT_EQ(pSW->tSma->tableUid, tbUid); EXPECT_STRCASEEQ((pSW->tSma + 1)->indexName, smaIndexName2); - EXPECT_EQ((pSW->tSma + 1)->tableUid, tSma.tableUid); - + EXPECT_STRCASEEQ((pSW->tSma + 1)->timezone, timezone); + EXPECT_STRCASEEQ((pSW->tSma + 1)->expr, expr); + EXPECT_STRCASEEQ((pSW->tSma + 1)->tagsFilter, tagsFilter); + EXPECT_EQ((pSW->tSma + 1)->indexUid, indexUid2); + EXPECT_EQ((pSW->tSma + 1)->tableUid, tbUid); + tdDestroyTSmaWrapper(pSW); tfree(pSW); @@ -208,44 +218,164 @@ TEST(testCase, tSma_DB_Put_Get_Del_Test) { tdDestroyTSma(&tSma); metaClose(pMeta); } +#endif -#if 0 -TEST(testCase, tSmaInsertTest) { - STSma tSma = {0}; - STSmaData* pSmaData = NULL; - STsdb tsdb = {0}; - - // init +#if 1 +TEST(testCase, tSma_Data_Insert_Query_Test) { + // step 1: prepare meta + const char * smaIndexName1 = "sma_index_test_1"; + const char * timezone = "Asia/Shanghai"; + const char * expr = "select count(a,b, top 20), from table interval 1d, sliding 1h;"; + const char * tagsFilter = "where tags.location='Beijing' and tags.district='ChaoYang'"; + const char * smaTestDir = "./smaTest"; + const tb_uid_t tbUid = 1234567890; + const int64_t indexUid1 = 2000000001; + const int64_t interval1 = 1; + const int8_t intervalUnit1 = TD_TIME_UNIT_DAY; + const uint32_t nCntTSma = 2; + TSKEY skey1 = 1646987196; + const int64_t testSmaData1 = 100; + const int64_t testSmaData2 = 200; + // encode + STSma tSma = {0}; + tSma.version = 0; tSma.intervalUnit = TD_TIME_UNIT_DAY; tSma.interval = 1; - tSma.numOfFuncIds = 5; // sum/min/max/avg/last - - int32_t blockSize = tSma.numOfFuncIds * sizeof(int64_t); - int32_t numOfColIds = 3; - int32_t numOfBlocks = 10; - - int32_t dataLen = numOfColIds * numOfBlocks * blockSize; - - pSmaData = (STSmaData*)malloc(sizeof(STSmaData) + dataLen); - ASSERT_EQ(pSmaData != NULL, true); - pSmaData->tableUid = 3232329230; - pSmaData->numOfColIds = numOfColIds; - pSmaData->numOfBlocks = numOfBlocks; - pSmaData->dataLen = dataLen; - pSmaData->tsWindow.skey = 1640000000; - pSmaData->tsWindow.ekey = 1645788649; - pSmaData->colIds = (col_id_t*)malloc(sizeof(col_id_t) * numOfColIds); - ASSERT_EQ(pSmaData->colIds != NULL, true); - - for (int32_t i = 0; i < numOfColIds; ++i) { - *(pSmaData->colIds + i) = (i + PRIMARYKEY_TIMESTAMP_COL_ID); + tSma.slidingUnit = TD_TIME_UNIT_HOUR; + tSma.sliding = 0; + tSma.indexUid = indexUid1; + tstrncpy(tSma.indexName, smaIndexName1, TSDB_INDEX_NAME_LEN); + tstrncpy(tSma.timezone, timezone, TD_TIMEZONE_LEN); + tSma.tableUid = tbUid; + + tSma.exprLen = strlen(expr); + tSma.expr = (char *)calloc(tSma.exprLen + 1, 1); + tstrncpy(tSma.expr, expr, tSma.exprLen + 1); + + tSma.tagsFilterLen = strlen(tagsFilter); + tSma.tagsFilter = (char *)calloc(tSma.tagsFilterLen + 1, 1); + tstrncpy(tSma.tagsFilter, tagsFilter, tSma.tagsFilterLen + 1); + + SMeta * pMeta = NULL; + STSma * pSmaCfg = &tSma; + const SMetaCfg *pMetaCfg = &defaultMetaOptions; + + taosRemoveDir(smaTestDir); + + pMeta = metaOpen(smaTestDir, pMetaCfg, NULL); + assert(pMeta != NULL); + // save index 1 + EXPECT_EQ(metaSaveSmaToDB(pMeta, pSmaCfg), 0); + + // step 2: insert data + STSmaDataWrapper *pSmaData = NULL; + STsdb tsdb = {0}; + STsdbCfg * pCfg = &tsdb.config; + + tsdb.pMeta = pMeta; + tsdb.vgId = 2; + tsdb.config.daysPerFile = 10; // default days is 10 + tsdb.config.keep1 = 30; + tsdb.config.keep2 = 90; + tsdb.config.keep = 365; + tsdb.config.precision = TSDB_TIME_PRECISION_MILLI; + tsdb.config.update = TD_ROW_OVERWRITE_UPDATE; + tsdb.config.compression = TWO_STAGE_COMP; + + switch (tsdb.config.precision) { + case TSDB_TIME_PRECISION_MILLI: + skey1 *= 1e3; + break; + case TSDB_TIME_PRECISION_MICRO: + skey1 *= 1e6; + break; + case TSDB_TIME_PRECISION_NANO: + skey1 *= 1e9; + break; + default: // ms + skey1 *= 1e3; + break; } + char *msg = (char *)calloc(100, 1); + EXPECT_EQ(tsdbUpdateSmaWindow(&tsdb, TSDB_SMA_TYPE_TIME_RANGE, msg), 0); + + // init + int32_t allocCnt = 0; + int32_t allocStep = 40960; + int32_t buffer = 4096; + void * buf = NULL; + EXPECT_EQ(tsdbMakeRoom(&buf, allocStep), 0); + int32_t bufSize = taosTSizeof(buf); + int32_t numOfTables = 10; + col_id_t numOfCols = 4096; + EXPECT_GT(numOfCols, 0); + + pSmaData = (STSmaDataWrapper *)buf; + printf(">> allocate [%d] time to %d and addr is %p\n", ++allocCnt, bufSize, pSmaData); + pSmaData->skey = skey1; + pSmaData->interval = interval1; + pSmaData->intervalUnit = intervalUnit1; + pSmaData->indexUid = indexUid1; + + int32_t len = sizeof(STSmaDataWrapper); + for (int32_t t = 0; t < numOfTables; ++t) { + STSmaTbData *pTbData = (STSmaTbData *)POINTER_SHIFT(pSmaData, len); + pTbData->tableUid = tbUid + t; + + int32_t tableDataLen = sizeof(STSmaTbData); + for (col_id_t c = 0; c < numOfCols; ++c) { + if (bufSize - len - tableDataLen < buffer) { + EXPECT_EQ(tsdbMakeRoom(&buf, bufSize + allocStep), 0); + pSmaData = (STSmaDataWrapper *)buf; + pTbData = (STSmaTbData *)POINTER_SHIFT(pSmaData, len); + bufSize = taosTSizeof(buf); + printf(">> allocate [%d] time to %d and addr is %p\n", ++allocCnt, bufSize, pSmaData); + } + STSmaColData *pColData = (STSmaColData *)POINTER_SHIFT(pSmaData, len + tableDataLen); + pColData->colId = c + PRIMARYKEY_TIMESTAMP_COL_ID; + + // TODO: fill col data + if ((c & 1) == 0) { + pColData->blockSize = 8; + memcpy(pColData->data, &testSmaData1, 8); + } else { + pColData->blockSize = 16; + memcpy(pColData->data, &testSmaData1, 8); + memcpy(POINTER_SHIFT(pColData->data, 8), &testSmaData2, 8); + } + + tableDataLen += (sizeof(STSmaColData) + pColData->blockSize); + } + pTbData->dataLen = (tableDataLen - sizeof(STSmaTbData)); + len += tableDataLen; + // printf("bufSize=%d, len=%d, len of table[%d]=%d\n", bufSize, len, t, tableDataLen); + } + pSmaData->dataLen = (len - sizeof(STSmaDataWrapper)); + + EXPECT_GE(bufSize, pSmaData->dataLen); + // execute - EXPECT_EQ(tsdbInsertTSmaData(&tsdb, &tSma, pSmaData), TSDB_CODE_SUCCESS); + EXPECT_EQ(tsdbInsertTSmaData(&tsdb, (char *)pSmaData), TSDB_CODE_SUCCESS); + + // step 3: query + uint32_t checkDataCnt = 0; + for (int32_t t = 0; t < numOfTables; ++t) { + for (col_id_t c = 0; c < numOfCols; ++c) { + EXPECT_EQ(tsdbGetTSmaData(&tsdb, NULL, indexUid1, interval1, intervalUnit1, tbUid + t, + c + PRIMARYKEY_TIMESTAMP_COL_ID, skey1, 1), + TSDB_CODE_SUCCESS); + ++checkDataCnt; + } + } + + printf("%s:%d The sma data check count for insert and query is %" PRIu32 "\n", __FILE__, __LINE__, checkDataCnt); - // release - tdDestroySmaData(pSmaData); + // release data + taosTZfree(buf); + // release meta + tdDestroyTSma(&tSma); + metaClose(pMeta); } #endif diff --git a/source/libs/catalog/src/catalog.c b/source/libs/catalog/src/catalog.c index 77d25fa1641f8d509d46335ca1aaa8f9622d8efb..e1ccb03c6653276e5c9ca438bb219dd2babd8e7d 100644 --- a/source/libs/catalog/src/catalog.c +++ b/source/libs/catalog/src/catalog.c @@ -558,6 +558,42 @@ int32_t ctgAcquireVgInfoFromCache(SCatalog* pCtg, const char *dbFName, SCtgDBCac return TSDB_CODE_SUCCESS; } +int32_t ctgGetQnodeListFromMnode(SCatalog* pCtg, void *pRpc, const SEpSet* pMgmtEps, SArray **out) { + char *msg = NULL; + int32_t msgLen = 0; + + ctgDebug("try to get qnode list from mnode, mgmtEpInUse:%d", pMgmtEps->inUse); + + int32_t code = queryBuildMsg[TMSG_INDEX(TDMT_MND_QNODE_LIST)](NULL, &msg, 0, &msgLen); + if (code) { + ctgError("Build qnode list msg failed, error:%s", tstrerror(code)); + CTG_ERR_RET(code); + } + + SRpcMsg rpcMsg = { + .msgType = TDMT_MND_QNODE_LIST, + .pCont = msg, + .contLen = msgLen, + }; + + SRpcMsg rpcRsp = {0}; + + rpcSendRecv(pRpc, (SEpSet*)pMgmtEps, &rpcMsg, &rpcRsp); + if (TSDB_CODE_SUCCESS != rpcRsp.code) { + ctgError("error rsp for qnode list, error:%s", tstrerror(rpcRsp.code)); + CTG_ERR_RET(rpcRsp.code); + } + + code = queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_QNODE_LIST)](out, rpcRsp.pCont, rpcRsp.contLen); + if (code) { + ctgError("Process qnode list rsp failed, error:%s", tstrerror(rpcRsp.code)); + CTG_ERR_RET(code); + } + + ctgDebug("Got qnode list from mnode, listNum:%d", (int32_t)taosArrayGetSize(*out)); + + return TSDB_CODE_SUCCESS; +} int32_t ctgGetDBVgInfoFromMnode(SCatalog* pCtg, void *pRpc, const SEpSet* pMgmtEps, SBuildUseDBInput *input, SUseDbOutput *out) { @@ -965,7 +1001,7 @@ int32_t ctgGetVgInfoFromHashValue(SCatalog *pCtg, SDBVgInfo *dbInfo, const SName CTG_RET(code); } -int32_t ctgStbVersionCompare(const void* key1, const void* key2) { +int32_t ctgStbVersionSearchCompare(const void* key1, const void* key2) { if (*(uint64_t *)key1 < ((SSTableMetaVersion*)key2)->suid) { return -1; } else if (*(uint64_t *)key1 > ((SSTableMetaVersion*)key2)->suid) { @@ -975,7 +1011,7 @@ int32_t ctgStbVersionCompare(const void* key1, const void* key2) { } } -int32_t ctgDbVgVersionCompare(const void* key1, const void* key2) { +int32_t ctgDbVgVersionSearchCompare(const void* key1, const void* key2) { if (*(int64_t *)key1 < ((SDbVgVersion*)key2)->dbId) { return -1; } else if (*(int64_t *)key1 > ((SDbVgVersion*)key2)->dbId) { @@ -985,6 +1021,27 @@ int32_t ctgDbVgVersionCompare(const void* key1, const void* key2) { } } +int32_t ctgStbVersionSortCompare(const void* key1, const void* key2) { + if (((SSTableMetaVersion*)key1)->suid < ((SSTableMetaVersion*)key2)->suid) { + return -1; + } else if (((SSTableMetaVersion*)key1)->suid > ((SSTableMetaVersion*)key2)->suid) { + return 1; + } else { + return 0; + } +} + +int32_t ctgDbVgVersionSortCompare(const void* key1, const void* key2) { + if (((SDbVgVersion*)key1)->dbId < ((SDbVgVersion*)key2)->dbId) { + return -1; + } else if (((SDbVgVersion*)key1)->dbId > ((SDbVgVersion*)key2)->dbId) { + return 1; + } else { + return 0; + } +} + + int32_t ctgMetaRentInit(SCtgRentMgmt *mgmt, uint32_t rentSec, int8_t type) { mgmt->slotRIdx = 0; mgmt->slotNum = rentSec / CTG_RENT_SLOT_SECOND; @@ -1034,7 +1091,7 @@ _return: CTG_RET(code); } -int32_t ctgMetaRentUpdate(SCtgRentMgmt *mgmt, void *meta, int64_t id, int32_t size, __compar_fn_t compare) { +int32_t ctgMetaRentUpdate(SCtgRentMgmt *mgmt, void *meta, int64_t id, int32_t size, __compar_fn_t sortCompare, __compar_fn_t searchCompare) { int16_t widx = abs(id % mgmt->slotNum); SCtgRentSlot *slot = &mgmt->slots[widx]; @@ -1048,12 +1105,12 @@ int32_t ctgMetaRentUpdate(SCtgRentMgmt *mgmt, void *meta, int64_t id, int32_t si if (slot->needSort) { qDebug("meta slot before sorte, slot idx:%d, type:%d, size:%d", widx, mgmt->type, (int32_t)taosArrayGetSize(slot->meta)); - taosArraySort(slot->meta, compare); + taosArraySort(slot->meta, sortCompare); slot->needSort = false; qDebug("meta slot sorted, slot idx:%d, type:%d, size:%d", widx, mgmt->type, (int32_t)taosArrayGetSize(slot->meta)); } - void *orig = taosArraySearch(slot->meta, &id, compare, TD_EQ); + void *orig = taosArraySearch(slot->meta, &id, searchCompare, TD_EQ); if (NULL == orig) { qError("meta not found in slot, id:%"PRIx64", slot idx:%d, type:%d, size:%d", id, widx, mgmt->type, (int32_t)taosArrayGetSize(slot->meta)); CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR); @@ -1075,8 +1132,8 @@ _return: CTG_RET(code); } -int32_t ctgMetaRentRemove(SCtgRentMgmt *mgmt, int64_t id, __compar_fn_t compare) { - int16_t widx = labs(id % mgmt->slotNum); +int32_t ctgMetaRentRemove(SCtgRentMgmt *mgmt, int64_t id, __compar_fn_t sortCompare, __compar_fn_t searchCompare) { + int16_t widx = abs(id % mgmt->slotNum); SCtgRentSlot *slot = &mgmt->slots[widx]; int32_t code = 0; @@ -1088,12 +1145,12 @@ int32_t ctgMetaRentRemove(SCtgRentMgmt *mgmt, int64_t id, __compar_fn_t compare) } if (slot->needSort) { - taosArraySort(slot->meta, compare); + taosArraySort(slot->meta, sortCompare); slot->needSort = false; qDebug("meta slot sorted, slot idx:%d, type:%d", widx, mgmt->type); } - int32_t idx = taosArraySearchIdx(slot->meta, &id, compare, TD_EQ); + int32_t idx = taosArraySearchIdx(slot->meta, &id, searchCompare, TD_EQ); if (idx < 0) { qError("meta not found in slot, id:%"PRIx64", slot idx:%d, type:%d", id, widx, mgmt->type); CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR); @@ -1240,7 +1297,7 @@ void ctgRemoveStbRent(SCatalog* pCtg, SCtgTbMetaCache *cache) { uint64_t *suid = NULL; suid = taosHashGetKey(pIter, NULL); - if (TSDB_CODE_SUCCESS == ctgMetaRentRemove(&pCtg->stbRent, *suid, ctgStbVersionCompare)) { + if (TSDB_CODE_SUCCESS == ctgMetaRentRemove(&pCtg->stbRent, *suid, ctgStbVersionSortCompare, ctgStbVersionSearchCompare)) { ctgDebug("stb removed from rent, suid:%"PRIx64, *suid); } @@ -1264,7 +1321,7 @@ int32_t ctgRemoveDB(SCatalog* pCtg, SCtgDBCache *dbCache, const char* dbFName) { ctgInfo("db removed from cache, dbFName:%s, dbId:%"PRIx64, dbFName, dbCache->dbId); - CTG_ERR_RET(ctgMetaRentRemove(&pCtg->dbRent, dbCache->dbId, ctgDbVgVersionCompare)); + CTG_ERR_RET(ctgMetaRentRemove(&pCtg->dbRent, dbCache->dbId, ctgDbVgVersionSortCompare, ctgDbVgVersionSearchCompare)); ctgDebug("db removed from rent, dbFName:%s, dbId:%"PRIx64, dbFName, dbCache->dbId); @@ -1331,7 +1388,7 @@ int32_t ctgUpdateDBVgInfo(SCatalog* pCtg, const char* dbFName, uint64_t dbId, SD } bool newAdded = false; - SDbVgVersion vgVersion = {.dbId = dbId, .vgVersion = dbInfo->vgVersion}; + SDbVgVersion vgVersion = {.dbId = dbId, .vgVersion = dbInfo->vgVersion, .numOfTable = dbInfo->numOfTable}; SCtgDBCache *dbCache = NULL; CTG_ERR_RET(ctgGetAddDBCache(pCtg, dbFName, dbId, &dbCache)); @@ -1344,8 +1401,15 @@ int32_t ctgUpdateDBVgInfo(SCatalog* pCtg, const char* dbFName, uint64_t dbId, SD CTG_ERR_RET(ctgWAcquireVgInfo(pCtg, dbCache)); if (dbCache->vgInfo) { - if (dbInfo->vgVersion <= dbCache->vgInfo->vgVersion) { - ctgInfo("db vgVersion is old, dbFName:%s, vgVersion:%d, currentVersion:%d", dbFName, dbInfo->vgVersion, dbCache->vgInfo->vgVersion); + if (dbInfo->vgVersion < dbCache->vgInfo->vgVersion) { + ctgDebug("db vgVersion is old, dbFName:%s, vgVersion:%d, currentVersion:%d", dbFName, dbInfo->vgVersion, dbCache->vgInfo->vgVersion); + ctgWReleaseVgInfo(dbCache); + + return TSDB_CODE_SUCCESS; + } + + if (dbInfo->vgVersion == dbCache->vgInfo->vgVersion && dbInfo->numOfTable == dbCache->vgInfo->numOfTable) { + ctgDebug("no new db vgVersion or numOfTable, dbFName:%s, vgVersion:%d, numOfTable:%d", dbFName, dbInfo->vgVersion, dbInfo->numOfTable); ctgWReleaseVgInfo(dbCache); return TSDB_CODE_SUCCESS; @@ -1365,7 +1429,7 @@ int32_t ctgUpdateDBVgInfo(SCatalog* pCtg, const char* dbFName, uint64_t dbId, SD dbCache = NULL; strncpy(vgVersion.dbFName, dbFName, sizeof(vgVersion.dbFName)); - CTG_ERR_RET(ctgMetaRentUpdate(&pCtg->dbRent, &vgVersion, vgVersion.dbId, sizeof(SDbVgVersion), ctgDbVgVersionCompare)); + CTG_ERR_RET(ctgMetaRentUpdate(&pCtg->dbRent, &vgVersion, vgVersion.dbId, sizeof(SDbVgVersion), ctgDbVgVersionSortCompare, ctgDbVgVersionSearchCompare)); CTG_RET(code); } @@ -1397,8 +1461,8 @@ int32_t ctgUpdateTblMeta(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFName, ui CTG_UNLOCK(CTG_WRITE, &tbCache->stbLock); ctgDebug("stb removed from stbCache, dbFName:%s, stb:%s, suid:%"PRIx64, dbFName, tbName, orig->suid); - - ctgMetaRentRemove(&pCtg->stbRent, orig->suid, ctgStbVersionCompare); + + ctgMetaRentRemove(&pCtg->stbRent, orig->suid, ctgStbVersionSortCompare, ctgStbVersionSearchCompare); } origSuid = orig->suid; @@ -1511,6 +1575,7 @@ int32_t ctgGetDBVgInfo(SCatalog* pCtg, void *pRpc, const SEpSet* pMgmtEps, const if (inCache) { input.dbId = (*dbCache)->dbId; input.vgVersion = (*dbCache)->vgInfo->vgVersion; + input.numOfTable = (*dbCache)->vgInfo->numOfTable; } else { input.vgVersion = CTG_DEFAULT_INVALID_VERSION; } @@ -1924,7 +1989,7 @@ int32_t ctgActRemoveStb(SCtgMetaAction *action) { ctgInfo("stb removed from cache, dbFName:%s, stbName:%s, suid:%"PRIx64, msg->dbFName, msg->stbName, msg->suid); - CTG_ERR_JRET(ctgMetaRentRemove(&msg->pCtg->stbRent, msg->suid, ctgStbVersionCompare)); + CTG_ERR_JRET(ctgMetaRentRemove(&msg->pCtg->stbRent, msg->suid, ctgStbVersionSortCompare, ctgStbVersionSearchCompare)); ctgDebug("stb removed from rent, dbFName:%s, stbName:%s, suid:%"PRIx64, msg->dbFName, msg->stbName, msg->suid); @@ -2163,7 +2228,7 @@ void catalogFreeHandle(SCatalog* pCtg) { ctgInfo("handle freed, culsterId:%"PRIx64, clusterId); } -int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId) { +int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId, int32_t *tableNum) { CTG_API_ENTER(); if (NULL == pCtg || NULL == dbFName || NULL == version || NULL == dbId) { @@ -2194,6 +2259,7 @@ int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* vers *version = dbCache->vgInfo->vgVersion; *dbId = dbCache->dbId; + *tableNum = dbCache->vgInfo->numOfTable; ctgReleaseVgInfo(dbCache); ctgReleaseDBCache(pCtg, dbCache); @@ -2572,6 +2638,10 @@ int32_t catalogGetAllMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, } } + if (pReq->qNodeRequired) { + CTG_ERR_JRET(ctgGetQnodeListFromMnode(pCtg, pTrans, pMgmtEps, &pRsp->pEpSetList)); + } + CTG_API_LEAVE(TSDB_CODE_SUCCESS); _return: @@ -2635,7 +2705,7 @@ void catalogDestroy(void) { tsem_post(&gCtgMgmt.sem); while (CTG_IS_LOCKED(&gCtgMgmt.lock)) { - usleep(1); + taosUsleep(1); } CTG_LOCK(CTG_WRITE, &gCtgMgmt.lock); diff --git a/source/libs/catalog/test/catalogTests.cpp b/source/libs/catalog/test/catalogTests.cpp index c7867c4da5be3b7ab06a13370050a5c6d43b28ef..cc0e5bb1a9b653a72e766a32b75b6cc3710cf4c6 100644 --- a/source/libs/catalog/test/catalogTests.cpp +++ b/source/libs/catalog/test/catalogTests.cpp @@ -723,7 +723,7 @@ void *ctgTestGetDbVgroupThread(void *param) { } if (ctgTestEnableSleep) { - usleep(rand() % 5); + taosUsleep(taosRand() % 5); } if (++n % ctgTestPrintNum == 0) { printf("Get:%d\n", n); @@ -747,7 +747,7 @@ void *ctgTestSetSameDbVgroupThread(void *param) { } if (ctgTestEnableSleep) { - usleep(rand() % 5); + taosUsleep(taosRand() % 5); } if (++n % ctgTestPrintNum == 0) { printf("Set:%d\n", n); @@ -771,7 +771,7 @@ void *ctgTestSetDiffDbVgroupThread(void *param) { } if (ctgTestEnableSleep) { - usleep(rand() % 5); + taosUsleep(taosRand() % 5); } if (++n % ctgTestPrintNum == 0) { printf("Set:%d\n", n); @@ -801,7 +801,7 @@ void *ctgTestGetCtableMetaThread(void *param) { tfree(tbMeta); if (ctgTestEnableSleep) { - usleep(rand() % 5); + taosUsleep(taosRand() % 5); } if (++n % ctgTestPrintNum == 0) { @@ -838,7 +838,7 @@ void *ctgTestSetCtableMetaThread(void *param) { } if (ctgTestEnableSleep) { - usleep(rand() % 5); + taosUsleep(taosRand() % 5); } if (++n % ctgTestPrintNum == 0) { printf("Set:%d\n", n); @@ -880,7 +880,7 @@ TEST(tableMeta, normalTable) { ASSERT_EQ(vgInfo.epSet.numOfEps, 3); while (0 == ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_DB_NUM)) { - usleep(50000); + taosMsleep(50); } ctgTestSetRspTableMeta(); @@ -901,7 +901,7 @@ TEST(tableMeta, normalTable) { while (true) { uint32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (0 == n) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -949,7 +949,7 @@ TEST(tableMeta, normalTable) { allDbNum += dbNum; allStbNum += stbNum; - sleep(2); + taosSsleep(2); } ASSERT_EQ(allDbNum, 1); @@ -996,7 +996,7 @@ TEST(tableMeta, childTableCase) { while (true) { uint32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (0 == n) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1058,7 +1058,7 @@ TEST(tableMeta, childTableCase) { allDbNum += dbNum; allStbNum += stbNum; - sleep(2); + taosSsleep(2); } ASSERT_EQ(allDbNum, 1); @@ -1105,7 +1105,7 @@ TEST(tableMeta, superTableCase) { while (true) { uint32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (0 == n) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1132,7 +1132,7 @@ TEST(tableMeta, superTableCase) { while (true) { uint32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (2 != n) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1181,7 +1181,7 @@ TEST(tableMeta, superTableCase) { allDbNum += dbNum; allStbNum += stbNum; - sleep(2); + taosSsleep(2); } ASSERT_EQ(allDbNum, 1); @@ -1230,7 +1230,7 @@ TEST(tableMeta, rmStbMeta) { while (true) { uint32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (0 == n) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1244,7 +1244,7 @@ TEST(tableMeta, rmStbMeta) { int32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); int32_t m = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_STB_RENT_NUM); if (n || m) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1300,7 +1300,7 @@ TEST(tableMeta, updateStbMeta) { while (true) { uint32_t n = ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (0 == n) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1320,7 +1320,7 @@ TEST(tableMeta, updateStbMeta) { uint64_t n = 0; ctgDbgGetStatNum("runtime.qDoneNum", (void *)&n); if (n != 3) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -1392,7 +1392,7 @@ TEST(refreshGetMeta, normal2normal) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } STableMeta *tableMeta = NULL; @@ -1410,7 +1410,7 @@ TEST(refreshGetMeta, normal2normal) { tfree(tableMeta); while (0 == ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM)) { - usleep(50000); + taosMsleep(50); } code = catalogRefreshGetTableMeta(pCtg, mockPointer, (const SEpSet *)mockPointer, &n, &tableMeta, 0); @@ -1471,7 +1471,7 @@ TEST(refreshGetMeta, normal2notexist) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } STableMeta *tableMeta = NULL; @@ -1489,7 +1489,7 @@ TEST(refreshGetMeta, normal2notexist) { tfree(tableMeta); while (0 == ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM)) { - usleep(50000); + taosMsleep(50); } code = catalogRefreshGetTableMeta(pCtg, mockPointer, (const SEpSet *)mockPointer, &n, &tableMeta, 0); @@ -1545,7 +1545,7 @@ TEST(refreshGetMeta, normal2child) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } STableMeta *tableMeta = NULL; @@ -1563,7 +1563,7 @@ TEST(refreshGetMeta, normal2child) { tfree(tableMeta); while (0 == ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM)) { - usleep(50000); + taosMsleep(50); } code = catalogRefreshGetTableMeta(pCtg, mockPointer, (const SEpSet *)mockPointer, &n, &tableMeta, 0); @@ -1629,7 +1629,7 @@ TEST(refreshGetMeta, stable2child) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } STableMeta *tableMeta = NULL; @@ -1648,7 +1648,7 @@ TEST(refreshGetMeta, stable2child) { tfree(tableMeta); while (0 == ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM)) { - usleep(50000); + taosMsleep(50); } ctgTestCurrentSTableName = ctgTestSTablename; @@ -1714,7 +1714,7 @@ TEST(refreshGetMeta, stable2stable) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } STableMeta *tableMeta = NULL; @@ -1733,7 +1733,7 @@ TEST(refreshGetMeta, stable2stable) { tfree(tableMeta); while (0 == ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM)) { - usleep(50000); + taosMsleep(50); } code = catalogRefreshGetTableMeta(pCtg, mockPointer, (const SEpSet *)mockPointer, &n, &tableMeta, 0); @@ -1802,7 +1802,7 @@ TEST(refreshGetMeta, child2stable) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } STableMeta *tableMeta = NULL; @@ -1819,7 +1819,7 @@ TEST(refreshGetMeta, child2stable) { tfree(tableMeta); while (2 != ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM)) { - usleep(50000); + taosMsleep(50); } ctgTestCurrentSTableName = ctgTestTablename; @@ -2019,7 +2019,7 @@ TEST(dbVgroup, getSetDbVgroupCase) { if (n > 0) { break; } - usleep(50000); + taosMsleep(50); } code = catalogGetTableHashVgroup(pCtg, mockPointer, (const SEpSet *)mockPointer, &n, &vgInfo); @@ -2043,7 +2043,7 @@ TEST(dbVgroup, getSetDbVgroupCase) { uint64_t n = 0; ctgDbgGetStatNum("runtime.qDoneNum", (void *)&n); if (n != 3) { - usleep(50000); + taosMsleep(50); } else { break; } @@ -2100,20 +2100,20 @@ TEST(multiThread, getSetRmSameDbVgroup) { pthread_t thread1, thread2; pthread_create(&(thread1), &thattr, ctgTestSetSameDbVgroupThread, pCtg); - sleep(1); + taosSsleep(1); pthread_create(&(thread2), &thattr, ctgTestGetDbVgroupThread, pCtg); while (true) { if (ctgTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(ctgTestMTRunSec); + taosSsleep(ctgTestMTRunSec); break; } } ctgTestStop = true; - sleep(1); + taosSsleep(1); catalogDestroy(); memset(&gCtgMgmt, 0, sizeof(gCtgMgmt)); @@ -2152,20 +2152,20 @@ TEST(multiThread, getSetRmDiffDbVgroup) { pthread_t thread1, thread2; pthread_create(&(thread1), &thattr, ctgTestSetDiffDbVgroupThread, pCtg); - sleep(1); + taosSsleep(1); pthread_create(&(thread2), &thattr, ctgTestGetDbVgroupThread, pCtg); while (true) { if (ctgTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(ctgTestMTRunSec); + taosSsleep(ctgTestMTRunSec); break; } } ctgTestStop = true; - sleep(1); + taosSsleep(1); catalogDestroy(); memset(&gCtgMgmt, 0, sizeof(gCtgMgmt)); @@ -2203,20 +2203,20 @@ TEST(multiThread, ctableMeta) { pthread_t thread1, thread2; pthread_create(&(thread1), &thattr, ctgTestSetCtableMetaThread, pCtg); - sleep(1); + taosSsleep(1); pthread_create(&(thread1), &thattr, ctgTestGetCtableMetaThread, pCtg); while (true) { if (ctgTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(ctgTestMTRunSec); + taosSsleep(ctgTestMTRunSec); break; } } ctgTestStop = true; - sleep(2); + taosSsleep(2); catalogDestroy(); memset(&gCtgMgmt, 0, sizeof(gCtgMgmt)); @@ -2267,7 +2267,7 @@ TEST(rentTest, allRent) { ASSERT_EQ(tableMeta->tableInfo.rowSize, 12); while (ctgDbgGetClusterCacheNum(pCtg, CTG_DBG_META_NUM) < i) { - usleep(50000); + taosMsleep(50); } code = catalogGetExpiredDBs(pCtg, &dbs, &num); @@ -2292,7 +2292,7 @@ TEST(rentTest, allRent) { } printf("*************************************************\n"); - sleep(2); + taosSsleep(2); } catalogDestroy(); diff --git a/source/libs/executor/inc/dataSinkInt.h b/source/libs/executor/inc/dataSinkInt.h index f15be8521c1298e75cbf8b66304a715a2f99dac0..8acb6f7e8d933153c4d35437529dfaf46acf6174 100644 --- a/source/libs/executor/inc/dataSinkInt.h +++ b/source/libs/executor/inc/dataSinkInt.h @@ -22,6 +22,7 @@ extern "C" { #include "tcommon.h" #include "dataSinkMgt.h" +#include "plannodes.h" struct SDataSink; struct SDataSinkHandle; @@ -45,7 +46,7 @@ typedef struct SDataSinkHandle { FDestroyDataSinker fDestroy; } SDataSinkHandle; -int32_t createDataDispatcher(SDataSinkManager* pManager, const struct SDataSink* pDataSink, DataSinkHandle* pHandle); +int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle); #ifdef __cplusplus } diff --git a/source/libs/executor/inc/executil.h b/source/libs/executor/inc/executil.h index 17f457e9918bee0fe50bd252072d78a8c3c172c9..b34067ba4e7e19e70a8033f6336b9e46d5f4086e 100644 --- a/source/libs/executor/inc/executil.h +++ b/source/libs/executor/inc/executil.h @@ -92,10 +92,11 @@ typedef struct SResultRowPool { struct STaskAttr; struct STaskRuntimeEnv; struct SUdfInfo; +struct SqlFunctionCtx; int32_t getOutputInterResultBufSize(struct STaskAttr* pQueryAttr); -size_t getResultRowSize(SArray* pExprInfo); +size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput); int32_t initResultRowInfo(SResultRowInfo* pResultRowInfo, int32_t size); void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo); @@ -111,7 +112,6 @@ void clearResultRow(struct STaskRuntimeEnv* pRuntimeEnv, SResultRow* pResultR struct SResultRowEntryInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_t* offset); void* destroyQueryFuncExpr(SExprInfo* pExprInfo, int32_t numOfExpr); -void* freeColumnInfo(SColumnInfo* pColumnInfo, int32_t numOfCols); int32_t getRowNumForMultioutput(struct STaskAttr* pQueryAttr, bool topBottomQuery, bool stable); static FORCE_INLINE SResultRow *getResultRow(SResultRowInfo *pResultRowInfo, int32_t slot) { diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 991cd372c3f4dcd286fb0ab9931cadd3cdd7eca5..ee841e3ce938f28bc30a876575f23502b7c466d6 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -253,6 +253,11 @@ typedef struct STaskIdInfo { char* str; } STaskIdInfo; +typedef struct STaskBufInfo { + int32_t bufSize; // total available buffer size in bytes + int32_t remainBuf; // remain buffer size +} STaskBufInfo; + typedef struct SExecTaskInfo { STaskIdInfo id; char* content; @@ -264,7 +269,8 @@ typedef struct SExecTaskInfo { uint64_t totalRows; // total number of rows STableGroupInfo tableqinfoGroupInfo; // this is a group array list, including SArray structure char* sql; // query sql string - jmp_buf env; // + jmp_buf env; // when error occurs, abort + STaskBufInfo bufInfo; // available buffer info this task struct SOperatorInfo* pRoot; } SExecTaskInfo; @@ -307,9 +313,11 @@ typedef struct STaskRuntimeEnv { } STaskRuntimeEnv; enum { - OP_IN_EXECUTING = 1, - OP_RES_TO_RETURN = 2, - OP_EXEC_DONE = 3, + OP_NOT_OPENED = 0x0, + OP_OPENED = 0x1, + OP_IN_EXECUTING = 0x3, + OP_RES_TO_RETURN = 0x5, + OP_EXEC_DONE = 0x9, }; typedef struct SOperatorInfo { @@ -322,12 +330,14 @@ typedef struct SOperatorInfo { SExprInfo* pExpr; STaskRuntimeEnv* pRuntimeEnv; // todo remove it SExecTaskInfo* pTaskInfo; + SOperatorCostInfo cost; struct SOperatorInfo** pDownstream; // downstram pointer list int32_t numOfDownstream; // number of downstream. The value is always ONE expect for join operator - __optr_open_fn_t openFn; - __optr_fn_t nextDataFn; + __optr_fn_t getNextFn; + __optr_fn_t cleanupFn; __optr_close_fn_t closeFn; + __optr_open_fn_t _openFn; // DO NOT invoke this function directly } SOperatorInfo; typedef struct { @@ -362,8 +372,8 @@ typedef struct STaskParam { char* tbnameCond; char* prevResult; SArray* pTableIdList; - SSqlExpr** pExpr; - SSqlExpr** pSecExpr; + SExprBasicInfo** pExpr; + SExprBasicInfo** pSecExpr; SExprInfo* pExprs; SExprInfo* pSecExprs; @@ -378,9 +388,9 @@ typedef struct STaskParam { } STaskParam; enum { - DATA_NOT_READY = 0x1, - DATA_READY = 0x2, - DATA_EXHAUSTED = 0x3, + EX_SOURCE_DATA_NOT_READY = 0x1, + EX_SOURCE_DATA_READY = 0x2, + EX_SOURCE_DATA_EXHAUSTED = 0x3, }; typedef struct SSourceDataInfo { @@ -405,17 +415,15 @@ typedef struct SExchangeInfo { } SExchangeInfo; typedef struct STableScanInfo { - void* pTsdbReadHandle; - int32_t numOfBlocks; // extract basic running information. - int32_t numOfSkipped; - int32_t numOfBlockStatis; - int64_t numOfRows; - - int32_t order; // scan order - int32_t times; // repeat counts - int32_t current; - int32_t reverseTimes; // 0 by default - + void* pTsdbReadHandle; + int32_t numOfBlocks; // extract basic running information. + int32_t numOfSkipped; + int32_t numOfBlockStatis; + int64_t numOfRows; + int32_t order; // scan order + int32_t times; // repeat counts + int32_t current; + int32_t reverseTimes; // 0 by default SqlFunctionCtx* pCtx; // next operator query context SResultRowInfo* pResultRowInfo; int32_t* rowCellInfoOffset; @@ -424,8 +432,7 @@ typedef struct STableScanInfo { int32_t numOfOutput; int64_t elapsedTime; int32_t prevGroupId; // previous table group id - - int32_t scanFlag; // table scan flag to denote if it is a repeat/reverse/main scan + int32_t scanFlag; // table scan flag to denote if it is a repeat/reverse/main scan } STableScanInfo; typedef struct STagScanInfo { @@ -443,21 +450,43 @@ typedef struct SStreamBlockScanInfo { void* readerHandle; // stream block reader handle } SStreamBlockScanInfo; +typedef struct SSysTableScanInfo { + union { + void* pTransporter; + void* readHandle; + }; + + void *pCur; // cursor + SRetrieveTableReq* pReq; + SEpSet epSet; + int32_t type; // show type + tsem_t ready; + SSchema* pSchema; + SSDataBlock* pRes; + + int32_t capacity; + int64_t numOfBlocks; // extract basic running information. + int64_t totalRows; + int64_t elapsedTime; + int64_t totalBytes; +} SSysTableScanInfo; + typedef struct SOptrBasicInfo { SResultRowInfo resultRowInfo; int32_t* rowCellInfoOffset; // offset value for each row result cell info SqlFunctionCtx* pCtx; SSDataBlock* pRes; - uint32_t resRowSize; int32_t capacity; } SOptrBasicInfo; +//TODO move the resultrowsiz together with SOptrBasicInfo:rowCellInfoOffset typedef struct SAggSupporter { SHashObj* pResultRowHashTable; // quick locate the window object for each result SHashObj* pResultRowListSet; // used to check if current ResultRowInfo has ResultRow object or not SArray* pResultRowArrayList; // The array list that contains the Result rows char* keyBuf; // window key buffer SResultRowPool *pool; // The window result objects pool, all the resultRow Objects are allocated and managed by this object. + int32_t resultRowSize; // the result buffer size for each result row, with the meta data size for each row } SAggSupporter; typedef struct STableIntervalOperatorInfo { @@ -613,17 +642,23 @@ typedef struct SOrderOperatorInfo { uint64_t totalElapsed; // total elapsed time } SOrderOperatorInfo; -SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray* pSchema, SExecTaskInfo* pTaskInfo); +SOperatorInfo* createExchangeOperatorInfo(const SNodeList* pSources, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo); SOperatorInfo* createTableScanOperatorInfo(void* pTsdbReadHandle, int32_t order, int32_t numOfOutput, int32_t repeatTime, int32_t reverseTime, SExecTaskInfo* pTaskInfo); SOperatorInfo* createTableSeqScanOperatorInfo(void* pTsdbReadHandle, STaskRuntimeEnv* pRuntimeEnv); -SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo); -SOperatorInfo* createMultiTableAggOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo); +SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SSDataBlock* pResultBlock, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo); +SOperatorInfo* createMultiTableAggOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SSDataBlock* pResultBlock, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo); SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo); +SOperatorInfo* createOrderOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SArray* pOrderVal, SExecTaskInfo* pTaskInfo); +SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t numOfDownstream, SArray* pExprInfo, SArray* pOrderVal, SArray* pGroupInfo, SExecTaskInfo* pTaskInfo); +SOperatorInfo* createSysTableScanOperatorInfo(void* pSysTableReadHandle, const SArray* pExprInfo, const SSchema* pSchema, + int32_t tableType, SEpSet epset, SExecTaskInfo* pTaskInfo); SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream); SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SInterval* pInterval, SExecTaskInfo* pTaskInfo); +SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream); + SOperatorInfo* createAllTimeIntervalOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createSWindowOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, @@ -650,15 +685,9 @@ SOperatorInfo* createStatewindowOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOper int32_t numOfOutput); SOperatorInfo* createSLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput, void* merger, bool multigroupResult); -SOperatorInfo* createFilterOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, - int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter); SOperatorInfo* createJoinOperatorInfo(SOperatorInfo** pdownstream, int32_t numOfDownstream, SSchema* pSchema, int32_t numOfOutput); -SOperatorInfo* createOrderOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SArray* pOrderVal, SExecTaskInfo* pTaskInfo); -SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t numOfDownstream, SArray* pExprInfo, SArray* pOrderVal, SArray* pGroupInfo, SExecTaskInfo* pTaskInfo); - -// SSDataBlock* doSLimit(void* param, bool* newgroup); // int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo, uint64_t qId); void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock); @@ -672,20 +701,11 @@ void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFil void setInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order); void finalizeQueryResult(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset); -void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t* bufCapacity, int32_t numOfInputRows); void clearOutputBuf(SOptrBasicInfo* pBInfo, int32_t* bufCapacity); void copyTsColoum(SSDataBlock* pRes, SqlFunctionCtx* pCtx, int32_t numOfOutput); -int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExprInfo** pExprInfo, SSqlExpr** pExprMsg, - SColumnInfo* pTagCols, int32_t queryType, void* pMsg, struct SUdfInfo* pUdfInfo); - -int32_t createIndirectQueryFuncExprFromMsg(SQueryTableReq* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo, - SSqlExpr** pExpr, SExprInfo* prevExpr, struct SUdfInfo* pUdfInfo); - int32_t createQueryFilter(char* data, uint16_t len, SFilterInfo** pFilters); -SGroupbyExpr* createGroupbyExprFromMsg(SQueryTableReq* pQueryMsg, SColIndex* pColIndex, int32_t* code); - int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, STaskParam* param, char* start, int32_t prevResultLen, void* merger); diff --git a/source/libs/executor/src/dataDispatcher.c b/source/libs/executor/src/dataDispatcher.c index 3623f5947d25a73ca91da15db5663dc388583a29..a2e526c2bdbec0b3aae1bc46dff577e97c04c853 100644 --- a/source/libs/executor/src/dataDispatcher.c +++ b/source/libs/executor/src/dataDispatcher.c @@ -21,8 +21,6 @@ #include "tqueue.h" #include "executorimpl.h" -#define DATA_META_LENGTH(tables) (sizeof(int32_t) + sizeof(STableIdInfo) * taosHashGetSize(tables) + sizeof(SRetrieveTableRsp)) - typedef struct SDataDispatchBuf { int32_t useSize; int32_t allocSize; @@ -39,7 +37,7 @@ typedef struct SDataCacheEntry { typedef struct SDataDispatchHandle { SDataSinkHandle sink; SDataSinkManager* pManager; - SDataBlockSchema schema; + SDataBlockDescNode* pSchema; STaosQueue* pDataBlocks; SDataDispatchBuf nextOutput; int32_t status; @@ -48,12 +46,13 @@ typedef struct SDataDispatchHandle { pthread_mutex_t mutex; } SDataDispatchHandle; -static bool needCompress(const SSDataBlock* pData, const SDataBlockSchema* pSchema) { +static bool needCompress(const SSDataBlock* pData, const SDataBlockDescNode* pSchema) { if (tsCompressColData < 0 || 0 == pData->info.rows) { return false; } - for (int32_t col = 0; col < pSchema->numOfCols; ++col) { + int32_t numOfCols = LIST_LENGTH(pSchema->pSlots); + for (int32_t col = 0; col < numOfCols; ++col) { SColumnInfoData* pColRes = taosArrayGet(pData->pDataBlock, col); int32_t colSize = pColRes->info.bytes * pData->info.rows; if (NEEDTO_COMPRESS_QUERY(colSize)) { @@ -70,13 +69,14 @@ static int32_t compressColData(SColumnInfoData *pColRes, int32_t numOfRows, char pColRes->pData, colSize, numOfRows, data, colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0); } -static void copyData(const SInputData* pInput, const SDataBlockSchema* pSchema, char* data, int8_t compressed, int32_t *compLen) { +static void copyData(const SInputData* pInput, const SDataBlockDescNode* pSchema, char* data, int8_t compressed, int32_t *compLen) { + int32_t numOfCols = LIST_LENGTH(pSchema->pSlots); int32_t *compSizes = (int32_t*)data; if (compressed) { - data += pSchema->numOfCols * sizeof(int32_t); + data += numOfCols * sizeof(int32_t); } - for (int32_t col = 0; col < pSchema->numOfCols; ++col) { + for (int32_t col = 0; col < numOfCols; ++col) { SColumnInfoData* pColRes = taosArrayGet(pInput->pData->pDataBlock, col); if (compressed) { compSizes[col] = compressColData(pColRes, pInput->pData->info.rows, data, compressed); @@ -88,33 +88,20 @@ static void copyData(const SInputData* pInput, const SDataBlockSchema* pSchema, data += pColRes->info.bytes * pInput->pData->info.rows; } } - - int32_t numOfTables = (int32_t) taosHashGetSize(pInput->pTableRetrieveTsMap); - *(int32_t*)data = htonl(numOfTables); - data += sizeof(int32_t); - - STableIdInfo* item = taosHashIterate(pInput->pTableRetrieveTsMap, NULL); - while (item) { - STableIdInfo* pDst = (STableIdInfo*)data; - pDst->uid = htobe64(item->uid); - pDst->key = htobe64(item->key); - data += sizeof(STableIdInfo); - item = taosHashIterate(pInput->pTableRetrieveTsMap, item); - } } // data format with compress: SDataCacheEntry | cols_data_offset | col1_data col2_data ... | numOfTables | STableIdInfo STableIdInfo ... // data format: SDataCacheEntry | col1_data col2_data ... | numOfTables | STableIdInfo STableIdInfo ... static void toDataCacheEntry(const SDataDispatchHandle* pHandle, const SInputData* pInput, SDataDispatchBuf* pBuf) { SDataCacheEntry* pEntry = (SDataCacheEntry*)pBuf->pData; - pEntry->compressed = (int8_t)needCompress(pInput->pData, &(pHandle->schema)); + pEntry->compressed = (int8_t)needCompress(pInput->pData, pHandle->pSchema); pEntry->numOfRows = pInput->pData->info.rows; pEntry->dataLen = 0; - pBuf->useSize = DATA_META_LENGTH(pInput->pTableRetrieveTsMap); - copyData(pInput, &pHandle->schema, pEntry->data, pEntry->compressed, &pEntry->dataLen); + pBuf->useSize = sizeof(SRetrieveTableRsp); + copyData(pInput, pHandle->pSchema, pEntry->data, pEntry->compressed, &pEntry->dataLen); if (0 == pEntry->compressed) { - pEntry->dataLen = pHandle->schema.resultRowSize * pInput->pData->info.rows; + pEntry->dataLen = pHandle->pSchema->resultRowSize * pInput->pData->info.rows; } pBuf->useSize += pEntry->dataLen; // todo completed @@ -128,7 +115,7 @@ static bool allocBuf(SDataDispatchHandle* pDispatcher, const SInputData* pInput, return false; } - pBuf->allocSize = DATA_META_LENGTH(pInput->pTableRetrieveTsMap) + pDispatcher->schema.resultRowSize * pInput->pData->info.rows; + pBuf->allocSize = sizeof(SRetrieveTableRsp) + pDispatcher->pSchema->resultRowSize * pInput->pData->info.rows; pBuf->pData = malloc(pBuf->allocSize); if (pBuf->pData == NULL) { qError("SinkNode failed to malloc memory, size:%d, code:%d", pBuf->allocSize, TAOS_SYSTEM_ERROR(errno)); @@ -194,7 +181,7 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { if (NULL == pDispatcher->nextOutput.pData) { assert(pDispatcher->queryEnd); pOutput->useconds = pDispatcher->useconds; - pOutput->precision = pDispatcher->schema.precision; + pOutput->precision = pDispatcher->pSchema->precision; return TSDB_CODE_SUCCESS; } SDataCacheEntry* pEntry = (SDataCacheEntry*)(pDispatcher->nextOutput.pData); @@ -206,7 +193,7 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { pthread_mutex_lock(&pDispatcher->mutex); pOutput->queryEnd = pDispatcher->queryEnd; pOutput->useconds = pDispatcher->useconds; - pOutput->precision = pDispatcher->schema.precision; + pOutput->precision = pDispatcher->pSchema->precision; pthread_mutex_unlock(&pDispatcher->mutex); return TSDB_CODE_SUCCESS; } @@ -224,7 +211,7 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { pthread_mutex_destroy(&pDispatcher->mutex); } -int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSink* pDataSink, DataSinkHandle* pHandle) { +int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle) { SDataDispatchHandle* dispatcher = calloc(1, sizeof(SDataDispatchHandle)); if (NULL == dispatcher) { terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; @@ -236,7 +223,7 @@ int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSink* pDataS dispatcher->sink.fGetData = getDataBlock; dispatcher->sink.fDestroy = destroyDataSinker; dispatcher->pManager = pManager; - dispatcher->schema = pDataSink->schema; + dispatcher->pSchema = pDataSink->pInputDataBlockDesc; dispatcher->status = DS_BUF_EMPTY; dispatcher->queryEnd = false; dispatcher->pDataBlocks = taosOpenQueue(); diff --git a/source/libs/executor/src/dataSinkMgt.c b/source/libs/executor/src/dataSinkMgt.c index eb1f75f359f384e291de65b4a9fe52d547e6d220..343b3a3c95080ce82df9ca6db25eed2e9bc2125d 100644 --- a/source/libs/executor/src/dataSinkMgt.c +++ b/source/libs/executor/src/dataSinkMgt.c @@ -25,8 +25,8 @@ int32_t dsDataSinkMgtInit(SDataSinkMgtCfg *cfg) { pthread_mutex_init(&gDataSinkManager.mutex, NULL); } -int32_t dsCreateDataSinker(const struct SDataSink *pDataSink, DataSinkHandle* pHandle) { - if (DSINK_Dispatch == pDataSink->info.type) { +int32_t dsCreateDataSinker(const SDataSinkNode *pDataSink, DataSinkHandle* pHandle) { + if (QUERY_NODE_PHYSICAL_PLAN_DISPATCH == nodeType(pDataSink)) { return createDataDispatcher(&gDataSinkManager, pDataSink, pHandle); } return TSDB_CODE_FAILED; diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 1b901ee9f684e1894ad66128c47df6ca732126f4..9d77e23d388aea299b2974db58091dfb5a5cbea9 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -46,7 +46,7 @@ int32_t getOutputInterResultBufSize(STaskAttr* pQueryAttr) { int32_t size = 0; for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) { - size += pQueryAttr->pExpr1[i].base.interBytes; +// size += pQueryAttr->pExpr1[i].base.interBytes; } assert(size >= 0); @@ -172,9 +172,14 @@ SResultRowEntryInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_ return (SResultRowEntryInfo*)((char*) pRow->pEntryInfo + offset[index]); } -size_t getResultRowSize(SArray* pExprInfo) { - size_t numOfOutput = taosArrayGetSize(pExprInfo); - return (numOfOutput * sizeof(SResultRowEntryInfo)) + /*pQueryAttr->interBufSize +*/ sizeof(SResultRow); +size_t getResultRowSize(SqlFunctionCtx* pCtx, int32_t numOfOutput) { + int32_t rowSize = (numOfOutput * sizeof(SResultRowEntryInfo)) + sizeof(SResultRow); + + for(int32_t i = 0; i < numOfOutput; ++i) { + rowSize += pCtx[i].resDataInfo.interBufSize; + } + + return rowSize; } SResultRowPool* initResultRowPool(size_t size) { diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c index 19a3874f7592f17d61cd589652fc1f34a9cd0261..a8602b7c774469a3d2117877c6d0baeacb12345a 100644 --- a/source/libs/executor/src/executor.c +++ b/source/libs/executor/src/executor.c @@ -20,7 +20,7 @@ static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, char* id) { ASSERT(pOperator != NULL); - if (pOperator->operatorType != OP_StreamScan) { + if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { if (pOperator->numOfDownstream == 0) { qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id); return TSDB_CODE_QRY_APP_ERROR; @@ -99,7 +99,7 @@ int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, SArray* tableIdList, bool isA // traverse to the streamscan node to add this table id SOperatorInfo* pInfo = pTaskInfo->pRoot; - while (pInfo->operatorType != OP_StreamScan) { + while(pInfo->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { pInfo = pInfo->pDownstream[0]; } diff --git a/source/libs/executor/src/executorMain.c b/source/libs/executor/src/executorMain.c index fabaa2d31dc822c7d926fc674bbae37d783ba7f8..7e55a4b3e1615f8e98e78d7e27449a1a99e4de3b 100644 --- a/source/libs/executor/src/executorMain.c +++ b/source/libs/executor/src/executorMain.c @@ -158,7 +158,7 @@ int32_t qExecTask(qTaskInfo_t tinfo, SSDataBlock** pRes, uint64_t *useconds) { int64_t st = 0; st = taosGetTimestampUs(); - *pRes = pTaskInfo->pRoot->nextDataFn(pTaskInfo->pRoot, &newgroup); + *pRes = pTaskInfo->pRoot->getNextFn(pTaskInfo->pRoot, &newgroup); uint64_t el = (taosGetTimestampUs() - st); pTaskInfo->cost.elapsedTime += el; diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index eeb48a1f3db6e587770f8230f5cf6996ebeb11a6..8b0b46dbbdb234ab2bf18890aee29f14e5613e19 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -13,6 +13,9 @@ * along with this program. If not, see . */ +#include +#include +#include #include "os.h" #include "parser.h" @@ -61,7 +64,7 @@ typedef enum SResultTsInterpType { #if 0 static UNUSED_FUNC void *u_malloc (size_t __size) { - uint32_t v = rand(); + uint32_t v = taosRand(); if (v % 1000 <= 0) { return NULL; @@ -71,7 +74,7 @@ static UNUSED_FUNC void *u_malloc (size_t __size) { } static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) { - uint32_t v = rand(); + uint32_t v = taosRand(); if (v % 1000 <= 0) { return NULL; } else { @@ -80,7 +83,7 @@ static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) { } static UNUSED_FUNC void* u_realloc(void* p, size_t __size) { - uint32_t v = rand(); + uint32_t v = taosRand(); if (v % 5 <= 1) { return NULL; } else { @@ -160,7 +163,7 @@ static void getNextTimeWindow(SInterval* pInterval, int32_t precision, int32_t o struct tm tm; time_t t = (time_t)key; - localtime_r(&t, &tm); + taosLocalTime(&t, &tm); int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor); tm.tm_year = mon / 12; @@ -208,7 +211,11 @@ static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput); static void destroySWindowOperatorInfo(void* param, int32_t numOfOutput); static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput); static void destroyAggOperatorInfo(void* param, int32_t numOfOutput); +static void destroyExchangeOperatorInfo(void* param, int32_t numOfOutput); +static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput); + static void destroyOperatorInfo(SOperatorInfo* pOperator); +static void destroySysTableScannerOperatorInfo(void* param, int32_t numOfOutput); static void doSetOperatorCompleted(SOperatorInfo* pOperator) { pOperator->status = OP_EXEC_DONE; @@ -217,6 +224,17 @@ static void doSetOperatorCompleted(SOperatorInfo* pOperator) { } } +#define OPTR_IS_OPENED(_optr) (((_optr)->status & OP_OPENED) == OP_OPENED) +#define OPTR_SET_OPENED(_optr) ((_optr)->status |= OP_OPENED) + +static int32_t operatorDummyOpenFn(void* param) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; + OPTR_SET_OPENED(pOperator); + return TSDB_CODE_SUCCESS; +} + +static void operatorDummyCloseFn(void* param, int32_t numOfCols) {} + static int32_t doCopyToSDataBlock(SDiskbasedBuf *pBuf, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock, int32_t rowCapacity); static int32_t getGroupbyColumnIndex(SGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock); @@ -265,7 +283,7 @@ static void sortGroupResByOrderList(SGroupResInfo *pGroupResInfo, STaskRuntimeEn return; } - int32_t orderId = pRuntimeEnv->pQueryAttr->order.col.info.colId; + int32_t orderId = pRuntimeEnv->pQueryAttr->order.col.colId; if (orderId <= 0) { return; } @@ -315,8 +333,6 @@ SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numO } SSDataBlock* createOutputBuf_rv(SArray* pExprInfo, int32_t numOfRows) { - const static int32_t minSize = 8; - size_t numOfOutput = taosArrayGetSize(pExprInfo); SSDataBlock *res = calloc(1, sizeof(SSDataBlock)); @@ -330,15 +346,38 @@ SSDataBlock* createOutputBuf_rv(SArray* pExprInfo, int32_t numOfRows) { idata.info.type = pExpr->base.resSchema.type; idata.info.bytes = pExpr->base.resSchema.bytes; idata.info.colId = pExpr->base.resSchema.colId; - - int32_t size = TMAX(idata.info.bytes * numOfRows, minSize); - idata.pData = calloc(1, size); // at least to hold a pointer on x64 platform taosArrayPush(res->pDataBlock, &idata); } + blockDataEnsureCapacity(res, numOfRows); return res; } +SSDataBlock* createOutputBuf_rv1(SDataBlockDescNode* pNode) { + int32_t numOfCols = LIST_LENGTH(pNode->pSlots); + + SSDataBlock* pBlock = calloc(1, sizeof(SSDataBlock)); + pBlock->info.numOfCols = numOfCols; + pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); + + pBlock->info.blockId = pNode->dataBlockId; + pBlock->info.rowSize = pNode->resultRowSize; + + for(int32_t i = 0; i < numOfCols; ++i) { + SColumnInfoData idata = {{0}}; + SSlotDescNode* pDescNode = nodesListGetNode(pNode->pSlots, i); + idata.info.type = pDescNode->dataType.type; + idata.info.bytes = pDescNode->dataType.bytes; + idata.info.scale = pDescNode->dataType.scale; + idata.info.slotId = pDescNode->slotId; + idata.info.precision = pDescNode->dataType.precision; + + taosArrayPush(pBlock->pDataBlock, &idata); + } + + return pBlock; +} + static bool isSelectivityWithTagsQuery(SqlFunctionCtx *pCtx, int32_t numOfOutput) { return true; // bool hasTags = false; @@ -371,7 +410,7 @@ static bool isProjQuery(STaskAttr *pQueryAttr) { } static bool hasNull(SColumn* pColumn, SColumnDataAgg *pStatis) { - if (TSDB_COL_IS_TAG(pColumn->flag) || TSDB_COL_IS_UD_COL(pColumn->flag) || pColumn->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) { + if (TSDB_COL_IS_TAG(pColumn->flag) || TSDB_COL_IS_UD_COL(pColumn->flag) || pColumn->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { return false; } @@ -659,12 +698,6 @@ static STimeWindow getActiveTimeWindow(SResultRowInfo * pResultRowInfo, int64_t w.ekey = w.skey + pInterval->interval - 1; } } - - /* - * query border check, skey should not be bounded by the query time range, since the value skey will - * be used as the time window index value. So we only change ekey of time window accordingly. - */ -// ASSERT(win->skey <= win->ekey); // todo no need this return w; } @@ -978,7 +1011,7 @@ static void doApplyFunctions(SqlFunctionCtx* pCtx, STimeWindow* pWin, int32_t of } if (functionNeedToExecute(&pCtx[k])) { - pCtx[k].fpSet->addInput(&pCtx[k]); +// pCtx[k].fpSet.process(&pCtx[k]); } // restore it @@ -1123,91 +1156,82 @@ static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SqlFunctionCtx* pC } void setInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { -// if (pCtx[0].functionId == FUNCTION_ARITHM) { -// SScalar* pSupport = (SScalarFunctionSupport*) pCtx[0].param[1].pz; -// if (pSupport->colList == NULL) { -// doSetInputDataBlock(pOperator, pCtx, pBlock, order); -// } else { -// doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); -// } -// } else { - if (pBlock->pDataBlock != NULL) { - doSetInputDataBlock(pOperator, pCtx, pBlock, order); - } else { - doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); - } -// } + if (pBlock->pDataBlock != NULL) { + doSetInputDataBlock(pOperator, pCtx, pBlock, order); + } else { + doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); + } } static void doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { for (int32_t i = 0; i < pOperator->numOfOutput; ++i) { pCtx[i].order = order; pCtx[i].size = pBlock->info.rows; - pCtx[i].currentStage = MAIN_SCAN/*(uint8_t)pOperator->pRuntimeEnv->scanFlag*/; - - setBlockStatisInfo(&pCtx[i], pBlock, pOperator->pExpr[i].base.pColumns); - - if (pCtx[i].functionId == FUNCTION_ARITHM) { -// setArithParams((SScalarFunctionSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock); - } else { - uint32_t flag = pOperator->pExpr[i].base.pColumns->flag; - if (TSDB_COL_IS_NORMAL_COL(flag) /*|| (pCtx[i].functionId == FUNCTION_BLKINFO) || - (TSDB_COL_IS_TAG(flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)*/) { - - SColumn* pCol = pOperator->pExpr[i].base.pColumns; - if (pCtx[i].columnIndex == -1) { - for(int32_t j = 0; j < pBlock->info.numOfCols; ++j) { - SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, j); - if (pColData->info.colId == pCol->info.colId) { - pCtx[i].columnIndex = j; - break; - } - } - } - - SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pCtx[i].columnIndex); - // in case of the block distribution query, the inputBytes is not a constant value. - pCtx[i].pInput = p; - assert(p->info.colId == pCol->info.colId); - - if (pCtx[i].functionId < 0) { - SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); - pCtx[i].ptsList = (int64_t*) tsInfo->pData; - - continue; - } - -// uint32_t status = aAggs[pCtx[i].functionId].status; -// if ((status & (FUNCSTATE_SELECTIVITY | FUNCSTATE_NEED_TS)) != 0) { -// SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); - // In case of the top/bottom query again the nest query result, which has no timestamp column - // don't set the ptsList attribute. -// if (tsInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) { -// pCtx[i].ptsList = (int64_t*) tsInfo->pData; -// } else { -// pCtx[i].ptsList = NULL; -// } -// } -// } else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) { -// SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo; -// SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex); -// -// pCtx[i].pInput = p->pData; -// assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type); -// for(int32_t j = 0; j < pBlock->info.rows; ++j) { -// char* dst = p->pData + j * p->info.bytes; -// taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true); -// } - } - } - } -} - -static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SqlFunctionCtx* pCtx, SSDataBlock* pSDataBlock) { + pCtx[i].currentStage = MAIN_SCAN; + + // setBlockStatisInfo(&pCtx[i], pBlock, pOperator->pExpr[i].base.pColumns); + int32_t slotId = pOperator->pExpr[i].base.pParam[0].pCol->slotId; + + // uint32_t flag = pOperator->pExpr[i].base.pParam[0].pCol->flag; + // if (TSDB_COL_IS_NORMAL_COL(flag) /*|| (pCtx[i].functionId == FUNCTION_BLKINFO) || + // (TSDB_COL_IS_TAG(flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)*/) { + + // SColumn* pCol = pOperator->pExpr[i].base.pParam[0].pCol; + // if (pCtx[i].columnIndex == -1) { + // for(int32_t j = 0; j < pBlock->info.numOfCols; ++j) { + // SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, j); + // if (pColData->info.colId == pCol->colId) { + // pCtx[i].columnIndex = j; + // break; + // } + // } + // } + + // in case of the block distribution query, the inputBytes is not a constant value. + pCtx[i].input.pData[0] = taosArrayGet(pBlock->pDataBlock, slotId); + pCtx[i].input.totalRows = pBlock->info.rows; + pCtx[i].input.numOfRows = pBlock->info.rows; + pCtx[i].input.startRowIndex = 0; + + ASSERT(pCtx[i].input.pData[0] != NULL); + + // if (pCtx[i].functionId < 0) { + // SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); + // pCtx[i].ptsList = (int64_t*) tsInfo->pData; + + // continue; + // } + + // uint32_t status = aAggs[pCtx[i].functionId].status; + // if ((status & (FUNCSTATE_SELECTIVITY | FUNCSTATE_NEED_TS)) != 0) { + // SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); + // In case of the top/bottom query again the nest query result, which has no timestamp column + // don't set the ptsList attribute. + // if (tsInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) { + // pCtx[i].ptsList = (int64_t*) tsInfo->pData; + // } else { + // pCtx[i].ptsList = NULL; + // } + // } + // } else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) { + // SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo; + // SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex); + // + // pCtx[i].pInput = p->pData; + // assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type); + // for(int32_t j = 0; j < pBlock->info.rows; ++j) { + // char* dst = p->pData + j * p->info.bytes; + // taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true); + // } + // } + } +} + +static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SqlFunctionCtx* pCtx) { for (int32_t k = 0; k < pOperator->numOfOutput; ++k) { if (functionNeedToExecute(&pCtx[k])) { pCtx[k].startTs = startTs;// this can be set during create the struct - pCtx[k].fpSet->addInput(&pCtx[k]); + pCtx[k].fpSet.process(&pCtx[k]); } } } @@ -1867,7 +1891,7 @@ void setBlockStatisInfo(SqlFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColumn* pCtx->hasNull = hasNull(pColumn, pAgg); // set the statistics data for primary time stamp column - if (pCtx->functionId == FUNCTION_SPREAD && pColumn->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) { + if (pCtx->functionId == FUNCTION_SPREAD && pColumn->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { pCtx->isAggSet = true; pCtx->agg.min = pSDataBlock->info.window.skey; pCtx->agg.max = pSDataBlock->info.window.ekey; @@ -1906,9 +1930,9 @@ static int32_t setCtxTagColumnInfo(SqlFunctionCtx *pCtx, int32_t numOfOutput) { } } if (p != NULL) { - p->tagInfo.pTagCtxList = pTagCtx; - p->tagInfo.numOfTagCols = num; - p->tagInfo.tagsLen = tagLen; + p->subsidiaryRes.pCtx = pTagCtx; + p->subsidiaryRes.numOfCols = num; + p->subsidiaryRes.bufLen = tagLen; } else { tfree(pTagCtx); } @@ -1932,10 +1956,10 @@ static SqlFunctionCtx* createSqlFunctionCtx(STaskRuntimeEnv* pRuntimeEnv, SExprI } for (int32_t i = 0; i < numOfOutput; ++i) { - SSqlExpr *pSqlExpr = &pExpr[i].base; + SExprBasicInfo *pFunct = &pExpr[i].base; SqlFunctionCtx* pCtx = &pFuncCtx[i]; #if 0 - SColIndex *pIndex = &pSqlExpr->colInfo; + SColIndex *pIndex = &pFunct->colInfo; if (TSDB_COL_REQ_NULL(pIndex->flag)) { pCtx->requireNull = true; @@ -1944,33 +1968,30 @@ static SqlFunctionCtx* createSqlFunctionCtx(STaskRuntimeEnv* pRuntimeEnv, SExprI pCtx->requireNull = false; } #endif -// pCtx->inputBytes = pSqlExpr->colBytes; -// pCtx->inputType = pSqlExpr->colType; +// pCtx->inputBytes = pFunct->colBytes; +// pCtx->inputType = pFunct->colType; pCtx->ptsOutputBuf = NULL; - pCtx->resDataInfo.bytes = pSqlExpr->resSchema.bytes; - pCtx->resDataInfo.type = pSqlExpr->resSchema.type; + pCtx->resDataInfo.bytes = pFunct->resSchema.bytes; + pCtx->resDataInfo.type = pFunct->resSchema.type; pCtx->order = pQueryAttr->order.order; -// pCtx->functionId = pSqlExpr->functionId; +// pCtx->functionId = pFunct->functionId; pCtx->stableQuery = pQueryAttr->stableQuery; - pCtx->resDataInfo.intermediateBytes = pSqlExpr->interBytes; +// pCtx->resDataInfo.interBufSize = pFunct->interBytes; pCtx->start.key = INT64_MIN; pCtx->end.key = INT64_MIN; - pCtx->numOfParams = pSqlExpr->numOfParams; + pCtx->numOfParams = pFunct->numOfParams; for (int32_t j = 0; j < pCtx->numOfParams; ++j) { - int16_t type = pSqlExpr->param[j].nType; - int16_t bytes = pSqlExpr->param[j].nLen; -// if (pSqlExpr->functionId == FUNCTION_STDDEV_DST) { -// continue; -// } + int16_t type = pFunct->pParam[j].param.nType; + int16_t bytes = pFunct->pParam[j].param.nType; if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - taosVariantCreateFromBinary(&pCtx->param[j], pSqlExpr->param[j].pz, bytes, type); +// taosVariantCreateFromBinary(&pCtx->param[j], pFunct->param[j].pz, bytes, type); } else { - taosVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlExpr->param[j].i, bytes, type); +// taosVariantCreateFromBinary(&pCtx->param[j], (char *)&pFunct->param[j].i, bytes, type); } } @@ -1986,7 +2007,7 @@ static SqlFunctionCtx* createSqlFunctionCtx(STaskRuntimeEnv* pRuntimeEnv, SExprI pCtx->param[3].i = functionId; pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT; - pCtx->param[1].i = pQueryAttr->order.col.info.colId; + pCtx->param[1].i = pQueryAttr->order.col.colId; } else if (functionId == FUNCTION_INTERP) { pCtx->param[2].i = (int8_t)pQueryAttr->fillType; if (pQueryAttr->fillVal != NULL) { @@ -2020,7 +2041,7 @@ static SqlFunctionCtx* createSqlFunctionCtx(STaskRuntimeEnv* pRuntimeEnv, SExprI return pFuncCtx; } -static SqlFunctionCtx* createSqlFunctionCtx_rv(SArray* pExprInfo, int32_t** rowCellInfoOffset, uint32_t* pRowSize) { +static SqlFunctionCtx* createSqlFunctionCtx_rv(SArray* pExprInfo, int32_t** rowCellInfoOffset) { size_t numOfOutput = taosArrayGetSize(pExprInfo); SqlFunctionCtx * pFuncCtx = (SqlFunctionCtx *)calloc(numOfOutput, sizeof(SqlFunctionCtx)); @@ -2037,54 +2058,39 @@ static SqlFunctionCtx* createSqlFunctionCtx_rv(SArray* pExprInfo, int32_t** rowC for (int32_t i = 0; i < numOfOutput; ++i) { SExprInfo* pExpr = taosArrayGetP(pExprInfo, i); - SSqlExpr *pSqlExpr = &pExpr->base; + SExprBasicInfo *pFunct = &pExpr->base; SqlFunctionCtx* pCtx = &pFuncCtx[i]; -#if 0 - SColIndex *pIndex = &pSqlExpr->colInfo; - - if (TSDB_COL_REQ_NULL(pIndex->flag)) { - pCtx->requireNull = true; - pIndex->flag &= ~(TSDB_COL_NULL); - } else { - pCtx->requireNull = false; - } -#endif -// pCtx->inputBytes = pSqlExpr->; -// pCtx->inputType = pSqlExpr->colType; - - pCtx->ptsOutputBuf = NULL; - pCtx->fpSet = fpSet; - pCtx->columnIndex = -1; - pCtx->resDataInfo.bytes = pSqlExpr->resSchema.bytes; - pCtx->resDataInfo.type = pSqlExpr->resSchema.type; + fmGetFuncExecFuncs(pExpr->pExpr->_function.pFunctNode->funcId, &pCtx->fpSet); + pCtx->input.numOfInputCols = pFunct->numOfParams; - pCtx->order = TSDB_ORDER_ASC; - if (i == 0) { - pCtx->functionId = FUNCTION_TS; - } + pCtx->input.pData = calloc(pFunct->numOfParams, POINTER_BYTES); + pCtx->input.pColumnDataAgg = calloc(pFunct->numOfParams, POINTER_BYTES); -// pCtx->functionId = pSqlExpr->functionId; -// pCtx->stableQuery = pQueryAttr->stableQuery; - pCtx->resDataInfo.intermediateBytes = pSqlExpr->interBytes; - pCtx->start.key = INT64_MIN; - pCtx->end.key = INT64_MIN; + pCtx->ptsOutputBuf = NULL; + pCtx->resDataInfo.bytes = pFunct->resSchema.bytes; + pCtx->resDataInfo.type = pFunct->resSchema.type; + pCtx->order = TSDB_ORDER_ASC; + pCtx->start.key = INT64_MIN; + pCtx->end.key = INT64_MIN; - pCtx->numOfParams = pSqlExpr->numOfParams; + SFuncExecEnv env = {0}; + pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env); + pCtx->resDataInfo.interBufSize = env.calcMemSize; +#if 0 for (int32_t j = 0; j < pCtx->numOfParams; ++j) { - int16_t type = pSqlExpr->param[j].nType; - int16_t bytes = pSqlExpr->param[j].nLen; +// int16_t type = pFunct->param[j].nType; +// int16_t bytes = pFunct->param[j].nLen; - if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - taosVariantCreateFromBinary(&pCtx->param[j], pSqlExpr->param[j].pz, bytes, type); - } else { - taosVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlExpr->param[j].i, bytes, type); - } +// if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { +// taosVariantCreateFromBinary(&pCtx->param[j], pFunct->param[j].pz, bytes, type); +// } else { +// taosVariantCreateFromBinary(&pCtx->param[j], (char *)&pFunct->param[j].i, bytes, type); +// } } // set the order information for top/bottom query int32_t functionId = pCtx->functionId; - if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_DIFF) { int32_t f = getExprFunctionId(&pExpr[0]); assert(f == FUNCTION_TS || f == FUNCTION_TS_DUMMY); @@ -2117,19 +2123,18 @@ static SqlFunctionCtx* createSqlFunctionCtx_rv(SArray* pExprInfo, int32_t** rowC } else if (functionId == FUNCTION_ARITHM) { // pCtx->param[1].pz = (char*) getScalarFuncSupport(pRuntimeEnv->scalarSup, i); } +#endif } for(int32_t i = 1; i < numOfOutput; ++i) { - SExprInfo* pExpr = taosArrayGetP(pExprInfo, i - 1); - (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) + pExpr->base.interBytes); - *pRowSize += pExpr->base.resSchema.bytes; + (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) + pFuncCtx[i].resDataInfo.interBufSize); } setCtxTagColumnInfo(pFuncCtx, numOfOutput); return pFuncCtx; } -static void* destroySQLFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) { +static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) { if (pCtx == NULL) { return NULL; } @@ -2140,7 +2145,7 @@ static void* destroySQLFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) { } taosVariantDestroy(&pCtx[i].tag); - tfree(pCtx[i].tagInfo.pTagCtxList); + tfree(pCtx[i].subsidiaryRes.pCtx); } tfree(pCtx); @@ -2224,46 +2229,6 @@ static void destroyTsComp(STaskRuntimeEnv *pRuntimeEnv, STaskAttr *pQueryAttr) { } } -static void teardownQueryRuntimeEnv(STaskRuntimeEnv *pRuntimeEnv) { - STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr; - SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo; - - //qDebug("QInfo:0x%"PRIx64" teardown runtime env", pQInfo->qId); - - //destroyScalarFuncSupport(pRuntimeEnv->scalarSup, pQueryAttr->numOfOutput); -// destroyUdfInfo(pRuntimeEnv->pUdfInfo); - destroyDiskbasedBuf(pRuntimeEnv->pResultBuf); - doFreeQueryHandle(pRuntimeEnv); - - destroyTsComp(pRuntimeEnv, pQueryAttr); - - pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf); - - tfree(pRuntimeEnv->keyBuf); - tfree(pRuntimeEnv->prevRow); - tfree(pRuntimeEnv->tagVal); - - taosHashCleanup(pRuntimeEnv->pResultRowHashTable); - pRuntimeEnv->pResultRowHashTable = NULL; - - taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap); - pRuntimeEnv->pTableRetrieveTsMap = NULL; - - taosHashCleanup(pRuntimeEnv->pResultRowListSet); - pRuntimeEnv->pResultRowListSet = NULL; - - destroyOperatorInfo(pRuntimeEnv->proot); - - pRuntimeEnv->pool = destroyResultRowPool(pRuntimeEnv->pool); - taosArrayDestroyEx(pRuntimeEnv->prevResult, freeInterResult); - taosArrayDestroy(pRuntimeEnv->pResultRowArrayList); - pRuntimeEnv->prevResult = NULL; -} - -static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) { - return pQInfo->rspContext != NULL; -} - bool isTaskKilled(SExecTaskInfo *pTaskInfo) { // query has been executed more than tsShellActivityTimer, and the retrieve has not arrived // abort current query execution. @@ -2292,7 +2257,7 @@ void setTaskKilled(SExecTaskInfo *pTaskInfo) { pTaskInfo->code = TSDB_CODE_TSC_Q // } // // for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) { -// SSqlExpr *pExpr = &pQueryAttr->pExpr1[i].base; +// SExprBasicInfo *pExpr = &pQueryAttr->pExpr1[i].base; // // if (pExpr->functionId == FUNCTION_TS || pExpr->functionId == FUNCTION_TS_DUMMY) { // continue; @@ -2471,101 +2436,101 @@ static void doUpdateLastKey(STaskAttr* pQueryAttr) { } } -static void updateDataCheckOrder(SQInfo *pQInfo, SQueryTableReq* pQueryMsg, bool stableQuery) { - STaskAttr* pQueryAttr = pQInfo->runtimeEnv.pQueryAttr; - - // in case of point-interpolation query, use asc order scan - char msg[] = "QInfo:0x%"PRIx64" scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%" PRId64 - "-%" PRId64 ", new qrange:%" PRId64 "-%" PRId64; - - // todo handle the case the the order irrelevant query type mixed up with order critical query type - // descending order query for last_row query - if (isFirstLastRowQuery(pQueryAttr)) { - //qDebug("QInfo:0x%"PRIx64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId, pQueryAttr->order.order, TSDB_ORDER_ASC); - - pQueryAttr->order.order = TSDB_ORDER_ASC; - if (pQueryAttr->window.skey > pQueryAttr->window.ekey) { - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - } - - pQueryAttr->needReverseScan = false; - return; - } - - if (pQueryAttr->groupbyColumn && pQueryAttr->order.order == TSDB_ORDER_DESC) { - pQueryAttr->order.order = TSDB_ORDER_ASC; - if (pQueryAttr->window.skey > pQueryAttr->window.ekey) { - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - } - - pQueryAttr->needReverseScan = false; - doUpdateLastKey(pQueryAttr); - return; - } - - if (pQueryAttr->pointInterpQuery && pQueryAttr->interval.interval == 0) { - if (!QUERY_IS_ASC_QUERY(pQueryAttr)) { - //qDebug(msg, pQInfo->qId, "interp", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - } - - pQueryAttr->order.order = TSDB_ORDER_ASC; - return; - } - - if (pQueryAttr->interval.interval == 0) { - if (onlyFirstQuery(pQueryAttr)) { - if (!QUERY_IS_ASC_QUERY(pQueryAttr)) { - //qDebug(msg, pQInfo->qId, "only-first", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey, -// pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); - - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - doUpdateLastKey(pQueryAttr); - } - - pQueryAttr->order.order = TSDB_ORDER_ASC; - pQueryAttr->needReverseScan = false; - } else if (onlyLastQuery(pQueryAttr) && notContainSessionOrStateWindow(pQueryAttr)) { - if (QUERY_IS_ASC_QUERY(pQueryAttr)) { - //qDebug(msg, pQInfo->qId, "only-last", pQueryAttr->order.order, TSDB_ORDER_DESC, pQueryAttr->window.skey, -// pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); - - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - doUpdateLastKey(pQueryAttr); - } - - pQueryAttr->order.order = TSDB_ORDER_DESC; - pQueryAttr->needReverseScan = false; - } - - } else { // interval query - if (stableQuery) { - if (onlyFirstQuery(pQueryAttr)) { - if (!QUERY_IS_ASC_QUERY(pQueryAttr)) { - //qDebug(msg, pQInfo->qId, "only-first stable", pQueryAttr->order.order, TSDB_ORDER_ASC, -// pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); - - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - doUpdateLastKey(pQueryAttr); - } - - pQueryAttr->order.order = TSDB_ORDER_ASC; - pQueryAttr->needReverseScan = false; - } else if (onlyLastQuery(pQueryAttr)) { - if (QUERY_IS_ASC_QUERY(pQueryAttr)) { - //qDebug(msg, pQInfo->qId, "only-last stable", pQueryAttr->order.order, TSDB_ORDER_DESC, -// pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); - - TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); - doUpdateLastKey(pQueryAttr); - } - - pQueryAttr->order.order = TSDB_ORDER_DESC; - pQueryAttr->needReverseScan = false; - } - } - } -} +//static void updateDataCheckOrder(SQInfo *pQInfo, SQueryTableReq* pQueryMsg, bool stableQuery) { +// STaskAttr* pQueryAttr = pQInfo->runtimeEnv.pQueryAttr; +// +// // in case of point-interpolation query, use asc order scan +// char msg[] = "QInfo:0x%"PRIx64" scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%" PRId64 +// "-%" PRId64 ", new qrange:%" PRId64 "-%" PRId64; +// +// // todo handle the case the the order irrelevant query type mixed up with order critical query type +// // descending order query for last_row query +// if (isFirstLastRowQuery(pQueryAttr)) { +// //qDebug("QInfo:0x%"PRIx64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId, pQueryAttr->order.order, TSDB_ORDER_ASC); +// +// pQueryAttr->order.order = TSDB_ORDER_ASC; +// if (pQueryAttr->window.skey > pQueryAttr->window.ekey) { +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// } +// +// pQueryAttr->needReverseScan = false; +// return; +// } +// +// if (pQueryAttr->groupbyColumn && pQueryAttr->order.order == TSDB_ORDER_DESC) { +// pQueryAttr->order.order = TSDB_ORDER_ASC; +// if (pQueryAttr->window.skey > pQueryAttr->window.ekey) { +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// } +// +// pQueryAttr->needReverseScan = false; +// doUpdateLastKey(pQueryAttr); +// return; +// } +// +// if (pQueryAttr->pointInterpQuery && pQueryAttr->interval.interval == 0) { +// if (!QUERY_IS_ASC_QUERY(pQueryAttr)) { +// //qDebug(msg, pQInfo->qId, "interp", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// } +// +// pQueryAttr->order.order = TSDB_ORDER_ASC; +// return; +// } +// +// if (pQueryAttr->interval.interval == 0) { +// if (onlyFirstQuery(pQueryAttr)) { +// if (!QUERY_IS_ASC_QUERY(pQueryAttr)) { +// //qDebug(msg, pQInfo->qId, "only-first", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey, +//// pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); +// +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// doUpdateLastKey(pQueryAttr); +// } +// +// pQueryAttr->order.order = TSDB_ORDER_ASC; +// pQueryAttr->needReverseScan = false; +// } else if (onlyLastQuery(pQueryAttr) && notContainSessionOrStateWindow(pQueryAttr)) { +// if (QUERY_IS_ASC_QUERY(pQueryAttr)) { +// //qDebug(msg, pQInfo->qId, "only-last", pQueryAttr->order.order, TSDB_ORDER_DESC, pQueryAttr->window.skey, +//// pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); +// +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// doUpdateLastKey(pQueryAttr); +// } +// +// pQueryAttr->order.order = TSDB_ORDER_DESC; +// pQueryAttr->needReverseScan = false; +// } +// +// } else { // interval query +// if (stableQuery) { +// if (onlyFirstQuery(pQueryAttr)) { +// if (!QUERY_IS_ASC_QUERY(pQueryAttr)) { +// //qDebug(msg, pQInfo->qId, "only-first stable", pQueryAttr->order.order, TSDB_ORDER_ASC, +//// pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); +// +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// doUpdateLastKey(pQueryAttr); +// } +// +// pQueryAttr->order.order = TSDB_ORDER_ASC; +// pQueryAttr->needReverseScan = false; +// } else if (onlyLastQuery(pQueryAttr)) { +// if (QUERY_IS_ASC_QUERY(pQueryAttr)) { +// //qDebug(msg, pQInfo->qId, "only-last stable", pQueryAttr->order.order, TSDB_ORDER_DESC, +//// pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); +// +// TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY); +// doUpdateLastKey(pQueryAttr); +// } +// +// pQueryAttr->order.order = TSDB_ORDER_DESC; +// pQueryAttr->needReverseScan = false; +// } +// } +// } +//} static void getIntermediateBufInfo(STaskRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) { STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; @@ -2868,7 +2833,7 @@ static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSData int32_t numOfOutput = pTableScanInfo->numOfOutput; for (int32_t i = 0; i < numOfOutput; ++i) { int32_t functionId = pCtx[i].functionId; - int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->info.colId; + int32_t colId = pTableScanInfo->pExpr[i].base.pParam[0].pCol->colId; // group by + first/last should not apply the first/last block filter if (functionId < 0) { @@ -3196,11 +3161,12 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SqlFunctionCtx* pCt if (pQueryAttr->numOfOutput == 1 && functionId == FUNCTION_TS_COMP && pQueryAttr->stableQuery) { assert(pExprInfo->base.numOfParams == 1); - int16_t tagColId = (int16_t)pExprInfo->base.param[0].i; +// int16_t tagColId = (int16_t)pExprInfo->base.param[0].i; + int16_t tagColId = -1; SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId); doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes); - return; + } else { // set tag value, by which the results are aggregated. int32_t offset = 0; @@ -3210,12 +3176,12 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SqlFunctionCtx* pCt SExprInfo* pLocalExprInfo = &pExpr[idx]; // ts_comp column required the tag value for join filter - if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.pColumns->flag)) { + if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.pParam[0].pCol->flag)) { continue; } // todo use tag column index to optimize performance - doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->info.colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type, + doSetTagValueInParam(pTable, pLocalExprInfo->base.pParam[0].pCol->colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type, pLocalExprInfo->base.resSchema.bytes); if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resSchema.type) @@ -3333,9 +3299,9 @@ int32_t initResultRow(SResultRow *pResultRow) { /* * The start of each column SResultRowEntryInfo is denote by RowCellInfoOffset. * Note that in case of top/bottom query, the whole multiple rows of result is treated as only one row of results. - * +------------+-----------------result column 1-----------+-----------------result column 2-----------+ - * + SResultRow | SResultRowEntryInfo | intermediate buffer1 | SResultRowEntryInfo | intermediate buffer 2| - * +------------+-------------------------------------------+-------------------------------------------+ + * +------------+-----------------result column 1------------+------------------result column 2-----------+ + * | SResultRow | SResultRowEntryInfo | intermediate buffer1 | SResultRowEntryInfo | intermediate buffer 2| + * +------------+--------------------------------------------+--------------------------------------------+ * offset[0] offset[1] offset[2] */ void setDefaultOutputBuf(STaskRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid, int32_t stage) { @@ -3372,8 +3338,9 @@ void setDefaultOutputBuf(STaskRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, in initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols); } + // TODO refactor: some function move away -void setDefaultOutputBuf_rv(SOptrBasicInfo* pInfo, SAggSupporter* pSup, int32_t stage, SExecTaskInfo* pTaskInfo) { +void setFunctionResultOutput(SOptrBasicInfo* pInfo, SAggSupporter* pSup, int32_t stage, SExecTaskInfo* pTaskInfo) { SqlFunctionCtx* pCtx = pInfo->pCtx; SSDataBlock* pDataBlock = pInfo->pRes; int32_t* rowCellInfoOffset = pInfo->rowCellInfoOffset; @@ -3386,23 +3353,17 @@ void setDefaultOutputBuf_rv(SOptrBasicInfo* pInfo, SAggSupporter* pSup, int32_t for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { SColumnInfoData* pData = taosArrayGet(pDataBlock->pDataBlock, i); - /* - * set the output buffer information and intermediate buffer - * not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc. - */ struct SResultRowEntryInfo* pEntry = getResultCell(pRow, i, rowCellInfoOffset); cleanupResultRowEntry(pEntry); pCtx[i].resultInfo = pEntry; - pCtx[i].pOutput = pData->pData; pCtx[i].currentStage = stage; - assert(pCtx[i].pOutput != NULL); // set the timestamp output buffer for top/bottom/diff query - int32_t fid = pCtx[i].functionId; - if (fid == FUNCTION_TOP || fid == FUNCTION_BOTTOM || fid == FUNCTION_DIFF || fid == FUNCTION_DERIVATIVE) { - if (i > 0) pCtx[i].ptsOutputBuf = pCtx[i-1].pOutput; - } +// int32_t fid = pCtx[i].functionId; +// if (fid == FUNCTION_TOP || fid == FUNCTION_BOTTOM || fid == FUNCTION_DIFF || fid == FUNCTION_DERIVATIVE) { +// if (i > 0) pCtx[i].ptsOutputBuf = pCtx[i-1].pOutput; +// } } initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols); @@ -3493,7 +3454,7 @@ void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size) { continue; } - pCtx[j].fpSet->init(&pCtx[j], pCtx[j].resultInfo); + pCtx[j].fpSet.init(&pCtx[j], pCtx[j].resultInfo); } } @@ -3566,7 +3527,7 @@ void finalizeQueryResult(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SResult // if (pCtx[j].functionId < 0) { // doInvokeUdf(pRuntimeEnv->pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); // } else { - pCtx[j].fpSet->finalize(&pCtx[j]); + pCtx[j].fpSet.finalize(&pCtx[j]); // } } // } @@ -3710,7 +3671,7 @@ void doSetTableGroupOutputBuf(SAggOperatorInfo* pAggInfo, int32_t numOfOutput, i * all group belong to one result set, and each group result has different group id so set the id to be one */ if (pResultRow->pageId == -1) { - int32_t ret = addNewWindowResultBuf(pResultRow, pAggInfo->pResultBuf, tableGroupId, pAggInfo->binfo.resRowSize); + int32_t ret = addNewWindowResultBuf(pResultRow, pAggInfo->pResultBuf, tableGroupId, pAggInfo->binfo.pRes->info.rowSize); if (ret != TSDB_CODE_SUCCESS) { return; } @@ -3758,7 +3719,7 @@ void setResultOutputBuf(STaskRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SqlFu void setCtxTagForJoin(STaskRuntimeEnv* pRuntimeEnv, SqlFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable) { STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; - SSqlExpr* pExpr = &pExprInfo->base; + SExprBasicInfo* pExpr = &pExprInfo->base; // if (pQueryAttr->stableQuery && (pRuntimeEnv->pTsBuf != NULL) && // (pExpr->functionId == FUNCTION_TS || pExpr->functionId == FUNCTION_PRJ) && // (pExpr->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_ID)) { @@ -3834,7 +3795,7 @@ void setParamForStableStddev(STaskRuntimeEnv* pRuntimeEnv, SqlFunctionCtx* pCtx, continue; } - SSqlExpr* pExpr = &pExprInfo1->base; + SExprBasicInfo* pExpr = &pExprInfo1->base; pCtx[i].param[0].arr = NULL; pCtx[i].param[0].nType = TSDB_DATA_TYPE_INT; // avoid freeing the memory by setting the type to be int @@ -3863,7 +3824,7 @@ void setParamForStableStddevByColData(STaskRuntimeEnv* pRuntimeEnv, SqlFunctionC #if 0 int32_t numOfExprs = pQueryAttr->numOfOutput; for(int32_t i = 0; i < numOfExprs; ++i) { - SSqlExpr* pExpr1 = &pExpr[i].base; + SExprBasicInfo* pExpr1 = &pExpr[i].base; if (pExpr1->functionId != FUNCTION_STDDEV_DST) { continue; } @@ -4776,6 +4737,11 @@ static SSDataBlock* doTableScan(void* param, bool *newgroup) { STableScanInfo *pTableScanInfo = pOperator->info; SExecTaskInfo *pTaskInfo = pOperator->pTaskInfo; + pTaskInfo->code = pOperator->_openFn(pOperator); + if (pTaskInfo->code != TSDB_CODE_SUCCESS) { + return NULL; + } + // The read handle is not initialized yet, since no qualified tables exists if (pTableScanInfo->pTsdbReadHandle == NULL) { return NULL; @@ -4893,6 +4859,11 @@ static SSDataBlock* doStreamBlockScan(void* param, bool* newgroup) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SStreamBlockScanInfo* pInfo = pOperator->info; + pTaskInfo->code = pOperator->_openFn(pOperator); + if (pTaskInfo->code != TSDB_CODE_SUCCESS) { + return NULL; + } + SDataBlockInfo* pBlockInfo = &pInfo->pRes->info; pBlockInfo->rows = 0; @@ -4933,7 +4904,7 @@ int32_t loadRemoteDataCallback(void* param, const SDataBuf* pMsg, int32_t code) pRsp->useconds = htobe64(pRsp->useconds); pRsp->compLen = htonl(pRsp->compLen); - pSourceDataInfo->status = DATA_READY; + pSourceDataInfo->status = EX_SOURCE_DATA_READY; tsem_post(&pSourceDataInfo->pEx->ready); } @@ -4973,7 +4944,7 @@ static int32_t doSendFetchDataRequest(SExchangeInfo *pExchangeInfo, SExecTaskInf return pTaskInfo->code; } - SDownstreamSource *pSource = taosArrayGet(pExchangeInfo->pSources, sourceIndex); + SDownstreamSourceNode *pSource = taosArrayGet(pExchangeInfo->pSources, sourceIndex); SSourceDataInfo *pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, sourceIndex); qDebug("%s build fetch msg and send to vgId:%d, ep:%s, taskId:0x%" PRIx64 ", %d/%" PRIzu, @@ -5061,17 +5032,17 @@ static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo *pOperator, SEx for (int32_t i = 0; i < totalSources; ++i) { SSourceDataInfo* pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, i); - if (pDataInfo->status == DATA_EXHAUSTED) { + if (pDataInfo->status == EX_SOURCE_DATA_EXHAUSTED) { completed += 1; continue; } - if (pDataInfo->status != DATA_READY) { + if (pDataInfo->status != EX_SOURCE_DATA_READY) { continue; } SRetrieveTableRsp* pRsp = pDataInfo->pRsp; - SDownstreamSource* pSource = taosArrayGet(pExchangeInfo->pSources, i); + SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, i); SSDataBlock* pRes = pExchangeInfo->pResult; @@ -5079,7 +5050,7 @@ static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo *pOperator, SEx qDebug("%s vgId:%d, taskID:0x%" PRIx64 " index:%d completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64 " try next", GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, i + 1, pDataInfo->totalRows, pExchangeInfo->totalRows); - pDataInfo->status = DATA_EXHAUSTED; + pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED; completed += 1; continue; } @@ -5095,15 +5066,15 @@ static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo *pOperator, SEx GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pDataInfo->totalRows, pExchangeInfo->totalRows, pExchangeInfo->totalSize, i + 1, totalSources); - pDataInfo->status = DATA_EXHAUSTED; + pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED; } else { qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64 ", totalBytes:%" PRIu64, GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pExchangeInfo->totalRows, pExchangeInfo->totalSize); } - if (pDataInfo->status != DATA_EXHAUSTED) { - pDataInfo->status = DATA_NOT_READY; + if (pDataInfo->status != EX_SOURCE_DATA_EXHAUSTED) { + pDataInfo->status = EX_SOURCE_DATA_NOT_READY; code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i); if (code != TSDB_CODE_SUCCESS) { goto _error; @@ -5123,13 +5094,9 @@ _error: return NULL; } -static SSDataBlock* concurrentlyLoadRemoteData(SOperatorInfo *pOperator) { +static int32_t prepareConcurrentlyLoad(SOperatorInfo *pOperator) { SExchangeInfo *pExchangeInfo = pOperator->info; SExecTaskInfo *pTaskInfo = pOperator->pTaskInfo; - - if (pOperator->status == OP_RES_TO_RETURN) { - return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo); - } size_t totalSources = taosArrayGetSize(pExchangeInfo->pSources); int64_t startTs = taosGetTimestampUs(); @@ -5138,7 +5105,8 @@ static SSDataBlock* concurrentlyLoadRemoteData(SOperatorInfo *pOperator) { for(int32_t i = 0; i < totalSources; ++i) { int32_t code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i); if (code != TSDB_CODE_SUCCESS) { - return NULL; + pTaskInfo->code = code; + return code; } } @@ -5146,9 +5114,9 @@ static SSDataBlock* concurrentlyLoadRemoteData(SOperatorInfo *pOperator) { qDebug("%s send all fetch request to %"PRIzu" sources completed, elapsed:%"PRId64, GET_TASKID(pTaskInfo), totalSources, endTs - startTs); tsem_wait(&pExchangeInfo->ready); + pOperator->cost.openCost = taosGetTimestampUs() - startTs; - pOperator->status = OP_RES_TO_RETURN; - return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo); + return TSDB_CODE_SUCCESS; } static SSDataBlock* seqLoadRemoteData(SOperatorInfo *pOperator) { @@ -5168,7 +5136,7 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo *pOperator) { tsem_wait(&pExchangeInfo->ready); SSourceDataInfo* pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, pExchangeInfo->current); - SDownstreamSource* pSource = taosArrayGet(pExchangeInfo->pSources, pExchangeInfo->current); + SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, pExchangeInfo->current); SRetrieveTableRsp* pRsp = pDataInfo->pRsp; if (pRsp->numOfRows == 0) { @@ -5176,7 +5144,7 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo *pOperator) { GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pExchangeInfo->current + 1, pDataInfo->totalRows, pExchangeInfo->totalRows); - pDataInfo->status = DATA_EXHAUSTED; + pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED; pExchangeInfo->current += 1; continue; } @@ -5191,7 +5159,7 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo *pOperator) { pDataInfo->totalRows, pExchangeInfo->totalRows, pExchangeInfo->totalSize, pExchangeInfo->current + 1, totalSources); - pDataInfo->status = DATA_EXHAUSTED; + pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED; pExchangeInfo->current += 1; } else { qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64 ", totalBytes:%" PRIu64, @@ -5202,14 +5170,39 @@ static SSDataBlock* seqLoadRemoteData(SOperatorInfo *pOperator) { } } +static int32_t prepareLoadRemoteData(void* param) { + SOperatorInfo *pOperator = (SOperatorInfo*) param; + if (OPTR_IS_OPENED(pOperator)) { + return TSDB_CODE_SUCCESS; + } + + SExchangeInfo *pExchangeInfo = pOperator->info; + if (pExchangeInfo->seqLoadData) { + // do nothing for sequentially load data + } else { + int32_t code = prepareConcurrentlyLoad(pOperator); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + + OPTR_SET_OPENED(pOperator); + return TSDB_CODE_SUCCESS; +} + static SSDataBlock* doLoadRemoteData(void* param, bool* newgroup) { SOperatorInfo *pOperator = (SOperatorInfo*) param; SExchangeInfo *pExchangeInfo = pOperator->info; SExecTaskInfo *pTaskInfo = pOperator->pTaskInfo; - size_t totalSources = taosArrayGetSize(pExchangeInfo->pSources); + int32_t code = pOperator->_openFn(pOperator); + if (code != TSDB_CODE_SUCCESS) { + pTaskInfo->code = code; + return NULL; + } + size_t totalSources = taosArrayGetSize(pExchangeInfo->pSources); if (pOperator->status == OP_EXEC_DONE) { qDebug("%s all %"PRIzu" source(s) are exhausted, total rows:%"PRIu64" bytes:%"PRIu64", elapsed:%.2f ms", GET_TASKID(pTaskInfo), totalSources, pExchangeInfo->totalRows, pExchangeInfo->totalSize, pExchangeInfo->totalElapsed/1000.0); @@ -5217,11 +5210,10 @@ static SSDataBlock* doLoadRemoteData(void* param, bool* newgroup) { } *newgroup = false; - if (pExchangeInfo->seqLoadData) { return seqLoadRemoteData(pOperator); } else { - return concurrentlyLoadRemoteData(pOperator); + return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo); } #if 0 @@ -5234,22 +5226,51 @@ static SSDataBlock* doLoadRemoteData(void* param, bool* newgroup) { #endif } -static SSDataBlock* createResultDataBlock(const SArray* pExprInfo); +static int32_t initDataSource(int32_t numOfSources, SExchangeInfo* pInfo) { + pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo)); + if (pInfo->pSourceDataInfo == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + for(int32_t i = 0; i < numOfSources; ++i) { + SSourceDataInfo dataInfo = {0}; + dataInfo.status = EX_SOURCE_DATA_NOT_READY; + dataInfo.pEx = pInfo; + dataInfo.index = i; -SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray* pExprInfo, SExecTaskInfo* pTaskInfo) { + void* ret = taosArrayPush(pInfo->pSourceDataInfo, &dataInfo); + if (ret == NULL) { + taosArrayDestroy(pInfo->pSourceDataInfo); + return TSDB_CODE_OUT_OF_MEMORY; + } + } + + return TSDB_CODE_SUCCESS; +} + +// TODO handle the error +SOperatorInfo* createExchangeOperatorInfo(const SNodeList* pSources, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) { SExchangeInfo* pInfo = calloc(1, sizeof(SExchangeInfo)); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { + goto _error; + } + + size_t numOfSources = LIST_LENGTH(pSources); + pInfo->pSources = taosArrayInit(numOfSources, sizeof(SDownstreamSourceNode)); + if (pInfo->pSources == NULL) { tfree(pInfo); tfree(pOperator); terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; return NULL; } - size_t numOfSources = taosArrayGetSize(pSources); + for(int32_t i = 0; i < numOfSources; ++i) { + SNodeListNode* pNode = nodesListGetNode((SNodeList*) pSources, i); + taosArrayPush(pInfo->pSources, pNode); + } - pInfo->pSources = taosArrayDup(pSources); pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo)); if (pInfo->pSourceDataInfo == NULL || pInfo->pSources == NULL) { tfree(pInfo); @@ -5260,29 +5281,28 @@ SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray* return NULL; } - for(int32_t i = 0; i < numOfSources; ++i) { - SSourceDataInfo dataInfo = {0}; - dataInfo.status = DATA_NOT_READY; - dataInfo.pEx = pInfo; - dataInfo.index = i; - - taosArrayPush(pInfo->pSourceDataInfo, &dataInfo); + int32_t code = initDataSource(numOfSources, pInfo); + if (code != TSDB_CODE_SUCCESS) { + goto _error; } - size_t size = taosArrayGetSize(pExprInfo); - pInfo->pResult = createResultDataBlock(pExprInfo); + size_t size = pBlock->info.numOfCols; + pInfo->pResult = pBlock; pInfo->seqLoadData = true; + pInfo->seqLoadData = true; // sequentially load data from the source node tsem_init(&pInfo->ready, 0, 0); pOperator->name = "ExchangeOperator"; - pOperator->operatorType = OP_Exchange; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_EXCHANGE; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->numOfOutput = size; - pOperator->nextDataFn = doLoadRemoteData; pOperator->pTaskInfo = pTaskInfo; + pOperator->_openFn = prepareLoadRemoteData; // assign a dummy function. + pOperator->getNextFn = doLoadRemoteData; + pOperator->closeFn = destroyExchangeOperatorInfo; #if 1 { // todo refactor @@ -5308,13 +5328,23 @@ SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray* #endif return pOperator; -} -SSDataBlock* createResultDataBlock(const SArray* pExprInfo) { - SSDataBlock* pResBlock = calloc(1, sizeof(SSDataBlock)); - if (pResBlock == NULL) { - return NULL; - } + _error: + if (pInfo != NULL) { + destroyExchangeOperatorInfo(pInfo, 0); + } + + tfree(pInfo); + tfree(pOperator); + terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; + return NULL; +} + +SSDataBlock* createResultDataBlock(const SArray* pExprInfo) { + SSDataBlock* pResBlock = calloc(1, sizeof(SSDataBlock)); + if (pResBlock == NULL) { + return NULL; + } size_t numOfCols = taosArrayGetSize(pExprInfo); pResBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); @@ -5324,11 +5354,12 @@ SSDataBlock* createResultDataBlock(const SArray* pExprInfo) { SColumnInfoData colInfoData = {0}; SExprInfo* p = taosArrayGetP(pExprInfo, i); - SSchema* pSchema = &p->base.resSchema; + SResSchema* pSchema = &p->base.resSchema; colInfoData.info.type = pSchema->type; colInfoData.info.colId = pSchema->colId; colInfoData.info.bytes = pSchema->bytes; - + colInfoData.info.scale = pSchema->scale; + colInfoData.info.precision = pSchema->precision; taosArrayPush(pResult, &colInfoData); } @@ -5349,19 +5380,20 @@ SOperatorInfo* createTableScanOperatorInfo(void* pTsdbReadHandle, int32_t order, } pInfo->pTsdbReadHandle = pTsdbReadHandle; - pInfo->times = repeatTime; - pInfo->reverseTimes = reverseTime; - pInfo->order = order; - pInfo->current = 0; - pInfo->scanFlag = MAIN_SCAN; - + pInfo->times = repeatTime; + pInfo->reverseTimes = reverseTime; + pInfo->order = order; + pInfo->current = 0; + pInfo->scanFlag = MAIN_SCAN; pOperator->name = "TableScanOperator"; - pOperator->operatorType = OP_TableScan; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->numOfOutput = numOfOutput; - pOperator->nextDataFn = doTableScan; + pOperator->_openFn = operatorDummyOpenFn; + pOperator->getNextFn = doTableScan; + pOperator->closeFn = operatorDummyCloseFn; pOperator->pTaskInfo = pTaskInfo; return pOperator; @@ -5380,13 +5412,13 @@ SOperatorInfo* createTableSeqScanOperatorInfo(void* pTsdbReadHandle, STaskRuntim SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TableSeqScanOperator"; - pOperator->operatorType = OP_TableSeqScan; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->numOfOutput = pRuntimeEnv->pQueryAttr->numOfCols; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doTableScanImpl; + pOperator->getNextFn = doTableScanImpl; return pOperator; } @@ -5407,15 +5439,15 @@ SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbReadHandle, STaskRunt pOperator->name = "TableBlockInfoScanOperator"; // pOperator->operatorType = OP_TableBlockInfoScan; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; // pOperator->numOfOutput = pRuntimeEnv->pQueryAttr->numOfCols; - pOperator->nextDataFn = doBlockInfoScan; + pOperator->getNextFn = doBlockInfoScan; return pOperator; } -SOperatorInfo* createStreamScanOperatorInfo(void *streamReadHandle, SArray* pExprInfo, SArray* pTableIdList, SExecTaskInfo* pTaskInfo) { +SOperatorInfo* createStreamScanOperatorInfo(void *streamReadHandle, SSDataBlock* pResBlock, SArray* pColList, SArray* pTableIdList, SExecTaskInfo* pTaskInfo) { SStreamBlockScanInfo* pInfo = calloc(1, sizeof(SStreamBlockScanInfo)); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { @@ -5425,16 +5457,6 @@ SOperatorInfo* createStreamScanOperatorInfo(void *streamReadHandle, SArray* pExp return NULL; } - // todo dynamic set the value of 4096 - pInfo->pRes = createOutputBuf_rv(pExprInfo, 4096); - - int32_t numOfOutput = (int32_t) taosArrayGetSize(pExprInfo); - SArray* pColList = taosArrayInit(numOfOutput, sizeof(int32_t)); - for(int32_t i = 0; i < numOfOutput; ++i) { - SExprInfo* pExpr = taosArrayGetP(pExprInfo, i); - taosArrayPush(pColList, &pExpr->pExpr->pSchema[0].colId); - } - // set the extract column id to streamHandle tqReadHandleSetColIdList((STqReadHandle* )streamReadHandle, pColList); int32_t code = tqReadHandleSetTbUidList(streamReadHandle, pTableIdList); @@ -5444,16 +5466,135 @@ SOperatorInfo* createStreamScanOperatorInfo(void *streamReadHandle, SArray* pExp return NULL; } - pInfo->readerHandle = streamReadHandle; + pInfo->readerHandle = streamReadHandle; + pInfo->pRes = pResBlock; pOperator->name = "StreamBlockScanOperator"; - pOperator->operatorType = OP_StreamScan; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN; + pOperator->blockingOptr = false; + pOperator->status = OP_NOT_OPENED; + pOperator->info = pInfo; + pOperator->numOfOutput = pResBlock->info.numOfCols; + pOperator->_openFn = operatorDummyOpenFn; + pOperator->getNextFn = doStreamBlockScan; + pOperator->closeFn = operatorDummyCloseFn; + + pOperator->pTaskInfo = pTaskInfo; + return pOperator; +} + + +static int32_t loadSysTableContentCb(void* param, const SDataBuf* pMsg, int32_t code) { + SSourceDataInfo* pSourceDataInfo = (SSourceDataInfo*) param; + pSourceDataInfo->pRsp = pMsg->pData; + + SRetrieveTableRsp* pRsp = pSourceDataInfo->pRsp; + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + pSourceDataInfo->status = EX_SOURCE_DATA_READY; + tsem_post(&pSourceDataInfo->pEx->ready); +} + +static SSDataBlock* doSysTableScan(void* param, bool* newgroup) { +// build message and send to mnode to fetch the content of system tables. + SOperatorInfo* pOperator = (SOperatorInfo*) param; + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SSysTableScanInfo* pInfo = pOperator->info; + + // retrieve local table list info from vnode + if (pInfo->type == TSDB_MGMT_TABLE_TABLE) { + if (pInfo->pCur == NULL) { + pInfo->pCur = metaOpenTbCursor(pInfo->readHandle); + } + + SColumnInfoData* pTableNameCol = taosArrayGet(pInfo->pRes->pDataBlock, 0); + + char * name = NULL; + int32_t numOfRows = 0; + while ((name = metaTbCursorNext(pInfo->pCur)) != NULL) { + colDataAppend(pTableNameCol, numOfRows, name, false); + numOfRows += 1; + if (numOfRows >= pInfo->capacity) { + break; + } + } + + pInfo->totalRows += numOfRows; + pInfo->pRes->info.rows = numOfRows; + +// pInfo->elapsedTime; +// pInfo->totalBytes; + return (pInfo->pRes->info.rows == 0)? NULL:pInfo->pRes; + } else { // load the meta from mnode of the given epset + if (pInfo->pReq == NULL) { + pInfo->pReq = calloc(1, sizeof(SRetrieveTableReq)); + if (pInfo->pReq == NULL) { + pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + pInfo->pReq->type = pInfo->type; + } + + // send the fetch remote task result reques + SMsgSendInfo* pMsgSendInfo = calloc(1, sizeof(SMsgSendInfo)); + if (NULL == pMsgSendInfo) { + qError("%s prepare message %d failed", GET_TASKID(pTaskInfo), (int32_t)sizeof(SMsgSendInfo)); + pTaskInfo->code = TSDB_CODE_QRY_OUT_OF_MEMORY; + return NULL; + } + + pMsgSendInfo->param = NULL; + pMsgSendInfo->msgInfo.pData = pInfo->pReq; + pMsgSendInfo->msgInfo.len = sizeof(SRetrieveTableReq); + pMsgSendInfo->msgType = TDMT_MND_SYSTABLE_RETRIEVE; + pMsgSendInfo->fp = loadRemoteDataCallback; + + int64_t transporterId = 0; + int32_t code = asyncSendMsgToServer(pInfo->pTransporter, &pInfo->epSet, &transporterId, pMsgSendInfo); + + tsem_wait(&pInfo->ready); + // handle the response and return to the caller + } + + return NULL; +} + +SOperatorInfo* createSysTableScanOperatorInfo(void* pSysTableReadHandle, const SArray* pExprInfo, const SSchema* pSchema, + int32_t tableType, SEpSet epset, SExecTaskInfo* pTaskInfo) { + SSysTableScanInfo* pInfo = calloc(1, sizeof(SSysTableScanInfo)); + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); + if (pInfo == NULL || pOperator == NULL) { + tfree(pInfo); + tfree(pOperator); + terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; + return NULL; + } + + // todo: create the schema of result data block + pInfo->capacity = 4096; + pInfo->type = tableType; + if (pInfo->type == TSDB_MGMT_TABLE_TABLE) { + pInfo->readHandle = pSysTableReadHandle; + blockDataEnsureCapacity(pInfo->pRes, pInfo->capacity); + } else { + tsem_init(&pInfo->ready, 0, 0); + pInfo->epSet = epset; + } + + pInfo->readHandle = pSysTableReadHandle; + pOperator->name = "SysTableScanOperator"; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; - pOperator->numOfOutput = numOfOutput; - pOperator->nextDataFn = doStreamBlockScan; + pOperator->numOfOutput = taosArrayGetSize(pExprInfo); + pOperator->getNextFn = doSysTableScan; + pOperator->closeFn = destroySysTableScannerOperatorInfo; pOperator->pTaskInfo = pTaskInfo; + return pOperator; } @@ -5539,10 +5680,10 @@ SArray* getOrderCheckColumns(STaskAttr* pQuery) { for(int32_t i = 0; i < numOfCols; ++i) { SColIndex* index = taosArrayGet(pOrderColumns, i); for(int32_t j = 0; j < pQuery->numOfOutput; ++j) { - SSqlExpr* pExpr = &pQuery->pExpr1[j].base; + SExprBasicInfo* pExpr = &pQuery->pExpr1[j].base; int32_t functionId = getExprFunctionId(&pQuery->pExpr1[j]); - if (index->colId == pExpr->pColumns->info.colId && + if (index->colId == pExpr->pParam[0].pCol->colId && (functionId == FUNCTION_PRJ || functionId == FUNCTION_TAG || functionId == FUNCTION_TS)) { index->colIndex = j; index->colId = pExpr->resSchema.colId; @@ -5569,18 +5710,18 @@ SArray* getResultGroupCheckColumns(STaskAttr* pQuery) { bool found = false; for(int32_t j = 0; j < pQuery->numOfOutput; ++j) { - SSqlExpr* pExpr = &pQuery->pExpr1[j].base; + SExprBasicInfo* pExpr = &pQuery->pExpr1[j].base; int32_t functionId = getExprFunctionId(&pQuery->pExpr1[j]); // FUNCTION_TAG_DUMMY function needs to be ignored - if (index->colId == pExpr->pColumns->info.colId && - ((TSDB_COL_IS_TAG(pExpr->pColumns->flag) && functionId == FUNCTION_TAG) || - (TSDB_COL_IS_NORMAL_COL(pExpr->pColumns->flag) && functionId == FUNCTION_PRJ))) { - index->colIndex = j; - index->colId = pExpr->resSchema.colId; - found = true; - break; - } +// if (index->colId == pExpr->pColumns->info.colId && +// ((TSDB_COL_IS_TAG(pExpr->pColumns->flag) && functionId == FUNCTION_TAG) || +// (TSDB_COL_IS_NORMAL_COL(pExpr->pColumns->flag) && functionId == FUNCTION_PRJ))) { +// index->colIndex = j; +// index->colId = pExpr->resSchema.colId; +// found = true; +// break; +// } } assert(found && index->colIndex >= 0 && index->colIndex < pQuery->numOfOutput); @@ -5589,7 +5730,7 @@ SArray* getResultGroupCheckColumns(STaskAttr* pQuery) { return pOrderColumns; } -static int32_t initAggSup(SAggSupporter* pAggSup, SArray* pExprInfo); +static int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx *pCtx, int32_t numOfOutput); static void clearupAggSup(SAggSupporter* pAggSup); static void destroySortedMergeOperatorInfo(void* param, int32_t numOfOutput) { @@ -5612,6 +5753,21 @@ static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) { tfree(pInfo->prevRow); } +static void assignExprInfo(SExprInfo* dst, const SExprInfo* src) { + assert(dst != NULL && src != NULL); + + *dst = *src; + + dst->pExpr = exprdup(src->pExpr); + dst->base.pParam = calloc(src->base.numOfParams, sizeof(SColumn)); + memcpy(dst->base.pParam, src->base.pParam, sizeof(SColumn) * src->base.numOfParams); + +// memset(dst->base.param, 0, sizeof(SVariant) * tListLen(dst->base.param)); +// for (int32_t j = 0; j < src->base.numOfParams; ++j) { +// taosVariantAssign(&dst->base.param[j], &src->base.param[j]); +// } +} + static SExprInfo* exprArrayDup(SArray* pExprList) { size_t numOfOutput = taosArrayGetSize(pExprList); @@ -5663,7 +5819,7 @@ SSDataBlock* loadNextDataBlock(void* param) { SOperatorInfo* pOperator = (SOperatorInfo*) param; bool newgroup = false; - return pOperator->nextDataFn(pOperator, &newgroup); + return pOperator->getNextFn(pOperator, &newgroup); } static bool needToMerge(SSDataBlock* pBlock, SArray* groupInfo, char **buf, int32_t rowIndex) { @@ -5708,7 +5864,7 @@ static void doMergeResultImpl(SSortedMergeOperatorInfo* pInfo, SqlFunctionCtx *p for (int32_t j = 0; j < numOfExpr; ++j) { int32_t functionId = pCtx[j].functionId; - pCtx[j].fpSet->addInput(&pCtx[j]); +// pCtx[j].fpSet->addInput(&pCtx[j]); // if (functionId < 0) { // SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); @@ -5731,7 +5887,7 @@ static void doFinalizeResultImpl(SqlFunctionCtx *pCtx, int32_t numOfExpr) { // SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); // doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); // } else { - pCtx[j].fpSet->addInput(&pCtx[j]); + pCtx[j].fpSet.finalize(&pCtx[j]); } } @@ -5767,7 +5923,7 @@ static void doMergeImpl(SOperatorInfo* pOperator, int32_t numOfExpr, SSDataBlock doMergeResultImpl(pInfo, pCtx, numOfExpr, i); } else { doFinalizeResultImpl(pCtx, numOfExpr); - int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfOutput); + int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfOutput, NULL); // setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows); // TODO check for available buffer; @@ -5779,7 +5935,7 @@ static void doMergeImpl(SOperatorInfo* pOperator, int32_t numOfExpr, SSDataBlock continue; } - pCtx[j].fpSet->addInput(&pCtx[j]); + pCtx[j].fpSet.process(&pCtx[j]); } doMergeResultImpl(pInfo, pCtx, numOfExpr, i); @@ -5823,7 +5979,7 @@ static SSDataBlock* doMerge(SOperatorInfo* pOperator) { } doFinalizeResultImpl(pInfo->binfo.pCtx, pOperator->numOfOutput); - int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfOutput); + int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfOutput, NULL); // setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows); // TODO check for available buffer; @@ -5879,7 +6035,7 @@ static SArray* createBlockOrder(SArray* pExprInfo, SArray* pOrderVal) { for (int32_t i = 0; i < taosArrayGetSize(pExprInfo); ++i) { SExprInfo* pExpr = taosArrayGet(pExprInfo, i); - if (pExpr->base.resSchema.colId == pOrder->col.info.colId) { + if (pExpr->base.resSchema.colId == pOrder->col.colId) { orderInfo.colIndex = i; break; } @@ -5909,10 +6065,10 @@ static int32_t initGroupCol(SArray* pExprInfo, SArray* pGroupInfo, SSortedMergeO SColumn* pCol = taosArrayGet(pGroupInfo, i); for(int32_t j = 0; j < taosArrayGetSize(pExprInfo); ++j) { SExprInfo* pe = taosArrayGet(pExprInfo, j); - if (pe->base.resSchema.colId == pCol->info.colId) { + if (pe->base.resSchema.colId == pCol->colId) { taosArrayPush(plist, pCol); taosArrayPush(pInfo->groupInfo, &j); - len += pCol->info.bytes; + len += pCol->bytes; break; } } @@ -5931,7 +6087,7 @@ static int32_t initGroupCol(SArray* pExprInfo, SArray* pGroupInfo, SSortedMergeO for(int32_t i = 0; i < numOfGroupCol; ++i) { pInfo->groupVal[i] = start + offset; SColumn* pCol = taosArrayGet(plist, i); - offset += pCol->info.bytes; + offset += pCol->bytes; } taosArrayDestroy(plist); @@ -5947,7 +6103,7 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t } int32_t numOfOutput = taosArrayGetSize(pExprInfo); - pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset, &pInfo->binfo.resRowSize); + pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset); pInfo->binfo.pRes = createOutputBuf_rv(pExprInfo, pInfo->binfo.capacity); initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)1); @@ -5955,12 +6111,12 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t goto _error; } - int32_t code = initAggSup(&pInfo->aggSup, pExprInfo); + int32_t code = doInitAggInfoSup(&pInfo->aggSup, pInfo->binfo.pCtx, numOfOutput); if (code != TSDB_CODE_SUCCESS) { goto _error; } - setDefaultOutputBuf_rv(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, pTaskInfo); + setFunctionResultOutput(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, pTaskInfo); code = initGroupCol(pExprInfo, pGroupInfo, pInfo); if (code != TSDB_CODE_SUCCESS) { goto _error; @@ -5975,15 +6131,15 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t pInfo->binfo.capacity = blockDataGetCapacityInRow(pInfo->binfo.pRes, pInfo->bufPageSize); pOperator->name = "SortedMerge"; - pOperator->operatorType = OP_SortedMerge; + // pOperator->operatorType = OP_SortedMerge; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->numOfOutput = numOfOutput; pOperator->pExpr = exprArrayDup(pExprInfo); pOperator->pTaskInfo = pTaskInfo; - pOperator->nextDataFn = doSortedMerge; + pOperator->getNextFn = doSortedMerge; pOperator->closeFn = destroySortedMergeOperatorInfo; code = appendDownstream(pOperator, downstream, numOfDownstream); @@ -6073,13 +6229,13 @@ SOperatorInfo *createOrderOperatorInfo(SOperatorInfo* downstream, SArray* pExprI } pOperator->name = "Order"; - pOperator->operatorType = OP_Order; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SORT; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->pTaskInfo = pTaskInfo; - pOperator->nextDataFn = doSort; + pOperator->getNextFn = doSort; pOperator->closeFn = destroyOrderOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -6105,7 +6261,7 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6118,15 +6274,15 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { // the pDataBlock are always the same one, no need to call this again setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); - doAggregateImpl(pOperator, 0, pInfo->pCtx, pBlock); + doAggregateImpl(pOperator, 0, pInfo->pCtx); } doSetOperatorCompleted(pOperator); finalizeQueryResult(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset); - pInfo->pRes->info.rows = getNumOfResult(pInfo->pCtx, pOperator->numOfOutput); + getNumOfResult(pInfo->pCtx, pOperator->numOfOutput, pInfo->pRes); - return (pInfo->pRes->info.rows != 0)? pInfo->pRes:NULL; + return (blockDataGetNumOfRows(pInfo->pRes) != 0)? pInfo->pRes:NULL; } static SSDataBlock* doMultiTableAggregate(void* param, bool* newgroup) { @@ -6155,7 +6311,7 @@ static SSDataBlock* doMultiTableAggregate(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6181,7 +6337,7 @@ static SSDataBlock* doMultiTableAggregate(void* param, bool* newgroup) { } setExecutionContext(pOperator->numOfOutput, pAggInfo->current->groupIndex, key, pTaskInfo, pAggInfo->current, pAggInfo); - doAggregateImpl(pOperator, 0, pInfo->pCtx, pBlock); + doAggregateImpl(pOperator, 0, pInfo->pCtx); } pOperator->status = OP_RES_TO_RETURN; @@ -6228,7 +6384,7 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { projectApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); - pRes->info.rows = getNumOfResult(pInfo->pCtx, pOperator->numOfOutput); + pRes->info.rows = getNumOfResult(pInfo->pCtx, pOperator->numOfOutput, NULL); if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) { copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfOutput); resetResultRowEntryResult(pInfo->pCtx, pOperator->numOfOutput); @@ -6241,7 +6397,7 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { // The downstream exec may change the value of the newgroup, so use a local variable instead. publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = pOperator->pDownstream[0]->nextDataFn(pOperator->pDownstream[0], newgroup); + SSDataBlock* pBlock = pOperator->pDownstream[0]->getNextFn(pOperator->pDownstream[0], newgroup); publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6277,7 +6433,7 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { updateOutputBuf(pInfo, &pInfo->capacity, pBlock->info.rows); projectApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); - pRes->info.rows = getNumOfResult(pInfo->pCtx, pOperator->numOfOutput); + pRes->info.rows = getNumOfResult(pInfo->pCtx, pOperator->numOfOutput, NULL); if (pRes->info.rows >= 1000/*pRuntimeEnv->resultInfo.threshold*/) { break; } @@ -6299,7 +6455,7 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) { SSDataBlock* pBlock = NULL; while (1) { publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - pBlock = pOperator->pDownstream[0]->nextDataFn(pOperator->pDownstream[0], newgroup); + pBlock = pOperator->pDownstream[0]->getNextFn(pOperator->pDownstream[0], newgroup); publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6350,7 +6506,7 @@ static SSDataBlock* doFilter(void* param, bool* newgroup) { while (1) { publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock *pBlock = pOperator->pDownstream[0]->nextDataFn(pOperator->pDownstream[0], newgroup); + SSDataBlock *pBlock = pOperator->pDownstream[0]->getNextFn(pOperator->pDownstream[0], newgroup); publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6393,7 +6549,7 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6453,7 +6609,7 @@ static SSDataBlock* doAllIntervalAgg(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6516,7 +6672,7 @@ static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6571,7 +6727,7 @@ static SSDataBlock* doAllSTableIntervalAgg(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6706,7 +6862,7 @@ static SSDataBlock* doStateWindowAgg(void *param, bool* newgroup) { SOperatorInfo* downstream = pOperator->pDownstream[0]; while (1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -6768,7 +6924,7 @@ static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { break; @@ -6821,7 +6977,7 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = downstream->nextDataFn(downstream, newgroup); + SSDataBlock* pBlock = downstream->getNextFn(downstream, newgroup); publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { break; @@ -6906,7 +7062,7 @@ static SSDataBlock* doFill(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - SSDataBlock* pBlock = pOperator->pDownstream[0]->nextDataFn(pOperator->pDownstream[0], newgroup); + SSDataBlock* pBlock = pOperator->pDownstream[0]->getNextFn(pOperator->pDownstream[0], newgroup); publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (*newgroup) { @@ -6996,13 +7152,14 @@ static void destroyOperatorInfo(SOperatorInfo* pOperator) { tfree(pOperator); } -static int32_t initAggSup(SAggSupporter* pAggSup, SArray* pExprInfo) { +int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx *pCtx, int32_t numOfOutput) { _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pAggSup->resultRowSize = getResultRowSize(pCtx, numOfOutput); pAggSup->keyBuf = calloc(1, sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES); pAggSup->pResultRowHashTable = taosHashInit(10, hashFn, true, HASH_NO_LOCK); pAggSup->pResultRowListSet = taosHashInit(100, hashFn, false, HASH_NO_LOCK); - pAggSup->pool = initResultRowPool(getResultRowSize(pExprInfo)); + pAggSup->pool = initResultRowPool(pAggSup->resultRowSize); pAggSup->pResultRowArrayList = taosArrayInit(10, sizeof(SResultRowCell)); if (pAggSup->keyBuf == NULL || pAggSup->pResultRowArrayList == NULL || pAggSup->pResultRowListSet == NULL || @@ -7021,12 +7178,12 @@ static void clearupAggSup(SAggSupporter* pAggSup) { destroyResultRowPool(pAggSup->pool); } -static int32_t initAggInfo(SAggOperatorInfo* pInfo, SArray* pExprInfo, int32_t numOfRows, const STableGroupInfo* pTableGroupInfo) { - pInfo->binfo.pRes = createOutputBuf_rv(pExprInfo, numOfRows); - pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset, &pInfo->binfo.resRowSize); - pInfo->binfo.capacity = 4096; +static int32_t initAggInfo(SAggOperatorInfo* pInfo, SArray* pExprInfo, int32_t numOfRows, SSDataBlock* pResultBlock, const STableGroupInfo* pTableGroupInfo) { + pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset); + pInfo->binfo.pRes = pResultBlock; + pInfo->binfo.capacity = numOfRows; - initAggSup(&pInfo->aggSup, pExprInfo); + doInitAggInfoSup(&pInfo->aggSup, pInfo->binfo.pCtx, taosArrayGetSize(pExprInfo)); pInfo->pTableQueryInfo = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo)); int32_t index = 0; @@ -7048,27 +7205,28 @@ static int32_t initAggInfo(SAggOperatorInfo* pInfo, SArray* pExprInfo, int32_t n return TSDB_CODE_SUCCESS; } -SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo) { +SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SSDataBlock* pResultBlock, + SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo) { SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo)); int32_t numOfRows = 1; //(int32_t)(getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery)); - initAggInfo(pInfo, pExprInfo, numOfRows, pTableGroupInfo); - setDefaultOutputBuf_rv(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, pTaskInfo); + initAggInfo(pInfo, pExprInfo, numOfRows, pResultBlock, pTableGroupInfo); + setFunctionResultOutput(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, pTaskInfo); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TableAggregate"; - pOperator->operatorType = OP_Aggregate; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_AGG; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->pExpr = exprArrayDup(pExprInfo); pOperator->numOfOutput = taosArrayGetSize(pExprInfo); pOperator->pTaskInfo = pTaskInfo; - pOperator->nextDataFn = doAggregate; - pOperator->closeFn = destroyAggOperatorInfo; + pOperator->getNextFn = doAggregate; + pOperator->closeFn = destroyAggOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); return pOperator; @@ -7077,7 +7235,7 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pE static void doDestroyBasicInfo(SOptrBasicInfo* pInfo, int32_t numOfOutput) { assert(pInfo != NULL); - destroySQLFunctionCtx(pInfo->pCtx, numOfOutput); + destroySqlFunctionCtx(pInfo->pCtx, numOfOutput); tfree(pInfo->rowCellInfoOffset); cleanupResultRowInfo(&pInfo->resultRowInfo); @@ -7097,6 +7255,7 @@ static void destroyAggOperatorInfo(void* param, int32_t numOfOutput) { SAggOperatorInfo* pInfo = (SAggOperatorInfo*) param; doDestroyBasicInfo(&pInfo->binfo, numOfOutput); } + static void destroySWindowOperatorInfo(void* param, int32_t numOfOutput) { SSWindowOperatorInfo* pInfo = (SSWindowOperatorInfo*) param; doDestroyBasicInfo(&pInfo->binfo, numOfOutput); @@ -7115,17 +7274,17 @@ static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) { tfree(pInfo->prevData); } -static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) { +void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) { SProjectOperatorInfo* pInfo = (SProjectOperatorInfo*) param; doDestroyBasicInfo(&pInfo->binfo, numOfOutput); } -static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) { +void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) { STagScanInfo* pInfo = (STagScanInfo*) param; pInfo->pRes = blockDataDestroy(pInfo->pRes); } -static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput) { +void destroyOrderOperatorInfo(void* param, int32_t numOfOutput) { SOrderOperatorInfo* pInfo = (SOrderOperatorInfo*) param; pInfo->pDataBlock = blockDataDestroy(pInfo->pDataBlock); @@ -7145,26 +7304,48 @@ static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) { pInfo->pRes = blockDataDestroy(pInfo->pRes); } -SOperatorInfo* createMultiTableAggOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo) { +static void destroySysTableScannerOperatorInfo(void* param, int32_t numOfOutput) { + SSysTableScanInfo* pInfo = (SSysTableScanInfo*) param; + tsem_destroy(&pInfo->ready); + blockDataDestroy(pInfo->pRes); + + if (pInfo->type == TSDB_MGMT_TABLE_TABLE) { + metaCloseTbCursor(pInfo->pCur); + } +} + +void destroyExchangeOperatorInfo(void* param, int32_t numOfOutput) { + SExchangeInfo* pExInfo = (SExchangeInfo*) param; + taosArrayDestroy(pExInfo->pSources); + taosArrayDestroy(pExInfo->pSourceDataInfo); + if (pExInfo->pResult != NULL) { + blockDataDestroy(pExInfo->pResult); + } + + tsem_destroy(&pExInfo->ready); +} + +SOperatorInfo* createMultiTableAggOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SSDataBlock* pResBlock, SExecTaskInfo* pTaskInfo, const STableGroupInfo* pTableGroupInfo) { SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo)); int32_t numOfRows = 1; size_t numOfOutput = taosArrayGetSize(pExprInfo); - initAggInfo(pInfo, pExprInfo, numOfRows, pTableGroupInfo); + initAggInfo(pInfo, pExprInfo, numOfRows, pResBlock, pTableGroupInfo); size_t tableGroup = taosArrayGetSize(pTableGroupInfo->pGroupList); initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)tableGroup); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "MultiTableAggregate"; - pOperator->operatorType = OP_MultiTableAggregate; + // pOperator->operatorType = OP_MultiTableAggregate; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->pExpr = exprArrayDup(pExprInfo); pOperator->numOfOutput = numOfOutput; + pOperator->pTaskInfo = pTaskInfo; - pOperator->nextDataFn = doMultiTableAggregate; + pOperator->getNextFn = doMultiTableAggregate; pOperator->closeFn = destroyAggOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7176,21 +7357,21 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SArray* pExp int32_t numOfRows = 4096; pInfo->binfo.pRes = createOutputBuf_rv(pExprInfo, numOfRows); - pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset, &pInfo->binfo.resRowSize); + pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset); // initResultRowInfo(&pBInfo->resultRowInfo, 8); -// setDefaultOutputBuf_rv(pBInfo, MAIN_SCAN); +// setFunctionResultOutput(pBInfo, MAIN_SCAN); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "ProjectOperator"; - pOperator->operatorType = OP_Project; + // pOperator->operatorType = OP_Project; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; pOperator->pExpr = exprArrayDup(pExprInfo); pOperator->numOfOutput = taosArrayGetSize(pExprInfo); - pOperator->nextDataFn = doProjectOperation; + pOperator->getNextFn = doProjectOperation; pOperator->closeFn = destroyProjectOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7230,31 +7411,6 @@ SColumnInfo* extractColumnFilterInfo(SExprInfo* pExpr, int32_t numOfOutput, int3 return 0; } -SOperatorInfo* createFilterOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, - int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter) { - SFilterOperatorInfo* pInfo = calloc(1, sizeof(SFilterOperatorInfo)); - - assert(numOfFilter > 0 && pCols != NULL); -// doCreateFilterInfo(pCols, numOfOutput, numOfFilter, &pInfo->pFilterInfo, 0); - pInfo->numOfFilterCols = numOfFilter; - - SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); - - pOperator->name = "FilterOperator"; -// pOperator->operatorType = OP_Filter; - pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; - pOperator->numOfOutput = numOfOutput; - pOperator->pExpr = pExpr; - pOperator->nextDataFn = doFilter; - pOperator->info = pInfo; - pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->closeFn = destroyConditionOperatorInfo; - int32_t code = appendDownstream(pOperator, &downstream, 1); - - return pOperator; -} - SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream) { SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo)); pInfo->limit = pRuntimeEnv->pQueryAttr->limit.limit; @@ -7264,11 +7420,11 @@ SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorIn pOperator->name = "LimitOperator"; // pOperator->operatorType = OP_Limit; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; - pOperator->nextDataFn = doLimit; + pOperator->status = OP_NOT_OPENED; + pOperator->getNextFn = doLimit; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - int32_t code = appendDownstream(pOperator, &downstream, 1); + int32_t code = appendDownstream(pOperator, &downstream, 1); return pOperator; } @@ -7276,16 +7432,17 @@ SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorIn SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SInterval* pInterval, SExecTaskInfo* pTaskInfo) { STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo)); - initAggSup(&pInfo->aggSup, pExprInfo); + size_t numOfOutput = taosArrayGetSize(pExprInfo); + doInitAggInfoSup(&pInfo->aggSup, pInfo->binfo.pCtx, numOfOutput); - pInfo->order = TSDB_ORDER_ASC; + pInfo->order = TSDB_ORDER_ASC; pInfo->precision = TSDB_TIME_PRECISION_MICRO; - pInfo->win = pTaskInfo->window; - pInfo->interval = *pInterval; + pInfo->win = pTaskInfo->window; + pInfo->interval = *pInterval; - int32_t code = createDiskbasedBuf(&pInfo->pResultBuf, 4096, 4096 * 256, pTaskInfo->id.str, "/tmp/"); + int32_t code = createDiskbasedBuf(&pInfo->pResultBuf, 4096, 4096 * 256, pTaskInfo->id.str, "/tmp/"); - pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset, &pInfo->binfo.resRowSize); + pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset); pInfo->binfo.pRes = createOutputBuf_rv(pExprInfo, pInfo->binfo.capacity); initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)1); @@ -7293,15 +7450,15 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SArray* pEx SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TimeIntervalAggOperator"; - pOperator->operatorType = OP_TimeWindow; + // pOperator->operatorType = OP_TimeWindow; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->pExpr = exprArrayDup(pExprInfo); pOperator->pTaskInfo = pTaskInfo; pOperator->numOfOutput = taosArrayGetSize(pExprInfo); pOperator->info = pInfo; - pOperator->nextDataFn = doIntervalAgg; + pOperator->getNextFn = doIntervalAgg; pOperator->closeFn = destroyBasicOperatorInfo; code = appendDownstream(pOperator, &downstream, 1); @@ -7320,12 +7477,12 @@ SOperatorInfo* createAllTimeIntervalOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, S pOperator->name = "AllTimeIntervalAggOperator"; // pOperator->operatorType = OP_AllTimeWindow; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doAllIntervalAgg; + pOperator->getNextFn = doAllIntervalAgg; pOperator->closeFn = destroyBasicOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7344,12 +7501,12 @@ SOperatorInfo* createStatewindowOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOper pOperator->name = "StateWindowOperator"; // pOperator->operatorType = OP_StateWindow; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doStateWindowAgg; + pOperator->getNextFn = doStateWindowAgg; pOperator->closeFn = destroyStateWindowOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7369,12 +7526,12 @@ SOperatorInfo* createSWindowOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperator pOperator->name = "SessionWindowAggOperator"; // pOperator->operatorType = OP_SessionWindow; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doSessionWindowAgg; + pOperator->getNextFn = doSessionWindowAgg; pOperator->closeFn = destroySWindowOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7392,13 +7549,13 @@ SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(STaskRuntimeEnv* pRuntim pOperator->name = "MultiTableTimeIntervalOperator"; // pOperator->operatorType = OP_MultiTableTimeInterval; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doSTableIntervalAgg; + pOperator->getNextFn = doSTableIntervalAgg; pOperator->closeFn = destroyBasicOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7416,13 +7573,13 @@ SOperatorInfo* createAllMultiTableTimeIntervalOperatorInfo(STaskRuntimeEnv* pRun pOperator->name = "AllMultiTableTimeIntervalOperator"; // pOperator->operatorType = OP_AllMultiTableTimeInterval; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doAllSTableIntervalAgg; + pOperator->getNextFn = doAllSTableIntervalAgg; pOperator->closeFn = destroyBasicOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7448,13 +7605,13 @@ SOperatorInfo* createGroupbyOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperator SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "GroupbyAggOperator"; pOperator->blockingOptr = true; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; // pOperator->operatorType = OP_Groupby; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = hashGroupbyAggregate; + pOperator->getNextFn = hashGroupbyAggregate; pOperator->closeFn = destroyGroupbyOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7487,13 +7644,13 @@ SOperatorInfo* createFillOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInf pOperator->name = "FillOperator"; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; // pOperator->operatorType = OP_Fill; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = doFill; + pOperator->getNextFn = doFill; pOperator->closeFn = destroySFillOperatorInfo; int32_t code = appendDownstream(pOperator, &downstream, 1); @@ -7536,15 +7693,14 @@ SOperatorInfo* createSLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorI SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "SLimitOperator"; - pOperator->operatorType = OP_SLimit; + // pOperator->operatorType = OP_SLimit; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; // pOperator->exec = doSLimit; pOperator->info = pInfo; - pOperator->pRuntimeEnv = pRuntimeEnv; pOperator->closeFn = destroySlimitOperatorInfo; - int32_t code = appendDownstream(pOperator, &downstream, 1); + int32_t code = appendDownstream(pOperator, &downstream, 1); return pOperator; } @@ -7678,6 +7834,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { return (pRes->info.rows == 0)? NULL:pInfo->pRes; #endif + return 0; } SOperatorInfo* createTagScanOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput) { @@ -7692,11 +7849,11 @@ SOperatorInfo* createTagScanOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SExprInfo SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "SeqTableTagScan"; - pOperator->operatorType = OP_TagScan; + pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; - pOperator->nextDataFn = doTagScan; + pOperator->getNextFn = doTagScan; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->pRuntimeEnv = pRuntimeEnv; @@ -7766,7 +7923,7 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) { while(1) { publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - pBlock = pOperator->pDownstream[0]->nextDataFn(pOperator->pDownstream[0], newgroup); + pBlock = pOperator->pDownstream[0]->getNextFn(pOperator->pDownstream[0], newgroup); publishOperatorProfEvent(pOperator->pDownstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { @@ -7832,13 +7989,13 @@ SOperatorInfo* createDistinctOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperato SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "DistinctOperator"; pOperator->blockingOptr = false; - pOperator->status = OP_IN_EXECUTING; + pOperator->status = OP_NOT_OPENED; // pOperator->operatorType = OP_Distinct; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->nextDataFn = hashDistinct; + pOperator->getNextFn = hashDistinct; pOperator->pExpr = pExpr; pOperator->closeFn = destroyDistinctOperatorInfo; @@ -7846,16 +8003,16 @@ SOperatorInfo* createDistinctOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperato return pOperator; } -static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) { +static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SExprBasicInfo *pExpr, SColumnInfo* pTagCols) { int32_t j = 0; - if (TSDB_COL_IS_TAG(pExpr->pColumns->flag)) { - if (pExpr->pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) { + if (TSDB_COL_IS_TAG(pExpr->pParam[0].pCol->type)) { + if (pExpr->pParam[0].pCol->colId == TSDB_TBNAME_COLUMN_INDEX) { return TSDB_TBNAME_COLUMN_INDEX; } while(j < pTableInfo->numOfTags) { - if (pExpr->pColumns->info.colId == pTagCols[j].colId) { + if (pExpr->pParam[0].pCol->colId == pTagCols[j].colId) { return j; } @@ -7877,47 +8034,12 @@ static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *p return INT32_MIN; // return a less than TSDB_TBNAME_COLUMN_INDEX value } -bool validateExprColumnInfo(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) { +bool validateExprColumnInfo(SQueriedTableInfo *pTableInfo, SExprBasicInfo *pExpr, SColumnInfo* pTagCols) { int32_t j = getColumnIndexInSource(pTableInfo, pExpr, pTagCols); return j != INT32_MIN; } -static bool validateQueryMsg(SQueryTableReq *pQueryMsg) { - if (pQueryMsg->interval.interval < 0) { - //qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval); - return false; - } - -// if (pQueryMsg->sw.gap < 0 || pQueryMsg->sw.primaryColId != PRIMARYKEY_TIMESTAMP_COL_ID) { - //qError("qmsg:%p illegal value of session window time %" PRId64, pQueryMsg, pQueryMsg->sw.gap); -// return false; -// } - -// if (pQueryMsg->sw.gap > 0 && pQueryMsg->interval.interval > 0) { - //qError("qmsg:%p illegal value of session window time %" PRId64" and interval value %"PRId64, pQueryMsg, -// pQueryMsg->sw.gap, pQueryMsg->interval.interval); -// return false; -// } - - if (pQueryMsg->numOfTables <= 0) { - //qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables); - return false; - } - - if (pQueryMsg->numOfGroupCols < 0) { - //qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols); - return false; - } - - if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) { - //qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput); - return false; - } - - return true; -} - -static bool validateQueryTableCols(SQueriedTableInfo* pTableInfo, SSqlExpr** pExpr, int32_t numOfOutput, +static bool validateQueryTableCols(SQueriedTableInfo* pTableInfo, SExprBasicInfo** pExpr, int32_t numOfOutput, SColumnInfo* pTagCols, void* pMsg) { int32_t numOfTotal = pTableInfo->numOfCols + pTableInfo->numOfTags; if (pTableInfo->numOfCols < 0 || pTableInfo->numOfTags < 0 || numOfTotal > TSDB_MAX_COLUMNS) { @@ -7927,7 +8049,7 @@ static bool validateQueryTableCols(SQueriedTableInfo* pTableInfo, SSqlExpr** pEx if (numOfTotal == 0) { // table total columns are not required. // for(int32_t i = 0; i < numOfOutput; ++i) { -// SSqlExpr* p = pExpr[i]; +// SExprBasicInfo* p = pExpr[i]; // if ((p->functionId == FUNCTION_TAGPRJ) || // (p->functionId == FUNCTION_TID_TAG && p->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) || // (p->functionId == FUNCTION_COUNT && p->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) || @@ -7948,23 +8070,6 @@ static bool validateQueryTableCols(SQueriedTableInfo* pTableInfo, SSqlExpr** pEx return true; } -static char *createTableIdList(SQueryTableReq *pQueryMsg, char *pMsg, SArray **pTableIdList) { - assert(pQueryMsg->numOfTables > 0); - - *pTableIdList = taosArrayInit(pQueryMsg->numOfTables, sizeof(STableIdInfo)); - - for (int32_t j = 0; j < pQueryMsg->numOfTables; ++j) { - STableIdInfo* pTableIdInfo = (STableIdInfo *)pMsg; - pTableIdInfo->uid = htobe64(pTableIdInfo->uid); - pTableIdInfo->key = htobe64(pTableIdInfo->key); - - taosArrayPush(*pTableIdList, pTableIdInfo); - pMsg += sizeof(STableIdInfo); - } - - return pMsg; -} - static int32_t deserializeColFilterInfo(SColumnFilterInfo* pColFilters, int16_t numOfFilters, char** pMsg) { for (int32_t f = 0; f < numOfFilters; ++f) { SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)(*pMsg); @@ -7996,6 +8101,65 @@ static int32_t deserializeColFilterInfo(SColumnFilterInfo* pColFilters, int16_t return TSDB_CODE_SUCCESS; } +static SResSchema createResSchema(int32_t type, int32_t bytes, int32_t slotId, int32_t scale, int32_t precision, const char* name) { + SResSchema s = {0}; + s.scale = scale; + s.precision = precision; + s.type = type; + s.bytes = bytes; + s.colId = slotId; + strncpy(s.name, name, tListLen(s.name)); + + return s; +} + +SArray* createExprInfo(SAggPhysiNode* pPhyNode) { + int32_t numOfAggFuncs = LIST_LENGTH(pPhyNode->pAggFuncs); + + SArray* pArray = taosArrayInit(numOfAggFuncs, POINTER_BYTES); + for(int32_t i = 0; i < numOfAggFuncs; ++i) { + SExprInfo* pExp = calloc(1, sizeof(SExprInfo)); + + pExp->pExpr = calloc(1, sizeof(tExprNode)); + pExp->pExpr->_function.num = 1; + + pExp->base.pParam = calloc(1, sizeof(SFunctParam)); + pExp->base.numOfParams = 1; + + pExp->base.pParam[0].pCol = calloc(1, sizeof(SColumn)); + SColumn* pCol = pExp->base.pParam[0].pCol; + + STargetNode* pTargetNode = (STargetNode*) nodesListGetNode(pPhyNode->pAggFuncs, i); + ASSERT(pTargetNode->slotId == i); + + SFunctionNode* pFuncNode = (SFunctionNode*)pTargetNode->pExpr; + + SDataType *pType = &pFuncNode->node.resType; + pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, + pType->scale, pType->precision, pFuncNode->node.aliasName); + + pExp->pExpr->_function.pFunctNode = pFuncNode; + strncpy(pExp->pExpr->_function.functionName, pFuncNode->functionName, tListLen(pExp->pExpr->_function.functionName)); + + // TODO: value parameter needs to be handled + int32_t numOfParam = LIST_LENGTH(pFuncNode->pParameterList); + for(int32_t j = 0; j < numOfParam; ++j) { + SNode* p1 = nodesListGetNode(pFuncNode->pParameterList, j); + SColumnNode* pcn = (SColumnNode*)p1; + + pCol->slotId = pcn->slotId; + pCol->bytes = pcn->node.resType.bytes; + pCol->type = pcn->node.resType.type; + pCol->scale = pcn->node.resType.scale; + pCol->precision = pcn->node.resType.precision; + pCol->dataBlockId = pcn->dataBlockId; + } + taosArrayPush(pArray, &pExp); + } + + return pArray; +} + static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId) { SExecTaskInfo* pTaskInfo = calloc(1, sizeof(SExecTaskInfo)); setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED); @@ -8010,104 +8174,124 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId) { return pTaskInfo; } -static tsdbReaderT doCreateDataReader(STableScanPhyNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId); +static tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId); static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo, uint64_t queryId, uint64_t taskId); +static SArray* extractTableIdList(const STableGroupInfo* pTableGroupInfo); +static SArray* extractScanColumnId(SNodeList* pNodeList); + +SOperatorInfo* doCreateOperatorTreeNode(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId, STableGroupInfo* pTableGroupInfo) { + if (nodeType(pPhyNode) == QUERY_NODE_PHYSICAL_PLAN_PROJECT) { // ignore the project node + pPhyNode = nodesListGetNode(pPhyNode->pChildren, 0); + } -SOperatorInfo* doCreateOperatorTreeNode(SPhyNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId, STableGroupInfo* pTableGroupInfo) { - if (pPhyNode->pChildren == NULL || taosArrayGetSize(pPhyNode->pChildren) == 0) { - if (pPhyNode->info.type == OP_TableScan) { - SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode; + if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) { + if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pPhyNode)) { + SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode; - size_t numOfCols = taosArrayGetSize(pPhyNode->pTargets); - tsdbReaderT pDataReader = doCreateDataReader((STableScanPhyNode*) pPhyNode, pHandle, (uint64_t) queryId, taskId); + size_t numOfCols = LIST_LENGTH(pScanPhyNode->pScanCols); + tsdbReaderT pDataReader = doCreateDataReader((STableScanPhysiNode*)pPhyNode, pHandle, (uint64_t)queryId, taskId); int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId); - return createTableScanOperatorInfo(pDataReader, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pScanPhyNode->reverse, pTaskInfo); - } else if (pPhyNode->info.type == OP_Exchange) { - SExchangePhyNode* pEx = (SExchangePhyNode*) pPhyNode; - return createExchangeOperatorInfo(pEx->pSrcEndPoints, pEx->node.pTargets, pTaskInfo); - } else if (pPhyNode->info.type == OP_StreamScan) { - SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode; // simple child table. + return createTableScanOperatorInfo(pDataReader, pScanPhyNode->order, numOfCols, pScanPhyNode->count, + pScanPhyNode->reverse, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == nodeType(pPhyNode)) { + SExchangePhysiNode* pExchange = (SExchangePhysiNode*)pPhyNode; + SSDataBlock* pResBlock = createOutputBuf_rv1(pExchange->node.pOutputDataBlockDesc); + return createExchangeOperatorInfo(pExchange->pSrcEndPoints, pResBlock, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == nodeType(pPhyNode)) { + SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode; // simple child table. + STableGroupInfo groupInfo = {0}; int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, &groupInfo, queryId, taskId); - SArray* idList = NULL; + SArray* tableIdList = extractTableIdList(&groupInfo); - if (groupInfo.numOfTables > 0) { - SArray* pa = taosArrayGetP(groupInfo.pGroupList, 0); - ASSERT(taosArrayGetSize(groupInfo.pGroupList) == 1); + SSDataBlock* pResBlock = createOutputBuf_rv1(pScanPhyNode->node.pOutputDataBlockDesc); + SArray* colList = extractScanColumnId(pScanPhyNode->pScanCols); - // Transfer the Array of STableKeyInfo into uid list. - size_t numOfTables = taosArrayGetSize(pa); - idList = taosArrayInit(numOfTables, sizeof(uint64_t)); + SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pResBlock, colList, tableIdList, pTaskInfo); - for (int32_t i = 0; i < numOfTables; ++i) { - STableKeyInfo* pkeyInfo = taosArrayGet(pa, i); - taosArrayPush(idList, &pkeyInfo->uid); - } - } else { - idList = taosArrayInit(4, sizeof(uint64_t)); - } - - SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pPhyNode->pTargets, idList, pTaskInfo); - taosArrayDestroy(idList); - - //TODO destroy groupInfo + taosArrayDestroy(tableIdList); return pOperator; } } - if (pPhyNode->info.type == OP_Aggregate) { - size_t size = taosArrayGetSize(pPhyNode->pChildren); + if (QUERY_NODE_PHYSICAL_PLAN_AGG == nodeType(pPhyNode)) { + size_t size = LIST_LENGTH(pPhyNode->pChildren); assert(size == 1); - // TODO single table agg for (int32_t i = 0; i < size; ++i) { - SPhyNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i); + SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i); SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo); - return createAggregateOperatorInfo(op, pPhyNode->pTargets, pTaskInfo, pTableGroupInfo); + + SArray* pExprInfo = createExprInfo((SAggPhysiNode*)pPhyNode); + SSDataBlock* pResBlock = createOutputBuf_rv1(pPhyNode->pOutputDataBlockDesc); + return createAggregateOperatorInfo(op, pExprInfo, pResBlock, pTaskInfo, pTableGroupInfo); } - } else if (pPhyNode->info.type == OP_MultiTableAggregate) { + } /*else if (pPhyNode->info.type == OP_MultiTableAggregate) { size_t size = taosArrayGetSize(pPhyNode->pChildren); assert(size == 1); for (int32_t i = 0; i < size; ++i) { - SPhyNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i); + SPhysiNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i); SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo); return createMultiTableAggOperatorInfo(op, pPhyNode->pTargets, pTaskInfo, pTableGroupInfo); } - } + }*/ } -static tsdbReaderT createDataReaderImpl(STableScanPhyNode* pTableScanNode, STableGroupInfo* pGroupInfo, void* readHandle, uint64_t queryId, uint64_t taskId) { +static tsdbReaderT createDataReaderImpl(STableScanPhysiNode* pTableScanNode, STableGroupInfo* pGroupInfo, void* readHandle, uint64_t queryId, uint64_t taskId) { STsdbQueryCond cond = {.loadExternalRows = false}; - cond.order = pTableScanNode->scan.order; - cond.numOfCols = taosArrayGetSize(pTableScanNode->scan.node.pTargets); - cond.colList = calloc(cond.numOfCols, sizeof(SColumnInfo)); + cond.order = pTableScanNode->scan.order; + cond.numOfCols = LIST_LENGTH(pTableScanNode->scan.pScanCols); + cond.colList = calloc(cond.numOfCols, sizeof(SColumnInfo)); if (cond.colList == NULL) { terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; return NULL; } - cond.twindow = pTableScanNode->window; + cond.twindow = pTableScanNode->scanRange; cond.type = BLOCK_LOAD_OFFSET_SEQ_ORDER; +// cond.type = pTableScanNode->scanFlag; + int32_t j = 0; for (int32_t i = 0; i < cond.numOfCols; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pTableScanNode->scan.node.pTargets, i); - assert(pExprInfo->pExpr->nodeType == TEXPR_COL_NODE); + STargetNode* pNode = (STargetNode*)nodesListGetNode(pTableScanNode->scan.pScanCols, i); + SColumnNode* pColNode = (SColumnNode*)pNode->pExpr; + if (pColNode->colType == COLUMN_TYPE_TAG) { + continue; + } - SSchema* pSchema = pExprInfo->pExpr->pSchema; - cond.colList[i].type = pSchema->type; - cond.colList[i].bytes = pSchema->bytes; - cond.colList[i].colId = pSchema->colId; + cond.colList[j].type = pColNode->node.resType.type; + cond.colList[j].bytes = pColNode->node.resType.bytes; + cond.colList[j].colId = pColNode->colId; + j += 1; } + cond.numOfCols = j; return tsdbQueryTables(readHandle, &cond, pGroupInfo, queryId, taskId); } -static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo, uint64_t queryId, uint64_t taskId) { +SArray* extractScanColumnId(SNodeList* pNodeList) { + size_t numOfCols = LIST_LENGTH(pNodeList); + SArray* pList = taosArrayInit(numOfCols, sizeof(int16_t)); + if (pList == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + for(int32_t i = 0; i < numOfCols; ++i) { + STargetNode* pNode = (STargetNode*) nodesListGetNode(pNodeList, i); + SColumnNode* pColNode = (SColumnNode*) pNode->pExpr; + taosArrayPush(pList, &pColNode->colId); + } + + return pList; +} + +int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo, uint64_t queryId, uint64_t taskId) { int32_t code = 0; if (tableType == TSDB_SUPER_TABLE) { code = tsdbQuerySTableByTagCond(metaHandle, tableUid, 0, NULL, 0, 0, NULL, pGroupInfo, NULL, 0, queryId, taskId); @@ -8118,7 +8302,25 @@ static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t return code; } -static tsdbReaderT doCreateDataReader(STableScanPhyNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId) { +SArray* extractTableIdList(const STableGroupInfo* pTableGroupInfo) { + SArray* tableIdList = taosArrayInit(4, sizeof(uint64_t)); + + if (pTableGroupInfo->numOfTables > 0) { + SArray* pa = taosArrayGetP(pTableGroupInfo->pGroupList, 0); + ASSERT(taosArrayGetSize(pTableGroupInfo->pGroupList) == 1); + + // Transfer the Array of STableKeyInfo into uid list. + size_t numOfTables = taosArrayGetSize(pa); + for (int32_t i = 0; i < numOfTables; ++i) { + STableKeyInfo* pkeyInfo = taosArrayGet(pa, i); + taosArrayPush(tableIdList, &pkeyInfo->uid); + } + } + + return tableIdList; +} + +tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, uint64_t queryId, uint64_t taskId) { STableGroupInfo groupInfo = {0}; uint64_t uid = pTableScanNode->scan.uid; @@ -8201,27 +8403,6 @@ int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int return TSDB_CODE_SUCCESS; } -int32_t buildArithmeticExprFromMsg(SExprInfo *pExprInfo, void *pQueryMsg) { - //qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg); - - tExprNode* pExprNode = NULL; - TRY(TSDB_MAX_TAG_CONDITIONS) { - pExprNode = exprTreeFromBinary(pExprInfo->base.param[0].pz, pExprInfo->base.param[0].nLen); - } CATCH( code ) { - CLEANUP_EXECUTE(); - //qError("qmsg:%p failed to create arithmetic expression string from:%s, reason: %s", pQueryMsg, pExprInfo->base.param[0].pz, tstrerror(code)); - return code; - } END_TRY - - if (pExprNode == NULL) { - //qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pExprInfo->base.param[0].pz); - return TSDB_CODE_QRY_APP_ERROR; - } - - pExprInfo->pExpr = pExprNode; - return TSDB_CODE_SUCCESS; -} - static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) { for (int32_t i = 0; i < numOfOutput; ++i) { int16_t functId = getExprFunctionId(&pExprs[i]); @@ -8243,127 +8424,6 @@ static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SCol } // TODO tag length should be passed from client, refactor -int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExprInfo** pExprInfo, - SSqlExpr** pExprMsg, SColumnInfo* pTagCols, int32_t queryType, void* pMsg, struct SUdfInfo* pUdfInfo) { - *pExprInfo = NULL; - int32_t code = TSDB_CODE_SUCCESS; - -// code = initUdfInfo(pUdfInfo); - if (code) { - return code; - } - - SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo)); - if (pExprs == NULL) { - return TSDB_CODE_QRY_OUT_OF_MEMORY; - } - - bool isSuperTable = /*QUERY_IS_STABLE_QUERY(queryType);*/ true; - int16_t tagLen = 0; - - for (int32_t i = 0; i < numOfOutput; ++i) { - pExprs[i].base = *pExprMsg[i]; - - memset(pExprs[i].base.param, 0, sizeof(SVariant) * tListLen(pExprs[i].base.param)); - for (int32_t j = 0; j < pExprMsg[i]->numOfParams; ++j) { - taosVariantAssign(&pExprs[i].base.param[j], &pExprMsg[i]->param[j]); - } - - int16_t type = 0; - int16_t bytes = 0; - - // parse the arithmetic expression - int32_t functionId = getExprFunctionId(&pExprs[i]); - if (functionId == FUNCTION_ARITHM) { - code = buildArithmeticExprFromMsg(&pExprs[i], pMsg); - - if (code != TSDB_CODE_SUCCESS) { - tfree(pExprs); - return code; - } - - type = TSDB_DATA_TYPE_DOUBLE; - bytes = tDataTypes[type].bytes; - } else if (functionId == FUNCTION_BLKINFO) { - SSchema s = {.type=TSDB_DATA_TYPE_BINARY, .bytes=TSDB_MAX_BINARY_LEN}; - type = s.type; - bytes = s.bytes; - } else if (pExprs[i].base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX && functionId == FUNCTION_TAGPRJ) { // parse the normal column - const SSchema* s = tGetTbnameColumnSchema(); - type = s->type; - bytes = s->bytes; - } else if (pExprs[i].base.pColumns->info.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.pColumns->info.colId > TSDB_RES_COL_ID) { - // it is a user-defined constant value column - assert(functionId == FUNCTION_PRJ); - - type = pExprs[i].base.param[1].nType; - bytes = pExprs[i].base.param[1].nLen; - if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - bytes += VARSTR_HEADER_SIZE; - } - } else { - int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols); - if (TSDB_COL_IS_TAG(pExprs[i].base.pColumns->flag)) { - if (j < TSDB_TBNAME_COLUMN_INDEX || j >= pTableInfo->numOfTags) { - tfree(pExprs); - return TSDB_CODE_QRY_INVALID_MSG; - } - } else { - if (j < PRIMARYKEY_TIMESTAMP_COL_ID || j >= pTableInfo->numOfCols) { - tfree(pExprs); - return TSDB_CODE_QRY_INVALID_MSG; - } - } - - if (pExprs[i].base.pColumns->info.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) { - SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.pColumns->flag))? &pTagCols[j]:&pTableInfo->colList[j]; - type = pCol->type; - bytes = pCol->bytes; - } else { - const SSchema* s = tGetTbnameColumnSchema(); - - type = s->type; - bytes = s->bytes; - } - -// if (pExprs[i].base.flist.numOfFilters > 0) { -// int32_t ret = cloneExprFilterInfo(&pExprs[i].base.flist.filterInfo, pExprMsg[i]->flist.filterInfo, -// pExprMsg[i]->flist.numOfFilters); -// if (ret) { -// tfree(pExprs); -// return ret; -// } -// } - } - - int32_t param = (int32_t)pExprs[i].base.param[0].i; -// if (functionId != FUNCTION_ARITHM && -// (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) { -// tfree(pExprs); -// return TSDB_CODE_QRY_INVALID_MSG; -// } - - // todo remove it - SResultDataInfo info; - if (getResultDataInfo(type, bytes, functionId, param, &info, 0, isSuperTable/*, pUdfInfo*/) != TSDB_CODE_SUCCESS) { - tfree(pExprs); - return TSDB_CODE_QRY_INVALID_MSG; - } - - if (functionId == FUNCTION_TAG_DUMMY || functionId == FUNCTION_TS_DUMMY) { - tagLen += pExprs[i].base.resSchema.bytes; - } - - assert(isValidDataType(pExprs[i].base.resSchema.type)); - } - - // the tag length is affected by other tag columns, so this should be update. - updateOutputBufForTopBotQuery(pTableInfo, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable); - - *pExprInfo = pExprs; - return TSDB_CODE_SUCCESS; -} - int32_t createQueryFilter(char *data, uint16_t len, SFilterInfo** pFilters) { tExprNode* expr = NULL; @@ -8385,26 +8445,6 @@ int32_t createQueryFilter(char *data, uint16_t len, SFilterInfo** pFilters) { // return ret; } -SGroupbyExpr *createGroupbyExprFromMsg(SQueryTableReq *pQueryMsg, SColIndex *pColIndex, int32_t *code) { - if (pQueryMsg->numOfGroupCols == 0) { - return NULL; - } - - // using group by tag columns - SGroupbyExpr *pGroupbyExpr = (SGroupbyExpr *)calloc(1, sizeof(SGroupbyExpr)); - if (pGroupbyExpr == NULL) { - *code = TSDB_CODE_QRY_OUT_OF_MEMORY; - return NULL; - } - - pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex)); - for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) { - taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]); - } - - return pGroupbyExpr; -} - //int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo, uint64_t qId) { // *pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * numOfFilterCols); // if (*pFilterInfo == NULL) { @@ -8492,7 +8532,7 @@ static void doUpdateExprColumnIndex(STaskAttr *pQueryAttr) { assert(pQueryAttr->pExpr1 != NULL && pQueryAttr != NULL); for (int32_t k = 0; k < pQueryAttr->numOfOutput; ++k) { - SSqlExpr *pSqlExprMsg = &pQueryAttr->pExpr1[k].base; + SExprBasicInfo *pSqlExprMsg = &pQueryAttr->pExpr1[k].base; // if (pSqlExprMsg->functionId == FUNCTION_ARITHM) { // continue; // } @@ -8549,75 +8589,6 @@ void setResultBufSize(STaskAttr* pQueryAttr, SRspResultInfo* pResultInfo) { pResultInfo->total = 0; } -FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) { - return ((SQInfo *)qHandle)->qId == qId; -} - -int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, STaskParam* param, char* start, - int32_t prevResultLen, void* merger) { - int32_t code = TSDB_CODE_SUCCESS; - - STaskRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; - pRuntimeEnv->qinfo = pQInfo; - - STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr; - - STSBuf *pTsBuf = NULL; - - if (pTsBufInfo->tsLen > 0) { // open new file to save the result - char* tsBlock = start + pTsBufInfo->tsOffset; - pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pTsBufInfo->tsNumOfBlocks, pTsBufInfo->tsLen, pTsBufInfo->tsOrder, - pQueryAttr->vgId); - - if (pTsBuf == NULL) { - code = TSDB_CODE_QRY_NO_DISKSPACE; - goto _error; - } - tsBufResetPos(pTsBuf); - bool ret = tsBufNextPos(pTsBuf); - UNUSED(ret); - } - - SArray* prevResult = NULL; - if (prevResultLen > 0) { - prevResult = interResFromBinary(param->prevResult, prevResultLen); - pRuntimeEnv->prevResult = prevResult; - } - - pRuntimeEnv->currentOffset = pQueryAttr->limit.offset; - if (tsdb != NULL) { -// pQueryAttr->precision = tsdbGetCfg(tsdb)->precision; - } - - if ((QUERY_IS_ASC_QUERY(pQueryAttr) && (pQueryAttr->window.skey > pQueryAttr->window.ekey)) || - (!QUERY_IS_ASC_QUERY(pQueryAttr) && (pQueryAttr->window.ekey > pQueryAttr->window.skey))) { - //qDebug("QInfo:0x%"PRIx64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQueryAttr->window.skey, -// pQueryAttr->window.ekey, pQueryAttr->order.order); -// setTaskStatus(pOperator->pTaskInfo, QUERY_COMPLETED); - pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0; - // todo free memory - return TSDB_CODE_SUCCESS; - } - - if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) { - //qDebug("QInfo:0x%"PRIx64" no table qualified for tag filter, abort query", pQInfo->qId); -// setTaskStatus(pOperator->pTaskInfo, QUERY_COMPLETED); - return TSDB_CODE_SUCCESS; - } - - // filter the qualified - if ((code = doInitQInfo(pQInfo, pTsBuf, tsdb, sourceOptr, param->tableScanOperator, param->pOperator, merger)) != TSDB_CODE_SUCCESS) { - goto _error; - } - - return code; - -_error: - // table query ref will be decrease during error handling -// doDestroyTask(pQInfo); - return code; -} - //TODO refactor void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) { if (pFilter == NULL || numOfFilters == 0) { @@ -8657,44 +8628,6 @@ static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) { pTableqinfoGroupInfo->numOfTables = 0; } -void* destroyQueryFuncExpr(SExprInfo* pExprInfo, int32_t numOfExpr) { - if (pExprInfo == NULL) { - assert(numOfExpr == 0); - return NULL; - } - - for (int32_t i = 0; i < numOfExpr; ++i) { - if (pExprInfo[i].pExpr != NULL) { - tExprTreeDestroy(pExprInfo[i].pExpr, NULL); - } - -// if (pExprInfo[i].base.flist.filterInfo) { -// freeColumnFilterInfo(pExprInfo[i].base.flist.filterInfo, pExprInfo[i].base.flist.numOfFilters); -// } - - for(int32_t j = 0; j < pExprInfo[i].base.numOfParams; ++j) { - taosVariantDestroy(&pExprInfo[i].base.param[j]); - } - } - - tfree(pExprInfo); - return NULL; -} - -void* freeColumnInfo(SColumnInfo* pColumnInfo, int32_t numOfCols) { - if (pColumnInfo != NULL) { - assert(numOfCols >= 0); - - for (int32_t i = 0; i < numOfCols; i++) { - freeColumnFilterInfo(pColumnInfo[i].flist.filterInfo, pColumnInfo[i].flist.numOfFilters); - } - - tfree(pColumnInfo); - } - - return NULL; -} - void doDestroyTask(SExecTaskInfo *pTaskInfo) { qDebug("%s execTask is freed", GET_TASKID(pTaskInfo)); diff --git a/source/libs/executor/test/executorTests.cpp b/source/libs/executor/test/executorTests.cpp index ff29d5f3555613b08911fbb8d1b39cc6cab9b645..38ceeffc20c09bcf507bbeeaf70bbb4602c8b41f 100644 --- a/source/libs/executor/test/executorTests.cpp +++ b/source/libs/executor/test/executorTests.cpp @@ -201,9 +201,9 @@ SOperatorInfo* createDummyOperator(int32_t startVal, int32_t numOfBlocks, int32_ pOperator->name = "dummyInputOpertor4Test"; if (numOfCols == 1) { - pOperator->nextDataFn = getDummyBlock; + pOperator->getNextFn = getDummyBlock; } else { - pOperator->nextDataFn = get2ColsDummyBlock; + pOperator->getNextFn = get2ColsDummyBlock; } SDummyInputInfo *pInfo = (SDummyInputInfo*) calloc(1, sizeof(SDummyInputInfo)); @@ -224,600 +224,734 @@ int main(int argc, char** argv) { TEST(testCase, build_executor_tree_Test) { const char* msg = "{\n" - " \"Type\": \"33\",\n" - " \"Name\": \"PhysiProject\",\n" - " \"PhysiProject\": {\n" - " \"OutputDataBlockDesc\": {\n" - " \"Type\": \"19\",\n" - " \"Name\": \"TupleDesc\",\n" - " \"TupleDesc\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"Slots\": [\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"0\",\n" - " \"DataType\": {\n" - " \"Type\": \"9\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": false\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"1\",\n" - " \"DataType\": {\n" - " \"Type\": \"4\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"4\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": false\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"2\",\n" - " \"DataType\": {\n" - " \"Type\": \"8\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"20\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": false\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"3\",\n" - " \"DataType\": {\n" - " \"Type\": \"5\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": false\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"4\",\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": false\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"5\",\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": false\n" - " }\n" - " }\n" - " ]\n" - " }\n" - " },\n" - " \"Children\": [\n" - " {\n" - " \"Type\": \"30\",\n" - " \"Name\": \"PhysiTableScan\",\n" - " \"PhysiTableScan\": {\n" - " \"OutputDataBlockDesc\": {\n" - " \"Type\": \"19\",\n" - " \"Name\": \"TupleDesc\",\n" - " \"TupleDesc\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"Slots\": [\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"0\",\n" - " \"DataType\": {\n" - " \"Type\": \"9\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": true\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"1\",\n" - " \"DataType\": {\n" - " \"Type\": \"4\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"4\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": true\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"2\",\n" - " \"DataType\": {\n" - " \"Type\": \"8\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"20\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": true\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"3\",\n" - " \"DataType\": {\n" - " \"Type\": \"5\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": true\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"4\",\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": true\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"20\",\n" - " \"Name\": \"SlotDesc\",\n" - " \"SlotDesc\": {\n" - " \"SlotId\": \"5\",\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"Reserve\": false,\n" - " \"Output\": true\n" - " }\n" - " }\n" - " ]\n" - " }\n" - " },\n" - " \"ScanCols\": [\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"9\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"ts\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"1\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"ts\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"1\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"4\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"4\"\n" - " },\n" - " \"AliasName\": \"c1\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"2\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c1\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"2\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"8\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"20\"\n" - " },\n" - " \"AliasName\": \"c2\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"3\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c2\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"3\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"5\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"c3\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"4\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c3\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"4\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"c4\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"5\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c4\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"5\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"c5\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"6\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c5\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " }\n" - " ],\n" - " \"TableId\": \"1\",\n" - " \"TableType\": \"3\",\n" - " \"ScanOrder\": \"1\",\n" - " \"ScanCount\": \"1\",\n" - " \"ReverseScanCount\": \"0\",\n" - " \"ScanFlag\": \"0\",\n" - " \"StartKey\": \"-9223372036854775808\",\n" - " \"EndKey\": \"9223372036854775807\"\n" - " }\n" - " }\n" - " ],\n" - " \"Projections\": [\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"SlotId\": \"0\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"9\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"ts\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"1\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"ts\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"0\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"SlotId\": \"1\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"4\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"4\"\n" - " },\n" - " \"AliasName\": \"c1\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"2\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c1\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"1\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"SlotId\": \"2\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"8\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"20\"\n" - " },\n" - " \"AliasName\": \"c2\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"3\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c2\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"2\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"SlotId\": \"3\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"5\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"c3\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"4\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c3\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"3\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"SlotId\": \"4\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"c4\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"5\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c4\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"4\"\n" - " }\n" - " }\n" - " }\n" - " },\n" - " {\n" - " \"Type\": \"18\",\n" - " \"Name\": \"Target\",\n" - " \"Target\": {\n" - " \"DataBlockId\": \"1\",\n" - " \"SlotId\": \"5\",\n" - " \"Expr\": {\n" - " \"Type\": \"1\",\n" - " \"Name\": \"Column\",\n" - " \"Column\": {\n" - " \"DataType\": {\n" - " \"Type\": \"7\",\n" - " \"Precision\": \"0\",\n" - " \"Scale\": \"0\",\n" - " \"Bytes\": \"8\"\n" - " },\n" - " \"AliasName\": \"c5\",\n" - " \"TableId\": \"0\",\n" - " \"ColId\": \"6\",\n" - " \"ColType\": \"1\",\n" - " \"DbName\": \"test\",\n" - " \"TableName\": \"t1\",\n" - " \"TableAlias\": \"t1\",\n" - " \"ColName\": \"c5\",\n" - " \"DataBlockId\": \"0\",\n" - " \"SlotId\": \"5\"\n" - " }\n" - " }\n" - " }\n" - " }\n" - " ]\n" - " }\n" - "}"; + " \"NodeType\": \"48\",\n" + " \"Name\": \"PhysiSubplan\",\n" + " \"PhysiSubplan\": {\n" + " \"Id\": {\n" + " \"QueryId\": \"0\",\n" + " \"TemplateId\": \"0\",\n" + " \"SubplanId\": \"0\"\n" + " },\n" + " \"SubplanType\": \"0\",\n" + " \"MsgType\": \"515\",\n" + " \"Level\": \"0\",\n" + " \"NodeAddr\": {\n" + " \"Id\": \"1\",\n" + " \"InUse\": \"0\",\n" + " \"NumOfEps\": \"1\",\n" + " \"Eps\": [\n" + " {\n" + " \"Fqdn\": \"node1\",\n" + " \"Port\": \"6030\"\n" + " }\n" + " ]\n" + " },\n" + " \"RootNode\": {\n" + " \"NodeType\": \"41\",\n" + " \"Name\": \"PhysiProject\",\n" + " \"PhysiProject\": {\n" + " \"OutputDataBlockDesc\": {\n" + " \"NodeType\": \"19\",\n" + " \"Name\": \"TupleDesc\",\n" + " \"TupleDesc\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"Slots\": [\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"0\",\n" + " \"DataType\": {\n" + " \"Type\": \"9\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"1\",\n" + " \"DataType\": {\n" + " \"Type\": \"4\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"4\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"2\",\n" + " \"DataType\": {\n" + " \"Type\": \"8\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"20\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"3\",\n" + " \"DataType\": {\n" + " \"Type\": \"5\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"4\",\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"5\",\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"Children\": [\n" + " {\n" + " \"NodeType\": \"38\",\n" + " \"Name\": \"PhysiTableScan\",\n" + " \"PhysiTableScan\": {\n" + " \"OutputDataBlockDesc\": {\n" + " \"NodeType\": \"19\",\n" + " \"Name\": \"TupleDesc\",\n" + " \"TupleDesc\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"Slots\": [\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"0\",\n" + " \"DataType\": {\n" + " \"Type\": \"9\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": true\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"1\",\n" + " \"DataType\": {\n" + " \"Type\": \"4\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"4\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": true\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"2\",\n" + " \"DataType\": {\n" + " \"Type\": \"8\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"20\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": true\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"3\",\n" + " \"DataType\": {\n" + " \"Type\": \"5\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": true\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"4\",\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": true\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"5\",\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": true\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"ScanCols\": [\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"9\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"ts\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"1\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"ts\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"1\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"4\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"4\"\n" + " },\n" + " \"AliasName\": \"c1\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"2\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c1\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"2\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"8\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"20\"\n" + " },\n" + " \"AliasName\": \"c2\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"3\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c2\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"3\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"5\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"c3\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"4\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c3\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"4\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"c4\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"5\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c4\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"5\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"c5\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"6\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c5\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " ],\n" + " \"TableId\": \"1\",\n" + " \"TableType\": \"3\",\n" + " \"ScanOrder\": \"1\",\n" + " \"ScanCount\": \"1\",\n" + " \"ReverseScanCount\": \"0\",\n" + " \"ScanFlag\": \"0\",\n" + " \"StartKey\": \"-9223372036854775808\",\n" + " \"EndKey\": \"9223372036854775807\"\n" + " }\n" + " }\n" + " ],\n" + " \"Projections\": [\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"SlotId\": \"0\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"9\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"ts\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"1\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"ts\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"0\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"SlotId\": \"1\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"4\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"4\"\n" + " },\n" + " \"AliasName\": \"c1\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"2\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c1\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"1\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"SlotId\": \"2\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"8\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"20\"\n" + " },\n" + " \"AliasName\": \"c2\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"3\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c2\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"2\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"SlotId\": \"3\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"5\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"c3\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"4\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c3\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"3\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"SlotId\": \"4\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"c4\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"5\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c4\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"4\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"18\",\n" + " \"Name\": \"Target\",\n" + " \"Target\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"SlotId\": \"5\",\n" + " \"Expr\": {\n" + " \"NodeType\": \"1\",\n" + " \"Name\": \"Column\",\n" + " \"Column\": {\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"AliasName\": \"c5\",\n" + " \"TableId\": \"0\",\n" + " \"ColId\": \"6\",\n" + " \"ColType\": \"1\",\n" + " \"DbName\": \"test\",\n" + " \"TableName\": \"t1\",\n" + " \"TableAlias\": \"t1\",\n" + " \"ColName\": \"c5\",\n" + " \"DataBlockId\": \"0\",\n" + " \"SlotId\": \"5\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"DataSink\": {\n" + " \"NodeType\": \"46\",\n" + " \"Name\": \"PhysiDispatch\",\n" + " \"PhysiDispatch\": {\n" + " \"InputDataBlockDesc\": {\n" + " \"NodeType\": \"19\",\n" + " \"Name\": \"TupleDesc\",\n" + " \"TupleDesc\": {\n" + " \"DataBlockId\": \"1\",\n" + " \"Slots\": [\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"0\",\n" + " \"DataType\": {\n" + " \"Type\": \"9\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"1\",\n" + " \"DataType\": {\n" + " \"Type\": \"4\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"4\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"2\",\n" + " \"DataType\": {\n" + " \"Type\": \"8\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"20\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"3\",\n" + " \"DataType\": {\n" + " \"Type\": \"5\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"4\",\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " },\n" + " {\n" + " \"NodeType\": \"20\",\n" + " \"Name\": \"SlotDesc\",\n" + " \"SlotDesc\": {\n" + " \"SlotId\": \"5\",\n" + " \"DataType\": {\n" + " \"Type\": \"7\",\n" + " \"Precision\": \"0\",\n" + " \"Scale\": \"0\",\n" + " \"Bytes\": \"8\"\n" + " },\n" + " \"Reserve\": false,\n" + " \"Output\": false\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SExecTaskInfo* pTaskInfo = nullptr; DataSinkHandle sinkHandle = nullptr; SReadHandle handle = {.reader = reinterpret_cast(0x1), .meta = reinterpret_cast(0x1)}; - SSubplan* plan = NULL; - qStringToSubplan(msg, &plan); + struct SSubplan *plan = NULL; + int32_t code = qStringToSubplan(msg, &plan); + ASSERT_EQ(code, 0); - int32_t code = qCreateExecTask(&handle, 2, 1, NULL, (void**) &pTaskInfo, &sinkHandle); + code = qCreateExecTask(&handle, 2, 1, plan, (void**) &pTaskInfo, &sinkHandle); + ASSERT_EQ(code, 0); } +#if 0 + TEST(testCase, inMem_sort_Test) { SArray* pOrderVal = taosArrayInit(4, sizeof(SOrder)); SOrder o = {.order = TSDB_ORDER_ASC}; @@ -837,7 +971,7 @@ TEST(testCase, inMem_sort_Test) { SOperatorInfo* pOperator = createOrderOperatorInfo(createDummyOperator(10000, 5, 1000, data_asc, 1), pExprInfo, pOrderVal, NULL); bool newgroup = false; - SSDataBlock* pRes = pOperator->nextDataFn(pOperator, &newgroup); + SSDataBlock* pRes = pOperator->getNextFn(pOperator, &newgroup); SColumnInfoData* pCol1 = static_cast(taosArrayGet(pRes->pDataBlock, 0)); SColumnInfoData* pCol2 = static_cast(taosArrayGet(pRes->pDataBlock, 1)); @@ -847,6 +981,8 @@ TEST(testCase, inMem_sort_Test) { } } +#endif + typedef struct su { int32_t v; char *c; @@ -865,11 +1001,12 @@ int32_t cmp(const void* p1, const void* p2) { } } +#if 0 TEST(testCase, external_sort_Test) { #if 0 su* v = static_cast(calloc(1000000, sizeof(su))); for(int32_t i = 0; i < 1000000; ++i) { - v[i].v = rand(); + v[i].v = taosRand(); v[i].c = static_cast(malloc(4)); *(int32_t*) v[i].c = i; } @@ -882,7 +1019,7 @@ TEST(testCase, external_sort_Test) { return; #endif - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); SArray* pOrderVal = taosArrayInit(4, sizeof(SOrder)); SOrder o = {0}; @@ -912,7 +1049,7 @@ TEST(testCase, external_sort_Test) { while(1) { int64_t s = taosGetTimestampUs(); - pRes = pOperator->nextDataFn(pOperator, &newgroup); + pRes = pOperator->getNextFn(pOperator, &newgroup); int64_t e = taosGetTimestampUs(); if (t++ == 1) { @@ -943,7 +1080,7 @@ TEST(testCase, external_sort_Test) { } TEST(testCase, sorted_merge_Test) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); SArray* pOrderVal = taosArrayInit(4, sizeof(SOrder)); SOrder o = {0}; @@ -984,7 +1121,7 @@ TEST(testCase, sorted_merge_Test) { while(1) { int64_t s = taosGetTimestampUs(); - pRes = pOperator->nextDataFn(pOperator, &newgroup); + pRes = pOperator->getNextFn(pOperator, &newgroup); int64_t e = taosGetTimestampUs(); if (t++ == 1) { @@ -1015,7 +1152,7 @@ TEST(testCase, sorted_merge_Test) { } TEST(testCase, time_interval_Operator_Test) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); SArray* pOrderVal = taosArrayInit(4, sizeof(SOrder)); SOrder o = {0}; @@ -1062,7 +1199,7 @@ TEST(testCase, time_interval_Operator_Test) { while(1) { int64_t s = taosGetTimestampUs(); - pRes = pOperator->nextDataFn(pOperator, &newgroup); + pRes = pOperator->getNextFn(pOperator, &newgroup); int64_t e = taosGetTimestampUs(); if (t++ == 1) { @@ -1091,5 +1228,6 @@ TEST(testCase, time_interval_Operator_Test) { taosArrayDestroy(pExprInfo); taosArrayDestroy(pOrderVal); } +#endif #pragma GCC diagnostic pop diff --git a/source/libs/executor/test/lhashTests.cpp b/source/libs/executor/test/lhashTests.cpp index 66ef3b0877d67f3967a1b642e03d84c4e979c8d5..695552faa0f353cc631b87cf03f51003c7b66aed 100644 --- a/source/libs/executor/test/lhashTests.cpp +++ b/source/libs/executor/test/lhashTests.cpp @@ -25,7 +25,7 @@ #pragma GCC diagnostic ignored "-Wsign-compare" TEST(testCase, linear_hash_Tests) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); _hash_fn_t fn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT); #if 0 diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h new file mode 100644 index 0000000000000000000000000000000000000000..7ba7d7bdcccffd14e6f224e62ddf08e2dd8475bd --- /dev/null +++ b/source/libs/function/inc/builtinsimpl.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#ifndef TDENGINE_BUILTINSIMPL_H +#define TDENGINE_BUILTINSIMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "function.h" + +bool functionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo); +void functionFinalizer(SqlFunctionCtx *pCtx); + +bool getCountFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv); +void countFunction(SqlFunctionCtx *pCtx); + +bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv); +void sumFunction(SqlFunctionCtx *pCtx); + +bool minFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo); +bool maxFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo); +bool getMinmaxFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv); +void minFunction(SqlFunctionCtx* pCtx); +void maxFunction(SqlFunctionCtx *pCtx); + +#ifdef __cplusplus +} +#endif +#endif // TDENGINE_BUILTINSIMPL_H diff --git a/source/libs/function/inc/taggfunction.h b/source/libs/function/inc/taggfunction.h index 65a100efed0d894ef0f64f32341cb79be217a0cf..d71ff789ba8342ed231a20e1ba8b686d93e959c0 100644 --- a/source/libs/function/inc/taggfunction.h +++ b/source/libs/function/inc/taggfunction.h @@ -83,9 +83,7 @@ static FORCE_INLINE void initResultRowEntry(SResultRowEntryInfo *pResInfo, int32 pResInfo->initialized = true; // the this struct has been initialized flag pResInfo->complete = false; - pResInfo->hasResult = false; pResInfo->numOfRes = 0; - memset(GET_ROWCELL_INTERBUF(pResInfo), 0, bufLen); } diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index d9eeb6eeeb324ea7b9c03d432a5eee7552c43ce7..edb0acf07508c520abddf51e06e1e75ea30264d6 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -14,7 +14,9 @@ */ #include "builtins.h" +#include "builtinsimpl.h" #include "taoserror.h" +#include "tdatablock.h" int32_t stubCheckAndGetResultType(SFunctionNode* pFunc); @@ -23,36 +25,92 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .name = "count", .type = FUNCTION_TYPE_COUNT, .classification = FUNC_MGT_AGG_FUNC, - .checkFunc = stubCheckAndGetResultType, - .getEnvFunc = NULL, - .initFunc = NULL, - .processFunc = NULL, - .finalizeFunc = NULL + .checkFunc = stubCheckAndGetResultType, + .getEnvFunc = getCountFuncEnv, + .initFunc = functionSetup, + .processFunc = countFunction, + .finalizeFunc = functionFinalizer }, { .name = "sum", .type = FUNCTION_TYPE_SUM, .classification = FUNC_MGT_AGG_FUNC, - .checkFunc = stubCheckAndGetResultType, - .getEnvFunc = NULL, - .initFunc = NULL, - .processFunc = NULL, - .finalizeFunc = NULL + .checkFunc = stubCheckAndGetResultType, + .getEnvFunc = getSumFuncEnv, + .initFunc = functionSetup, + .processFunc = sumFunction, + .finalizeFunc = functionFinalizer + }, + { + .name = "min", + .type = FUNCTION_TYPE_MIN, + .classification = FUNC_MGT_AGG_FUNC, + .checkFunc = stubCheckAndGetResultType, + .getEnvFunc = getMinmaxFuncEnv, + .initFunc = minFunctionSetup, + .processFunc = minFunction, + .finalizeFunc = functionFinalizer + }, + { + .name = "max", + .type = FUNCTION_TYPE_MAX, + .classification = FUNC_MGT_AGG_FUNC, + .checkFunc = stubCheckAndGetResultType, + .getEnvFunc = getMinmaxFuncEnv, + .initFunc = maxFunctionSetup, + .processFunc = maxFunction, + .finalizeFunc = functionFinalizer }, { .name = "concat", .type = FUNCTION_TYPE_CONCAT, .classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC, - .checkFunc = stubCheckAndGetResultType, - .getEnvFunc = NULL, - .initFunc = NULL, + .checkFunc = stubCheckAndGetResultType, + .getEnvFunc = NULL, + .initFunc = NULL, .sprocessFunc = NULL, .finalizeFunc = NULL } }; -const int funcMgtBuiltinsNum = (sizeof(funcMgtBuiltins) / sizeof(SBuiltinFuncDefinition)); +const int32_t funcMgtBuiltinsNum = (sizeof(funcMgtBuiltins) / sizeof(SBuiltinFuncDefinition)); int32_t stubCheckAndGetResultType(SFunctionNode* pFunc) { + switch(pFunc->funcType) { + case FUNCTION_TYPE_COUNT: + pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT}; + break; + case FUNCTION_TYPE_SUM: { + SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, 0); + int32_t paraType = pParam->node.resType.type; + + int32_t resType = 0; + if (IS_SIGNED_NUMERIC_TYPE(paraType)) { + resType = TSDB_DATA_TYPE_BIGINT; + } else if (IS_UNSIGNED_NUMERIC_TYPE(paraType)) { + resType = TSDB_DATA_TYPE_UBIGINT; + } else if (IS_FLOAT_TYPE(paraType)) { + resType = TSDB_DATA_TYPE_DOUBLE; + } else { + ASSERT(0); + } + + pFunc->node.resType = (SDataType) { .bytes = tDataTypes[resType].bytes, .type = resType }; + break; + } + case FUNCTION_TYPE_MIN: + case FUNCTION_TYPE_MAX: { + SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, 0); + int32_t paraType = pParam->node.resType.type; + pFunc->node.resType = (SDataType) { .bytes = tDataTypes[paraType].bytes, .type = paraType }; + break; + } + case FUNCTION_TYPE_CONCAT: + // todo + break; + default: + ASSERT(0); // to found the fault ASAP. + } + return TSDB_CODE_SUCCESS; } diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c new file mode 100644 index 0000000000000000000000000000000000000000..aaaee6d56cca8f16204eae16d2b26c352de4957d --- /dev/null +++ b/source/libs/function/src/builtinsimpl.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "builtinsimpl.h" +#include "querynodes.h" +#include "taggfunction.h" +#include "tdatablock.h" + +#define SET_VAL(_info, numOfElem, res) \ + do { \ + if ((numOfElem) <= 0) { \ + break; \ + } \ + (_info)->numOfRes = (res); \ + (_info)->hasResult = DATA_SET_FLAG; \ + } while (0) + +typedef struct SSumRes { + union { + int64_t isum; + uint64_t usum; + double dsum; + }; +} SSumRes; + +bool functionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) { + if (pResultInfo->initialized) { + return false; + } + + if (pCtx->pOutput != NULL) { + memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes); + } + + initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize); + return true; +} + +static void doFinalizer(SResultRowEntryInfo* pResInfo) { cleanupResultRowEntry(pResInfo); } + +void functionFinalizer(SqlFunctionCtx *pCtx) { + SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); + if (pResInfo->hasResult != DATA_SET_FLAG) { +// setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); + } + + doFinalizer(pResInfo); +} + +bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { + pEnv->calcMemSize = sizeof(int64_t); + return true; +} + +/* + * count function does need the finalize, if data is missing, the default value, which is 0, is used + * count function does not use the pCtx->interResBuf to keep the intermediate buffer + */ +void countFunction(SqlFunctionCtx *pCtx) { + int32_t numOfElem = 0; + + /* + * 1. column data missing (schema modified) causes pCtx->hasNull == true. pCtx->isAggSet == true; + * 2. for general non-primary key columns, pCtx->hasNull may be true or false, pCtx->isAggSet == true; + * 3. for primary key column, pCtx->hasNull always be false, pCtx->isAggSet == false; + */ + SInputColumnInfoData* pInput = &pCtx->input; + SColumnInfoData* pInputCol = pInput->pData[0]; + + if (pInput->colDataAggIsSet && pInput->totalRows == pInput->numOfRows) { + numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull; + ASSERT(numOfElem >= 0); + } else { + if (pInputCol->hasNull) { + for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) { + if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) { + continue; + } + numOfElem += 1; + } + } else { + //when counting on the primary time stamp column and no statistics data is presented, use the size value directly. + numOfElem = pInput->numOfRows; + } + } + + SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); + char* buf = GET_ROWCELL_INTERBUF(pResInfo); + *((int64_t *)buf) += numOfElem; + + SET_VAL(pResInfo, numOfElem, 1); +} + +#define LIST_ADD_N(_res, _col, _start, _rows, _t, numOfElem) \ + do { \ + _t *d = (_t *)(_col->pData); \ + for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \ + if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \ + continue; \ + }; \ + (_res) += (d)[i]; \ + (numOfElem)++; \ + } \ + } while (0) + +void sumFunction(SqlFunctionCtx *pCtx) { + int32_t numOfElem = 0; + + // Only the pre-computing information loaded and actual data does not loaded + SInputColumnInfoData* pInput = &pCtx->input; + SColumnDataAgg *pAgg = pInput->pColumnDataAgg[0]; + int32_t type = pInput->pData[0]->info.type; + + SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); + + if (pInput->colDataAggIsSet) { + numOfElem = pInput->numOfRows - pAgg->numOfNull; + ASSERT(numOfElem >= 0); + + if (IS_SIGNED_NUMERIC_TYPE(type)) { + pSumRes->isum += pAgg->sum; + } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { + pSumRes->usum += pAgg->sum; + } else if (IS_FLOAT_TYPE(type)) { + pSumRes->dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum)); + } + } else { // computing based on the true data block + SColumnInfoData* pCol = pInput->pData[0]; + + int32_t start = pInput->startRowIndex; + int32_t numOfRows = pInput->numOfRows; + + if (IS_SIGNED_NUMERIC_TYPE(type)) { + if (type == TSDB_DATA_TYPE_TINYINT) { + LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem); + } else if (type == TSDB_DATA_TYPE_SMALLINT) { + LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem); + } else if (type == TSDB_DATA_TYPE_INT) { + LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem); + } else if (type == TSDB_DATA_TYPE_BIGINT) { + LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem); + } + } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { + if (type == TSDB_DATA_TYPE_UTINYINT) { + LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem); + } else if (type == TSDB_DATA_TYPE_USMALLINT) { + LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem); + } else if (type == TSDB_DATA_TYPE_UINT) { + LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem); + } else if (type == TSDB_DATA_TYPE_UBIGINT) { + LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem); + } + } else if (type == TSDB_DATA_TYPE_DOUBLE) { + LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem); + } else if (type == TSDB_DATA_TYPE_FLOAT) { + LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem); + } + } + + // data in the check operation are all null, not output + SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1); +} + +bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) { + pEnv->calcMemSize = sizeof(SSumRes); + return true; +} + +bool maxFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) { + if (!functionSetup(pCtx, pResultInfo)) { + return false; + } + + char* buf = GET_ROWCELL_INTERBUF(pResultInfo); + switch (pCtx->resDataInfo.type) { + case TSDB_DATA_TYPE_INT: + *((int32_t *)buf) = INT32_MIN; + break; + case TSDB_DATA_TYPE_UINT: + *((uint32_t *)buf) = 0; + break; + case TSDB_DATA_TYPE_FLOAT: + *((float *)buf) = -FLT_MAX; + break; + case TSDB_DATA_TYPE_DOUBLE: + SET_DOUBLE_VAL(((double *)buf), -DBL_MAX); + break; + case TSDB_DATA_TYPE_BIGINT: + *((int64_t *)buf) = INT64_MIN; + break; + case TSDB_DATA_TYPE_UBIGINT: + *((uint64_t *)buf) = 0; + break; + case TSDB_DATA_TYPE_SMALLINT: + *((int16_t *)buf) = INT16_MIN; + break; + case TSDB_DATA_TYPE_USMALLINT: + *((uint16_t *)buf) = 0; + break; + case TSDB_DATA_TYPE_TINYINT: + *((int8_t *)buf) = INT8_MIN; + break; + case TSDB_DATA_TYPE_UTINYINT: + *((uint8_t *)buf) = 0; + break; + default: + assert(0); + } + return true; +} + +bool minFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) { + if (!functionSetup(pCtx, pResultInfo)) { + return false; // not initialized since it has been initialized + } + + char* buf = GET_ROWCELL_INTERBUF(pResultInfo); + switch (pCtx->resDataInfo.type) { + case TSDB_DATA_TYPE_TINYINT: + *((int8_t *)buf) = INT8_MAX; + break; + case TSDB_DATA_TYPE_UTINYINT: + *(uint8_t *) buf = UINT8_MAX; + break; + case TSDB_DATA_TYPE_SMALLINT: + *((int16_t *)buf) = INT16_MAX; + break; + case TSDB_DATA_TYPE_USMALLINT: + *((uint16_t *)buf) = UINT16_MAX; + break; + case TSDB_DATA_TYPE_INT: + *((int32_t *)buf) = INT32_MAX; + break; + case TSDB_DATA_TYPE_UINT: + *((uint32_t *)buf) = UINT32_MAX; + break; + case TSDB_DATA_TYPE_BIGINT: + *((int64_t *)buf) = INT64_MAX; + break; + case TSDB_DATA_TYPE_UBIGINT: + *((uint64_t *)buf) = UINT64_MAX; + break; + case TSDB_DATA_TYPE_FLOAT: + *((float *)buf) = FLT_MAX; + break; + case TSDB_DATA_TYPE_DOUBLE: + SET_DOUBLE_VAL(((double *)buf), DBL_MAX); + break; + default: + assert(0); + } + + return true; +} + +bool getMinmaxFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) { + SNode* pNode = nodesListGetNode(pFunc->pParameterList, 0); + pEnv->calcMemSize = sizeof(int64_t); + return true; +} + +#define GET_TS_LIST(x) ((TSKEY*)((x)->ptsList)) +#define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)]) + +#define DO_UPDATE_TAG_COLUMNS_WITHOUT_TS(ctx) \ + do { \ + for (int32_t _i = 0; _i < (ctx)->tagInfo.numOfTagCols; ++_i) { \ + SqlFunctionCtx *__ctx = (ctx)->tagInfo.pTagCtxList[_i]; \ + __ctx->fpSet.process(__ctx); \ + } \ + } while (0); + +#define DO_UPDATE_SUBSID_RES(ctx, ts) \ + do { \ + for (int32_t _i = 0; _i < (ctx)->subsidiaryRes.numOfCols; ++_i) { \ + SqlFunctionCtx *__ctx = (ctx)->subsidiaryRes.pCtx[_i]; \ + if (__ctx->functionId == FUNCTION_TS_DUMMY) { \ + __ctx->tag.i = (ts); \ + __ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; \ + } \ + __ctx->fpSet.process(__ctx); \ + } \ + } while (0) + +#define UPDATE_DATA(ctx, left, right, num, sign, _ts) \ + do { \ + if (((left) < (right)) ^ (sign)) { \ + (left) = (right); \ + DO_UPDATE_SUBSID_RES(ctx, _ts); \ + (num) += 1; \ + } \ + } while (0) + +#define LOOPCHECK_N(val, _col, ctx, _t, _nrow, _start, sign, num) \ + do { \ + _t* d = (_t*)((_col)->pData); \ + for (int32_t i = (_start); i < (_nrow) + (_start); ++i) { \ + if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \ + continue; \ + } \ + TSKEY ts = (ctx)->ptsList != NULL ? GET_TS_DATA(ctx, i) : 0; \ + UPDATE_DATA(ctx, val, d[i], num, sign, ts); \ + } \ + } while (0) + +int32_t doMinMaxHelper(SqlFunctionCtx *pCtx, int32_t isMinFunc) { + int32_t numOfElems = 0; + + SInputColumnInfoData* pInput = &pCtx->input; + SColumnDataAgg *pAgg = pInput->pColumnDataAgg[0]; + + SColumnInfoData* pCol = pInput->pData[0]; + int32_t type = pCol->info.type; + + SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); + char* buf = GET_ROWCELL_INTERBUF(pResInfo); + + // data in current data block are qualified to the query + if (pInput->colDataAggIsSet) { + numOfElems = pInput->numOfRows - pAgg->numOfNull; + ASSERT(pInput->numOfRows == pInput->totalRows && numOfElems >= 0); + + if (numOfElems == 0) { + return numOfElems; + } + + void* tval = NULL; + int16_t index = 0; + + if (isMinFunc) { + tval = &pInput->pColumnDataAgg[0]->min; + index = pInput->pColumnDataAgg[0]->minIndex; + } else { + tval = &pInput->pColumnDataAgg[0]->max; + index = pInput->pColumnDataAgg[0]->maxIndex; + } + + TSKEY key = TSKEY_INITIAL_VAL; + if (pCtx->ptsList != NULL) { + // the index is the original position, not the relative position + key = pCtx->ptsList[index]; + } + + if (IS_SIGNED_NUMERIC_TYPE(type)) { + int64_t val = GET_INT64_VAL(tval); + +#if defined(_DEBUG_VIEW) + qDebug("max value updated according to pre-cal:%d", *data); +#endif + + if ((*(int64_t*)buf < val) ^ isMinFunc) { + *(int64_t*) buf = val; + for (int32_t i = 0; i < (pCtx)->subsidiaryRes.numOfCols; ++i) { + SqlFunctionCtx* __ctx = pCtx->subsidiaryRes.pCtx[i]; + if (__ctx->functionId == FUNCTION_TS_DUMMY) { // TODO refactor + __ctx->tag.i = key; + __ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; + } + + __ctx->fpSet.process(__ctx); + } + } + } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { + uint64_t val = GET_UINT64_VAL(tval); + UPDATE_DATA(pCtx, *(uint64_t*)buf, val, numOfElems, isMinFunc, key); + } else if (type == TSDB_DATA_TYPE_DOUBLE) { + double val = GET_DOUBLE_VAL(tval); + UPDATE_DATA(pCtx, *(double*)buf, val, numOfElems, isMinFunc, key); + } else if (type == TSDB_DATA_TYPE_FLOAT) { + double val = GET_DOUBLE_VAL(tval); + UPDATE_DATA(pCtx, *(float*)buf, (float)val, numOfElems, isMinFunc, key); + } + + return numOfElems; + } + + int32_t start = pInput->startRowIndex; + int32_t numOfRows = pInput->numOfRows; + + if (IS_SIGNED_NUMERIC_TYPE(type)) { + if (type == TSDB_DATA_TYPE_TINYINT) { + LOOPCHECK_N(*(int8_t*)buf, pCol, pCtx, int8_t, numOfRows, start, isMinFunc, numOfElems); + } else if (type == TSDB_DATA_TYPE_SMALLINT) { + LOOPCHECK_N(*(int16_t*) buf, pCol, pCtx, int16_t, numOfRows, start, isMinFunc, numOfElems); + } else if (type == TSDB_DATA_TYPE_INT) { + int32_t *pData = (int32_t*)pCol->pData; + int32_t *val = (int32_t*) buf; + + for (int32_t i = 0; i < pCtx->size; ++i) { + if ((pCol->hasNull) && colDataIsNull_f(pCol->nullbitmap, i)) { + continue; + } + + if ((*val < pData[i]) ^ isMinFunc) { + *val = pData[i]; + TSKEY ts = (pCtx->ptsList != NULL)? GET_TS_DATA(pCtx, i) : 0; + DO_UPDATE_SUBSID_RES(pCtx, ts); + } + + numOfElems += 1; + } + +#if defined(_DEBUG_VIEW) + qDebug("max value updated:%d", *retVal); +#endif + } else if (type == TSDB_DATA_TYPE_BIGINT) { + LOOPCHECK_N(*(int64_t*) buf, pCol, pCtx, int64_t, numOfRows, start, isMinFunc, numOfElems); + } + } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { + if (type == TSDB_DATA_TYPE_UTINYINT) { + LOOPCHECK_N(*(uint8_t*) buf, pCol, pCtx, uint8_t, numOfRows, start, isMinFunc, numOfElems); + } else if (type == TSDB_DATA_TYPE_USMALLINT) { + LOOPCHECK_N(*(uint16_t*) buf, pCol, pCtx, uint16_t, numOfRows, start, isMinFunc, numOfElems); + } else if (type == TSDB_DATA_TYPE_UINT) { + LOOPCHECK_N(*(uint32_t*) buf, pCol, pCtx, uint32_t, numOfRows, start, isMinFunc, numOfElems); + } else if (type == TSDB_DATA_TYPE_UBIGINT) { + LOOPCHECK_N(*(uint64_t*) buf, pCol, pCtx, uint64_t, numOfRows, start, isMinFunc, numOfElems); + } + } else if (type == TSDB_DATA_TYPE_DOUBLE) { + LOOPCHECK_N(*(double*) buf, pCol, pCtx, double, numOfRows, start, isMinFunc, numOfElems); + } else if (type == TSDB_DATA_TYPE_FLOAT) { + LOOPCHECK_N(*(float*) buf, pCol, pCtx, float, numOfRows, start, isMinFunc, numOfElems); + } + + return numOfElems; +} + +void minFunction(SqlFunctionCtx *pCtx) { + int32_t numOfElems = doMinMaxHelper(pCtx, 1); + SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1); +} + +void maxFunction(SqlFunctionCtx *pCtx) { + int32_t numOfElems = doMinMaxHelper(pCtx, 0); + SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1); +} \ No newline at end of file diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index c6330c6015b346c03e9477efa138f769f3c7ee8d..41b0126a073ef0e22c253406af592d9f1f46621d 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -26,18 +26,27 @@ typedef struct SFuncMgtService { } SFuncMgtService; static SFuncMgtService gFunMgtService; +static pthread_once_t functionHashTableInit = PTHREAD_ONCE_INIT; +static int32_t initFunctionCode = 0; -int32_t fmFuncMgtInit() { +static void doInitFunctionHashTable() { gFunMgtService.pFuncNameHashTable = taosHashInit(funcMgtBuiltinsNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); if (NULL == gFunMgtService.pFuncNameHashTable) { - return TSDB_CODE_FAILED; + initFunctionCode = TSDB_CODE_FAILED; + return; } + for (int32_t i = 0; i < funcMgtBuiltinsNum; ++i) { if (TSDB_CODE_SUCCESS != taosHashPut(gFunMgtService.pFuncNameHashTable, funcMgtBuiltins[i].name, strlen(funcMgtBuiltins[i].name), &i, sizeof(int32_t))) { - return TSDB_CODE_FAILED; + initFunctionCode = TSDB_CODE_FAILED; + return; } } - return TSDB_CODE_SUCCESS; +} + +int32_t fmFuncMgtInit() { + pthread_once(&functionHashTableInit, doInitFunctionHashTable); + return initFunctionCode; } int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType) { @@ -85,3 +94,10 @@ bool fmIsAggFunc(int32_t funcId) { } return FUNC_MGT_TEST_MASK(funcMgtBuiltins[funcId].classification, FUNC_MGT_AGG_FUNC); } + +void fmFuncMgtDestroy() { + void* m = gFunMgtService.pFuncNameHashTable; + if (m != NULL && atomic_val_compare_exchange_ptr(&gFunMgtService.pFuncNameHashTable, m, 0) == m) { + taosHashCleanup(m); + } +} diff --git a/source/libs/function/src/taggfunction.c b/source/libs/function/src/taggfunction.c index 7fb63f591089fb19c693bae5eb205c72f3f5aace..4360515328d286304688a9949040f3e2df86335b 100644 --- a/source/libs/function/src/taggfunction.c +++ b/source/libs/function/src/taggfunction.c @@ -16,10 +16,10 @@ #include "os.h" #include "taosdef.h" #include "tmsg.h" -#include "tglobal.h" #include "thash.h" #include "ttypes.h" +#include "function.h" #include "taggfunction.h" #include "tfill.h" #include "thistogram.h" @@ -200,27 +200,47 @@ void cleanupResultRowEntry(struct SResultRowEntryInfo* pCell) { pCell->initialized = false; } -int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num) { - int32_t maxOutput = 0; +int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num, SSDataBlock* pResBlock) { + int32_t maxRows = 0; + for (int32_t j = 0; j < num; ++j) { +#if 0 int32_t id = pCtx[j].functionId; /* * ts, tag, tagprj function can not decide the output number of current query * the number of output result is decided by main output */ - if (/*hasMainFunction && */(id == FUNCTION_TS || id == FUNCTION_TAG || id == FUNCTION_TAGPRJ)) { + if (id == FUNCTION_TS || id == FUNCTION_TAG || id == FUNCTION_TAGPRJ) { continue; } - +#endif SResultRowEntryInfo *pResInfo = GET_RES_INFO(&pCtx[j]); - if (pResInfo != NULL && maxOutput < pResInfo->numOfRes) { - maxOutput = pResInfo->numOfRes; + if (pResInfo != NULL && maxRows < pResInfo->numOfRes) { + maxRows = pResInfo->numOfRes; } } - assert(maxOutput >= 0); - return maxOutput; + assert(maxRows >= 0); + + blockDataEnsureCapacity(pResBlock, maxRows); + for(int32_t i = 0; i < num; ++i) { + SColumnInfoData* pCol = taosArrayGet(pResBlock->pDataBlock, i); + + SResultRowEntryInfo *pResInfo = GET_RES_INFO(&pCtx[i]); + if (!pResInfo->hasResult) { + for(int32_t j = 0; j < pResInfo->numOfRes; ++j) { + colDataAppend(pCol, j, NULL, true); // TODO add set null data api + } + } else { + for (int32_t j = 0; j < pResInfo->numOfRes; ++j) { + colDataAppend(pCol, j, GET_ROWCELL_INTERBUF(pResInfo), false); + } + } + } + + pResBlock->info.rows = maxRows; + return maxRows; } void resetResultRowEntryResult(SqlFunctionCtx* pCtx, int32_t num) { @@ -254,9 +274,9 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI pInfo->bytes = (int16_t)dataBytes; if (functionId == FUNCTION_INTERP) { - pInfo->intermediateBytes = sizeof(SInterpInfoDetail); + pInfo->interBufSize = sizeof(SInterpInfoDetail); } else { - pInfo->intermediateBytes = 0; + pInfo->interBufSize = 0; } return TSDB_CODE_SUCCESS; @@ -266,42 +286,42 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI if (functionId == FUNCTION_TID_TAG) { // todo use struct pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = (int16_t)(dataBytes + sizeof(int16_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE); - pInfo->intermediateBytes = 0; + pInfo->interBufSize = 0; return TSDB_CODE_SUCCESS; } if (functionId == FUNCTION_BLKINFO) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = 16384; - pInfo->intermediateBytes = 0; + pInfo->interBufSize = 0; return TSDB_CODE_SUCCESS; } if (functionId == FUNCTION_COUNT) { pInfo->type = TSDB_DATA_TYPE_BIGINT; pInfo->bytes = sizeof(int64_t); - pInfo->intermediateBytes = 0; + pInfo->interBufSize = 0; return TSDB_CODE_SUCCESS; } if (functionId == FUNCTION_ARITHM) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = 0; + pInfo->interBufSize = 0; return TSDB_CODE_SUCCESS; } if (functionId == FUNCTION_TS_COMP) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = 1; // this results is compressed ts data, only one byte - pInfo->intermediateBytes = POINTER_BYTES; + pInfo->interBufSize = POINTER_BYTES; return TSDB_CODE_SUCCESS; } if (functionId == FUNCTION_DERIVATIVE) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); // this results is compressed ts data, only one byte - pInfo->intermediateBytes = sizeof(SDerivInfo); + pInfo->interBufSize = sizeof(SDerivInfo); return TSDB_CODE_SUCCESS; } @@ -310,11 +330,11 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI // if (pUdfInfo->bufSize > 0) { // pInfo->type = TSDB_DATA_TYPE_BINARY; // pInfo->bytes = pUdfInfo->bufSize; -// pInfo->intermediateBytes = pInfo->bytes; +// pInfo->interBufSize = pInfo->bytes; // } else { // pInfo->type = pUdfInfo->resType; // pInfo->bytes = pUdfInfo->resBytes; -// pInfo->intermediateBytes = pInfo->bytes; +// pInfo->interBufSize = pInfo->bytes; // } // // return TSDB_CODE_SUCCESS; @@ -323,54 +343,54 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI if (functionId == FUNCTION_MIN || functionId == FUNCTION_MAX) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = (int16_t)(dataBytes + DATA_SET_FLAG_SIZE); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_SUM) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = sizeof(SSumInfo); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_AVG) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = sizeof(SAvgInfo); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId >= FUNCTION_RATE && functionId <= FUNCTION_IRATE) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(SRateInfo); - pInfo->intermediateBytes = sizeof(SRateInfo); + pInfo->interBufSize = sizeof(SRateInfo); return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = (int16_t)(sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_SPREAD) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = sizeof(SSpreadInfo); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_APERCT) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1) + sizeof(SHistogramInfo) + sizeof(SAPercentileInfo); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_LAST_ROW) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = (int16_t)(sizeof(SLastrowInfo) + dataBytes); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_TWA) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(STwaInfo); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; return TSDB_CODE_SUCCESS; } } @@ -385,18 +405,18 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI } pInfo->bytes = sizeof(int64_t); - pInfo->intermediateBytes = sizeof(SSumInfo); + pInfo->interBufSize = sizeof(SSumInfo); return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_APERCT) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = + pInfo->interBufSize = sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1); return TSDB_CODE_SUCCESS; } else if (functionId == FUNCTION_TWA) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = sizeof(STwaInfo); + pInfo->interBufSize = sizeof(STwaInfo); return TSDB_CODE_SUCCESS; } @@ -405,9 +425,9 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI // pInfo->bytes = pUdfInfo->resBytes; // // if (pUdfInfo->bufSize > 0) { -// pInfo->intermediateBytes = pUdfInfo->bufSize; +// pInfo->interBufSize = pUdfInfo->bufSize; // } else { -// pInfo->intermediateBytes = pInfo->bytes; +// pInfo->interBufSize = pInfo->bytes; // } // // return TSDB_CODE_SUCCESS; @@ -416,39 +436,39 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI if (functionId == FUNCTION_AVG) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = sizeof(SAvgInfo); + pInfo->interBufSize = sizeof(SAvgInfo); } else if (functionId >= FUNCTION_RATE && functionId <= FUNCTION_IRATE) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = sizeof(SRateInfo); + pInfo->interBufSize = sizeof(SRateInfo); } else if (functionId == FUNCTION_STDDEV) { pInfo->type = TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = sizeof(SStddevInfo); + pInfo->interBufSize = sizeof(SStddevInfo); } else if (functionId == FUNCTION_MIN || functionId == FUNCTION_MAX) { pInfo->type = (int16_t)dataType; pInfo->bytes = (int16_t)dataBytes; - pInfo->intermediateBytes = dataBytes + DATA_SET_FLAG_SIZE; + pInfo->interBufSize = dataBytes + DATA_SET_FLAG_SIZE; } else if (functionId == FUNCTION_FIRST || functionId == FUNCTION_LAST) { pInfo->type = (int16_t)dataType; pInfo->bytes = (int16_t)dataBytes; - pInfo->intermediateBytes = (int16_t)(dataBytes + sizeof(SFirstLastInfo)); + pInfo->interBufSize = (int16_t)(dataBytes + sizeof(SFirstLastInfo)); } else if (functionId == FUNCTION_SPREAD) { pInfo->type = (int16_t)TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = sizeof(double); - pInfo->intermediateBytes = sizeof(SSpreadInfo); + pInfo->interBufSize = sizeof(SSpreadInfo); } else if (functionId == FUNCTION_PERCT) { pInfo->type = (int16_t)TSDB_DATA_TYPE_DOUBLE; pInfo->bytes = (int16_t)sizeof(double); - pInfo->intermediateBytes = (int16_t)sizeof(SPercentileInfo); + pInfo->interBufSize = (int16_t)sizeof(SPercentileInfo); } else if (functionId == FUNCTION_LEASTSQR) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = TMAX(AVG_FUNCTION_INTER_BUFFER_SIZE, sizeof(SLeastsquaresInfo)); // string - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; } else if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_LAST_DST) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = (int16_t)(dataBytes + sizeof(SFirstLastInfo)); - pInfo->intermediateBytes = pInfo->bytes; + pInfo->interBufSize = pInfo->bytes; } else if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM) { pInfo->type = (int16_t)dataType; pInfo->bytes = (int16_t)dataBytes; @@ -456,15 +476,15 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI size_t size = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; // the output column may be larger than sizeof(STopBotInfo) - pInfo->intermediateBytes = (int32_t)size; + pInfo->interBufSize = (int32_t)size; } else if (functionId == FUNCTION_LAST_ROW) { pInfo->type = (int16_t)dataType; pInfo->bytes = (int16_t)dataBytes; - pInfo->intermediateBytes = dataBytes; + pInfo->interBufSize = dataBytes; } else if (functionId == FUNCTION_STDDEV_DST) { pInfo->type = TSDB_DATA_TYPE_BINARY; pInfo->bytes = sizeof(SStddevdstInfo); - pInfo->intermediateBytes = (pInfo->bytes); + pInfo->interBufSize = (pInfo->bytes); } else { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -479,7 +499,7 @@ static bool function_setup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInf } memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes); - initResultRowEntry(pResultInfo, pCtx->resDataInfo.intermediateBytes); + initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize); return true; } @@ -492,9 +512,9 @@ static bool function_setup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInf */ static void function_finalizer(SqlFunctionCtx *pCtx) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - if (pResInfo->hasResult != DATA_SET_FLAG) { - setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); - } +// if (pResInfo->hasResult != DATA_SET_FLAG) { // TODO set the correct null value +// setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); +// } doFinalizer(pCtx); } @@ -530,7 +550,7 @@ static void count_function(SqlFunctionCtx *pCtx) { } if (numOfElem > 0) { - GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; +// GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } *((int64_t *)pCtx->pOutput) += numOfElem; @@ -694,7 +714,7 @@ static void do_sum(SqlFunctionCtx *pCtx) { SET_VAL(pCtx, notNullElems, 1); if (notNullElems > 0) { - GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; +// GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } } @@ -703,11 +723,11 @@ static void sum_function(SqlFunctionCtx *pCtx) { // keep the result data in output buffer, not in the intermediate buffer SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) { +// if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) { // set the flag for super table query SSumInfo *pSum = (SSumInfo *)pCtx->pOutput; pSum->hasResult = DATA_SET_FLAG; - } +// } } static void sum_func_merge(SqlFunctionCtx *pCtx) { @@ -738,7 +758,7 @@ static void sum_func_merge(SqlFunctionCtx *pCtx) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); if (notNullElems > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -876,7 +896,7 @@ static void avg_function(SqlFunctionCtx *pCtx) { pAvgInfo->num += notNullElems; if (notNullElems > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } // keep the data into the final output buffer for super table query since this execution may be the last one @@ -938,157 +958,6 @@ static void avg_finalizer(SqlFunctionCtx *pCtx) { ///////////////////////////////////////////////////////////////////////////////////////////// -static void minMax_function(SqlFunctionCtx *pCtx, char *pOutput, int32_t isMin, int32_t *notNullElems) { - // data in current data block are qualified to the query - if (pCtx->isAggSet) { - *notNullElems = pCtx->size - pCtx->agg.numOfNull; - assert(*notNullElems >= 0); - - if (*notNullElems == 0) { - return; - } - - void* tval = NULL; - int16_t index = 0; - - if (isMin) { - tval = &pCtx->agg.min; - index = pCtx->agg.minIndex; - } else { - tval = &pCtx->agg.max; - index = pCtx->agg.maxIndex; - } - - TSKEY key = TSKEY_INITIAL_VAL; - if (pCtx->ptsList != NULL) { - /** - * NOTE: work around the bug caused by invalid pre-calculated function. - * Here the selectivity + ts will not return correct value. - * - * The following codes of 3 lines will be removed later. - */ -// if (index < 0 || index >= pCtx->size + pCtx->startOffset) { -// index = 0; -// } - - // the index is the original position, not the relative position - key = pCtx->ptsList[index]; - } - - if (IS_SIGNED_NUMERIC_TYPE(pCtx->inputType)) { - int64_t val = GET_INT64_VAL(tval); - if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { - int8_t *data = (int8_t *)pOutput; - - UPDATE_DATA(pCtx, *data, (int8_t)val, notNullElems, isMin, key); - } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { - int16_t *data = (int16_t *)pOutput; - - UPDATE_DATA(pCtx, *data, (int16_t)val, notNullElems, isMin, key); - } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { - int32_t *data = (int32_t *)pOutput; -#if defined(_DEBUG_VIEW) - qDebug("max value updated according to pre-cal:%d", *data); -#endif - - if ((*data < val) ^ isMin) { - *data = (int32_t)val; - for (int32_t i = 0; i < (pCtx)->tagInfo.numOfTagCols; ++i) { - SqlFunctionCtx *__ctx = pCtx->tagInfo.pTagCtxList[i]; - if (__ctx->functionId == FUNCTION_TS_DUMMY) { - __ctx->tag.i = key; - __ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; - } - - aggFunc[FUNCTION_TAG].addInput(__ctx); - } - } - } else if (pCtx->inputType == TSDB_DATA_TYPE_BIGINT) { - int64_t *data = (int64_t *)pOutput; - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); - } - } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inputType)) { - uint64_t val = GET_UINT64_VAL(tval); - if (pCtx->inputType == TSDB_DATA_TYPE_UTINYINT) { - uint8_t *data = (uint8_t *)pOutput; - - UPDATE_DATA(pCtx, *data, (uint8_t)val, notNullElems, isMin, key); - } else if (pCtx->inputType == TSDB_DATA_TYPE_USMALLINT) { - uint16_t *data = (uint16_t *)pOutput; - UPDATE_DATA(pCtx, *data, (uint16_t)val, notNullElems, isMin, key); - } else if (pCtx->inputType == TSDB_DATA_TYPE_UINT) { - uint32_t *data = (uint32_t *)pOutput; - UPDATE_DATA(pCtx, *data, (uint32_t)val, notNullElems, isMin, key); - } else if (pCtx->inputType == TSDB_DATA_TYPE_UBIGINT) { - uint64_t *data = (uint64_t *)pOutput; - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); - } - } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE) { - double *data = (double *)pOutput; - double val = GET_DOUBLE_VAL(tval); - - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); - } else if (pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { - float *data = (float *)pOutput; - double val = GET_DOUBLE_VAL(tval); - - UPDATE_DATA(pCtx, *data, (float)val, notNullElems, isMin, key); - } - - return; - } - - void *p = GET_INPUT_DATA_LIST(pCtx); - TSKEY *tsList = GET_TS_LIST(pCtx); - - *notNullElems = 0; - - if (IS_SIGNED_NUMERIC_TYPE(pCtx->inputType)) { - if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { - TYPED_LOOPCHECK_N(int8_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { - TYPED_LOOPCHECK_N(int16_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { - int32_t *pData = p; - int32_t *retVal = (int32_t*) pOutput; - - for (int32_t i = 0; i < pCtx->size; ++i) { - if (pCtx->hasNull && isNull((const char*)&pData[i], pCtx->inputType)) { - continue; - } - - if ((*retVal < pData[i]) ^ isMin) { - *retVal = pData[i]; - TSKEY k = tsList[i]; - - DO_UPDATE_TAG_COLUMNS(pCtx, k); - } - - *notNullElems += 1; - } -#if defined(_DEBUG_VIEW) - qDebug("max value updated:%d", *retVal); -#endif - } else if (pCtx->inputType == TSDB_DATA_TYPE_BIGINT) { - TYPED_LOOPCHECK_N(int64_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } - } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inputType)) { - if (pCtx->inputType == TSDB_DATA_TYPE_UTINYINT) { - TYPED_LOOPCHECK_N(uint8_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } else if (pCtx->inputType == TSDB_DATA_TYPE_USMALLINT) { - TYPED_LOOPCHECK_N(uint16_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } else if (pCtx->inputType == TSDB_DATA_TYPE_UINT) { - TYPED_LOOPCHECK_N(uint32_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } else if (pCtx->inputType == TSDB_DATA_TYPE_UBIGINT) { - TYPED_LOOPCHECK_N(uint64_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } - } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE) { - TYPED_LOOPCHECK_N(double, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } else if (pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { - TYPED_LOOPCHECK_N(float, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); - } -} - static bool min_func_setup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) { if (!function_setup(pCtx, pResultInfo)) { return false; // not initialized since it has been initialized @@ -1184,43 +1053,9 @@ static bool max_func_setup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInf /* * the output result of min/max function is the final output buffer, not the intermediate result buffer */ -static void min_function(SqlFunctionCtx *pCtx) { - int32_t notNullElems = 0; - minMax_function(pCtx, pCtx->pOutput, 1, ¬NullElems); - - SET_VAL(pCtx, notNullElems, 1); - - if (notNullElems > 0) { - SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; - - // set the flag for super table query - if (pCtx->stableQuery) { - *(pCtx->pOutput + pCtx->inputBytes) = DATA_SET_FLAG; - } - } -} - -static void max_function(SqlFunctionCtx *pCtx) { - int32_t notNullElems = 0; - minMax_function(pCtx, pCtx->pOutput, 0, ¬NullElems); - - SET_VAL(pCtx, notNullElems, 1); - - if (notNullElems > 0) { - SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; - - // set the flag for super table query - if (pCtx->stableQuery) { - *(pCtx->pOutput + pCtx->inputBytes) = DATA_SET_FLAG; - } - } -} - static int32_t minmax_merge_impl(SqlFunctionCtx *pCtx, int32_t bytes, char *output, bool isMin) { int32_t notNullElems = 0; - +#if 0 GET_TRUE_DATA_TYPE(); assert(pCtx->stableQuery); @@ -1299,7 +1134,8 @@ static int32_t minmax_merge_impl(SqlFunctionCtx *pCtx, int32_t bytes, char *outp break; } } - +#endif + return notNullElems; } @@ -1310,7 +1146,7 @@ static void min_func_merge(SqlFunctionCtx *pCtx) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); if (notNullElems > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -1321,7 +1157,7 @@ static void max_func_merge(SqlFunctionCtx *pCtx) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); if (numOfElem > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -1598,11 +1434,11 @@ static void first_function(SqlFunctionCtx *pCtx) { memcpy(pCtx->pOutput, data, pCtx->inputBytes); if (pCtx->ptsList != NULL) { TSKEY k = GET_TS_DATA(pCtx, i); - DO_UPDATE_TAG_COLUMNS(pCtx, k); +// DO_UPDATE_TAG_COLUMNS(pCtx, k); } SResultRowEntryInfo *pInfo = GET_RES_INFO(pCtx); - pInfo->hasResult = DATA_SET_FLAG; +// pInfo->hasResult = DATA_SET_FLAG; pInfo->complete = true; notNullElems++; @@ -1622,7 +1458,7 @@ static void first_data_assign_impl(SqlFunctionCtx *pCtx, char *pData, int32_t in pInfo->hasResult = DATA_SET_FLAG; pInfo->ts = timestamp[index]; - DO_UPDATE_TAG_COLUMNS(pCtx, pInfo->ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, pInfo->ts); } } @@ -1652,7 +1488,7 @@ static void first_dist_function(SqlFunctionCtx *pCtx) { first_data_assign_impl(pCtx, data, i); SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; notNullElems++; break; @@ -1676,11 +1512,11 @@ static void first_dist_func_merge(SqlFunctionCtx *pCtx) { pCtx->param[1].i = pInput->ts; pCtx->param[1].nType = pCtx->resDataInfo.type; - DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); } SET_VAL(pCtx, 1, 1); - GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; +// GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1710,9 +1546,9 @@ static void last_function(SqlFunctionCtx *pCtx) { memcpy(pCtx->pOutput, data, pCtx->inputBytes); TSKEY ts = pCtx->ptsList ? GET_TS_DATA(pCtx, i) : 0; - DO_UPDATE_TAG_COLUMNS(pCtx, ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, ts); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; pResInfo->complete = true; // set query completed on this column notNullElems++; break; @@ -1727,13 +1563,13 @@ static void last_function(SqlFunctionCtx *pCtx) { TSKEY ts = pCtx->ptsList ? GET_TS_DATA(pCtx, i) : 0; char* buf = GET_ROWCELL_INTERBUF(pResInfo); - if (pResInfo->hasResult != DATA_SET_FLAG || (*(TSKEY*)buf) < ts) { - pResInfo->hasResult = DATA_SET_FLAG; - memcpy(pCtx->pOutput, data, pCtx->inputBytes); - - *(TSKEY*)buf = ts; - DO_UPDATE_TAG_COLUMNS(pCtx, ts); - } +// if (pResInfo->hasResult != DATA_SET_FLAG || (*(TSKEY*)buf) < ts) { +// //pResInfo->hasResult = DATA_SET_FLAG; +// memcpy(pCtx->pOutput, data, pCtx->inputBytes); +// +// *(TSKEY*)buf = ts; +// DO_UPDATE_TAG_COLUMNS(pCtx, ts); +// } notNullElems++; break; @@ -1757,7 +1593,7 @@ static void last_data_assign_impl(SqlFunctionCtx *pCtx, char *pData, int32_t ind pInfo->hasResult = DATA_SET_FLAG; pInfo->ts = timestamp[index]; - DO_UPDATE_TAG_COLUMNS(pCtx, pInfo->ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, pInfo->ts); } } @@ -1782,7 +1618,7 @@ static void last_dist_function(SqlFunctionCtx *pCtx) { last_data_assign_impl(pCtx, data, i); SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; notNullElems++; break; @@ -1813,11 +1649,11 @@ static void last_dist_func_merge(SqlFunctionCtx *pCtx) { pCtx->param[1].i = pInput->ts; pCtx->param[1].nType = pCtx->resDataInfo.type; - DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); } SET_VAL(pCtx, 1, 1); - GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; +// GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } ////////////////////////////////////////////////////////////////////////////////// @@ -1832,7 +1668,7 @@ static void last_row_function(SqlFunctionCtx *pCtx) { assignVal(pCtx->pOutput, pData + (pCtx->size - 1) * pCtx->inputBytes, pCtx->inputBytes, pCtx->inputType); SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; // set the result to final result buffer in case of super table query if (pCtx->stableQuery) { @@ -1840,10 +1676,10 @@ static void last_row_function(SqlFunctionCtx *pCtx) { pInfo1->ts = GET_TS_DATA(pCtx, pCtx->size - 1); pInfo1->hasResult = DATA_SET_FLAG; - DO_UPDATE_TAG_COLUMNS(pCtx, pInfo1->ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, pInfo1->ts); } else { TSKEY ts = GET_TS_DATA(pCtx, pCtx->size - 1); - DO_UPDATE_TAG_COLUMNS(pCtx, ts); +// DO_UPDATE_TAG_COLUMNS(pCtx, ts); } SET_VAL(pCtx, pCtx->size, 1); @@ -1852,10 +1688,10 @@ static void last_row_function(SqlFunctionCtx *pCtx) { static void last_row_finalizer(SqlFunctionCtx *pCtx) { // do nothing at the first stage SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - if (pResInfo->hasResult != DATA_SET_FLAG) { - setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); - return; - } +// if (pResInfo->hasResult != DATA_SET_FLAG) { +// setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); +// return; +// } GET_RES_INFO(pCtx)->numOfRes = 1; doFinalizer(pCtx); @@ -1863,25 +1699,25 @@ static void last_row_finalizer(SqlFunctionCtx *pCtx) { ////////////////////////////////////////////////////////////////////////////////// static void valuePairAssign(tValuePair *dst, int16_t type, const char *val, int64_t tsKey, char *pTags, - SExtTagsInfo *pTagInfo, int16_t stage) { + SSubsidiaryResInfo *pTagInfo, int16_t stage) { dst->v.nType = type; dst->v.i = *(int64_t *)val; dst->timestamp = tsKey; int32_t size = 0; if (stage == MERGE_STAGE) { - memcpy(dst->pTags, pTags, (size_t)pTagInfo->tagsLen); +// memcpy(dst->pTags, pTags, (size_t)pTagInfo->tagsLen); } else { // the tags are dumped from the ctx tag fields - for (int32_t i = 0; i < pTagInfo->numOfTagCols; ++i) { - SqlFunctionCtx* ctx = pTagInfo->pTagCtxList[i]; - if (ctx->functionId == FUNCTION_TS_DUMMY) { - ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; - ctx->tag.i = tsKey; - } - - taosVariantDump(&ctx->tag, dst->pTags + size, ctx->tag.nType, true); - size += pTagInfo->pTagCtxList[i]->resDataInfo.bytes; - } +// for (int32_t i = 0; i < pTagInfo->numOfTagCols; ++i) { +// SqlFunctionCtx* ctx = pTagInfo->pTagCtxList[i]; +// if (ctx->functionId == FUNCTION_TS_DUMMY) { +// ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; +// ctx->tag.i = tsKey; +// } +// +// taosVariantDump(&ctx->tag, dst->pTags + size, ctx->tag.nType, true); +// size += pTagInfo->pTagCtxList[i]->resDataInfo.bytes; +// } } } @@ -1936,7 +1772,7 @@ static void topBotSwapFn(void *dst, void *src, const void *param) } static void do_top_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pData, int64_t ts, uint16_t type, - SExtTagsInfo *pTagInfo, char *pTags, int16_t stage) { + SSubsidiaryResInfo *pTagInfo, char *pTags, int16_t stage) { SVariant val = {0}; taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type); @@ -1946,7 +1782,7 @@ static void do_top_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pData, if (pInfo->num < maxLen) { valuePairAssign(pList[pInfo->num], type, (const char *)&val.i, ts, pTags, pTagInfo, stage); - taosheapsort((void *) pList, sizeof(tValuePair **), pInfo->num + 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 0); +// taosheapsort((void *) pList, sizeof(tValuePair **), pInfo->num + 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 0); pInfo->num++; } else { @@ -1954,13 +1790,13 @@ static void do_top_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pData, (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pList[0]->v.u) || (IS_FLOAT_TYPE(type) && val.d > pList[0]->v.d)) { valuePairAssign(pList[0], type, (const char *)&val.i, ts, pTags, pTagInfo, stage); - taosheapadjust((void *) pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 0); +// taosheapadjust((void *) pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 0); } } } static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pData, int64_t ts, uint16_t type, - SExtTagsInfo *pTagInfo, char *pTags, int16_t stage) { + SSubsidiaryResInfo *pTagInfo, char *pTags, int16_t stage) { SVariant val = {0}; taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type); @@ -1970,7 +1806,7 @@ static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pDa if (pInfo->num < maxLen) { valuePairAssign(pList[pInfo->num], type, (const char *)&val.i, ts, pTags, pTagInfo, stage); - taosheapsort((void *) pList, sizeof(tValuePair **), pInfo->num + 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 1); +// taosheapsort((void *) pList, sizeof(tValuePair **), pInfo->num + 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 1); pInfo->num++; } else { @@ -1978,7 +1814,7 @@ static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pDa (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pList[0]->v.u) || (IS_FLOAT_TYPE(type) && val.d < pList[0]->v.d)) { valuePairAssign(pList[0], type, (const char *)&val.i, ts, pTags, pTagInfo, stage); - taosheapadjust((void *) pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 1); +// taosheapadjust((void *) pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 1); } } } @@ -2093,21 +1929,21 @@ static void copyTopBotRes(SqlFunctionCtx *pCtx, int32_t type) { // set the corresponding tag data for each record // todo check malloc failure - char **pData = calloc(pCtx->tagInfo.numOfTagCols, POINTER_BYTES); - for (int32_t i = 0; i < pCtx->tagInfo.numOfTagCols; ++i) { - pData[i] = pCtx->tagInfo.pTagCtxList[i]->pOutput; - } +// char **pData = calloc(pCtx->tagInfo.numOfTagCols, POINTER_BYTES); +// for (int32_t i = 0; i < pCtx->tagInfo.numOfTagCols; ++i) { +// pData[i] = pCtx->tagInfo.pTagCtxList[i]->pOutput; +// } - for (int32_t i = 0; i < len; ++i, output += step) { - int16_t offset = 0; - for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) { - memcpy(pData[j], tvp[i]->pTags + offset, (size_t)pCtx->tagInfo.pTagCtxList[j]->resDataInfo.bytes); - offset += pCtx->tagInfo.pTagCtxList[j]->resDataInfo.bytes; - pData[j] += pCtx->tagInfo.pTagCtxList[j]->resDataInfo.bytes; - } - } +// for (int32_t i = 0; i < len; ++i, output += step) { +// int16_t offset = 0; +// for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) { +// memcpy(pData[j], tvp[i]->pTags + offset, (size_t)pCtx->tagInfo.pTagCtxList[j]->resDataInfo.bytes); +// offset += pCtx->tagInfo.pTagCtxList[j]->resDataInfo.bytes; +// pData[j] += pCtx->tagInfo.pTagCtxList[j]->resDataInfo.bytes; +// } +// } - tfree(pData); +// tfree(pData); } /* @@ -2141,13 +1977,13 @@ static void buildTopBotStruct(STopBotInfo *pTopBotInfo, SqlFunctionCtx *pCtx) { pTopBotInfo->res = (tValuePair**) tmp; tmp += POINTER_BYTES * pCtx->param[0].i; - size_t size = sizeof(tValuePair) + pCtx->tagInfo.tagsLen; +// size_t size = sizeof(tValuePair) + pCtx->tagInfo.tagsLen; - for (int32_t i = 0; i < pCtx->param[0].i; ++i) { - pTopBotInfo->res[i] = (tValuePair*) tmp; - pTopBotInfo->res[i]->pTags = tmp + sizeof(tValuePair); - tmp += size; - } +// for (int32_t i = 0; i < pCtx->param[0].i; ++i) { +// pTopBotInfo->res[i] = (tValuePair*) tmp; +// pTopBotInfo->res[i]->pTags = tmp + sizeof(tValuePair); +// tmp += size; +// } } bool topbot_datablock_filter(SqlFunctionCtx *pCtx, const char *minval, const char *maxval) { @@ -2236,7 +2072,7 @@ static void top_function(SqlFunctionCtx *pCtx) { // NOTE: Set the default timestamp if it is missing [todo refactor] TSKEY ts = (pCtx->ptsList != NULL)? GET_TS_DATA(pCtx, i):0; - do_top_function_add(pRes, (int32_t)pCtx->param[0].i, data, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); +// do_top_function_add(pRes, (int32_t)pCtx->param[0].i, data, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); } if (!pCtx->hasNull) { @@ -2248,7 +2084,7 @@ static void top_function(SqlFunctionCtx *pCtx) { if (notNullElems > 0) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -2263,15 +2099,15 @@ static void top_func_merge(SqlFunctionCtx *pCtx) { // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { int16_t type = (pCtx->resDataInfo.type == TSDB_DATA_TYPE_FLOAT)? TSDB_DATA_TYPE_DOUBLE:pCtx->resDataInfo.type; - do_top_function_add(pOutput, (int32_t)pCtx->param[0].i, &pInput->res[i]->v.i, pInput->res[i]->timestamp, - type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); +// do_top_function_add(pOutput, (int32_t)pCtx->param[0].i, &pInput->res[i]->v.i, pInput->res[i]->timestamp, +// type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } SET_VAL(pCtx, pInput->num, pOutput->num); if (pOutput->num > 0) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -2293,7 +2129,7 @@ static void bottom_function(SqlFunctionCtx *pCtx) { notNullElems++; // NOTE: Set the default timestamp if it is missing [todo refactor] TSKEY ts = (pCtx->ptsList != NULL)? GET_TS_DATA(pCtx, i):0; - do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i, data, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); +// do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i, data, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); } if (!pCtx->hasNull) { @@ -2305,7 +2141,7 @@ static void bottom_function(SqlFunctionCtx *pCtx) { if (notNullElems > 0) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -2320,15 +2156,15 @@ static void bottom_func_merge(SqlFunctionCtx *pCtx) { // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { int16_t type = (pCtx->resDataInfo.type == TSDB_DATA_TYPE_FLOAT) ? TSDB_DATA_TYPE_DOUBLE : pCtx->resDataInfo.type; - do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i, &pInput->res[i]->v.i, pInput->res[i]->timestamp, type, - &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); +// do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i, &pInput->res[i]->v.i, pInput->res[i]->timestamp, type, +// &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } SET_VAL(pCtx, pInput->num, pOutput->num); if (pOutput->num > 0) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -2338,7 +2174,7 @@ static void top_bottom_func_finalizer(SqlFunctionCtx *pCtx) { // data in temporary list is less than the required number of results, not enough qualified number of results STopBotInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo); if (pRes->num == 0) { // no result - assert(pResInfo->hasResult != DATA_SET_FLAG); +// assert(pResInfo->hasResult != DATA_SET_FLAG); // TODO: } @@ -2457,7 +2293,7 @@ static void percentile_function(SqlFunctionCtx *pCtx) { } SET_VAL(pCtx, notNullElems, 1); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } static void percentile_finalizer(SqlFunctionCtx *pCtx) { @@ -2538,7 +2374,7 @@ static void apercentile_function(SqlFunctionCtx *pCtx) { SET_VAL(pCtx, notNullElems, 1); if (notNullElems > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } } @@ -2568,7 +2404,7 @@ static void apercentile_func_merge(SqlFunctionCtx *pCtx) { } SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; SET_VAL(pCtx, 1, 1); } @@ -2579,18 +2415,18 @@ static void apercentile_finalizer(SqlFunctionCtx *pCtx) { SAPercentileInfo *pOutput = GET_ROWCELL_INTERBUF(pResInfo); if (pCtx->currentStage == MERGE_STAGE) { - if (pResInfo->hasResult == DATA_SET_FLAG) { // check for null - assert(pOutput->pHisto->numOfElems > 0); - - double ratio[] = {v}; - double *res = tHistogramUniform(pOutput->pHisto, ratio, 1); - - memcpy(pCtx->pOutput, res, sizeof(double)); - free(res); - } else { - setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); - return; - } +// if (pResInfo->hasResult == DATA_SET_FLAG) { // check for null +// assert(pOutput->pHisto->numOfElems > 0); +// +// double ratio[] = {v}; +// double *res = tHistogramUniform(pOutput->pHisto, ratio, 1); +// +// memcpy(pCtx->pOutput, res, sizeof(double)); +// free(res); +// } else { +// setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); +// return; +// } } else { if (pOutput->pHisto->numOfElems > 0) { double ratio[] = {v}; @@ -2718,7 +2554,7 @@ static void leastsquares_function(SqlFunctionCtx *pCtx) { pInfo->num += numOfElem; if (pInfo->num > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } SET_VAL(pCtx, numOfElem, 1); @@ -3356,7 +3192,7 @@ static void spread_function(SqlFunctionCtx *pCtx) { SET_VAL(pCtx, numOfElems, 1); if (numOfElems > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; pInfo->hasResult = DATA_SET_FLAG; } @@ -3384,7 +3220,7 @@ void spread_func_merge(SqlFunctionCtx *pCtx) { pCtx->param[3].d = pData->max; } - GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; +// GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } void spread_function_finalizer(SqlFunctionCtx *pCtx) { @@ -3397,10 +3233,10 @@ void spread_function_finalizer(SqlFunctionCtx *pCtx) { if (pCtx->currentStage == MERGE_STAGE) { assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY); - if (pResInfo->hasResult != DATA_SET_FLAG) { - setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); - return; - } +// if (pResInfo->hasResult != DATA_SET_FLAG) { +// setNull(pCtx->pOutput, pCtx->resDataInfo.type, pCtx->resDataInfo.bytes); +// return; +// } SET_DOUBLE_VAL((double *)pCtx->pOutput, pCtx->param[3].d - pCtx->param[0].d); } else { @@ -3708,7 +3544,7 @@ static void twa_function(SqlFunctionCtx *pCtx) { SET_VAL(pCtx, notNullElems, 1); if (notNullElems > 0) { - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } if (pCtx->stableQuery) { @@ -3726,7 +3562,7 @@ void twa_function_copy(SqlFunctionCtx *pCtx) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes); - pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult; +// pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult; } void twa_function_finalizer(SqlFunctionCtx *pCtx) { @@ -3738,7 +3574,7 @@ void twa_function_finalizer(SqlFunctionCtx *pCtx) { return; } - assert(pInfo->win.ekey == pInfo->p.key && pInfo->hasResult == pResInfo->hasResult); +// assert(pInfo->win.ekey == pInfo->p.key && pInfo->hasResult == pResInfo->hasResult); if (pInfo->win.ekey == pInfo->win.skey) { SET_DOUBLE_VAL((double *)pCtx->pOutput, pInfo->p.val); } else { @@ -3948,7 +3784,7 @@ static void ts_comp_function(SqlFunctionCtx *pCtx) { } SET_VAL(pCtx, pCtx->size, 1); - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } static void ts_comp_finalize(SqlFunctionCtx *pCtx) { @@ -4069,7 +3905,7 @@ static void rate_function(SqlFunctionCtx *pCtx) { if (notNullElems > 0) { pRateInfo->hasResult = DATA_SET_FLAG; - pResInfo->hasResult = DATA_SET_FLAG; +// pResInfo->hasResult = DATA_SET_FLAG; } // keep the data into the final output buffer for super table query since this execution may be the last one @@ -4083,7 +3919,7 @@ static void rate_func_copy(SqlFunctionCtx *pCtx) { SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes); - pResInfo->hasResult = ((SRateInfo*)pCtx->pInput)->hasResult; +// pResInfo->hasResult = ((SRateInfo*)pCtx->pInput)->hasResult; } static void rate_finalizer(SqlFunctionCtx *pCtx) { @@ -4099,7 +3935,7 @@ static void rate_finalizer(SqlFunctionCtx *pCtx) { // cannot set the numOfIteratedElems again since it is set during previous iteration pResInfo->numOfRes = 1; - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; doFinalizer(pCtx); } @@ -4139,7 +3975,7 @@ static void irate_function(SqlFunctionCtx *pCtx) { if (notNullElems > 0) { pRateInfo->hasResult = DATA_SET_FLAG; - pResInfo->hasResult = DATA_SET_FLAG; +// pResInfo->hasResult = DATA_SET_FLAG; } // keep the data into the final output buffer for super table query since this execution may be the last one @@ -4197,7 +4033,7 @@ static void blockInfo_func(SqlFunctionCtx* pCtx) { memcpy(pCtx->pOutput, pCtx->pInput, sizeof(int32_t) + len); pResInfo->numOfRes = 1; - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } static void mergeTableBlockDist(SResultRowEntryInfo* pResInfo, const STableBlockDist* pSrc) { @@ -4211,10 +4047,10 @@ static void mergeTableBlockDist(SResultRowEntryInfo* pResInfo, const STableBlock pDist->totalSize += pSrc->totalSize; pDist->totalRows += pSrc->totalRows; - if (pResInfo->hasResult == DATA_SET_FLAG) { - pDist->maxRows = TMAX(pDist->maxRows, pSrc->maxRows); - pDist->minRows = TMIN(pDist->minRows, pSrc->minRows); - } else { +// if (pResInfo->hasResult == DATA_SET_FLAG) { +// pDist->maxRows = TMAX(pDist->maxRows, pSrc->maxRows); +// pDist->minRows = TMIN(pDist->minRows, pSrc->minRows); +// } else { pDist->maxRows = pSrc->maxRows; pDist->minRows = pSrc->minRows; @@ -4224,7 +4060,7 @@ static void mergeTableBlockDist(SResultRowEntryInfo* pResInfo, const STableBlock } pDist->dataBlockInfos = taosArrayInit(maxSteps, sizeof(SFileBlockInfo)); taosArraySetSize(pDist->dataBlockInfos, maxSteps); - } +// } size_t steps = taosArrayGetSize(pSrc->dataBlockInfos); for (int32_t i = 0; i < steps; ++i) { @@ -4243,7 +4079,7 @@ void block_func_merge(SqlFunctionCtx* pCtx) { taosArrayDestroy(info.dataBlockInfos); pResInfo->numOfRes = 1; - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; } void getPercentiles(STableBlockDist *pTableBlockDist, int64_t totalBlocks, int32_t numOfPercents, @@ -4354,7 +4190,7 @@ void blockinfo_func_finalizer(SqlFunctionCtx* pCtx) { // cannot set the numOfIteratedElems again since it is set during previous iteration pResInfo->numOfRes = 1; - pResInfo->hasResult = DATA_SET_FLAG; + //pResInfo->hasResult = DATA_SET_FLAG; doFinalizer(pCtx); } @@ -4381,24 +4217,6 @@ int32_t functionCompatList[] = { 6, 8, 7, }; -//typedef struct SFunctionFpSet { -// bool (*init)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment -// void (*addInput)(struct SqlFunctionCtx *pCtx); -// -// // finalizer must be called after all exec has been executed to generated final result. -// void (*finalize)(struct SqlFunctionCtx *pCtx); -// void (*combine)(struct SqlFunctionCtx *pCtx); -//} SFunctionFpSet; - -SFunctionFpSet fpSet[1] = { - { - .init = function_setup, - .addInput = count_function, - .finalize = doFinalizer, - .combine = count_func_merge, - }, -}; - SAggFunctionInfo aggFunc[35] = {{ // 0, count function does not invoke the finalize function "count", @@ -4446,7 +4264,7 @@ SAggFunctionInfo aggFunc[35] = {{ FUNCTION_MIN, BASIC_FUNC_SO | FUNCSTATE_SELECTIVITY, min_func_setup, - min_function, + NULL, function_finalizer, min_func_merge, statisRequired, @@ -4459,7 +4277,7 @@ SAggFunctionInfo aggFunc[35] = {{ FUNCTION_MAX, BASIC_FUNC_SO | FUNCSTATE_SELECTIVITY, max_func_setup, - max_function, + NULL, function_finalizer, max_func_merge, statisRequired, diff --git a/source/libs/function/src/tfill.c b/source/libs/function/src/tfill.c index 653e30cec883b1bb82a635e945cf1ec3077fcfba..46d82aa6fbbf1854eeb8415fe21340fd5d16dad5 100644 --- a/source/libs/function/src/tfill.c +++ b/source/libs/function/src/tfill.c @@ -543,7 +543,7 @@ struct SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, co pFillCol[i].col.offset = offset; pFillCol[i].col.colId = pExprInfo->base.resSchema.colId; pFillCol[i].tagIndex = -2; - pFillCol[i].flag = pExprInfo->base.pColumns->flag; // always be the normal column for table query + pFillCol[i].flag = pExprInfo->base.pParam[0].pCol->flag; // always be the normal column for table query // pFillCol[i].functionId = pExprInfo->pExpr->_function.functionId; pFillCol[i].fillVal.i = fillVal[i]; diff --git a/source/libs/index/src/index.c b/source/libs/index/src/index.c index ae0a6c775e413cb95198b246fb5b74e3da41aca0..744f6ca70bb5dbbb2b7233e188044ae626da61cd 100644 --- a/source/libs/index/src/index.c +++ b/source/libs/index/src/index.c @@ -341,6 +341,8 @@ static int indexTermSearch(SIndex* sIdx, SIndexTermQuery* query, SArray** result // TODO: iterator mem and tidex STermValueType s = kTypeValue; + int64_t st = taosGetTimestampUs(); + SIdxTempResult* tr = sIdxTempResultCreate(); if (0 == indexCacheSearch(cache, query, tr, &s)) { if (s == kTypeDeletion) { @@ -348,17 +350,23 @@ static int indexTermSearch(SIndex* sIdx, SIndexTermQuery* query, SArray** result // coloum already drop by other oper, no need to query tindex return 0; } else { + st = taosGetTimestampUs(); if (0 != indexTFileSearch(sIdx->tindex, query, tr)) { indexError("corrupt at index(TFile) col:%s val: %s", term->colName, term->colVal); goto END; } + int64_t tfCost = taosGetTimestampUs() - st; + indexInfo("tfile search cost: %" PRIu64 "us", tfCost); } } else { indexError("corrupt at index(cache) col:%s val: %s", term->colName, term->colVal); goto END; } + int64_t cost = taosGetTimestampUs() - st; + indexInfo("search cost: %" PRIu64 "us", cost); sIdxTempResultMergeTo(*result, tr); + sIdxTempResultDestroy(tr); return 0; END: diff --git a/source/libs/index/src/index_cache.c b/source/libs/index/src/index_cache.c index d3b25afdbcd7d198d738eb2a5bce2ba6b43a2e4b..b40ded9e9ace2763950a93f272cb309074febc2c 100644 --- a/source/libs/index/src/index_cache.c +++ b/source/libs/index/src/index_cache.c @@ -276,7 +276,12 @@ static int indexQueryMem(MemTable* mem, CacheTerm* ct, EIndexQueryType qtype, SI } else if (c->operaType == DEL_VALUE) { INDEX_MERGE_ADD_DEL(tr->added, tr->deled, c->uid) } + } else { + break; } + } else if (qtype == QUERY_PREFIX) { + } else if (qtype == QUERY_SUFFIX) { + } else if (qtype == QUERY_RANGE) { } } } @@ -284,6 +289,7 @@ static int indexQueryMem(MemTable* mem, CacheTerm* ct, EIndexQueryType qtype, SI return 0; } int indexCacheSearch(void* cache, SIndexTermQuery* query, SIdxTempResult* result, STermValueType* s) { + int64_t st = taosGetTimestampUs(); if (cache == NULL) { return 0; } @@ -312,12 +318,14 @@ int indexCacheSearch(void* cache, SIndexTermQuery* query, SIdxTempResult* result // continue search in imm ret = indexQueryMem(imm, &ct, qtype, result, s); } + if (hasJson) { tfree(p); } indexMemUnRef(mem); indexMemUnRef(imm); + indexInfo("cache search, time cost %" PRIu64 "us", taosGetTimestampUs() - st); return ret; } diff --git a/source/libs/index/src/index_tfile.c b/source/libs/index/src/index_tfile.c index fd267fbf03d5742ab838581e735e7ba19f1a6254..780b7160fca098a851071871d5e79b3e3768a57d 100644 --- a/source/libs/index/src/index_tfile.c +++ b/source/libs/index/src/index_tfile.c @@ -189,8 +189,8 @@ int tfileReaderSearch(TFileReader* reader, SIndexTermQuery* query, SIdxTempResul bool hasJson = INDEX_TYPE_CONTAIN_EXTERN_TYPE(term->colType, TSDB_DATA_TYPE_JSON); EIndexQueryType qtype = query->qType; - SArray* result = taosArrayInit(16, sizeof(uint64_t)); - int ret = -1; + // SArray* result = taosArrayInit(16, sizeof(uint64_t)); + int ret = -1; // refactor to callback later if (qtype == QUERY_TERM) { uint64_t offset; @@ -200,11 +200,18 @@ int tfileReaderSearch(TFileReader* reader, SIndexTermQuery* query, SIdxTempResul p = indexPackJsonData(term); sz = strlen(p); } + int64_t st = taosGetTimestampUs(); FstSlice key = fstSliceCreate(p, sz); if (fstGet(reader->fst, &key, &offset)) { - indexInfo("index: %" PRIu64 ", col: %s, colVal: %s, found table info in tindex", term->suid, term->colName, - term->colVal); - ret = tfileReaderLoadTableIds(reader, offset, result); + int64_t et = taosGetTimestampUs(); + int64_t cost = et - st; + indexInfo("index: %" PRIu64 ", col: %s, colVal: %s, found table info in tindex, time cost: %" PRIu64 "us", + term->suid, term->colName, term->colVal, cost); + + ret = tfileReaderLoadTableIds(reader, offset, tr->total); + cost = taosGetTimestampUs() - et; + indexInfo("index: %" PRIu64 ", col: %s, colVal: %s, load all table info, time cost: %" PRIu64 "us", term->suid, + term->colName, term->colVal, cost); } else { indexInfo("index: %" PRIu64 ", col: %s, colVal: %s, not found table info in tindex", term->suid, term->colName, term->colVal); @@ -225,8 +232,8 @@ int tfileReaderSearch(TFileReader* reader, SIndexTermQuery* query, SIdxTempResul } tfileReaderUnRef(reader); - taosArrayAddAll(tr->total, result); - taosArrayDestroy(result); + // taosArrayAddAll(tr->total, result); + // taosArrayDestroy(result); return ret; } @@ -391,6 +398,7 @@ int indexTFileSearch(void* tfile, SIndexTermQuery* query, SIdxTempResult* result return ret; } + int64_t st = taosGetTimestampUs(); IndexTFile* pTfile = tfile; SIndexTerm* term = query->term; @@ -399,6 +407,8 @@ int indexTFileSearch(void* tfile, SIndexTermQuery* query, SIdxTempResult* result if (reader == NULL) { return 0; } + int64_t cost = taosGetTimestampUs() - st; + indexInfo("index tfile stage 1 cost: %" PRId64 "", cost); return tfileReaderSearch(reader, query, result); } @@ -722,13 +732,13 @@ static SArray* tfileGetFileList(const char* path) { uint32_t version; SArray* files = taosArrayInit(4, sizeof(void*)); - DIR* dir = opendir(path); - if (NULL == dir) { + TdDirPtr pDir = taosOpenDir(path); + if (NULL == pDir) { return NULL; } - struct dirent* entry; - while ((entry = readdir(dir)) != NULL) { - char* file = entry->d_name; + TdDirEntryPtr pDirEntry; + while ((pDirEntry = taosReadDir(pDir)) != NULL) { + char* file = taosGetDirEntryName(pDirEntry); if (0 != tfileParseFileName(file, &suid, buf, &version)) { continue; } @@ -738,7 +748,7 @@ static SArray* tfileGetFileList(const char* path) { sprintf(buf, "%s/%s", path, file); taosArrayPush(files, &buf); } - closedir(dir); + taosCloseDir(pDir); taosArraySort(files, tfileCompare); tfileRmExpireFile(files); diff --git a/source/libs/index/test/fstTest.cc b/source/libs/index/test/fstTest.cc index 618e20bc4ba588f0d7e5586290f3c5d40016dc72..410d5b702125df60c780fbcf5a90951dc9d24323 100644 --- a/source/libs/index/test/fstTest.cc +++ b/source/libs/index/test/fstTest.cc @@ -258,7 +258,7 @@ void checkFstCheckIterator() { // prefix search std::vector result; - AutomationCtx* ctx = automCtxCreate((void*)"ab", AUTOMATION_ALWAYS); + AutomationCtx* ctx = automCtxCreate((void*)"H", AUTOMATION_PREFIX); m->Search(ctx, result); std::cout << "size: " << result.size() << std::endl; // assert(result.size() == count); @@ -328,11 +328,11 @@ void iterTFileReader(char* path, char* uid, char* colName, char* ver) { int main(int argc, char* argv[]) { // tool to check all kind of fst test // if (argc > 1) { validateTFile(argv[1]); } - if (argc > 4) { - // path suid colName ver - iterTFileReader(argv[1], argv[2], argv[3], argv[4]); - } - // checkFstCheckIterator(); + // if (argc > 4) { + // path suid colName ver + // iterTFileReader(argv[1], argv[2], argv[3], argv[4]); + //} + checkFstCheckIterator(); // checkFstLongTerm(); // checkFstPrefixSearch(); diff --git a/source/libs/index/test/indexTests.cc b/source/libs/index/test/indexTests.cc index ce3f7fe25e3e1b58cdf50fe6fda861edd5795b9e..5f339f286576f3fd5d535470ed9583a2b65363df 100644 --- a/source/libs/index/test/indexTests.cc +++ b/source/libs/index/test/indexTests.cc @@ -699,7 +699,7 @@ class IndexObj { for (int i = 0; i < numOfTable; i++) { for (int k = 0; k < 10 && k < colVal.size(); k++) { // opt - tColVal[rand() % colValSize] = 'a' + k % 26; + tColVal[taosRand() % colValSize] = 'a' + k % 26; } SIndexTerm* term = indexTermCreate(0, ADD_VALUE, TSDB_DATA_TYPE_BINARY, colName.c_str(), colName.size(), tColVal.c_str(), tColVal.size()); @@ -768,7 +768,7 @@ class IndexObj { int64_t s = taosGetTimestampUs(); if (Search(mq, result) == 0) { int64_t e = taosGetTimestampUs(); - std::cout << "search one successfully and time cost:" << e - s << "\tquery col:" << colName + std::cout << "search one successfully and time cost:" << e - s << "us\tquery col:" << colName << "\t val: " << colVal << "\t size:" << taosArrayGetSize(result) << std::endl; } else { } @@ -1106,6 +1106,7 @@ TEST_F(IndexEnv2, testIndex_del) { } index->Del("tag10", "Hello", 12); index->Del("tag10", "Hello", 11); + EXPECT_EQ(98, index->SearchOne("tag10", "Hello")); index->WriteMultiMillonData("tag10", "xxxxxxxxxxxxxx", 100 * 10000); index->Del("tag10", "Hello", 17); diff --git a/source/libs/monitor/CMakeLists.txt b/source/libs/monitor/CMakeLists.txt index 050372fab3ff0d4a9dd11d73fd6f85c645dfd6dd..58f1c08039731f083bf366165b99a56401100e5e 100644 --- a/source/libs/monitor/CMakeLists.txt +++ b/source/libs/monitor/CMakeLists.txt @@ -3,7 +3,6 @@ add_library(monitor STATIC ${MONITOR_SRC}) target_include_directories( monitor PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/monitor" - PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/transport" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" ) diff --git a/source/libs/monitor/inc/monInt.h b/source/libs/monitor/inc/monInt.h index c3b65695551f5d5fd2b4c84e8577d1636ae0157b..6ef901410bff1923ee425ffcaff6c44eb7d047d8 100644 --- a/source/libs/monitor/inc/monInt.h +++ b/source/libs/monitor/inc/monInt.h @@ -19,7 +19,6 @@ #include "monitor.h" #include "tarray.h" -#include "tlockfree.h" #include "tjson.h" typedef struct { diff --git a/include/libs/nodes/nodesShowStmts.h b/source/libs/nodes/inc/nodesUtil.h similarity index 58% rename from include/libs/nodes/nodesShowStmts.h rename to source/libs/nodes/inc/nodesUtil.h index 312fbbc4f479380153fcf6fa6b7836e803388124..de00b6bca4d9203bf260ea3b55945061a3264d4c 100644 --- a/include/libs/nodes/nodesShowStmts.h +++ b/source/libs/nodes/inc/nodesUtil.h @@ -13,26 +13,22 @@ * along with this program. If not, see . */ -#ifndef _TD_NODES_SHOW_STMTS_H_ -#define _TD_NODES_SHOW_STMTS_H_ +#ifndef _TD_NODES_INT_H_ +#define _TD_NODES_INT_H_ #ifdef __cplusplus extern "C" { #endif -#include "nodes.h" - -typedef enum EShowStmtType { - SHOW_TYPE_DATABASE = 1 -} EShowStmtType; - -typedef struct SShowStmt { - ENodeType type; // QUERY_NODE_SHOW_STMT - EShowStmtType showType; -} SShowStmt; +#define nodesFatal(param, ...) qFatal("NODES: " param, __VA_ARGS__) +#define nodesError(param, ...) qError("NODES: " param, __VA_ARGS__) +#define nodesWarn(param, ...) qWarn("NODES: " param, __VA_ARGS__) +#define nodesInfo(param, ...) qInfo("NODES: " param, __VA_ARGS__) +#define nodesDebug(param, ...) qDebug("NODES: " param, __VA_ARGS__) +#define nodesTrace(param, ...) qTrace("NODES: " param, __VA_ARGS__) #ifdef __cplusplus } #endif -#endif /*_TD_NODES_SHOW_STMTS_H_*/ +#endif /*_TD_NODES_INT_H_*/ diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index e23c9ebe9d21fb8842b313f3ad886d2f813dba5d..34c211561bd3840caa612e6a3fe074138f1545cc 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -13,6 +13,8 @@ * along with this program. If not, see . */ +#include "nodesUtil.h" +#include "plannodes.h" #include "querynodes.h" #include "taos.h" #include "taoserror.h" @@ -32,8 +34,11 @@ (pDst)->fldname = strdup((pSrc)->fldname); \ } while (0) -#define COPY_NODE_FIELD(fldname) \ +#define CLONE_NODE_FIELD(fldname) \ do { \ + if (NULL == (pSrc)->fldname) { \ + break; \ + } \ (pDst)->fldname = nodesCloneNode((pSrc)->fldname); \ if (NULL == (pDst)->fldname) { \ nodesDestroyNode((SNode*)(pDst)); \ @@ -41,8 +46,11 @@ } \ } while (0) -#define COPY_NODE_LIST_FIELD(fldname) \ +#define CLONE_NODE_LIST_FIELD(fldname) \ do { \ + if (NULL == (pSrc)->fldname) { \ + break; \ + } \ (pDst)->fldname = nodesCloneList((pSrc)->fldname); \ if (NULL == (pDst)->fldname) { \ nodesDestroyNode((SNode*)(pDst)); \ @@ -50,6 +58,25 @@ } \ } while (0) +#define CLONE_OBJECT_FIELD(fldname, cloneFunc) \ + do { \ + if (NULL == (pSrc)->fldname) { \ + break; \ + } \ + (pDst)->fldname = cloneFunc((pSrc)->fldname); \ + if (NULL == (pDst)->fldname) { \ + nodesDestroyNode((SNode*)(pDst)); \ + return NULL; \ + } \ + } while (0) + +#define COPY_BASE_OBJECT_FIELD(fldname, copyFunc) \ + do { \ + if (NULL == copyFunc(&((pSrc)->fldname), &((pDst)->fldname))) { \ + return NULL; \ + } \ + } while (0) + static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) { COPY_SCALAR_FIELD(type); COPY_SCALAR_FIELD(precision); @@ -60,7 +87,7 @@ static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) { static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) { dataTypeCopy(&pSrc->resType, &pDst->resType); COPY_CHAR_ARRAY_FIELD(aliasName); - // COPY_NODE_LIST_FIELD(pAssociationList); + // CLONE_NODE_LIST_FIELD(pAssociationList); } static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) { @@ -71,7 +98,7 @@ static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) { COPY_CHAR_ARRAY_FIELD(tableName); COPY_CHAR_ARRAY_FIELD(tableAlias); COPY_CHAR_ARRAY_FIELD(colName); - // COPY_NODE_FIELD(pProjectRef); + // CLONE_NODE_FIELD(pProjectRef); COPY_SCALAR_FIELD(dataBlockId); COPY_SCALAR_FIELD(slotId); return (SNode*)pDst; @@ -104,7 +131,6 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) { case TSDB_DATA_TYPE_DOUBLE: COPY_SCALAR_FIELD(datum.d); break; - case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: @@ -123,15 +149,15 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) { static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) { exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst); COPY_SCALAR_FIELD(opType); - COPY_NODE_FIELD(pLeft); - COPY_NODE_FIELD(pRight); + CLONE_NODE_FIELD(pLeft); + CLONE_NODE_FIELD(pRight); return (SNode*)pDst; } static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) { exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst); COPY_SCALAR_FIELD(condType); - COPY_NODE_LIST_FIELD(pParameterList); + CLONE_NODE_LIST_FIELD(pParameterList); return (SNode*)pDst; } @@ -140,24 +166,136 @@ static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) { COPY_CHAR_ARRAY_FIELD(functionName); COPY_SCALAR_FIELD(funcId); COPY_SCALAR_FIELD(funcType); - COPY_NODE_LIST_FIELD(pParameterList); + CLONE_NODE_LIST_FIELD(pParameterList); return (SNode*)pDst; } static SNode* targetNodeCopy(const STargetNode* pSrc, STargetNode* pDst) { COPY_SCALAR_FIELD(dataBlockId); COPY_SCALAR_FIELD(slotId); - COPY_NODE_FIELD(pExpr); + CLONE_NODE_FIELD(pExpr); return (SNode*)pDst; } static SNode* groupingSetNodeCopy(const SGroupingSetNode* pSrc, SGroupingSetNode* pDst) { COPY_SCALAR_FIELD(groupingSetType); - COPY_NODE_LIST_FIELD(pParameterList); + CLONE_NODE_LIST_FIELD(pParameterList); + return (SNode*)pDst; +} + +static SNode* fillNodeCopy(const SFillNode* pSrc, SFillNode* pDst) { + COPY_SCALAR_FIELD(mode); + CLONE_NODE_FIELD(pValues); + return (SNode*)pDst; +} + +static SNode* logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) { + COPY_SCALAR_FIELD(id); + CLONE_NODE_LIST_FIELD(pTargets); + CLONE_NODE_FIELD(pConditions); + CLONE_NODE_LIST_FIELD(pChildren); + return (SNode*)pDst; +} + +static STableMeta* tableMetaClone(const STableMeta* pSrc) { + int32_t len = sizeof(STableMeta) + (pSrc->tableInfo.numOfTags + pSrc->tableInfo.numOfColumns) * sizeof(SSchema); + STableMeta* pDst = malloc(len); + if (NULL == pDst) { + return NULL; + } + memcpy(pDst, pSrc, len); + return pDst; +} + +static SVgroupsInfo* vgroupsInfoClone(const SVgroupsInfo* pSrc) { + int32_t len = sizeof(SVgroupsInfo) + pSrc->numOfVgroups * sizeof(SVgroupInfo); + SVgroupsInfo* pDst = malloc(len); + if (NULL == pDst) { + return NULL; + } + memcpy(pDst, pSrc, len); + return pDst; +} + +static SNode* logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) { + COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); + CLONE_NODE_LIST_FIELD(pScanCols); + CLONE_OBJECT_FIELD(pMeta, tableMetaClone); + CLONE_OBJECT_FIELD(pVgroupList, vgroupsInfoClone); + COPY_SCALAR_FIELD(scanType); + COPY_SCALAR_FIELD(scanFlag); + COPY_SCALAR_FIELD(scanRange); + COPY_SCALAR_FIELD(tableName); + return (SNode*)pDst; +} + +static SNode* logicAggCopy(const SAggLogicNode* pSrc, SAggLogicNode* pDst) { + COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); + CLONE_NODE_LIST_FIELD(pGroupKeys); + CLONE_NODE_LIST_FIELD(pAggFuncs); + return (SNode*)pDst; +} + +static SNode* logicProjectCopy(const SProjectLogicNode* pSrc, SProjectLogicNode* pDst) { + COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); + CLONE_NODE_LIST_FIELD(pProjections); + return (SNode*)pDst; +} + +static SNode* logicVnodeModifCopy(const SVnodeModifLogicNode* pSrc, SVnodeModifLogicNode* pDst) { + COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); + COPY_SCALAR_FIELD(msgType); + return (SNode*)pDst; +} + +static SNode* logicExchangeCopy(const SExchangeLogicNode* pSrc, SExchangeLogicNode* pDst) { + COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); + COPY_SCALAR_FIELD(srcGroupId); + return (SNode*)pDst; +} + +static SNode* logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* pDst) { + COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); + COPY_SCALAR_FIELD(winType); + CLONE_NODE_LIST_FIELD(pFuncs); + COPY_SCALAR_FIELD(interval); + COPY_SCALAR_FIELD(offset); + COPY_SCALAR_FIELD(sliding); + CLONE_NODE_FIELD(pFill); return (SNode*)pDst; } -SNode* nodesCloneNode(const SNode* pNode) { +static SNode* logicSubplanCopy(const SSubLogicPlan* pSrc, SSubLogicPlan* pDst) { + CLONE_NODE_FIELD(pNode); + COPY_SCALAR_FIELD(subplanType); + return (SNode*)pDst; +} + +static SNode* dataBlockDescCopy(const SDataBlockDescNode* pSrc, SDataBlockDescNode* pDst) { + COPY_SCALAR_FIELD(dataBlockId); + CLONE_NODE_LIST_FIELD(pSlots); + COPY_SCALAR_FIELD(resultRowSize); + COPY_SCALAR_FIELD(precision); + return (SNode*)pDst; +} + +static SNode* slotDescCopy(const SSlotDescNode* pSrc, SSlotDescNode* pDst) { + COPY_SCALAR_FIELD(slotId); + dataTypeCopy(&pSrc->dataType, &pDst->dataType); + COPY_SCALAR_FIELD(reserve); + COPY_SCALAR_FIELD(output); + COPY_SCALAR_FIELD(tag); + return (SNode*)pDst; +} + +static SNode* downstreamSourceCopy(const SDownstreamSourceNode* pSrc, SDownstreamSourceNode* pDst) { + COPY_SCALAR_FIELD(addr); + COPY_SCALAR_FIELD(taskId); + COPY_SCALAR_FIELD(schedId); + return (SNode*)pDst; +} + +SNodeptr nodesCloneNode(const SNodeptr pNode) { if (NULL == pNode) { return NULL; } @@ -187,10 +325,35 @@ SNode* nodesCloneNode(const SNode* pNode) { return groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst); case QUERY_NODE_ORDER_BY_EXPR: case QUERY_NODE_LIMIT: + break; + case QUERY_NODE_FILL: + return fillNodeCopy((const SFillNode*)pNode, (SFillNode*)pDst); + case QUERY_NODE_DATABLOCK_DESC: + return dataBlockDescCopy((const SDataBlockDescNode*)pNode, (SDataBlockDescNode*)pDst); + case QUERY_NODE_SLOT_DESC: + return slotDescCopy((const SSlotDescNode*)pNode, (SSlotDescNode*)pDst); + case QUERY_NODE_DOWNSTREAM_SOURCE: + return downstreamSourceCopy((const SDownstreamSourceNode*)pNode, (SDownstreamSourceNode*)pDst); + case QUERY_NODE_LOGIC_PLAN_SCAN: + return logicScanCopy((const SScanLogicNode*)pNode, (SScanLogicNode*)pDst); + case QUERY_NODE_LOGIC_PLAN_AGG: + return logicAggCopy((const SAggLogicNode*)pNode, (SAggLogicNode*)pDst); + case QUERY_NODE_LOGIC_PLAN_PROJECT: + return logicProjectCopy((const SProjectLogicNode*)pNode, (SProjectLogicNode*)pDst); + case QUERY_NODE_LOGIC_PLAN_VNODE_MODIF: + return logicVnodeModifCopy((const SVnodeModifLogicNode*)pNode, (SVnodeModifLogicNode*)pDst); + case QUERY_NODE_LOGIC_PLAN_EXCHANGE: + return logicExchangeCopy((const SExchangeLogicNode*)pNode, (SExchangeLogicNode*)pDst); + case QUERY_NODE_LOGIC_PLAN_WINDOW: + return logicWindowCopy((const SWindowLogicNode*)pNode, (SWindowLogicNode*)pDst); + case QUERY_NODE_LOGIC_SUBPLAN: + return logicSubplanCopy((const SSubLogicPlan*)pNode, (SSubLogicPlan*)pDst); default: break; } - return pDst; + nodesDestroyNode(pDst); + nodesError("nodesCloneNode unknown node = %s", nodesNodeName(nodeType(pNode))); + return NULL; } SNodeList* nodesCloneList(const SNodeList* pList) { diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index b1fd4bb56f78c63384a79d9955550f9a0690cb96..57ebc2c4b6fb3956a6a80b6e688aae8751406c19 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "nodesUtil.h" #include "plannodes.h" #include "querynodes.h" #include "query.h" @@ -24,7 +25,7 @@ static int32_t jsonToNode(const SJson* pJson, void* pObj); static int32_t jsonToNodeObject(const SJson* pJson, const char* pName, SNode** pNode); static int32_t makeNodeByJson(const SJson* pJson, SNode** pNode); -static char* nodeName(ENodeType type) { +const char* nodesNodeName(ENodeType type) { switch (type) { case QUERY_NODE_COLUMN: return "Column"; @@ -58,20 +59,32 @@ static char* nodeName(ENodeType type) { return "NodeList"; case QUERY_NODE_FILL: return "Fill"; - case QUERY_NODE_TARGET: - return "Target"; case QUERY_NODE_RAW_EXPR: return "RawExpr"; + case QUERY_NODE_TARGET: + return "Target"; case QUERY_NODE_DATABLOCK_DESC: return "TupleDesc"; case QUERY_NODE_SLOT_DESC: return "SlotDesc"; + case QUERY_NODE_COLUMN_DEF: + return "ColumnDef"; case QUERY_NODE_SET_OPERATOR: return "SetOperator"; case QUERY_NODE_SELECT_STMT: return "SelectStmt"; - case QUERY_NODE_SHOW_STMT: - return "ShowStmt"; + case QUERY_NODE_VNODE_MODIF_STMT: + return "VnodeModifStmt"; + case QUERY_NODE_CREATE_DATABASE_STMT: + return "CreateDatabaseStmt"; + case QUERY_NODE_CREATE_TABLE_STMT: + return "CreateTableStmt"; + case QUERY_NODE_USE_DATABASE_STMT: + return "UseDatabaseStmt"; + case QUERY_NODE_SHOW_DATABASES_STMT: + return "ShowDatabaseStmt"; + case QUERY_NODE_SHOW_TABLES_STMT: + return "ShowTablesStmt"; case QUERY_NODE_LOGIC_PLAN_SCAN: return "LogicScan"; case QUERY_NODE_LOGIC_PLAN_JOIN: @@ -80,22 +93,45 @@ static char* nodeName(ENodeType type) { return "LogicAgg"; case QUERY_NODE_LOGIC_PLAN_PROJECT: return "LogicProject"; + case QUERY_NODE_LOGIC_PLAN_VNODE_MODIF: + return "LogicVnodeModif"; + case QUERY_NODE_LOGIC_SUBPLAN: + return "LogicSubplan"; + case QUERY_NODE_LOGIC_PLAN: + return "LogicPlan"; case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: return "PhysiTagScan"; case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: return "PhysiTableScan"; + case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN: + return "PhysiTableSeqScan"; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN: + return "PhysiSreamScan"; case QUERY_NODE_PHYSICAL_PLAN_PROJECT: return "PhysiProject"; case QUERY_NODE_PHYSICAL_PLAN_JOIN: return "PhysiJoin"; case QUERY_NODE_PHYSICAL_PLAN_AGG: return "PhysiAgg"; + case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: + return "PhysiExchange"; + case QUERY_NODE_PHYSICAL_PLAN_SORT: + return "PhysiSort"; + case QUERY_NODE_PHYSICAL_PLAN_INTERVAL: + return "PhysiInterval"; + case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: + return "PhysiDispatch"; + case QUERY_NODE_PHYSICAL_PLAN_INSERT: + return "PhysiInsert"; + case QUERY_NODE_PHYSICAL_SUBPLAN: + return "PhysiSubplan"; + case QUERY_NODE_PHYSICAL_PLAN: + return "PhysiPlan"; default: break; } - static char tmp[20]; - snprintf(tmp, sizeof(tmp), "Unknown %d", type); - return tmp; + nodesWarn("nodesNodeName unknown node = %d", type); + return "UnknownNode"; } static int32_t nodeListToJson(SJson* pJson, const char* pName, const SNodeList* pList) { @@ -230,7 +266,7 @@ static const char* jkPhysiPlanChildren = "Children"; static int32_t physicPlanNodeToJson(const void* pObj, SJson* pJson) { const SPhysiNode* pNode = (const SPhysiNode*)pObj; - int32_t code = tjsonAddObject(pJson, jkPhysiPlanOutputDataBlockDesc, nodeToJson, &pNode->outputDataBlockDesc); + int32_t code = tjsonAddObject(pJson, jkPhysiPlanOutputDataBlockDesc, nodeToJson, pNode->pOutputDataBlockDesc); if (TSDB_CODE_SUCCESS == code) { code = tjsonAddObject(pJson, jkPhysiPlanConditions, nodeToJson, pNode->pConditions); } @@ -244,7 +280,7 @@ static int32_t physicPlanNodeToJson(const void* pObj, SJson* pJson) { static int32_t jsonToPhysicPlanNode(const SJson* pJson, void* pObj) { SPhysiNode* pNode = (SPhysiNode*)pObj; - int32_t code = tjsonToObject(pJson, jkPhysiPlanOutputDataBlockDesc, jsonToNode, &pNode->outputDataBlockDesc); + int32_t code = jsonToNodeObject(pJson, jkPhysiPlanOutputDataBlockDesc, (SNode**)&pNode->pOutputDataBlockDesc); if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeObject(pJson, jkPhysiPlanConditions, &pNode->pConditions); } @@ -255,12 +291,52 @@ static int32_t jsonToPhysicPlanNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkNameType = "NameType"; +static const char* jkNameAcctId = "AcctId"; +static const char* jkNameDbName = "DbName"; +static const char* jkNameTableName = "TableName"; + +static int32_t nameToJson(const void* pObj, SJson* pJson) { + const SName* pNode = (const SName*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkNameType, pNode->type); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkNameAcctId, pNode->acctId); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkNameDbName, pNode->dbname); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkNameTableName, pNode->tname); + } + + return code; +} + +static int32_t jsonToName(const SJson* pJson, void* pObj) { + SName* pNode = (SName*)pObj; + + int32_t code = tjsonGetUTinyIntValue(pJson, jkNameType, &pNode->type); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkNameAcctId, &pNode->acctId); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkNameDbName, pNode->dbname); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkNameTableName, pNode->tname); + } + + return code; +} + static const char* jkScanPhysiPlanScanCols = "ScanCols"; static const char* jkScanPhysiPlanTableId = "TableId"; static const char* jkScanPhysiPlanTableType = "TableType"; static const char* jkScanPhysiPlanScanOrder = "ScanOrder"; static const char* jkScanPhysiPlanScanCount = "ScanCount"; static const char* jkScanPhysiPlanReverseScanCount = "ReverseScanCount"; +static const char* jkScanPhysiPlanTableName = "TableName"; static int32_t physiScanNodeToJson(const void* pObj, SJson* pJson) { const STagScanPhysiNode* pNode = (const STagScanPhysiNode*)pObj; @@ -284,6 +360,9 @@ static int32_t physiScanNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = tjsonAddIntegerToObject(pJson, jkScanPhysiPlanReverseScanCount, pNode->reverse); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkScanPhysiPlanTableName, nameToJson, &pNode->tableName); + } return code; } @@ -310,6 +389,9 @@ static int32_t jsonToPhysiScanNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = tjsonGetIntValue(pJson, jkScanPhysiPlanReverseScanCount, &pNode->reverse); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonToObject(pJson, jkScanPhysiPlanTableName, jsonToName, &pNode->tableName); + } return code; } @@ -462,6 +544,306 @@ static int32_t jsonToPhysiAggNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkExchangePhysiPlanSrcGroupId = "SrcGroupId"; +static const char* jkExchangePhysiPlanSrcEndPoints = "SrcEndPoints"; + +static int32_t physiExchangeNodeToJson(const void* pObj, SJson* pJson) { + const SExchangePhysiNode* pNode = (const SExchangePhysiNode*)pObj; + + int32_t code = physicPlanNodeToJson(pObj, pJson); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkExchangePhysiPlanSrcGroupId, pNode->srcGroupId); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkExchangePhysiPlanSrcEndPoints, pNode->pSrcEndPoints); + } + + return code; +} + +static int32_t jsonToPhysiExchangeNode(const SJson* pJson, void* pObj) { + SExchangePhysiNode* pNode = (SExchangePhysiNode*)pObj; + + int32_t code = jsonToPhysicPlanNode(pJson, pObj); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkExchangePhysiPlanSrcGroupId, &pNode->srcGroupId); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkExchangePhysiPlanSrcEndPoints, &pNode->pSrcEndPoints); + } + + return code; +} + +static const char* jkIntervalPhysiPlanExprs = "Exprs"; +static const char* jkIntervalPhysiPlanFuncs = "Funcs"; +static const char* jkIntervalPhysiPlanInterval = "Interval"; +static const char* jkIntervalPhysiPlanOffset = "Offset"; +static const char* jkIntervalPhysiPlanSliding = "Sliding"; +static const char* jkIntervalPhysiPlanFill = "Fill"; + +static int32_t physiIntervalNodeToJson(const void* pObj, SJson* pJson) { + const SIntervalPhysiNode* pNode = (const SIntervalPhysiNode*)pObj; + + int32_t code = physicPlanNodeToJson(pObj, pJson); + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkIntervalPhysiPlanExprs, pNode->pExprs); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkIntervalPhysiPlanFuncs, pNode->pFuncs); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkIntervalPhysiPlanInterval, pNode->interval); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkIntervalPhysiPlanOffset, pNode->offset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkIntervalPhysiPlanSliding, pNode->sliding); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkIntervalPhysiPlanFill, nodeToJson, pNode->pFill); + } + + return code; +} + +static int32_t jsonToPhysiIntervalNode(const SJson* pJson, void* pObj) { + SIntervalPhysiNode* pNode = (SIntervalPhysiNode*)pObj; + + int32_t code = jsonToPhysicPlanNode(pJson, pObj); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkIntervalPhysiPlanExprs, &pNode->pExprs); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkIntervalPhysiPlanFuncs, &pNode->pFuncs); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkIntervalPhysiPlanInterval, &pNode->interval); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkIntervalPhysiPlanOffset, &pNode->offset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkIntervalPhysiPlanSliding, &pNode->sliding); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkIntervalPhysiPlanFill, (SNode**)&pNode->pFill); + } + + return code; +} + +static const char* jkDataSinkInputDataBlockDesc = "InputDataBlockDesc"; + +static int32_t physicDataSinkNodeToJson(const void* pObj, SJson* pJson) { + const SDataSinkNode* pNode = (const SDataSinkNode*)pObj; + return tjsonAddObject(pJson, jkDataSinkInputDataBlockDesc, nodeToJson, pNode->pInputDataBlockDesc); +} + +static int32_t jsonToPhysicDataSinkNode(const SJson* pJson, void* pObj) { + SDataSinkNode* pNode = (SDataSinkNode*)pObj; + return jsonToNodeObject(pJson, jkDataSinkInputDataBlockDesc, (SNode**)&pNode->pInputDataBlockDesc); +} + +static int32_t physiDispatchNodeToJson(const void* pObj, SJson* pJson) { + return physicDataSinkNodeToJson(pObj, pJson); +} + +static int32_t jsonToPhysiDispatchNode(const SJson* pJson, void* pObj) { + return jsonToPhysicDataSinkNode(pJson, pObj); +} + +static const char* jkSubplanIdQueryId = "QueryId"; +static const char* jkSubplanIdGroupId = "GroupId"; +static const char* jkSubplanIdSubplanId = "SubplanId"; + +static int32_t subplanIdToJson(const void* pObj, SJson* pJson) { + const SSubplanId* pNode = (const SSubplanId*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkSubplanIdQueryId, pNode->queryId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkSubplanIdGroupId, pNode->groupId); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkSubplanIdSubplanId, pNode->subplanId); + } + + return code; +} + +static int32_t jsonToSubplanId(const SJson* pJson, void* pObj) { + SSubplanId* pNode = (SSubplanId*)pObj; + + int32_t code = tjsonGetUBigIntValue(pJson, jkSubplanIdQueryId, &pNode->queryId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkSubplanIdGroupId, &pNode->groupId); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkSubplanIdSubplanId, &pNode->subplanId); + } + + return code; +} + +static const char* jkEndPointFqdn = "Fqdn"; +static const char* jkEndPointPort = "Port"; + +static int32_t epToJson(const void* pObj, SJson* pJson) { + const SEp* pNode = (const SEp*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkEndPointFqdn, pNode->fqdn); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkEndPointPort, pNode->port); + } + + return code; +} + +static int32_t jsonToEp(const SJson* pJson, void* pObj) { + SEp* pNode = (SEp*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkEndPointFqdn, pNode->fqdn); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetSmallIntValue(pJson, jkEndPointPort, &pNode->port); + } + + return code; +} + +static const char* jkQueryNodeAddrId = "Id"; +static const char* jkQueryNodeAddrInUse = "InUse"; +static const char* jkQueryNodeAddrNumOfEps = "NumOfEps"; +static const char* jkQueryNodeAddrEps = "Eps"; + +static int32_t queryNodeAddrToJson(const void* pObj, SJson* pJson) { + const SQueryNodeAddr* pNode = (const SQueryNodeAddr*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkQueryNodeAddrId, pNode->nodeId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkQueryNodeAddrInUse, pNode->epSet.inUse); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkQueryNodeAddrNumOfEps, pNode->epSet.numOfEps); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddArray(pJson, jkQueryNodeAddrEps, epToJson, pNode->epSet.eps, sizeof(SEp), pNode->epSet.numOfEps); + } + + return code; +} + +static int32_t jsonToQueryNodeAddr(const SJson* pJson, void* pObj) { + SQueryNodeAddr* pNode = (SQueryNodeAddr*)pObj; + + int32_t code = tjsonGetIntValue(pJson, jkQueryNodeAddrId, &pNode->nodeId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkQueryNodeAddrInUse, &pNode->epSet.inUse); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkQueryNodeAddrNumOfEps, &pNode->epSet.numOfEps); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonToArray(pJson, jkQueryNodeAddrEps, jsonToEp, pNode->epSet.eps, sizeof(SEp)); + } + + return code; +} + +static const char* jkSubplanId = "Id"; +static const char* jkSubplanType = "SubplanType"; +static const char* jkSubplanMsgType = "MsgType"; +static const char* jkSubplanLevel = "Level"; +static const char* jkSubplanNodeAddr = "NodeAddr"; +static const char* jkSubplanRootNode = "RootNode"; +static const char* jkSubplanDataSink = "DataSink"; + +static int32_t subplanToJson(const void* pObj, SJson* pJson) { + const SSubplan* pNode = (const SSubplan*)pObj; + + int32_t code = tjsonAddObject(pJson, jkSubplanId, subplanIdToJson, &pNode->id); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkSubplanType, pNode->subplanType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkSubplanMsgType, pNode->msgType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkSubplanLevel, pNode->level); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkSubplanNodeAddr, queryNodeAddrToJson, &pNode->execNode); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkSubplanRootNode, nodeToJson, pNode->pNode); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkSubplanDataSink, nodeToJson, pNode->pDataSink); + } + + return code; +} + +static int32_t jsonToSubplan(const SJson* pJson, void* pObj) { + SSubplan* pNode = (SSubplan*)pObj; + + int32_t code = tjsonToObject(pJson, jkSubplanId, jsonToSubplanId, &pNode->id); + if (TSDB_CODE_SUCCESS == code) { + int32_t val; + code = tjsonGetIntValue(pJson, jkSubplanType, &val); + pNode->subplanType = val; + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkSubplanMsgType, &pNode->msgType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkSubplanLevel, &pNode->level); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonToObject(pJson, jkSubplanNodeAddr, jsonToQueryNodeAddr, &pNode->execNode); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkSubplanRootNode, (SNode**)&pNode->pNode); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkSubplanDataSink, (SNode**)&pNode->pDataSink); + } + + return code; +} + +static const char* jkPlanQueryId = "QueryId"; +static const char* jkPlanNumOfSubplans = "NumOfSubplans"; +static const char* jkPlanSubplans = "Subplans"; + +static int32_t planToJson(const void* pObj, SJson* pJson) { + const SQueryPlan* pNode = (const SQueryPlan*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkPlanQueryId, pNode->queryId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkPlanNumOfSubplans, pNode->numOfSubplans); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkPlanSubplans, pNode->pSubplans); + } + + return code; +} + +static int32_t jsonToPlan(const SJson* pJson, void* pObj) { + SQueryPlan* pNode = (SQueryPlan*)pObj; + + int32_t code = tjsonGetUBigIntValue(pJson, jkPlanQueryId, &pNode->queryId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkPlanNumOfSubplans, &pNode->numOfSubplans); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkPlanSubplans, &pNode->pSubplans); + } + + return code; +} + static const char* jkAggLogicPlanGroupKeys = "GroupKeys"; static const char* jkAggLogicPlanAggFuncs = "AggFuncs"; @@ -627,46 +1009,40 @@ static int32_t jsonToColumnNode(const SJson* pJson, void* pObj) { static const char* jkValueLiteral = "Literal"; static const char* jkValueDuration = "Duration"; +static const char* jkValueTranslate = "Translate"; static const char* jkValueDatum = "Datum"; -static int32_t valueNodeToJson(const void* pObj, SJson* pJson) { +static int32_t datumToJson(const void* pObj, SJson* pJson) { const SValueNode* pNode = (const SValueNode*)pObj; - int32_t code = exprNodeToJson(pObj, pJson); - if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->literal); - } - if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddBoolToObject(pJson, jkValueDuration, pNode->isDuration); - } + int32_t code = TSDB_CODE_SUCCESS; switch (pNode->node.resType.type) { case TSDB_DATA_TYPE_NULL: break; case TSDB_DATA_TYPE_BOOL: - code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.b); + code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.b); break; case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: case TSDB_DATA_TYPE_INT: case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TIMESTAMP: - code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.i); + code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.i); break; case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_UBIGINT: - code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.u); + code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.u); break; case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_DOUBLE: - code = tjsonAddDoubleToObject(pJson, jkValueDuration, pNode->datum.d); + code = tjsonAddDoubleToObject(pJson, jkValueDatum, pNode->datum.d); break; - case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: - code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->datum.p); + code = tjsonAddStringToObject(pJson, jkValueDatum, pNode->datum.p); break; case TSDB_DATA_TYPE_JSON: case TSDB_DATA_TYPE_DECIMAL: @@ -676,47 +1052,60 @@ static int32_t valueNodeToJson(const void* pObj, SJson* pJson) { break; } - return code; + return code ; } -static int32_t jsonToValueNode(const SJson* pJson, void* pObj) { - SValueNode* pNode = (SValueNode*)pObj; +static int32_t valueNodeToJson(const void* pObj, SJson* pJson) { + const SValueNode* pNode = (const SValueNode*)pObj; - int32_t code = jsonToExprNode(pJson, pObj); + int32_t code = exprNodeToJson(pObj, pJson); if (TSDB_CODE_SUCCESS == code) { - code = tjsonDupStringValue(pJson, jkValueLiteral, &pNode->literal); + code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->literal); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetBoolValue(pJson, jkValueDuration, &pNode->isDuration); + code = tjsonAddBoolToObject(pJson, jkValueDuration, pNode->isDuration); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkValueTranslate, pNode->translate); } + if (TSDB_CODE_SUCCESS == code && pNode->translate) { + code = datumToJson(pNode, pJson); + } + + return code; +} + +static int32_t jsonToDatum(const SJson* pJson, void* pObj) { + SValueNode* pNode = (SValueNode*)pObj; + + int32_t code = TSDB_CODE_SUCCESS; switch (pNode->node.resType.type) { case TSDB_DATA_TYPE_NULL: break; case TSDB_DATA_TYPE_BOOL: - code = tjsonGetBoolValue(pJson, jkValueDuration, &pNode->datum.b); + code = tjsonGetBoolValue(pJson, jkValueDatum, &pNode->datum.b); break; case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: case TSDB_DATA_TYPE_INT: case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TIMESTAMP: - code = tjsonGetBigIntValue(pJson, jkValueDuration, &pNode->datum.i); + code = tjsonGetBigIntValue(pJson, jkValueDatum, &pNode->datum.i); break; case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_UBIGINT: - code = tjsonGetUBigIntValue(pJson, jkValueDuration, &pNode->datum.u); + code = tjsonGetUBigIntValue(pJson, jkValueDatum, &pNode->datum.u); break; case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_DOUBLE: - code = tjsonGetDoubleValue(pJson, jkValueDuration, &pNode->datum.d); + code = tjsonGetDoubleValue(pJson, jkValueDatum, &pNode->datum.d); break; - case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: - code = tjsonDupStringValue(pJson, jkValueLiteral, &pNode->datum.p); + code = tjsonDupStringValue(pJson, jkValueDatum, &pNode->datum.p); break; case TSDB_DATA_TYPE_JSON: case TSDB_DATA_TYPE_DECIMAL: @@ -729,6 +1118,26 @@ static int32_t jsonToValueNode(const SJson* pJson, void* pObj) { return code; } +static int32_t jsonToValueNode(const SJson* pJson, void* pObj) { + SValueNode* pNode = (SValueNode*)pObj; + + int32_t code = jsonToExprNode(pJson, pObj); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonDupStringValue(pJson, jkValueLiteral, &pNode->literal); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkValueDuration, &pNode->isDuration); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkValueTranslate, &pNode->translate); + } + if (TSDB_CODE_SUCCESS == code && pNode->translate) { + code = jsonToDatum(pJson, pNode); + } + + return code; +} + static const char* jkOperatorType = "OpType"; static const char* jkOperatorLeft = "Left"; static const char* jkOperatorRight = "Right"; @@ -861,6 +1270,31 @@ static int32_t groupingSetNodeToJson(const void* pObj, SJson* pJson) { return code; } +static const char* jkNodeListDataType = "DataType"; +static const char* jkNodeListNodeList = "NodeList"; + +static int32_t nodeListNodeToJson(const void* pObj, SJson* pJson) { + const SNodeListNode* pNode = (const SNodeListNode*)pObj; + + int32_t code = tjsonAddObject(pJson, jkNodeListDataType, dataTypeToJson, &pNode->dataType); + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkNodeListNodeList, pNode->pNodeList); + } + + return code; +} + +static int32_t jsonToNodeListNode(const SJson* pJson, void* pObj) { + SNodeListNode* pNode = (SNodeListNode*)pObj; + + int32_t code = tjsonToObject(pJson, jkNodeListDataType, jsonToDataType, &pNode->dataType); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkNodeListNodeList, &pNode->pNodeList); + } + + return code; +} + static const char* jkTargetDataBlockId = "DataBlockId"; static const char* jkTargetSlotId = "SlotId"; static const char* jkTargetExpr = "Expr"; @@ -932,13 +1366,50 @@ static int32_t jsonToSlotDescNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkDownstreamSourceAddr = "Addr"; +static const char* jkDownstreamSourceTaskId = "TaskId"; +static const char* jkDownstreamSourceSchedId = "SchedId"; + +static int32_t downstreamSourceNodeToJson(const void* pObj, SJson* pJson) { + const SDownstreamSourceNode* pNode = (const SDownstreamSourceNode*)pObj; + + int32_t code = tjsonAddObject(pJson, jkDownstreamSourceAddr, queryNodeAddrToJson, &pNode->addr); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceTaskId, pNode->taskId); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceSchedId, pNode->schedId); + } + + return code; +} + +static int32_t jsonToDownstreamSourceNode(const SJson* pJson, void* pObj) { + SDownstreamSourceNode* pNode = (SDownstreamSourceNode*)pObj; + + int32_t code = tjsonToObject(pJson, jkDownstreamSourceAddr, jsonToQueryNodeAddr, &pNode->addr); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetUBigIntValue(pJson, jkDownstreamSourceTaskId, &pNode->taskId); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetUBigIntValue(pJson, jkDownstreamSourceSchedId, &pNode->schedId); + } + + return code; +} + static const char* jkDataBlockDescDataBlockId = "DataBlockId"; static const char* jkDataBlockDescSlots = "Slots"; +static const char* jkDataBlockResultRowSize = "ResultRowSize"; static int32_t dataBlockDescNodeToJson(const void* pObj, SJson* pJson) { const SDataBlockDescNode* pNode = (const SDataBlockDescNode*)pObj; int32_t code = tjsonAddIntegerToObject(pJson, jkDataBlockDescDataBlockId, pNode->dataBlockId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkDataBlockResultRowSize, pNode->resultRowSize); + } + if (TSDB_CODE_SUCCESS == code) { code = nodeListToJson(pJson, jkDataBlockDescSlots, pNode->pSlots); } @@ -950,6 +1421,10 @@ static int32_t jsonToDataBlockDescNode(const SJson* pJson, void* pObj) { SDataBlockDescNode* pNode = (SDataBlockDescNode*)pObj; int32_t code = tjsonGetSmallIntValue(pJson, jkDataBlockDescDataBlockId, &pNode->dataBlockId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkDataBlockResultRowSize, &pNode->resultRowSize); + } + if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeList(pJson, jkDataBlockDescSlots, &pNode->pSlots); } @@ -1030,21 +1505,32 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { case QUERY_NODE_STATE_WINDOW: case QUERY_NODE_SESSION_WINDOW: case QUERY_NODE_INTERVAL_WINDOW: + break; case QUERY_NODE_NODE_LIST: + return nodeListNodeToJson(pObj, pJson); case QUERY_NODE_FILL: - case QUERY_NODE_TARGET: - return targetNodeToJson(pObj, pJson); case QUERY_NODE_RAW_EXPR: break; + case QUERY_NODE_TARGET: + return targetNodeToJson(pObj, pJson); case QUERY_NODE_DATABLOCK_DESC: return dataBlockDescNodeToJson(pObj, pJson); case QUERY_NODE_SLOT_DESC: return slotDescNodeToJson(pObj, pJson); + case QUERY_NODE_COLUMN_DEF: + break; + case QUERY_NODE_DOWNSTREAM_SOURCE: + return downstreamSourceNodeToJson(pObj, pJson); case QUERY_NODE_SET_OPERATOR: break; case QUERY_NODE_SELECT_STMT: return selectStmtTojson(pObj, pJson); - case QUERY_NODE_SHOW_STMT: + case QUERY_NODE_VNODE_MODIF_STMT: + case QUERY_NODE_CREATE_DATABASE_STMT: + case QUERY_NODE_CREATE_TABLE_STMT: + case QUERY_NODE_USE_DATABASE_STMT: + case QUERY_NODE_SHOW_DATABASES_STMT: + case QUERY_NODE_SHOW_TABLES_STMT: break; case QUERY_NODE_LOGIC_PLAN_SCAN: return logicScanNodeToJson(pObj, pJson); @@ -1054,19 +1540,41 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { return logicAggNodeToJson(pObj, pJson); case QUERY_NODE_LOGIC_PLAN_PROJECT: return logicProjectNodeToJson(pObj, pJson); + case QUERY_NODE_LOGIC_PLAN_VNODE_MODIF: + case QUERY_NODE_LOGIC_SUBPLAN: + case QUERY_NODE_LOGIC_PLAN: + break; case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: return physiTagScanNodeToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: return physiTableScanNodeToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN: + break; case QUERY_NODE_PHYSICAL_PLAN_PROJECT: return physiProjectNodeToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_JOIN: return physiJoinNodeToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_AGG: return physiAggNodeToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: + return physiExchangeNodeToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN_SORT: + break; + case QUERY_NODE_PHYSICAL_PLAN_INTERVAL: + return physiIntervalNodeToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: + return physiDispatchNodeToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN_INSERT: + break; + case QUERY_NODE_PHYSICAL_SUBPLAN: + return subplanToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN: + return planToJson(pObj, pJson); default: break; } + nodesWarn("specificNodeToJson unknown node = %s", nodesNodeName(nodeType(pObj))); return TSDB_CODE_SUCCESS; } @@ -1093,7 +1601,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { // case QUERY_NODE_STATE_WINDOW: // case QUERY_NODE_SESSION_WINDOW: // case QUERY_NODE_INTERVAL_WINDOW: - // case QUERY_NODE_NODE_LIST: + case QUERY_NODE_NODE_LIST: + return jsonToNodeListNode(pJson, pObj); // case QUERY_NODE_FILL: case QUERY_NODE_TARGET: return jsonToTargetNode(pJson, pObj); @@ -1103,12 +1612,12 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { return jsonToDataBlockDescNode(pJson, pObj); case QUERY_NODE_SLOT_DESC: return jsonToSlotDescNode(pJson, pObj); + case QUERY_NODE_DOWNSTREAM_SOURCE: + return jsonToDownstreamSourceNode(pJson, pObj); // case QUERY_NODE_SET_OPERATOR: // break; // case QUERY_NODE_SELECT_STMT: // return jsonToSelectStmt(pJson, pObj); - // case QUERY_NODE_SHOW_STMT: - // break; // case QUERY_NODE_LOGIC_PLAN_SCAN: // return jsonToLogicScanNode(pJson, pObj); // case QUERY_NODE_LOGIC_PLAN_JOIN: @@ -1127,13 +1636,22 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { return jsonToPhysiJoinNode(pJson, pObj); case QUERY_NODE_PHYSICAL_PLAN_AGG: return jsonToPhysiAggNode(pJson, pObj); + case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: + return jsonToPhysiExchangeNode(pJson, pObj); + case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: + return jsonToPhysiDispatchNode(pJson, pObj); + case QUERY_NODE_PHYSICAL_SUBPLAN: + return jsonToSubplan(pJson, pObj); + case QUERY_NODE_PHYSICAL_PLAN: + return jsonToPlan(pJson, pObj); default: break; } + nodesWarn("jsonToSpecificNode unknown node = %s", nodesNodeName(nodeType(pObj))); return TSDB_CODE_SUCCESS; } -static const char* jkNodeType = "Type"; +static const char* jkNodeType = "NodeType"; static const char* jkNodeName = "Name"; static int32_t nodeToJson(const void* pObj, SJson* pJson) { @@ -1141,10 +1659,13 @@ static int32_t nodeToJson(const void* pObj, SJson* pJson) { int32_t code = tjsonAddIntegerToObject(pJson, jkNodeType, pNode->type); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkNodeName, nodeName(pNode->type)); + code = tjsonAddStringToObject(pJson, jkNodeName, nodesNodeName(pNode->type)); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddObject(pJson, nodeName(pNode->type), specificNodeToJson, pNode); + code = tjsonAddObject(pJson, nodesNodeName(pNode->type), specificNodeToJson, pNode); + if (TSDB_CODE_SUCCESS != code) { + nodesError("%s ToJson error", nodesNodeName(pNode->type)); + } } return code; @@ -1157,7 +1678,10 @@ static int32_t jsonToNode(const SJson* pJson, void* pObj) { int32_t code = tjsonGetIntValue(pJson, jkNodeType, &val); pNode->type = val; if (TSDB_CODE_SUCCESS == code) { - code = tjsonToObject(pJson, nodeName(pNode->type), jsonToSpecificNode, pNode); + code = tjsonToObject(pJson, nodesNodeName(pNode->type), jsonToSpecificNode, pNode); + if (TSDB_CODE_SUCCESS != code) { + nodesError("%s toNode error", nodesNodeName(pNode->type)); + } } return code; @@ -1180,14 +1704,15 @@ static int32_t makeNodeByJson(const SJson* pJson, SNode** pNode) { static int32_t jsonToNodeObject(const SJson* pJson, const char* pName, SNode** pNode) { SJson* pJsonNode = tjsonGetObjectItem(pJson, pName); if (NULL == pJsonNode) { - return TSDB_CODE_FAILED; + return TSDB_CODE_SUCCESS; } return makeNodeByJson(pJsonNode, pNode); } -int32_t nodesNodeToString(const SNode* pNode, bool format, char** pStr, int32_t* pLen) { +int32_t nodesNodeToString(const SNodeptr pNode, bool format, char** pStr, int32_t* pLen) { if (NULL == pNode || NULL == pStr || NULL == pLen) { - return TSDB_CODE_SUCCESS; + terrno = TSDB_CODE_FAILED; + return TSDB_CODE_FAILED; } SJson* pJson = tjsonCreateObject(); diff --git a/source/libs/nodes/src/nodesEqualFuncs.c b/source/libs/nodes/src/nodesEqualFuncs.c index fb2463d350841c72b162cd73fe817b63bbfafda8..4185754355ddfd98fc9c7243ab961ed727a8d4d4 100644 --- a/source/libs/nodes/src/nodesEqualFuncs.c +++ b/source/libs/nodes/src/nodesEqualFuncs.c @@ -95,7 +95,7 @@ static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) { return true; } -bool nodesEqualNode(const SNode* a, const SNode* b) { +bool nodesEqualNode(const SNodeptr a, const SNodeptr b) { if (a == b) { return true; } diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c index 5c81cce94aa66f8b082e686c509fef483eff13e2..e3c2dff1208b427db0df79dfe1eafd2fb7682c2b 100644 --- a/source/libs/nodes/src/nodesTraverseFuncs.c +++ b/source/libs/nodes/src/nodesTraverseFuncs.c @@ -129,7 +129,7 @@ static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FNodeWalke return DEAL_RES_CONTINUE; } -void nodesWalkNode(SNode* pNode, FNodeWalker walker, void* pContext) { +void nodesWalkNode(SNodeptr pNode, FNodeWalker walker, void* pContext) { (void)walkNode(pNode, TRAVERSAL_PREORDER, walker, pContext); } @@ -137,7 +137,7 @@ void nodesWalkList(SNodeList* pNodeList, FNodeWalker walker, void* pContext) { (void)walkList(pNodeList, TRAVERSAL_PREORDER, walker, pContext); } -void nodesWalkNodePostOrder(SNode* pNode, FNodeWalker walker, void* pContext) { +void nodesWalkNodePostOrder(SNodeptr pNode, FNodeWalker walker, void* pContext) { (void)walkNode(pNode, TRAVERSAL_POSTORDER, walker, pContext); } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index eac5606bd62e2a3d4b1868359483d6e30caca90c..0adbf8cb2f0afbd0ec64c1cb5f1876e8bbbd764d 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -13,11 +13,12 @@ * along with this program. If not, see . */ -#include "querynodes.h" +#include "cmdnodes.h" +#include "nodesUtil.h" #include "plannodes.h" +#include "querynodes.h" #include "taos.h" #include "taoserror.h" -#include "taos.h" #include "thash.h" static SNode* makeNode(ENodeType type, size_t size) { @@ -29,7 +30,7 @@ static SNode* makeNode(ENodeType type, size_t size) { return p; } -SNode* nodesMakeNode(ENodeType type) { +SNodeptr nodesMakeNode(ENodeType type) { switch (type) { case QUERY_NODE_COLUMN: return makeNode(type, sizeof(SColumnNode)); @@ -65,12 +66,62 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SFillNode)); case QUERY_NODE_RAW_EXPR: return makeNode(type, sizeof(SRawExprNode)); + case QUERY_NODE_TARGET: + return makeNode(type, sizeof(STargetNode)); + case QUERY_NODE_DATABLOCK_DESC: + return makeNode(type, sizeof(SDataBlockDescNode)); + case QUERY_NODE_SLOT_DESC: + return makeNode(type, sizeof(SSlotDescNode)); + case QUERY_NODE_COLUMN_DEF: + return makeNode(type, sizeof(SColumnDefNode)); + case QUERY_NODE_DOWNSTREAM_SOURCE: + return makeNode(type, sizeof(SDownstreamSourceNode)); case QUERY_NODE_SET_OPERATOR: return makeNode(type, sizeof(SSetOperator)); case QUERY_NODE_SELECT_STMT: return makeNode(type, sizeof(SSelectStmt)); - // case QUERY_NODE_SHOW_STMT: - // return makeNode(type, sizeof(SShowStmt)); + case QUERY_NODE_VNODE_MODIF_STMT: + return makeNode(type, sizeof(SVnodeModifOpStmt)); + case QUERY_NODE_CREATE_DATABASE_STMT: + return makeNode(type, sizeof(SCreateDatabaseStmt)); + case QUERY_NODE_DROP_DATABASE_STMT: + return makeNode(type, sizeof(SDropDatabaseStmt)); + case QUERY_NODE_SHOW_DATABASES_STMT: + return makeNode(type, sizeof(SShowStmt)); + case QUERY_NODE_CREATE_TABLE_STMT: + return makeNode(type, sizeof(SCreateTableStmt)); + case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: + return makeNode(type, sizeof(SCreateSubTableClause)); + case QUERY_NODE_CREATE_MULTI_TABLE_STMT: + return makeNode(type, sizeof(SCreateMultiTableStmt)); + case QUERY_NODE_DROP_TABLE_CLAUSE: + return makeNode(type, sizeof(SDropTableClause)); + case QUERY_NODE_DROP_TABLE_STMT: + return makeNode(type, sizeof(SDropTableStmt)); + case QUERY_NODE_DROP_SUPER_TABLE_STMT: + return makeNode(type, sizeof(SDropSuperTableStmt)); + case QUERY_NODE_SHOW_TABLES_STMT: + case QUERY_NODE_SHOW_STABLES_STMT: + return makeNode(type, sizeof(SShowStmt)); + case QUERY_NODE_CREATE_USER_STMT: + return makeNode(type, sizeof(SCreateUserStmt)); + case QUERY_NODE_ALTER_USER_STMT: + return makeNode(type, sizeof(SAlterUserStmt)); + case QUERY_NODE_DROP_USER_STMT: + return makeNode(type, sizeof(SDropUserStmt)); + case QUERY_NODE_SHOW_USERS_STMT: + return makeNode(type, sizeof(SShowStmt)); + case QUERY_NODE_USE_DATABASE_STMT: + return makeNode(type, sizeof(SUseDatabaseStmt)); + case QUERY_NODE_CREATE_DNODE_STMT: + return makeNode(type, sizeof(SCreateDnodeStmt)); + case QUERY_NODE_DROP_DNODE_STMT: + return makeNode(type, sizeof(SDropDnodeStmt)); + case QUERY_NODE_SHOW_DNODES_STMT: + return makeNode(type, sizeof(SShowStmt)); + case QUERY_NODE_SHOW_VGROUPS_STMT: + case QUERY_NODE_SHOW_MNODES_STMT: + return makeNode(type, sizeof(SShowStmt)); case QUERY_NODE_LOGIC_PLAN_SCAN: return makeNode(type, sizeof(SScanLogicNode)); case QUERY_NODE_LOGIC_PLAN_JOIN: @@ -79,33 +130,52 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SAggLogicNode)); case QUERY_NODE_LOGIC_PLAN_PROJECT: return makeNode(type, sizeof(SProjectLogicNode)); - case QUERY_NODE_TARGET: - return makeNode(type, sizeof(STargetNode)); - case QUERY_NODE_DATABLOCK_DESC: - return makeNode(type, sizeof(SDataBlockDescNode)); - case QUERY_NODE_SLOT_DESC: - return makeNode(type, sizeof(SSlotDescNode)); + case QUERY_NODE_LOGIC_PLAN_VNODE_MODIF: + return makeNode(type, sizeof(SVnodeModifLogicNode)); + case QUERY_NODE_LOGIC_PLAN_EXCHANGE: + return makeNode(type, sizeof(SExchangeLogicNode)); + case QUERY_NODE_LOGIC_PLAN_WINDOW: + return makeNode(type, sizeof(SWindowLogicNode)); + case QUERY_NODE_LOGIC_SUBPLAN: + return makeNode(type, sizeof(SSubLogicPlan)); + case QUERY_NODE_LOGIC_PLAN: + return makeNode(type, sizeof(SQueryLogicPlan)); case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: return makeNode(type, sizeof(STagScanPhysiNode)); case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: return makeNode(type, sizeof(STableScanPhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN: + return makeNode(type, sizeof(STableSeqScanPhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN: + return makeNode(type, sizeof(SNode)); case QUERY_NODE_PHYSICAL_PLAN_PROJECT: return makeNode(type, sizeof(SProjectPhysiNode)); case QUERY_NODE_PHYSICAL_PLAN_JOIN: return makeNode(type, sizeof(SJoinPhysiNode)); case QUERY_NODE_PHYSICAL_PLAN_AGG: return makeNode(type, sizeof(SAggPhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: + return makeNode(type, sizeof(SExchangePhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_SORT: + return makeNode(type, sizeof(SNode)); + case QUERY_NODE_PHYSICAL_PLAN_INTERVAL: + return makeNode(type, sizeof(SIntervalPhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: + return makeNode(type, sizeof(SDataDispatcherNode)); + case QUERY_NODE_PHYSICAL_PLAN_INSERT: + return makeNode(type, sizeof(SDataInserterNode)); + case QUERY_NODE_PHYSICAL_SUBPLAN: + return makeNode(type, sizeof(SSubplan)); + case QUERY_NODE_PHYSICAL_PLAN: + return makeNode(type, sizeof(SQueryPlan)); default: break; } + nodesError("nodesMakeNode unknown node = %s", nodesNodeName(type)); return NULL; } static EDealRes destroyNode(SNode** pNode, void* pContext) { - if (NULL == pNode || NULL == *pNode) { - return DEAL_RES_IGNORE_CHILD; - } - switch (nodeType(*pNode)) { case QUERY_NODE_VALUE: { SValueNode* pValue = (SValueNode*)*pNode; @@ -118,16 +188,65 @@ static EDealRes destroyNode(SNode** pNode, void* pContext) { break; } case QUERY_NODE_LOGIC_CONDITION: - nodesDestroyList(((SLogicConditionNode*)(*pNode))->pParameterList); + nodesClearList(((SLogicConditionNode*)(*pNode))->pParameterList); break; case QUERY_NODE_FUNCTION: - nodesDestroyList(((SFunctionNode*)(*pNode))->pParameterList); + nodesClearList(((SFunctionNode*)(*pNode))->pParameterList); + break; + case QUERY_NODE_REAL_TABLE: { + SRealTableNode* pReal = (SRealTableNode*)*pNode; + tfree(pReal->pMeta); + tfree(pReal->pVgroupList); + break; + } + case QUERY_NODE_TEMP_TABLE: + nodesDestroyNode(((STempTableNode*)(*pNode))->pSubquery); break; case QUERY_NODE_GROUPING_SET: - nodesDestroyList(((SGroupingSetNode*)(*pNode))->pParameterList); + nodesClearList(((SGroupingSetNode*)(*pNode))->pParameterList); break; case QUERY_NODE_NODE_LIST: - nodesDestroyList(((SNodeListNode*)(*pNode))->pNodeList); + nodesClearList(((SNodeListNode*)(*pNode))->pNodeList); + break; + case QUERY_NODE_SELECT_STMT: { + SSelectStmt* pStmt = (SSelectStmt*)*pNode; + nodesDestroyList(pStmt->pProjectionList); + nodesDestroyNode(pStmt->pFromTable); + nodesDestroyNode(pStmt->pWhere); + nodesDestroyList(pStmt->pPartitionByList); + nodesDestroyNode(pStmt->pWindow); + nodesDestroyList(pStmt->pGroupByList); + nodesDestroyNode(pStmt->pHaving); + nodesDestroyList(pStmt->pOrderByList); + nodesDestroyNode(pStmt->pLimit); + nodesDestroyNode(pStmt->pSlimit); + break; + } + case QUERY_NODE_VNODE_MODIF_STMT: { + SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)*pNode; + size_t size = taosArrayGetSize(pStmt->pDataBlocks); + for (size_t i = 0; i < size; ++i) { + SVgDataBlocks* pVg = taosArrayGetP(pStmt->pDataBlocks, i); + tfree(pVg->pData); + tfree(pVg); + } + taosArrayDestroy(pStmt->pDataBlocks); + break; + } + case QUERY_NODE_CREATE_TABLE_STMT: { + SCreateTableStmt* pStmt = (SCreateTableStmt*)*pNode; + nodesDestroyList(pStmt->pCols); + nodesDestroyList(pStmt->pTags); + break; + } + case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: { + SCreateSubTableClause* pStmt = (SCreateSubTableClause*)*pNode; + nodesDestroyList(pStmt->pSpecificTags); + nodesDestroyList(pStmt->pValsOfTags); + break; + } + case QUERY_NODE_CREATE_MULTI_TABLE_STMT: + nodesDestroyList(((SCreateMultiTableStmt*)(*pNode))->pSubTables); break; default: break; @@ -136,12 +255,11 @@ static EDealRes destroyNode(SNode** pNode, void* pContext) { return DEAL_RES_CONTINUE; } -void nodesDestroyNode(SNode* pNode) { +void nodesDestroyNode(SNodeptr pNode) { if (NULL == pNode) { return; } - - nodesRewriteNodePostOrder(&pNode, destroyNode, NULL); + nodesRewriteNodePostOrder((SNode**)&pNode, destroyNode, NULL); } SNodeList* nodesMakeList() { @@ -152,7 +270,7 @@ SNodeList* nodesMakeList() { return p; } -int32_t nodesListAppend(SNodeList* pList, SNode* pNode) { +int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode) { if (NULL == pList || NULL == pNode) { return TSDB_CODE_SUCCESS; } @@ -173,6 +291,17 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) { return TSDB_CODE_SUCCESS; } +int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode) { + if (NULL == pNode) { + return TSDB_CODE_OUT_OF_MEMORY; + } + int32_t code = nodesListAppend(pList, pNode); + if (TSDB_CODE_SUCCESS != code) { + nodesDestroyNode(pNode); + } + return code; +} + int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) { if (NULL == pTarget || NULL == pSrc) { return TSDB_CODE_SUCCESS; @@ -207,7 +336,7 @@ SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) { return pNext; } -SNode* nodesListGetNode(SNodeList* pList, int32_t index) { +SNodeptr nodesListGetNode(SNodeList* pList, int32_t index) { SNode* node; FOREACH(node, pList) { if (0 == index--) { @@ -218,6 +347,10 @@ SNode* nodesListGetNode(SNodeList* pList, int32_t index) { } void nodesDestroyList(SNodeList* pList) { + if (NULL == pList) { + return; + } + SListCell* pNext = pList->pHead; while (NULL != pNext) { pNext = nodesListErase(pList, pNext); @@ -225,6 +358,20 @@ void nodesDestroyList(SNodeList* pList) { tfree(pList); } +void nodesClearList(SNodeList* pList) { + if (NULL == pList) { + return; + } + + SListCell* pNext = pList->pHead; + while (NULL != pNext) { + SListCell* tmp = pNext; + pNext = pNext->pNext; + tfree(tmp); + } + tfree(pList); +} + void* nodesGetValueFromNode(SValueNode *pNode) { switch (pNode->node.resType.type) { case TSDB_DATA_TYPE_BOOL: @@ -243,7 +390,6 @@ void* nodesGetValueFromNode(SValueNode *pNode) { case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_DOUBLE: return (void*)&pNode->datum.d; - case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: diff --git a/source/libs/nodes/test/nodesTest.cpp b/source/libs/nodes/test/nodesTest.cpp index c116faf4cee3705c9cfdc51f8508411897d65eb4..fd4a9e8c20c3c13ea47b327559748c60a37f04d0 100644 --- a/source/libs/nodes/test/nodesTest.cpp +++ b/source/libs/nodes/test/nodesTest.cpp @@ -36,15 +36,15 @@ static EDealRes rewriterTest(SNode** pNode, void* pContext) { } TEST(NodesTest, traverseTest) { - SNode* pRoot = nodesMakeNode(QUERY_NODE_OPERATOR); + SNode* pRoot = (SNode*)nodesMakeNode(QUERY_NODE_OPERATOR); SOperatorNode* pOp = (SOperatorNode*)pRoot; SOperatorNode* pLeft = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR); - pLeft->pLeft = nodesMakeNode(QUERY_NODE_VALUE); + pLeft->pLeft = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); ((SValueNode*)(pLeft->pLeft))->literal = strdup("10"); - pLeft->pRight = nodesMakeNode(QUERY_NODE_VALUE); + pLeft->pRight = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); ((SValueNode*)(pLeft->pRight))->literal = strdup("5"); pOp->pLeft = (SNode*)pLeft; - pOp->pRight = nodesMakeNode(QUERY_NODE_VALUE); + pOp->pRight = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); ((SValueNode*)(pOp->pRight))->literal = strdup("3"); EXPECT_EQ(nodeType(pRoot), QUERY_NODE_OPERATOR); diff --git a/source/libs/parser/inc/astGenerator.h b/source/libs/parser/inc/astGenerator.h deleted file mode 100644 index 1327259a51b793d152fc7dffc123c55459fe3b26..0000000000000000000000000000000000000000 --- a/source/libs/parser/inc/astGenerator.h +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef TDENGINE_ASTGENERATOR_H -#define TDENGINE_ASTGENERATOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ttoken.h" -#include "tvariant.h" -#include "parser.h" - -#define ParseTOKENTYPE SToken - -#define NON_ARITHMEIC_EXPR 0 -#define NORMAL_ARITHMETIC 1 -#define AGG_ARIGHTMEIC 2 - -enum SQL_NODE_TYPE { - SQL_NODE_TABLE_COLUMN= 1, - SQL_NODE_SQLFUNCTION = 2, - SQL_NODE_VALUE = 3, - SQL_NODE_EXPR = 4, -}; - -enum SQL_FROM_NODE_TYPE { - SQL_FROM_NODE_SUBQUERY = 1, - SQL_FROM_NODE_TABLES = 2, -}; - -enum SQL_UNION_TYPE { - SQL_TYPE_UNIONALL = 1, - SQL_TYPE_UNION = 2, -}; - -extern char tTokenTypeSwitcher[13]; - -#define toTSDBType(x) \ - do { \ - if ((x) >= tListLen(tTokenTypeSwitcher)) { \ - (x) = TSDB_DATA_TYPE_BINARY; \ - } else { \ - (x) = tTokenTypeSwitcher[(x)]; \ - } \ - } while (0) - -#define TPARSER_HAS_TOKEN(_t) ((_t).n > 0) -#define TPARSER_SET_NONE_TOKEN(_t) ((_t).n = 0) - -typedef struct SListItem { - SVariant pVar; - uint8_t sortOrder; -} SListItem; - -typedef struct SIntervalVal { - int32_t token; - SToken interval; - SToken offset; -} SIntervalVal; - -typedef struct SSessionWindowVal { - SToken col; - SToken gap; -} SSessionWindowVal; - -typedef struct SWindowStateVal { - SToken col; -} SWindowStateVal; - -struct SRelationInfo; - -typedef struct SSqlNode { - struct SRelationInfo *from; // from clause SArray - struct SArray *pSelNodeList; // select clause - struct tSqlExpr *pWhere; // where clause [optional] - SArray *pGroupby; // groupby clause, only for tags[optional], SArray - SArray *pSortOrder; // orderby [optional], SArray - SArray *fillType; // fill type[optional], SArray - SIntervalVal interval; // (interval, interval_offset) [optional] - SSessionWindowVal sessionVal; // session window [optional] - SWindowStateVal windowstateVal; // window_state(col) [optional] - SToken sliding; // sliding window [optional] - SLimit limit; // limit offset [optional] - SLimit slimit; // group limit offset [optional] - SToken sqlstr; // sql string in select clause - struct tSqlExpr *pHaving; // having clause [optional] -} SSqlNode; - -typedef struct SSubclause { - int32_t unionType; - SArray *node; -} SSubclause; - -typedef struct SRelElement { - union { - SToken tableName; - SSubclause *pSubquery; - }; - - SToken aliasName; -} SRelElement; - -typedef struct SRelationInfo { - int32_t type; // nested query|table name list - SArray *list; // SArray -} SRelationInfo; - -typedef struct SCreatedTableInfo { - SToken name; // table name token - SToken stbName; // super table name token , for using clause - SArray *pTagNames; // create by using super table, tag name - SArray *pTagVals; // create by using super table, tag value. SArray - char *fullname; // table full name - int8_t igExist; // ignore if exists -} SCreatedTableInfo; - -typedef struct SCreateTableSql { - SToken name; // table name, create table [name] xxx - int8_t type; // create normal table/from super table/ stream - bool existCheck; - - struct { - SArray *pTagColumns; // SArray - SArray *pColumns; // SArray - } colInfo; - - SArray *childTableInfo; // SArray - SSqlNode *pSelect; -} SCreateTableSql; - -typedef struct SAlterTableInfo { - SToken name; - int16_t tableType; - int16_t type; - STagData tagData; - SArray *pAddColumns; // SArray - SArray *varList; // set t=val or: change src dst, SArray -} SAlterTableInfo; - -typedef struct SCreateDbInfo { - SToken dbname; - int32_t replica; - int32_t cacheBlockSize; - int32_t numOfVgroups; - int32_t numOfBlocks; - int32_t daysPerFile; - int32_t minRowsPerBlock; - int32_t maxRowsPerBlock; - int32_t fsyncPeriod; - int64_t commitTime; - int32_t walLevel; - int32_t quorum; - int32_t compressionLevel; - SToken precision; - bool ignoreExists; - int8_t update; - int8_t cachelast; - SArray *keep; - int8_t streamMode; -} SCreateDbInfo; - -typedef struct SCreateFuncInfo { - SToken name; - SToken path; - int32_t type; - int32_t bufSize; - SField output; -} SCreateFuncInfo; - -typedef struct SCreateAcctInfo { - int32_t maxUsers; - int32_t maxDbs; - int32_t maxTimeSeries; - int32_t maxStreams; - int32_t maxPointsPerSecond; - int64_t maxStorage; - int64_t maxQueryTime; - int32_t maxConnections; - SToken stat; -} SCreateAcctInfo; - -typedef struct SShowInfo { - uint8_t showType; - SToken prefix; - SToken pattern; -} SShowInfo; - -typedef struct SUserInfo { - SToken user; - SToken passwd; - SToken privilege; - int16_t type; -} SUserInfo; - -typedef struct SMiscInfo { - SArray *a; // SArray - bool existsCheck; - int16_t dbType; - int16_t tableType; - SUserInfo user; - union { - SCreateDbInfo dbOpt; - SCreateAcctInfo acctOpt; - SCreateFuncInfo funcOpt; - SShowInfo showOpt; - SToken id; - }; -} SMiscInfo; - -typedef struct SSqlInfo { - int32_t type; - bool valid; - SSubclause sub; - char msg[256]; - SArray *funcs; - union { - SCreateTableSql *pCreateTableInfo; - SAlterTableInfo *pAlterInfo; - SMiscInfo *pMiscInfo; - }; -} SSqlInfo; - -typedef struct tSqlExpr { - uint16_t type; // sql node type - uint32_t tokenId; // TK_LE: less than(binary expr) - - // The complete string of the function(col, param), and the function name is kept in exprToken - struct { - SToken operand; - struct SArray *paramList; // function parameters list - } Expr; - - SToken columnName; // table column info - SVariant value; // the use input value - SToken exprToken; // original sql expr string or function name of sql function - struct tSqlExpr *pLeft; // the left child - struct tSqlExpr *pRight; // the right child -} tSqlExpr; - -// used in select clause. select from xxx -typedef struct tSqlExprItem { - tSqlExpr *pNode; // The list of expressions - int32_t functionId; - char *aliasName; // alias name, null-terminated string - bool distinct; -} tSqlExprItem; - -SArray *tListItemAppend(SArray *pList, SVariant *pVar, uint8_t sortOrder); -SArray *tListItemInsert(SArray *pList, SVariant *pVar, uint8_t sortOrder, int32_t index); -SArray *tListItemAppendToken(SArray *pList, SToken *pAliasToken, uint8_t sortOrder); - -SRelationInfo *setTableNameList(SRelationInfo *pRelationInfo, SToken *pName, SToken *pAlias); -void * destroyRelationInfo(SRelationInfo *pFromInfo); -SRelationInfo *addSubquery(SRelationInfo *pRelationInfo, SSubclause *pSub, SToken *pAlias); - -// sql expr leaf node -tSqlExpr *tSqlExprCreateIdValue(SToken *pToken, int32_t optrType); -tSqlExpr *tSqlExprCreateFunction(SArray *pParam, SToken *pFuncToken, SToken *endToken, int32_t optType); -SArray * tRecordFuncName(SArray *pList, SToken *pToken); - -tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType); -tSqlExpr *tSqlExprClone(tSqlExpr *pSrc); -void tSqlExprCompact(tSqlExpr **pExpr); -bool tSqlExprIsLeaf(tSqlExpr *pExpr); -bool tSqlExprIsParentOfLeaf(tSqlExpr *pExpr); -void tSqlExprDestroy(tSqlExpr *pExpr); -SArray * tSqlExprListAppend(SArray *pList, tSqlExpr *pNode, SToken *pDistinct, SToken *pToken); -void tSqlExprListDestroy(SArray *pList); -void tSqlExprEvaluate(tSqlExpr* pExpr); - -SSqlNode *tSetQuerySqlNode(SToken *pSelectToken, SArray *pSelNodeList, SRelationInfo *pFrom, tSqlExpr *pWhere, - SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *ps, - SWindowStateVal *pw, SToken *pSliding, SArray *pFill, SLimit *pLimit, SLimit *pgLimit, tSqlExpr *pHaving); -int32_t tSqlExprCompare(tSqlExpr *left, tSqlExpr *right); - -SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SSqlNode *pSelect, int32_t type); - -SAlterTableInfo * tSetAlterTableInfo(SToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableType); -SCreatedTableInfo createNewChildTableInfo(SToken *pTableName, SArray *pTagNames, SArray *pTagVals, SToken *pToken, - SToken *igExists); -/*! - * test - * @param pSqlNode - */ -void destroyAllSqlNode(struct SSubclause *pSqlNode); -void destroySqlNode(SSqlNode *pSql); -void freeCreateTableInfo(void* p); - -SSqlInfo *setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SToken *pTableName, int32_t type); -SSubclause* setSubclause(SSubclause* sub, void *pSqlNode); -SSubclause* appendSelectClause(SSubclause *sub, int32_t unionType, void *pSubclause); - -void setCreatedTableName(SSqlInfo *pInfo, SToken *pTableNameToken, SToken *pIfNotExists); -void* destroyCreateTableSql(SCreateTableSql* pCreate); -void setDropFuncInfo(SSqlInfo *pInfo, int32_t type, SToken* pToken); -void setCreateFuncInfo(SSqlInfo *pInfo, int32_t type, SToken *pName, SToken *pPath, SField *output, SToken* bufSize, int32_t funcType); - -void destroySqlInfo(SSqlInfo *pInfo); - -void setDCLSqlElems(SSqlInfo *pInfo, int32_t type, int32_t nParams, ...); -void setDropDbTableInfo(SSqlInfo *pInfo, int32_t type, SToken* pToken, SToken* existsCheck,int16_t dbType,int16_t tableType); -void setShowOptions(SSqlInfo *pInfo, int32_t type, SToken* prefix, SToken* pPatterns); - -void setCreateDbInfo(SSqlInfo *pInfo, int32_t type, SToken *pToken, SCreateDbInfo *pDB, SToken *pIgExists); - -void setCreateAcctSql(SSqlInfo *pInfo, int32_t type, SToken *pName, SToken *pPwd, SCreateAcctInfo *pAcctInfo); -void setCreateUserSql(SSqlInfo *pInfo, SToken *pName, SToken *pPasswd); -void setKillSql(SSqlInfo *pInfo, int32_t type, SToken *ip); -void setAlterUserSql(SSqlInfo *pInfo, int16_t type, SToken *pName, SToken* pPwd, SToken *pPrivilege); - -void setCompactVnodeSql(SSqlInfo *pInfo, int32_t type, SArray *pParam); - -void setDefaultCreateDbOption(SCreateDbInfo *pDBInfo); -void setDefaultCreateTopicOption(SCreateDbInfo *pDBInfo); - -// prefix show db.tables; -void tSetDbName(SToken *pCpxName, SToken *pDb); - -void tSetColumnInfo(struct SField *pField, SToken *pName, struct SField *pType); -void tSetColumnType(struct SField *pField, SToken *type); - -/** - * The main parse function. - * @param yyp The parser - * @param yymajor The major token code number - * @param yyminor The value for the token - */ -void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor, SSqlInfo *); - -/** - * Free the allocated resources in case of failure. - * @param p The parser to be deleted - * @param freeProc Function used to reclaim memory - */ -void ParseFree(void *p, void (*freeProc)(void *)); - -/** - * Allocated callback function. - * @param mallocProc The parser allocator - * @return - */ -void *ParseAlloc(void *(*mallocProc)(size_t)); - -/** - * - * @param str sql string - * @return sql ast - */ -SSqlInfo doGenerateAST(const char *str); - -#ifdef __cplusplus -} -#endif - -#endif // TDENGINE_ASTGENERATOR_H diff --git a/source/libs/parser/inc/astToMsg.h b/source/libs/parser/inc/astToMsg.h deleted file mode 100644 index 77d6900acfb1396f13b9657341948ec98c6c804a..0000000000000000000000000000000000000000 --- a/source/libs/parser/inc/astToMsg.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef TDENGINE_ASTTOMSG_H -#define TDENGINE_ASTTOMSG_H - -#include "parserInt.h" -#include "tmsg.h" - -char* buildUserManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen); -char* buildAcctManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen); -char* buildDropUserMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen); -char* buildShowMsg(SShowInfo* pShowInfo, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf); -char* buildCreateDbMsg(SCreateDbInfo* pCreateDbInfo, int32_t* outputLen, SParseContext* pCtx, SMsgBuf* pMsgBuf); -char* buildCreateStbReq(SCreateTableSql* pCreateTableSql, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf); -char* buildDropStableReq(SSqlInfo* pInfo, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf); -char* buildCreateDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf); -char* buildDropDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf); - -#endif // TDENGINE_ASTTOMSG_H diff --git a/source/libs/parser/inc/insertParser.h b/source/libs/parser/inc/insertParser.h deleted file mode 100644 index 796bd9b429be6ab2eb4d289c672db4afb64c8791..0000000000000000000000000000000000000000 --- a/source/libs/parser/inc/insertParser.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef TDENGINE_INSERTPARSER_H -#define TDENGINE_INSERTPARSER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "parser.h" - -int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo); - -#ifdef __cplusplus -} -#endif - -#endif // TDENGINE_INSERTPARSER_H diff --git a/source/libs/parser/inc/new_sql.y b/source/libs/parser/inc/new_sql.y deleted file mode 100644 index 065cb9565098fe5279cedb82d5edb102cd87a692..0000000000000000000000000000000000000000 --- a/source/libs/parser/inc/new_sql.y +++ /dev/null @@ -1,436 +0,0 @@ -//lemon parser file to generate sql parse by using finite-state-machine code used to parse sql -//usage: lemon sql.y - -%name NewParse - -%token_prefix NEW_TK_ -%token_type { SToken } -%default_type { SNode* } -%default_destructor { PARSER_DESTRUCTOR_TRACE; nodesDestroyNode($$); } - -%extra_argument { SAstCreateContext* pCxt } - -%include { -#include -#include -#include -#include -#include - -#include "nodes.h" -#include "ttoken.h" -#include "ttokendef.h" -#include "astCreateFuncs.h" - -#if 0 -#define PARSER_TRACE printf("lemon rule = %s\n", yyRuleName[yyruleno]) -#define PARSER_DESTRUCTOR_TRACE printf("lemon destroy token = %s\n", yyTokenName[yymajor]) -#define PARSER_COMPLETE printf("parsing complete!\n" ) -#else -#define PARSER_TRACE -#define PARSER_DESTRUCTOR_TRACE -#define PARSER_COMPLETE -#endif -} - -%syntax_error { - if(TOKEN.z) { - char msg[] = "syntax error near \"%s\""; - int32_t sqlLen = strlen(&TOKEN.z[0]); - - if (sqlLen + sizeof(msg)/sizeof(msg[0]) + 1 > pCxt->pQueryCxt->msgLen) { - char tmpstr[128] = {0}; - memcpy(tmpstr, &TOKEN.z[0], sizeof(tmpstr)/sizeof(tmpstr[0]) - 1); - sprintf(pCxt->pQueryCxt->pMsg, msg, tmpstr); - } else { - sprintf(pCxt->pQueryCxt->pMsg, msg, &TOKEN.z[0]); - } - } else { - sprintf(pCxt->pQueryCxt->pMsg, "Incomplete SQL statement"); - } - pCxt->valid = false; -} - -%parse_accept { PARSER_COMPLETE; } - -%left OR. -%left AND. -//%right NOT. -%left UNION ALL MINUS EXCEPT INTERSECT. -//%left BITAND BITOR LSHIFT RSHIFT. -%left NK_PLUS NK_MINUS. -//%left DIVIDE TIMES. -%left NK_STAR NK_SLASH NK_REM. -//%left CONCAT. -//%right UMINUS UPLUS BITNOT. - -cmd ::= SHOW DATABASES. { PARSER_TRACE; createShowStmt(pCxt, SHOW_TYPE_DATABASE); } -cmd ::= query_expression(A). { PARSER_TRACE; pCxt->pRootNode = A; } - -/************************************************ literal *************************************************************/ -literal(A) ::= NK_INTEGER(B). { PARSER_TRACE; A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B)); } -literal(A) ::= NK_FLOAT(B). { PARSER_TRACE; A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B)); } -literal(A) ::= NK_STRING(B). { PARSER_TRACE; A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &B)); } -literal(A) ::= NK_BOOL(B). { PARSER_TRACE; A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &B)); } -literal(A) ::= TIMESTAMP(B) NK_STRING(C). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &B, &C, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &C)); } -literal(A) ::= duration_literal(B). { PARSER_TRACE; A = B; } - -duration_literal(A) ::= NK_VARIABLE(B). { PARSER_TRACE; A = createRawExprNode(pCxt, &B, createDurationValueNode(pCxt, &B)); } - -%type literal_list { SNodeList* } -%destructor literal_list { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -literal_list(A) ::= literal(B). { PARSER_TRACE; A = createNodeList(pCxt, releaseRawExprNode(pCxt, B)); } -literal_list(A) ::= literal_list(B) NK_COMMA literal(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, releaseRawExprNode(pCxt, C)); } - -/************************************************ names and identifiers ***********************************************/ -%type db_name { SToken } -%destructor db_name { PARSER_DESTRUCTOR_TRACE; } -db_name(A) ::= NK_ID(B). { PARSER_TRACE; A = B; } - -%type table_name { SToken } -%destructor table_name { PARSER_DESTRUCTOR_TRACE; } -table_name(A) ::= NK_ID(B). { PARSER_TRACE; A = B; } - -%type column_name { SToken } -%destructor column_name { PARSER_DESTRUCTOR_TRACE; } -column_name(A) ::= NK_ID(B). { PARSER_TRACE; A = B; } - -%type function_name { SToken } -%destructor function_name { PARSER_DESTRUCTOR_TRACE; } -function_name(A) ::= NK_ID(B). { PARSER_TRACE; A = B; } - -%type table_alias { SToken } -%destructor table_alias { PARSER_DESTRUCTOR_TRACE; } -table_alias(A) ::= NK_ID(B). { PARSER_TRACE; A = B; } - -%type column_alias { SToken } -%destructor column_alias { PARSER_DESTRUCTOR_TRACE; } -column_alias(A) ::= NK_ID(B). { PARSER_TRACE; A = B; } - -/************************************************ expression **********************************************************/ -expression(A) ::= literal(B). { PARSER_TRACE; A = B; } -//expression(A) ::= NK_QUESTION(B). { PARSER_TRACE; A = B; } -//expression(A) ::= pseudo_column(B). { PARSER_TRACE; A = B; } -expression(A) ::= column_reference(B). { PARSER_TRACE; A = B; } -expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); } -expression(A) ::= function_name(B) NK_LP NK_STAR(C) NK_RP(D). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, createNodeList(pCxt, createColumnNode(pCxt, NULL, &C)))); } -//expression(A) ::= cast_expression(B). { PARSER_TRACE; A = B; } -//expression(A) ::= case_expression(B). { PARSER_TRACE; A = B; } -expression(A) ::= subquery(B). { PARSER_TRACE; A = B; } -expression(A) ::= NK_LP(B) expression(C) NK_RP(D). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); } -expression(A) ::= NK_PLUS(B) expression(C). { - PARSER_TRACE; - SToken t = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &B, &t, releaseRawExprNode(pCxt, C)); - } -expression(A) ::= NK_MINUS(B) expression(C). { - PARSER_TRACE; - SToken t = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &B, &t, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, C), NULL)); - } -expression(A) ::= expression(B) NK_PLUS expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } -expression(A) ::= expression(B) NK_MINUS expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } -expression(A) ::= expression(B) NK_STAR expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } -expression(A) ::= expression(B) NK_SLASH expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } -expression(A) ::= expression(B) NK_REM expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MOD, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } - -%type expression_list { SNodeList* } -%destructor expression_list { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -expression_list(A) ::= expression(B). { PARSER_TRACE; A = createNodeList(pCxt, releaseRawExprNode(pCxt, B)); } -expression_list(A) ::= expression_list(B) NK_COMMA expression(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, releaseRawExprNode(pCxt, C)); } - -column_reference(A) ::= column_name(B). { PARSER_TRACE; A = createRawExprNode(pCxt, &B, createColumnNode(pCxt, NULL, &B)); } -column_reference(A) ::= table_name(B) NK_DOT column_name(C). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &B, &C, createColumnNode(pCxt, &B, &C)); } - -//pseudo_column(A) ::= NK_NOW. { PARSER_TRACE; A = createFunctionNode(pCxt, NULL, NULL); } - -/************************************************ predicate ***********************************************************/ -predicate(A) ::= expression(B) compare_op(C) expression(D). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, D); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); - } -//predicate(A) ::= expression(B) compare_op sub_type expression(B). -predicate(A) ::= expression(B) BETWEEN expression(C) AND expression(D). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, D); - A = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D))); - } -predicate(A) ::= expression(B) NOT BETWEEN expression(C) AND expression(D). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, D); - A = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); - } -predicate(A) ::= expression(B) IS NULL(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, B), NULL)); - } -predicate(A) ::= expression(B) IS NOT NULL(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, B), NULL)); - } -predicate(A) ::= expression(B) in_op(C) in_predicate_value(D). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, D); - A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); - } - -%type compare_op { EOperatorType } -%destructor compare_op { PARSER_DESTRUCTOR_TRACE; } -compare_op(A) ::= NK_LT. { PARSER_TRACE; A = OP_TYPE_LOWER_THAN; } -compare_op(A) ::= NK_GT. { PARSER_TRACE; A = OP_TYPE_GREATER_THAN; } -compare_op(A) ::= NK_LE. { PARSER_TRACE; A = OP_TYPE_LOWER_EQUAL; } -compare_op(A) ::= NK_GE. { PARSER_TRACE; A = OP_TYPE_GREATER_EQUAL; } -compare_op(A) ::= NK_NE. { PARSER_TRACE; A = OP_TYPE_NOT_EQUAL; } -compare_op(A) ::= NK_EQ. { PARSER_TRACE; A = OP_TYPE_EQUAL; } -compare_op(A) ::= LIKE. { PARSER_TRACE; A = OP_TYPE_LIKE; } -compare_op(A) ::= NOT LIKE. { PARSER_TRACE; A = OP_TYPE_NOT_LIKE; } -compare_op(A) ::= MATCH. { PARSER_TRACE; A = OP_TYPE_MATCH; } -compare_op(A) ::= NMATCH. { PARSER_TRACE; A = OP_TYPE_NMATCH; } - -%type in_op { EOperatorType } -%destructor in_op { PARSER_DESTRUCTOR_TRACE; } -in_op(A) ::= IN. { PARSER_TRACE; A = OP_TYPE_IN; } -in_op(A) ::= NOT IN. { PARSER_TRACE; A = OP_TYPE_NOT_IN; } - -in_predicate_value(A) ::= NK_LP(C) expression_list(B) NK_RP(D). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &C, &D, createNodeListNode(pCxt, B)); } - -/************************************************ boolean_value_expression ********************************************/ -boolean_value_expression(A) ::= boolean_primary(B). { PARSER_TRACE; A = B; } -boolean_value_expression(A) ::= NOT(C) boolean_primary(B). { - PARSER_TRACE; - SToken e = getTokenFromRawExprNode(pCxt, B); - A = createRawExprNodeExt(pCxt, &C, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, B), NULL)); - } -boolean_value_expression(A) ::= - boolean_value_expression(B) OR boolean_value_expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } -boolean_value_expression(A) ::= - boolean_value_expression(B) AND boolean_value_expression(C). { - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, B); - SToken e = getTokenFromRawExprNode(pCxt, C); - A = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); - } - -boolean_primary(A) ::= predicate(B). { PARSER_TRACE; A = B; } -boolean_primary(A) ::= NK_LP(C) boolean_value_expression(B) NK_RP(D). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &C, &D, releaseRawExprNode(pCxt, B)); } - -/************************************************ common_expression ********************************************/ -common_expression(A) ::= expression(B). { A = B; } -common_expression(A) ::= boolean_value_expression(B). { A = B; } - -/************************************************ from_clause *********************************************************/ -from_clause(A) ::= FROM table_reference_list(B). { PARSER_TRACE; A = B; } - -table_reference_list(A) ::= table_reference(B). { PARSER_TRACE; A = B; } -table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { PARSER_TRACE; A = createJoinTableNode(pCxt, JOIN_TYPE_INNER, B, C, NULL); } - -/************************************************ table_reference *****************************************************/ -table_reference(A) ::= table_primary(B). { PARSER_TRACE; A = B; } -table_reference(A) ::= joined_table(B). { PARSER_TRACE; A = B; } - -table_primary(A) ::= table_name(B) alias_opt(C). { PARSER_TRACE; A = createRealTableNode(pCxt, NULL, &B, &C); } -table_primary(A) ::= db_name(B) NK_DOT table_name(C) alias_opt(D). { PARSER_TRACE; A = createRealTableNode(pCxt, &B, &C, &D); } -table_primary(A) ::= subquery(B) alias_opt(C). { PARSER_TRACE; A = createTempTableNode(pCxt, releaseRawExprNode(pCxt, B), &C); } -table_primary(A) ::= parenthesized_joined_table(B). { PARSER_TRACE; A = B; } - -%type alias_opt { SToken } -%destructor alias_opt { PARSER_DESTRUCTOR_TRACE; } -alias_opt(A) ::= . { PARSER_TRACE; A = nil_token; } -alias_opt(A) ::= table_alias(B). { PARSER_TRACE; A = B; } -alias_opt(A) ::= AS table_alias(B). { PARSER_TRACE; A = B; } - -parenthesized_joined_table(A) ::= NK_LP joined_table(B) NK_RP. { PARSER_TRACE; A = B; } -parenthesized_joined_table(A) ::= NK_LP parenthesized_joined_table(B) NK_RP. { PARSER_TRACE; A = B; } - -/************************************************ joined_table ********************************************************/ -joined_table(A) ::= - table_reference(B) join_type(C) JOIN table_reference(D) ON search_condition(E). { PARSER_TRACE; A = createJoinTableNode(pCxt, C, B, D, E); } - -%type join_type { EJoinType } -%destructor join_type { PARSER_DESTRUCTOR_TRACE; } -join_type(A) ::= . { PARSER_TRACE; A = JOIN_TYPE_INNER; } -join_type(A) ::= INNER. { PARSER_TRACE; A = JOIN_TYPE_INNER; } - -/************************************************ query_specification *************************************************/ -query_specification(A) ::= - SELECT set_quantifier_opt(B) select_list(C) from_clause(D) where_clause_opt(E) - partition_by_clause_opt(F) twindow_clause_opt(G) - group_by_clause_opt(H) having_clause_opt(I). { - PARSER_TRACE; - A = createSelectStmt(pCxt, B, C, D); - A = addWhereClause(pCxt, A, E); - A = addPartitionByClause(pCxt, A, F); - A = addWindowClauseClause(pCxt, A, G); - A = addGroupByClause(pCxt, A, H); - A = addHavingClause(pCxt, A, I); - } - -%type set_quantifier_opt { bool } -%destructor set_quantifier_opt { PARSER_DESTRUCTOR_TRACE; } -set_quantifier_opt(A) ::= . { PARSER_TRACE; A = false; } -set_quantifier_opt(A) ::= DISTINCT. { PARSER_TRACE; A = true; } -set_quantifier_opt(A) ::= ALL. { PARSER_TRACE; A = false; } - -%type select_list { SNodeList* } -%destructor select_list { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -select_list(A) ::= NK_STAR. { PARSER_TRACE; A = NULL; } -select_list(A) ::= select_sublist(B). { PARSER_TRACE; A = B; } - -%type select_sublist { SNodeList* } -%destructor select_sublist { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -select_sublist(A) ::= select_item(B). { PARSER_TRACE; A = createNodeList(pCxt, B); } -select_sublist(A) ::= select_sublist(B) NK_COMMA select_item(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, C); } - -select_item(A) ::= common_expression(B). { - PARSER_TRACE; - SToken t = getTokenFromRawExprNode(pCxt, B); - A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &t); - } -select_item(A) ::= common_expression(B) column_alias(C). { PARSER_TRACE; A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &C); } -select_item(A) ::= common_expression(B) AS column_alias(C). { PARSER_TRACE; A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &C); } -select_item(A) ::= table_name(B) NK_DOT NK_STAR(C). { PARSER_TRACE; A = createColumnNode(pCxt, &B, &C); } - -where_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -where_clause_opt(A) ::= WHERE search_condition(B). { PARSER_TRACE; A = B; } - -%type partition_by_clause_opt { SNodeList* } -%destructor partition_by_clause_opt { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -partition_by_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -partition_by_clause_opt(A) ::= PARTITION BY expression_list(B). { PARSER_TRACE; A = B; } - -twindow_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -twindow_clause_opt(A) ::= - SESSION NK_LP column_reference(B) NK_COMMA NK_INTEGER(C) NK_RP. { PARSER_TRACE; A = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, B), &C); } -twindow_clause_opt(A) ::= STATE_WINDOW NK_LP column_reference(B) NK_RP. { PARSER_TRACE; A = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, B)); } -twindow_clause_opt(A) ::= - INTERVAL NK_LP duration_literal(B) NK_RP sliding_opt(C) fill_opt(D). { PARSER_TRACE; A = createIntervalWindowNode(pCxt, B, NULL, C, D); } -twindow_clause_opt(A) ::= - INTERVAL NK_LP duration_literal(B) NK_COMMA duration_literal(C) NK_RP - sliding_opt(D) fill_opt(E). { PARSER_TRACE; A = createIntervalWindowNode(pCxt, B, C, D, E); } - -sliding_opt(A) ::= . { PARSER_TRACE; A = NULL; } -sliding_opt(A) ::= SLIDING NK_LP duration_literal(B) NK_RP. { PARSER_TRACE; A = B; } - -fill_opt(A) ::= . { PARSER_TRACE; A = NULL; } -fill_opt(A) ::= FILL NK_LP fill_mode(B) NK_RP. { PARSER_TRACE; A = createFillNode(pCxt, B, NULL); } -fill_opt(A) ::= FILL NK_LP VALUE NK_COMMA literal_list(B) NK_RP. { PARSER_TRACE; A = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, B)); } - -%type fill_mode { EFillMode } -%destructor fill_mode { PARSER_DESTRUCTOR_TRACE; } -fill_mode(A) ::= NONE. { PARSER_TRACE; A = FILL_MODE_NONE; } -fill_mode(A) ::= PREV. { PARSER_TRACE; A = FILL_MODE_PREV; } -fill_mode(A) ::= NULL. { PARSER_TRACE; A = FILL_MODE_NULL; } -fill_mode(A) ::= LINEAR. { PARSER_TRACE; A = FILL_MODE_LINEAR; } -fill_mode(A) ::= NEXT. { PARSER_TRACE; A = FILL_MODE_NEXT; } - -%type group_by_clause_opt { SNodeList* } -%destructor group_by_clause_opt { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -group_by_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -group_by_clause_opt(A) ::= GROUP BY group_by_list(B). { PARSER_TRACE; A = B; } - -%type group_by_list { SNodeList* } -%destructor group_by_list { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -group_by_list(A) ::= expression(B). { PARSER_TRACE; A = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, B))); } -group_by_list(A) ::= group_by_list(B) NK_COMMA expression(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, C))); } - -having_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -having_clause_opt(A) ::= HAVING search_condition(B). { PARSER_TRACE; A = B; } - -/************************************************ query_expression ****************************************************/ -query_expression(A) ::= - query_expression_body(B) - order_by_clause_opt(C) slimit_clause_opt(D) limit_clause_opt(E). { - PARSER_TRACE; - A = addOrderByClause(pCxt, B, C); - A = addSlimitClause(pCxt, A, D); - A = addLimitClause(pCxt, A, E); - } - -query_expression_body(A) ::= query_primary(B). { PARSER_TRACE; A = B; } -query_expression_body(A) ::= - query_expression_body(B) UNION ALL query_expression_body(D). { PARSER_TRACE; A = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, B, D); } - -query_primary(A) ::= query_specification(B). { PARSER_TRACE; A = B; } -//query_primary(A) ::= -// NK_LP query_expression_body(B) -// order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP. { PARSER_TRACE; A = B;} - -%type order_by_clause_opt { SNodeList* } -%destructor order_by_clause_opt { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -order_by_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { PARSER_TRACE; A = B; } - -slimit_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B). { PARSER_TRACE; A = createLimitNode(pCxt, &B, NULL); } -slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B) SOFFSET NK_INTEGER(C). { PARSER_TRACE; A = createLimitNode(pCxt, &B, &C); } -slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { PARSER_TRACE; A = createLimitNode(pCxt, &B, &C); } - -limit_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; } -limit_clause_opt(A) ::= LIMIT NK_INTEGER(B). { PARSER_TRACE; A = createLimitNode(pCxt, &B, NULL); } -limit_clause_opt(A) ::= LIMIT NK_INTEGER(B) OFFSET NK_INTEGER(C). { PARSER_TRACE; A = createLimitNode(pCxt, &B, &C); } -limit_clause_opt(A) ::= LIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { PARSER_TRACE; A = createLimitNode(pCxt, &B, &C); } - -/************************************************ subquery ************************************************************/ -subquery(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { PARSER_TRACE; A = createRawExprNodeExt(pCxt, &B, &D, C); } - -/************************************************ search_condition ****************************************************/ -search_condition(A) ::= common_expression(B). { PARSER_TRACE; A = releaseRawExprNode(pCxt, B); } - -/************************************************ sort_specification_list *********************************************/ -%type sort_specification_list { SNodeList* } -%destructor sort_specification_list { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); } -sort_specification_list(A) ::= sort_specification(B). { PARSER_TRACE; A = createNodeList(pCxt, B); } -sort_specification_list(A) ::= - sort_specification_list(B) NK_COMMA sort_specification(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, C); } - -sort_specification(A) ::= - expression(B) ordering_specification_opt(C) null_ordering_opt(D). { PARSER_TRACE; A = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, B), C, D); } - -%type ordering_specification_opt EOrder -%destructor ordering_specification_opt { PARSER_DESTRUCTOR_TRACE; } -ordering_specification_opt(A) ::= . { PARSER_TRACE; A = ORDER_ASC; } -ordering_specification_opt(A) ::= ASC. { PARSER_TRACE; A = ORDER_ASC; } -ordering_specification_opt(A) ::= DESC. { PARSER_TRACE; A = ORDER_DESC; } - -%type null_ordering_opt ENullOrder -%destructor null_ordering_opt { PARSER_DESTRUCTOR_TRACE; } -null_ordering_opt(A) ::= . { PARSER_TRACE; A = NULL_ORDER_DEFAULT; } -null_ordering_opt(A) ::= NULLS FIRST. { PARSER_TRACE; A = NULL_ORDER_FIRST; } -null_ordering_opt(A) ::= NULLS LAST. { PARSER_TRACE; A = NULL_ORDER_LAST; } diff --git a/source/libs/parser/inc/astCreateFuncs.h b/source/libs/parser/inc/parAst.h similarity index 56% rename from source/libs/parser/inc/astCreateFuncs.h rename to source/libs/parser/inc/parAst.h index b44e621704670014e2fac7704b79888a0096595c..11c56ddf3c6cabf746266429c91ad4033960f591 100644 --- a/source/libs/parser/inc/astCreateFuncs.h +++ b/source/libs/parser/inc/parAst.h @@ -20,13 +20,55 @@ extern "C" { #endif +#include "cmdnodes.h" +#include "parser.h" +#include "parToken.h" +#include "parUtil.h" #include "querynodes.h" -#include "nodesShowStmts.h" -#include "astCreateContext.h" -#include "ttoken.h" + +typedef struct SAstCreateContext { + SParseContext* pQueryCxt; + SMsgBuf msgBuf; + bool notSupport; + bool valid; + SNode* pRootNode; +} SAstCreateContext; + +typedef enum EDatabaseOptionType { + DB_OPTION_BLOCKS = 0, + DB_OPTION_CACHE, + DB_OPTION_CACHELAST, + DB_OPTION_COMP, + DB_OPTION_DAYS, + DB_OPTION_FSYNC, + DB_OPTION_MAXROWS, + DB_OPTION_MINROWS, + DB_OPTION_KEEP, + DB_OPTION_PRECISION, + DB_OPTION_QUORUM, + DB_OPTION_REPLICA, + DB_OPTION_TTL, + DB_OPTION_WAL, + DB_OPTION_VGROUPS, + DB_OPTION_SINGLESTABLE, + DB_OPTION_STREAMMODE, + + DB_OPTION_MAX +} EDatabaseOptionType; + +typedef enum ETableOptionType { + TABLE_OPTION_KEEP = 0, + TABLE_OPTION_TTL, + TABLE_OPTION_COMMENT, + TABLE_OPTION_SMA, + + TABLE_OPTION_MAX +} ETableOptionType; extern SToken nil_token; +void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt); + SNode* createRawExprNode(SAstCreateContext* pCxt, const SToken* pToken, SNode* pNode); SNode* createRawExprNodeExt(SAstCreateContext* pCxt, const SToken* pStart, const SToken* pEnd, SNode* pNode); SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode); @@ -67,8 +109,29 @@ SNode* addLimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit); SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable); SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight); -SNode* createShowStmt(SAstCreateContext* pCxt, EShowStmtType type); - +SDatabaseOptions* createDefaultDatabaseOptions(SAstCreateContext* pCxt); +SDatabaseOptions* setDatabaseOption(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, EDatabaseOptionType type, const SToken* pVal); +SNode* createCreateDatabaseStmt(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pDbName, SDatabaseOptions* pOptions); +SNode* createDropDatabaseStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pDbName); +STableOptions* createDefaultTableOptions(SAstCreateContext* pCxt); +STableOptions* setTableOption(SAstCreateContext* pCxt, STableOptions* pOptions, ETableOptionType type, const SToken* pVal); +STableOptions* setTableSmaOption(SAstCreateContext* pCxt, STableOptions* pOptions, SNodeList* pSma); +SNode* createColumnDefNode(SAstCreateContext* pCxt, const SToken* pColName, SDataType dataType, const SToken* pComment); +SDataType createDataType(uint8_t type); +SDataType createVarLenDataType(uint8_t type, const SToken* pLen); +SNode* createCreateTableStmt(SAstCreateContext* pCxt, bool ignoreExists, SNode* pRealTable, SNodeList* pCols, SNodeList* pTags, STableOptions* pOptions); +SNode* createCreateSubTableClause(SAstCreateContext* pCxt, bool ignoreExists, SNode* pRealTable, SNode* pUseRealTable, SNodeList* pSpecificTags, SNodeList* pValsOfTags); +SNode* createCreateMultiTableStmt(SAstCreateContext* pCxt, SNodeList* pSubTables); +SNode* createDropTableClause(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable); +SNode* createDropTableStmt(SAstCreateContext* pCxt, SNodeList* pTables); +SNode* createDropSuperTableStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable); +SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, const SToken* pDbName); +SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDbName); +SNode* createCreateUserStmt(SAstCreateContext* pCxt, const SToken* pUserName, const SToken* pPassword); +SNode* createAlterUserStmt(SAstCreateContext* pCxt, const SToken* pUserName, int8_t alterType, const SToken* pVal); +SNode* createDropUserStmt(SAstCreateContext* pCxt, const SToken* pUserName); +SNode* createCreateDnodeStmt(SAstCreateContext* pCxt, const SToken* pFqdn, const SToken* pPort); +SNode* createDropDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode); #ifdef __cplusplus } diff --git a/source/libs/parser/inc/dataBlockMgt.h b/source/libs/parser/inc/parInsertData.h similarity index 100% rename from source/libs/parser/inc/dataBlockMgt.h rename to source/libs/parser/inc/parInsertData.h diff --git a/source/libs/parser/inc/parserImpl.h b/source/libs/parser/inc/parInt.h similarity index 77% rename from source/libs/parser/inc/parserImpl.h rename to source/libs/parser/inc/parInt.h index f2777a236881a94a3b3f68395118b5e63e60bb84..af0d78717e1341d4b73b0d69a72fb74d7fd61375 100644 --- a/source/libs/parser/inc/parserImpl.h +++ b/source/libs/parser/inc/parInt.h @@ -13,21 +13,21 @@ * along with this program. If not, see . */ -#ifndef _TD_PARSER_IMPL_H_ -#define _TD_PARSER_IMPL_H_ +#ifndef _TD_PARSER_INT_H_ +#define _TD_PARSER_INT_H_ #ifdef __cplusplus extern "C" { #endif -#include "querynodes.h" -#include "newParser.h" +#include "parser.h" -int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery); +int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery); +int32_t doParse(SParseContext* pParseCxt, SQuery** pQuery); int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery); #ifdef __cplusplus } #endif -#endif /*_TD_PARSER_IMPL_H_*/ +#endif /*_TD_PARSER_INT_H_*/ diff --git a/source/libs/parser/inc/ttoken.h b/source/libs/parser/inc/parToken.h similarity index 86% rename from source/libs/parser/inc/ttoken.h rename to source/libs/parser/inc/parToken.h index c041edf2b25d2ea9e270e3370e2df68ebcd19b8f..1122bafd12f21f5ded91b43b4d593781a2bd4b97 100644 --- a/source/libs/parser/inc/ttoken.h +++ b/source/libs/parser/inc/parToken.h @@ -36,7 +36,7 @@ typedef struct SToken { * @return */ #define isNumber(tk) \ -((tk)->type == TK_INTEGER || (tk)->type == TK_FLOAT || (tk)->type == TK_HEX || (tk)->type == TK_BIN) +((tk)->type == TK_NK_INTEGER || (tk)->type == TK_NK_FLOAT || (tk)->type == TK_NK_HEX || (tk)->type == TK_NK_BIN) /** * tokenizer for sql string @@ -67,11 +67,11 @@ bool taosIsKeyWordToken(const char *z, int32_t len); /** * check if it is a token or not * @param pToken - * @return token type, if it is not a number, TK_ILLEGAL will return + * @return token type, if it is not a number, TK_NK_ILLEGAL will return */ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) { const char* z = pToken->z; - int32_t type = TK_ILLEGAL; + int32_t type = TK_NK_ILLEGAL; uint32_t i = 0; for(; i < pToken->n; ++i) { @@ -88,7 +88,7 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) { * .123e4 */ if (!isdigit(z[i+1])) { - return TK_ILLEGAL; + return TK_NK_ILLEGAL; } for (i += 2; isdigit(z[i]); i++) { @@ -102,20 +102,20 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) { } } - type = TK_FLOAT; + type = TK_NK_FLOAT; goto _end; } case '0': { char next = z[i + 1]; if (next == 'b') { // bin number - type = TK_BIN; + type = TK_NK_BIN; for (i += 2; (z[i] == '0' || z[i] == '1'); ++i) { } goto _end; } else if (next == 'x') { //hex number - type = TK_HEX; + type = TK_NK_HEX; for (i += 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) { } @@ -131,7 +131,7 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) { case '7': case '8': case '9': { - type = TK_INTEGER; + type = TK_NK_INTEGER; for (; isdigit(z[i]); i++) { } @@ -144,11 +144,11 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) { } seg++; - type = TK_FLOAT; + type = TK_NK_FLOAT; } if (seg > 1) { - return TK_ILLEGAL; + return TK_NK_ILLEGAL; } if ((z[i] == 'e' || z[i] == 'E') && @@ -158,18 +158,18 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) { i++; } - type = TK_FLOAT; + type = TK_NK_FLOAT; } goto _end; } default: - return TK_ILLEGAL; + return TK_NK_ILLEGAL; } } _end: - return (i < pToken->n)? TK_ILLEGAL:type; + return (i < pToken->n)? TK_NK_ILLEGAL:type; } void taosCleanupKeywordsTable(); diff --git a/source/libs/parser/inc/queryInfoUtil.h b/source/libs/parser/inc/parUtil.h similarity index 56% rename from source/libs/parser/inc/queryInfoUtil.h rename to source/libs/parser/inc/parUtil.h index 638c3d11bf4b0a13860b693c733c78fdd834fab6..4d7a8e2a18b280e4f1882a0c96838c36d3f00959 100644 --- a/source/libs/parser/inc/queryInfoUtil.h +++ b/source/libs/parser/inc/parUtil.h @@ -13,38 +13,36 @@ * along with this program. If not, see . */ -#ifndef TDENGINE_QUERYINFOUTIL_H -#define TDENGINE_QUERYINFOUTIL_H +#ifndef TDENGINE_PARSER_UTIL_H +#define TDENGINE_PARSER_UTIL_H #ifdef __cplusplus extern "C" { #endif -#include "parserInt.h" -SSchema* getTbnameColumnSchema(); +#include "os.h" +#include "query.h" -int32_t getNumOfColumns(const STableMeta* pTableMeta); -int32_t getNumOfTags(const STableMeta* pTableMeta); -SSchema *getTableColumnSchema(const STableMeta *pTableMeta); -SSchema *getTableTagSchema(const STableMeta* pTableMeta); - -SArray *getCurrentExprList(SQueryStmtInfo* pQueryInfo); -size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo); - -void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level); -void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize); - -SExprInfo* getExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index); +typedef struct SMsgBuf { + int32_t len; + char *buf; +} SMsgBuf; -void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes); - -void cleanupFieldInfo(SFieldInfo* pFieldInfo); +int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...); +int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg); +int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr); +STableMeta* tableMetaDup(const STableMeta* pTableMeta); +SSchema *getTableColumnSchema(const STableMeta *pTableMeta); +SSchema *getTableTagSchema(const STableMeta* pTableMeta); +int32_t getNumOfColumns(const STableMeta* pTableMeta); +int32_t getNumOfTags(const STableMeta* pTableMeta); STableComInfo getTableInfo(const STableMeta* pTableMeta); -SArray *extractFunctionList(SArray* pExprInfoList); + +int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen); #ifdef __cplusplus } #endif -#endif // TDENGINE_QUERYINFOUTIL_H +#endif // TDENGINE_PARSER_UTIL_H diff --git a/source/libs/parser/inc/parserInt.h b/source/libs/parser/inc/parserInt.h deleted file mode 100644 index abb19b3ab60085bc40e4c212a222b26bcd2d8d37..0000000000000000000000000000000000000000 --- a/source/libs/parser/inc/parserInt.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef _TD_PARSER_INT_H_ -#define _TD_PARSER_INT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "catalog.h" -#include "tname.h" -#include "astGenerator.h" - -struct SSqlNode; - - -typedef struct SInternalField { - TAOS_FIELD field; - bool visible; - SExprInfo *pExpr; -} SInternalField; - -typedef struct SMsgBuf { - int32_t len; - char *buf; -} SMsgBuf; - -void clearTableMetaInfo(STableMetaInfo* pTableMetaInfo); - -void clearAllTableMetaInfo(SQueryStmtInfo* pQueryInfo, bool removeMeta, uint64_t id); - -/** - * Validate the sql info, according to the corresponding metadata info from catalog. - * @param pCtx - * @param pInfo - * @param pQueryInfo - * @param msgBuf - * @param msgBufLen - * @return - */ -int32_t qParserValidateSqlNode(SParseContext *pCtx, SSqlInfo* pInfo, SQueryStmtInfo* pQueryInfo, char* msgBuf, int32_t msgBufLen); - -/** - * validate the ddl ast, and convert the ast to the corresponding message format - * @param pSqlInfo - * @param output - * @param type - * @return - */ -SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen); - -/** - * - * @param pInfo - * @param pCtx - * @param msgBuf - * @param msgBufLen - * @return - */ -SVnodeModifOpStmtInfo* qParserValidateCreateTbSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen); - -/** - * Evaluate the numeric and timestamp arithmetic expression in the WHERE clause. - * @param pNode - * @param tsPrecision - * @param msg - * @param msgBufLen - * @return - */ -int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, SMsgBuf* pMsgBuf); - -int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf); - -SQueryStmtInfo* createQueryInfo(); - -void destroyQueryInfo(SQueryStmtInfo* pQueryInfo); - -int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf); - -/** - * Extract request meta info from the sql statement - * @param pSqlInfo - * @param pMetaInfo - * @param msg - * @param msgBufLen - * @return - */ -int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SCatalogReq* pMetaInfo, SParseContext *pCtx, char* msg, int32_t msgBufLen); - -/** - * Destroy the meta data request structure. - * @param pMetaInfo - */ -void qParserCleanupMetaRequestInfo(SCatalogReq* pMetaInfo); - -#ifdef __cplusplus -} -#endif - -#endif /*_TD_PARSER_INT_H_*/ \ No newline at end of file diff --git a/source/libs/parser/inc/parserUtil.h b/source/libs/parser/inc/parserUtil.h deleted file mode 100644 index d660d36d3f77c63cad3c3a6903576c9c6d200e6f..0000000000000000000000000000000000000000 --- a/source/libs/parser/inc/parserUtil.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef TDENGINE_PARSERUTIL_H -#define TDENGINE_PARSERUTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "os.h" -#include "ttoken.h" -#include "parserInt.h" - -#define UTIL_TABLE_IS_SUPER_TABLE(metaInfo) \ - (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_SUPER_TABLE)) - -#define UTIL_TABLE_IS_CHILD_TABLE(metaInfo) \ - (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE)) - -#define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo) \ - (!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo))) - -#define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \ - (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE)) - -TAOS_FIELD createField(const SSchema* pSchema); -void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema); -SColumn createColumn(uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema); - -SInternalField* insertFieldInfo(SFieldInfo* pFieldInfo, int32_t index, SSchema* field); -int32_t getNumOfFields(SFieldInfo* pFieldInfo); -SInternalField* getInternalField(SFieldInfo* pFieldInfo, int32_t index); - -int32_t parserValidateIdToken(SToken* pToken); -int32_t parserValidatePassword(SToken* pToken, SMsgBuf* pMsgBuf); -int32_t parserValidateNameToken(SToken* pToken); - -int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg); -int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr); - -STableMetaInfo* addEmptyMetaInfo(SQueryStmtInfo* pQueryInfo); - -void columnListCopyAll(SArray* dst, const SArray* src); - -SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag); -SColumn* insertPrimaryTsColumn(SArray* pColumnList, const char* colName, uint64_t tableUid); - -void cleanupTagCond(STagCond* pTagCond); -void cleanupColumnCond(SArray** pCond); - -uint32_t convertRelationalOperator(SToken *pToken); -int32_t getExprFunctionId(SExprInfo *pExprInfo); - -STableMeta* tableMetaDup(const STableMeta* pTableMeta); - -bool isDclSqlStatement(SSqlInfo* pSqlInfo); -bool isDdlSqlStatement(SSqlInfo* pSqlInfo); -bool isDqlSqlStatement(SSqlInfo* pSqlInfo); - -typedef struct SKvParam { - SKVRowBuilder *builder; - SSchema *schema; - char buf[TSDB_MAX_TAGS_LEN]; -} SKvParam; - -int32_t KvRowAppend(const void *value, int32_t len, void *param); - -typedef int32_t (*_row_append_fn_t)(const void *value, int32_t len, void *param); -int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf); - -int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf); - -#ifdef __cplusplus -} -#endif - -#endif // TDENGINE_PARSERUTIL_H diff --git a/source/libs/parser/inc/sql.y b/source/libs/parser/inc/sql.y index fa713d5fb42cd8ddda7ccb3b9037f4ca31f88891..f4ed3d85978a537ff676ad69642c2bd354c3ed68 100644 --- a/source/libs/parser/inc/sql.y +++ b/source/libs/parser/inc/sql.y @@ -1,24 +1,12 @@ //lemon parser file to generate sql parse by using finite-state-machine code used to parse sql //usage: lemon sql.y -%token_prefix TK_ - -%token_type {SToken} -%default_type {SToken} -%extra_argument {SSqlInfo* pInfo} -%fallback ID BOOL INTEGER FLOAT STRING TIMESTAMP. +%token_prefix TK_ +%token_type { SToken } +%default_type { SNode* } +%default_destructor { nodesDestroyNode($$); } -%left OR. -%left AND. -%right NOT. -%left EQ NE ISNULL NOTNULL IS LIKE MATCH NMATCH GLOB BETWEEN IN. -%left GT GE LT LE. -%left BITAND BITOR LSHIFT RSHIFT. -%left PLUS MINUS. -%left DIVIDE TIMES. -%left STAR SLASH REM. -%left CONCAT. -%right UMINUS UPLUS BITNOT. +%extra_argument { SAstCreateContext* pCxt } %include { #include @@ -26,920 +14,545 @@ #include #include #include -#include "astGenerator.h" -#include "tmsgtype.h" -#include "ttoken.h" + +#include "nodes.h" +#include "parToken.h" #include "ttokendef.h" -#include "tvariant.h" -#include "parserInt.h" +#include "parAst.h" } -%syntax_error { - pInfo->valid = false; - int32_t outputBufLen = tListLen(pInfo->msg); - int32_t len = 0; - +%syntax_error { if(TOKEN.z) { - char msg[] = "syntax error near \"%s\""; - int32_t sqlLen = strlen(&TOKEN.z[0]); - - if (sqlLen + sizeof(msg)/sizeof(msg[0]) + 1 > outputBufLen) { - char tmpstr[128] = {0}; - memcpy(tmpstr, &TOKEN.z[0], sizeof(tmpstr)/sizeof(tmpstr[0]) - 1); - len = sprintf(pInfo->msg, msg, tmpstr); - } else { - len = sprintf(pInfo->msg, msg, &TOKEN.z[0]); - } - - } else { - len = sprintf(pInfo->msg, "Incomplete SQL statement"); - } - - assert(len <= outputBufLen); -} - -%parse_accept {} - -program ::= cmd. {} - -//////////////////////////////////THE SHOW STATEMENT/////////////////////////////////////////// -cmd ::= SHOW DATABASES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_DB, 0, 0);} -cmd ::= SHOW TOPICS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_TP, 0, 0);} -cmd ::= SHOW FUNCTIONS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_FUNC, 0, 0);} -cmd ::= SHOW MNODES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_MNODE, 0, 0);} -cmd ::= SHOW DNODES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_DNODE, 0, 0);} -cmd ::= SHOW ACCOUNTS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_ACCT, 0, 0);} -cmd ::= SHOW USERS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_USER, 0, 0);} - -cmd ::= SHOW MODULES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_MODULE, 0, 0); } -cmd ::= SHOW QUERIES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_QUERIES, 0, 0); } -cmd ::= SHOW CONNECTIONS.{ setShowOptions(pInfo, TSDB_MGMT_TABLE_CONNS, 0, 0);} -cmd ::= SHOW STREAMS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_STREAMS, 0, 0); } -cmd ::= SHOW VARIABLES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_VARIABLES, 0, 0); } -cmd ::= SHOW SCORES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_TRANS, 0, 0); } -cmd ::= SHOW GRANTS. { setShowOptions(pInfo, TSDB_MGMT_TABLE_GRANTS, 0, 0); } - -cmd ::= SHOW VNODES. { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, 0, 0); } -cmd ::= SHOW VNODES ids(X). { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, &X, 0); } - - -%type dbPrefix {SToken} -dbPrefix(A) ::=. {A.n = 0; A.type = 0;} -dbPrefix(A) ::= ids(X) DOT. {A = X; } - -%type cpxName {SToken} -cpxName(A) ::= . {A.n = 0; } -cpxName(A) ::= DOT ids(Y). {A = Y; A.n += 1; } - -cmd ::= SHOW CREATE TABLE ids(X) cpxName(Y). { - X.n += Y.n; - setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &X); -} -cmd ::= SHOW CREATE STABLE ids(X) cpxName(Y). { - X.n += Y.n; - setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_STABLE, 1, &X); -} - -cmd ::= SHOW CREATE DATABASE ids(X). { - setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &X); -} - -cmd ::= SHOW dbPrefix(X) TABLES. { - setShowOptions(pInfo, TSDB_MGMT_TABLE_TABLE, &X, 0); -} - -cmd ::= SHOW dbPrefix(X) TABLES LIKE ids(Y). { - setShowOptions(pInfo, TSDB_MGMT_TABLE_TABLE, &X, &Y); -} - -cmd ::= SHOW dbPrefix(X) STABLES. { - setShowOptions(pInfo, TSDB_MGMT_TABLE_STB, &X, 0); -} - -cmd ::= SHOW dbPrefix(X) STABLES LIKE ids(Y). { - SToken token; - tSetDbName(&token, &X); - setShowOptions(pInfo, TSDB_MGMT_TABLE_STB, &token, &Y); -} - -cmd ::= SHOW dbPrefix(X) VGROUPS. { - SToken token; - tSetDbName(&token, &X); - setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, 0); -} - -cmd ::= SHOW dbPrefix(X) VGROUPS ids(Y). { - SToken token; - tSetDbName(&token, &X); - setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, &Y); -} - -//drop configure for tables -cmd ::= DROP TABLE ifexists(Y) ids(X) cpxName(Z). { - X.n += Z.n; - setDropDbTableInfo(pInfo, TSDB_SQL_DROP_TABLE, &X, &Y, -1, -1); -} - -//drop stable -cmd ::= DROP STABLE ifexists(Y) ids(X) cpxName(Z). { - X.n += Z.n; - setDropDbTableInfo(pInfo, TSDB_SQL_DROP_TABLE, &X, &Y, -1, TSDB_SUPER_TABLE); -} - -cmd ::= DROP DATABASE ifexists(Y) ids(X). { setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &X, &Y, TSDB_DB_TYPE_DEFAULT, -1); } -cmd ::= DROP TOPIC ifexists(Y) ids(X). { setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &X, &Y, TSDB_DB_TYPE_TOPIC, -1); } -cmd ::= DROP FUNCTION ids(X). { setDropFuncInfo(pInfo, TSDB_SQL_DROP_FUNCTION, &X); } - -cmd ::= DROP DNODE ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &X); } -cmd ::= DROP USER ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_DROP_USER, 1, &X); } -cmd ::= DROP ACCOUNT ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &X); } - -/////////////////////////////////THE USE STATEMENT////////////////////////////////////////// -cmd ::= USE ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_USE_DB, 1, &X);} - -/////////////////////////////////THE DESCRIBE STATEMENT///////////////////////////////////// -cmd ::= DESCRIBE ids(X) cpxName(Y). { - X.n += Y.n; - setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); -} -cmd ::= DESC ids(X) cpxName(Y). { - X.n += Y.n; - setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); -} -/////////////////////////////////THE ALTER STATEMENT//////////////////////////////////////// -cmd ::= ALTER USER ids(X) PASS ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &X, &Y, NULL); } -cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &X, NULL, &Y);} -cmd ::= ALTER DNODE ids(X) ids(Y). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &X, &Y); } -cmd ::= ALTER DNODE ids(X) ids(Y) ids(Z). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &X, &Y, &Z); } -cmd ::= ALTER LOCAL ids(X). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &X); } -cmd ::= ALTER LOCAL ids(X) ids(Y). { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &X, &Y); } -cmd ::= ALTER DATABASE ids(X) alter_db_optr(Y). { SToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &X, &Y, &t);} -//cmd ::= ALTER TOPIC ids(X) alter_topic_optr(Y). { SToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &X, &Y, &t);} - -cmd ::= ALTER ACCOUNT ids(X) acct_optr(Z). { setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &X, NULL, &Z);} -cmd ::= ALTER ACCOUNT ids(X) PASS ids(Y) acct_optr(Z). { setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &X, &Y, &Z);} - -////////////////////////////// COMPACT STATEMENT ////////////////////////////////////////////// - -cmd ::= COMPACT VNODES IN LP exprlist(Y) RP. { setCompactVnodeSql(pInfo, TSDB_SQL_COMPACT_VNODE, Y);} - -// An IDENTIFIER can be a generic identifier, or one of several keywords. -// Any non-standard keyword can also be an identifier. -// And "ids" is an identifer-or-string. -%type ids {SToken} -ids(A) ::= ID(X). {A = X; } -//ids(A) ::= STRING(X). {A = X; } - -%type ifexists {SToken} -ifexists(X) ::= IF EXISTS. { X.n = 1;} -ifexists(X) ::= . { X.n = 0;} - -%type ifnotexists {SToken} -ifnotexists(X) ::= IF NOT EXISTS. { X.n = 1;} -ifnotexists(X) ::= . { X.n = 0;} - -/////////////////////////////////THE CREATE STATEMENT/////////////////////////////////////// -//create option for dnode/db/user/account -cmd ::= CREATE DNODE ids(X) PORT ids(Y). { setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 2, &X, &Y);} -cmd ::= CREATE DNODE IPTOKEN(X) PORT ids(Y). { setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 2, &X, &Y);} -cmd ::= CREATE ACCOUNT ids(X) PASS ids(Y) acct_optr(Z). - { setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &X, &Y, &Z);} -cmd ::= CREATE DATABASE ifnotexists(Z) ids(X) db_optr(Y). { setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &X, &Y, &Z);} -//cmd ::= CREATE TOPIC ifnotexists(Z) ids(X) topic_optr(Y). { setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &X, &Y, &Z);} -cmd ::= CREATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z) bufsize(B). { setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &X, &Y, &Z, &B, 1);} -cmd ::= CREATE AGGREGATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z) bufsize(B). { setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &X, &Y, &Z, &B, 2);} -cmd ::= CREATE USER ids(X) PASS ids(Y). { setCreateUserSql(pInfo, &X, &Y);} - -bufsize(Y) ::= . { Y.n = 0; } -bufsize(Y) ::= BUFSIZE INTEGER(X). { Y = X; } - -pps(Y) ::= . { Y.n = 0; } -pps(Y) ::= PPS INTEGER(X). { Y = X; } - -tseries(Y) ::= . { Y.n = 0; } -tseries(Y) ::= TSERIES INTEGER(X). { Y = X; } - -dbs(Y) ::= . { Y.n = 0; } -dbs(Y) ::= DBS INTEGER(X). { Y = X; } - -streams(Y) ::= . { Y.n = 0; } -streams(Y) ::= STREAMS INTEGER(X). { Y = X; } - -storage(Y) ::= . { Y.n = 0; } -storage(Y) ::= STORAGE INTEGER(X). { Y = X; } - -qtime(Y) ::= . { Y.n = 0; } -qtime(Y) ::= QTIME INTEGER(X). { Y = X; } - -users(Y) ::= . { Y.n = 0; } -users(Y) ::= USERS INTEGER(X). { Y = X; } - -conns(Y) ::= . { Y.n = 0; } -conns(Y) ::= CONNS INTEGER(X). { Y = X; } - -state(Y) ::= . { Y.n = 0; } -state(Y) ::= STATE ids(X). { Y = X; } - -%type acct_optr {SCreateAcctInfo} -acct_optr(Y) ::= pps(C) tseries(D) storage(P) streams(F) qtime(Q) dbs(E) users(K) conns(L) state(M). { - Y.maxUsers = (K.n>0)?atoi(K.z):-1; - Y.maxDbs = (E.n>0)?atoi(E.z):-1; - Y.maxTimeSeries = (D.n>0)?atoi(D.z):-1; - Y.maxStreams = (F.n>0)?atoi(F.z):-1; - Y.maxPointsPerSecond = (C.n>0)?atoi(C.z):-1; - Y.maxStorage = (P.n>0)?strtoll(P.z, NULL, 10):-1; - Y.maxQueryTime = (Q.n>0)?strtoll(Q.z, NULL, 10):-1; - Y.maxConnections = (L.n>0)?atoi(L.z):-1; - Y.stat = M; -} - -%type intitemlist {SArray*} -%destructor intitemlist {taosArrayDestroy($$);} - -%type intitem {SVariant} -intitemlist(A) ::= intitemlist(X) COMMA intitem(Y). { A = tListItemAppend(X, &Y, -1); } -intitemlist(A) ::= intitem(X). { A = tListItemAppend(NULL, &X, -1); } - -intitem(A) ::= INTEGER(X). { toTSDBType(X.type); taosVariantCreate(&A, X.z, X.n, X.type); } - -%type keep {SArray*} -%destructor keep {taosArrayDestroy($$);} -keep(Y) ::= KEEP intitemlist(X). { Y = X; } - -cache(Y) ::= CACHE INTEGER(X). { Y = X; } -replica(Y) ::= REPLICA INTEGER(X). { Y = X; } -quorum(Y) ::= QUORUM INTEGER(X). { Y = X; } -days(Y) ::= DAYS INTEGER(X). { Y = X; } -minrows(Y) ::= MINROWS INTEGER(X). { Y = X; } -maxrows(Y) ::= MAXROWS INTEGER(X). { Y = X; } -blocks(Y) ::= BLOCKS INTEGER(X). { Y = X; } -ctime(Y) ::= CTIME INTEGER(X). { Y = X; } -wal(Y) ::= WAL INTEGER(X). { Y = X; } -fsync(Y) ::= FSYNC INTEGER(X). { Y = X; } -comp(Y) ::= COMP INTEGER(X). { Y = X; } -prec(Y) ::= PRECISION STRING(X). { Y = X; } -update(Y) ::= UPDATE INTEGER(X). { Y = X; } -cachelast(Y) ::= CACHELAST INTEGER(X). { Y = X; } -vgroups(Y) ::= VGROUPS INTEGER(X). { Y = X; } -//partitions(Y) ::= PARTITIONS INTEGER(X). { Y = X; } -stream_mode(Y) ::= STREAM MODE INTEGER(X). { Y = X; } - -%type db_optr {SCreateDbInfo} -db_optr(Y) ::= . {setDefaultCreateDbOption(&Y);} - -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) quorum(X). { Y = Z; Y.quorum = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) days(X). { Y = Z; Y.daysPerFile = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) minrows(X). { Y = Z; Y.minRowsPerBlock = strtod(X.z, NULL); } -db_optr(Y) ::= db_optr(Z) maxrows(X). { Y = Z; Y.maxRowsPerBlock = strtod(X.z, NULL); } -db_optr(Y) ::= db_optr(Z) blocks(X). { Y = Z; Y.numOfBlocks = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) ctime(X). { Y = Z; Y.commitTime = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) wal(X). { Y = Z; Y.walLevel = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) fsync(X). { Y = Z; Y.fsyncPeriod = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) comp(X). { Y = Z; Y.compressionLevel = strtol(X.z, NULL, 10); } -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) update(X). { Y = Z; Y.update = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) cachelast(X). { Y = Z; Y.cachelast = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) vgroups(X). { Y = Z; Y.numOfVgroups = strtol(X.z, NULL, 10); } -db_optr(Y) ::= db_optr(Z) stream_mode(X). { Y = Z; Y.streamMode = strtol(X.z, NULL, 10); } - -//%type topic_optr {SCreateDbInfo} -// -//topic_optr(Y) ::= db_optr(Z). { Y = Z; Y.dbType = TSDB_DB_TYPE_TOPIC; } -//topic_optr(Y) ::= topic_optr(Z) partitions(X). { Y = Z; Y.partitions = strtol(X.z, NULL, 10); } - -%type alter_db_optr {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) quorum(X). { Y = Z; Y.quorum = strtol(X.z, NULL, 10); } -alter_db_optr(Y) ::= alter_db_optr(Z) keep(X). { Y = Z; Y.keep = X; } -alter_db_optr(Y) ::= alter_db_optr(Z) blocks(X). { Y = Z; Y.numOfBlocks = strtol(X.z, NULL, 10); } -alter_db_optr(Y) ::= alter_db_optr(Z) comp(X). { Y = Z; Y.compressionLevel = strtol(X.z, NULL, 10); } -alter_db_optr(Y) ::= alter_db_optr(Z) update(X). { Y = Z; Y.update = strtol(X.z, NULL, 10); } -alter_db_optr(Y) ::= alter_db_optr(Z) cachelast(X). { Y = Z; Y.cachelast = strtol(X.z, NULL, 10); } - -// dynamically update the following two parameters are not allowed. -//alter_db_optr(Y) ::= alter_db_optr(Z) fsync(X). { Y = Z; Y.fsyncPeriod = strtol(X.z, NULL, 10); } -//alter_db_optr(Y) ::= alter_db_optr(Z) wal(X). { Y = Z; Y.walLevel = strtol(X.z, NULL, 10); } not support yet - -//%type alter_topic_optr {SCreateDbInfo} - -//alter_topic_optr(Y) ::= alter_db_optr(Z). { Y = Z; Y.dbType = TSDB_DB_TYPE_TOPIC; } -//alter_topic_optr(Y) ::= alter_topic_optr(Z) partitions(X). { Y = Z; Y.partitions = strtol(X.z, NULL, 10); } - -%type typename {SField} -typename(A) ::= ids(X). { - X.type = 0; - tSetColumnType (&A, &X); -} - -//define binary type, e.g., binary(10), nchar(10) -typename(A) ::= ids(X) LP signed(Y) RP. { - if (Y <= 0) { - X.type = 0; - tSetColumnType(&A, &X); + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, TOKEN.z); } else { - X.type = -Y; // negative value of name length - tSetColumnType(&A, &X); + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCOMPLETE_SQL); } + pCxt->valid = false; } -// define the unsigned number type -typename(A) ::= ids(X) UNSIGNED(Z). { - X.type = 0; - X.n = ((Z.z + Z.n) - X.z); - tSetColumnType (&A, &X); -} - -%type signed {int64_t} -signed(A) ::= INTEGER(X). { A = strtol(X.z, NULL, 10); } -signed(A) ::= PLUS INTEGER(X). { A = strtol(X.z, NULL, 10); } -signed(A) ::= MINUS INTEGER(X). { A = -strtol(X.z, NULL, 10);} - -////////////////////////////////// The CREATE TABLE statement /////////////////////////////// -cmd ::= CREATE TABLE create_table_args. {} -cmd ::= CREATE TABLE create_stable_args. {} -cmd ::= CREATE STABLE create_stable_args. {} -cmd ::= CREATE TABLE create_table_list(Z). { pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = Z;} - -%type create_table_list{SCreateTableSql*} -%destructor create_table_list{destroyCreateTableSql($$);} -create_table_list(A) ::= create_from_stable(Z). { - SCreateTableSql* pCreateTable = calloc(1, sizeof(SCreateTableSql)); - pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); - - taosArrayPush(pCreateTable->childTableInfo, &Z); - pCreateTable->type = TSDB_SQL_CREATE_TABLE; - A = pCreateTable; -} - -create_table_list(A) ::= create_table_list(X) create_from_stable(Z). { - taosArrayPush(X->childTableInfo, &Z); - A = X; -} - -%type create_table_args{SCreateTableSql*} -create_table_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) LP columnlist(X) RP. { - A = tSetCreateTableInfo(X, NULL, NULL, TSDB_SQL_CREATE_TABLE); - setSqlInfo(pInfo, A, NULL, TSDB_SQL_CREATE_TABLE); - - V.n += Z.n; - setCreatedTableName(pInfo, &V, &U); -} - -// create super table -%type create_stable_args{SCreateTableSql*} -create_stable_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) LP columnlist(X) RP TAGS LP columnlist(Y) RP. { - A = tSetCreateTableInfo(X, Y, NULL, TSDB_SQL_CREATE_STABLE); - setSqlInfo(pInfo, A, NULL, TSDB_SQL_CREATE_STABLE); - - V.n += Z.n; - setCreatedTableName(pInfo, &V, &U); -} - -// create table by using super table -// create table table_name using super_table_name tags(tag_values1, tag_values2) -%type create_from_stable{SCreatedTableInfo} -create_from_stable(A) ::= ifnotexists(U) ids(V) cpxName(Z) USING ids(X) cpxName(F) TAGS LP tagitemlist1(Y) RP. { - X.n += F.n; - V.n += Z.n; - A = createNewChildTableInfo(&X, NULL, Y, &V, &U); -} - -create_from_stable(A) ::= ifnotexists(U) ids(V) cpxName(Z) USING ids(X) cpxName(F) LP tagNamelist(P) RP TAGS LP tagitemlist1(Y) RP. { - X.n += F.n; - V.n += Z.n; - A = createNewChildTableInfo(&X, P, Y, &V, &U); -} - -%type tagNamelist{SArray*} -%destructor tagNamelist {taosArrayDestroy($$);} -tagNamelist(A) ::= tagNamelist(X) COMMA ids(Y). {taosArrayPush(X, &Y); A = X; } -tagNamelist(A) ::= ids(X). {A = taosArrayInit(4, sizeof(SToken)); taosArrayPush(A, &X);} - -// create stream -// create table table_name as select count(*) from super_table_name interval(time) -create_table_args(A) ::= ifnotexists(U) ids(V) cpxName(Z) AS select(S). { -// A = tSetCreateTableInfo(NULL, NULL, S, TSQL_CREATE_STREAM); -// setSqlInfo(pInfo, A, NULL, TSDB_SQL_CREATE_TABLE); -// -// V.n += Z.n; -// setCreatedTableName(pInfo, &V, &U); -} - -%type column{SField} -%type columnlist{SArray*} -%destructor columnlist {taosArrayDestroy($$);} -columnlist(A) ::= columnlist(X) COMMA column(Y). {taosArrayPush(X, &Y); A = X; } -columnlist(A) ::= column(X). {A = taosArrayInit(4, sizeof(SField)); taosArrayPush(A, &X);} - -// The information used for a column is the name and type of column: -// tinyint smallint int bigint float double bool timestamp binary(x) nchar(x) -column(A) ::= ids(X) typename(Y). { - tSetColumnInfo(&A, &X, &Y); -} - -%type tagitemlist1 {SArray*} -%destructor tagitemlist1 {taosArrayDestroy($$);} - -tagitemlist1(A) ::= tagitemlist1(X) COMMA tagitem1(Y). { taosArrayPush(X, &Y); A = X;} -tagitemlist1(A) ::= tagitem1(Y). { A = taosArrayInit(4, sizeof(SToken)); taosArrayPush(A, &Y); } - -%type tagitem1 {SToken} -tagitem1(A) ::= MINUS(X) INTEGER(Y). { A.n = X.n + Y.n; A.type = Y.type; A.z = X.z;} -tagitem1(A) ::= MINUS(X) FLOAT(Y). { A.n = X.n + Y.n; A.type = Y.type; A.z = X.z;} -tagitem1(A) ::= PLUS(X) INTEGER(Y). { A.n = X.n + Y.n; A.type = Y.type; A.z = X.z;} -tagitem1(A) ::= PLUS(X) FLOAT(Y). { A.n = X.n + Y.n; A.type = Y.type; A.z = X.z;} -tagitem1(A) ::= INTEGER(X). { A = X; } -tagitem1(A) ::= FLOAT(X). { A = X; } -tagitem1(A) ::= STRING(X). { A = X; } -tagitem1(A) ::= BOOL(X). { A = X; } -tagitem1(A) ::= NULL(X). { A = X; } -tagitem1(A) ::= NOW(X). { A = X; } - -%type tagitemlist {SArray*} -%destructor tagitemlist {taosArrayDestroy($$);} - -%type tagitem {SVariant} -tagitemlist(A) ::= tagitemlist(X) COMMA tagitem(Y). { A = tListItemAppend(X, &Y, -1); } -tagitemlist(A) ::= tagitem(X). { A = tListItemAppend(NULL, &X, -1); } - -tagitem(A) ::= INTEGER(X). { toTSDBType(X.type); taosVariantCreate(&A, X.z, X.n, X.type); } -tagitem(A) ::= FLOAT(X). { toTSDBType(X.type); taosVariantCreate(&A, X.z, X.n, X.type); } -tagitem(A) ::= STRING(X). { toTSDBType(X.type); taosVariantCreate(&A, X.z, X.n, X.type); } -tagitem(A) ::= BOOL(X). { toTSDBType(X.type); taosVariantCreate(&A, X.z, X.n, X.type); } -tagitem(A) ::= NULL(X). { X.type = 0; taosVariantCreate(&A, X.z, X.n, X.type); } -tagitem(A) ::= NOW(X). { X.type = TSDB_DATA_TYPE_TIMESTAMP; taosVariantCreate(&A, X.z, X.n, X.type);} - -tagitem(A) ::= MINUS(X) INTEGER(Y).{ - X.n += Y.n; - X.type = Y.type; - toTSDBType(X.type); - taosVariantCreate(&A, X.z, X.n, X.type); -} - -tagitem(A) ::= MINUS(X) FLOAT(Y). { - X.n += Y.n; - X.type = Y.type; - toTSDBType(X.type); - taosVariantCreate(&A, X.z, X.n, X.type); -} - -tagitem(A) ::= PLUS(X) INTEGER(Y). { - X.n += Y.n; - X.type = Y.type; - toTSDBType(X.type); - taosVariantCreate(&A, X.z, X.n, X.type); -} - -tagitem(A) ::= PLUS(X) FLOAT(Y). { - X.n += Y.n; - X.type = Y.type; - toTSDBType(X.type); - taosVariantCreate(&A, X.z, X.n, X.type); -} - -//////////////////////// The SELECT statement ///////////////////////////////// -%type select {SSqlNode*} -%destructor select {destroySqlNode($$);} -select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_option(K) sliding_opt(S) session_option(H) windowstate_option(D) fill_opt(F)groupby_opt(P) having_opt(N) orderby_opt(Z) slimit_opt(G) limit_opt(L). { - A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &D, &S, F, &L, &G, N); -} - -select(A) ::= LP select(B) RP. {A = B;} - -%type union {SSubclause*} -%destructor union {destroyAllSqlNode($$);} -union(Y) ::= select(X). { Y = setSubclause(NULL, X); } -union(Y) ::= union(Z) UNION ALL select(X). { Y = appendSelectClause(Z, SQL_TYPE_UNIONALL, X); } -union(Y) ::= union(Z) UNION select(X). { Y = appendSelectClause(Z, SQL_TYPE_UNION, X); } -cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); } - -// Support for the SQL exprssion without from & where subclauses, e.g., -// select database() -// select server_version() -// select client_version() -// select server_state() -select(A) ::= SELECT(T) selcollist(W). { - A = tSetQuerySqlNode(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); -} - -// selcollist is a list of expressions that are to become the return -// values of the SELECT statement. The "*" in statements like -// "SELECT * FROM ..." is encoded as a special expression with an opcode of TK_ALL. -%type selcollist {SArray*} -%destructor selcollist {tSqlExprListDestroy($$);} - -%type sclp {SArray*} -%destructor sclp {tSqlExprListDestroy($$);} -sclp(A) ::= selcollist(X) COMMA. {A = X;} -sclp(A) ::= . {A = 0;} -selcollist(A) ::= sclp(P) distinct(Z) expr(X) as(Y). { - A = tSqlExprListAppend(P, X, Z.n? &Z:0, Y.n?&Y:0); -} - -selcollist(A) ::= sclp(P) STAR. { - tSqlExpr *pNode = tSqlExprCreateIdValue(NULL, TK_ALL); - A = tSqlExprListAppend(P, pNode, 0, 0); -} - -// An option "AS " phrase that can follow one of the expressions that -// define the result set, or one of the tables in the FROM clause. -%type as {SToken} -as(X) ::= AS ids(Y). { X = Y; } -as(X) ::= ids(Y). { X = Y; } -as(X) ::= . { X.n = 0; } - -%type distinct {SToken} -distinct(X) ::= DISTINCT(Y). { X = Y; } -distinct(X) ::= . { X.n = 0;} - -// A complete FROM clause. -%type from {SRelationInfo*} -%destructor from {destroyRelationInfo($$);} -from(A) ::= FROM tablelist(X). {A = X;} -from(A) ::= FROM sub(X). {A = X;} - -%type sub {SRelationInfo*} -%destructor sub {destroyRelationInfo($$);} -sub(A) ::= LP union(Y) RP. {A = addSubquery(NULL, Y, NULL);} -sub(A) ::= LP union(Y) RP ids(Z). {A = addSubquery(NULL, Y, &Z);} -sub(A) ::= sub(X) COMMA LP union(Y) RP ids(Z).{A = addSubquery(X, Y, &Z);} - -%type tablelist {SRelationInfo*} -%destructor tablelist {destroyRelationInfo($$);} -tablelist(A) ::= ids(X) cpxName(Y). { - X.n += Y.n; - A = setTableNameList(NULL, &X, NULL); -} - -tablelist(A) ::= ids(X) cpxName(Y) ids(Z). { - X.n += Y.n; - A = setTableNameList(NULL, &X, &Z); -} - -tablelist(A) ::= tablelist(Y) COMMA ids(X) cpxName(Z). { - X.n += Z.n; - A = setTableNameList(Y, &X, NULL); -} - -tablelist(A) ::= tablelist(Y) COMMA ids(X) cpxName(Z) ids(F). { - X.n += Z.n; - A = setTableNameList(Y, &X, &F); -} - -// The value of interval should be the form of "number+[a,s,m,h,d,n,y]" or "now" -%type tmvar {SToken} -tmvar(A) ::= VARIABLE(X). {A = X;} - -%type interval_option {SIntervalVal} -interval_option(N) ::= intervalKey(A) LP tmvar(E) RP. {N.interval = E; N.offset.n = 0; N.token = A;} -interval_option(N) ::= intervalKey(A) LP tmvar(E) COMMA tmvar(X) RP. {N.interval = E; N.offset = X; N.token = A;} -interval_option(N) ::= . {memset(&N, 0, sizeof(N));} - -%type intervalKey {int32_t} -intervalKey(A) ::= INTERVAL. {A = TK_INTERVAL;} -intervalKey(A) ::= EVERY. {A = TK_EVERY; } - -%type session_option {SSessionWindowVal} -session_option(X) ::= . {X.col.n = 0; X.gap.n = 0;} -session_option(X) ::= SESSION LP ids(V) cpxName(Z) COMMA tmvar(Y) RP. { - V.n += Z.n; - X.col = V; - X.gap = Y; -} - -%type windowstate_option {SWindowStateVal} -windowstate_option(X) ::= . { X.col.n = 0; X.col.z = NULL;} -windowstate_option(X) ::= STATE_WINDOW LP ids(V) RP. { X.col = V; } - -%type fill_opt {SArray*} -%destructor fill_opt {taosArrayDestroy($$);} -fill_opt(N) ::= . { N = 0; } -fill_opt(N) ::= FILL LP ID(Y) COMMA tagitemlist(X) RP. { - SVariant A = {0}; - toTSDBType(Y.type); - taosVariantCreate(&A, Y.z, Y.n, Y.type); - - tListItemInsert(X, &A, -1, 0); - N = X; -} - -fill_opt(N) ::= FILL LP ID(Y) RP. { - toTSDBType(Y.type); - N = tListItemAppendToken(NULL, &Y, -1); -} - -%type sliding_opt {SToken} -sliding_opt(K) ::= SLIDING LP tmvar(E) RP. {K = E; } -sliding_opt(K) ::= . {K.n = 0; K.z = NULL; K.type = 0; } - -%type orderby_opt {SArray*} -%destructor orderby_opt {taosArrayDestroy($$);} - -%type sortlist {SArray*} -%destructor sortlist {taosArrayDestroy($$);} - -%type sortitem {SVariant} -%destructor sortitem {taosVariantDestroy(&$$);} - -orderby_opt(A) ::= . {A = 0;} -orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} - -sortlist(A) ::= sortlist(X) COMMA item(Y) sortorder(Z). { - A = tListItemAppend(X, &Y, Z); -} - -sortlist(A) ::= item(Y) sortorder(Z). { - A = tListItemAppend(NULL, &Y, Z); -} - -%type item {SVariant} -item(A) ::= ids(X) cpxName(Y). { - toTSDBType(X.type); - X.n += Y.n; - - taosVariantCreate(&A, X.z, X.n, X.type); -} - -%type sortorder {int} -sortorder(A) ::= ASC. { A = TSDB_ORDER_ASC; } -sortorder(A) ::= DESC. { A = TSDB_ORDER_DESC;} -sortorder(A) ::= . { A = TSDB_ORDER_ASC; } // Ascending order by default - -//group by clause -%type groupby_opt {SArray*} -%destructor groupby_opt {taosArrayDestroy($$);} -%type grouplist {SArray*} -%destructor grouplist {taosArrayDestroy($$);} - -groupby_opt(A) ::= . { A = 0;} -groupby_opt(A) ::= GROUP BY grouplist(X). { A = X;} - -grouplist(A) ::= grouplist(X) COMMA item(Y). { - A = tListItemAppend(X, &Y, -1); -} - -grouplist(A) ::= item(X). { - A = tListItemAppend(NULL, &X, -1); -} - -//having clause, ignore the input condition in having -%type having_opt {tSqlExpr*} -%destructor having_opt {tSqlExprDestroy($$);} -having_opt(A) ::=. {A = 0;} -having_opt(A) ::= HAVING expr(X). {A = X;} - -//limit-offset subclause -%type limit_opt {SLimit} -limit_opt(A) ::= . {A.limit = -1; A.offset = 0;} -limit_opt(A) ::= LIMIT signed(X). {A.limit = X; A.offset = 0;} -limit_opt(A) ::= LIMIT signed(X) OFFSET signed(Y). - { A.limit = X; A.offset = Y;} -limit_opt(A) ::= LIMIT signed(X) COMMA signed(Y). - { A.limit = Y; A.offset = X;} - -%type slimit_opt {SLimit} -slimit_opt(A) ::= . {A.limit = -1; A.offset = 0;} -slimit_opt(A) ::= SLIMIT signed(X). {A.limit = X; A.offset = 0;} -slimit_opt(A) ::= SLIMIT signed(X) SOFFSET signed(Y). - {A.limit = X; A.offset = Y;} -slimit_opt(A) ::= SLIMIT signed(X) COMMA signed(Y). - {A.limit = Y; A.offset = X;} - -%type where_opt {tSqlExpr*} -%destructor where_opt {tSqlExprDestroy($$);} - -where_opt(A) ::= . {A = 0;} -where_opt(A) ::= WHERE expr(X). {A = X;} - -/////////////////////////// Expression Processing ///////////////////////////// -// -%type expr {tSqlExpr*} -%destructor expr {tSqlExprDestroy($$);} - -expr(A) ::= LP(X) expr(Y) RP(Z). {A = Y; A->exprToken.z = X.z; A->exprToken.n = (Z.z - X.z + 1);} - -expr(A) ::= ID(X). { A = tSqlExprCreateIdValue(&X, TK_ID);} -expr(A) ::= ID(X) DOT ID(Y). { X.n += (1+Y.n); A = tSqlExprCreateIdValue(&X, TK_ID);} -expr(A) ::= ID(X) DOT STAR(Y). { X.n += (1+Y.n); A = tSqlExprCreateIdValue(&X, TK_ALL);} - -expr(A) ::= INTEGER(X). { A = tSqlExprCreateIdValue(&X, TK_INTEGER);} -expr(A) ::= MINUS(X) INTEGER(Y). { X.n += Y.n; X.type = TK_INTEGER; A = tSqlExprCreateIdValue(&X, TK_INTEGER);} -expr(A) ::= PLUS(X) INTEGER(Y). { X.n += Y.n; X.type = TK_INTEGER; A = tSqlExprCreateIdValue(&X, TK_INTEGER);} -expr(A) ::= FLOAT(X). { A = tSqlExprCreateIdValue(&X, TK_FLOAT);} -expr(A) ::= MINUS(X) FLOAT(Y). { X.n += Y.n; X.type = TK_FLOAT; A = tSqlExprCreateIdValue(&X, TK_FLOAT);} -expr(A) ::= PLUS(X) FLOAT(Y). { X.n += Y.n; X.type = TK_FLOAT; A = tSqlExprCreateIdValue(&X, TK_FLOAT);} -expr(A) ::= STRING(X). { A = tSqlExprCreateIdValue(&X, TK_STRING);} -expr(A) ::= NOW(X). { A = tSqlExprCreateIdValue(&X, TK_NOW); } -expr(A) ::= VARIABLE(X). { A = tSqlExprCreateIdValue(&X, TK_VARIABLE);} -expr(A) ::= PLUS(X) VARIABLE(Y). { X.n += Y.n; X.type = TK_VARIABLE; A = tSqlExprCreateIdValue(&X, TK_VARIABLE);} -expr(A) ::= MINUS(X) VARIABLE(Y). { X.n += Y.n; X.type = TK_VARIABLE; A = tSqlExprCreateIdValue(&X, TK_VARIABLE);} -expr(A) ::= BOOL(X). { A = tSqlExprCreateIdValue(&X, TK_BOOL);} -expr(A) ::= NULL(X). { A = tSqlExprCreateIdValue(&X, TK_NULL);} - -// ordinary functions: min(x), max(x), top(k, 20) -expr(A) ::= ID(X) LP exprlist(Y) RP(E). { tRecordFuncName(pInfo->funcs, &X); A = tSqlExprCreateFunction(Y, &X, &E, X.type); } - -// for parsing sql functions with wildcard for parameters. e.g., count(*)/first(*)/last(*) operation -expr(A) ::= ID(X) LP STAR RP(Y). { tRecordFuncName(pInfo->funcs, &X); A = tSqlExprCreateFunction(NULL, &X, &Y, X.type); } - -// is (not) null expression -expr(A) ::= expr(X) IS NULL. {A = tSqlExprCreate(X, NULL, TK_ISNULL);} -expr(A) ::= expr(X) IS NOT NULL. {A = tSqlExprCreate(X, NULL, TK_NOTNULL);} - -// relational expression -expr(A) ::= expr(X) LT expr(Y). {A = tSqlExprCreate(X, Y, TK_LT);} -expr(A) ::= expr(X) GT expr(Y). {A = tSqlExprCreate(X, Y, TK_GT);} -expr(A) ::= expr(X) LE expr(Y). {A = tSqlExprCreate(X, Y, TK_LE);} -expr(A) ::= expr(X) GE expr(Y). {A = tSqlExprCreate(X, Y, TK_GE);} -expr(A) ::= expr(X) NE expr(Y). {A = tSqlExprCreate(X, Y, TK_NE);} -expr(A) ::= expr(X) EQ expr(Y). {A = tSqlExprCreate(X, Y, TK_EQ);} - -expr(A) ::= expr(X) BETWEEN expr(Y) AND expr(Z). { tSqlExpr* X2 = tSqlExprClone(X); A = tSqlExprCreate(tSqlExprCreate(X, Y, TK_GE), tSqlExprCreate(X2, Z, TK_LE), TK_AND);} - -expr(A) ::= expr(X) AND expr(Y). {A = tSqlExprCreate(X, Y, TK_AND);} -expr(A) ::= expr(X) OR expr(Y). {A = tSqlExprCreate(X, Y, TK_OR); } - -// binary arithmetic expression -expr(A) ::= expr(X) PLUS expr(Y). {A = tSqlExprCreate(X, Y, TK_PLUS); } -expr(A) ::= expr(X) MINUS expr(Y). {A = tSqlExprCreate(X, Y, TK_MINUS); } -expr(A) ::= expr(X) STAR expr(Y). {A = tSqlExprCreate(X, Y, TK_STAR); } -expr(A) ::= expr(X) SLASH expr(Y). {A = tSqlExprCreate(X, Y, TK_DIVIDE);} -expr(A) ::= expr(X) REM expr(Y). {A = tSqlExprCreate(X, Y, TK_REM); } - -// like expression -expr(A) ::= expr(X) LIKE expr(Y). {A = tSqlExprCreate(X, Y, TK_LIKE); } - -// match expression -expr(A) ::= expr(X) MATCH expr(Y). {A = tSqlExprCreate(X, Y, TK_MATCH); } -expr(A) ::= expr(X) NMATCH expr(Y). {A = tSqlExprCreate(X, Y, TK_NMATCH); } - -//in expression -expr(A) ::= expr(X) IN LP exprlist(Y) RP. {A = tSqlExprCreate(X, (tSqlExpr*)Y, TK_IN); } - -%type exprlist {SArray*} -%destructor exprlist {tSqlExprListDestroy($$);} - -%type expritem {tSqlExpr*} -%destructor expritem {tSqlExprDestroy($$);} - -exprlist(A) ::= exprlist(X) COMMA expritem(Y). {A = tSqlExprListAppend(X,Y,0, 0);} -exprlist(A) ::= expritem(X). {A = tSqlExprListAppend(0,X,0, 0);} -expritem(A) ::= expr(X). {A = X;} -expritem(A) ::= . {A = 0;} - -///////////////////////////////////reset query cache////////////////////////////////////// -cmd ::= RESET QUERY CACHE. { setDCLSqlElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} - -///////////////////////////////////sync replica database////////////////////////////////// -cmd ::= SYNCDB ids(X) REPLICA.{ setDCLSqlElems(pInfo, TSDB_SQL_SYNC_DB_REPLICA, 1, &X);} - -///////////////////////////////////ALTER TABLE statement////////////////////////////////// -cmd ::= ALTER TABLE ids(X) cpxName(F) ADD COLUMN columnlist(A). { - X.n += F.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER TABLE ids(X) cpxName(F) DROP COLUMN ids(A). { - X.n += F.n; - toTSDBType(A.type); - SArray* K = tListItemAppendToken(NULL, &A, -1); - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER TABLE ids(X) cpxName(F) MODIFY COLUMN columnlist(A). { - X.n += F.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -//////////////////////////////////ALTER TAGS statement///////////////////////////////////// -cmd ::= ALTER TABLE ids(X) cpxName(Y) ADD TAG columnlist(A). { - X.n += Y.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_TAG, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} -cmd ::= ALTER TABLE ids(X) cpxName(Z) DROP TAG ids(Y). { - X.n += Z.n; - - toTSDBType(Y.type); - SArray* A = tListItemAppendToken(NULL, &Y, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_DROP_TAG, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER TABLE ids(X) cpxName(F) CHANGE TAG ids(Y) ids(Z). { - X.n += F.n; - - toTSDBType(Y.type); - SArray* A = tListItemAppendToken(NULL, &Y, -1); - - toTSDBType(Z.type); - A = tListItemAppendToken(A, &Z, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER TABLE ids(X) cpxName(F) SET TAG ids(Y) EQ tagitem(Z). { - X.n += F.n; - - toTSDBType(Y.type); - SArray* A = tListItemAppendToken(NULL, &Y, -1); - A = tListItemAppend(A, &Z, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER TABLE ids(X) cpxName(F) MODIFY TAG columnlist(A). { - X.n += F.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -///////////////////////////////////ALTER STABLE statement////////////////////////////////// -cmd ::= ALTER STABLE ids(X) cpxName(F) ADD COLUMN columnlist(A). { - X.n += F.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER STABLE ids(X) cpxName(F) DROP COLUMN ids(A). { - X.n += F.n; - - toTSDBType(A.type); - SArray* K = tListItemAppendToken(NULL, &A, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER STABLE ids(X) cpxName(F) MODIFY COLUMN columnlist(A). { - X.n += F.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -//////////////////////////////////ALTER TAGS statement///////////////////////////////////// -cmd ::= ALTER STABLE ids(X) cpxName(Y) ADD TAG columnlist(A). { - X.n += Y.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_ADD_TAG, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} -cmd ::= ALTER STABLE ids(X) cpxName(Z) DROP TAG ids(Y). { - X.n += Z.n; - - toTSDBType(Y.type); - SArray* A = tListItemAppendToken(NULL, &Y, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_DROP_TAG, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER STABLE ids(X) cpxName(F) CHANGE TAG ids(Y) ids(Z). { - X.n += F.n; - - toTSDBType(Y.type); - SArray* A = tListItemAppendToken(NULL, &Y, -1); - - toTSDBType(Z.type); - A = tListItemAppendToken(A, &Z, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER STABLE ids(X) cpxName(F) SET TAG ids(Y) EQ tagitem(Z). { - X.n += F.n; - - toTSDBType(Y.type); - SArray* A = tListItemAppendToken(NULL, &Y, -1); - A = tListItemAppend(A, &Z, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -cmd ::= ALTER STABLE ids(X) cpxName(F) MODIFY TAG columnlist(A). { - X.n += F.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&X, A, NULL, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} - -////////////////////////////////////////kill statement/////////////////////////////////////// -cmd ::= KILL CONNECTION INTEGER(Y). {setKillSql(pInfo, TSDB_SQL_KILL_CONNECTION, &Y);} -cmd ::= KILL STREAM INTEGER(X) COLON(Z) INTEGER(Y). {X.n += (Z.n + Y.n); setKillSql(pInfo, TSDB_SQL_KILL_STREAM, &X);} -cmd ::= KILL QUERY INTEGER(X) COLON(Z) INTEGER(Y). {X.n += (Z.n + Y.n); setKillSql(pInfo, TSDB_SQL_KILL_QUERY, &X);} - -%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 - LIKE MATCH NMATCH KEY OF OFFSET RAISE REPLACE RESTRICT ROW STATEMENT TRIGGER VIEW ALL - NOW IPTOKEN SEMI NONE PREV LINEAR IMPORT TBNAME JOIN STABLE NULL INSERT INTO VALUES. +%left OR. +%left AND. +//%right NOT. +%left UNION ALL MINUS EXCEPT INTERSECT. +%left NK_BITAND NK_BITOR NK_LSHIFT NK_RSHIFT. +%left NK_PLUS NK_MINUS. +//%left DIVIDE TIMES. +%left NK_STAR NK_SLASH NK_REM. +%left NK_CONCAT. +//%right NK_BITNOT. + +/************************************************ create/alter/drop/show user *****************************************/ +cmd ::= CREATE USER user_name(A) PASS NK_STRING(B). { pCxt->pRootNode = createCreateUserStmt(pCxt, &A, &B);} +cmd ::= ALTER USER user_name(A) PASS NK_STRING(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_PASSWD, &B);} +cmd ::= ALTER USER user_name(A) PRIVILEGE NK_STRING(B). { pCxt->pRootNode = createAlterUserStmt(pCxt, &A, TSDB_ALTER_USER_PRIVILEGES, &B);} +cmd ::= DROP USER user_name(A). { pCxt->pRootNode = createDropUserStmt(pCxt, &A); } +cmd ::= SHOW USERS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_USERS_STMT, NULL); } + +/************************************************ create/drop/show dnode **********************************************/ +cmd ::= CREATE DNODE dnode_endpoint(A). { pCxt->pRootNode = createCreateDnodeStmt(pCxt, &A, NULL);} +cmd ::= CREATE DNODE dnode_host_name(A) PORT NK_INTEGER(B). { pCxt->pRootNode = createCreateDnodeStmt(pCxt, &A, &B);} +cmd ::= DROP DNODE NK_INTEGER(A). { pCxt->pRootNode = createDropDnodeStmt(pCxt, &A);} +cmd ::= DROP DNODE dnode_endpoint(A). { pCxt->pRootNode = createDropDnodeStmt(pCxt, &A);} +cmd ::= SHOW DNODES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DNODES_STMT, NULL); } + +%type dnode_endpoint { SToken } +%destructor dnode_endpoint { } +dnode_endpoint(A) ::= NK_STRING(B). { A = B; } + +%type dnode_host_name { SToken } +%destructor dnode_host_name { } +dnode_host_name(A) ::= NK_ID(B). { A = B; } +dnode_host_name(A) ::= NK_IPTOKEN(B). { A = B; } + +/************************************************ create/drop/show/use database ***************************************/ +cmd ::= CREATE DATABASE not_exists_opt(A) db_name(B) db_options(C). { pCxt->pRootNode = createCreateDatabaseStmt(pCxt, A, &B, C);} +cmd ::= DROP DATABASE exists_opt(A) db_name(B). { pCxt->pRootNode = createDropDatabaseStmt(pCxt, A, &B); } +cmd ::= SHOW DATABASES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DATABASES_STMT, NULL); } +cmd ::= USE db_name(A). { pCxt->pRootNode = createUseDatabaseStmt(pCxt, &A);} + +%type not_exists_opt { bool } +%destructor not_exists_opt { } +not_exists_opt(A) ::= IF NOT EXISTS. { A = true; } +not_exists_opt(A) ::= . { A = false; } + +%type exists_opt { bool } +%destructor exists_opt { } +exists_opt(A) ::= IF EXISTS. { A = true; } +exists_opt(A) ::= . { A = false; } + +%type db_options { SDatabaseOptions* } +%destructor db_options { tfree($$); } +db_options(A) ::= . { A = createDefaultDatabaseOptions(pCxt); } +db_options(A) ::= db_options(B) BLOCKS NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_BLOCKS, &C); } +db_options(A) ::= db_options(B) CACHE NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_CACHE, &C); } +db_options(A) ::= db_options(B) CACHELAST NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_CACHELAST, &C); } +db_options(A) ::= db_options(B) COMP NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_COMP, &C); } +db_options(A) ::= db_options(B) DAYS NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_DAYS, &C); } +db_options(A) ::= db_options(B) FSYNC NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_FSYNC, &C); } +db_options(A) ::= db_options(B) MAXROWS NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_MAXROWS, &C); } +db_options(A) ::= db_options(B) MINROWS NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_MINROWS, &C); } +db_options(A) ::= db_options(B) KEEP NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_KEEP, &C); } +db_options(A) ::= db_options(B) PRECISION NK_STRING(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_PRECISION, &C); } +db_options(A) ::= db_options(B) QUORUM NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_QUORUM, &C); } +db_options(A) ::= db_options(B) REPLICA NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_REPLICA, &C); } +db_options(A) ::= db_options(B) TTL NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_TTL, &C); } +db_options(A) ::= db_options(B) WAL NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_WAL, &C); } +db_options(A) ::= db_options(B) VGROUPS NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_VGROUPS, &C); } +db_options(A) ::= db_options(B) SINGLE_STABLE NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_SINGLESTABLE, &C); } +db_options(A) ::= db_options(B) STREAM_MODE NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_STREAMMODE, &C); } + +/************************************************ create/drop/show table/stable ***************************************/ +cmd ::= CREATE TABLE not_exists_opt(A) full_table_name(B) + NK_LP column_def_list(C) NK_RP tags_def_opt(D) table_options(E). { pCxt->pRootNode = createCreateTableStmt(pCxt, A, B, C, D, E);} +cmd ::= CREATE TABLE multi_create_clause(A). { pCxt->pRootNode = createCreateMultiTableStmt(pCxt, A);} +cmd ::= CREATE STABLE not_exists_opt(A) full_table_name(B) + NK_LP column_def_list(C) NK_RP tags_def(D) table_options(E). { pCxt->pRootNode = createCreateTableStmt(pCxt, A, B, C, D, E);} +cmd ::= DROP TABLE multi_drop_clause(A). { pCxt->pRootNode = createDropTableStmt(pCxt, A); } +cmd ::= DROP STABLE exists_opt(A) full_table_name(B). { pCxt->pRootNode = createDropSuperTableStmt(pCxt, A, B); } +cmd ::= SHOW TABLES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TABLES_STMT, NULL); } +cmd ::= SHOW STABLES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STABLES_STMT, NULL); } + +%type multi_create_clause { SNodeList* } +%destructor multi_create_clause { nodesDestroyList($$); } +multi_create_clause(A) ::= create_subtable_clause(B). { A = createNodeList(pCxt, B); } +multi_create_clause(A) ::= multi_create_clause(B) create_subtable_clause(C). { A = addNodeToList(pCxt, B, C); } + +create_subtable_clause(A) ::= + not_exists_opt(B) full_table_name(C) USING full_table_name(D) + specific_tags_opt(E) TAGS NK_LP literal_list(F) NK_RP. { A = createCreateSubTableClause(pCxt, B, C, D, E, F); } + +%type multi_drop_clause { SNodeList* } +%destructor multi_drop_clause { nodesDestroyList($$); } +multi_drop_clause(A) ::= drop_table_clause(B). { A = createNodeList(pCxt, B); } +multi_drop_clause(A) ::= multi_drop_clause(B) drop_table_clause(C). { A = addNodeToList(pCxt, B, C); } + +drop_table_clause(A) ::= exists_opt(B) full_table_name(C). { A = createDropTableClause(pCxt, B, C); } + +%type specific_tags_opt { SNodeList* } +%destructor specific_tags_opt { nodesDestroyList($$); } +specific_tags_opt(A) ::= . { A = NULL; } +specific_tags_opt(A) ::= NK_LP col_name_list(B) NK_RP. { A = B; } + +full_table_name(A) ::= table_name(B). { A = createRealTableNode(pCxt, NULL, &B, NULL); } +full_table_name(A) ::= db_name(B) NK_DOT table_name(C). { A = createRealTableNode(pCxt, &B, &C, NULL); } + +%type column_def_list { SNodeList* } +%destructor column_def_list { nodesDestroyList($$); } +column_def_list(A) ::= column_def(B). { A = createNodeList(pCxt, B); } +column_def_list(A) ::= column_def_list(B) NK_COMMA column_def(C). { A = addNodeToList(pCxt, B, C); } + +column_def(A) ::= column_name(B) type_name(C). { A = createColumnDefNode(pCxt, &B, C, NULL); } +column_def(A) ::= column_name(B) type_name(C) COMMENT NK_STRING(D). { A = createColumnDefNode(pCxt, &B, C, &D); } + +%type type_name { SDataType } +%destructor type_name { } +type_name(A) ::= BOOL. { A = createDataType(TSDB_DATA_TYPE_BOOL); } +type_name(A) ::= TINYINT. { A = createDataType(TSDB_DATA_TYPE_TINYINT); } +type_name(A) ::= SMALLINT. { A = createDataType(TSDB_DATA_TYPE_SMALLINT); } +type_name(A) ::= INT. { A = createDataType(TSDB_DATA_TYPE_INT); } +type_name(A) ::= INTEGER. { A = createDataType(TSDB_DATA_TYPE_INT); } +type_name(A) ::= BIGINT. { A = createDataType(TSDB_DATA_TYPE_BIGINT); } +type_name(A) ::= FLOAT. { A = createDataType(TSDB_DATA_TYPE_FLOAT); } +type_name(A) ::= DOUBLE. { A = createDataType(TSDB_DATA_TYPE_DOUBLE); } +type_name(A) ::= BINARY NK_LP NK_INTEGER(B) NK_RP. { A = createVarLenDataType(TSDB_DATA_TYPE_BINARY, &B); } +type_name(A) ::= TIMESTAMP. { A = createDataType(TSDB_DATA_TYPE_TIMESTAMP); } +type_name(A) ::= NCHAR NK_LP NK_INTEGER(B) NK_RP. { A = createVarLenDataType(TSDB_DATA_TYPE_NCHAR, &B); } +type_name(A) ::= TINYINT UNSIGNED. { A = createDataType(TSDB_DATA_TYPE_UTINYINT); } +type_name(A) ::= SMALLINT UNSIGNED. { A = createDataType(TSDB_DATA_TYPE_USMALLINT); } +type_name(A) ::= INT UNSIGNED. { A = createDataType(TSDB_DATA_TYPE_UINT); } +type_name(A) ::= BIGINT UNSIGNED. { A = createDataType(TSDB_DATA_TYPE_UBIGINT); } +type_name(A) ::= JSON. { A = createDataType(TSDB_DATA_TYPE_JSON); } +type_name(A) ::= VARCHAR NK_LP NK_INTEGER(B) NK_RP. { A = createVarLenDataType(TSDB_DATA_TYPE_VARCHAR, &B); } +type_name(A) ::= MEDIUMBLOB. { A = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); } +type_name(A) ::= BLOB. { A = createDataType(TSDB_DATA_TYPE_BLOB); } +type_name(A) ::= VARBINARY NK_LP NK_INTEGER(B) NK_RP. { A = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &B); } +type_name(A) ::= DECIMAL. { A = createDataType(TSDB_DATA_TYPE_DECIMAL); } +type_name(A) ::= DECIMAL NK_LP NK_INTEGER NK_RP. { A = createDataType(TSDB_DATA_TYPE_DECIMAL); } +type_name(A) ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP. { A = createDataType(TSDB_DATA_TYPE_DECIMAL); } + +%type tags_def_opt { SNodeList* } +%destructor tags_def_opt { nodesDestroyList($$); } +tags_def_opt(A) ::= . { A = NULL; } +tags_def_opt(A) ::= tags_def(B). { A = B; } + +%type tags_def { SNodeList* } +%destructor tags_def { nodesDestroyList($$); } +tags_def(A) ::= TAGS NK_LP column_def_list(B) NK_RP. { A = B; } + +%type table_options { STableOptions* } +%destructor table_options { tfree($$); } +table_options(A) ::= . { A = createDefaultTableOptions(pCxt);} +table_options(A) ::= table_options(B) COMMENT NK_STRING(C). { A = setTableOption(pCxt, B, TABLE_OPTION_COMMENT, &C); } +table_options(A) ::= table_options(B) KEEP NK_INTEGER(C). { A = setTableOption(pCxt, B, TABLE_OPTION_KEEP, &C); } +table_options(A) ::= table_options(B) TTL NK_INTEGER(C). { A = setTableOption(pCxt, B, TABLE_OPTION_TTL, &C); } +table_options(A) ::= table_options(B) SMA NK_LP col_name_list(C) NK_RP. { A = setTableSmaOption(pCxt, B, C); } + +%type col_name_list { SNodeList* } +%destructor col_name_list { nodesDestroyList($$); } +col_name_list(A) ::= col_name(B). { A = createNodeList(pCxt, B); } +col_name_list(A) ::= col_name_list(B) NK_COMMA col_name(C). { A = addNodeToList(pCxt, B, C); } + +col_name(A) ::= column_name(B). { A = createColumnNode(pCxt, NULL, &B); } + +/************************************************ show vgroups ********************************************************/ +cmd ::= SHOW VGROUPS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, NULL); } +cmd ::= SHOW db_name(B) NK_DOT VGROUPS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, &B); } + +/************************************************ show mnodes *********************************************************/ +cmd ::= SHOW MNODES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MNODES_STMT, NULL); } + +/************************************************ select **************************************************************/ +cmd ::= query_expression(A). { pCxt->pRootNode = A; } + +/************************************************ literal *************************************************************/ +literal(A) ::= NK_INTEGER(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B)); } +literal(A) ::= NK_FLOAT(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B)); } +literal(A) ::= NK_STRING(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &B)); } +literal(A) ::= NK_BOOL(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &B)); } +literal(A) ::= TIMESTAMP(B) NK_STRING(C). { A = createRawExprNodeExt(pCxt, &B, &C, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &C)); } +literal(A) ::= duration_literal(B). { A = B; } + +duration_literal(A) ::= NK_VARIABLE(B). { A = createRawExprNode(pCxt, &B, createDurationValueNode(pCxt, &B)); } + +%type literal_list { SNodeList* } +%destructor literal_list { nodesDestroyList($$); } +literal_list(A) ::= literal(B). { A = createNodeList(pCxt, releaseRawExprNode(pCxt, B)); } +literal_list(A) ::= literal_list(B) NK_COMMA literal(C). { A = addNodeToList(pCxt, B, releaseRawExprNode(pCxt, C)); } + +/************************************************ names and identifiers ***********************************************/ +%type db_name { SToken } +%destructor db_name { } +db_name(A) ::= NK_ID(B). { A = B; } + +%type table_name { SToken } +%destructor table_name { } +table_name(A) ::= NK_ID(B). { A = B; } + +%type column_name { SToken } +%destructor column_name { } +column_name(A) ::= NK_ID(B). { A = B; } + +%type function_name { SToken } +%destructor function_name { } +function_name(A) ::= NK_ID(B). { A = B; } + +%type table_alias { SToken } +%destructor table_alias { } +table_alias(A) ::= NK_ID(B). { A = B; } + +%type column_alias { SToken } +%destructor column_alias { } +column_alias(A) ::= NK_ID(B). { A = B; } + +%type user_name { SToken } +%destructor user_name { } +user_name(A) ::= NK_ID(B). { A = B; } + +/************************************************ expression **********************************************************/ +expression(A) ::= literal(B). { A = B; } +//expression(A) ::= NK_QUESTION(B). { A = B; } +//expression(A) ::= pseudo_column(B). { A = B; } +expression(A) ::= column_reference(B). { A = B; } +expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); } +expression(A) ::= function_name(B) NK_LP NK_STAR(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, createNodeList(pCxt, createColumnNode(pCxt, NULL, &C)))); } +//expression(A) ::= cast_expression(B). { A = B; } +//expression(A) ::= case_expression(B). { A = B; } +expression(A) ::= subquery(B). { A = B; } +expression(A) ::= NK_LP(B) expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); } +expression(A) ::= NK_PLUS(B) expression(C). { + SToken t = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &B, &t, releaseRawExprNode(pCxt, C)); + } +expression(A) ::= NK_MINUS(B) expression(C). { + SToken t = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &B, &t, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, C), NULL)); + } +expression(A) ::= expression(B) NK_PLUS expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } +expression(A) ::= expression(B) NK_MINUS expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } +expression(A) ::= expression(B) NK_STAR expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } +expression(A) ::= expression(B) NK_SLASH expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } +expression(A) ::= expression(B) NK_REM expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MOD, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } + +%type expression_list { SNodeList* } +%destructor expression_list { nodesDestroyList($$); } +expression_list(A) ::= expression(B). { A = createNodeList(pCxt, releaseRawExprNode(pCxt, B)); } +expression_list(A) ::= expression_list(B) NK_COMMA expression(C). { A = addNodeToList(pCxt, B, releaseRawExprNode(pCxt, C)); } + +column_reference(A) ::= column_name(B). { A = createRawExprNode(pCxt, &B, createColumnNode(pCxt, NULL, &B)); } +column_reference(A) ::= table_name(B) NK_DOT column_name(C). { A = createRawExprNodeExt(pCxt, &B, &C, createColumnNode(pCxt, &B, &C)); } + +//pseudo_column(A) ::= NK_NOW. { A = createFunctionNode(pCxt, NULL, NULL); } + +/************************************************ predicate ***********************************************************/ +predicate(A) ::= expression(B) compare_op(C) expression(D). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, D); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); + } +//predicate(A) ::= expression(B) compare_op sub_type expression(B). +predicate(A) ::= expression(B) BETWEEN expression(C) AND expression(D). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, D); + A = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D))); + } +predicate(A) ::= expression(B) NOT BETWEEN expression(C) AND expression(D). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, D); + A = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); + } +predicate(A) ::= expression(B) IS NULL(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, B), NULL)); + } +predicate(A) ::= expression(B) IS NOT NULL(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, B), NULL)); + } +predicate(A) ::= expression(B) in_op(C) in_predicate_value(D). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, D); + A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); + } + +%type compare_op { EOperatorType } +%destructor compare_op { } +compare_op(A) ::= NK_LT. { A = OP_TYPE_LOWER_THAN; } +compare_op(A) ::= NK_GT. { A = OP_TYPE_GREATER_THAN; } +compare_op(A) ::= NK_LE. { A = OP_TYPE_LOWER_EQUAL; } +compare_op(A) ::= NK_GE. { A = OP_TYPE_GREATER_EQUAL; } +compare_op(A) ::= NK_NE. { A = OP_TYPE_NOT_EQUAL; } +compare_op(A) ::= NK_EQ. { A = OP_TYPE_EQUAL; } +compare_op(A) ::= LIKE. { A = OP_TYPE_LIKE; } +compare_op(A) ::= NOT LIKE. { A = OP_TYPE_NOT_LIKE; } +compare_op(A) ::= MATCH. { A = OP_TYPE_MATCH; } +compare_op(A) ::= NMATCH. { A = OP_TYPE_NMATCH; } + +%type in_op { EOperatorType } +%destructor in_op { } +in_op(A) ::= IN. { A = OP_TYPE_IN; } +in_op(A) ::= NOT IN. { A = OP_TYPE_NOT_IN; } + +in_predicate_value(A) ::= NK_LP(C) expression_list(B) NK_RP(D). { A = createRawExprNodeExt(pCxt, &C, &D, createNodeListNode(pCxt, B)); } + +/************************************************ boolean_value_expression ********************************************/ +boolean_value_expression(A) ::= boolean_primary(B). { A = B; } +boolean_value_expression(A) ::= NOT(C) boolean_primary(B). { + SToken e = getTokenFromRawExprNode(pCxt, B); + A = createRawExprNodeExt(pCxt, &C, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, B), NULL)); + } +boolean_value_expression(A) ::= + boolean_value_expression(B) OR boolean_value_expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } +boolean_value_expression(A) ::= + boolean_value_expression(B) AND boolean_value_expression(C). { + SToken s = getTokenFromRawExprNode(pCxt, B); + SToken e = getTokenFromRawExprNode(pCxt, C); + A = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); + } + +boolean_primary(A) ::= predicate(B). { A = B; } +boolean_primary(A) ::= NK_LP(C) boolean_value_expression(B) NK_RP(D). { A = createRawExprNodeExt(pCxt, &C, &D, releaseRawExprNode(pCxt, B)); } + +/************************************************ common_expression ********************************************/ +common_expression(A) ::= expression(B). { A = B; } +common_expression(A) ::= boolean_value_expression(B). { A = B; } + +/************************************************ from_clause *********************************************************/ +from_clause(A) ::= FROM table_reference_list(B). { A = B; } + +table_reference_list(A) ::= table_reference(B). { A = B; } +table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { A = createJoinTableNode(pCxt, JOIN_TYPE_INNER, B, C, NULL); } + +/************************************************ table_reference *****************************************************/ +table_reference(A) ::= table_primary(B). { A = B; } +table_reference(A) ::= joined_table(B). { A = B; } + +table_primary(A) ::= table_name(B) alias_opt(C). { A = createRealTableNode(pCxt, NULL, &B, &C); } +table_primary(A) ::= db_name(B) NK_DOT table_name(C) alias_opt(D). { A = createRealTableNode(pCxt, &B, &C, &D); } +table_primary(A) ::= subquery(B) alias_opt(C). { A = createTempTableNode(pCxt, releaseRawExprNode(pCxt, B), &C); } +table_primary(A) ::= parenthesized_joined_table(B). { A = B; } + +%type alias_opt { SToken } +%destructor alias_opt { } +alias_opt(A) ::= . { A = nil_token; } +alias_opt(A) ::= table_alias(B). { A = B; } +alias_opt(A) ::= AS table_alias(B). { A = B; } + +parenthesized_joined_table(A) ::= NK_LP joined_table(B) NK_RP. { A = B; } +parenthesized_joined_table(A) ::= NK_LP parenthesized_joined_table(B) NK_RP. { A = B; } + +/************************************************ joined_table ********************************************************/ +joined_table(A) ::= + table_reference(B) join_type(C) JOIN table_reference(D) ON search_condition(E). { A = createJoinTableNode(pCxt, C, B, D, E); } + +%type join_type { EJoinType } +%destructor join_type { } +join_type(A) ::= . { A = JOIN_TYPE_INNER; } +join_type(A) ::= INNER. { A = JOIN_TYPE_INNER; } + +/************************************************ query_specification *************************************************/ +query_specification(A) ::= + SELECT set_quantifier_opt(B) select_list(C) from_clause(D) where_clause_opt(E) + partition_by_clause_opt(F) twindow_clause_opt(G) + group_by_clause_opt(H) having_clause_opt(I). { + A = createSelectStmt(pCxt, B, C, D); + A = addWhereClause(pCxt, A, E); + A = addPartitionByClause(pCxt, A, F); + A = addWindowClauseClause(pCxt, A, G); + A = addGroupByClause(pCxt, A, H); + A = addHavingClause(pCxt, A, I); + } + +%type set_quantifier_opt { bool } +%destructor set_quantifier_opt { } +set_quantifier_opt(A) ::= . { A = false; } +set_quantifier_opt(A) ::= DISTINCT. { A = true; } +set_quantifier_opt(A) ::= ALL. { A = false; } + +%type select_list { SNodeList* } +%destructor select_list { nodesDestroyList($$); } +select_list(A) ::= NK_STAR. { A = NULL; } +select_list(A) ::= select_sublist(B). { A = B; } + +%type select_sublist { SNodeList* } +%destructor select_sublist { nodesDestroyList($$); } +select_sublist(A) ::= select_item(B). { A = createNodeList(pCxt, B); } +select_sublist(A) ::= select_sublist(B) NK_COMMA select_item(C). { A = addNodeToList(pCxt, B, C); } + +select_item(A) ::= common_expression(B). { + SToken t = getTokenFromRawExprNode(pCxt, B); + A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &t); + } +select_item(A) ::= common_expression(B) column_alias(C). { A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &C); } +select_item(A) ::= common_expression(B) AS column_alias(C). { A = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, B), &C); } +select_item(A) ::= table_name(B) NK_DOT NK_STAR(C). { A = createColumnNode(pCxt, &B, &C); } + +where_clause_opt(A) ::= . { A = NULL; } +where_clause_opt(A) ::= WHERE search_condition(B). { A = B; } + +%type partition_by_clause_opt { SNodeList* } +%destructor partition_by_clause_opt { nodesDestroyList($$); } +partition_by_clause_opt(A) ::= . { A = NULL; } +partition_by_clause_opt(A) ::= PARTITION BY expression_list(B). { A = B; } + +twindow_clause_opt(A) ::= . { A = NULL; } +twindow_clause_opt(A) ::= + SESSION NK_LP column_reference(B) NK_COMMA NK_INTEGER(C) NK_RP. { A = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, B), &C); } +twindow_clause_opt(A) ::= STATE_WINDOW NK_LP column_reference(B) NK_RP. { A = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, B)); } +twindow_clause_opt(A) ::= + INTERVAL NK_LP duration_literal(B) NK_RP sliding_opt(C) fill_opt(D). { A = createIntervalWindowNode(pCxt, B, NULL, C, D); } +twindow_clause_opt(A) ::= + INTERVAL NK_LP duration_literal(B) NK_COMMA duration_literal(C) NK_RP + sliding_opt(D) fill_opt(E). { A = createIntervalWindowNode(pCxt, B, C, D, E); } + +sliding_opt(A) ::= . { A = NULL; } +sliding_opt(A) ::= SLIDING NK_LP duration_literal(B) NK_RP. { A = B; } + +fill_opt(A) ::= . { A = NULL; } +fill_opt(A) ::= FILL NK_LP fill_mode(B) NK_RP. { A = createFillNode(pCxt, B, NULL); } +fill_opt(A) ::= FILL NK_LP VALUE NK_COMMA literal_list(B) NK_RP. { A = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, B)); } + +%type fill_mode { EFillMode } +%destructor fill_mode { } +fill_mode(A) ::= NONE. { A = FILL_MODE_NONE; } +fill_mode(A) ::= PREV. { A = FILL_MODE_PREV; } +fill_mode(A) ::= NULL. { A = FILL_MODE_NULL; } +fill_mode(A) ::= LINEAR. { A = FILL_MODE_LINEAR; } +fill_mode(A) ::= NEXT. { A = FILL_MODE_NEXT; } + +%type group_by_clause_opt { SNodeList* } +%destructor group_by_clause_opt { nodesDestroyList($$); } +group_by_clause_opt(A) ::= . { A = NULL; } +group_by_clause_opt(A) ::= GROUP BY group_by_list(B). { A = B; } + +%type group_by_list { SNodeList* } +%destructor group_by_list { nodesDestroyList($$); } +group_by_list(A) ::= expression(B). { A = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, B))); } +group_by_list(A) ::= group_by_list(B) NK_COMMA expression(C). { A = addNodeToList(pCxt, B, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, C))); } + +having_clause_opt(A) ::= . { A = NULL; } +having_clause_opt(A) ::= HAVING search_condition(B). { A = B; } + +/************************************************ query_expression ****************************************************/ +query_expression(A) ::= + query_expression_body(B) + order_by_clause_opt(C) slimit_clause_opt(D) limit_clause_opt(E). { + A = addOrderByClause(pCxt, B, C); + A = addSlimitClause(pCxt, A, D); + A = addLimitClause(pCxt, A, E); + } + +query_expression_body(A) ::= query_primary(B). { A = B; } +query_expression_body(A) ::= + query_expression_body(B) UNION ALL query_expression_body(D). { A = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, B, D); } + +query_primary(A) ::= query_specification(B). { A = B; } +//query_primary(A) ::= +// NK_LP query_expression_body(B) +// order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP. { A = B;} + +%type order_by_clause_opt { SNodeList* } +%destructor order_by_clause_opt { nodesDestroyList($$); } +order_by_clause_opt(A) ::= . { A = NULL; } +order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { A = B; } + +slimit_clause_opt(A) ::= . { A = NULL; } +slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B). { A = createLimitNode(pCxt, &B, NULL); } +slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B) SOFFSET NK_INTEGER(C). { A = createLimitNode(pCxt, &B, &C); } +slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); } + +limit_clause_opt(A) ::= . { A = NULL; } +limit_clause_opt(A) ::= LIMIT NK_INTEGER(B). { A = createLimitNode(pCxt, &B, NULL); } +limit_clause_opt(A) ::= LIMIT NK_INTEGER(B) OFFSET NK_INTEGER(C). { A = createLimitNode(pCxt, &B, &C); } +limit_clause_opt(A) ::= LIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); } + +/************************************************ subquery ************************************************************/ +subquery(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, C); } + +/************************************************ search_condition ****************************************************/ +search_condition(A) ::= common_expression(B). { A = releaseRawExprNode(pCxt, B); } + +/************************************************ sort_specification_list *********************************************/ +%type sort_specification_list { SNodeList* } +%destructor sort_specification_list { nodesDestroyList($$); } +sort_specification_list(A) ::= sort_specification(B). { A = createNodeList(pCxt, B); } +sort_specification_list(A) ::= + sort_specification_list(B) NK_COMMA sort_specification(C). { A = addNodeToList(pCxt, B, C); } + +sort_specification(A) ::= + expression(B) ordering_specification_opt(C) null_ordering_opt(D). { A = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, B), C, D); } + +%type ordering_specification_opt EOrder +%destructor ordering_specification_opt { } +ordering_specification_opt(A) ::= . { A = ORDER_ASC; } +ordering_specification_opt(A) ::= ASC. { A = ORDER_ASC; } +ordering_specification_opt(A) ::= DESC. { A = ORDER_DESC; } + +%type null_ordering_opt ENullOrder +%destructor null_ordering_opt { } +null_ordering_opt(A) ::= . { A = NULL_ORDER_DEFAULT; } +null_ordering_opt(A) ::= NULLS FIRST. { A = NULL_ORDER_FIRST; } +null_ordering_opt(A) ::= NULLS LAST. { A = NULL_ORDER_LAST; } diff --git a/source/libs/parser/src/astCreateContext.c b/source/libs/parser/src/astCreateContext.c deleted file mode 100644 index a8c82780cac4faaa132cb842de6d4529a44c3395..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/astCreateContext.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "ttoken.h" -#include "astCreateContext.h" - -int32_t createAstCreateContext(SParseContext* pQueryCxt, SAstCreateContext* pCxt) { - pCxt->pQueryCxt = pQueryCxt; - pCxt->notSupport = false; - pCxt->valid = true; - pCxt->pRootNode = NULL; - return TSDB_CODE_SUCCESS; -} - -int32_t destroyAstCreateContext(SAstCreateContext* pCxt) { - return TSDB_CODE_SUCCESS; -} diff --git a/source/libs/parser/src/astCreateFuncs.c b/source/libs/parser/src/astCreateFuncs.c deleted file mode 100644 index c129ebeef1473a3c0c209908bbb86118b7b59862..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/astCreateFuncs.c +++ /dev/null @@ -1,384 +0,0 @@ - -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "astCreateFuncs.h" - -#define CHECK_OUT_OF_MEM(p) \ - do { \ - if (NULL == (p)) { \ - pCxt->valid = false; \ - return NULL; \ - } \ - } while (0) - -#define CHECK_RAW_EXPR_NODE(node) \ - do { \ - if (NULL == (node) || QUERY_NODE_RAW_EXPR != nodeType(node)) { \ - pCxt->valid = false; \ - return NULL; \ - } \ - } while (0) - -SToken nil_token = { .type = TK_NIL, .n = 0, .z = NULL }; - -static bool checkDbName(SAstCreateContext* pCxt, const SToken* pDbName) { - if (NULL == pDbName) { - return true; - } - pCxt->valid = pDbName->n < TSDB_DB_NAME_LEN ? true : false; - return pCxt->valid; -} - -static bool checkTableName(SAstCreateContext* pCxt, const SToken* pTableName) { - if (NULL == pTableName) { - return true; - } - pCxt->valid = pTableName->n < TSDB_TABLE_NAME_LEN ? true : false; - return pCxt->valid; -} - -static bool checkColumnName(SAstCreateContext* pCxt, const SToken* pColumnName) { - if (NULL == pColumnName) { - return true; - } - pCxt->valid = pColumnName->n < TSDB_COL_NAME_LEN ? true : false; - return pCxt->valid; -} - -SNode* createRawExprNode(SAstCreateContext* pCxt, const SToken* pToken, SNode* pNode) { - SRawExprNode* target = (SRawExprNode*)nodesMakeNode(QUERY_NODE_RAW_EXPR); - CHECK_OUT_OF_MEM(target); - target->p = pToken->z; - target->n = pToken->n; - target->pNode = pNode; - return (SNode*)target; -} - -SNode* createRawExprNodeExt(SAstCreateContext* pCxt, const SToken* pStart, const SToken* pEnd, SNode* pNode) { - SRawExprNode* target = (SRawExprNode*)nodesMakeNode(QUERY_NODE_RAW_EXPR); - CHECK_OUT_OF_MEM(target); - target->p = pStart->z; - target->n = (pEnd->z + pEnd->n) - pStart->z; - target->pNode = pNode; - return (SNode*)target; -} - -SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { - CHECK_RAW_EXPR_NODE(pNode); - SNode* tmp = ((SRawExprNode*)pNode)->pNode; - tfree(pNode); - return tmp; -} - -SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { - if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) { - pCxt->valid = false; - return nil_token; - } - SRawExprNode* target = (SRawExprNode*)pNode; - SToken t = { .type = 0, .z = target->p, .n = target->n}; - return t; -} - -SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) { - SNodeList* list = nodesMakeList(); - CHECK_OUT_OF_MEM(list); - if (TSDB_CODE_SUCCESS != nodesListAppend(list, pNode)) { - pCxt->valid = false; - } - return list; -} - -SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) { - if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pNode)) { - pCxt->valid = false; - } - return pList; -} - -SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableAlias, const SToken* pColumnName) { - if (!checkTableName(pCxt, pTableAlias) || !checkColumnName(pCxt, pColumnName)) { - return NULL; - } - SColumnNode* col = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - CHECK_OUT_OF_MEM(col); - if (NULL != pTableAlias) { - strncpy(col->tableAlias, pTableAlias->z, pTableAlias->n); - } - strncpy(col->colName, pColumnName->z, pColumnName->n); - return (SNode*)col; -} - -SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral) { - SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); - CHECK_OUT_OF_MEM(val); - val->literal = strndup(pLiteral->z, pLiteral->n); - CHECK_OUT_OF_MEM(val->literal); - val->node.resType.type = dataType; - val->node.resType.bytes = tDataTypes[dataType].bytes; - if (TSDB_DATA_TYPE_TIMESTAMP == dataType) { - val->node.resType.precision = TSDB_TIME_PRECISION_MILLI; - } - return (SNode*)val; -} - -SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) { - SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); - CHECK_OUT_OF_MEM(val); - val->literal = strndup(pLiteral->z, pLiteral->n); - CHECK_OUT_OF_MEM(val->literal); - val->isDuration = true; - val->node.resType.type = TSDB_DATA_TYPE_BIGINT; - val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - val->node.resType.precision = TSDB_TIME_PRECISION_MILLI; - return (SNode*)val; -} - -SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2) { - SLogicConditionNode* cond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); - CHECK_OUT_OF_MEM(cond); - cond->condType = type; - cond->pParameterList = nodesMakeList(); - nodesListAppend(cond->pParameterList, pParam1); - nodesListAppend(cond->pParameterList, pParam2); - return (SNode*)cond; -} - -SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight) { - SOperatorNode* op = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR); - CHECK_OUT_OF_MEM(op); - op->opType = type; - op->pLeft = pLeft; - op->pRight = pRight; - return (SNode*)op; -} - -SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight) { - return createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, - createOperatorNode(pCxt, OP_TYPE_GREATER_EQUAL, pExpr, pLeft), createOperatorNode(pCxt, OP_TYPE_LOWER_EQUAL, pExpr, pRight)); -} - -SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight) { - return createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, - createOperatorNode(pCxt, OP_TYPE_LOWER_THAN, pExpr, pLeft), createOperatorNode(pCxt, OP_TYPE_GREATER_THAN, pExpr, pRight)); -} - -SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList) { - SFunctionNode* func = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); - CHECK_OUT_OF_MEM(func); - strncpy(func->functionName, pFuncName->z, pFuncName->n); - func->pParameterList = pParameterList; - return (SNode*)func; -} - -SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList) { - SNodeListNode* list = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); - CHECK_OUT_OF_MEM(list); - list->pNodeList = pList; - return (SNode*)list; -} - -SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName, const SToken* pTableAlias) { - if (!checkDbName(pCxt, pDbName) || !checkTableName(pCxt, pTableName)) { - return NULL; - } - SRealTableNode* realTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE); - CHECK_OUT_OF_MEM(realTable); - if (NULL != pDbName) { - strncpy(realTable->table.dbName, pDbName->z, pDbName->n); - } else { - strcpy(realTable->table.dbName, pCxt->pQueryCxt->db); - } - if (NULL != pTableAlias && TK_NIL != pTableAlias->type) { - strncpy(realTable->table.tableAlias, pTableAlias->z, pTableAlias->n); - } else { - strncpy(realTable->table.tableAlias, pTableName->z, pTableName->n); - } - strncpy(realTable->table.tableName, pTableName->z, pTableName->n); - return (SNode*)realTable; -} - -SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const SToken* pTableAlias) { - STempTableNode* tempTable = (STempTableNode*)nodesMakeNode(QUERY_NODE_TEMP_TABLE); - CHECK_OUT_OF_MEM(tempTable); - tempTable->pSubquery = pSubquery; - if (NULL != pTableAlias && TK_NIL != pTableAlias->type) { - strncpy(tempTable->table.tableAlias, pTableAlias->z, pTableAlias->n); - } - return (SNode*)tempTable; -} - -SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, SNode* pLeft, SNode* pRight, SNode* pJoinCond) { - SJoinTableNode* joinTable = (SJoinTableNode*)nodesMakeNode(QUERY_NODE_JOIN_TABLE); - CHECK_OUT_OF_MEM(joinTable); - joinTable->joinType = type; - joinTable->pLeft = pLeft; - joinTable->pRight = pRight; - joinTable->pOnCond = pJoinCond; - return (SNode*)joinTable; -} - -SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset) { - SLimitNode* limitNode = (SLimitNode*)nodesMakeNode(QUERY_NODE_LIMIT); - CHECK_OUT_OF_MEM(limitNode); - // limitNode->limit = limit; - // limitNode->offset = offset; - return (SNode*)limitNode; -} - -SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder) { - SOrderByExprNode* orderByExpr = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR); - CHECK_OUT_OF_MEM(orderByExpr); - orderByExpr->pExpr = pExpr; - orderByExpr->order = order; - if (NULL_ORDER_DEFAULT == nullOrder) { - nullOrder = (ORDER_ASC == order ? NULL_ORDER_FIRST : NULL_ORDER_LAST); - } - orderByExpr->nullOrder = nullOrder; - return (SNode*)orderByExpr; -} - -SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, const SToken* pVal) { - SSessionWindowNode* session = (SSessionWindowNode*)nodesMakeNode(QUERY_NODE_SESSION_WINDOW); - CHECK_OUT_OF_MEM(session); - session->pCol = pCol; - // session->gap = getInteger(pVal); - return (SNode*)session; -} - -SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pCol) { - SStateWindowNode* state = (SStateWindowNode*)nodesMakeNode(QUERY_NODE_STATE_WINDOW); - CHECK_OUT_OF_MEM(state); - state->pCol = pCol; - return (SNode*)state; -} - -SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* pFill) { - SIntervalWindowNode* interval = (SIntervalWindowNode*)nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW); - CHECK_OUT_OF_MEM(interval); - interval->pInterval = pInterval; - interval->pOffset = pOffset; - interval->pSliding = pSliding; - interval->pFill = pFill; - return (SNode*)interval; -} - -SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) { - SFillNode* fill = (SFillNode*)nodesMakeNode(QUERY_NODE_FILL); - CHECK_OUT_OF_MEM(fill); - fill->mode = mode; - fill->pValues = pValues; - return (SNode*)fill; -} - -SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) { - SGroupingSetNode* groupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET); - CHECK_OUT_OF_MEM(groupingSet); - groupingSet->groupingSetType = GP_TYPE_NORMAL; - groupingSet->pParameterList = nodesMakeList(); - nodesListAppend(groupingSet->pParameterList, pNode); - return (SNode*)groupingSet; -} - -SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) { - if (NULL == pNode || !pCxt->valid) { - return pNode; - } - uint32_t maxLen = sizeof(((SExprNode*)pNode)->aliasName); - strncpy(((SExprNode*)pNode)->aliasName, pAlias->z, pAlias->n > maxLen ? maxLen : pAlias->n); - return pNode; -} - -SNode* addWhereClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWhere) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pWhere = pWhere; - } - return pStmt; -} - -SNode* addPartitionByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pPartitionByList) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pPartitionByList = pPartitionByList; - } - return pStmt; -} - -SNode* addWindowClauseClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWindow) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pWindow = pWindow; - } - return pStmt; -} - -SNode* addGroupByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pGroupByList) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pGroupByList = pGroupByList; - } - return pStmt; -} - -SNode* addHavingClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pHaving) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pHaving = pHaving; - } - return pStmt; -} - -SNode* addOrderByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrderByList) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pOrderByList = pOrderByList; - } - return pStmt; -} - -SNode* addSlimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pSlimit = pSlimit; - } - return pStmt; -} - -SNode* addLimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit) { - if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { - ((SSelectStmt*)pStmt)->pLimit = pLimit; - } - return pStmt; -} - -SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable) { - SSelectStmt* select = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT); - CHECK_OUT_OF_MEM(select); - select->isDistinct = isDistinct; - select->pProjectionList = pProjectionList; - select->pFromTable = pTable; - return (SNode*)select; -} - -SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) { - SSetOperator* setOp = (SSetOperator*)nodesMakeNode(QUERY_NODE_SET_OPERATOR); - CHECK_OUT_OF_MEM(setOp); - setOp->opType = type; - setOp->pLeft = pLeft; - setOp->pRight = pRight; - return (SNode*)setOp; -} - -SNode* createShowStmt(SAstCreateContext* pCxt, EShowStmtType type) { - SShowStmt* show = (SShowStmt*)nodesMakeNode(QUERY_NODE_SHOW_STMT); - CHECK_OUT_OF_MEM(show); - show->showType = type; - return (SNode*)show; -} diff --git a/source/libs/parser/src/astGenerator.c b/source/libs/parser/src/astGenerator.c deleted file mode 100644 index 5dce5120f98131eda4257fc459a34b1f209b7b1f..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/astGenerator.c +++ /dev/null @@ -1,1158 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "os.h" -#include "taos.h" -#include "tmsg.h" -#include "parserInt.h" -#include "tmsgtype.h" -#include "astGenerator.h" - -SArray *tListItemAppend(SArray *pList, SVariant *pVar, uint8_t sortOrder) { - if (pList == NULL) { - pList = taosArrayInit(4, sizeof(SListItem)); - } - - if (pVar == NULL) { - return pList; - } - - /* - * Here we do not employ the assign function, since we need the pz attribute of structure , which is the point to char string. - * Otherwise, the original pointer may be lost, which causes memory leak. - */ - SListItem item; - item.pVar = *pVar; - item.sortOrder = sortOrder; - - taosArrayPush(pList, &item); - return pList; -} - -SArray *tListItemInsert(SArray *pList, SVariant *pVar, uint8_t sortOrder, int32_t index) { - if (pList == NULL || pVar == NULL || index >= taosArrayGetSize(pList)) { - return tListItemAppend(pList, pVar, sortOrder); - } - - SListItem item; - item.pVar = *pVar; - item.sortOrder = sortOrder; - - taosArrayInsert(pList, index, &item); - return pList; -} - -SArray *tListItemAppendToken(SArray *pList, SToken *pAliasToken, uint8_t sortOrder) { - if (pList == NULL) { - pList = taosArrayInit(4, sizeof(SListItem)); - } - - if (pAliasToken) { - SListItem item; - taosVariantCreate(&item.pVar, pAliasToken->z, pAliasToken->n, pAliasToken->type); - item.sortOrder = sortOrder; - - taosArrayPush(pList, &item); - } - - return pList; -} - -SRelationInfo *setTableNameList(SRelationInfo *pRelationInfo, SToken *pName, SToken *pAlias) { - if (pRelationInfo == NULL) { - pRelationInfo = calloc(1, sizeof(SRelationInfo)); - pRelationInfo->list = taosArrayInit(4, sizeof(SRelElement)); - } - - pRelationInfo->type = SQL_FROM_NODE_TABLES; - SRelElement p = {.tableName = *pName}; - if (pAlias != NULL) { - p.aliasName = *pAlias; - } else { - TPARSER_SET_NONE_TOKEN(p.aliasName); - } - - taosArrayPush(pRelationInfo->list, &p); - return pRelationInfo; -} - -void *destroyRelationInfo(SRelationInfo *pRelationInfo) { - if (pRelationInfo == NULL) { - return NULL; - } - - if (pRelationInfo->type == SQL_FROM_NODE_TABLES) { - taosArrayDestroy(pRelationInfo->list); - } else { - size_t size = taosArrayGetSize(pRelationInfo->list); - for(int32_t i = 0; i < size; ++i) { - SSubclause* pa = taosArrayGetP(pRelationInfo->list, i); - destroyAllSqlNode(pa); - } - taosArrayDestroy(pRelationInfo->list); - } - - tfree(pRelationInfo); - return NULL; -} - -SRelationInfo *addSubquery(SRelationInfo *pRelationInfo, SSubclause *pSub, SToken *pAlias) { - if (pRelationInfo == NULL) { - pRelationInfo = calloc(1, sizeof(SRelationInfo)); - pRelationInfo->list = taosArrayInit(4, sizeof(SRelElement)); - } - - pRelationInfo->type = SQL_FROM_NODE_SUBQUERY; - - SRelElement p = {.pSubquery = pSub}; - if (pAlias != NULL) { - p.aliasName = *pAlias; - } else { - TPARSER_SET_NONE_TOKEN(p.aliasName); - } - - taosArrayPush(pRelationInfo->list, &p); - return pRelationInfo; -} - -// sql expr leaf node -tSqlExpr *tSqlExprCreateIdValue(SToken *pToken, int32_t optrType) { - tSqlExpr *pSqlExpr = calloc(1, sizeof(tSqlExpr)); - - if (pToken != NULL) { - pSqlExpr->exprToken = *pToken; - } - - if (optrType == TK_NULL) { -// if (pToken) { -// pToken->type = TSDB_DATA_TYPE_NULL; -// tVariantCreate(&pSqlExpr->value, pToken); -// } - pSqlExpr->tokenId = optrType; - pSqlExpr->type = SQL_NODE_VALUE; - } else if (optrType == TK_INTEGER || optrType == TK_STRING || optrType == TK_FLOAT || optrType == TK_BOOL) { - pSqlExpr->tokenId = optrType; - pSqlExpr->type = SQL_NODE_VALUE; - } else if (optrType == TK_NOW || optrType == TK_VARIABLE) { - pSqlExpr->tokenId = optrType; // TK_TIMESTAMP used to denote this is a timestamp value - pSqlExpr->type = SQL_NODE_VALUE; - } else { - // Here it must be the column name (tk_id) if it is not a number or string. - assert(optrType == TK_ID || optrType == TK_ALL); - if (pToken != NULL) { - pSqlExpr->columnName = *pToken; - } - - pSqlExpr->tokenId = optrType; - pSqlExpr->type = SQL_NODE_TABLE_COLUMN; - } - - return pSqlExpr; -} - -tSqlExpr *tSqlExprCreateFunction(SArray *pParam, SToken *pFuncToken, SToken *endToken, int32_t optType) { - if (pFuncToken == NULL) { - return NULL; - } - - tSqlExpr *pExpr = calloc(1, sizeof(tSqlExpr)); - pExpr->tokenId = optType; - pExpr->type = SQL_NODE_SQLFUNCTION; - pExpr->Expr.paramList = pParam; - - int32_t len = (int32_t)((endToken->z + endToken->n) - pFuncToken->z); - pExpr->Expr.operand = (*pFuncToken); - - pExpr->exprToken.n = len; - pExpr->exprToken.z = pFuncToken->z; - pExpr->exprToken.type = pFuncToken->type; - - return pExpr; -} - -SArray *tRecordFuncName(SArray *pList, SToken *pToken) { - assert(pList != NULL && pToken != NULL); - taosArrayPush(pList, pToken); - return pList; -} - -tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType) { - tSqlExpr *pExpr = calloc(1, sizeof(tSqlExpr)); - pExpr->type = SQL_NODE_EXPR; - - if (pLeft != NULL && pRight != NULL && (optrType != TK_IN)) { - const char* endPos = pRight->exprToken.z + pRight->exprToken.n; - pExpr->exprToken.z = pLeft->exprToken.z; - pExpr->exprToken.n = (uint32_t)(endPos - pExpr->exprToken.z); - pExpr->exprToken.type = pLeft->exprToken.type; - } - - if (optrType == TK_IN) { - pExpr->tokenId = optrType; - pExpr->pLeft = pLeft; - - tSqlExpr *pRSub = calloc(1, sizeof(tSqlExpr)); - pRSub->tokenId = TK_SET; // TODO refactor ..... - pRSub->Expr.paramList = (SArray *)pRight; - - pExpr->pRight = pRSub; - } else { - pExpr->tokenId = optrType; - pExpr->pLeft = pLeft; - - if (pLeft != NULL && pRight == NULL) { - pRight = calloc(1, sizeof(tSqlExpr)); - } - - pExpr->pRight = pRight; - } - - return pExpr; -} - -tSqlExpr *tSqlExprClone(tSqlExpr *pSrc) { - tSqlExpr *pExpr = malloc(sizeof(tSqlExpr)); - memcpy(pExpr, pSrc, sizeof(*pSrc)); - - if (pSrc->pLeft) { - pExpr->pLeft = tSqlExprClone(pSrc->pLeft); - } - - if (pSrc->pRight) { - pExpr->pRight = tSqlExprClone(pSrc->pRight); - } - - memset(&pExpr->value, 0, sizeof(pExpr->value)); - taosVariantAssign(&pExpr->value, &pSrc->value); - - //we don't clone paramList now because clone is only used for between/and - assert(pSrc->Expr.paramList == NULL); - return pExpr; -} - -void tSqlExprCompact(tSqlExpr **pExpr) { - if (*pExpr == NULL || tSqlExprIsParentOfLeaf(*pExpr)) { - return; - } - - if ((*pExpr)->pLeft) { - tSqlExprCompact(&(*pExpr)->pLeft); - } - - if ((*pExpr)->pRight) { - tSqlExprCompact(&(*pExpr)->pRight); - } - - if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight == NULL && ((*pExpr)->tokenId == TK_OR || (*pExpr)->tokenId == TK_AND)) { - tSqlExprDestroy(*pExpr); - *pExpr = NULL; - } else if ((*pExpr)->pLeft == NULL && (*pExpr)->pRight != NULL) { - tSqlExpr* tmpPtr = (*pExpr)->pRight; - (*pExpr)->pRight = NULL; - - tSqlExprDestroy(*pExpr); - (*pExpr) = tmpPtr; - } else if ((*pExpr)->pRight == NULL && (*pExpr)->pLeft != NULL) { - tSqlExpr* tmpPtr = (*pExpr)->pLeft; - (*pExpr)->pLeft = NULL; - - tSqlExprDestroy(*pExpr); - (*pExpr) = tmpPtr; - } -} - -bool tSqlExprIsLeaf(tSqlExpr *pExpr) { - return (pExpr->pRight == NULL && pExpr->pLeft == NULL) && - (pExpr->tokenId == 0 || - (pExpr->tokenId == TK_ID) || - (pExpr->tokenId == TK_BOOL || pExpr->tokenId == TK_STRING || pExpr->tokenId == TK_FLOAT) || - (pExpr->tokenId == TK_NULL) || - (pExpr->tokenId == TK_SET)); -} - -bool tSqlExprIsParentOfLeaf(tSqlExpr *pExpr) { - return (pExpr->pLeft != NULL && pExpr->pRight != NULL) && - (tSqlExprIsLeaf(pExpr->pLeft) && tSqlExprIsLeaf(pExpr->pRight)); -} - -static void doDestroySqlExprNode(tSqlExpr *pExpr) { - if (pExpr == NULL) { - return; - } - - taosVariantDestroy(&pExpr->value); - tSqlExprListDestroy(pExpr->Expr.paramList); - free(pExpr); -} - -void tSqlExprDestroy(tSqlExpr *pExpr) { - if (pExpr == NULL) { - return; - } - - tSqlExprDestroy(pExpr->pLeft); - pExpr->pLeft = NULL; - tSqlExprDestroy(pExpr->pRight); - pExpr->pRight = NULL; - - doDestroySqlExprNode(pExpr); -} - -SArray * tSqlExprListAppend(SArray *pList, tSqlExpr *pNode, SToken *pDistinct, SToken *pToken) { - - if (pList == NULL) { - pList = taosArrayInit(4, sizeof(tSqlExprItem)); - } - - if (pNode || pToken) { - struct tSqlExprItem item = {0}; - - item.pNode = pNode; - item.distinct = (pDistinct != NULL); - - if (pToken) { // set the as clause - item.aliasName = malloc(pToken->n + 1); - strncpy(item.aliasName, pToken->z, pToken->n); - item.aliasName[pToken->n] = 0; - - strdequote(item.aliasName); - } - - taosArrayPush(pList, &item); - } - - return pList; -} - -static void freeExprElem(void* item) { - tSqlExprItem* exprItem = item; - - tfree(exprItem->aliasName); - tSqlExprDestroy(exprItem->pNode); -} - -void tSqlExprListDestroy(SArray *pList) { - if (pList == NULL) { - return; - } - taosArrayDestroyEx(pList, freeExprElem); -} - -void tSqlExprEvaluate(tSqlExpr* pExpr) { - tSqlExpr *pLeft = pExpr->pLeft; - tSqlExpr *pRight = pExpr->pRight; - - if (pLeft == NULL || pRight == NULL) { - return; - } - - int32_t optrType = pExpr->tokenId; - - if ((optrType == TK_PLUS || optrType == TK_MINUS || optrType == TK_STAR || optrType == TK_DIVIDE || - optrType == TK_REM)) { - /* - * if a exprToken is noted as the TK_TIMESTAMP, the time precision is microsecond - * Otherwise, the time precision is adaptive, determined by the time precision from databases. - */ - int32_t ltoken = pLeft->tokenId; - int32_t rtoken = pRight->tokenId; - - if ((ltoken == TK_INTEGER && rtoken == TK_INTEGER) || (ltoken == TK_TIMESTAMP && rtoken == TK_TIMESTAMP)) { - pExpr->value.nType = TSDB_DATA_TYPE_BIGINT; - pExpr->tokenId = ltoken; - pExpr->type = SQL_NODE_VALUE; - - switch (optrType) { - case TK_PLUS: { - pExpr->value.i = pLeft->value.i + pRight->value.i; - break; - } - case TK_MINUS: { - pExpr->value.i = pLeft->value.i - pRight->value.i; - break; - } - case TK_STAR: { - pExpr->value.i = pLeft->value.i * pRight->value.i; - break; - } - case TK_DIVIDE: { - pExpr->tokenId = TK_FLOAT; - pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE; - pExpr->value.d = (double)pLeft->value.i / pRight->value.i; - break; - } - case TK_REM: { - pExpr->value.i = pLeft->value.i % pRight->value.i; - break; - } - default: - assert(0); - } - - tSqlExprDestroy(pLeft); - tSqlExprDestroy(pRight); - - pExpr->pLeft = NULL; - pExpr->pRight = NULL; - } else if ((ltoken == TK_FLOAT && rtoken == TK_INTEGER) || (ltoken == TK_INTEGER && rtoken == TK_FLOAT) || - (ltoken == TK_FLOAT && rtoken == TK_FLOAT)) { - pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE; - pExpr->tokenId = TK_FLOAT; - pExpr->type = SQL_NODE_VALUE; - - double left = (pLeft->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pLeft->value.d : pLeft->value.i; - double right = (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pRight->value.d : pRight->value.i; - - switch (optrType) { - case TK_PLUS: { - pExpr->value.d = left + right; - break; - } - case TK_MINUS: { - pExpr->value.d = left - right; - break; - } - case TK_STAR: { - pExpr->value.d = left * right; - break; - } - case TK_DIVIDE: { - pExpr->value.d = left / right; - break; - } - case TK_REM: { - pExpr->value.d = left - ((int64_t)(left / right)) * right; - break; - } - default: - assert(0); - } - - tSqlExprDestroy(pLeft); - tSqlExprDestroy(pRight); - - pExpr->pLeft = NULL; - pExpr->pRight = NULL; - } - } -} - -SSqlNode *tSetQuerySqlNode(SToken *pSelectToken, SArray *pSelNodeList, SRelationInfo *pFrom, tSqlExpr *pWhere, - SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, - SSessionWindowVal *pSession, SWindowStateVal *pWindowStateVal, SToken *pSliding, SArray *pFill, SLimit *pLimit, - SLimit *psLimit, tSqlExpr *pHaving) { - assert(pSelNodeList != NULL); - - SSqlNode *pSqlNode = calloc(1, sizeof(SSqlNode)); - - // all later sql string are belonged to the stream sql - pSqlNode->sqlstr = *pSelectToken; - pSqlNode->sqlstr.n = (uint32_t)strlen(pSqlNode->sqlstr.z); - - pSqlNode->pSelNodeList = pSelNodeList; - pSqlNode->from = pFrom; - pSqlNode->pGroupby = pGroupby; - pSqlNode->pSortOrder = pSortOrder; - pSqlNode->pWhere = pWhere; - pSqlNode->fillType = pFill; - pSqlNode->pHaving = pHaving; - - if (pLimit != NULL) { - pSqlNode->limit = *pLimit; - } else { - pSqlNode->limit.limit = -1; - pSqlNode->limit.offset = 0; - } - - if (psLimit != NULL) { - pSqlNode->slimit = *psLimit; - } else { - pSqlNode->slimit.limit = -1; - pSqlNode->slimit.offset = 0; - } - - if (pInterval != NULL) { - pSqlNode->interval = *pInterval; - } else { - TPARSER_SET_NONE_TOKEN(pSqlNode->interval.interval); - TPARSER_SET_NONE_TOKEN(pSqlNode->interval.offset); - } - - if (pSliding != NULL) { - pSqlNode->sliding = *pSliding; - } else { - TPARSER_SET_NONE_TOKEN(pSqlNode->sliding); - } - - if (pSession != NULL) { - pSqlNode->sessionVal = *pSession; - } else { - TPARSER_SET_NONE_TOKEN(pSqlNode->sessionVal.gap); - TPARSER_SET_NONE_TOKEN(pSqlNode->sessionVal.col); - } - - if (pWindowStateVal != NULL) { - pSqlNode->windowstateVal = *pWindowStateVal; - } else { - TPARSER_SET_NONE_TOKEN(pSqlNode->windowstateVal.col); - } - - return pSqlNode; -} - -static FORCE_INLINE int32_t tStrTokenCompare(SToken* left, SToken* right) { - return (left->type == right->type && left->n == right->n && strncasecmp(left->z, right->z, left->n) == 0) ? 0 : 1; -} - -int32_t tSqlExprCompare(tSqlExpr *left, tSqlExpr *right) { - if ((left == NULL && right) || (left && right == NULL) || (left == NULL && right == NULL)) { - return 1; - } - - if (left->type != right->type) { - return 1; - } - - if (left->tokenId != right->tokenId) { - return 1; - } - - if ((left->pLeft && right->pLeft == NULL) - || (left->pLeft == NULL && right->pLeft) - || (left->pRight && right->pRight == NULL) - || (left->pRight == NULL && right->pRight) - || (left->Expr.paramList && right->Expr.paramList == NULL) - || (left->Expr.paramList == NULL && right->Expr.paramList)) { - return 1; - } - - if (taosVariantCompare(&left->value, &right->value)) { - return 1; - } - - if (tStrTokenCompare(&left->columnName, &right->columnName)) { - return 1; - } - - if (right->Expr.paramList && left->Expr.paramList) { - size_t size = taosArrayGetSize(right->Expr.paramList); - if (left->Expr.paramList && taosArrayGetSize(left->Expr.paramList) != size) { - return 1; - } - - for (int32_t i = 0; i < size; i++) { - tSqlExprItem* pLeftElem = taosArrayGet(left->Expr.paramList, i); - tSqlExpr* pSubLeft = pLeftElem->pNode; - tSqlExprItem* pRightElem = taosArrayGet(right->Expr.paramList, i); - tSqlExpr* pSubRight = pRightElem->pNode; - - if (tSqlExprCompare(pSubLeft, pSubRight)) { - return 1; - } - } - } - - if (left->pLeft && tSqlExprCompare(left->pLeft, right->pLeft)) { - return 1; - } - - if (left->pRight && tSqlExprCompare(left->pRight, right->pRight)) { - return 1; - } - - return 0; -} - -SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SSqlNode *pSelect, int32_t type) { - SCreateTableSql *pCreate = calloc(1, sizeof(SCreateTableSql)); - - switch (type) { - case TSDB_SQL_CREATE_TABLE: { - pCreate->colInfo.pColumns = pCols; - assert(pTags == NULL); - break; - } - case TSDB_SQL_CREATE_STABLE: { - pCreate->colInfo.pColumns = pCols; - pCreate->colInfo.pTagColumns = pTags; - assert(pTags != NULL && pCols != NULL); - break; - } -// case TSQL_CREATE_STREAM: { -// pCreate->pSelect = pSelect; -// break; -// } - - default: - assert(false); - } - - pCreate->type = type; - return pCreate; -} - -SAlterTableInfo *tSetAlterTableInfo(SToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableType) { - SAlterTableInfo *pAlterTable = calloc(1, sizeof(SAlterTableInfo)); - - pAlterTable->name = *pTableName; - pAlterTable->type = type; - pAlterTable->tableType = tableType; - - if (type == TSDB_ALTER_TABLE_ADD_COLUMN || type == TSDB_ALTER_TABLE_ADD_TAG || type == TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES || type == TSDB_ALTER_TABLE_UPDATE_TAG_BYTES) { - pAlterTable->pAddColumns = pCols; - assert(pVals == NULL); - } else { - /* - * ALTER_TABLE_TAGS_CHG, ALTER_TABLE_TAGS_SET, ALTER_TABLE_TAGS_DROP, - * ALTER_TABLE_DROP_COLUMN - */ - pAlterTable->varList = pVals; - assert(pCols == NULL); - } - - return pAlterTable; -} - -SCreatedTableInfo createNewChildTableInfo(SToken *pTableName, SArray *pTagNames, SArray *pTagVals, SToken *pToken, SToken* igExists) { - SCreatedTableInfo info; - memset(&info, 0, sizeof(SCreatedTableInfo)); - - info.name = *pToken; - info.pTagNames = pTagNames; - info.pTagVals = pTagVals; - info.stbName = *pTableName; - info.igExist = (igExists->n > 0)? 1:0; - - return info; -} - -void destroyAllSqlNode(struct SSubclause *pSub) { - if (pSub->node == NULL) { - return; - } - - size_t size = taosArrayGetSize(pSub->node); - for(int32_t i = 0; i < size; ++i) { - SSqlNode *pNode = taosArrayGetP(pSub->node, i); - destroySqlNode(pNode); - } - - taosArrayDestroy(pSub->node); -} - -static void freeItem(void *pItem) { - SListItem* p = (SListItem*) pItem; - taosVariantDestroy(&p->pVar); -} - -void destroySqlNode(SSqlNode *pSqlNode) { - if (pSqlNode == NULL) { - return; - } - - tSqlExprListDestroy(pSqlNode->pSelNodeList); - pSqlNode->pSelNodeList = NULL; - - tSqlExprDestroy(pSqlNode->pWhere); - pSqlNode->pWhere = NULL; - - taosArrayDestroyEx(pSqlNode->pSortOrder, freeItem); - pSqlNode->pSortOrder = NULL; - - taosArrayDestroyEx(pSqlNode->pGroupby, freeItem); - pSqlNode->pGroupby = NULL; - - pSqlNode->from = destroyRelationInfo(pSqlNode->from); - - taosArrayDestroyEx(pSqlNode->fillType, freeItem); - pSqlNode->fillType = NULL; - - tSqlExprDestroy(pSqlNode->pHaving); - free(pSqlNode); -} - -void freeCreateTableInfo(void* p) { - SCreatedTableInfo* pInfo = (SCreatedTableInfo*) p; - taosArrayDestroy(pInfo->pTagNames); - taosArrayDestroy(pInfo->pTagVals); - tfree(pInfo->fullname); -} - -SSqlInfo* setSqlInfo(SSqlInfo *pInfo, void *pSqlExprInfo, SToken *pTableName, int32_t type) { - pInfo->type = type; - - if (type == TSDB_SQL_SELECT) { - pInfo->sub = *(SSubclause*) pSqlExprInfo; - tfree(pSqlExprInfo); - } else { - pInfo->pCreateTableInfo = pSqlExprInfo; - } - - if (pTableName != NULL) { - pInfo->pCreateTableInfo->name = *pTableName; - } - - return pInfo; -} - -SSubclause* setSubclause(SSubclause* pSub, void *pSqlNode) { - if (pSub == NULL) { - pSub = malloc(sizeof(SSubclause)); - - pSub->unionType = SQL_TYPE_UNIONALL; - pSub->node = taosArrayInit(1, POINTER_BYTES); - } - - taosArrayPush(pSub->node, &pSqlNode); - return pSub; -} - -SSubclause* appendSelectClause(SSubclause *pSub, int32_t type, void *pSubclause) { - taosArrayPush(pSub->node, &pSubclause); - if (type == SQL_TYPE_UNION) { - pSub->unionType = type; - } - - return pSub; -} - -void setCreatedTableName(SSqlInfo *pInfo, SToken *pTableNameToken, SToken *pIfNotExists) { - pInfo->pCreateTableInfo->name = *pTableNameToken; - pInfo->pCreateTableInfo->existCheck = (pIfNotExists->n != 0); -} - -void* destroyCreateTableSql(SCreateTableSql* pCreate) { - destroySqlNode(pCreate->pSelect); - - taosArrayDestroy(pCreate->colInfo.pColumns); - taosArrayDestroy(pCreate->colInfo.pTagColumns); - - taosArrayDestroyEx(pCreate->childTableInfo, freeCreateTableInfo); - tfree(pCreate); - - return NULL; -} - -void setDropFuncInfo(SSqlInfo *pInfo, int32_t type, SToken* pToken) { - pInfo->type = type; - - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = (SMiscInfo *)calloc(1, sizeof(SMiscInfo)); - pInfo->pMiscInfo->a = taosArrayInit(4, sizeof(SToken)); - } - - taosArrayPush(pInfo->pMiscInfo->a, pToken); -} - -void setCreateFuncInfo(SSqlInfo *pInfo, int32_t type, SToken *pName, SToken *pPath, SField *output, SToken* bufSize, int32_t funcType) { - pInfo->type = type; - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - pInfo->pMiscInfo->funcOpt.name = *pName; - pInfo->pMiscInfo->funcOpt.path = *pPath; - pInfo->pMiscInfo->funcOpt.output = *output; - pInfo->pMiscInfo->funcOpt.type = funcType; - if (bufSize->n > 0) { - pInfo->pMiscInfo->funcOpt.bufSize = strtol(bufSize->z, NULL, 10); - } else { - pInfo->pMiscInfo->funcOpt.bufSize = 0; - } -} - -void destroySqlInfo(SSqlInfo *pInfo) { - if (pInfo == NULL) { - return; - } - - taosArrayDestroy(pInfo->funcs); - if (pInfo->type == TSDB_SQL_SELECT) { - destroyAllSqlNode(&pInfo->sub); - } else if (pInfo->type == TSDB_SQL_CREATE_STABLE || pInfo->type == TSDB_SQL_CREATE_TABLE) { - pInfo->pCreateTableInfo = destroyCreateTableSql(pInfo->pCreateTableInfo); - } else if (pInfo->type == TSDB_SQL_ALTER_TABLE) { - taosArrayDestroyEx(pInfo->pAlterInfo->varList, freeItem); - taosArrayDestroy(pInfo->pAlterInfo->pAddColumns); - tfree(pInfo->pAlterInfo->tagData.data); - tfree(pInfo->pAlterInfo); - } else if (pInfo->type == TSDB_SQL_COMPACT_VNODE) { - tSqlExprListDestroy(pInfo->sub.node); - } else { - if (pInfo->pMiscInfo != NULL) { - taosArrayDestroy(pInfo->pMiscInfo->a); - } - - if (pInfo->pMiscInfo != NULL && (pInfo->type == TSDB_SQL_CREATE_DB || pInfo->type == TSDB_SQL_ALTER_DB)) { - taosArrayDestroyEx(pInfo->pMiscInfo->dbOpt.keep, freeItem); - } - - tfree(pInfo->pMiscInfo); - } -} - -void setDCLSqlElems(SSqlInfo *pInfo, int32_t type, int32_t nParam, ...) { - pInfo->type = type; - if (nParam == 0) { - return; - } - - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = (SMiscInfo *)calloc(1, sizeof(SMiscInfo)); - pInfo->pMiscInfo->a = taosArrayInit(4, sizeof(SToken)); - } - - va_list va; - va_start(va, nParam); - - while ((nParam--) > 0) { - SToken *pToken = va_arg(va, SToken *); - taosArrayPush(pInfo->pMiscInfo->a, pToken); - } - - va_end(va); -} - -void setDropDbTableInfo(SSqlInfo *pInfo, int32_t type, SToken* pToken, SToken* existsCheck, int16_t dbType, int16_t tableType) { - pInfo->type = type; - - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = (SMiscInfo *)calloc(1, sizeof(SMiscInfo)); - pInfo->pMiscInfo->a = taosArrayInit(4, sizeof(SToken)); - } - - taosArrayPush(pInfo->pMiscInfo->a, pToken); - - pInfo->pMiscInfo->existsCheck = (existsCheck->n == 1); - pInfo->pMiscInfo->dbType = dbType; - pInfo->pMiscInfo->tableType = tableType; -} - -void setShowOptions(SSqlInfo *pInfo, int32_t type, SToken* prefix, SToken* pPatterns) { - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - pInfo->type = TSDB_SQL_SHOW; - - SShowInfo* pShowInfo = &pInfo->pMiscInfo->showOpt; - pShowInfo->showType = type; - - if (prefix != NULL && prefix->type != 0) { - pShowInfo->prefix = *prefix; - } else { - pShowInfo->prefix.type = 0; - } - - if (pPatterns != NULL && pPatterns->type != 0) { - pShowInfo->pattern = *pPatterns; - } else { - pShowInfo->pattern.type = 0; - } -} - -void setCreateDbInfo(SSqlInfo *pInfo, int32_t type, SToken *pToken, SCreateDbInfo *pDB, SToken *pIgExists) { - pInfo->type = type; - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - pInfo->pMiscInfo->dbOpt = *pDB; - pInfo->pMiscInfo->dbOpt.dbname = *pToken; - pInfo->pMiscInfo->dbOpt.ignoreExists = pIgExists->n; // sql.y has: ifnotexists(X) ::= IF NOT EXISTS. {X.n = 1;} -} - -void setCreateAcctSql(SSqlInfo *pInfo, int32_t type, SToken *pName, SToken *pPwd, SCreateAcctInfo *pAcctInfo) { - pInfo->type = type; - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - pInfo->pMiscInfo->acctOpt = *pAcctInfo; - - assert(pName != NULL); - pInfo->pMiscInfo->user.user = *pName; - - if (pPwd != NULL) { - pInfo->pMiscInfo->user.passwd = *pPwd; - } -} - -void setCreateUserSql(SSqlInfo *pInfo, SToken *pName, SToken *pPasswd) { - pInfo->type = TSDB_SQL_CREATE_USER; - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - assert(pName != NULL && pPasswd != NULL); - - pInfo->pMiscInfo->user.user = *pName; - pInfo->pMiscInfo->user.passwd = *pPasswd; -} - -void setKillSql(SSqlInfo *pInfo, int32_t type, SToken *id) { - pInfo->type = type; - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - assert(id != NULL); - pInfo->pMiscInfo->id = *id; -} - -void setAlterUserSql(SSqlInfo *pInfo, int16_t type, SToken *pName, SToken* pPwd, SToken *pPrivilege) { - pInfo->type = TSDB_SQL_ALTER_USER; - if (pInfo->pMiscInfo == NULL) { - pInfo->pMiscInfo = calloc(1, sizeof(SMiscInfo)); - } - - assert(pName != NULL); - - SUserInfo* pUser = &pInfo->pMiscInfo->user; - pUser->type = type; - pUser->user = *pName; - - if (pPwd != NULL) { - pUser->passwd = *pPwd; - } else { - pUser->passwd.type = TSDB_DATA_TYPE_NULL; - } - - if (pPrivilege != NULL) { - pUser->privilege = *pPrivilege; - } else { - pUser->privilege.type = TSDB_DATA_TYPE_NULL; - } -} - -void setCompactVnodeSql(SSqlInfo *pInfo, int32_t type, SArray *pParam) { - pInfo->type = type; - pInfo->sub.node = pParam; -} - -void setDefaultCreateDbOption(SCreateDbInfo *pDBInfo) { - pDBInfo->compressionLevel= -1; - pDBInfo->walLevel = -1; - pDBInfo->fsyncPeriod = -1; - pDBInfo->commitTime = -1; - pDBInfo->numOfVgroups = 2; - pDBInfo->cacheBlockSize = -1; - pDBInfo->numOfBlocks = -1; - pDBInfo->maxRowsPerBlock = -1; - pDBInfo->minRowsPerBlock = -1; - pDBInfo->daysPerFile = -1; - pDBInfo->replica = -1; - pDBInfo->quorum = -1; - pDBInfo->keep = NULL; - pDBInfo->update = -1; - pDBInfo->cachelast = -1; - - memset(&pDBInfo->precision, 0, sizeof(SToken)); -} - -// prefix show db.tables; -void tSetDbName(SToken *pCpxName, SToken *pDb) { - pCpxName->type = pDb->type; - pCpxName->z = pDb->z; - pCpxName->n = pDb->n; -} - -void tSetColumnInfo(SField *pField, SToken *pName, SField *pType) { - int32_t maxLen = sizeof(pField->name) / sizeof(pField->name[0]); - - // The column name is too long, set it to be invalid. - if ((int32_t) pName->n >= maxLen) { - pField->name[0] = 0; - } else { - strncpy(pField->name, pName->z, pName->n); - pField->name[pName->n] = 0; - } - - // denote an invalid data type in the column definition. - pField->type = pType->type; - if(!isValidDataType(pField->type)){ - pField->bytes = 0; - } else { - pField->bytes = pType->bytes; - } -} - -static int32_t tryParseNameTwoParts(SToken *type) { - int32_t t = -1; - - char* str = strndup(type->z, type->n); - if (str == NULL) { - return t; - } - - char* p = strtok(str, " "); - if (p == NULL) { - tfree(str); - return t; - } else { - char* unsign = strtok(NULL, " "); - if (unsign == NULL) { - tfree(str); - return t; - } - - if (strncasecmp(unsign, "UNSIGNED", 8) == 0) { - for(int32_t j = TSDB_DATA_TYPE_TINYINT; j <= TSDB_DATA_TYPE_BIGINT; ++j) { - if (strcasecmp(p, tDataTypes[j].name) == 0) { - t = j; - break; - } - } - - tfree(str); - - if (t == -1) { - return -1; - } - - switch(t) { - case TSDB_DATA_TYPE_TINYINT: return TSDB_DATA_TYPE_UTINYINT; - case TSDB_DATA_TYPE_SMALLINT: return TSDB_DATA_TYPE_USMALLINT; - case TSDB_DATA_TYPE_INT: return TSDB_DATA_TYPE_UINT; - case TSDB_DATA_TYPE_BIGINT: return TSDB_DATA_TYPE_UBIGINT; - default: - return -1; - } - - } else { - tfree(str); - return -1; - } - } -} - -void tSetColumnType(SField *pField, SToken *type) { - // set the field type invalid - pField->type = -1; - pField->name[0] = 0; - - int32_t i = 0; - while (i < tListLen(tDataTypes)) { - if ((type->n == tDataTypes[i].nameLen) && - (strncasecmp(type->z, tDataTypes[i].name, tDataTypes[i].nameLen) == 0)) { - break; - } - - i += 1; - } - - // no qualified data type found, try unsigned data type - if (i == tListLen(tDataTypes)) { - i = tryParseNameTwoParts(type); - if (i == -1) { - return; - } - } - - pField->type = i; - pField->bytes = tDataTypes[i].bytes; - - if (i == TSDB_DATA_TYPE_NCHAR) { - /* - * for nchar, the TOKENTYPE is the number of character, so the length is the - * number of bytes in UCS-4 format, which is 4 times larger than the number of characters - */ - if (type->type == 0) { - pField->bytes = 0; - } else { - int32_t bytes = -(int32_t)(type->type); - if (bytes > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - // overflowed. set bytes to -1 so that error can be reported - bytes = -1; - } else { - bytes = bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE; - } - pField->bytes = (int16_t)bytes; - } - } else if (i == TSDB_DATA_TYPE_BINARY) { - /* for binary, the TOKENTYPE is the length of binary */ - if (type->type == 0) { - pField->bytes = 0; - } else { - int32_t bytes = -(int32_t)(type->type); - if (bytes > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { - // overflowed. set bytes to -1 so that error can be reported - bytes = -1; - } else { - bytes += VARSTR_HEADER_SIZE; - } - - pField->bytes = (int16_t)bytes; - } - } -} - -SSqlInfo doGenerateAST(const char *pStr) { - void *pParser = ParseAlloc(malloc); - - SSqlInfo sqlInfo = {0}; - sqlInfo.valid = true; - sqlInfo.funcs = taosArrayInit(4, sizeof(SToken)); - - int32_t i = 0; - while (1) { - SToken t0 = {0}; - - if (pStr[i] == 0) { - Parse(pParser, 0, t0, &sqlInfo); - goto abort_parse; - } - - t0.n = tGetToken((char *)&pStr[i], &t0.type); - t0.z = (char *)(pStr + i); - i += t0.n; - - switch (t0.type) { - case TK_SPACE: - case TK_COMMENT: { - break; - } - case TK_SEMI: { - Parse(pParser, 0, t0, &sqlInfo); - goto abort_parse; - } - - case TK_QUESTION: - case TK_ILLEGAL: { - snprintf(sqlInfo.msg, tListLen(sqlInfo.msg), "unrecognized token: \"%s\"", t0.z); - sqlInfo.valid = false; - goto abort_parse; - } - - case TK_HEX: - case TK_OCT: - case TK_BIN: { - snprintf(sqlInfo.msg, tListLen(sqlInfo.msg), "unsupported token: \"%s\"", t0.z); - sqlInfo.valid = false; - goto abort_parse; - } - - default: - Parse(pParser, t0.type, t0, &sqlInfo); - if (sqlInfo.valid == false) { - goto abort_parse; - } - } - } - -abort_parse: - ParseFree(pParser, free); - return sqlInfo; -} diff --git a/source/libs/parser/src/astToMsg.c b/source/libs/parser/src/astToMsg.c deleted file mode 100644 index 963255527aeb5ade62c3de797404d9c9f6d005ce..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/astToMsg.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "astGenerator.h" -#include "parserInt.h" -#include "parserUtil.h" - -char* buildUserManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen) { - SCreateUserReq createReq = {0}; - - SUserInfo* pUser = &pInfo->pMiscInfo->user; - strncpy(createReq.user, pUser->user.z, pUser->user.n); - createReq.createType = pUser->type; - createReq.superUser = (int8_t)pUser->type; - - if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) { - // pMsg->privilege = (char)pCmd->count; - } else { - strncpy(createReq.pass, pUser->passwd.z, pUser->passwd.n); - } - - int32_t tlen = tSerializeSCreateUserReq(NULL, 0, &createReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSCreateUserReq(pReq, tlen, &createReq); - *outputLen = tlen; - return pReq; -} - -char* buildAcctManipulationMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgLen) { - SCreateAcctReq createReq = {0}; - - SToken* pName = &pInfo->pMiscInfo->user.user; - SToken* pPwd = &pInfo->pMiscInfo->user.passwd; - - strncpy(createReq.user, pName->z, pName->n); - strncpy(createReq.pass, pPwd->z, pPwd->n); - - SCreateAcctInfo* pAcctOpt = &pInfo->pMiscInfo->acctOpt; - - createReq.maxUsers = pAcctOpt->maxUsers; - createReq.maxDbs = pAcctOpt->maxDbs; - createReq.maxTimeSeries = pAcctOpt->maxTimeSeries; - createReq.maxStreams = pAcctOpt->maxStreams; - createReq.maxStorage = pAcctOpt->maxStorage; - - if (pAcctOpt->stat.n == 0) { - createReq.accessState = -1; - } else { - if (pAcctOpt->stat.z[0] == 'r' && pAcctOpt->stat.n == 1) { - createReq.accessState = TSDB_VN_READ_ACCCESS; - } else if (pAcctOpt->stat.z[0] == 'w' && pAcctOpt->stat.n == 1) { - createReq.accessState = TSDB_VN_WRITE_ACCCESS; - } else if (strncmp(pAcctOpt->stat.z, "all", 3) == 0 && pAcctOpt->stat.n == 3) { - createReq.accessState = TSDB_VN_ALL_ACCCESS; - } else if (strncmp(pAcctOpt->stat.z, "no", 2) == 0 && pAcctOpt->stat.n == 2) { - createReq.accessState = 0; - } - } - - int32_t tlen = tSerializeSCreateAcctReq(NULL, 0, &createReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSCreateAcctReq(pReq, tlen, &createReq); - *outputLen = tlen; - return pReq; -} - -char* buildDropUserMsg(SSqlInfo* pInfo, int32_t* outputLen, int64_t id, char* msgBuf, int32_t msgBufLen) { - SDropUserReq dropReq = {0}; - - SToken* pName = taosArrayGet(pInfo->pMiscInfo->a, 0); - if (pName->n >= TSDB_USER_LEN) { - return NULL; - } - - strncpy(dropReq.user, pName->z, pName->n); - - int32_t tlen = tSerializeSDropUserReq(NULL, 0, &dropReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSDropUserReq(pReq, tlen, &dropReq); - *outputLen = tlen; - return pReq; -} - -char* buildShowMsg(SShowInfo* pShowInfo, int32_t* outputLen, SParseContext* pCtx, SMsgBuf* pMsgBuf) { - SShowReq showReq = {.type = pShowInfo->showType}; - - if (pShowInfo->showType != TSDB_MGMT_TABLE_VNODES) { - SToken* pPattern = &pShowInfo->pattern; - if (pPattern->type > 0) { // only show tables support wildcard query - showReq.payloadLen = pPattern->n; - showReq.payload = malloc(showReq.payloadLen); - strncpy(showReq.payload, pPattern->z, pPattern->n); - } - } else { - SToken* pEpAddr = &pShowInfo->prefix; - assert(pEpAddr->n > 0 && pEpAddr->type > 0); - showReq.payloadLen = pEpAddr->n; - showReq.payload = malloc(showReq.payloadLen); - strncpy(showReq.payload, pEpAddr->z, pEpAddr->n); - } - - if (pShowInfo->showType == TSDB_MGMT_TABLE_STB || pShowInfo->showType == TSDB_MGMT_TABLE_VGROUP) { - SName n = {0}; - - if (pShowInfo->prefix.n > 0) { - if (pShowInfo->prefix.n >= TSDB_DB_FNAME_LEN) { - terrno = buildInvalidOperationMsg(pMsgBuf, "prefix name is too long"); - tFreeSShowReq(&showReq); - return NULL; - } - tNameSetDbName(&n, pCtx->acctId, pShowInfo->prefix.z, pShowInfo->prefix.n); - } else if (pCtx->db == NULL || strlen(pCtx->db) == 0) { - terrno = buildInvalidOperationMsg(pMsgBuf, "database is not specified"); - tFreeSShowReq(&showReq); - return NULL; - } else { - tNameSetDbName(&n, pCtx->acctId, pCtx->db, strlen(pCtx->db)); - } - - tNameGetFullDbName(&n, showReq.db); - } - - int32_t tlen = tSerializeSShowReq(NULL, 0, &showReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSShowReq(pReq, tlen, &showReq); - tFreeSShowReq(&showReq); - *outputLen = tlen; - return pReq; -} - -static int32_t setKeepOption(SCreateDbReq* pMsg, const SCreateDbInfo* pCreateDb, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid number of keep options"; - const char* msg2 = "invalid keep value"; - const char* msg3 = "invalid keep value, should be keep0 <= keep1 <= keep2"; - - pMsg->daysToKeep0 = -1; - pMsg->daysToKeep1 = -1; - pMsg->daysToKeep2 = -1; - - SArray* pKeep = pCreateDb->keep; - if (pKeep != NULL) { - size_t s = taosArrayGetSize(pKeep); -#ifdef _STORAGE - if (s >= 4 || s <= 0) { -#else - if (s != 1) { -#endif - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - // tListI* p0 = taosArrayGet(pKeep, 0); - // tVariantListItem* p1 = (s > 1) ? taosArrayGet(pKeep, 1) : p0; - // tVariantListItem* p2 = (s > 2) ? taosArrayGet(pKeep, 2) : p1; - // - // if ((int32_t)p0->pVar.i64 <= 0 || (int32_t)p1->pVar.i64 <= 0 || (int32_t)p2->pVar.i64 <= 0) { - // return buildInvalidOperationMsg(pMsgBuf, msg2); - // } - // if (!(((int32_t)p0->pVar.i64 <= (int32_t)p1->pVar.i64) && ((int32_t)p1->pVar.i64 <= (int32_t)p2->pVar.i64))) { - // return buildInvalidOperationMsg(pMsgBuf, msg3); - // } - // - // pMsg->daysToKeep0 = htonl((int32_t)p0->pVar.i64); - // pMsg->daysToKeep1 = htonl((int32_t)p1->pVar.i64); - // pMsg->daysToKeep2 = htonl((int32_t)p2->pVar.i64); - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t setTimePrecision(SCreateDbReq* pMsg, const SCreateDbInfo* pCreateDbInfo, SMsgBuf* pMsgBuf) { - const char* msg = "invalid time precision"; - - pMsg->precision = TSDB_TIME_PRECISION_MILLI; // millisecond by default - - SToken* pToken = (SToken*)&pCreateDbInfo->precision; - if (pToken->n > 0) { - pToken->n = strdequote(pToken->z); - - if (strncmp(pToken->z, TSDB_TIME_PRECISION_MILLI_STR, pToken->n) == 0 && - strlen(TSDB_TIME_PRECISION_MILLI_STR) == pToken->n) { - // time precision for this db: million second - pMsg->precision = TSDB_TIME_PRECISION_MILLI; - } else if (strncmp(pToken->z, TSDB_TIME_PRECISION_MICRO_STR, pToken->n) == 0 && - strlen(TSDB_TIME_PRECISION_MICRO_STR) == pToken->n) { - pMsg->precision = TSDB_TIME_PRECISION_MICRO; - } else if (strncmp(pToken->z, TSDB_TIME_PRECISION_NANO_STR, pToken->n) == 0 && - strlen(TSDB_TIME_PRECISION_NANO_STR) == pToken->n) { - pMsg->precision = TSDB_TIME_PRECISION_NANO; - } else { - return buildInvalidOperationMsg(pMsgBuf, msg); - } - } - - return TSDB_CODE_SUCCESS; -} - -static void doSetDbOptions(SCreateDbReq* pMsg, const SCreateDbInfo* pCreateDb) { - pMsg->cacheBlockSize = pCreateDb->cacheBlockSize; - pMsg->totalBlocks = pCreateDb->numOfBlocks; - pMsg->daysPerFile = pCreateDb->daysPerFile; - pMsg->commitTime = (int32_t)pCreateDb->commitTime; - pMsg->minRows = pCreateDb->minRowsPerBlock; - pMsg->maxRows = pCreateDb->maxRowsPerBlock; - pMsg->fsyncPeriod = pCreateDb->fsyncPeriod; - pMsg->compression = (int8_t)pCreateDb->compressionLevel; - pMsg->walLevel = (char)pCreateDb->walLevel; - pMsg->replications = pCreateDb->replica; - pMsg->quorum = pCreateDb->quorum; - pMsg->ignoreExist = pCreateDb->ignoreExists; - pMsg->update = pCreateDb->update; - pMsg->cacheLastRow = pCreateDb->cachelast; - pMsg->numOfVgroups = pCreateDb->numOfVgroups; - pMsg->streamMode = pCreateDb->streamMode; -} - -int32_t setDbOptions(SCreateDbReq* pCreateDbMsg, const SCreateDbInfo* pCreateDbSql, SMsgBuf* pMsgBuf) { - doSetDbOptions(pCreateDbMsg, pCreateDbSql); - - if (setKeepOption(pCreateDbMsg, pCreateDbSql, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (setTimePrecision(pCreateDbMsg, pCreateDbSql, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - return TSDB_CODE_SUCCESS; -} - -// can only perform the parameters based on the macro definitation -static int32_t doCheckDbOptions(SCreateDbReq* pCreate, SMsgBuf* pMsgBuf) { - char msg[512] = {0}; - - if (pCreate->walLevel != -1 && (pCreate->walLevel < TSDB_MIN_WAL_LEVEL || pCreate->walLevel > TSDB_MAX_WAL_LEVEL)) { - snprintf(msg, tListLen(msg), "invalid db option walLevel: %d, only 1-2 allowed", pCreate->walLevel); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - if (pCreate->replications != -1 && - (pCreate->replications < TSDB_MIN_DB_REPLICA_OPTION || pCreate->replications > TSDB_MAX_DB_REPLICA_OPTION)) { - snprintf(msg, tListLen(msg), "invalid db option replications: %d valid range: [%d, %d]", pCreate->replications, - TSDB_MIN_DB_REPLICA_OPTION, TSDB_MAX_DB_REPLICA_OPTION); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - int32_t blocks = pCreate->totalBlocks; - if (blocks != -1 && (blocks < TSDB_MIN_TOTAL_BLOCKS || blocks > TSDB_MAX_TOTAL_BLOCKS)) { - snprintf(msg, tListLen(msg), "invalid db option totalBlocks: %d valid range: [%d, %d]", blocks, - TSDB_MIN_TOTAL_BLOCKS, TSDB_MAX_TOTAL_BLOCKS); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - if (pCreate->quorum != -1 && - (pCreate->quorum < TSDB_MIN_DB_QUORUM_OPTION || pCreate->quorum > TSDB_MAX_DB_QUORUM_OPTION)) { - snprintf(msg, tListLen(msg), "invalid db option quorum: %d valid range: [%d, %d]", pCreate->quorum, - TSDB_MIN_DB_QUORUM_OPTION, TSDB_MAX_DB_QUORUM_OPTION); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - int32_t val = pCreate->daysPerFile; - if (val != -1 && (val < TSDB_MIN_DAYS_PER_FILE || val > TSDB_MAX_DAYS_PER_FILE)) { - snprintf(msg, tListLen(msg), "invalid db option daysPerFile: %d valid range: [%d, %d]", val, TSDB_MIN_DAYS_PER_FILE, - TSDB_MAX_DAYS_PER_FILE); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - val = pCreate->cacheBlockSize; - if (val != -1 && (val < TSDB_MIN_CACHE_BLOCK_SIZE || val > TSDB_MAX_CACHE_BLOCK_SIZE)) { - snprintf(msg, tListLen(msg), "invalid db option cacheBlockSize: %d valid range: [%d, %d]", val, - TSDB_MIN_CACHE_BLOCK_SIZE, TSDB_MAX_CACHE_BLOCK_SIZE); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - if (pCreate->precision != TSDB_TIME_PRECISION_MILLI && pCreate->precision != TSDB_TIME_PRECISION_MICRO && - pCreate->precision != TSDB_TIME_PRECISION_NANO) { - snprintf(msg, tListLen(msg), "invalid db option timePrecision: %d valid value: [%d, %d, %d]", pCreate->precision, - TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO, TSDB_TIME_PRECISION_NANO); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - val = pCreate->commitTime; - if (val != -1 && (val < TSDB_MIN_COMMIT_TIME || val > TSDB_MAX_COMMIT_TIME)) { - snprintf(msg, tListLen(msg), "invalid db option commitTime: %d valid range: [%d, %d]", val, TSDB_MIN_COMMIT_TIME, - TSDB_MAX_COMMIT_TIME); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - val = pCreate->fsyncPeriod; - if (val != -1 && (val < TSDB_MIN_FSYNC_PERIOD || val > TSDB_MAX_FSYNC_PERIOD)) { - snprintf(msg, tListLen(msg), "invalid db option fsyncPeriod: %d valid range: [%d, %d]", val, TSDB_MIN_FSYNC_PERIOD, - TSDB_MAX_FSYNC_PERIOD); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - if (pCreate->compression != -1 && - (pCreate->compression < TSDB_MIN_COMP_LEVEL || pCreate->compression > TSDB_MAX_COMP_LEVEL)) { - snprintf(msg, tListLen(msg), "invalid db option compression: %d valid range: [%d, %d]", pCreate->compression, - TSDB_MIN_COMP_LEVEL, TSDB_MAX_COMP_LEVEL); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - val = pCreate->numOfVgroups; - if (val < TSDB_MIN_VNODES_PER_DB || val > TSDB_MAX_VNODES_PER_DB) { - snprintf(msg, tListLen(msg), "invalid number of vgroups for DB:%d valid range: [%d, %d]", val, - TSDB_MIN_VNODES_PER_DB, TSDB_MAX_VNODES_PER_DB); - } - - val = pCreate->maxRows; - if (val < TSDB_MIN_MAX_ROW_FBLOCK || val > TSDB_MAX_MAX_ROW_FBLOCK) { - snprintf(msg, tListLen(msg), "invalid number of max rows in file block for DB:%d valid range: [%d, %d]", val, - TSDB_MIN_MAX_ROW_FBLOCK, TSDB_MAX_MAX_ROW_FBLOCK); - } - - val = pCreate->minRows; - if (val < TSDB_MIN_MIN_ROW_FBLOCK || val > TSDB_MAX_MIN_ROW_FBLOCK) { - snprintf(msg, tListLen(msg), "invalid number of min rows in file block for DB:%d valid range: [%d, %d]", val, - TSDB_MIN_MIN_ROW_FBLOCK, TSDB_MAX_MIN_ROW_FBLOCK); - } - - return TSDB_CODE_SUCCESS; -} - -char* buildCreateDbMsg(SCreateDbInfo* pCreateDbInfo, int32_t* outputLen, SParseContext* pCtx, SMsgBuf* pMsgBuf) { - SCreateDbReq createReq = {0}; - - if (setDbOptions(&createReq, pCreateDbInfo, pMsgBuf) != TSDB_CODE_SUCCESS) { - terrno = TSDB_CODE_TSC_INVALID_OPERATION; - return NULL; - } - - SName name = {0}; - int32_t ret = tNameSetDbName(&name, pCtx->acctId, pCreateDbInfo->dbname.z, pCreateDbInfo->dbname.n); - if (ret != TSDB_CODE_SUCCESS) { - terrno = ret; - return NULL; - } - - tNameGetFullDbName(&name, createReq.db); - - if (doCheckDbOptions(&createReq, pMsgBuf) != TSDB_CODE_SUCCESS) { - terrno = TSDB_CODE_TSC_INVALID_OPERATION; - return NULL; - } - - int32_t tlen = tSerializeSCreateDbReq(NULL, 0, &createReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSCreateDbReq(pReq, tlen, &createReq); - *outputLen = tlen; - return pReq; -} - -char* buildCreateStbReq(SCreateTableSql* pCreateTableSql, int32_t* outputLen, SParseContext* pParseCtx, - SMsgBuf* pMsgBuf) { - SMCreateStbReq createReq = {0}; - createReq.igExists = pCreateTableSql->existCheck ? 1 : 0; - createReq.pColumns = pCreateTableSql->colInfo.pColumns; - createReq.pTags = pCreateTableSql->colInfo.pTagColumns; - createReq.numOfColumns = (int32_t)taosArrayGetSize(pCreateTableSql->colInfo.pColumns); - createReq.numOfTags = (int32_t)taosArrayGetSize(pCreateTableSql->colInfo.pTagColumns); - - SName n = {0}; - if (createSName(&n, &pCreateTableSql->name, pParseCtx, pMsgBuf) != 0) { - return NULL; - } - - if (tNameExtractFullName(&n, createReq.name) != 0) { - buildInvalidOperationMsg(pMsgBuf, "invalid table name or database not specified"); - return NULL; - } - - int32_t tlen = tSerializeSMCreateStbReq(NULL, 0, &createReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSMCreateStbReq(pReq, tlen, &createReq); - *outputLen = tlen; - return pReq; -} - -char* buildDropStableReq(SSqlInfo* pInfo, int32_t* outputLen, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) { - SToken* tableName = taosArrayGet(pInfo->pMiscInfo->a, 0); - - SName name = {0}; - int32_t code = createSName(&name, tableName, pParseCtx, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - terrno = buildInvalidOperationMsg(pMsgBuf, "invalid table name"); - return NULL; - } - - SMDropStbReq dropReq = {0}; - code = tNameExtractFullName(&name, dropReq.name); - - assert(code == TSDB_CODE_SUCCESS && name.type == TSDB_TABLE_NAME_T); - dropReq.igNotExists = pInfo->pMiscInfo->existsCheck ? 1 : 0; - - int32_t tlen = tSerializeSMDropStbReq(NULL, 0, &dropReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSMDropStbReq(pReq, tlen, &dropReq); - *outputLen = tlen; - return pReq; -} - -char* buildCreateDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid host name (name too long, maximum length 128)"; - const char* msg2 = "dnode name can not be string"; - const char* msg3 = "port should be an integer that is less than 65535 and greater than 0"; - const char* msg4 = "failed prepare create dnode message"; - - if (taosArrayGetSize(pInfo->pMiscInfo->a) != 2) { - buildInvalidOperationMsg(pMsgBuf, msg1); - return NULL; - } - - SToken* id = taosArrayGet(pInfo->pMiscInfo->a, 0); - if (id->type != TK_ID && id->type != TK_IPTOKEN) { - buildInvalidOperationMsg(pMsgBuf, msg2); - return NULL; - } - - SToken* port = taosArrayGet(pInfo->pMiscInfo->a, 1); - if (port->type != TK_INTEGER) { - buildInvalidOperationMsg(pMsgBuf, msg3); - return NULL; - } - - bool isSign = false; - int64_t val = 0; - - toInteger(port->z, port->n, 10, &val, &isSign); - if (val >= UINT16_MAX || val <= 0) { - buildInvalidOperationMsg(pMsgBuf, msg3); - return NULL; - } - - SCreateDnodeReq createReq = {0}; - - strncpy(createReq.fqdn, id->z, id->n); - createReq.port = val; - - int32_t tlen = tSerializeSCreateDnodeReq(NULL, 0, &createReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSCreateDnodeReq(pReq, tlen, &createReq); - *outputLen = tlen; - return pReq; -} - -char* buildDropDnodeMsg(SSqlInfo* pInfo, int32_t* outputLen, SMsgBuf* pMsgBuf) { - SDropDnodeReq dropReq = {0}; - - SToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0); - - char* end = NULL; - dropReq.dnodeId = strtoll(pzName->z, &end, 10); - - if (end - pzName->z != pzName->n) { - buildInvalidOperationMsg(pMsgBuf, "invalid dnode id"); - return NULL; - } - - int32_t tlen = tSerializeSDropDnodeReq(NULL, 0, &dropReq); - void* pReq = malloc(tlen); - if (pReq == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - tSerializeSDropDnodeReq(pReq, tlen, &dropReq); - *outputLen = tlen; - return pReq; -} \ No newline at end of file diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c deleted file mode 100644 index ffc9f4a3f6538419e80278a4bb2162439d187770..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/astValidate.c +++ /dev/null @@ -1,4002 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "astGenerator.h" -#include "function.h" -#include "parserInt.h" -#include "parserUtil.h" -#include "queryInfoUtil.h" -#include "tbuffer.h" -#include "tglobal.h" -#include "tmsgtype.h" -#include "ttime.h" -#include "astToMsg.h" - -#define TSQL_TBNAME_L "tbname" -#define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0" -#define VALID_COLUMN_INDEX(index) (((index).tableIndex >= 0) && ((index).columnIndex >= TSDB_TBNAME_COLUMN_INDEX)) - -#define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey)) - -// -1 is tbname column index, so here use the -2 as the initial value -#define COLUMN_INDEX_INITIAL_VAL (-2) -#define COLUMN_INDEX_INITIALIZER { COLUMN_INDEX_INITIAL_VAL, COLUMN_INDEX_INITIAL_VAL } - -static int32_t resColId = 5000; -int32_t getNewResColId() { - return resColId++; -} - -static int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, bool outerQuery, SMsgBuf* pMsgBuf); -static int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, SSchema* columnSchema, - tExprNode** pNode, SColumnIndex* pIndex, tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf); - -void setTokenAndResColumnName(tSqlExprItem* pItem, char* resColumnName, char* rawName, int32_t nameLength) { - memset(resColumnName, 0, nameLength); - - int32_t len = ((int32_t)pItem->pNode->exprToken.n < nameLength) ? (int32_t)pItem->pNode->exprToken.n : nameLength; - strncpy(rawName, pItem->pNode->exprToken.z, len); - - if (pItem->aliasName != NULL) { - assert(strlen(pItem->aliasName) < nameLength); - tstrncpy(resColumnName, pItem->aliasName, len); - } else { - strncpy(resColumnName, rawName, len); - } -} - -static int32_t evaluateSqlNodeImpl(tSqlExpr* pExpr, int32_t tsPrecision) { - int32_t code = 0; - if (pExpr->type == SQL_NODE_EXPR) { - code = evaluateSqlNodeImpl(pExpr->pLeft, tsPrecision); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - code = evaluateSqlNodeImpl(pExpr->pRight, tsPrecision); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - if (pExpr->pLeft->type == SQL_NODE_VALUE && pExpr->pRight->type == SQL_NODE_VALUE) { - tSqlExpr* pLeft = pExpr->pLeft; - tSqlExpr* pRight = pExpr->pRight; - if ((pLeft->tokenId == TK_TIMESTAMP && (pRight->tokenId == TK_INTEGER || pRight->tokenId == TK_FLOAT)) || - ((pRight->tokenId == TK_TIMESTAMP && (pLeft->tokenId == TK_INTEGER || pLeft->tokenId == TK_FLOAT)))) { - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - } else if (pLeft->tokenId == TK_TIMESTAMP && pRight->tokenId == TK_TIMESTAMP) { - tSqlExprEvaluate(pExpr); - } else { - tSqlExprEvaluate(pExpr); - } - } else { - // Other types of expressions are not evaluated, they will be handled during the validation of the abstract syntax tree. - } - } else if (pExpr->type == SQL_NODE_VALUE) { - if (pExpr->tokenId == TK_NOW) { - pExpr->value.i = taosGetTimestamp(tsPrecision); - pExpr->value.nType = TSDB_DATA_TYPE_BIGINT; - pExpr->tokenId = TK_TIMESTAMP; - } else if (pExpr->tokenId == TK_VARIABLE) { - char unit = 0; - SToken* pToken = &pExpr->exprToken; - int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pExpr->value.i, &unit, tsPrecision); - if (ret != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - } - - pExpr->value.nType = TSDB_DATA_TYPE_BIGINT; - pExpr->tokenId = TK_TIMESTAMP; - } else if (pExpr->tokenId == TK_NULL) { - pExpr->value.nType = TSDB_DATA_TYPE_NULL; - } else if (pExpr->tokenId == TK_INTEGER || pExpr->tokenId == TK_STRING || pExpr->tokenId == TK_FLOAT || pExpr->tokenId == TK_BOOL) { - SToken* pToken = &pExpr->exprToken; - - int32_t tokenType = pToken->type; - toTSDBType(tokenType); - taosVariantCreate(&pExpr->value, pToken->z, pToken->n, tokenType); - } - - return TSDB_CODE_SUCCESS; - // other types of data are handled in the parent level. - } else if (pExpr->type == SQL_NODE_SQLFUNCTION) { - SArray* pParam = pExpr->Expr.paramList; - - if (pParam != NULL) { - for (int32_t i = 0; i < taosArrayGetSize(pParam); ++i) { - tSqlExprItem* pItem = taosArrayGet(pParam, i); - evaluateSqlNodeImpl(pItem->pNode, tsPrecision); - } - } - } - - return TSDB_CODE_SUCCESS; -} - -void destroyFilterInfo(SColumnFilterList* pFilterList) { - if (pFilterList->filterInfo == NULL) { - pFilterList->numOfFilters = 0; - return; - } - - for(int32_t i = 0; i < pFilterList->numOfFilters; ++i) { - if (pFilterList->filterInfo[i].filterstr) { - tfree(pFilterList->filterInfo[i].pz); - } - } - - tfree(pFilterList->filterInfo); - pFilterList->numOfFilters = 0; -} - -void columnDestroy(SColumn* pCol) { - destroyFilterInfo(&pCol->info.flist); - free(pCol); -} - -void destroyColumnList(SArray* pColumnList) { - if (pColumnList == NULL) { - return; - } - - size_t num = taosArrayGetSize(pColumnList); - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGetP(pColumnList, i); - columnDestroy(pCol); - } - - taosArrayDestroy(pColumnList); -} - -void clearTableMetaInfo(STableMetaInfo* pTableMetaInfo) { - if (pTableMetaInfo == NULL) { - return; - } - - tfree(pTableMetaInfo->pTableMeta); - tfree(pTableMetaInfo->vgroupList); - - destroyColumnList(pTableMetaInfo->tagColList); - pTableMetaInfo->tagColList = NULL; - - free(pTableMetaInfo); -} - -static STableMeta* extractTempTableMetaFromSubquery(SQueryStmtInfo* pUpstream) { - STableMetaInfo* pUpstreamTableMetaInfo = getMetaInfo(pUpstream, 0); - - int32_t numOfColumns = pUpstream->fieldsInfo.numOfOutput; - STableMeta *meta = calloc(1, sizeof(STableMeta) + sizeof(SSchema) * numOfColumns); - meta->tableType = TSDB_TEMP_TABLE; - - STableComInfo *info = &meta->tableInfo; - info->numOfColumns = numOfColumns; - info->precision = pUpstreamTableMetaInfo->pTableMeta->tableInfo.precision; - info->numOfTags = 0; - - int32_t n = 0; - for(int32_t i = 0; i < numOfColumns; ++i) { - SInternalField* pField = getInternalField(&pUpstream->fieldsInfo, i); - if (!pField->visible) { - continue; - } - - meta->schema[n] = pField->pExpr->base.resSchema; - info->rowSize += meta->schema[n].bytes; - n += 1; - } - - info->numOfColumns = n; - return meta; -} - -SQueryStmtInfo *createQueryInfo() { - SQueryStmtInfo* pQueryInfo = calloc(1, sizeof(SQueryStmtInfo)); - - pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField)); - pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); - pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX; - pQueryInfo->limit.limit = -1; - pQueryInfo->limit.offset = 0; - - pQueryInfo->slimit.limit = -1; - pQueryInfo->slimit.offset = 0; - pQueryInfo->pDownstream = taosArrayInit(4, POINTER_BYTES); - pQueryInfo->window = TSWINDOW_INITIALIZER; - - pQueryInfo->exprList = calloc(10, POINTER_BYTES); - - for(int32_t i = 0; i < 10; ++i) { - pQueryInfo->exprList[i] = taosArrayInit(4, POINTER_BYTES); - } - - pQueryInfo->exprListLevelIndex = 0; - - return pQueryInfo; -} - -static void destroyQueryInfoImpl(SQueryStmtInfo* pQueryInfo) { - cleanupTagCond(&pQueryInfo->tagCond); - cleanupColumnCond(&pQueryInfo->colCond); - cleanupFieldInfo(&pQueryInfo->fieldsInfo); - - dropAllExprInfo(pQueryInfo->exprList, 10); - - tfree(pQueryInfo->exprList); - - columnListDestroy(pQueryInfo->colList); - pQueryInfo->colList = NULL; - - if (pQueryInfo->groupbyExpr.columnInfo != NULL) { - taosArrayDestroy(pQueryInfo->groupbyExpr.columnInfo); - pQueryInfo->groupbyExpr.columnInfo = NULL; - } - - pQueryInfo->fillType = 0; - - tfree(pQueryInfo->fillVal); - tfree(pQueryInfo->buf); - - taosArrayDestroy(pQueryInfo->pDownstream); - pQueryInfo->pDownstream = NULL; - pQueryInfo->bufLen = 0; -} - -void destroyQueryInfo(SQueryStmtInfo* pQueryInfo) { - while (pQueryInfo != NULL) { - SQueryStmtInfo* p = pQueryInfo->sibling; - - size_t numOfUpstream = taosArrayGetSize(pQueryInfo->pDownstream); - for (int32_t i = 0; i < numOfUpstream; ++i) { - SQueryStmtInfo* pDownstream = taosArrayGetP(pQueryInfo->pDownstream, i); - destroyQueryInfoImpl(pDownstream); - clearAllTableMetaInfo(pDownstream, false, 0); - tfree(pDownstream); - } - - destroyQueryInfoImpl(pQueryInfo); - clearAllTableMetaInfo(pQueryInfo, false, 0); - tfree(pQueryInfo); - pQueryInfo = p; - } -} - -static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { - SRelElement* subInfo = taosArrayGet(pSqlNode->from->list, index); - - // union all is not support currently - SSqlNode* p = taosArrayGetP(subInfo->pSubquery->node, 0); - if (taosArrayGetSize(subInfo->pSubquery->node) >= 2) { - return buildInvalidOperationMsg(pMsgBuf, "not support union in subquery"); - } - - SQueryStmtInfo* pSub = createQueryInfo(); - - SArray *pUdfInfo = NULL; - if (pQueryInfo->pUdfInfo) { - pUdfInfo = taosArrayDup(pQueryInfo->pUdfInfo); - } - - pSub->pUdfInfo = pUdfInfo; - int32_t code = validateSqlNode(p, pSub, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - // create dummy table meta info - STableMetaInfo* pTableMetaInfo1 = calloc(1, sizeof(STableMetaInfo)); - if (pTableMetaInfo1 == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - - pTableMetaInfo1->pTableMeta = extractTempTableMetaFromSubquery(pSub); - - if (subInfo->aliasName.n > 0) { - if (subInfo->aliasName.n >= TSDB_TABLE_FNAME_LEN) { - tfree(pTableMetaInfo1); - return buildInvalidOperationMsg(pMsgBuf, "subquery alias name too long"); - } - - tstrncpy(pTableMetaInfo1->aliasName, subInfo->aliasName.z, subInfo->aliasName.n + 1); - } - - taosArrayPush(pQueryInfo->pDownstream, &pSub); - - // NOTE: order mix up in subquery not support yet. - pQueryInfo->order = pSub->order; - - STableMetaInfo** tmp = realloc(pQueryInfo->pTableMetaInfo, (pQueryInfo->numOfTables + 1) * POINTER_BYTES); - if (tmp == NULL) { - tfree(pTableMetaInfo1); - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - - pQueryInfo->pTableMetaInfo = tmp; - - pQueryInfo->pTableMetaInfo[pQueryInfo->numOfTables] = pTableMetaInfo1; - pQueryInfo->numOfTables += 1; - - // all columns are added into the table column list - STableMeta* pMeta = pTableMetaInfo1->pTableMeta; - int32_t startOffset = (int32_t) taosArrayGetSize(pQueryInfo->colList); - - for(int32_t i = 0; i < pMeta->tableInfo.numOfColumns; ++i) { - columnListInsert(pQueryInfo->colList, pMeta->uid, &pMeta->schema[i], TSDB_COL_NORMAL); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t getTableIndexImpl(SToken* pTableToken, SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex) { - if (pTableToken->n == 0) { // only one table and no table name prefix in column name - if (pQueryInfo->numOfTables == 1) { - pIndex->tableIndex = 0; - } else { - pIndex->tableIndex = COLUMN_INDEX_INITIAL_VAL; - } - - return TSDB_CODE_SUCCESS; - } - - pIndex->tableIndex = COLUMN_INDEX_INITIAL_VAL; - for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, i); - char* name = pTableMetaInfo->aliasName; - if (strncasecmp(name, pTableToken->z, pTableToken->n) == 0 && strlen(name) == pTableToken->n) { - pIndex->tableIndex = i; - return TSDB_CODE_SUCCESS; - } - } - - return TSDB_CODE_TSC_INVALID_OPERATION; -} - -void extractTableNameFromToken(SToken* pToken, SToken* pTable) { - const char sep = TS_PATH_DELIMITER[0]; - - if (pToken == pTable || pToken == NULL || pTable == NULL) { - return; - } - - char* r = strnchr(pToken->z, sep, pToken->n, false); - - if (r != NULL) { // record the table name token - pTable->n = (uint32_t)(r - pToken->z); - pTable->z = pToken->z; - - r += 1; - pToken->n -= (uint32_t)(r - pToken->z); - pToken->z = r; - } -} - -int32_t getTableIndexByName(SToken* pToken, SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex) { - SToken tableToken = {0}; - extractTableNameFromToken(pToken, &tableToken); - - if (getTableIndexImpl(&tableToken, pQueryInfo, pIndex) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - return TSDB_CODE_SUCCESS; -} - -static int16_t doGetColumnIndex(SQueryStmtInfo* pQueryInfo, int32_t index, const SToken* pToken, int16_t* type) { - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, index)->pTableMeta; - - int32_t numOfCols = getNumOfColumns(pTableMeta) + getNumOfTags(pTableMeta); - SSchema* pSchema = getTableColumnSchema(pTableMeta); - - int16_t columnIndex = COLUMN_INDEX_INITIAL_VAL; - - for (int32_t i = 0; i < numOfCols; ++i) { - if (pToken->n != strlen(pSchema[i].name)) { - continue; - } - - if (strncasecmp(pSchema[i].name, pToken->z, pToken->n) == 0) { - columnIndex = i; - break; - } - } - - *type = (columnIndex >= getNumOfColumns(pTableMeta))? TSDB_COL_TAG:TSDB_COL_NORMAL; - return columnIndex; -} - -static bool isTablenameToken(SToken* token) { - SToken tmpToken = *token; - SToken tableToken = {0}; - - extractTableNameFromToken(&tmpToken, &tableToken); - return (tmpToken.n == strlen(TSQL_TBNAME_L) && strncasecmp(TSQL_TBNAME_L, tmpToken.z, tmpToken.n) == 0); -} - -int32_t doGetColumnIndexByName(SToken* pToken, SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, SMsgBuf* pMsgBuf) { - const char* msg0 = "ambiguous column name"; - const char* msg1 = "invalid column name"; - - pIndex->type = TSDB_COL_NORMAL; - - if (isTablenameToken(pToken)) { - pIndex->columnIndex = TSDB_TBNAME_COLUMN_INDEX; - pIndex->type = TSDB_COL_TAG; - } else if (strlen(DEFAULT_PRIMARY_TIMESTAMP_COL_NAME) == pToken->n && - strncasecmp(pToken->z, DEFAULT_PRIMARY_TIMESTAMP_COL_NAME, pToken->n) == 0) { - pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_ID; // just make runtime happy, need fix java test case InsertSpecialCharacterJniTest - } else if (pToken->n == 0) { - pIndex->columnIndex = PRIMARYKEY_TIMESTAMP_COL_ID; // just make runtime happy, need fix java test case InsertSpecialCharacterJniTest - } else { - // not specify the table name, try to locate the table index by column name - if (pIndex->tableIndex == COLUMN_INDEX_INITIAL_VAL) { - for (int16_t i = 0; i < pQueryInfo->numOfTables; ++i) { - int16_t colIndex = doGetColumnIndex(pQueryInfo, i, pToken, &pIndex->type); - - if (colIndex != COLUMN_INDEX_INITIAL_VAL) { - if (pIndex->columnIndex != COLUMN_INDEX_INITIAL_VAL) { - return buildInvalidOperationMsg(pMsgBuf, msg0); - } else { - pIndex->tableIndex = i; - pIndex->columnIndex = colIndex; - } - } - } - } else { // table index is valid, get the column index - pIndex->columnIndex = doGetColumnIndex(pQueryInfo, pIndex->tableIndex, pToken, &pIndex->type); - } - - if (pIndex->columnIndex == COLUMN_INDEX_INITIAL_VAL) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - if (VALID_COLUMN_INDEX(*pIndex)) { - return TSDB_CODE_SUCCESS; - } else { - return TSDB_CODE_TSC_INVALID_OPERATION; - } -} - -int32_t getColumnIndexByName(const SToken* pToken, SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, SMsgBuf* pMsgBuf) { - if (pQueryInfo->pTableMetaInfo == NULL || pQueryInfo->numOfTables == 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - SToken tmpToken = *pToken; - if (getTableIndexByName(&tmpToken, pQueryInfo, pIndex) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - return doGetColumnIndexByName(&tmpToken, pQueryInfo, pIndex, pMsgBuf); -} - -int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf* pMsgBuf) { - const char* msg1 = "too many columns in group by clause"; - const char* msg2 = "invalid column name in group by clause"; - const char* msg3 = "columns from one table allowed as group by columns"; - const char* msg4 = "join query does not support group by"; - const char* msg5 = "not allowed column type for group by"; - const char* msg6 = "tags not allowed for table query"; - const char* msg7 = "normal column and tags can not be mixed up in group by clause"; - const char* msg8 = "normal column can only locate at the end of group by clause"; - - SGroupbyExpr* pGroupExpr = &(pQueryInfo->groupbyExpr); - pGroupExpr->columnInfo = taosArrayInit(4, sizeof(SColIndex)); - if (pGroupExpr->columnInfo == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - - // todo : handle two tables situation - STableMetaInfo* pTableMetaInfo = NULL; - if (pList == NULL) { - return TSDB_CODE_SUCCESS; - } - - if (pQueryInfo->numOfTables > 1) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - size_t num = taosArrayGetSize(pList); - if (num > TSDB_MAX_TAGS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - int32_t numOfGroupbyCols = 0; - SSchema *pSchema = NULL; - int32_t tableIndex = COLUMN_INDEX_INITIAL_VAL; - bool groupbyTag = false; - - for (int32_t i = 0; i < num; ++i) { - SListItem * pItem = taosArrayGet(pList, i); - SVariant* pVar = &pItem->pVar; - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - SToken token = {pVar->nLen, pVar->nType, pVar->pz}; - if (getColumnIndexByName(&token, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - // Group by multiple tables is not supported. - if (tableIndex == COLUMN_INDEX_INITIAL_VAL) { - tableIndex = index.tableIndex; - } else if (tableIndex != index.tableIndex) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - - if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - pSchema = getTbnameColumnSchema(); - } else { - pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); - } - - bool groupTag = TSDB_COL_IS_TAG(index.type); - if (groupTag) { - if (!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - groupbyTag = true; - - SColumn c = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, pSchema); - taosArrayPush(pGroupExpr->columnInfo, &c); - - columnListInsert(pTableMetaInfo->tagColList, pTableMeta->uid, pSchema, TSDB_COL_TAG); - } else { - // check if the column type is valid, here only support the bool/tinyint/smallint/bigint group by - if (pSchema->type == TSDB_DATA_TYPE_FLOAT || pSchema->type == TSDB_DATA_TYPE_DOUBLE) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - SColumn c = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_NORMAL, pSchema); - taosArrayPush(pGroupExpr->columnInfo, &c); - - columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL); - - numOfGroupbyCols++; - pQueryInfo->info.groupbyColumn = true; - } - } - - if (numOfGroupbyCols > 0 && groupbyTag) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - - // todo ??? - // 1. the normal column in the group by clause can only located at the end position - for(int32_t i = 0; i < num; ++i) { - SColIndex* pIndex = taosArrayGet(pGroupExpr->columnInfo, i); - if (TSDB_COL_IS_NORMAL_COL(pIndex->flag) && i != num - 1) { - return buildInvalidOperationMsg(pMsgBuf, msg8); - } - } - - pGroupExpr->groupbyTag = groupbyTag; - return TSDB_CODE_SUCCESS; -} - -int32_t checkForUnsupportedQuery(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { - const char* msg1 = "not support percentile/interp/block_dist in the outer query yet"; - - for (int32_t i = 0; i < getNumOfExprs(pQueryInfo); ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - assert(pExpr->pExpr->nodeType == TEXPR_UNARYEXPR_NODE); - - int32_t f = getExprFunctionId(pExpr); - if (f == FUNCTION_PERCT || f == FUNCTION_INTERP) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (f == FUNCTION_BLKINFO && taosArrayGetSize(pQueryInfo->pDownstream) > 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - -#if 0 - //todo planner handle this - if (/*(timeWindowQuery || pQueryInfo->stateWindow) &&*/ f == FUNCTION_LAST) { - pExpr->base.numOfParams = 1; - pExpr->base.param[0].i = TSDB_ORDER_ASC; - pExpr->base.param[0].nType = TSDB_DATA_TYPE_INT; - } -#endif - } -} - -int32_t validateWhereNode(SQueryStmtInfo *pQueryInfo, tSqlExpr* pWhereExpr, SMsgBuf* pMsgBuf) { - return 0; -} - -static int32_t parseIntervalOffset(SQueryStmtInfo* pQueryInfo, SToken* offsetToken, int32_t precision, SMsgBuf* pMsgBuf) { - const char* msg1 = "interval offset cannot be negative"; - const char* msg2 = "interval offset should be shorter than interval"; - const char* msg3 = "cannot use 'year' as offset when interval is 'month'"; - - SToken* t = offsetToken; - SInterval* pInterval = &pQueryInfo->interval; - - if (t->n == 0) { - pInterval->offsetUnit = pInterval->intervalUnit; - pInterval->offset = 0; - return TSDB_CODE_SUCCESS; - } - - if (parseNatualDuration(t->z, t->n, &pInterval->offset, &pInterval->offsetUnit, precision) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (pInterval->offset < 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (!TIME_IS_VAR_DURATION(pInterval->offsetUnit)) { - if (!TIME_IS_VAR_DURATION(pInterval->intervalUnit)) { - if (pInterval->offset > pInterval->interval) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - } - } else if (pInterval->offsetUnit == pInterval->intervalUnit) { - if (pInterval->offset >= pInterval->interval) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - } else if (pInterval->intervalUnit == 'n' && pInterval->offsetUnit == 'y') { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } else if (pInterval->intervalUnit == 'y' && pInterval->offsetUnit == 'n') { - if (pInterval->interval * 12 <= pQueryInfo->interval.offset) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - } else { - // TODO: offset should be shorter than interval, but how to check - // conflicts like 30days offset and 1 month interval - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t parseSlidingClause(SQueryStmtInfo* pQueryInfo, SToken* pSliding, int32_t precision, SMsgBuf* pMsgBuf) { - const char* msg1 = "sliding value no larger than the interval value"; - const char* msg2 = "sliding value can not less than 1% of interval value"; - const char* msg3 = "does not support sliding when interval is natural month/year"; - const char* msg4 = "sliding value too small"; - - const static int32_t INTERVAL_SLIDING_FACTOR = 100; - - SInterval* pInterval = &pQueryInfo->interval; - if (pSliding->n == 0) { - pInterval->slidingUnit = pInterval->intervalUnit; - pInterval->sliding = pInterval->interval; - return TSDB_CODE_SUCCESS; - } - - if (TIME_IS_VAR_DURATION(pInterval->intervalUnit)) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - parseAbsoluteDuration(pSliding->z, pSliding->n, &pInterval->sliding, &pInterval->slidingUnit, precision); - - // less than the threshold - if (pInterval->sliding < convertTimePrecision(tsMinSlidingTime, TSDB_TIME_PRECISION_MILLI, precision)) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - if (pInterval->sliding > pInterval->interval) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if ((pInterval->interval != 0) && (pInterval->interval/pInterval->sliding > INTERVAL_SLIDING_FACTOR)) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - return TSDB_CODE_SUCCESS; -} - -static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, int32_t outputIndex, int32_t tableIndex); - -// validate the interval info -int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { - const char* msg1 = "sliding cannot be used without interval"; - const char* msg2 = "only point interpolation query requires keyword EVERY"; - const char* msg3 = "interval value is too small"; - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - STableComInfo tinfo = getTableInfo(pTableMetaInfo->pTableMeta); - - if (!TPARSER_HAS_TOKEN(pSqlNode->interval.interval)) { - if (TPARSER_HAS_TOKEN(pSqlNode->sliding)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } else { - return TSDB_CODE_SUCCESS; - } - } - - // interval is not null - SToken *t = &pSqlNode->interval.interval; - if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval, - &pQueryInfo->interval.intervalUnit, tinfo.precision) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (pQueryInfo->interval.interval <= 0) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - if (!TIME_IS_VAR_DURATION(pQueryInfo->interval.intervalUnit)) { - // interval cannot be less than 10 milliseconds - if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MICRO) < tsMinIntervalTime) { - char msg[50] = {0}; - snprintf(msg, 50, "interval time window can not be less than %d %s", tsMinIntervalTime, TSDB_TIME_PRECISION_MICRO_STR); - return buildInvalidOperationMsg(pMsgBuf, msg); - } - } - - if (parseIntervalOffset(pQueryInfo, &pSqlNode->interval.offset, tinfo.precision, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (parseSlidingClause(pQueryInfo, &pSqlNode->sliding, tinfo.precision, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (tsCompatibleModel) { - SExprInfo* pFirstExpr = getExprInfo(pQueryInfo, 0); - if (pFirstExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE || strcasecmp(pFirstExpr->pExpr->_function.functionName, "dummy") != 0) { - setTsOutputExprInfo(pQueryInfo, pTableMetaInfo, 0, 0); - } - } - - // It is a time window query - pQueryInfo->info.timewindow = true; - return TSDB_CODE_SUCCESS; -} - -int32_t validateSessionNode(SQueryStmtInfo *pQueryInfo, SSessionWindowVal* pSession, int32_t precision, SMsgBuf* pMsgBuf) { - const char* msg1 = "gap should be fixed time window"; - const char* msg2 = "only one type time window allowed"; - const char* msg3 = "invalid column name"; - const char* msg4 = "invalid time window"; - const char* msg5 = "only the primary time stamp column can be used in session window"; - - // no session window - if (!TPARSER_HAS_TOKEN(pSession->gap)) { - return TSDB_CODE_SUCCESS; - } - - SToken* col = &pSession->col; - SToken* gap = &pSession->gap; - - char timeUnit = 0; - if (parseNatualDuration(gap->z, gap->n, &pQueryInfo->sessionWindow.gap, &timeUnit, precision) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - if (TIME_IS_VAR_DURATION(timeUnit)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (pQueryInfo->sessionWindow.gap != 0 && pQueryInfo->interval.interval != 0) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - if (pQueryInfo->sessionWindow.gap == 0) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if ((getColumnIndexByName(col, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS)) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - - SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); - pQueryInfo->sessionWindow.col = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); - pQueryInfo->info.sessionWindow = true; - return TSDB_CODE_SUCCESS; -} - -// parse the window_state -int32_t validateStateWindowNode(SQueryStmtInfo *pQueryInfo, SWindowStateVal* pWindowState, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid column name"; - const char* msg2 = "invalid column type to create state window"; - const char* msg3 = "not support state_window with group by"; - const char* msg4 = "function not support for super table query"; - const char* msg5 = "not support state_window on tag column"; - - SToken *col = &(pWindowState->col) ; - if (!TPARSER_HAS_TOKEN(*col)) { - return TSDB_CODE_SUCCESS; - } - - SGroupbyExpr* pGroupExpr = &pQueryInfo->groupbyExpr; - if (taosArrayGetSize(pGroupExpr->columnInfo) > 0) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(col, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - STableMetaInfo *pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - - if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - if (TSDB_COL_IS_TAG(index.type)) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); - if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP || IS_FLOAT_TYPE(pSchema->type)) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - pQueryInfo->stateWindow.col = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); - pQueryInfo->info.stateWindow = true; - - columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, index.type); - return TSDB_CODE_SUCCESS; -} - -// parse the having clause in the first place -int32_t validateHavingNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { - return 0; -} - -int32_t validateLimitNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - - const char* msg1 = "slimit/soffset only available for STable query"; - const char* msg2 = "slimit/soffset can not apply to projection query"; - const char* msg3 = "soffset/offset can not be less than 0"; - - // handle the limit offset value, validate the limit - pQueryInfo->limit = pSqlNode->limit; - pQueryInfo->slimit = pSqlNode->slimit; - -// tscDebug("0x%"PRIx64" limit:%" PRId64 ", offset:%" PRId64 " slimit:%" PRId64 ", soffset:%" PRId64, pSql->self, -// pQueryInfo->limit.limit, pQueryInfo->limit.offset, pQueryInfo->slimit.limit, pQueryInfo->slimit.offset); - - if (pQueryInfo->slimit.offset < 0 || pQueryInfo->limit.offset < 0) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - if (pQueryInfo->limit.limit == 0) { -// tscDebug("0x%"PRIx64" limit 0, no output result", pSql->self); - pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; - return TSDB_CODE_SUCCESS; - } - - if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { -// if (!tscQueryTags(pQueryInfo)) { // local handle the super table tag query -// if (tscIsProjectionQueryOnSTable(pQueryInfo, 0)) { -// if (pQueryInfo->slimit.limit > 0 || pQueryInfo->slimit.offset > 0) { -// return buildInvalidOperationMsg(pMsgBuf, msg2); -// } -// -// // for projection query on super table, all queries are subqueries -// if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && -// !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY)) { -// pQueryInfo->type |= TSDB_QUERY_TYPE_SUBQUERY; -// } -// } -// } - - if (pQueryInfo->slimit.limit == 0) { -// tscDebug("0x%"PRIx64" slimit 0, no output result", pSql->self); - pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; - return TSDB_CODE_SUCCESS; - } - - // No tables included. No results generated. Query results are empty. - if (pTableMetaInfo->vgroupList->numOfVgroups == 0) { -// tscDebug("0x%"PRIx64" no table in super table, no output result", pSql->self); - pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; - return TSDB_CODE_SUCCESS; - } - } else { - if (pQueryInfo->slimit.limit != -1 || pQueryInfo->slimit.offset != 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid column name in orderby clause"; - const char* msg2 = "too many order by columns"; - const char* msg3 = "only one column allowed in orderby"; - const char* msg4 = "invalid order by column index"; - - if (pSqlNode->pSortOrder == NULL) { - return TSDB_CODE_SUCCESS; - } - - pQueryInfo->order = taosArrayInit(4, sizeof(SOrder)); - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - SArray* pSortOrder = pSqlNode->pSortOrder; - - /* - * for table query, there is only one or none order option is allowed, which is the - * ts or values(top/bottom) order is supported. - * - * for super table query, the order option must be less than 3. - */ - size_t size = taosArrayGetSize(pSortOrder); - if ((UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) && (pQueryInfo->info.projectionQuery)) { - if (size > 1) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - } - - // handle the first part of order by - bool found = false; - for(int32_t i = 0; i < taosArrayGetSize(pSortOrder); ++i) { - SListItem* pItem = taosArrayGet(pSortOrder, i); - - SVariant* pVar = &pItem->pVar; - if (pVar->nType == TSDB_DATA_TYPE_BINARY) { - SOrder order = {0}; - - // find the orde column among the result field. - for (int32_t j = 0; j < getNumOfFields(&pQueryInfo->fieldsInfo); ++j) { - SInternalField* pInfo = taosArrayGet(pQueryInfo->fieldsInfo.internalField, j); - SSchema* pSchema = &pInfo->pExpr->base.resSchema; - if (strcasecmp(pVar->pz, pSchema->name) == 0) { - setColumn(&order.col, pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TMP, pSchema); - - order.order = pItem->sortOrder; - taosArrayPush(pQueryInfo->order, &order); - found = true; - break; - } - } - - if (!found) { - return buildInvalidOperationMsg(pMsgBuf, "invalid order by column"); - } - - } else { // order by [1|2|3] - if (pVar->i > getNumOfFields(&pQueryInfo->fieldsInfo)) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - int32_t index = pVar->i - 1; - SExprInfo* pExprInfo = getExprInfo(pQueryInfo, index); - - SOrder c = {0}; - setColumn(&c.col, pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TMP, &pExprInfo->base.resSchema); - c.order = pItem->sortOrder; - taosArrayPush(pQueryInfo->order, &c); - } - } - - return TSDB_CODE_SUCCESS; -} - -#if 0 -// set order by info -int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { - const char* msg0 = "only one column allowed in orderby"; - const char* msg1 = "invalid column name in orderby clause"; - const char* msg2 = "too many order by columns"; - const char* msg3 = "only primary timestamp/tbname/first tag in groupby clause allowed"; - const char* msg4 = "only tag in groupby clause allowed in order clause"; - const char* msg5 = "only primary timestamp/column in top/bottom function allowed as order column"; - const char* msg6 = "only primary timestamp allowed as the second order column"; - const char* msg7 = "only primary timestamp/column in groupby clause allowed as order column"; - const char* msg8 = "only column in groupby clause allowed as order column"; - const char* msg9 = "orderby column must projected in subquery"; - const char* msg10 = "not support distinct mixed with order by"; - -// setDefaultOrderInfo(pQueryInfo); - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - SSchema* pSchema = getTableColumnSchema(pTableMetaInfo->pTableMeta); - int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta); - - if (pSqlNode->pSortOrder == NULL) { - return TSDB_CODE_SUCCESS; - } - - SArray* pSortOrder = pSqlNode->pSortOrder; - - /* - * for table query, there is only one or none order option is allowed, which is the - * ts or values(top/bottom) order is supported. - * - * for super table query, the order option must be less than 3. - */ - size_t size = taosArrayGetSize(pSortOrder); - if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo)) { - if (size > 1) { - return buildInvalidOperationMsg(pMsgBuf, msg0); - } - } else { - if (size > 2) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - } - -#if 0 - if (size > 0 && pQueryInfo->distinct) { - return buildInvalidOperationMsg(pMsgBuf, msg10); - } -#endif - - // handle the first part of order by - SVariant* pVar = taosArrayGet(pSortOrder, 0); - -#if 0 - // e.g., order by 1 asc, return directly with out further check. - if (pVar->nType >= TSDB_DATA_TYPE_TINYINT && pVar->nType <= TSDB_DATA_TYPE_BIGINT) { - return TSDB_CODE_SUCCESS; - } -#endif - - SToken columnName = {pVar->nLen, pVar->nType, pVar->pz}; - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // super table query - if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - bool orderByTags = false; - bool orderByTS = false; - bool orderByGroupbyCol = false; - - if (TSDB_COL_IS_TAG(index.type) && index.columnIndex != TSDB_TBNAME_COLUMN_INDEX) { - // it is a tag column - if (pQueryInfo->groupbyExpr.columnInfo == NULL) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - int32_t relTagIndex = index.columnIndex - numOfCols; - SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0); - if (relTagIndex == pColIndex->colIndex) { - orderByTags = true; - } - } else if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - orderByTags = true; - } - - if (PRIMARYKEY_TIMESTAMP_COL_ID == index.columnIndex) { - orderByTS = true; - } - - SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo; - if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) { - SColIndex* pColIndex = taosArrayGet(columnInfo, 0); - if (PRIMARYKEY_TIMESTAMP_COL_ID != index.columnIndex && pColIndex->colIndex == index.columnIndex) { - orderByGroupbyCol = true; - } - } - - if (!(orderByTags || orderByTS || orderByGroupbyCol) /*&& !isTopBottomQuery(pQueryInfo)*/) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } else { // order by top/bottom result value column is not supported in case of interval query. - assert(!(orderByTags && orderByTS && orderByGroupbyCol)); - } - - size_t s = taosArrayGetSize(pSortOrder); - if (s == 1) { - if (orderByTags) { - pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - numOfCols; - - SListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->groupbyExpr.orderType = p1->sortOrder; - } else if (orderByGroupbyCol) { - SListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0); - - pQueryInfo->groupbyExpr.orderType = p1->sortOrder; - pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId; - } else if (isTopBottomQuery(pQueryInfo)) { - /* order of top/bottom query in interval is not valid */ - int32_t pos = tscExprTopBottomIndex(pQueryInfo); - assert(pos > 0); - - SExprInfo* pExpr = getExprInfo(pQueryInfo, pos - 1); -// assert(getExprFunctionId(pExpr) == FUNCTION_TS); - - pExpr = getExprInfo(pQueryInfo, pos); - - // other tag are not allowed - if (pExpr->base.pColumns->colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - SListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->order.order = p1->sortOrder; - pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId; - return TSDB_CODE_SUCCESS; - } else { - SListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0); - - pQueryInfo->order.order = p1->sortOrder; - pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_ID; - - // orderby ts query on super table - if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) { - bool found = false; - for (int32_t i = 0; i < getNumOfExprs(pQueryInfo); ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - if (getExprFunctionId(pExpr) == FUNCTION_PRJ && pExpr->base.pColumns->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { - found = true; - break; - } - } - - if (!found && pQueryInfo->pDownstream) { - return buildInvalidOperationMsg(pMsgBuf, msg9); - } - - // this is a invisible output column, in order to used to sort the result. - setTsOutputExprInfo(pQueryInfo, pTableMetaInfo, 0, index.tableIndex); - } - } - } else { - SListItem *pItem = taosArrayGet(pSqlNode->pSortOrder, 0); - if (orderByTags) { - pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - numOfCols; - pQueryInfo->groupbyExpr.orderType = pItem->sortOrder; - } else if (orderByGroupbyCol) { - pQueryInfo->order.order = pItem->sortOrder; - pQueryInfo->order.orderColId = index.columnIndex; - } else { - pQueryInfo->order.order = pItem->sortOrder; - pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_ID; - } - - pItem = taosArrayGet(pSqlNode->pSortOrder, 1); - SVariant* pVar2 = &pItem->pVar; - SToken cname = {pVar2->nLen, pVar2->nType, pVar2->pz}; - if (getColumnIndexByName(&cname, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } else { - SListItem* p1 = taosArrayGet(pSortOrder, 1); - pQueryInfo->order.order = p1->sortOrder; - pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_ID; - } - } - - } else if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo)) { // check order by clause for normal table & temp table - if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID && !isTopBottomQuery(pQueryInfo)) { - bool validOrder = false; - SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo; - if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) { - SColIndex* pColIndex = taosArrayGet(columnInfo, 0); - validOrder = (pColIndex->colIndex == index.columnIndex); - } - - if (!validOrder) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - - SListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->groupbyExpr.orderIndex = pSchema[index.columnIndex].colId; - pQueryInfo->groupbyExpr.orderType = p1->sortOrder; - } - - if (isTopBottomQuery(pQueryInfo)) { - SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo; - if (columnInfo != NULL && taosArrayGetSize(columnInfo) > 0) { - SColIndex* pColIndex = taosArrayGet(columnInfo, 0); - - if (pColIndex->colIndex == index.columnIndex) { - return buildInvalidOperationMsg(pMsgBuf, msg8); - } - } else { - int32_t pos = tscExprTopBottomIndex(pQueryInfo); - assert(pos > 0); - SExprInfo* pExpr = getExprInfo(pQueryInfo, pos - 1); - assert(getExprFunctionId(pExpr) == FUNCTION_TS); - - pExpr = getExprInfo(pQueryInfo, pos); - - if (pExpr->base.pColumns->colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - } - - SListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->order.order = pItem->sortOrder; - - pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId; - return TSDB_CODE_SUCCESS; - } - - SListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->order.order = pItem->sortOrder; - pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId; - } else { - // handle the temp table order by clause. You can order by any single column in case of the temp table, created by - // inner subquery. - assert(UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo) && taosArrayGetSize(pSqlNode->pSortOrder) == 1); - - if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - SListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->order.order = pItem->sortOrder; - pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId; - } - - return TSDB_CODE_SUCCESS; -} -#endif - -static int32_t checkFillQueryRange(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { - const char* msg1 = "start(end) time of time range required or time range too large"; - - if (pQueryInfo->interval.interval == 0) { - return TSDB_CODE_SUCCESS; - } - - // TODO disable this check temporarily -// bool initialWindows = TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER); -// if (initialWindows) { -// return buildInvalidOperationMsg(pMsgBuf, msg1); -// } - - int64_t timeRange = TABS(pQueryInfo->window.skey - pQueryInfo->window.ekey); - - int64_t intervalRange = 0; - if (!TIME_IS_VAR_DURATION(pQueryInfo->interval.intervalUnit)) { - intervalRange = pQueryInfo->interval.interval; - - // number of result is not greater than 10,000,000 - if ((timeRange == 0) || (timeRange / intervalRange) >= MAX_INTERVAL_TIME_WINDOW) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t validateFillNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { - SArray* pFillToken = pSqlNode->fillType; - if (pSqlNode->fillType == NULL) { - return TSDB_CODE_SUCCESS; - } - - SListItem* pItem = taosArrayGet(pFillToken, 0); - - const int32_t START_INTERPO_COL_IDX = 1; - - const char* msg1 = "value is expected"; - const char* msg2 = "invalid fill option"; - const char* msg4 = "illegal value or data overflow"; - const char* msg6 = "not supported function now"; - - /* - * fill options are set at the end position, when all columns are set properly - * the columns may be increased due to group by operation - */ - if (checkFillQueryRange(pQueryInfo, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - - if (pItem->pVar.nType != TSDB_DATA_TYPE_BINARY) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - int32_t numOfFields = (int32_t) getNumOfFields(&pQueryInfo->fieldsInfo); - - pQueryInfo->fillVal = calloc(numOfFields, sizeof(int64_t)); - if (pQueryInfo->fillVal == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - - pQueryInfo->numOfFillVal = (int32_t)numOfFields; - if (strncasecmp(pItem->pVar.pz, "none", 4) == 0 && pItem->pVar.nLen == 4) { - pQueryInfo->fillType = TSDB_FILL_NONE; - } else if (strncasecmp(pItem->pVar.pz, "null", 4) == 0 && pItem->pVar.nLen == 4) { - pQueryInfo->fillType = TSDB_FILL_NULL; - for (int32_t i = START_INTERPO_COL_IDX; i < numOfFields; ++i) { - TAOS_FIELD* pField = &getInternalField(&pQueryInfo->fieldsInfo, i)->field; - setNull((char*)&pQueryInfo->fillVal[i], pField->type, pField->bytes); - } - } else if (strncasecmp(pItem->pVar.pz, "prev", 4) == 0 && pItem->pVar.nLen == 4) { - pQueryInfo->fillType = TSDB_FILL_PREV; -// if (pQueryInfo->info.interpQuery && pQueryInfo->order.order == TSDB_ORDER_DESC) { -// return buildInvalidOperationMsg(pMsgBuf, msg6); -// } - } else if (strncasecmp(pItem->pVar.pz, "next", 4) == 0 && pItem->pVar.nLen == 4) { - pQueryInfo->fillType = TSDB_FILL_NEXT; - } else if (strncasecmp(pItem->pVar.pz, "linear", 6) == 0 && pItem->pVar.nLen == 6) { - pQueryInfo->fillType = TSDB_FILL_LINEAR; - } else if (strncasecmp(pItem->pVar.pz, "value", 5) == 0 && pItem->pVar.nLen == 5) { - pQueryInfo->fillType = TSDB_FILL_SET_VALUE; - - size_t num = taosArrayGetSize(pFillToken); - if (num == 1) { // no actual value, return with error code - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - int32_t startPos = 1; - int32_t numOfFillVal = (int32_t)(num - 1); - - // for point interpolation query, we do not have the timestamp column - if (pQueryInfo->info.interpQuery) { - startPos = 0; - if (numOfFillVal > numOfFields) { - numOfFillVal = numOfFields; - } - } else { - numOfFillVal = TMIN(num, numOfFields); - } - - int32_t j = 1; - - for (int32_t i = startPos; i < numOfFillVal; ++i, ++j) { - TAOS_FIELD* pField = &getInternalField(&pQueryInfo->fieldsInfo, i)->field; - if (pField->type == TSDB_DATA_TYPE_BINARY || pField->type == TSDB_DATA_TYPE_NCHAR) { - setVardataNull((char*) &pQueryInfo->fillVal[i], pField->type); - continue; - } - - SVariant* p = taosArrayGet(pFillToken, j); - int32_t ret = taosVariantDump(p, (char*)&pQueryInfo->fillVal[i], pField->type, true); - if (ret != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - } - - if ((num < numOfFields) || ((num - 1 < numOfFields) && (pQueryInfo->info.interpQuery))) { - SListItem* lastItem = taosArrayGetLast(pFillToken); - - for (int32_t i = numOfFillVal; i < numOfFields; ++i) { - TAOS_FIELD* pField = &getInternalField(&pQueryInfo->fieldsInfo, i)->field; - - if (pField->type == TSDB_DATA_TYPE_BINARY || pField->type == TSDB_DATA_TYPE_NCHAR) { - setVardataNull((char*) &pQueryInfo->fillVal[i], pField->type); - } else { - taosVariantDump(&lastItem->pVar, (char*)&pQueryInfo->fillVal[i], pField->type, true); - } - } - } - } else { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - return TSDB_CODE_SUCCESS; -} - -static void pushDownAggFuncExprInfo(SQueryStmtInfo* pQueryInfo); -static void addColumnNodeFromLowerLevel(SQueryStmtInfo* pQueryInfo); - -static void freeItemHelper(void* pItem) { - void** p = pItem; - if (*p != NULL) { - tfree(*p); - } -} - -int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { - assert(pSqlNode != NULL && (pSqlNode->from == NULL || taosArrayGetSize(pSqlNode->from->list) > 0)); - - const char* msg1 = "point interpolation query needs timestamp"; - const char* msg2 = "too many tables in from clause"; - const char* msg3 = "start(end) time of query range required or time range too large"; - const char* msg4 = "interval query not supported, since the result of sub query not include valid timestamp column"; - const char* msg5 = "only tag query not compatible with normal column filter"; - const char* msg7 = "derivative/twa/irate requires timestamp column exists in subquery"; - const char* msg8 = "condition missing for join query"; - - int32_t code = TSDB_CODE_SUCCESS; - - /* - * handle the sql expression without from subclause - * select server_status(); - * select server_version(); - * select client_version(); - * select database(); - * select 1+2; - * select now(); - */ - if (pSqlNode->from == NULL) { - assert(pSqlNode->fillType == NULL && pSqlNode->pGroupby == NULL && pSqlNode->pWhere == NULL && - pSqlNode->pSortOrder == NULL); - assert(0); -// return doLocalQueryProcess(pCmd, pQueryInfo, pSqlNode); - } - - if (pSqlNode->from->type == SQL_FROM_NODE_SUBQUERY) { - pQueryInfo->numOfTables = 0; - - // parse the subquery in the first place - int32_t numOfSub = (int32_t)taosArrayGetSize(pSqlNode->from->list); - for (int32_t i = 0; i < numOfSub; ++i) { - SRelElement* subInfo = taosArrayGet(pSqlNode->from->list, i); - code = doValidateSubquery(pSqlNode, i, pQueryInfo, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - // parse the group by clause in the first place - if (validateGroupbyNode(pQueryInfo, pSqlNode->pGroupby, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (validateSelectNodeList(pQueryInfo, pSqlNode->pSelNodeList, true, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - code = checkForUnsupportedQuery(pQueryInfo, pMsgBuf); - - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, 0)->pTableMeta; - SSchema* pSchema = getOneColumnSchema(pTableMeta, 0); - int32_t precision = pTableMeta->tableInfo.precision; - -#if 0 - if (pSchema->type != TSDB_DATA_TYPE_TIMESTAMP) { - int32_t numOfExprs = (int32_t)getNumOfExprs(pQueryInfo); - - for (int32_t i = 0; i < numOfExprs; ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - - int32_t f = pExpr->pExpr->_node.functionId; - if (f == FUNCTION_DERIVATIVE || f == FUNCTION_TWA || f == FUNCTION_IRATE) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - } - } -#endif - - // validate the query filter condition info - if (pSqlNode->pWhere != NULL) { - if (validateWhereNode(pQueryInfo, pSqlNode->pWhere, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } else { - if (pQueryInfo->numOfTables > 1) { - return buildInvalidOperationMsg(pMsgBuf, msg8); - } - } - - // validate the interval info - if (validateIntervalNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } else { - if (validateSessionNode(pQueryInfo, &pSqlNode->sessionVal, precision, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // parse the window_state - if (validateStateWindowNode(pQueryInfo, &pSqlNode->windowstateVal, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } - - // parse the having clause in the first place - int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1); - if (validateHavingNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if ((code = validateLimitNode(pQueryInfo, pSqlNode, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - - // set order by info - if (validateOrderbyNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if ((code = validateFillNode(pQueryInfo, pSqlNode, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - } else { - pQueryInfo->command = TSDB_SQL_SELECT; - if (taosArrayGetSize(pSqlNode->from->list) > TSDB_MAX_JOIN_TABLE_NUM) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - pQueryInfo->info.stableQuery = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo); - - int32_t precision = pTableMetaInfo->pTableMeta->tableInfo.precision; - - // parse the group by clause in the first place - if (validateGroupbyNode(pQueryInfo, pSqlNode->pGroupby, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // set where info - if (pSqlNode->pWhere != NULL) { - if (validateWhereNode(pQueryInfo, pSqlNode->pWhere, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } else { - if (taosArrayGetSize(pSqlNode->from->list) > 1) { // Cross join not allowed yet - return buildInvalidOperationMsg(pMsgBuf, "cross join not supported yet"); - } - } - - if (validateSelectNodeList(pQueryInfo, pSqlNode->pSelNodeList, false, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // parse the window_state - if (validateStateWindowNode(pQueryInfo, &pSqlNode->windowstateVal, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // set interval value - if (validateIntervalNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // parse the having clause in the first place - if (validateHavingNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - /* - * transfer sql functions that need secondary merge into another format - * in dealing with super table queries such as: count/first/last - */ - if (validateSessionNode(pQueryInfo, &pSqlNode->sessionVal, precision, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // no result due to invalid query time range - if (pQueryInfo->window.skey > pQueryInfo->window.ekey) { - pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; - return TSDB_CODE_SUCCESS; - } - - // set order by info - if (validateOrderbyNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if ((code = validateLimitNode(pQueryInfo, pSqlNode, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - - if ((code = validateFillNode(pQueryInfo, pSqlNode, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - } - - pushDownAggFuncExprInfo(pQueryInfo); - - for(int32_t i = 0; i < 1; ++i) { - SArray* functionList = extractFunctionList(pQueryInfo->exprList[i]); - extractFunctionDesc(functionList, &pQueryInfo->info); - - code = checkForInvalidExpr(pQueryInfo, pMsgBuf); - taosArrayDestroyEx(functionList, freeItemHelper); - - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - return TSDB_CODE_SUCCESS; // Does not build query message here -} - -static bool isTagOrPrimaryTs(SExprInfo* pExprInfo) { - if (pExprInfo->pExpr->nodeType != TEXPR_COL_NODE) { - return false; - } - - assert(pExprInfo->base.pColumns->info.colId == pExprInfo->pExpr->pSchema->colId); - return (TSDB_COL_IS_TAG(pExprInfo->base.pColumns->flag) || pExprInfo->pExpr->pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID); -} - -// todo extract the table column in expression - -static bool isGroupbyCol(SExprInfo* pExprInfo, SGroupbyExpr* pGroupbyExpr) { - assert(pExprInfo != NULL && pGroupbyExpr != NULL); - - int32_t nodeType = pExprInfo->pExpr->nodeType; - assert(nodeType == TEXPR_COL_NODE || nodeType == TEXPR_BINARYEXPR_NODE); - - for(int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) { - SColumn* pCol = taosArrayGet(pGroupbyExpr->columnInfo, i); - if (pCol->info.colId == pExprInfo->pExpr->pSchema->colId) { - return true; - } - } - - return false; -} - -static bool isAllAggExpr(SArray* pList) { - assert(pList != NULL); - - for (int32_t k = 0; k < taosArrayGetSize(pList); ++k) { - SExprInfo* p = taosArrayGetP(pList, k); - if (p->pExpr->nodeType != TEXPR_FUNCTION_NODE || !qIsAggregateFunction(p->pExpr->_function.functionName)) { - return false; - } - } - - return true; -} - -static bool isAllProjectExpr(SArray *pList) { - assert(pList != NULL); - - for(int32_t i = 0; i < taosArrayGetSize(pList); ++i) { - SExprInfo* p = taosArrayGetP(pList, i); - if (p->pExpr->nodeType == TEXPR_FUNCTION_NODE && !qIsAggregateFunction(p->pExpr->_function.functionName)) { - return false; - } - } - - return true; -} - -static SExprInfo* createColumnNodeFromAggFunc(SSchema* pSchema); - -static void pushDownAggFuncExprInfo(SQueryStmtInfo* pQueryInfo) { - assert(pQueryInfo != NULL); - - size_t level = getExprFunctionLevel(pQueryInfo); - for(int32_t i = 0; i < level - 1; ++i) { - SArray* p = pQueryInfo->exprList[i]; - - // If direct lower level expressions are all aggregate function, check if current function can be push down or not - SArray* pNext = pQueryInfo->exprList[i + 1]; - if (!isAllAggExpr(pNext)) { - continue; - } - - for (int32_t j = 0; j < taosArrayGetSize(p); ++j) { - SExprInfo* pExpr = taosArrayGetP(p, j); - - if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE && qIsAggregateFunction(pExpr->pExpr->_function.functionName)) { - bool canPushDown = true; - for (int32_t k = 0; k < taosArrayGetSize(pNext); ++k) { - SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k); - // pExpr depends on the output of the down level, so it can not be push downwards - if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) { - canPushDown = false; - break; - } - } - - if (canPushDown) { - taosArrayInsert(pNext, j, &pExpr); - taosArrayRemove(p, j); - - // Add the project function of the current level, to output the calculated result - SExprInfo* pNew = createColumnNodeFromAggFunc(&pExpr->base.resSchema); - taosArrayInsert(p, j, &pNew); - } - } - } - } -} - -// todo change the logic plan data -static void addColumnNodeFromLowerLevel(SQueryStmtInfo* pQueryInfo) { - assert(pQueryInfo != NULL); - - size_t level = getExprFunctionLevel(pQueryInfo); - for (int32_t i = 0; i < level - 1; ++i) { - SArray* p = pQueryInfo->exprList[i]; - if (isAllAggExpr(p)) { - continue; - } - - // If direct lower level expressions are all aggregate function, check if current function can be push down or not - SArray* pNext = pQueryInfo->exprList[i + 1]; - if (isAllAggExpr(pNext)) { - continue; - } - - for (int32_t j = 0; j < taosArrayGetSize(pNext); ++j) { - SExprInfo* pExpr = taosArrayGetP(p, j); - - bool exists = false; - for (int32_t k = 0; k < taosArrayGetSize(p); ++k) { - SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k); - // pExpr depends on the output of the down level, so it can not be push downwards - if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) { - exists = true; - break; - } - } - - if (!exists) { - SExprInfo* pNew = calloc(1, sizeof(SExprInfo)); - pNew->pExpr = exprdup(pExpr->pExpr); - memcpy(&pNew->base, &pExpr->base, sizeof(SSqlExpr)); - - int32_t pos = taosArrayGetSize(p); - // Add the project function of the current level, to output the calculated result - taosArrayInsert(p, pos - 1, &pExpr); - } - } - } -} - -int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { - assert(pQueryInfo != NULL && pMsgBuf != NULL); - - const char* msg1 = "invalid query expression"; - const char* msg2 = "top/bottom query does not support order by value in time window query"; - const char* msg3 = "fill only available in time window query"; - const char* msg4 = "top/bottom not support fill"; - const char* msg5 = "scalar function can not be used in time window query"; - const char* msg6 = "not support distinct mixed with join"; - const char* msg7 = "not support distinct mixed with groupby"; - const char* msg8 = "block_dist not support subquery, only support stable/table"; - const char* msg9 = "time window aggregate can not be mixed up with group by column"; - - if (pQueryInfo->info.topbotQuery) { - - // 1. invalid sql: - // select top(col, k) from table_name [interval(1d)|session(ts, 1d)|statewindow(col)] order by k asc - // order by normal column is not supported - if (pQueryInfo->order != NULL) { - size_t numOfOrder = taosArrayGetSize(pQueryInfo->order); - if (numOfOrder > 1) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - if (numOfOrder > 0) { - SColumn* pOrderCol = taosArrayGet(pQueryInfo->order, 0); - if (pQueryInfo->info.timewindow && pOrderCol->info.colId != PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - } - } - - // select top(col, k) from table_name interval(10s) fill(prev) - // not support fill in top/bottom query. - if (pQueryInfo->fillType != TSDB_FILL_NONE) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - // select top(col, k), count(*) from table_name - size_t size = getNumOfExprs(pQueryInfo); - for (int32_t i = 0; i < size; ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - - if (pExpr->pExpr->nodeType == TEXPR_COL_NODE) { - if (!isTagOrPrimaryTs(pExpr) && !isGroupbyCol(pExpr, &pQueryInfo->groupbyExpr)) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); - } - - } else if (pExpr->pExpr->nodeType == TEXPR_BINARYEXPR_NODE) { - continue; - // todo extract all column node in tree, and check for each node - - continue; - } - - // dummy column is also the placeholder for primary timestamp column in the result. - const char* functionName = pExpr->pExpr->_function.functionName; - if (strcmp(functionName, "top") != 0 && strcmp(functionName, "bottom") != 0 && strcmp(functionName, "dummy") != 0) { - if (qIsAggregateFunction(functionName)) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); - } - - // the primary key is valid - if (pExpr->pExpr->nodeType == TEXPR_COL_NODE) { - if (pExpr->pExpr->pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { - continue; - } - } - - continue; - } - } - } - - /* - * 2. invalid sql: - * select count(tbname)/count(tag1)/count(tag2) from super_table_name [interval(1d)|session(ts, 1d)|statewindow(col)]; - */ - if (pQueryInfo->info.timewindow) { - size_t size = getNumOfExprs(pQueryInfo); - for (int32_t i = 0; i < size; ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - if (pExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE) { - continue; - } - - int32_t functionId = getExprFunctionId(pExpr); - if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.pColumns->flag)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - } - - /* - * 3. invalid sql: - * select tbname, tags_fields from super_table_name [interval(1s)|session(ts,1s)|statewindow(col)] - */ - if (pQueryInfo->info.onlyTagQuery && pQueryInfo->info.timewindow) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - /* - * 4. invalid sql: - * select * from table_name fill(prev|next|null|none) - */ - if (!pQueryInfo->info.timewindow && !pQueryInfo->info.interpQuery && pQueryInfo->fillType != TSDB_FILL_NONE) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - /* - * 5. invalid sql: - * select diff(col)|derivative(col)|* from table_name interval(1s)|session(20s)|statewindow(col) - * projection query not compatible with the time window query - */ - if (pQueryInfo->info.timewindow && pQueryInfo->info.projectionQuery) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - /* - * 6. invalid sql: - * distinct + join not supported. - * select distinct a,b from table1, table2 where table1.ts=table2.ts - * - * distinct + group by not supported: - * select distinct count(a) from table_name group by col1; - */ - if (pQueryInfo->info.distinct) { - if (pQueryInfo->info.join) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - if (taosArrayGetSize(pQueryInfo->groupbyExpr.columnInfo) != 0) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - } - - /* - * 7. invalid sql: - * nested subquery not support block_dist query - * select block_dist() from (select * from table_name) - */ - - /* - * 8. invalid sql: - * select count(*) from table_name [interval(10s)|session(ts, 10s)|state_window(col_name)] group by col_name - */ - if ((pQueryInfo->info.timewindow || pQueryInfo->info.stateWindow || pQueryInfo->info.sessionWindow) && - pQueryInfo->info.groupbyColumn) { - return buildInvalidOperationMsg(pMsgBuf, msg9); - } - - /* - * 9. invalid sql: - * select count(*), col_name from table_name - */ - if (pQueryInfo->info.agg) { - bool isSelectivity = false; - - if (pQueryInfo->info.projectionQuery) { - size_t size = getNumOfExprs(pQueryInfo); - for (int32_t i = 0; i < size; ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE) { - if (!isSelectivity) { - isSelectivity = qIsSelectivityFunction(pExpr->pExpr->_function.functionName); - } - continue; - } - - if (isSelectivity && isTagOrPrimaryTs(pExpr)) { - continue; - } - - if (!isGroupbyCol(pExpr, &pQueryInfo->groupbyExpr)) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select"); - } - } - } - } -} - -int32_t addResColumnInfo(SQueryStmtInfo* pQueryInfo, int32_t outputIndex, SSchema* pSchema, SExprInfo* pSqlExpr) { - SInternalField* pInfo = insertFieldInfo(&pQueryInfo->fieldsInfo, outputIndex, pSchema); - pInfo->pExpr = pSqlExpr; - return TSDB_CODE_SUCCESS; -} - -void setResultColName(char* name, tSqlExprItem* pItem, SToken* pToken, SToken* functionToken, bool multiCols) { - if (pItem->aliasName != NULL) { - tstrncpy(name, pItem->aliasName, TSDB_COL_NAME_LEN); - } else if (multiCols) { - char uname[TSDB_COL_NAME_LEN] = {0}; - int32_t len = TMIN(pToken->n + 1, TSDB_COL_NAME_LEN); - tstrncpy(uname, pToken->z, len); - - if (tsKeepOriginalColumnName) { // keep the original column name - tstrncpy(name, uname, TSDB_COL_NAME_LEN); - } else { - const int32_t size = TSDB_COL_NAME_LEN + FUNCTIONS_NAME_MAX_LENGTH + 2 + 1; - char tmp[TSDB_COL_NAME_LEN + FUNCTIONS_NAME_MAX_LENGTH + 2 + 1] = {0}; - - char f[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - strncpy(f, functionToken->z, functionToken->n); - - snprintf(tmp, size, "%s(%s)", f, uname); - tstrncpy(name, tmp, TSDB_COL_NAME_LEN); - } - } else { // use the user-input result column name - int32_t len = TMIN(pItem->pNode->exprToken.n + 1, TSDB_COL_NAME_LEN); - tstrncpy(name, pItem->pNode->exprToken.z, len); - } -} - -SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, const char* funcName, SSourceParam* pSourceParam, int32_t outputIndex, - STableMetaInfo* pTableMetaInfo, SSchema* pResultSchema, int32_t interSize, const char* token, bool finalResult) { - SExprInfo* pExpr = createExprInfo(pTableMetaInfo, funcName, pSourceParam, pResultSchema, interSize); - tstrncpy(pExpr->base.token, token, sizeof(pExpr->base.token)); - - SArray* pExprList = getCurrentExprList(pQueryInfo); - addExprInfo(pExprList, outputIndex, pExpr, pQueryInfo->exprListLevelIndex); - - uint64_t uid = pTableMetaInfo->pTableMeta->uid; - - if (pSourceParam->pColumnList != NULL) { - SColumn* pCol = taosArrayGetP(pSourceParam->pColumnList, 0); - - if (TSDB_COL_IS_TAG(pCol->flag) || TSDB_COL_IS_NORMAL_COL(pCol->flag)) { - SArray* p = TSDB_COL_IS_TAG(pCol->flag) ? pTableMetaInfo->tagColList : pQueryInfo->colList; - - for (int32_t i = 0; i < pSourceParam->num; ++i) { - SColumn* pColumn = taosArrayGetP(pSourceParam->pColumnList, i); - SSchema s = createSchema(pColumn->info.type, pColumn->info.bytes, pColumn->info.colId, pColumn->name) ; - columnListInsert(p, uid, &s, pCol->flag); - } - } - - if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) { - char* colName = pTableMetaInfo->pTableMeta->schema[0].name; - insertPrimaryTsColumn(pQueryInfo->colList, colName, uid); - } - } - - if (finalResult) { - addResColumnInfo(pQueryInfo, outputIndex, pResultSchema, pExpr); - } - - return pExpr; -} - -static void extractFunctionName(char* name, const tSqlExprItem* pItem) { - assert(pItem != NULL); - SToken* funcToken = &pItem->pNode->Expr.operand; - memcpy(name, funcToken->z, funcToken->n); -} - -static int32_t addOneExprInfo(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, int32_t functionId, int32_t outputIndex, SSchema* pSchema, SColumnIndex* pColIndex, tExprNode* pNode, bool finalResult, SMsgBuf* pMsgBuf) { - const char* msg1 = "not support column types"; - if (functionId == FUNCTION_SPREAD) { - if (IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type == TSDB_DATA_TYPE_BOOL) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - char name[TSDB_COL_NAME_LEN] = {0}; - SToken t = {.z = pSchema->name, .n = (uint32_t)strnlen(pSchema->name, TSDB_COL_NAME_LEN)}; - setResultColName(name, pItem, &t, &pItem->pNode->Expr.operand, true); - - SResultDataInfo resInfo = {0}; - getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resInfo, 0, false); - - SSchema resultSchema = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), name); - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pColIndex->tableIndex); - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, pColIndex->type, pSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, pNode, &c); - - char fname[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - extractFunctionName(fname, pItem); - doAddOneExprInfo(pQueryInfo, fname, ¶m, outputIndex, pTableMetaInfo, &resultSchema, resInfo.intermediateBytes, name, finalResult); - - return TSDB_CODE_SUCCESS; -} - -static int32_t checkForAliasName(SMsgBuf* pMsgBuf, char* aliasName) { - const char* msg1 = "column alias name too long"; - if (aliasName != NULL && strlen(aliasName) >= TSDB_COL_NAME_LEN) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, bool* keepTableCols, SMsgBuf* pMsgBuf); - -static int64_t getTickPerSecond(SVariant* pVariant, int32_t precision, int64_t* tickPerSec, SMsgBuf *pMsgBuf) { - const char* msg10 = "derivative duration should be greater than 1 Second"; - - if (taosVariantDump(pVariant, (char*) tickPerSec, TSDB_DATA_TYPE_BIGINT, true) < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (precision == TSDB_TIME_PRECISION_MILLI) { - *tickPerSec /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MICRO); - } else if (precision == TSDB_TIME_PRECISION_MICRO) { - *tickPerSec /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MILLI); - } - - if (*tickPerSec <= 0 || *tickPerSec < TSDB_TICK_PER_SECOND(precision)) { - return buildInvalidOperationMsg(pMsgBuf, msg10); - } - - return TSDB_CODE_SUCCESS; -} - -// set the first column ts for top/bottom query -static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, int32_t outputIndex, int32_t tableIndex) { - SColumnIndex indexTS = {.tableIndex = tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_ID, .type = TSDB_COL_NORMAL}; - SSchema s = createSchema(TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, getNewResColId(), "ts"); - - SColumn col = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_NORMAL, &s); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &col); - - SExprInfo* pExpr = createExprInfo(pTableMetaInfo, "dummy", ¶m, &s, TSDB_KEYSIZE); - strncpy(pExpr->base.token, "ts", tListLen(pExpr->base.token)); - - SArray* pExprList = getCurrentExprList(pQueryInfo); - addExprInfo(pExprList, outputIndex, pExpr, pQueryInfo->exprListLevelIndex); - - SSchema* pSourceSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, indexTS.columnIndex); - columnListInsert(pQueryInfo->colList, pTableMetaInfo->pTableMeta->uid, pSourceSchema, TSDB_COL_NORMAL); - addResColumnInfo(pQueryInfo, outputIndex, &pExpr->base.resSchema, pExpr); -} - -static int32_t setColumnIndex(SQueryStmtInfo* pQueryInfo, SArray* pParamList, SColumnIndex* index, SSchema* columnSchema, tExprNode** pNode, SMsgBuf* pMsgBuf) { - const char* msg1 = "illegal column name"; - const char* msg2 = "invalid table name"; - - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, 0)->pTableMeta; - if (pParamList == NULL) { - // count(*) is equalled to count(primary_timestamp_key) - *index = (SColumnIndex) {0, 0, false}; - *columnSchema = *(SSchema*) getOneColumnSchema(pTableMeta, index->columnIndex); - } else { - tSqlExprItem* pParamElem = taosArrayGet(pParamList, 0); - - SToken* pToken = &pParamElem->pNode->columnName; - int16_t tokenId = pParamElem->pNode->tokenId; - - // select count(table.*), select count(1), count(2) - if (tokenId == TK_ALL || tokenId == TK_INTEGER || tokenId == TK_FLOAT) { - // check if the table name is valid or not - SToken tmpToken = pParamElem->pNode->columnName; - if (getTableIndexByName(&tmpToken, pQueryInfo, index) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - *index = (SColumnIndex) {0, PRIMARYKEY_TIMESTAMP_COL_ID, false}; - *columnSchema = *(SSchema*) getOneColumnSchema(pTableMeta, index->columnIndex); - } else if (pToken->z != NULL && pToken->n > 0) { - // count the number of table created according to the super table - if (getColumnIndexByName(pToken, pQueryInfo, index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - *columnSchema = *(SSchema*) getOneColumnSchema(pTableMeta, index->columnIndex); - } else { - STableMetaInfo* pTableMetaInfo = NULL; - int32_t code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, columnSchema, pNode, index, pParamElem, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t doAddAllColumnExprInSelectClause(SQueryStmtInfo *pQueryInfo, STableMetaInfo* pTableMetaInfo, tSqlExprItem* pItem, int32_t functionId, - int32_t tableIndex, int32_t* colIndex, bool finalResult, SMsgBuf* pMsgBuf) { - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - for (int32_t i = 0; i < getNumOfColumns(pTableMeta); ++i) { - SColumnIndex index = {.tableIndex = tableIndex, .columnIndex = i, .type = TSDB_COL_NORMAL}; - - SSchema* pSchema = getOneColumnSchema(pTableMeta, i); - if (addOneExprInfo(pQueryInfo, pItem, functionId, *colIndex, pSchema, &index, NULL, finalResult, pMsgBuf) != 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - (*colIndex)++; - } -} - -static int32_t doHandleOneParam(SQueryStmtInfo *pQueryInfo, tSqlExprItem* pItem, tSqlExprItem* pParamElem, int32_t functionId, - int32_t* outputIndex, bool finalResult, SMsgBuf* pMsgBuf) { - const char* msg3 = "illegal column name"; - const char* msg4 = "invalid table name"; - const char* msg6 = "functions applied to tags are not allowed"; - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - - if (pParamElem->pNode->tokenId == TK_ALL) { // select table.* - SToken tmpToken = pParamElem->pNode->columnName; - - if (getTableIndexByName(&tmpToken, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - doAddAllColumnExprInSelectClause(pQueryInfo, pTableMetaInfo, pItem, functionId, index.tableIndex, outputIndex, finalResult, pMsgBuf); - } else { - tExprNode* pNode = NULL; - int32_t tokenId = pParamElem->pNode->tokenId; - SSchema columnSchema = {0}; - STableMetaInfo* pTableMetaInfo = {0}; - - int32_t code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem, pMsgBuf); - - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - // functions can not be applied to tags - if (TSDB_COL_IS_TAG(index.type) && (functionId == FUNCTION_INTERP || functionId == FUNCTION_SPREAD)) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - if (addOneExprInfo(pQueryInfo, pItem, functionId, (*outputIndex)++, &columnSchema, &index, pNode, finalResult, pMsgBuf) != 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } -} - -static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf); -static int32_t addScalarExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf); - -int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, - SSchema* columnSchema, tExprNode** pNode, SColumnIndex* pIndex, - tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf) { - const char* msg1 = "not support column types"; - const char* msg2 = "invalid parameters"; - const char* msg3 = "illegal column name"; - const char* msg4 = "nested function is not supported"; - const char* msg5 = "functions applied to tags are not allowed"; - const char* msg6 = "aggregate function can not be nested in aggregate function"; - const char* msg7 = "invalid function name"; - - pQueryInfo->exprListLevelIndex += 1; - - if (tokenId == TK_ALL || tokenId == TK_ID) { // simple parameter - // simple parameter or nested function - // It is a parameter of a aggregate function, so it can not be still a aggregate function. - // E.g., the sql statement of "select count(count(*)) from table_name" is invalid. - tSqlExpr* pSqlExpr = pParamElem->pNode; - if (pParamElem->pNode->type == SQL_NODE_SQLFUNCTION) { - bool scalarFunc = false; - pParamElem->functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalarFunc); - if (pParamElem->functionId == FUNCTION_INVALID_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - - if (!scalarFunc) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - SArray* pExprList = getCurrentExprList(pQueryInfo); - size_t n = taosArrayGetSize(pExprList); - - // todo extract the table uid - pIndex->tableIndex = 0; - int32_t code = addScalarExprAndResColumn(pQueryInfo, n, pParamElem, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - SExprInfo** pLastExpr = taosArrayGetLast(pExprList); - *pNode = (*pLastExpr)->pExpr; - *(SSchema*) columnSchema = (*pLastExpr)->base.resSchema; - *pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - } else { - if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - // functions can not be applied to tags - if (TSDB_COL_IS_TAG(pIndex->type)) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - // 2. check if sql function can be applied on this column data type - *pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); - *columnSchema = *(SSchema*)getOneColumnSchema((*pTableMetaInfo)->pTableMeta, pIndex->columnIndex); - } - } else if (tokenId == TK_PLUS || tokenId == TK_MINUS || tokenId == TK_STAR || tokenId == TK_REM || tokenId == TK_DIVIDE || tokenId == TK_CONCAT) { - pIndex->tableIndex = 0; // todo set the correct table index - pIndex->type = TSDB_COL_TMP; // It is a temporary column generated by arithmetic expression. - - SArray* pExprList = getCurrentExprList(pQueryInfo); - size_t n = taosArrayGetSize(pExprList); - int32_t code = addScalarExprAndResColumn(pQueryInfo, n, pParamElem, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - SExprInfo** pLastExpr = taosArrayGetLast(getCurrentExprList(pQueryInfo)); - *pNode = (*pLastExpr)->pExpr; - *(SSchema*) columnSchema = (*pLastExpr)->base.resSchema; - *pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - } else { - assert(0); - } - - pQueryInfo->exprListLevelIndex -= 1; - return TSDB_CODE_SUCCESS; -} - -static int32_t checkForkParam(tSqlExpr* pSqlExpr, size_t k, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid parameters"; - - SArray* pParamList = pSqlExpr->Expr.paramList; - - if (k == 0) { - if (pParamList != NULL && taosArrayGetSize(pParamList) != 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } else if (k == 1) { - if (!(pParamList == NULL || taosArrayGetSize(pParamList) == k)) { - return buildInvalidOperationMsg(pMsgBuf, msg1);; - } - } else { - if (pParamList != NULL && taosArrayGetSize(pParamList) != k) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - return TSDB_CODE_SUCCESS; -} - -int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult, SMsgBuf* pMsgBuf) { - STableMetaInfo* pTableMetaInfo = NULL; - int32_t functionId = pItem->functionId; - int32_t code = TSDB_CODE_SUCCESS; - - const char* msg1 = "not support column types"; - const char* msg2 = "invalid parameters"; - const char* msg3 = "illegal column name"; - const char* msg4 = "invalid table name"; - const char* msg5 = "parameter is out of range [0, 100]"; - const char* msg6 = "functions applied to tags are not allowed"; - const char* msg7 = "normal table can not apply this function"; - const char* msg8 = "multi-columns selection does not support alias column name"; - const char* msg9 = "diff/derivative can no be applied to unsigned numeric type"; - const char* msg10 = "derivative duration should be greater than 1 Second"; - const char* msg11 = "third parameter in derivative should be 0 or 1"; - const char* msg12 = "parameter is out of range [1, 100]"; - const char* msg13 = "nested function is not supported"; - - if (checkForAliasName(pMsgBuf, pItem->aliasName) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - switch (functionId) { - case FUNCTION_COUNT: { - // more than one parameter for count() function - SArray* pParamList = pItem->pNode->Expr.paramList; - if ((code = checkForkParam(pItem->pNode, 1, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - - tExprNode* pNode = NULL; - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - SSchema columnSchema = {0}; - - code = setColumnIndex(pQueryInfo, pParamList, &index, &columnSchema, &pNode, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - int32_t size = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - SSchema s = createSchema(TSDB_DATA_TYPE_BIGINT, size, getNewResColId(), ""); - - char token[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, s.name, token,sizeof(s.name) - 1); - - pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &columnSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, pNode, &c); - - int32_t outputIndex = getNumOfFields(&pQueryInfo->fieldsInfo); - - char fname[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - extractFunctionName(fname, pItem); - doAddOneExprInfo(pQueryInfo, fname, ¶m, outputIndex, pTableMetaInfo, &s, size, token, finalResult); - return TSDB_CODE_SUCCESS; - } - - case FUNCTION_SUM: - case FUNCTION_AVG: - case FUNCTION_RATE: - case FUNCTION_IRATE: - case FUNCTION_TWA: - case FUNCTION_MIN: - case FUNCTION_MAX: - case FUNCTION_DIFF: - case FUNCTION_DERIVATIVE: - case FUNCTION_STDDEV: - case FUNCTION_LEASTSQR: { - // 1. valid the number of parameters - int32_t numOfParams = (pItem->pNode->Expr.paramList == NULL)? 0: (int32_t) taosArrayGetSize(pItem->pNode->Expr.paramList); - - // no parameters or more than one parameter for function - if (pItem->pNode->Expr.paramList == NULL || - (functionId != FUNCTION_LEASTSQR && functionId != FUNCTION_DERIVATIVE && numOfParams != 1) || - ((functionId == FUNCTION_LEASTSQR || functionId == FUNCTION_DERIVATIVE) && numOfParams != 3)) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0); - - tExprNode* pNode = NULL; - int32_t tokenId = pParamElem->pNode->tokenId; - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - SSchema columnSchema = {0}; - code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem, pMsgBuf); - - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - if (tokenId == TK_ALL || tokenId == TK_ID) { - if (!IS_NUMERIC_TYPE(columnSchema.type)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } else if (IS_UNSIGNED_NUMERIC_TYPE(columnSchema.type) && (functionId == FUNCTION_DIFF || functionId == FUNCTION_DERIVATIVE)) { - return buildInvalidOperationMsg(pMsgBuf, msg9); - } - } - - int32_t precision = pTableMetaInfo->pTableMeta->tableInfo.precision; - - SResultDataInfo resInfo = {0}; - if (getResultDataInfo(columnSchema.type, columnSchema.bytes, functionId, 0, &resInfo, 0, false) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // set the first column ts for diff query - int32_t numOfOutput = getNumOfFields(&pQueryInfo->fieldsInfo); - if (functionId == FUNCTION_DIFF || functionId == FUNCTION_DERIVATIVE) { - setTsOutputExprInfo(pQueryInfo, pTableMetaInfo, numOfOutput, index.tableIndex); - numOfOutput += 1; - } - - SSchema s = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), "ts"); - - char token[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &columnSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, pNode, &c); - - char funcName[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - extractFunctionName(funcName, pItem); - - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, funcName, ¶m, numOfOutput, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); - if (functionId == FUNCTION_LEASTSQR) { // set the leastsquares parameters - char val[8] = {0}; - if (taosVariantDump(&pParamElem[1].pNode->value, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - addExprInfoParam(&pExpr->base, val, TSDB_DATA_TYPE_DOUBLE, DOUBLE_BYTES); - - memset(val, 0, tListLen(val)); - if (taosVariantDump(&pParamElem[2].pNode->value, val, TSDB_DATA_TYPE_DOUBLE, true) < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - addExprInfoParam(&pExpr->base, val, TSDB_DATA_TYPE_DOUBLE, DOUBLE_BYTES); - } else if (functionId == FUNCTION_IRATE) { - addExprInfoParam(&pExpr->base, (char*) &precision, TSDB_DATA_TYPE_BIGINT, LONG_BYTES); - } else if (functionId == FUNCTION_DERIVATIVE) { - char val[8] = {0}; - - int64_t tickPerSec = 0; - code = getTickPerSecond(&pParamElem[1].pNode->value, precision, &tickPerSec, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - addExprInfoParam(&pExpr->base, (char*) &tickPerSec, TSDB_DATA_TYPE_BIGINT, LONG_BYTES); - memset(val, 0, tListLen(val)); - - if (taosVariantDump(&pParamElem[2].pNode->value, val, TSDB_DATA_TYPE_BIGINT, true) < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (GET_INT64_VAL(val) != 0 && GET_INT64_VAL(val) != 1) { - return buildInvalidOperationMsg(pMsgBuf, msg11); - } - - addExprInfoParam(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, LONG_BYTES); - } - return TSDB_CODE_SUCCESS; - } - - case FUNCTION_FIRST: - case FUNCTION_LAST: - case FUNCTION_SPREAD: - case FUNCTION_LAST_ROW: - case FUNCTION_INTERP: { - bool requireAllFields = (pItem->pNode->Expr.paramList == NULL); - - if (!requireAllFields) { - SArray* pParamList = pItem->pNode->Expr.paramList; - if (taosArrayGetSize(pParamList) < 1) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - if (taosArrayGetSize(pParamList) > 1 && (pItem->aliasName != NULL)) { - return buildInvalidOperationMsg(pMsgBuf, msg8); - } - - // in first/last function, multiple columns can be add to resultset - for (int32_t i = 0; i < taosArrayGetSize(pParamList); ++i) { - tSqlExprItem* pParamElem = taosArrayGet(pParamList, i); - doHandleOneParam(pQueryInfo, pItem, pParamElem, functionId, &colIndex, finalResult, pMsgBuf); - } - } else { // select function(*) from xxx - int32_t numOfFields = 0; - - // multicolumn selection does not support alias name - if (pItem->aliasName != NULL && strlen(pItem->aliasName) > 0) { - return buildInvalidOperationMsg(pMsgBuf, msg8); - } - - for (int32_t j = 0; j < pQueryInfo->numOfTables; ++j) { - pTableMetaInfo = getMetaInfo(pQueryInfo, j); - doAddAllColumnExprInSelectClause(pQueryInfo, pTableMetaInfo, pItem, functionId, j, &colIndex, finalResult, pMsgBuf); - numOfFields += getNumOfColumns(pTableMetaInfo->pTableMeta); - } - } - return TSDB_CODE_SUCCESS; - } - - case FUNCTION_TOP: - case FUNCTION_BOTTOM: - case FUNCTION_PERCT: - case FUNCTION_APERCT: { - // 1. valid the number of parameters - // no parameters or more than one parameter for function - if ((code = checkForkParam(pItem->pNode, 2, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - - tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0); - if (pParamElem->pNode->tokenId == TK_ALL) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - tExprNode* pNode = NULL; - int32_t tokenId = pParamElem->pNode->tokenId; - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - SSchema columnSchema = {0}; - code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem,pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - // functions can not be applied to tags - if (TSDB_COL_IS_TAG(index.type)) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - - // 2. valid the column type - if (!IS_NUMERIC_TYPE(columnSchema.type)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - // 3. valid the parameters - if (pParamElem[1].pNode->tokenId == TK_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - SResultDataInfo resInfo = {0}; - getResultDataInfo(columnSchema.type, columnSchema.bytes, functionId, 0, &resInfo, 0, false); - if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM) { - // set the first column ts for top/bottom query - setTsOutputExprInfo(pQueryInfo, pTableMetaInfo, colIndex, index.tableIndex); - colIndex += 1; // the first column is ts - } - - SSchema s = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), ""); - - char token[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &columnSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, pNode, &c); - - char funcName[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - extractFunctionName(funcName, pItem); - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, funcName, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); - - SToken* pParamToken = &pParamElem[1].pNode->exprToken; - pExpr->base.numOfParams += 1; - - SVariant* pVar = &pExpr->base.param[0]; - if (functionId == FUNCTION_PERCT || functionId == FUNCTION_APERCT) { - taosVariantCreate(pVar, pParamToken->z, pParamToken->n, TSDB_DATA_TYPE_DOUBLE); - - /* - * sql function transformation - * for dp = 0, it is actually min, - * for dp = 100, it is max, - */ - if (pVar->d < 0 || pVar->d > TOP_BOTTOM_QUERY_LIMIT) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - } else { - taosVariantCreate(pVar, pParamToken->z, pParamToken->n, TSDB_DATA_TYPE_BIGINT); - if (pVar->i <= 0 || pVar->i > 100) { // todo use macro - return buildInvalidOperationMsg(pMsgBuf, msg12); - } - } - - return TSDB_CODE_SUCCESS; - } - - case FUNCTION_TID_TAG: { - pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - - // no parameters or more than one parameter for function - if ((code = checkForkParam(pItem->pNode, 1, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - - tSqlExprItem* pParamItem = taosArrayGet(pItem->pNode->Expr.paramList, 0); - tSqlExpr* pParam = pParamItem->pNode; - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(&pParam->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - SSchema* pSchema = getTableTagSchema(pTableMetaInfo->pTableMeta); - - // functions can not be applied to normal columns - int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta); - if (index.columnIndex < numOfCols && index.columnIndex != TSDB_TBNAME_COLUMN_INDEX) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - if (index.columnIndex > 0) { - index.columnIndex -= numOfCols; - } - - // 2. valid the column type - int16_t colType = 0; - if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - colType = TSDB_DATA_TYPE_BINARY; - } else { - colType = pSchema[index.columnIndex].type; - } - - if (colType == TSDB_DATA_TYPE_BOOL) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - columnListInsert(pTableMetaInfo->tagColList, pTableMetaInfo->pTableMeta->uid, &pSchema[index.columnIndex], TSDB_COL_TAG); - SSchema* pTagSchema = getTableTagSchema(pTableMetaInfo->pTableMeta); - - SSchema s = (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX)? *getTbnameColumnSchema(): pTagSchema[index.columnIndex]; - - SResultDataInfo resInfo = {0}; - int32_t ret = getResultDataInfo(s.type, s.bytes, FUNCTION_TID_TAG, 0, &resInfo, 0, 0); - assert(ret == TSDB_CODE_SUCCESS); - - SSchema result = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), s.name); - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &result); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &c); - - /*SExprInfo* pExpr = */doAddOneExprInfo(pQueryInfo, "tbid", ¶m, 0, pTableMetaInfo, &result, 0, s.name, true); - return TSDB_CODE_SUCCESS; - } - - case FUNCTION_BLKINFO: { - // no parameters or more than one parameter for function - if ((code = checkForkParam(pItem->pNode, 0, pMsgBuf))!= TSDB_CODE_SUCCESS) { - return code; - } - - SColumnIndex index = {.tableIndex = 0, .columnIndex = 0, .type = TSDB_COL_NORMAL}; - pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - - SResultDataInfo resInfo = {0}; - getResultDataInfo(TSDB_DATA_TYPE_INT, 4, functionId, 0, &resInfo, 0, 0); - - SSchema s = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), "block_dist"); - SSchema colSchema = {0}; - - char token[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &colSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &c); - - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, "block_dist", ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); - - int64_t rowSize = pTableMetaInfo->pTableMeta->tableInfo.rowSize; - addExprInfoParam(&pExpr->base, (char*) &rowSize, TSDB_DATA_TYPE_BIGINT, 8); - return TSDB_CODE_SUCCESS; - } - - case FUNCTION_COV: { - // 1. valid the number of parameters - // no parameters or more than one parameter for function - if ((code = checkForkParam(pItem->pNode, 2, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - - tSqlExprItem* p1 = taosArrayGet(pItem->pNode->Expr.paramList, 0); - tSqlExprItem* p2 = taosArrayGet(pItem->pNode->Expr.paramList, 1); - - int32_t p1Type = p1->pNode->tokenId, p2Type = p2->pNode->tokenId; - if (p1Type != TK_ID || p2Type != TK_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - // validate the first parameter - tExprNode* pNode1 = NULL; - int32_t tokenId1 = p1->pNode->tokenId; - SColumnIndex index1 = COLUMN_INDEX_INITIALIZER; - SSchema columnSchema1 = {0}; - - code = extractFunctionParameterInfo(pQueryInfo, tokenId1, &pTableMetaInfo, &columnSchema1, &pNode1, &index1, p1, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - // validate the second parameter - tExprNode* pNode2 = NULL; - int32_t tokenId2 = p1->pNode->tokenId; - SColumnIndex index2 = COLUMN_INDEX_INITIALIZER; - SSchema columnSchema2 = {0}; - code = extractFunctionParameterInfo(pQueryInfo, tokenId2, &pTableMetaInfo, &columnSchema2, &pNode2, &index2, p1, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - int32_t srcType1 = columnSchema1.type, srcType2 = columnSchema2.type; - if (IS_VAR_DATA_TYPE(srcType1) || IS_VAR_DATA_TYPE(columnSchema2.type) || srcType1 == TSDB_DATA_TYPE_TIMESTAMP || - srcType1 == TSDB_DATA_TYPE_BOOL || srcType2 == TSDB_DATA_TYPE_TIMESTAMP || srcType2 == TSDB_DATA_TYPE_BOOL) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - SResultDataInfo resInfo = {.type = TSDB_DATA_TYPE_DOUBLE, .bytes = sizeof(double), .intermediateBytes = 0}; - SSchema s = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), ""); - - char token[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - - SColumn c1 = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index1.type, &columnSchema1); - SColumn c2 = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index2.type, &columnSchema2); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, pNode1, &c1); - addIntoSourceParam(¶m, pNode2, &c2); - - char funcName[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - extractFunctionName(funcName, pItem); - - doAddOneExprInfo(pQueryInfo, funcName, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); - return TSDB_CODE_SUCCESS; - } - - default: { -// pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n); -// if (pUdfInfo == NULL) { -// return buildInvalidOperationMsg(pMsgBuf, msg9); -// } - - tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0);; - if (pParamElem->pNode->tokenId != TK_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - - // functions can not be applied to tags - if (index.columnIndex >= getNumOfColumns(pTableMetaInfo->pTableMeta)) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - SResultDataInfo resInfo = {0}; - getResultDataInfo(TSDB_DATA_TYPE_INT, 4, functionId, 0, &resInfo, 0, false/*, pUdfInfo*/); - - SSchema s = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), ""); - SSchema* colSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, index.tableIndex); - - char token[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, colSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &c); - - char funcName[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - extractFunctionName(funcName, pItem); - doAddOneExprInfo(pQueryInfo, funcName, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); - return TSDB_CODE_SUCCESS; - } - } - - return TSDB_CODE_TSC_INVALID_OPERATION; -} - -static int32_t validateExprLeafColumnNode(SQueryStmtInfo *pQueryInfo, SToken* pColumnName, SArray* pList, SMsgBuf* pMsgBuf) { - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(pColumnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // if column is timestamp not support arithmetic, so return invalid sql - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - - SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); - if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - SColumn c = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); - taosArrayPush(pList, &c); - - return TSDB_CODE_SUCCESS; -} - -static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SMsgBuf* pMsgBuf) { - tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL}; - - // sql function list in selection clause. - // Append the sqlExpr into exprList of pQueryInfo structure sequentially - bool scalar = false; - item.functionId = qIsBuiltinFunction(pExpr->Expr.operand.z, pExpr->Expr.operand.n, &scalar); - if (item.functionId < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo); - - if (scalar) { - printf("scalar function found!\n"); -// if (addScalarExprAndResColumn(pQueryInfo, outputIndex, &item, pMsgBuf) != TSDB_CODE_SUCCESS) { -// return TSDB_CODE_TSC_INVALID_OPERATION; -// } - } else { - if (addAggExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k) - int32_t inc = (int32_t)getNumOfExprs(pQueryInfo) - outputIndex; - if (inc > 1) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // Not supported data type in expression - for (int32_t i = 0; i < inc; ++i) { - SExprInfo* p1 = getExprInfo(pQueryInfo, i + outputIndex); - int16_t t = p1->base.resSchema.type; - if (t == TSDB_DATA_TYPE_TIMESTAMP) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t validateScalarFunctionParamNum(tSqlExpr* pSqlExpr, int32_t functionId, SMsgBuf* pMsgBuf) { - int32_t code = TSDB_CODE_SUCCESS; - switch (functionId) { - case FUNCTION_CEIL: { - code = checkForkParam(pSqlExpr, 1, pMsgBuf); - break; - } - case FUNCTION_LENGTH: { - code = checkForkParam(pSqlExpr, 1, pMsgBuf); - break; - } - } - - return code; -} - -// todo merge with the addScalarExprAndResColumn -int32_t doAddOneProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, SSchema* pSchema, const char* aliasName, - int32_t colId, SMsgBuf* pMsgBuf) { - const char* name = (aliasName == NULL)? pSchema->name:aliasName; - SSchema s = createSchema(pSchema->type, pSchema->bytes, colId, name); - - SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); - SToken colNameToken = {.z = pSchema->name, .n = strlen(pSchema->name)}; - - tSqlExpr sqlNode = {0}; - sqlNode.type = SQL_NODE_TABLE_COLUMN; - sqlNode.columnName = colNameToken; - - tExprNode* pNode = NULL; - bool keepTableCols = true; - int32_t ret = sqlExprToExprNode(&pNode, &sqlNode, pQueryInfo, pColumnList, &keepTableCols, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - tExprTreeDestroy(pNode, NULL); - return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); - } - - SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); - tstrncpy(pExpr->base.resSchema.name, name, tListLen(pExpr->base.resSchema.name)); - tstrncpy(pExpr->base.token, name, tListLen(pExpr->base.token)); - - SArray* pExprList = getCurrentExprList(pQueryInfo); - addExprInfo(pExprList, outputColIndex, pExpr, pQueryInfo->exprListLevelIndex); - - // extract columns according to the tExprNode tree - size_t num = taosArrayGetSize(pColumnList); - pExpr->base.pColumns = calloc(num, sizeof(SColumn)); - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGet(pColumnList, i); - pExpr->base.pColumns[i] = *pCol; - } - - pExpr->base.numOfCols = num; - - if (pQueryInfo->exprListLevelIndex == 0) { - int32_t exists = getNumOfFields(&pQueryInfo->fieldsInfo); - addResColumnInfo(pQueryInfo, exists, &pExpr->base.resSchema, pExpr); - } - - pQueryInfo->info.projectionQuery = true; - - taosArrayDestroy(pColumnList); - return TSDB_CODE_SUCCESS; -} - -static int32_t doAddMultipleProjectExprAndResColumns(SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, int32_t startPos, SMsgBuf* pMsgBuf) { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); - - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - STableComInfo tinfo = getTableInfo(pTableMeta); - - int32_t numOfTotalColumns = tinfo.numOfColumns; - if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { - numOfTotalColumns += tinfo.numOfTags; - } - - for (int32_t j = 0; j < numOfTotalColumns; ++j) { - SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, j); - doAddOneProjectCol(pQueryInfo, startPos + j, pSchema, NULL, getNewResColId(), pMsgBuf); - } - - return numOfTotalColumns; -} - -// User input constant value as a new result column -static SColumnIndex createConstantColumnIndex(int32_t* colId) { - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - index.columnIndex = ((*colId)--); - index.tableIndex = 0; - index.type = TSDB_COL_UDC; - return index; -} - -static SSchema createConstantColumnSchema(SVariant* pVal, const SToken* exprStr, const char* name) { - SSchema s = {0}; - - s.type = pVal->nType; - if (IS_VAR_DATA_TYPE(s.type)) { - s.bytes = (int16_t)(pVal->nLen + VARSTR_HEADER_SIZE); - } else { - s.bytes = tDataTypes[pVal->nType].bytes; - } - - s.colId = TSDB_UD_COLUMN_INDEX; - - if (name != NULL) { - tstrncpy(s.name, name, sizeof(s.name)); - } else { - size_t tlen = TMIN(sizeof(s.name), exprStr->n + 1); - tstrncpy(s.name, exprStr->z, tlen); - strdequote(s.name); - } - - return s; -} - -static int32_t handleTbnameProjection(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, SColumnIndex* pIndex, int32_t startPos, bool outerQuery, SMsgBuf* pMsgBuf) { - const char* msg1 = "tbname not allowed in outer query"; - - SSchema colSchema = {0}; - if (outerQuery) { // todo?? - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); - - bool existed = false; - SSchema* pSchema = pTableMetaInfo->pTableMeta->schema; - - int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta); - for (int32_t i = 0; i < numOfCols; ++i) { - if (strncasecmp(pSchema[i].name, TSQL_TBNAME_L, tListLen(pSchema[i].name)) == 0) { - existed = true; - pIndex->columnIndex = i; - break; - } - } - - if (!existed) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - colSchema = pSchema[pIndex->columnIndex]; - } else { - colSchema = *getTbnameColumnSchema(); - } - - return doAddOneProjectCol(pQueryInfo, startPos, &colSchema, pItem->aliasName, getNewResColId(), pMsgBuf); -} - -int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, bool outerQuery, SMsgBuf* pMsgBuf) { - const char* msg1 = "tag for normal table query is not allowed"; - const char* msg2 = "invalid column name"; - - if (checkForAliasName(pMsgBuf, pItem->aliasName) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - int32_t startPos = (int32_t)getNumOfExprs(pQueryInfo); - int32_t tokenId = pItem->pNode->tokenId; - if (tokenId == TK_ALL) { // project on all fields - TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY); - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getTableIndexByName(&pItem->pNode->columnName, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - // all columns are required - if (index.tableIndex == COLUMN_INDEX_INITIAL_VAL) { // all table columns are required. - for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { - index.tableIndex = i; - int32_t inc = doAddMultipleProjectExprAndResColumns(pQueryInfo, &index, startPos, pMsgBuf); - startPos += inc; - } - } else { - doAddMultipleProjectExprAndResColumns(pQueryInfo, &index, startPos, pMsgBuf); - } - - // add the primary timestamp column even though it is not required by user - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, index.tableIndex)->pTableMeta; - if (pTableMeta->tableType != TSDB_TEMP_TABLE) { - insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->schema[0].name, pTableMeta->uid); - } - } else if (tokenId == TK_STRING || tokenId == TK_INTEGER || tokenId == TK_FLOAT) { //constant value column - SColumnIndex index = createConstantColumnIndex(&pQueryInfo->udColumnId); - SSchema colSchema = createConstantColumnSchema(&pItem->pNode->value, &pItem->pNode->exprToken, pItem->aliasName); - - char token[TSDB_COL_NAME_LEN] = {0}; - tstrncpy(token, pItem->pNode->exprToken.z, TMIN(TSDB_COL_NAME_LEN, TSDB_COL_NAME_LEN)); - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &colSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &c); - - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, "project", ¶m, startPos, pTableMetaInfo, &colSchema, 0, token, true); - // NOTE: the first parameter is reserved for the tag column id during join query process. - pExpr->base.numOfParams = 2; - taosVariantAssign(&pExpr->base.param[1], &pItem->pNode->value); - } else if (tokenId == TK_ID) { // column name - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(&pItem->pNode->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - handleTbnameProjection(pQueryInfo, pItem, &index, startPos, outerQuery, pMsgBuf); - } else { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - if (TSDB_COL_IS_TAG(index.type) && UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); - doAddOneProjectCol(pQueryInfo, startPos, pSchema, pItem->aliasName, getNewResColId(), pMsgBuf); - } - - // add the primary timestamp column even though it is not required by user - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - if (!UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo)) { - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->schema[0].name, pTableMeta->uid); - } - } else { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pList, int32_t* type, SMsgBuf* pMsgBuf) { - if (pExpr->type == SQL_NODE_TABLE_COLUMN) { - if (*type == NON_ARITHMEIC_EXPR) { - *type = NORMAL_ARITHMETIC; - } else if (*type == AGG_ARIGHTMEIC) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - int32_t code = validateExprLeafColumnNode(pQueryInfo, &pExpr->columnName, pList, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else if ((pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.d) || isinf(pExpr->value.d))) || - pExpr->tokenId == TK_NULL) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } else if (pExpr->type == SQL_NODE_SQLFUNCTION) { - if (*type == NON_ARITHMEIC_EXPR) { - *type = AGG_ARIGHTMEIC; - } else if (*type == NORMAL_ARITHMETIC) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - int32_t code = validateExprLeafFunctionNode(pQueryInfo, pExpr, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - return TSDB_CODE_SUCCESS; -} - -static uint64_t findTmpSourceColumnInNextLevel(SQueryStmtInfo* pQueryInfo, tExprNode *pExpr) { - // This function must be a aggregate function, so it must be in the next level - pQueryInfo->exprListLevelIndex += 1; - - // set the input column data byte and type. - SArray* pExprList = getCurrentExprList(pQueryInfo); - - bool found = false; - uint64_t uid = 0; - - size_t size = taosArrayGetSize(pExprList); - for (int32_t i = 0; i < size; ++i) { - SExprInfo* p1 = taosArrayGetP(pExprList, i); - - if (strcmp((pExpr)->pSchema->name, p1->base.resSchema.name) == 0) { - memcpy((pExpr)->pSchema, &p1->base.resSchema, sizeof(SSchema)); - found = true; - uid = p1->base.pColumns->uid; - break; - } - } - - assert(found); - pQueryInfo->exprListLevelIndex -= 1; - - return uid; -} - -static tExprNode* doCreateColumnNode(SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, bool keepTableCols, SArray* pCols) { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - - tExprNode* pExpr = calloc(1, sizeof(tExprNode)); - - pExpr->nodeType = TEXPR_COL_NODE; - pExpr->pSchema = calloc(1, sizeof(SSchema)); - - SSchema* pSchema = NULL; - if (pIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - pSchema = getTbnameColumnSchema(); - } else { - pSchema = getOneColumnSchema(pTableMeta, pIndex->columnIndex); - } - - *(SSchema*)(pExpr->pSchema) = *pSchema; - - if (keepTableCols && TSDB_COL_IS_NORMAL_COL(pIndex->type)) { - SColumn c = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, pIndex->type, pExpr->pSchema); - taosArrayPush(pCols, &c); - } - - if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) { - columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL); - SSchema* pTsSchema = getOneColumnSchema(pTableMeta, 0); - insertPrimaryTsColumn(pQueryInfo->colList, pTsSchema->name, pTableMeta->uid); - } else { - columnListInsert(pTableMetaInfo->tagColList, pTableMeta->uid, pSchema, TSDB_COL_TAG); - } - - return pExpr; -} - -static SExprInfo* createColumnNodeFromAggFunc(SSchema* pSchema) { - tExprNode* pExprNode = calloc(1, sizeof(tExprNode)); - - pExprNode->nodeType = TEXPR_COL_NODE; - pExprNode->pSchema = calloc(1, sizeof(SSchema)); - *(SSchema*)(pExprNode->pSchema) = *pSchema; - - SExprInfo* pExpr = calloc(1, sizeof(SExprInfo)); - if (pExpr == NULL) { - return NULL; - } - - pExpr->pExpr = pExprNode; - memcpy(&pExpr->base.resSchema, pSchema, sizeof(SSchema)); - return pExpr; -} - -static int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SMsgBuf* pMsgBuf); - -static int32_t doProcessFunctionLeafNodeParam(SQueryStmtInfo* pQueryInfo, int32_t* num, tExprNode*** p, SArray* pCols, - bool* keepTableCols, const tSqlExpr* pSqlExpr, SMsgBuf* pMsgBuf) { - SArray* pParamList = pSqlExpr->Expr.paramList; - if (pParamList != NULL) { - *num = taosArrayGetSize(pParamList); - (*p) = calloc((*num), POINTER_BYTES); - - for (int32_t i = 0; i < (*num); ++i) { - tSqlExprItem* pItem = taosArrayGet(pParamList, i); - - int32_t ret = validateSqlExpr(pItem->pNode, pQueryInfo, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - - int32_t code = sqlExprToExprNode(&(*p)[i], pItem->pNode, pQueryInfo, pCols, keepTableCols, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - } else { // handle the case: count(*) + 22 - if (strncasecmp(pSqlExpr->Expr.operand.z, "count", pSqlExpr->Expr.operand.n) != 0) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression"); - } - - *num = 1; - (*p) = calloc(*num, POINTER_BYTES); - - SColumnIndex index = {.type = TSDB_COL_NORMAL, .tableIndex = 0, .columnIndex = 0}; - (*p)[0] = doCreateColumnNode(pQueryInfo, &index, *keepTableCols, pCols); - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t doValidateExpr(SQueryStmtInfo *pQueryInfo, tSqlExpr* pFuncNode, tSqlExpr* pTableColumnNode, SMsgBuf* pMsgBuf) { - char token[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - strncpy(token, pFuncNode->Expr.operand.z, pFuncNode->Expr.operand.n); - bool isAgg = qIsAggregateFunction(token); - - // count(*) + column is a invalid expression. - if (isAgg) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression"); - } - return TSDB_CODE_SUCCESS; -} - -int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SMsgBuf* pMsgBuf) { - assert(pSqlExpr); - - if (pSqlExpr->type == SQL_NODE_EXPR) { - int32_t valid = validateSqlExpr(pSqlExpr->pLeft, pQueryInfo, pMsgBuf); - if (valid != TSDB_CODE_SUCCESS) { - return valid; - } - - valid = validateSqlExpr(pSqlExpr->pRight, pQueryInfo, pMsgBuf); - if (valid != TSDB_CODE_SUCCESS) { - return valid; - } - - tSqlExpr* pLeft = pSqlExpr->pLeft, *pRight = pSqlExpr->pRight; - if (pLeft->type == SQL_NODE_SQLFUNCTION && pRight->type == SQL_NODE_SQLFUNCTION) { - - char token[FUNCTIONS_NAME_MAX_LENGTH] = {0}; - strncpy(token, pLeft->Expr.operand.z, pLeft->Expr.operand.n); - bool agg1 = qIsAggregateFunction(token); - - strncpy(token, pRight->Expr.operand.z, pRight->Expr.operand.n); - bool agg2 = qIsAggregateFunction(token); - - if (agg1 != agg2) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression"); - } - } - - if (pLeft->type == SQL_NODE_SQLFUNCTION && pRight->type == SQL_NODE_TABLE_COLUMN) { - int32_t code = doValidateExpr(pQueryInfo, pLeft, pRight, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else if (pRight->type == SQL_NODE_SQLFUNCTION && pLeft->type == SQL_NODE_TABLE_COLUMN) { - int32_t code = doValidateExpr(pQueryInfo, pRight, pLeft, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - int32_t tokenId = pSqlExpr->tokenId; - if (pRight->type == SQL_NODE_VALUE && (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE || pRight->value.nType == TSDB_DATA_TYPE_INT) && - pRight->value.d == 0 && tokenId == TK_DIVIDE) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression (divided by 0)"); - } - - if (tokenId == TK_DIVIDE || tokenId == TK_TIMES || tokenId == TK_MINUS || tokenId == TK_PLUS || tokenId == TK_MODULES) { - if ((pRight->type == SQL_NODE_VALUE && pRight->value.nType == TSDB_DATA_TYPE_BINARY) || - (pLeft->type == SQL_NODE_VALUE && pLeft->value.nType == TSDB_DATA_TYPE_BINARY)) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expression (string in arithmetic expression)"); - } - } - - } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - - int32_t ret = getColumnIndexByName(&pSqlExpr->columnName, pQueryInfo, &index, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { - bool scalar = false; - int32_t functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalar); - if (functionId < 0) { - return buildInvalidOperationMsg(pMsgBuf, "invalid function name"); - } - - // do check the parameter number for scalar function - if (scalar) { - int32_t ret = validateScalarFunctionParamNum((tSqlExpr*) pSqlExpr, functionId, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, "invalid number of function parameters"); - } - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, bool* keepTableCols, SMsgBuf* pMsgBuf) { - tExprNode* pLeft = NULL; - tExprNode* pRight= NULL; - - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (pSqlExpr->type == SQL_NODE_EXPR) { - if (pSqlExpr->pLeft != NULL) { - int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, keepTableCols, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - } - - if (pSqlExpr->pRight != NULL) { - int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, keepTableCols, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - tExprTreeDestroy(pLeft, NULL); - return ret; - } - } - - if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) { - *pExpr = calloc(1, sizeof(tExprNode)); - return TSDB_CODE_SUCCESS; - } - } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { - bool scalar = false; - int32_t functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalar); - if (functionId < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (!scalar) { - pQueryInfo->exprListLevelIndex += 1; - } - - *keepTableCols = false; - - int32_t num = 0; - tExprNode** p = NULL; - int32_t code = doProcessFunctionLeafNodeParam(pQueryInfo, &num, &p, pCols, keepTableCols, pSqlExpr, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo); - - if (scalar) { - printf("scalar function found! %s\n", pSqlExpr->exprToken.z); - - // Expression on the results of aggregation functions - *pExpr = calloc(1, sizeof(tExprNode)); - (*pExpr)->nodeType = TEXPR_FUNCTION_NODE; - - (*pExpr)->_function.pChild = p; - (*pExpr)->_function.num = num; - strncpy((*pExpr)->_function.functionName, pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n); - return TSDB_CODE_SUCCESS; - } else { - printf("agg function found, %s\n", pSqlExpr->exprToken.z); - tSqlExprItem item = {.pNode = (tSqlExpr*)pSqlExpr, .aliasName = NULL, .functionId = functionId}; - if (addAggExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - pQueryInfo->exprListLevelIndex -= 1; - // convert the aggregate function to be the input data columns for the outer function. - } - } - - if (pSqlExpr->pLeft == NULL) { // it is the leaf node - assert(pSqlExpr->pRight == NULL); - - if (pSqlExpr->type == SQL_NODE_VALUE) { - int32_t ret = TSDB_CODE_SUCCESS; - *pExpr = calloc(1, sizeof(tExprNode)); - (*pExpr)->nodeType = TEXPR_VALUE_NODE; - (*pExpr)->pVal = calloc(1, sizeof(SVariant)); - taosVariantAssign((*pExpr)->pVal, &pSqlExpr->value); - - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, 0)->pTableMeta; - if (pCols != NULL && taosArrayGetSize(pCols) > 0) { - SColIndex* idx = taosArrayGet(pCols, 0); - SSchema* pSchema = getOneColumnSchema(pTableMeta, idx->colIndex); - - // convert time by precision - if (pSchema != NULL && TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && TSDB_DATA_TYPE_BINARY == (*pExpr)->pVal->nType) { -#if 0 - ret = setColumnFilterInfoForTimestamp(pCmd, pQueryInfo, (*pExpr)->pVal); -#endif - } - } - return ret; - } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { - // Expression on the results of aggregation functions - *pExpr = calloc(1, sizeof(tExprNode)); - (*pExpr)->nodeType = TEXPR_COL_NODE; - (*pExpr)->pSchema = calloc(1, sizeof(SSchema)); - strncpy((*pExpr)->pSchema->name, pSqlExpr->exprToken.z, pSqlExpr->exprToken.n); - - // it must be the aggregate function - assert(qIsAggregateFunction((*pExpr)->pSchema->name)); - - uint64_t uid = findTmpSourceColumnInNextLevel(pQueryInfo, *pExpr); - if (!(*keepTableCols)) { - SColumn c = createColumn(uid, NULL, TSDB_COL_TMP, (*pExpr)->pSchema); - taosArrayPush(pCols, &c); - } - } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column expression - int32_t ret = getColumnIndexByName(&pSqlExpr->columnName, pQueryInfo, &index, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - - *pExpr = doCreateColumnNode(pQueryInfo, &index, *keepTableCols, pCols); - return TSDB_CODE_SUCCESS; - } else if (pSqlExpr->tokenId == TK_SET) { - int32_t colType = -1; - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, pQueryInfo->curTableIdx)->pTableMeta; - if (pCols != NULL) { - size_t colSize = taosArrayGetSize(pCols); - - if (colSize > 0) { - SColIndex* idx = taosArrayGet(pCols, colSize - 1); - SSchema* pSchema = getOneColumnSchema(pTableMeta, idx->colIndex); - if (pSchema != NULL) { - colType = pSchema->type; - } - } - } - - SVariant *pVal; - if (colType >= TSDB_DATA_TYPE_TINYINT && colType <= TSDB_DATA_TYPE_BIGINT) { - colType = TSDB_DATA_TYPE_BIGINT; - } else if (colType == TSDB_DATA_TYPE_FLOAT || colType == TSDB_DATA_TYPE_DOUBLE) { - colType = TSDB_DATA_TYPE_DOUBLE; - } - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pQueryInfo->curTableIdx); - STableComInfo tinfo = getTableInfo(pTableMetaInfo->pTableMeta); -#if 0 - if (serializeExprListToVariant(pSqlExpr->Expr.paramList, &pVal, colType, tinfo.precision) == false) { - return buildInvalidOperationMsg(pMsgBuf, "not support filter expression"); - } -#endif - *pExpr = calloc(1, sizeof(tExprNode)); - (*pExpr)->nodeType = TEXPR_VALUE_NODE; - (*pExpr)->pVal = pVal; - } else { - return buildInvalidOperationMsg(pMsgBuf, "not support filter expression"); - } - } else { - *pExpr = (tExprNode*)calloc(1, sizeof(tExprNode)); - (*pExpr)->nodeType = TEXPR_BINARYEXPR_NODE; - - (*pExpr)->_node.pLeft = pLeft; - (*pExpr)->_node.pRight = pRight; - - SToken t = {.type = pSqlExpr->tokenId}; - (*pExpr)->_node.optr = convertRelationalOperator(&t); - - assert((*pExpr)->_node.optr != 0); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t addScalarExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { - SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); - SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), ""); - - int32_t ret = validateSqlExpr(pItem->pNode, pQueryInfo, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - - tExprNode* pNode = NULL; - bool keepTableCols = true; - ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, pColumnList, &keepTableCols, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - tExprTreeDestroy(pNode, NULL); - return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); - } - - SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); - setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN); - - SArray* pExprList = getCurrentExprList(pQueryInfo); - addExprInfo(pExprList, exprIndex, pExpr, pQueryInfo->exprListLevelIndex); - - // extract columns according to the tExprNode tree - size_t num = taosArrayGetSize(pColumnList); - pExpr->base.pColumns = calloc(num, sizeof(SColumn)); - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGet(pColumnList, i); - pExpr->base.pColumns[i] = *pCol; - } - - pExpr->base.numOfCols = num; - - pExpr->base.numOfParams = 1; - SBufferWriter bw = tbufInitWriter(NULL, false); - // TRY(0) { - exprTreeToBinary(&bw, pExpr->pExpr); - // } CATCH(code) { - // tbufCloseWriter(&bw); - // UNUSED(code); - // TODO: other error handling - // } END_TRY - - SSqlExpr* pSqlExpr = &pExpr->base; - pSqlExpr->param[0].nLen = (int16_t)tbufTell(&bw); - pSqlExpr->param[0].pz = tbufGetData(&bw, true); - pSqlExpr->param[0].nType = TSDB_DATA_TYPE_BINARY; - - tbufCloseWriter(&bw); - - if (pQueryInfo->exprListLevelIndex == 0) { - int32_t exists = getNumOfFields(&pQueryInfo->fieldsInfo); - addResColumnInfo(pQueryInfo, exists, &pExpr->base.resSchema, pExpr); - } - - // tbufCloseWriter(&bw); // TODO there is a memory leak - - taosArrayDestroy(pColumnList); - return TSDB_CODE_SUCCESS; -} - -int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, bool outerQuery, SMsgBuf* pMsgBuf) { - assert(pSelNodeList != NULL); - - const char* msg1 = "too many items in selection clause"; - const char* msg2 = "functions or others can not be mixed up"; - const char* msg3 = "not support query expression"; - const char* msg4 = "distinct should be in the first place in select clause"; - const char* msg5 = "invalid function name"; - - // too many result columns not support order by in query - if (taosArrayGetSize(pSelNodeList) > TSDB_MAX_COLUMNS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - int32_t code = TSDB_CODE_SUCCESS; - size_t numOfExpr = taosArrayGetSize(pSelNodeList); - - for (int32_t i = 0; i < numOfExpr; ++i) { - int32_t outputIndex = (int32_t) getNumOfExprs(pQueryInfo); - tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i); - int32_t type = pItem->pNode->type; - - if (pItem->distinct) { - if (i != 0 || type == SQL_NODE_SQLFUNCTION || type == SQL_NODE_EXPR) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - pQueryInfo->info.distinct = true; - } - - if (type == SQL_NODE_SQLFUNCTION) { - bool scalarFunc = false; - pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &scalarFunc); - if (pItem->functionId == FUNCTION_INVALID_ID) { // temporarily disable the udf -// int32_t functionId = FUNCTION_INVALID_ID; -// bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId); -// if (!valid) { - return buildInvalidOperationMsg(pMsgBuf, msg5); -// } - -// pItem->functionId = functionId; - } - - if (scalarFunc) { // scalar function - if ((code = addScalarExprAndResColumn(pQueryInfo, outputIndex, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - } else { // aggregate function - // sql function in selection clause, append sql function info in pSqlCmd structure sequentially - if ((code = addAggExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - } - } else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) { - // use the dynamic array list to decide if the function is valid or not - // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2 - if ((code = addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - } else if (type == SQL_NODE_EXPR) { - if ((code = addScalarExprAndResColumn(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } - } else { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, SMsgBuf* pMsgBuf) { - assert(pNode != NULL && pMsgBuf != NULL && pMsgBuf->len > 0); - - // Evaluate expression in where clause - if (pNode->pWhere != NULL) { - int32_t code = evaluateSqlNodeImpl(pNode->pWhere, tsPrecision); - if (code != TSDB_CODE_SUCCESS) { - strncpy(pMsgBuf->buf, "invalid time expression in sql", pMsgBuf->len); - return code; - } - } - - // Evaluate the expression in select clause - size_t size = taosArrayGetSize(pNode->pSelNodeList); - for(int32_t i = 0; i < size; ++i) { - tSqlExprItem* pItem = taosArrayGet(pNode->pSelNodeList, i); - int32_t code = evaluateSqlNodeImpl(pItem->pNode, tsPrecision); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - return TSDB_CODE_SUCCESS; -} - -//TODO remove it -int32_t setTableVgroupList(SParseContext *pCtx, SName* name, SVgroupsInfo **pVgList) { - SArray* vgroupList = NULL; - int32_t code = catalogGetTableDistVgInfo(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, name, &vgroupList); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - size_t vgroupNum = taosArrayGetSize(vgroupList); - - SVgroupsInfo *vgList = calloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo) * vgroupNum); - vgList->numOfVgroups = vgroupNum; - - for (int32_t i = 0; i < vgroupNum; ++i) { - SVgroupInfo *vg = taosArrayGet(vgroupList, i); - vgList->vgroups[i] = *vg; - } - - *pVgList = vgList; - taosArrayDestroy(vgroupList); - - return TSDB_CODE_SUCCESS; -} - -int32_t qParserValidateSqlNode(SParseContext *pCtx, SSqlInfo* pInfo, SQueryStmtInfo* pQueryInfo, char* msgBuf, int32_t msgBufLen) { - assert(pCtx != NULL && pInfo != NULL); - int32_t code = 0; - - SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; - SMsgBuf* pMsgBuf = &m; - - switch (pInfo->type) { -#if 0 - case TSDB_SQL_DROP_TABLE: - case TSDB_SQL_DROP_USER: - case TSDB_SQL_DROP_ACCT: - case TSDB_SQL_DROP_DNODE: - case TSDB_SQL_DROP_DB: { - const char* msg1 = "param name too long"; - const char* msg2 = "invalid name"; - - SToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0); - if ((pInfo->type != TSDB_SQL_DROP_DNODE) && (parserValidateIdToken(pzName) != TSDB_CODE_SUCCESS)) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - if (pInfo->type == TSDB_SQL_DROP_DB) { - assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1); - code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - } else if (pInfo->type == TSDB_SQL_DROP_TABLE) { - assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1); - - code = tscSetTableFullName(&pTableMetaInfo->name, pzName, pSql); - if(code != TSDB_CODE_SUCCESS) { - return code; - } - } else if (pInfo->type == TSDB_SQL_DROP_DNODE) { - if (pzName->type == TK_STRING) { - pzName->n = strdequote(pzName->z); - } - strncpy(pCmd->payload, pzName->z, pzName->n); - } else { // drop user/account - if (pzName->n >= TSDB_USER_LEN) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - strncpy(pCmd->payload, pzName->z, pzName->n); - } - - break; - } - - case TSDB_SQL_RESET_CACHE: { - return TSDB_CODE_SUCCESS; - } - - case TSDB_SQL_CREATE_FUNCTION: - case TSDB_SQL_DROP_FUNCTION: { - code = handleUserDefinedFunc(pSql, pInfo); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - break; - } - - case TSDB_SQL_DESCRIBE_TABLE: { - const char* msg1 = "invalid table name"; - - SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); - if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - // additional msg has been attached already - code = tscSetTableFullName(&pTableMetaInfo->name, pToken, pSql); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - return tscGetTableMeta(pSql, pTableMetaInfo); - } - case TSDB_SQL_SHOW_CREATE_STABLE: - case TSDB_SQL_SHOW_CREATE_TABLE: { - const char* msg1 = "invalid table name"; - - SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); - if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - code = tscSetTableFullName(&pTableMetaInfo->name, pToken, pSql); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - return tscGetTableMeta(pSql, pTableMetaInfo); - } - case TSDB_SQL_SHOW_CREATE_DATABASE: { - const char* msg1 = "invalid database name"; - - SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); - if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (pToken->n > TSDB_DB_NAME_LEN) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - return tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pToken); - } - case TSDB_SQL_CFG_DNODE: { - const char* msg2 = "invalid configure options or values, such as resetlog / debugFlag 135 / balance 'vnode:2-dnode:2' / monitor 1 "; - const char* msg3 = "invalid dnode ep"; - - /* validate the ip address */ - SMiscInfo* pMiscInfo = pInfo->pMiscInfo; - - /* validate the parameter names and options */ - if (validateDNodeConfig(pMiscInfo) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - char* pMsg = pCmd->payload; - - SMCfgDnodeReq* pCfg = (SMCfgDnodeReq*)pMsg; - - SToken* t0 = taosArrayGet(pMiscInfo->a, 0); - SToken* t1 = taosArrayGet(pMiscInfo->a, 1); - - t0->n = strdequote(t0->z); - strncpy(pCfg->ep, t0->z, t0->n); - - if (validateEp(pCfg->ep) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - strncpy(pCfg->config, t1->z, t1->n); - - if (taosArrayGetSize(pMiscInfo->a) == 3) { - SToken* t2 = taosArrayGet(pMiscInfo->a, 2); - - pCfg->config[t1->n] = ' '; // add sep - strncpy(&pCfg->config[t1->n + 1], t2->z, t2->n); - } - - break; - } - - case TSDB_SQL_CFG_LOCAL: { - SMiscInfo *pMiscInfo = pInfo->pMiscInfo; - const char *msg = "invalid configure options or values"; - - // validate the parameter names and options - if (validateLocalConfig(pMiscInfo) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg); - } - - int32_t numOfToken = (int32_t) taosArrayGetSize(pMiscInfo->a); - assert(numOfToken >= 1 && numOfToken <= 2); - - SToken* t = taosArrayGet(pMiscInfo->a, 0); - strncpy(pCmd->payload, t->z, t->n); - if (numOfToken == 2) { - SToken* t1 = taosArrayGet(pMiscInfo->a, 1); - pCmd->payload[t->n] = ' '; // add sep - strncpy(&pCmd->payload[t->n + 1], t1->z, t1->n); - } - return TSDB_CODE_SUCCESS; - } - - case TSDB_SQL_SELECT: { - const char * msg1 = "no nested query supported in union clause"; - code = loadAllTableMeta(pSql, pInfo); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - pQueryInfo = tscGetQueryInfo(pCmd); - - size_t size = taosArrayGetSize(pInfo->list); - for (int32_t i = 0; i < size; ++i) { - SSqlNode* pSqlNode = taosArrayGetP(pInfo->list, i); - - tscTrace("0x%"PRIx64" start to parse the %dth subclause, total:%"PRIzu, pSql->self, i, size); - - if (size > 1 && pSqlNode->from && pSqlNode->from->type == SQL_FROM_NODE_SUBQUERY) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - -// normalizeSqlNode(pSqlNode); // normalize the column name in each function - if ((code = validateSqlNode(pSql, pSqlNode, pQueryInfo)) != TSDB_CODE_SUCCESS) { - return code; - } - - tscPrintSelNodeList(pSql, i); - - if ((i + 1) < size && pQueryInfo->sibling == NULL) { - if ((code = tscAddQueryInfo(pCmd)) != TSDB_CODE_SUCCESS) { - return code; - } - - SArray *pUdfInfo = NULL; - if (pQueryInfo->pUdfInfo) { - pUdfInfo = taosArrayDup(pQueryInfo->pUdfInfo); - } - - pQueryInfo = pCmd->active; - pQueryInfo->pUdfInfo = pUdfInfo; - pQueryInfo->udfCopy = true; - } - } - - if ((code = normalizeVarDataTypeLength(pCmd)) != TSDB_CODE_SUCCESS) { - return code; - } - - // set the command/global limit parameters from the first subclause to the sqlcmd object - pCmd->active = pCmd->pQueryInfo; - pCmd->command = pCmd->pQueryInfo->command; - - STableMetaInfo* pTableMetaInfo1 = getMetaInfo(pCmd->active, 0); - if (pTableMetaInfo1->pTableMeta != NULL) { - pSql->res.precision = tscGetTableInfo(pTableMetaInfo1->pTableMeta).precision; - } - - return TSDB_CODE_SUCCESS; // do not build query message here - } - - case TSDB_SQL_ALTER_TABLE: { - if ((code = setAlterTableInfo(pSql, pInfo)) != TSDB_CODE_SUCCESS) { - return code; - } - - break; - } - - case TSDB_SQL_KILL_QUERY: - case TSDB_SQL_KILL_STREAM: - case TSDB_SQL_KILL_CONNECTION: { - if ((code = setKillInfo(pSql, pInfo, pInfo->type)) != TSDB_CODE_SUCCESS) { - return code; - } - break; - } - - case TSDB_SQL_SYNC_DB_REPLICA: { - const char* msg1 = "invalid db name"; - SToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0); - - assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1); - code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - break; - } - case TSDB_SQL_COMPACT_VNODE:{ - const char* msg = "invalid compact"; - if (setCompactVnodeInfo(pSql, pInfo) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg); - } - break; - } - default: - return buildInvalidOperationMsg(pMsgBuf, "not support sql expression"); - } -#endif - } - - SCatalogReq req = {0}; - SMetaData data = {0}; - - // TODO: check if the qnode info has been cached already - req.qNodeRequired = true; - code = qParserExtractRequestedMetaInfo(pInfo, &req, pCtx, msgBuf, msgBufLen); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - // load the meta data from catalog -// code = catalogGetAllMeta(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &req, &data); - STableMeta* pmt = NULL; - - SName* name = taosArrayGet(req.pTableName, 0); - code = catalogGetTableMeta(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, name, &pmt); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - data.pTableMeta = taosArrayInit(1, POINTER_BYTES); - taosArrayPush(data.pTableMeta, &pmt); - - pQueryInfo->pTableMetaInfo = calloc(1, POINTER_BYTES); - pQueryInfo->pTableMetaInfo[0] = calloc(1, sizeof(STableMetaInfo)); - pQueryInfo->pTableMetaInfo[0]->pTableMeta = pmt; - pQueryInfo->pTableMetaInfo[0]->name = *name; - pQueryInfo->numOfTables = 1; - pQueryInfo->pTableMetaInfo[0]->tagColList = taosArrayInit(4, POINTER_BYTES); - strcpy(pQueryInfo->pTableMetaInfo[0]->aliasName, name->tname); - - code = setTableVgroupList(pCtx, name, &pQueryInfo->pTableMetaInfo[0]->vgroupList); - if (code != TSDB_CODE_SUCCESS) { - taosArrayDestroy(data.pTableMeta); - return code; - } - - // evaluate the sqlnode - STableMeta* pTableMeta = (STableMeta*) taosArrayGetP(data.pTableMeta, 0); - assert(pTableMeta != NULL); - - SMsgBuf buf = {.buf = msgBuf, .len = msgBufLen}; - - size_t len = taosArrayGetSize(pInfo->sub.node); - for(int32_t i = 0; i < len; ++i) { - SSqlNode* p = taosArrayGetP(pInfo->sub.node, i); - code = evaluateSqlNode(p, pTableMeta->tableInfo.precision, &buf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - for(int32_t i = 0; i < len; ++i) { - SSqlNode* p = taosArrayGetP(pInfo->sub.node, i); - validateSqlNode(p, pQueryInfo, &buf); - } - - taosArrayDestroy(data.pTableMeta); - taosArrayDestroy(req.pUdf); - taosArrayDestroy(req.pTableName); - - return code; -} diff --git a/source/libs/parser/src/dCDAstProcess.c b/source/libs/parser/src/dCDAstProcess.c deleted file mode 100644 index 7ec2d05d4448255b4277c2a8d11b1f9bc2251a1b..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/dCDAstProcess.c +++ /dev/null @@ -1,905 +0,0 @@ -#include "tmsg.h" -#include "tglobal.h" -#include "parserInt.h" -#include "ttime.h" -#include "astToMsg.h" -#include "astGenerator.h" -#include "parserUtil.h" -#include "queryInfoUtil.h" - -/* is contained in pFieldList or not */ -static bool has(SArray* pFieldList, int32_t startIndex, const char* name) { - size_t numOfCols = taosArrayGetSize(pFieldList); - for (int32_t j = startIndex; j < numOfCols; ++j) { - TAOS_FIELD* field = taosArrayGet(pFieldList, j); - if (strncasecmp(name, field->name, sizeof(field->name) - 1) == 0) return true; - } - - return false; -} - -static int32_t setShowInfo(SShowInfo* pShowInfo, SParseContext* pCtx, void** output, int32_t* outputLen, - SEpSet* pEpSet, void** pExtension, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid name"; - const char* msg2 = "wildcard string should be less than %d characters"; - const char* msg3 = "database name too long"; - const char* msg4 = "pattern is invalid"; - const char* msg5 = "database name is empty"; - const char* msg6 = "pattern string is empty"; - const char* msg7 = "database not specified"; - /* - * database prefix in pInfo->pMiscInfo->a[0] - * wildcard in like clause in pInfo->pMiscInfo->a[1] - */ - int16_t showType = pShowInfo->showType; - if (showType == TSDB_MGMT_TABLE_TABLE) { - SArray* array = NULL; - SName name = {0}; - - if (pCtx->db == NULL && pShowInfo->prefix.n == 0) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - - SVShowTablesReq* pShowReq = calloc(1, sizeof(SVShowTablesReq)); - if (pShowInfo->prefix.n > 0) { - tNameSetDbName(&name, pCtx->acctId, pShowInfo->prefix.z, pShowInfo->prefix.n); - } else { - tNameSetDbName(&name, pCtx->acctId, pCtx->db, strlen(pCtx->db)); - } - - char dbFname[TSDB_DB_FNAME_LEN] = {0}; - tNameGetFullDbName(&name, dbFname); - - int32_t code = catalogGetDBVgInfo(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, dbFname, false, &array); - if (code != TSDB_CODE_SUCCESS) { - terrno = code; - return code; - } - - SVgroupInfo* info = taosArrayGet(array, 0); - pShowReq->head.vgId = htonl(info->vgId); - *pEpSet = info->epSet; - - *outputLen = sizeof(SVShowTablesReq); - *output = pShowReq; - *pExtension = array; - } else { - if (showType == TSDB_MGMT_TABLE_STB || showType == TSDB_MGMT_TABLE_VGROUP) { - SToken* pDbPrefixToken = &pShowInfo->prefix; - if (pDbPrefixToken->type != 0) { - if (pDbPrefixToken->n >= TSDB_DB_NAME_LEN) { // db name is too long - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - if (pDbPrefixToken->n <= 0) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - if (parserValidateIdToken(pDbPrefixToken) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - // int32_t ret = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pRequest->pTsc), pDbPrefixToken); - // if (ret != TSDB_CODE_SUCCESS) { - // return buildInvalidOperationMsg(pMsgBuf, msg1); - // } - } - - // show table/stable like 'xxxx', set the like pattern for show tables - SToken* pPattern = &pShowInfo->pattern; - if (pPattern->type != 0) { - if (pPattern->type == TK_ID && pPattern->z[0] == TS_ESCAPE_CHAR) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - pPattern->n = strdequote(pPattern->z); - if (pPattern->n <= 0) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - if (pPattern->n > tsMaxWildCardsLen) { - char tmp[64] = {0}; - sprintf(tmp, msg2, tsMaxWildCardsLen); - return buildInvalidOperationMsg(pMsgBuf, tmp); - } - } - } else if (showType == TSDB_MGMT_TABLE_VNODES) { - if (pShowInfo->prefix.type == 0) { - return buildInvalidOperationMsg(pMsgBuf, "No specified dnode ep"); - } - - if (pShowInfo->prefix.type == TK_STRING) { - pShowInfo->prefix.n = strdequote(pShowInfo->prefix.z); - } - } - - *pEpSet = pCtx->mgmtEpSet; - *output = buildShowMsg(pShowInfo, outputLen, pCtx, pMsgBuf); - if (*output == NULL) { - return terrno; - } - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t validateTableColumns(SArray* pFieldList, int32_t maxRowLength, int32_t maxColumns, SMsgBuf* pMsgBuf) { - const char* msg2 = "row length exceeds max length"; - const char* msg3 = "duplicated column names"; - const char* msg4 = "invalid data type"; - const char* msg5 = "invalid binary/nchar column length"; - const char* msg6 = "invalid column name"; - const char* msg7 = "too many columns"; - const char* msg8 = "illegal number of columns"; - - size_t numOfCols = taosArrayGetSize(pFieldList); - if (numOfCols > maxColumns) { - return buildInvalidOperationMsg(pMsgBuf, msg7); - } - - int32_t rowLen = 0; - for (int32_t i = 0; i < numOfCols; ++i) { - TAOS_FIELD* pField = taosArrayGet(pFieldList, i); - if (!isValidDataType(pField->type)) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - if (pField->bytes == 0) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - if ((pField->type == TSDB_DATA_TYPE_BINARY && (pField->bytes <= 0 || pField->bytes > TSDB_MAX_BINARY_LEN)) || - (pField->type == TSDB_DATA_TYPE_NCHAR && (pField->bytes <= 0 || pField->bytes > TSDB_MAX_NCHAR_LEN))) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } - - SToken nameToken = {.z = pField->name, .n = strlen(pField->name), .type = TK_ID}; - if (parserValidateNameToken(&nameToken) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg6); - } - - // field name must be unique - if (has(pFieldList, i + 1, pField->name) == true) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - rowLen += pField->bytes; - } - - // max row length must be less than TSDB_MAX_BYTES_PER_ROW - if (rowLen > maxRowLength) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t validateTableColumnInfo(SArray* pFieldList, SMsgBuf* pMsgBuf) { - assert(pFieldList != NULL && pMsgBuf != NULL); - - const char* msg1 = "first column must be timestamp"; - const char* msg2 = "illegal number of columns"; - - // first column must be timestamp - SField* pField = taosArrayGet(pFieldList, 0); - if (pField->type != TSDB_DATA_TYPE_TIMESTAMP) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - // number of fields no less than 2 - size_t numOfCols = taosArrayGetSize(pFieldList); - if (numOfCols <= 1) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - return validateTableColumns(pFieldList, TSDB_MAX_BYTES_PER_ROW, TSDB_MAX_COLUMNS, pMsgBuf); -} - -static int32_t validateTagParams(SArray* pTagsList, SArray* pFieldList, SMsgBuf* pMsgBuf) { - assert(pTagsList != NULL); - - const char* msg1 = "invalid number of tag columns"; - const char* msg3 = "duplicated column names"; - - // number of fields at least 1 - size_t numOfTags = taosArrayGetSize(pTagsList); - if (numOfTags < 1) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - // field name must be unique - for (int32_t i = 0; i < numOfTags; ++i) { - SField* p = taosArrayGet(pTagsList, i); - if (has(pFieldList, 0, p->name) == true) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - } - - return validateTableColumns(pFieldList, TSDB_MAX_TAGS_LEN, TSDB_MAX_TAGS, pMsgBuf); -} - -int32_t doCheckForCreateTable(SCreateTableSql* pCreateTable, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid table name"; - - SArray* pFieldList = pCreateTable->colInfo.pColumns; - SArray* pTagList = pCreateTable->colInfo.pTagColumns; - assert(pFieldList != NULL); - - // if sql specifies db, use it, otherwise use default db - SToken* pNameToken = &(pCreateTable->name); - - if (parserValidateIdToken(pNameToken) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (validateTableColumnInfo(pFieldList, pMsgBuf) != TSDB_CODE_SUCCESS || - (pTagList != NULL && validateTagParams(pTagList, pFieldList, pMsgBuf) != TSDB_CODE_SUCCESS)) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - return TSDB_CODE_SUCCESS; -} - -typedef struct SVgroupTablesBatch { - SVCreateTbBatchReq req; - SVgroupInfo info; -} SVgroupTablesBatch; - -static SArray* doSerializeVgroupCreateTableInfo(SHashObj* pVgroupHashmap); - -static int32_t doParseSerializeTagValue(SSchema* pTagSchema, int32_t numOfInputTag, SKVRowBuilder* pKvRowBuilder, - SArray* pTagValList, int32_t tsPrecision, SMsgBuf* pMsgBuf) { - const char* msg1 = "illegal value or data overflow"; - int32_t code = TSDB_CODE_SUCCESS; - - for (int32_t i = 0; i < numOfInputTag; ++i) { - SSchema* pSchema = &pTagSchema[i]; - - char* endPtr = NULL; - char tmpTokenBuf[TSDB_MAX_TAGS_LEN] = {0}; - SKvParam param = {.builder = pKvRowBuilder, .schema = pSchema}; - - SToken* pItem = taosArrayGet(pTagValList, i); - if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP && pItem->z[0] == '\'') { - pItem->z += 1; - } - - code = parseValueToken(&endPtr, pItem, pSchema, tsPrecision, tmpTokenBuf, KvRowAppend, ¶m, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - return code; -} - -static void addCreateTbReqIntoVgroup(SHashObj* pVgroupHashmap, const SName* pTableName, SKVRow row, uint64_t suid, SVgroupInfo* pVgInfo) { - struct SVCreateTbReq req = {0}; - req.type = TD_CHILD_TABLE; - req.name = strdup(tNameGetTableName(pTableName)); - req.ctbCfg.suid = suid; - req.ctbCfg.pTag = row; - - SVgroupTablesBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId)); - if (pTableBatch == NULL) { - SVgroupTablesBatch tBatch = {0}; - tBatch.info = *pVgInfo; - - tBatch.req.pArray = taosArrayInit(4, sizeof(struct SVCreateTbReq)); - taosArrayPush(tBatch.req.pArray, &req); - - taosHashPut(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId), &tBatch, sizeof(tBatch)); - } else { // add to the correct vgroup - assert(pVgInfo->vgId == pTableBatch->info.vgId); - taosArrayPush(pTableBatch->req.pArray, &req); - } -} - -static void destroyCreateTbReqBatch(SVgroupTablesBatch* pTbBatch) { - size_t size = taosArrayGetSize(pTbBatch->req.pArray); - for(int32_t i = 0; i < size; ++i) { - SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i); - tfree(pTableReq->name); - - if (pTableReq->type == TSDB_NORMAL_TABLE) { - tfree(pTableReq->ntbCfg.pSchema); - } else if (pTableReq->type == TSDB_CHILD_TABLE) { - tfree(pTableReq->ctbCfg.pTag); - } else { - assert(0); - } - } - - taosArrayDestroy(pTbBatch->req.pArray); -} - -static int32_t doCheckAndBuildCreateCTableReq(SCreateTableSql* pCreateTable, SParseContext* pCtx, SMsgBuf* pMsgBuf, SArray** pBufArray) { - const char* msg1 = "invalid table name"; - const char* msg2 = "tags number not matched"; - const char* msg3 = "tag value too long"; - const char* msg4 = "illegal value or data overflow"; - - int32_t code = 0; - STableMeta* pSuperTableMeta = NULL; - - SHashObj* pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); - - // super table name, create table by using dst - size_t numOfTables = taosArrayGetSize(pCreateTable->childTableInfo); - for (int32_t j = 0; j < numOfTables; ++j) { - SCreatedTableInfo* pCreateTableInfo = taosArrayGet(pCreateTable->childTableInfo, j); - - SToken* pSTableNameToken = &pCreateTableInfo->stbName; - code = parserValidateNameToken(pSTableNameToken); - if (code != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg1); - goto _error; - } - - SName name = {0}; - code = createSName(&name, pSTableNameToken, pCtx, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - SKVRowBuilder kvRowBuilder = {0}; - if (tdInitKVRowBuilder(&kvRowBuilder) < 0) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - - SArray* pValList = pCreateTableInfo->pTagVals; - size_t numOfInputTag = taosArrayGetSize(pValList); - - code = catalogGetTableMeta(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &name, &pSuperTableMeta); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - assert(pSuperTableMeta != NULL); - - // too long tag values will return invalid sql, not be truncated automatically - SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta); - STableComInfo tinfo = getTableInfo(pSuperTableMeta); - - SArray* pNameList = NULL; - size_t numOfBoundTags = 0; - int32_t schemaSize = getNumOfTags(pSuperTableMeta); - - if (pCreateTableInfo->pTagNames) { - pNameList = pCreateTableInfo->pTagNames; - numOfBoundTags = taosArrayGetSize(pNameList); - - if (numOfInputTag != numOfBoundTags || schemaSize < numOfInputTag) { - tdDestroyKVRowBuilder(&kvRowBuilder); - code = buildInvalidOperationMsg(pMsgBuf, msg2); - goto _error; - } - - bool findColumnIndex = false; - for (int32_t i = 0; i < numOfBoundTags; ++i) { - SToken* sToken = taosArrayGet(pNameList, i); - - char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW] = {0}; // create tmp buf to avoid alter orginal sqlstr - strncpy(tmpTokenBuf, sToken->z, sToken->n); - sToken->z = tmpTokenBuf; - - // if (TK_STRING == sToken->type) { - // tscDequoteAndTrimToken(sToken); - // } - - // if (TK_ID == sToken->type) { - // tscRmEscapeAndTrimToken(sToken); - // } - - SListItem* pItem = taosArrayGet(pValList, i); - - findColumnIndex = false; - - // todo speedup by using hash list - for (int32_t t = 0; t < schemaSize; ++t) { - if (strncmp(sToken->z, pTagSchema[t].name, sToken->n) == 0 && strlen(pTagSchema[t].name) == sToken->n) { - SSchema* pSchema = &pTagSchema[t]; - - char tagVal[TSDB_MAX_TAGS_LEN] = {0}; - if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { - if (pItem->pVar.nLen > pSchema->bytes) { - tdDestroyKVRowBuilder(&kvRowBuilder); - code = buildInvalidOperationMsg(pMsgBuf, msg3); - goto _error; - } - } else if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) { - if (pItem->pVar.nType == TSDB_DATA_TYPE_BINARY) { - // code = convertTimestampStrToInt64(&(pItem->pVar), tinfo.precision); - // if (code != TSDB_CODE_SUCCESS) { - // return buildInvalidOperationMsg(pMsgBuf, msg4); - // } - } else if (pItem->pVar.nType == TSDB_DATA_TYPE_TIMESTAMP) { - pItem->pVar.i = convertTimePrecision(pItem->pVar.i, TSDB_TIME_PRECISION_NANO, tinfo.precision); - } - } - - code = taosVariantDump(&(pItem->pVar), tagVal, pSchema->type, true); - - // check again after the convert since it may be converted from binary to nchar. - if (IS_VAR_DATA_TYPE(pSchema->type)) { - int16_t len = varDataTLen(tagVal); - if (len > pSchema->bytes) { - tdDestroyKVRowBuilder(&kvRowBuilder); - code = buildInvalidOperationMsg(pMsgBuf, msg3); - goto _error; - } - } - - if (code != TSDB_CODE_SUCCESS) { - tdDestroyKVRowBuilder(&kvRowBuilder); - code = buildInvalidOperationMsg(pMsgBuf, msg4); - goto _error; - } - - tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal); - - findColumnIndex = true; - break; - } - } - - if (!findColumnIndex) { - tdDestroyKVRowBuilder(&kvRowBuilder); - // return buildInvalidOperationMsg(pMsgBuf, "invalid tag name", sToken->z); - } - } - } else { - if (schemaSize != numOfInputTag) { - tdDestroyKVRowBuilder(&kvRowBuilder); - code = buildInvalidOperationMsg(pMsgBuf, msg2); - goto _error; - } - - code = doParseSerializeTagValue(pTagSchema, numOfInputTag, &kvRowBuilder, pValList, tinfo.precision, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - tdDestroyKVRowBuilder(&kvRowBuilder); - goto _error; - } - } - - SKVRow row = tdGetKVRowFromBuilder(&kvRowBuilder); - tdDestroyKVRowBuilder(&kvRowBuilder); - if (row == NULL) { - code = TSDB_CODE_QRY_OUT_OF_MEMORY; - goto _error; - } - - tdSortKVRowByColIdx(row); - - SName tableName = {0}; - code = createSName(&tableName, &pCreateTableInfo->name, pCtx, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - // Find a appropriate vgroup to accommodate this table , according to the table name - SVgroupInfo info = {0}; - code = catalogGetTableHashVgroup(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &tableName, &info); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - addCreateTbReqIntoVgroup(pVgroupHashmap, &tableName, row, pSuperTableMeta->uid, &info); - tfree(pSuperTableMeta); - } - - *pBufArray = doSerializeVgroupCreateTableInfo(pVgroupHashmap); - if (*pBufArray == NULL) { - code = terrno; - goto _error; - } - - taosHashCleanup(pVgroupHashmap); - return TSDB_CODE_SUCCESS; - - _error: - taosHashCleanup(pVgroupHashmap); - tfree(pSuperTableMeta); - terrno = code; - return code; -} - -static int32_t serializeVgroupTablesBatchImpl(SVgroupTablesBatch* pTbBatch, SArray* pBufArray) { - int tlen = sizeof(SMsgHead) + tSerializeSVCreateTbBatchReq(NULL, &(pTbBatch->req)); - void* buf = malloc(tlen); - if (buf == NULL) { - // TODO: handle error - } - - ((SMsgHead*)buf)->vgId = htonl(pTbBatch->info.vgId); - ((SMsgHead*)buf)->contLen = htonl(tlen); - - void* pBuf = POINTER_SHIFT(buf, sizeof(SMsgHead)); - tSerializeSVCreateTbBatchReq(&pBuf, &(pTbBatch->req)); - - SVgDataBlocks* pVgData = calloc(1, sizeof(SVgDataBlocks)); - pVgData->vg = pTbBatch->info; - pVgData->pData = buf; - pVgData->size = tlen; - pVgData->numOfTables = (int32_t) taosArrayGetSize(pTbBatch->req.pArray); - - taosArrayPush(pBufArray, &pVgData); -} - -static int32_t doBuildSingleTableBatchReq(SName* pTableName, SArray* pColumns, SVgroupInfo* pVgroupInfo, SVgroupTablesBatch* pBatch) { - struct SVCreateTbReq req = {0}; - req.type = TD_NORMAL_TABLE; - req.name = strdup(tNameGetTableName(pTableName)); - - req.ntbCfg.nCols = taosArrayGetSize(pColumns); - int32_t num = req.ntbCfg.nCols; - - req.ntbCfg.pSchema = calloc(num, sizeof(SSchema)); - for(int32_t i = 0; i < num; ++i) { - SSchema* pSchema = taosArrayGet(pColumns, i); - memcpy(&req.ntbCfg.pSchema[i], pSchema, sizeof(SSchema)); - } - - pBatch->info = *pVgroupInfo; - pBatch->req.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq)); - if (pBatch->req.pArray == NULL) { - return TSDB_CODE_QRY_OUT_OF_MEMORY; - } - - taosArrayPush(pBatch->req.pArray, &req); - return TSDB_CODE_SUCCESS; -} - -int32_t doCheckAndBuildCreateTableReq(SCreateTableSql* pCreateTable, SParseContext* pCtx, SMsgBuf* pMsgBuf, char** pOutput, int32_t* len) { - SArray* pBufArray = NULL; - int32_t code = 0; - - // it is a sql statement to create a normal table - if (pCreateTable->childTableInfo == NULL) { - assert(taosArrayGetSize(pCreateTable->colInfo.pColumns) > 0 && pCreateTable->colInfo.pTagColumns == NULL); - code = doCheckForCreateTable(pCreateTable, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - SName tableName = {0}; - code = createSName(&tableName, &pCreateTable->name, pCtx, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - SVgroupInfo info = {0}; - catalogGetTableHashVgroup(pCtx->pCatalog, pCtx->pTransporter, &pCtx->mgmtEpSet, &tableName, &info); - - SVgroupTablesBatch tbatch = {0}; - code = doBuildSingleTableBatchReq(&tableName, pCreateTable->colInfo.pColumns, &info, &tbatch); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - pBufArray = taosArrayInit(1, POINTER_BYTES); - if (pBufArray == NULL) { - return TSDB_CODE_QRY_OUT_OF_MEMORY; - } - - serializeVgroupTablesBatchImpl(&tbatch, pBufArray); - destroyCreateTbReqBatch(&tbatch); - } else { // it is a child table, created according to a super table - code = doCheckAndBuildCreateCTableReq(pCreateTable, pCtx, pMsgBuf, &pBufArray); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - SVnodeModifOpStmtInfo* pStmtInfo = calloc(1, sizeof(SVnodeModifOpStmtInfo)); - pStmtInfo->nodeType = TSDB_SQL_CREATE_TABLE; - pStmtInfo->pDataBlocks = pBufArray; - - *pOutput = (char*) pStmtInfo; - *len = sizeof(SVnodeModifOpStmtInfo); - - return TSDB_CODE_SUCCESS; -} - -SArray* doSerializeVgroupCreateTableInfo(SHashObj* pVgroupHashmap) { - SArray* pBufArray = taosArrayInit(taosHashGetSize(pVgroupHashmap), sizeof(void*)); - - SVgroupTablesBatch* pTbBatch = NULL; - do { - pTbBatch = taosHashIterate(pVgroupHashmap, pTbBatch); - if (pTbBatch == NULL) { - break; - } - - /*int32_t code = */serializeVgroupTablesBatchImpl(pTbBatch, pBufArray); - destroyCreateTbReqBatch(pTbBatch); - } while (true); - - return pBufArray; -} - -SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen) { - int32_t code = 0; - - SDclStmtInfo* pDcl = calloc(1, sizeof(SDclStmtInfo)); - - SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; - SMsgBuf* pMsgBuf = &m; - - pDcl->epSet = pCtx->mgmtEpSet; - - switch (pInfo->type) { - case TSDB_SQL_CREATE_USER: - case TSDB_SQL_ALTER_USER: { - const char* msg1 = "not support options"; - const char* msg2 = "invalid user/account name"; - const char* msg3 = "name too long"; - const char* msg4 = "invalid user rights"; - - SUserInfo* pUser = &pInfo->pMiscInfo->user; - SToken* pName = &pUser->user; - SToken* pPwd = &pUser->passwd; - - if (pName->n >= TSDB_USER_LEN) { - code = buildInvalidOperationMsg(pMsgBuf, msg3); - goto _error; - } - - if (parserValidateIdToken(pName) != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg2); - goto _error; - } - - if (pInfo->type == TSDB_SQL_CREATE_USER) { - if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) { - code = TSDB_CODE_TSC_INVALID_OPERATION; - goto _error; - } - } else { - if (pUser->type == TSDB_ALTER_USER_PASSWD) { - if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) { - code = TSDB_CODE_TSC_INVALID_OPERATION; - goto _error; - } - } else if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) { - assert(pPwd->type == TSDB_DATA_TYPE_NULL); - - SToken* pPrivilege = &pUser->privilege; - if (strncasecmp(pPrivilege->z, "super", 5) == 0 && pPrivilege->n == 5) { - // pCmd->count = 1; - } else if (strncasecmp(pPrivilege->z, "normal", 4) == 0 && pPrivilege->n == 4) { - // pCmd->count = 2; - } else { - code = buildInvalidOperationMsg(pMsgBuf, msg4); - goto _error; - } - } else { - code = buildInvalidOperationMsg(pMsgBuf, msg1); - goto _error; - } - } - - pDcl->pMsg = (char*)buildUserManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen); - pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_USER) ? TDMT_MND_CREATE_USER : TDMT_MND_ALTER_USER; - break; - } - - case TSDB_SQL_CREATE_ACCT: - case TSDB_SQL_ALTER_ACCT: { - const char* msg1 = "invalid state option, available options[no, r, w, all]"; - const char* msg2 = "invalid user/account name"; - const char* msg3 = "name too long"; - - SToken* pName = &pInfo->pMiscInfo->user.user; - SToken* pPwd = &pInfo->pMiscInfo->user.passwd; - - if (parserValidatePassword(pPwd, pMsgBuf) != TSDB_CODE_SUCCESS) { - code = TSDB_CODE_TSC_INVALID_OPERATION; - goto _error; - } - - if (pName->n >= TSDB_USER_LEN) { - code = buildInvalidOperationMsg(pMsgBuf, msg3); - goto _error; - } - - if (parserValidateNameToken(pName) != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg2); - goto _error; - } - - SCreateAcctInfo* pAcctOpt = &pInfo->pMiscInfo->acctOpt; - if (pAcctOpt->stat.n > 0) { - if (pAcctOpt->stat.z[0] == 'r' && pAcctOpt->stat.n == 1) { - } else if (pAcctOpt->stat.z[0] == 'w' && pAcctOpt->stat.n == 1) { - } else if (strncmp(pAcctOpt->stat.z, "all", 3) == 0 && pAcctOpt->stat.n == 3) { - } else if (strncmp(pAcctOpt->stat.z, "no", 2) == 0 && pAcctOpt->stat.n == 2) { - } else { - code = buildInvalidOperationMsg(pMsgBuf, msg1); - goto _error; - } - } - - pDcl->pMsg = (char*)buildAcctManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen); - pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_ACCT) ? TDMT_MND_CREATE_ACCT : TDMT_MND_ALTER_ACCT; - break; - } - - case TSDB_SQL_DROP_ACCT: - case TSDB_SQL_DROP_USER: { - pDcl->pMsg = (char*)buildDropUserMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen); - pDcl->msgType = (pInfo->type == TSDB_SQL_DROP_ACCT) ? TDMT_MND_DROP_ACCT : TDMT_MND_DROP_USER; - break; - } - - case TSDB_SQL_SHOW: { - SShowInfo* pShowInfo = &pInfo->pMiscInfo->showOpt; - code = setShowInfo(pShowInfo, pCtx, (void**)&pDcl->pMsg, &pDcl->msgLen, &pDcl->epSet, &pDcl->pExtension, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - pDcl->msgType = (pShowInfo->showType == TSDB_MGMT_TABLE_TABLE) ? TDMT_VND_SHOW_TABLES : TDMT_MND_SHOW; - break; - } - - case TSDB_SQL_USE_DB: { - const char* msg = "invalid db name"; - - SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0); - if (parserValidateNameToken(pToken) != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg); - goto _error; - } - - SName n = {0}; - int32_t ret = tNameSetDbName(&n, pCtx->acctId, pToken->z, pToken->n); - if (ret != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg); - goto _error; - } - - SUseDbReq usedbReq = {0}; - tNameExtractFullName(&n, usedbReq.db); - catalogGetDBVgVersion(pCtx->pCatalog, usedbReq.db, &usedbReq.vgVersion, &usedbReq.dbId); - - int32_t bufLen = tSerializeSUseDbReq(NULL, 0, &usedbReq); - void* pBuf = malloc(bufLen); - tSerializeSUseDbReq(pBuf, bufLen, &usedbReq); - - pDcl->pMsg = pBuf; - pDcl->msgLen = bufLen; - pDcl->msgType = TDMT_MND_USE_DB; - break; - } - - case TSDB_SQL_ALTER_DB: - case TSDB_SQL_CREATE_DB: { - const char* msg1 = "invalid db name"; - const char* msg2 = "name too long"; - - SCreateDbInfo* pCreateDB = &(pInfo->pMiscInfo->dbOpt); - if (pCreateDB->dbname.n >= TSDB_DB_NAME_LEN) { - code = buildInvalidOperationMsg(pMsgBuf, msg2); - goto _error; - } - - char buf[TSDB_DB_NAME_LEN] = {0}; - SToken token = taosTokenDup(&pCreateDB->dbname, buf, tListLen(buf)); - - if (parserValidateNameToken(&token) != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg1); - goto _error; - } - - int32_t bufLen = 0; - char* pBuf = buildCreateDbMsg(pCreateDB, &bufLen, pCtx, pMsgBuf); - - pDcl->pMsg = pBuf; - pDcl->msgLen = bufLen; - pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_DB) ? TDMT_MND_CREATE_DB : TDMT_MND_ALTER_DB; - break; - } - - case TSDB_SQL_DROP_DB: { - const char* msg1 = "invalid database name"; - - assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1); - SToken* dbName = taosArrayGet(pInfo->pMiscInfo->a, 0); - - SName name = {0}; - code = tNameSetDbName(&name, pCtx->acctId, dbName->z, dbName->n); - if (code != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg1); - goto _error; - } - - SDropDbReq dropdbReq = {0}; - code = tNameExtractFullName(&name, dropdbReq.db); - dropdbReq.ignoreNotExists = pInfo->pMiscInfo->existsCheck ? 1 : 0; - assert(code == TSDB_CODE_SUCCESS && name.type == TSDB_DB_NAME_T); - - int32_t bufLen = tSerializeSDropDbReq(NULL, 0, &dropdbReq); - void* pBuf = malloc(bufLen); - tSerializeSDropDbReq(pBuf, bufLen, &dropdbReq); - - pDcl->msgType = TDMT_MND_DROP_DB; - pDcl->msgLen = bufLen; - pDcl->pMsg = pBuf; - break; - } - - case TSDB_SQL_CREATE_STABLE: { - SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo; - if ((code = doCheckForCreateTable(pCreateTable, pMsgBuf)) != TSDB_CODE_SUCCESS) { - terrno = code; - goto _error; - } - - pDcl->pMsg = buildCreateStbReq(pCreateTable, &pDcl->msgLen, pCtx, pMsgBuf); - pDcl->msgType = TDMT_MND_CREATE_STB; - break; - } - - case TSDB_SQL_DROP_TABLE: { - pDcl->pMsg = buildDropStableReq(pInfo, &pDcl->msgLen, pCtx, pMsgBuf); - if (pDcl->pMsg == NULL) { - goto _error; - } - - pDcl->msgType = TDMT_MND_DROP_STB; - break; - } - - case TSDB_SQL_CREATE_DNODE: { - pDcl->pMsg = (char*)buildCreateDnodeMsg(pInfo, &pDcl->msgLen, pMsgBuf); - if (pDcl->pMsg == NULL) { - goto _error; - } - - pDcl->msgType = TDMT_MND_CREATE_DNODE; - break; - } - - case TSDB_SQL_DROP_DNODE: { - pDcl->pMsg = (char*)buildDropDnodeMsg(pInfo, &pDcl->msgLen, pMsgBuf); - if (pDcl->pMsg == NULL) { - goto _error; - } - - pDcl->msgType = TDMT_MND_DROP_DNODE; - break; - } - - default: - break; - } - - return pDcl; - - _error: - terrno = code; - tfree(pDcl); - return NULL; -} - -SVnodeModifOpStmtInfo* qParserValidateCreateTbSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, char* msgBuf, int32_t msgBufLen) { - SCreateTableSql* pCreateTable = pInfo->pCreateTableInfo; - assert(pCreateTable->type == TSDB_SQL_CREATE_TABLE); - - SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; - SMsgBuf* pMsgBuf = &m; - - SVnodeModifOpStmtInfo* pModifSqlStmt = NULL; - - int32_t msgLen = 0; - int32_t code = doCheckAndBuildCreateTableReq(pCreateTable, pCtx, pMsgBuf, (char**) &pModifSqlStmt, &msgLen); - if (code != TSDB_CODE_SUCCESS) { - terrno = code; - tfree(pModifSqlStmt); - return NULL; - } - - return pModifSqlStmt; -} diff --git a/source/libs/parser/src/new_sql.c b/source/libs/parser/src/new_sql.c deleted file mode 100644 index 2d0c4b7eba73909cd878c7e3d06fb1e5a3c1d93a..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/new_sql.c +++ /dev/null @@ -1,2332 +0,0 @@ -/* -** 2000-05-29 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Driver template for the LEMON parser generator. -** -** The "lemon" program processes an LALR(1) input grammar file, then uses -** this template to construct a parser. The "lemon" program inserts text -** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the -** interstitial "-" characters) contained in this template is changed into -** the value of the %name directive from the grammar. Otherwise, the content -** of this template is copied straight through into the generate parser -** source file. -** -** The following is the concatenation of all %include directives from the -** input grammar file: -*/ -#include -#include -/************ Begin %include sections from the grammar ************************/ - -#include -#include -#include -#include -#include - -#include "nodes.h" -#include "ttoken.h" -#include "ttokendef.h" -#include "astCreateFuncs.h" - -#if 0 -#define PARSER_TRACE printf("lemon rule = %s\n", yyRuleName[yyruleno]) -#define PARSER_DESTRUCTOR_TRACE printf("lemon destroy token = %s\n", yyTokenName[yymajor]) -#define PARSER_COMPLETE printf("parsing complete!\n" ) -#else -#define PARSER_TRACE -#define PARSER_DESTRUCTOR_TRACE -#define PARSER_COMPLETE -#endif -/**************** End of %include directives **********************************/ -/* These constants specify the various numeric values for terminal symbols -** in a format understandable to "makeheaders". This section is blank unless -** "lemon" is run with the "-m" command-line option. -***************** Begin makeheaders token definitions *************************/ -/**************** End makeheaders token definitions ***************************/ - -/* The next sections is a series of control #defines. -** various aspects of the generated parser. -** YYCODETYPE is the data type used to store the integer codes -** that represent terminal and non-terminal symbols. -** "unsigned char" is used if there are fewer than -** 256 symbols. Larger types otherwise. -** YYNOCODE is a number of type YYCODETYPE that is not used for -** any terminal or nonterminal symbol. -** YYFALLBACK If defined, this indicates that one or more tokens -** (also known as: "terminal symbols") have fall-back -** values which should be used if the original symbol -** would not parse. This permits keywords to sometimes -** be used as identifiers, for example. -** YYACTIONTYPE is the data type used for "action codes" - numbers -** that indicate what to do in response to the next -** token. -** NewParseTOKENTYPE is the data type used for minor type for terminal -** symbols. Background: A "minor type" is a semantic -** value associated with a terminal or non-terminal -** symbols. For example, for an "ID" terminal symbol, -** the minor type might be the name of the identifier. -** Each non-terminal can have a different minor type. -** Terminal symbols all have the same minor type, though. -** This macros defines the minor type for terminal -** symbols. -** YYMINORTYPE is the data type used for all minor types. -** This is typically a union of many types, one of -** which is NewParseTOKENTYPE. The entry in the union -** for terminal symbols is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. If -** zero the stack is dynamically sized using realloc() -** NewParseARG_SDECL A static variable declaration for the %extra_argument -** NewParseARG_PDECL A parameter declaration for the %extra_argument -** NewParseARG_PARAM Code to pass %extra_argument as a subroutine parameter -** NewParseARG_STORE Code to store %extra_argument into yypParser -** NewParseARG_FETCH Code to extract %extra_argument from yypParser -** NewParseCTX_* As NewParseARG_ except for %extra_context -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. -** YYNSTATE the combined number of states. -** YYNRULE the number of rules in the grammar -** YYNTOKEN Number of terminal symbols -** YY_MAX_SHIFT Maximum value for shift actions -** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions -** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_ERROR_ACTION The yy_action[] code for syntax error -** YY_ACCEPT_ACTION The yy_action[] code for accept -** YY_NO_ACTION The yy_action[] code for no-op -** YY_MIN_REDUCE Minimum value for reduce actions -** YY_MAX_REDUCE Maximum value for reduce actions -*/ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/************* Begin control #defines *****************************************/ -#define YYCODETYPE unsigned char -#define YYNOCODE 126 -#define YYACTIONTYPE unsigned short int -#define NewParseTOKENTYPE SToken -typedef union { - int yyinit; - NewParseTOKENTYPE yy0; - EFillMode yy18; - SToken yy29; - EJoinType yy36; - SNode* yy56; - ENullOrder yy109; - EOperatorType yy128; - bool yy173; - SNodeList* yy208; - EOrder yy218; -} YYMINORTYPE; -#ifndef YYSTACKDEPTH -#define YYSTACKDEPTH 100 -#endif -#define NewParseARG_SDECL SAstCreateContext* pCxt ; -#define NewParseARG_PDECL , SAstCreateContext* pCxt -#define NewParseARG_PARAM ,pCxt -#define NewParseARG_FETCH SAstCreateContext* pCxt =yypParser->pCxt ; -#define NewParseARG_STORE yypParser->pCxt =pCxt ; -#define NewParseCTX_SDECL -#define NewParseCTX_PDECL -#define NewParseCTX_PARAM -#define NewParseCTX_FETCH -#define NewParseCTX_STORE -#define YYNSTATE 148 -#define YYNRULE 140 -#define YYNTOKEN 72 -#define YY_MAX_SHIFT 147 -#define YY_MIN_SHIFTREDUCE 245 -#define YY_MAX_SHIFTREDUCE 384 -#define YY_ERROR_ACTION 385 -#define YY_ACCEPT_ACTION 386 -#define YY_NO_ACTION 387 -#define YY_MIN_REDUCE 388 -#define YY_MAX_REDUCE 527 -/************* End control #defines *******************************************/ -#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) - -/* Define the yytestcase() macro to be a no-op if is not already defined -** otherwise. -** -** Applications can choose to define yytestcase() in the %include section -** to a macro that can assist in verifying code coverage. For production -** code the yytestcase() macro should be turned off. But it is useful -** for testing. -*/ -#ifndef yytestcase -# define yytestcase(X) -#endif - - -/* Next are the tables used to determine what action to take based on the -** current state and lookahead token. These tables are used to implement -** functions that take a state number and lookahead value and return an -** action integer. -** -** Suppose the action integer is N. Then the action is determined as -** follows -** -** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead -** token onto the stack and goto state N. -** -** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then -** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. -** -** N == YY_ERROR_ACTION A syntax error has occurred. -** -** N == YY_ACCEPT_ACTION The parser accepts its input. -** -** N == YY_NO_ACTION No such action. Denotes unused -** slots in the yy_action[] table. -** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE -** -** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as either: -** -** (A) N = yy_action[ yy_shift_ofst[S] + X ] -** (B) N = yy_default[S] -** -** The (A) formula is preferred. The B formula is used instead if -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X. -** -** The formulas above are for computing the action when the lookahead is -** a terminal symbol. If the lookahead is a non-terminal (as occurs after -** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array. -** -** The following are the tables generated in this section: -** -** yy_action[] A single table containing all actions. -** yy_lookahead[] A table containing the lookahead for each entry in -** yy_action. Used to detect hash collisions. -** yy_shift_ofst[] For each state, the offset into yy_action for -** shifting terminals. -** yy_reduce_ofst[] For each state, the offset into yy_action for -** shifting non-terminals after a reduce. -** yy_default[] Default action for each state. -** -*********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (750) -static const YYACTIONTYPE yy_action[] = { - /* 0 */ 397, 395, 93, 23, 72, 398, 395, 73, 30, 28, - /* 10 */ 26, 25, 24, 405, 395, 142, 420, 142, 420, 143, - /* 20 */ 110, 113, 80, 406, 267, 409, 22, 88, 97, 147, - /* 30 */ 285, 286, 287, 288, 289, 290, 291, 293, 294, 295, - /* 40 */ 30, 28, 26, 25, 24, 405, 395, 142, 420, 142, - /* 50 */ 420, 143, 118, 117, 46, 406, 260, 409, 22, 88, - /* 60 */ 97, 55, 285, 286, 287, 288, 289, 290, 291, 293, - /* 70 */ 294, 295, 132, 405, 395, 70, 65, 142, 420, 143, - /* 80 */ 127, 10, 39, 406, 55, 409, 445, 119, 114, 112, - /* 90 */ 87, 441, 334, 133, 519, 247, 248, 249, 250, 144, - /* 100 */ 253, 459, 506, 55, 258, 405, 395, 475, 261, 128, - /* 110 */ 420, 143, 127, 10, 40, 406, 54, 409, 445, 456, - /* 120 */ 504, 459, 95, 441, 49, 405, 395, 56, 135, 142, - /* 130 */ 420, 143, 383, 384, 81, 406, 71, 409, 20, 455, - /* 140 */ 405, 395, 103, 472, 128, 420, 143, 125, 292, 40, - /* 150 */ 406, 296, 409, 445, 29, 27, 421, 95, 441, 49, - /* 160 */ 75, 247, 248, 249, 250, 144, 253, 120, 102, 1, - /* 170 */ 459, 9, 8, 11, 26, 25, 24, 464, 473, 322, - /* 180 */ 405, 395, 386, 145, 142, 420, 143, 134, 454, 40, - /* 190 */ 406, 55, 409, 445, 303, 29, 27, 95, 441, 518, - /* 200 */ 2, 326, 247, 248, 249, 250, 144, 253, 479, 102, - /* 210 */ 1, 405, 395, 506, 11, 142, 420, 143, 6, 322, - /* 220 */ 40, 406, 261, 409, 445, 9, 8, 54, 95, 441, - /* 230 */ 518, 504, 405, 395, 506, 139, 142, 420, 143, 502, - /* 240 */ 111, 40, 406, 325, 409, 445, 486, 136, 505, 95, - /* 250 */ 441, 518, 504, 476, 29, 27, 327, 108, 124, 45, - /* 260 */ 463, 247, 248, 249, 250, 144, 253, 43, 102, 1, - /* 270 */ 57, 42, 351, 11, 348, 253, 126, 50, 452, 453, - /* 280 */ 140, 457, 132, 405, 395, 106, 107, 142, 420, 143, - /* 290 */ 137, 59, 79, 406, 62, 409, 29, 27, 109, 349, - /* 300 */ 350, 352, 353, 247, 248, 249, 250, 144, 253, 485, - /* 310 */ 102, 7, 506, 30, 28, 26, 25, 24, 31, 405, - /* 320 */ 395, 297, 94, 142, 420, 143, 54, 5, 41, 406, - /* 330 */ 504, 409, 445, 55, 61, 466, 444, 441, 405, 395, - /* 340 */ 121, 64, 142, 420, 143, 48, 105, 41, 406, 4, - /* 350 */ 409, 445, 130, 322, 282, 129, 441, 132, 66, 257, - /* 360 */ 31, 124, 45, 264, 29, 27, 131, 402, 44, 400, - /* 370 */ 43, 247, 248, 249, 250, 144, 253, 260, 102, 7, - /* 380 */ 68, 452, 123, 32, 122, 29, 27, 506, 460, 67, - /* 390 */ 16, 427, 247, 248, 249, 250, 144, 253, 521, 102, - /* 400 */ 1, 54, 98, 405, 395, 504, 141, 142, 420, 143, - /* 410 */ 138, 503, 41, 406, 258, 409, 445, 29, 27, 74, - /* 420 */ 3, 442, 14, 31, 247, 248, 249, 250, 144, 253, - /* 430 */ 58, 102, 7, 115, 345, 60, 405, 395, 35, 347, - /* 440 */ 142, 420, 143, 47, 63, 85, 406, 101, 409, 405, - /* 450 */ 395, 116, 341, 142, 420, 143, 36, 400, 85, 406, - /* 460 */ 104, 409, 405, 395, 340, 18, 142, 420, 143, 37, - /* 470 */ 69, 85, 406, 96, 409, 405, 395, 319, 15, 142, - /* 480 */ 420, 143, 318, 33, 46, 406, 34, 409, 405, 395, - /* 490 */ 8, 399, 142, 420, 143, 53, 283, 82, 406, 265, - /* 500 */ 409, 405, 395, 374, 17, 142, 420, 143, 12, 38, - /* 510 */ 77, 406, 369, 409, 368, 99, 405, 395, 373, 372, - /* 520 */ 142, 420, 143, 100, 520, 83, 406, 76, 409, 405, - /* 530 */ 395, 251, 13, 142, 420, 143, 389, 388, 78, 406, - /* 540 */ 146, 409, 405, 395, 387, 387, 142, 420, 143, 387, - /* 550 */ 387, 84, 406, 387, 409, 405, 395, 387, 387, 142, - /* 560 */ 420, 143, 387, 387, 417, 406, 387, 409, 405, 395, - /* 570 */ 387, 387, 142, 420, 143, 387, 387, 416, 406, 387, - /* 580 */ 409, 405, 395, 387, 387, 142, 420, 143, 387, 387, - /* 590 */ 415, 406, 387, 409, 387, 405, 395, 387, 387, 142, - /* 600 */ 420, 143, 387, 387, 91, 406, 387, 409, 405, 395, - /* 610 */ 387, 387, 142, 420, 143, 387, 387, 90, 406, 387, - /* 620 */ 409, 405, 395, 387, 387, 142, 420, 143, 387, 387, - /* 630 */ 92, 406, 387, 409, 405, 395, 387, 387, 142, 420, - /* 640 */ 143, 387, 387, 89, 406, 387, 409, 405, 395, 387, - /* 650 */ 387, 142, 420, 143, 387, 387, 86, 406, 387, 409, - /* 660 */ 124, 45, 387, 387, 387, 124, 45, 387, 387, 43, - /* 670 */ 387, 387, 387, 387, 43, 387, 387, 387, 387, 51, - /* 680 */ 452, 453, 387, 457, 52, 452, 453, 387, 457, 30, - /* 690 */ 28, 26, 25, 24, 19, 387, 387, 387, 387, 387, - /* 700 */ 30, 28, 26, 25, 24, 21, 387, 387, 387, 387, - /* 710 */ 387, 30, 28, 26, 25, 24, 387, 387, 387, 387, - /* 720 */ 30, 28, 26, 25, 24, 387, 387, 387, 387, 387, - /* 730 */ 387, 387, 387, 387, 387, 387, 267, 387, 387, 387, - /* 740 */ 387, 387, 387, 387, 387, 387, 387, 387, 380, 381, -}; -static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 74, 75, 76, 88, 89, 74, 75, 124, 8, 9, - /* 10 */ 10, 11, 12, 74, 75, 78, 79, 78, 79, 80, - /* 20 */ 115, 84, 83, 84, 24, 86, 26, 27, 28, 13, - /* 30 */ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - /* 40 */ 8, 9, 10, 11, 12, 74, 75, 78, 79, 78, - /* 50 */ 79, 80, 22, 84, 83, 84, 22, 86, 26, 27, - /* 60 */ 28, 45, 30, 31, 32, 33, 34, 35, 36, 37, - /* 70 */ 38, 39, 73, 74, 75, 41, 108, 78, 79, 80, - /* 80 */ 22, 23, 83, 84, 45, 86, 87, 50, 51, 52, - /* 90 */ 91, 92, 10, 122, 123, 15, 16, 17, 18, 19, - /* 100 */ 20, 81, 103, 45, 22, 74, 75, 82, 22, 78, - /* 110 */ 79, 80, 22, 23, 83, 84, 117, 86, 87, 99, - /* 120 */ 121, 81, 91, 92, 93, 74, 75, 41, 3, 78, - /* 130 */ 79, 80, 70, 71, 83, 84, 105, 86, 26, 99, - /* 140 */ 74, 75, 111, 112, 78, 79, 80, 101, 36, 83, - /* 150 */ 84, 39, 86, 87, 8, 9, 79, 91, 92, 93, - /* 160 */ 118, 15, 16, 17, 18, 19, 20, 116, 22, 23, - /* 170 */ 81, 1, 2, 27, 10, 11, 12, 42, 112, 44, - /* 180 */ 74, 75, 72, 73, 78, 79, 80, 62, 99, 83, - /* 190 */ 84, 45, 86, 87, 24, 8, 9, 91, 92, 93, - /* 200 */ 104, 4, 15, 16, 17, 18, 19, 20, 102, 22, - /* 210 */ 23, 74, 75, 103, 27, 78, 79, 80, 43, 44, - /* 220 */ 83, 84, 22, 86, 87, 1, 2, 117, 91, 92, - /* 230 */ 93, 121, 74, 75, 103, 21, 78, 79, 80, 102, - /* 240 */ 54, 83, 84, 46, 86, 87, 114, 21, 117, 91, - /* 250 */ 92, 93, 121, 82, 8, 9, 10, 53, 77, 78, - /* 260 */ 102, 15, 16, 17, 18, 19, 20, 86, 22, 23, - /* 270 */ 113, 21, 29, 27, 24, 20, 95, 96, 97, 98, - /* 280 */ 66, 100, 73, 74, 75, 75, 75, 78, 79, 80, - /* 290 */ 64, 21, 83, 84, 24, 86, 8, 9, 55, 56, - /* 300 */ 57, 58, 59, 15, 16, 17, 18, 19, 20, 114, - /* 310 */ 22, 23, 103, 8, 9, 10, 11, 12, 21, 74, - /* 320 */ 75, 24, 75, 78, 79, 80, 117, 61, 83, 84, - /* 330 */ 121, 86, 87, 45, 113, 110, 91, 92, 74, 75, - /* 340 */ 60, 109, 78, 79, 80, 107, 48, 83, 84, 47, - /* 350 */ 86, 87, 27, 44, 29, 91, 92, 73, 106, 22, - /* 360 */ 21, 77, 78, 24, 8, 9, 10, 23, 78, 25, - /* 370 */ 86, 15, 16, 17, 18, 19, 20, 22, 22, 23, - /* 380 */ 96, 97, 98, 40, 100, 8, 9, 103, 81, 94, - /* 390 */ 23, 90, 15, 16, 17, 18, 19, 20, 125, 22, - /* 400 */ 23, 117, 69, 74, 75, 121, 65, 78, 79, 80, - /* 410 */ 63, 120, 83, 84, 22, 86, 87, 8, 9, 119, - /* 420 */ 21, 92, 49, 21, 15, 16, 17, 18, 19, 20, - /* 430 */ 24, 22, 23, 15, 24, 23, 74, 75, 21, 24, - /* 440 */ 78, 79, 80, 23, 23, 83, 84, 85, 86, 74, - /* 450 */ 75, 21, 24, 78, 79, 80, 23, 25, 83, 84, - /* 460 */ 85, 86, 74, 75, 24, 21, 78, 79, 80, 23, - /* 470 */ 25, 83, 84, 85, 86, 74, 75, 24, 49, 78, - /* 480 */ 79, 80, 24, 42, 83, 84, 21, 86, 74, 75, - /* 490 */ 2, 25, 78, 79, 80, 25, 29, 83, 84, 24, - /* 500 */ 86, 74, 75, 24, 21, 78, 79, 80, 49, 4, - /* 510 */ 83, 84, 15, 86, 15, 15, 74, 75, 15, 15, - /* 520 */ 78, 79, 80, 15, 123, 83, 84, 25, 86, 74, - /* 530 */ 75, 17, 23, 78, 79, 80, 0, 0, 83, 84, - /* 540 */ 14, 86, 74, 75, 126, 126, 78, 79, 80, 126, - /* 550 */ 126, 83, 84, 126, 86, 74, 75, 126, 126, 78, - /* 560 */ 79, 80, 126, 126, 83, 84, 126, 86, 74, 75, - /* 570 */ 126, 126, 78, 79, 80, 126, 126, 83, 84, 126, - /* 580 */ 86, 74, 75, 126, 126, 78, 79, 80, 126, 126, - /* 590 */ 83, 84, 126, 86, 126, 74, 75, 126, 126, 78, - /* 600 */ 79, 80, 126, 126, 83, 84, 126, 86, 74, 75, - /* 610 */ 126, 126, 78, 79, 80, 126, 126, 83, 84, 126, - /* 620 */ 86, 74, 75, 126, 126, 78, 79, 80, 126, 126, - /* 630 */ 83, 84, 126, 86, 74, 75, 126, 126, 78, 79, - /* 640 */ 80, 126, 126, 83, 84, 126, 86, 74, 75, 126, - /* 650 */ 126, 78, 79, 80, 126, 126, 83, 84, 126, 86, - /* 660 */ 77, 78, 126, 126, 126, 77, 78, 126, 126, 86, - /* 670 */ 126, 126, 126, 126, 86, 126, 126, 126, 126, 96, - /* 680 */ 97, 98, 126, 100, 96, 97, 98, 126, 100, 8, - /* 690 */ 9, 10, 11, 12, 2, 126, 126, 126, 126, 126, - /* 700 */ 8, 9, 10, 11, 12, 2, 126, 126, 126, 126, - /* 710 */ 126, 8, 9, 10, 11, 12, 126, 126, 126, 126, - /* 720 */ 8, 9, 10, 11, 12, 126, 126, 126, 126, 126, - /* 730 */ 126, 126, 126, 126, 126, 126, 24, 126, 126, 126, - /* 740 */ 126, 126, 126, 126, 126, 126, 126, 126, 67, 68, - /* 750 */ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - /* 760 */ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - /* 770 */ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - /* 780 */ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - /* 790 */ 126, 126, 126, -}; -#define YY_SHIFT_COUNT (147) -#define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (712) -static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 16, 146, 246, 187, 187, 187, 187, 288, 187, 187, - /* 10 */ 58, 377, 409, 356, 409, 409, 409, 409, 409, 409, - /* 20 */ 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, - /* 30 */ 409, 409, 90, 90, 90, 80, 30, 30, 39, 0, - /* 40 */ 32, 32, 80, 34, 34, 34, 681, 243, 37, 86, - /* 50 */ 135, 175, 135, 82, 125, 197, 200, 186, 204, 255, - /* 60 */ 255, 186, 204, 255, 266, 280, 298, 302, 309, 337, - /* 70 */ 355, 343, 367, 333, 341, 347, 392, 692, 703, 712, - /* 80 */ 305, 305, 305, 305, 305, 305, 305, 170, 112, 164, - /* 90 */ 164, 164, 164, 250, 270, 224, 297, 325, 62, 226, - /* 100 */ 214, 339, 344, 399, 402, 373, 406, 410, 412, 417, - /* 110 */ 415, 420, 421, 428, 433, 440, 418, 430, 432, 446, - /* 120 */ 444, 429, 453, 458, 445, 441, 465, 466, 470, 488, - /* 130 */ 467, 475, 479, 483, 459, 505, 497, 499, 500, 503, - /* 140 */ 504, 508, 502, 509, 514, 536, 537, 526, -}; -#define YY_REDUCE_COUNT (76) -#define YY_REDUCE_MIN (-117) -#define YY_REDUCE_MAX (588) -static const short yy_reduce_ofst[] = { - /* 0 */ 110, -1, 31, 66, 106, 137, 158, 209, 245, 264, - /* 10 */ 284, 329, -29, 362, 375, 51, 388, 401, -61, 414, - /* 20 */ 427, 442, 455, 468, 481, 494, 507, 521, 534, 547, - /* 30 */ 560, 573, 181, 583, 588, -74, -63, -31, 131, -85, - /* 40 */ -85, -85, -69, 20, 40, 89, -117, -95, -32, 25, - /* 50 */ 46, 46, 46, 77, 42, 96, 171, 132, 157, 210, - /* 60 */ 211, 195, 221, 247, 225, 232, 238, 252, 46, 290, - /* 70 */ 307, 295, 301, 273, 291, 300, 77, -}; -static const YYACTIONTYPE yy_default[] = { - /* 0 */ 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - /* 10 */ 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - /* 20 */ 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - /* 30 */ 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, - /* 40 */ 447, 385, 385, 458, 458, 458, 522, 385, 482, 474, - /* 50 */ 450, 464, 451, 385, 507, 467, 385, 489, 487, 385, - /* 60 */ 385, 489, 487, 385, 501, 497, 480, 478, 464, 385, - /* 70 */ 385, 385, 385, 525, 513, 509, 385, 385, 385, 385, - /* 80 */ 500, 499, 424, 423, 422, 418, 419, 385, 385, 413, - /* 90 */ 414, 412, 411, 385, 385, 448, 385, 385, 385, 510, - /* 100 */ 514, 385, 401, 471, 481, 385, 385, 385, 385, 385, - /* 110 */ 385, 385, 385, 385, 385, 385, 385, 385, 401, 385, - /* 120 */ 498, 385, 457, 453, 385, 385, 449, 400, 385, 443, - /* 130 */ 385, 385, 385, 508, 385, 385, 385, 385, 385, 385, - /* 140 */ 385, 385, 385, 385, 385, 385, 385, 385, -}; -/********** End of lemon-generated parsing tables *****************************/ - -/* The next table maps tokens (terminal symbols) into fallback tokens. -** If a construct like the following: -** -** %fallback ID X Y Z. -** -** appears in the grammar, then ID becomes a fallback token for X, Y, -** and Z. Whenever one of the tokens X, Y, or Z is input to the parser -** but it does not parse, the type of the token is changed to ID and -** the parse is retried before an error is thrown. -** -** This feature can be used, for example, to cause some keywords in a language -** to revert to identifiers if they keyword does not apply in the context where -** it appears. -*/ -#ifdef YYFALLBACK -static const YYCODETYPE yyFallback[] = { -}; -#endif /* YYFALLBACK */ - -/* The following structure represents a single element of the -** parser's stack. Information stored includes: -** -** + The state number for the parser at this level of the stack. -** -** + The value of the token stored at this level of the stack. -** (In other words, the "major" token.) -** -** + The semantic value stored at this level of the stack. This is -** the information used by the action routines in the grammar. -** It is sometimes called the "minor" token. -** -** After the "shift" half of a SHIFTREDUCE action, the stateno field -** actually contains the reduce action for the second half of the -** SHIFTREDUCE. -*/ -struct yyStackEntry { - YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ - YYCODETYPE major; /* The major token value. This is the code - ** number for the token at this stack level */ - YYMINORTYPE minor; /* The user-supplied minor token value. This - ** is the value of the token */ -}; -typedef struct yyStackEntry yyStackEntry; - -/* The state of the parser is completely contained in an instance of -** the following structure */ -struct yyParser { - yyStackEntry *yytos; /* Pointer to top element of the stack */ -#ifdef YYTRACKMAXSTACKDEPTH - int yyhwm; /* High-water mark of the stack */ -#endif -#ifndef YYNOERRORRECOVERY - int yyerrcnt; /* Shifts left before out of the error */ -#endif - NewParseARG_SDECL /* A place to hold %extra_argument */ - NewParseCTX_SDECL /* A place to hold %extra_context */ -#if YYSTACKDEPTH<=0 - int yystksz; /* Current side of the stack */ - yyStackEntry *yystack; /* The parser's stack */ - yyStackEntry yystk0; /* First stack entry */ -#else - yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ - yyStackEntry *yystackEnd; /* Last entry in the stack */ -#endif -}; -typedef struct yyParser yyParser; - -#ifndef NDEBUG -#include -static FILE *yyTraceFILE = 0; -static char *yyTracePrompt = 0; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Turn parser tracing on by giving a stream to which to write the trace -** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL -** -** Inputs: -**
    -**
  • A FILE* to which trace output should be written. -** If NULL, then tracing is turned off. -**
  • A prefix string written at the beginning of every -** line of trace output. If NULL, then tracing is -** turned off. -**
-** -** Outputs: -** None. -*/ -void NewParseTrace(FILE *TraceFILE, char *zTracePrompt){ - yyTraceFILE = TraceFILE; - yyTracePrompt = zTracePrompt; - if( yyTraceFILE==0 ) yyTracePrompt = 0; - else if( yyTracePrompt==0 ) yyTraceFILE = 0; -} -#endif /* NDEBUG */ - -#if defined(YYCOVERAGE) || !defined(NDEBUG) -/* For tracing shifts, the names of all terminals and nonterminals -** are required. The following table supplies these names */ -static const char *const yyTokenName[] = { - /* 0 */ "$", - /* 1 */ "OR", - /* 2 */ "AND", - /* 3 */ "UNION", - /* 4 */ "ALL", - /* 5 */ "MINUS", - /* 6 */ "EXCEPT", - /* 7 */ "INTERSECT", - /* 8 */ "NK_PLUS", - /* 9 */ "NK_MINUS", - /* 10 */ "NK_STAR", - /* 11 */ "NK_SLASH", - /* 12 */ "NK_REM", - /* 13 */ "SHOW", - /* 14 */ "DATABASES", - /* 15 */ "NK_INTEGER", - /* 16 */ "NK_FLOAT", - /* 17 */ "NK_STRING", - /* 18 */ "NK_BOOL", - /* 19 */ "TIMESTAMP", - /* 20 */ "NK_VARIABLE", - /* 21 */ "NK_COMMA", - /* 22 */ "NK_ID", - /* 23 */ "NK_LP", - /* 24 */ "NK_RP", - /* 25 */ "NK_DOT", - /* 26 */ "BETWEEN", - /* 27 */ "NOT", - /* 28 */ "IS", - /* 29 */ "NULL", - /* 30 */ "NK_LT", - /* 31 */ "NK_GT", - /* 32 */ "NK_LE", - /* 33 */ "NK_GE", - /* 34 */ "NK_NE", - /* 35 */ "NK_EQ", - /* 36 */ "LIKE", - /* 37 */ "MATCH", - /* 38 */ "NMATCH", - /* 39 */ "IN", - /* 40 */ "FROM", - /* 41 */ "AS", - /* 42 */ "JOIN", - /* 43 */ "ON", - /* 44 */ "INNER", - /* 45 */ "SELECT", - /* 46 */ "DISTINCT", - /* 47 */ "WHERE", - /* 48 */ "PARTITION", - /* 49 */ "BY", - /* 50 */ "SESSION", - /* 51 */ "STATE_WINDOW", - /* 52 */ "INTERVAL", - /* 53 */ "SLIDING", - /* 54 */ "FILL", - /* 55 */ "VALUE", - /* 56 */ "NONE", - /* 57 */ "PREV", - /* 58 */ "LINEAR", - /* 59 */ "NEXT", - /* 60 */ "GROUP", - /* 61 */ "HAVING", - /* 62 */ "ORDER", - /* 63 */ "SLIMIT", - /* 64 */ "SOFFSET", - /* 65 */ "LIMIT", - /* 66 */ "OFFSET", - /* 67 */ "ASC", - /* 68 */ "DESC", - /* 69 */ "NULLS", - /* 70 */ "FIRST", - /* 71 */ "LAST", - /* 72 */ "cmd", - /* 73 */ "query_expression", - /* 74 */ "literal", - /* 75 */ "duration_literal", - /* 76 */ "literal_list", - /* 77 */ "db_name", - /* 78 */ "table_name", - /* 79 */ "column_name", - /* 80 */ "function_name", - /* 81 */ "table_alias", - /* 82 */ "column_alias", - /* 83 */ "expression", - /* 84 */ "column_reference", - /* 85 */ "expression_list", - /* 86 */ "subquery", - /* 87 */ "predicate", - /* 88 */ "compare_op", - /* 89 */ "in_op", - /* 90 */ "in_predicate_value", - /* 91 */ "boolean_value_expression", - /* 92 */ "boolean_primary", - /* 93 */ "common_expression", - /* 94 */ "from_clause", - /* 95 */ "table_reference_list", - /* 96 */ "table_reference", - /* 97 */ "table_primary", - /* 98 */ "joined_table", - /* 99 */ "alias_opt", - /* 100 */ "parenthesized_joined_table", - /* 101 */ "join_type", - /* 102 */ "search_condition", - /* 103 */ "query_specification", - /* 104 */ "set_quantifier_opt", - /* 105 */ "select_list", - /* 106 */ "where_clause_opt", - /* 107 */ "partition_by_clause_opt", - /* 108 */ "twindow_clause_opt", - /* 109 */ "group_by_clause_opt", - /* 110 */ "having_clause_opt", - /* 111 */ "select_sublist", - /* 112 */ "select_item", - /* 113 */ "sliding_opt", - /* 114 */ "fill_opt", - /* 115 */ "fill_mode", - /* 116 */ "group_by_list", - /* 117 */ "query_expression_body", - /* 118 */ "order_by_clause_opt", - /* 119 */ "slimit_clause_opt", - /* 120 */ "limit_clause_opt", - /* 121 */ "query_primary", - /* 122 */ "sort_specification_list", - /* 123 */ "sort_specification", - /* 124 */ "ordering_specification_opt", - /* 125 */ "null_ordering_opt", -}; -#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ - -#ifndef NDEBUG -/* For tracing reduce actions, the names of all rules are required. -*/ -static const char *const yyRuleName[] = { - /* 0 */ "cmd ::= SHOW DATABASES", - /* 1 */ "cmd ::= query_expression", - /* 2 */ "literal ::= NK_INTEGER", - /* 3 */ "literal ::= NK_FLOAT", - /* 4 */ "literal ::= NK_STRING", - /* 5 */ "literal ::= NK_BOOL", - /* 6 */ "literal ::= TIMESTAMP NK_STRING", - /* 7 */ "literal ::= duration_literal", - /* 8 */ "duration_literal ::= NK_VARIABLE", - /* 9 */ "literal_list ::= literal", - /* 10 */ "literal_list ::= literal_list NK_COMMA literal", - /* 11 */ "db_name ::= NK_ID", - /* 12 */ "table_name ::= NK_ID", - /* 13 */ "column_name ::= NK_ID", - /* 14 */ "function_name ::= NK_ID", - /* 15 */ "table_alias ::= NK_ID", - /* 16 */ "column_alias ::= NK_ID", - /* 17 */ "expression ::= literal", - /* 18 */ "expression ::= column_reference", - /* 19 */ "expression ::= function_name NK_LP expression_list NK_RP", - /* 20 */ "expression ::= function_name NK_LP NK_STAR NK_RP", - /* 21 */ "expression ::= subquery", - /* 22 */ "expression ::= NK_LP expression NK_RP", - /* 23 */ "expression ::= NK_PLUS expression", - /* 24 */ "expression ::= NK_MINUS expression", - /* 25 */ "expression ::= expression NK_PLUS expression", - /* 26 */ "expression ::= expression NK_MINUS expression", - /* 27 */ "expression ::= expression NK_STAR expression", - /* 28 */ "expression ::= expression NK_SLASH expression", - /* 29 */ "expression ::= expression NK_REM expression", - /* 30 */ "expression_list ::= expression", - /* 31 */ "expression_list ::= expression_list NK_COMMA expression", - /* 32 */ "column_reference ::= column_name", - /* 33 */ "column_reference ::= table_name NK_DOT column_name", - /* 34 */ "predicate ::= expression compare_op expression", - /* 35 */ "predicate ::= expression BETWEEN expression AND expression", - /* 36 */ "predicate ::= expression NOT BETWEEN expression AND expression", - /* 37 */ "predicate ::= expression IS NULL", - /* 38 */ "predicate ::= expression IS NOT NULL", - /* 39 */ "predicate ::= expression in_op in_predicate_value", - /* 40 */ "compare_op ::= NK_LT", - /* 41 */ "compare_op ::= NK_GT", - /* 42 */ "compare_op ::= NK_LE", - /* 43 */ "compare_op ::= NK_GE", - /* 44 */ "compare_op ::= NK_NE", - /* 45 */ "compare_op ::= NK_EQ", - /* 46 */ "compare_op ::= LIKE", - /* 47 */ "compare_op ::= NOT LIKE", - /* 48 */ "compare_op ::= MATCH", - /* 49 */ "compare_op ::= NMATCH", - /* 50 */ "in_op ::= IN", - /* 51 */ "in_op ::= NOT IN", - /* 52 */ "in_predicate_value ::= NK_LP expression_list NK_RP", - /* 53 */ "boolean_value_expression ::= boolean_primary", - /* 54 */ "boolean_value_expression ::= NOT boolean_primary", - /* 55 */ "boolean_value_expression ::= boolean_value_expression OR boolean_value_expression", - /* 56 */ "boolean_value_expression ::= boolean_value_expression AND boolean_value_expression", - /* 57 */ "boolean_primary ::= predicate", - /* 58 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP", - /* 59 */ "common_expression ::= expression", - /* 60 */ "common_expression ::= boolean_value_expression", - /* 61 */ "from_clause ::= FROM table_reference_list", - /* 62 */ "table_reference_list ::= table_reference", - /* 63 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference", - /* 64 */ "table_reference ::= table_primary", - /* 65 */ "table_reference ::= joined_table", - /* 66 */ "table_primary ::= table_name alias_opt", - /* 67 */ "table_primary ::= db_name NK_DOT table_name alias_opt", - /* 68 */ "table_primary ::= subquery alias_opt", - /* 69 */ "table_primary ::= parenthesized_joined_table", - /* 70 */ "alias_opt ::=", - /* 71 */ "alias_opt ::= table_alias", - /* 72 */ "alias_opt ::= AS table_alias", - /* 73 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP", - /* 74 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP", - /* 75 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition", - /* 76 */ "join_type ::=", - /* 77 */ "join_type ::= INNER", - /* 78 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt twindow_clause_opt group_by_clause_opt having_clause_opt", - /* 79 */ "set_quantifier_opt ::=", - /* 80 */ "set_quantifier_opt ::= DISTINCT", - /* 81 */ "set_quantifier_opt ::= ALL", - /* 82 */ "select_list ::= NK_STAR", - /* 83 */ "select_list ::= select_sublist", - /* 84 */ "select_sublist ::= select_item", - /* 85 */ "select_sublist ::= select_sublist NK_COMMA select_item", - /* 86 */ "select_item ::= common_expression", - /* 87 */ "select_item ::= common_expression column_alias", - /* 88 */ "select_item ::= common_expression AS column_alias", - /* 89 */ "select_item ::= table_name NK_DOT NK_STAR", - /* 90 */ "where_clause_opt ::=", - /* 91 */ "where_clause_opt ::= WHERE search_condition", - /* 92 */ "partition_by_clause_opt ::=", - /* 93 */ "partition_by_clause_opt ::= PARTITION BY expression_list", - /* 94 */ "twindow_clause_opt ::=", - /* 95 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA NK_INTEGER NK_RP", - /* 96 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP column_reference NK_RP", - /* 97 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt", - /* 98 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt", - /* 99 */ "sliding_opt ::=", - /* 100 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP", - /* 101 */ "fill_opt ::=", - /* 102 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP", - /* 103 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP", - /* 104 */ "fill_mode ::= NONE", - /* 105 */ "fill_mode ::= PREV", - /* 106 */ "fill_mode ::= NULL", - /* 107 */ "fill_mode ::= LINEAR", - /* 108 */ "fill_mode ::= NEXT", - /* 109 */ "group_by_clause_opt ::=", - /* 110 */ "group_by_clause_opt ::= GROUP BY group_by_list", - /* 111 */ "group_by_list ::= expression", - /* 112 */ "group_by_list ::= group_by_list NK_COMMA expression", - /* 113 */ "having_clause_opt ::=", - /* 114 */ "having_clause_opt ::= HAVING search_condition", - /* 115 */ "query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt", - /* 116 */ "query_expression_body ::= query_primary", - /* 117 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body", - /* 118 */ "query_primary ::= query_specification", - /* 119 */ "order_by_clause_opt ::=", - /* 120 */ "order_by_clause_opt ::= ORDER BY sort_specification_list", - /* 121 */ "slimit_clause_opt ::=", - /* 122 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER", - /* 123 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER", - /* 124 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER", - /* 125 */ "limit_clause_opt ::=", - /* 126 */ "limit_clause_opt ::= LIMIT NK_INTEGER", - /* 127 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER", - /* 128 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER", - /* 129 */ "subquery ::= NK_LP query_expression NK_RP", - /* 130 */ "search_condition ::= common_expression", - /* 131 */ "sort_specification_list ::= sort_specification", - /* 132 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification", - /* 133 */ "sort_specification ::= expression ordering_specification_opt null_ordering_opt", - /* 134 */ "ordering_specification_opt ::=", - /* 135 */ "ordering_specification_opt ::= ASC", - /* 136 */ "ordering_specification_opt ::= DESC", - /* 137 */ "null_ordering_opt ::=", - /* 138 */ "null_ordering_opt ::= NULLS FIRST", - /* 139 */ "null_ordering_opt ::= NULLS LAST", -}; -#endif /* NDEBUG */ - - -#if YYSTACKDEPTH<=0 -/* -** Try to increase the size of the parser stack. Return the number -** of errors. Return 0 on success. -*/ -static int yyGrowStack(yyParser *p){ - int newSize; - int idx; - yyStackEntry *pNew; - - newSize = p->yystksz*2 + 100; - idx = p->yytos ? (int)(p->yytos - p->yystack) : 0; - if( p->yystack==&p->yystk0 ){ - pNew = malloc(newSize*sizeof(pNew[0])); - if( pNew ) pNew[0] = p->yystk0; - }else{ - pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); - } - if( pNew ){ - p->yystack = pNew; - p->yytos = &p->yystack[idx]; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", - yyTracePrompt, p->yystksz, newSize); - } -#endif - p->yystksz = newSize; - } - return pNew==0; -} -#endif - -/* Datatype of the argument to the memory allocated passed as the -** second argument to NewParseAlloc() below. This can be changed by -** putting an appropriate #define in the %include section of the input -** grammar. -*/ -#ifndef YYMALLOCARGTYPE -# define YYMALLOCARGTYPE size_t -#endif - -/* Initialize a new parser that has already been allocated. -*/ -void NewParseInit(void *yypRawParser NewParseCTX_PDECL){ - yyParser *yypParser = (yyParser*)yypRawParser; - NewParseCTX_STORE -#ifdef YYTRACKMAXSTACKDEPTH - yypParser->yyhwm = 0; -#endif -#if YYSTACKDEPTH<=0 - yypParser->yytos = NULL; - yypParser->yystack = NULL; - yypParser->yystksz = 0; - if( yyGrowStack(yypParser) ){ - yypParser->yystack = &yypParser->yystk0; - yypParser->yystksz = 1; - } -#endif -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - yypParser->yytos = yypParser->yystack; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; -#if YYSTACKDEPTH>0 - yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; -#endif -} - -#ifndef NewParse_ENGINEALWAYSONSTACK -/* -** This function allocates a new parser. -** The only argument is a pointer to a function which works like -** malloc. -** -** Inputs: -** A pointer to the function used to allocate memory. -** -** Outputs: -** A pointer to a parser. This pointer is used in subsequent calls -** to NewParse and NewParseFree. -*/ -void *NewParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) NewParseCTX_PDECL){ - yyParser *yypParser; - yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( yypParser ){ - NewParseCTX_STORE - NewParseInit(yypParser NewParseCTX_PARAM); - } - return (void*)yypParser; -} -#endif /* NewParse_ENGINEALWAYSONSTACK */ - - -/* The following function deletes the "minor type" or semantic value -** associated with a symbol. The symbol can be either a terminal -** or nonterminal. "yymajor" is the symbol code, and "yypminor" is -** a pointer to the value to be deleted. The code used to do the -** deletions is derived from the %destructor and/or %token_destructor -** directives of the input grammar. -*/ -static void yy_destructor( - yyParser *yypParser, /* The parser */ - YYCODETYPE yymajor, /* Type code for object to destroy */ - YYMINORTYPE *yypminor /* The object to be destroyed */ -){ - NewParseARG_FETCH - NewParseCTX_FETCH - switch( yymajor ){ - /* Here is inserted the actions which take place when a - ** terminal or non-terminal is destroyed. This can happen - ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is - ** being destroyed before it is finished parsing. - ** - ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are *not* used - ** inside the C code. - */ -/********* Begin destructor definitions ***************************************/ - /* Default NON-TERMINAL Destructor */ - case 72: /* cmd */ - case 73: /* query_expression */ - case 74: /* literal */ - case 75: /* duration_literal */ - case 83: /* expression */ - case 84: /* column_reference */ - case 86: /* subquery */ - case 87: /* predicate */ - case 90: /* in_predicate_value */ - case 91: /* boolean_value_expression */ - case 92: /* boolean_primary */ - case 93: /* common_expression */ - case 94: /* from_clause */ - case 95: /* table_reference_list */ - case 96: /* table_reference */ - case 97: /* table_primary */ - case 98: /* joined_table */ - case 100: /* parenthesized_joined_table */ - case 102: /* search_condition */ - case 103: /* query_specification */ - case 106: /* where_clause_opt */ - case 108: /* twindow_clause_opt */ - case 110: /* having_clause_opt */ - case 112: /* select_item */ - case 113: /* sliding_opt */ - case 114: /* fill_opt */ - case 117: /* query_expression_body */ - case 119: /* slimit_clause_opt */ - case 120: /* limit_clause_opt */ - case 121: /* query_primary */ - case 123: /* sort_specification */ -{ - PARSER_DESTRUCTOR_TRACE; nodesDestroyNode((yypminor->yy56)); -} - break; - case 76: /* literal_list */ - case 85: /* expression_list */ - case 105: /* select_list */ - case 107: /* partition_by_clause_opt */ - case 109: /* group_by_clause_opt */ - case 111: /* select_sublist */ - case 116: /* group_by_list */ - case 118: /* order_by_clause_opt */ - case 122: /* sort_specification_list */ -{ - PARSER_DESTRUCTOR_TRACE; nodesDestroyList((yypminor->yy208)); -} - break; - case 77: /* db_name */ - case 78: /* table_name */ - case 79: /* column_name */ - case 80: /* function_name */ - case 81: /* table_alias */ - case 82: /* column_alias */ - case 99: /* alias_opt */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; - case 88: /* compare_op */ - case 89: /* in_op */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; - case 101: /* join_type */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; - case 104: /* set_quantifier_opt */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; - case 115: /* fill_mode */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; - case 124: /* ordering_specification_opt */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; - case 125: /* null_ordering_opt */ -{ - PARSER_DESTRUCTOR_TRACE; -} - break; -/********* End destructor definitions *****************************************/ - default: break; /* If no destructor action specified: do nothing */ - } -} - -/* -** Pop the parser's stack once. -** -** If there is a destructor routine associated with the token which -** is popped from the stack, then call it. -*/ -static void yy_pop_parser_stack(yyParser *pParser){ - yyStackEntry *yytos; - assert( pParser->yytos!=0 ); - assert( pParser->yytos > pParser->yystack ); - yytos = pParser->yytos--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - yy_destructor(pParser, yytos->major, &yytos->minor); -} - -/* -** Clear all secondary memory allocations from the parser -*/ -void NewParseFinalize(void *p){ - yyParser *pParser = (yyParser*)p; - while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); -#if YYSTACKDEPTH<=0 - if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); -#endif -} - -#ifndef NewParse_ENGINEALWAYSONSTACK -/* -** Deallocate and destroy a parser. Destructors are called for -** all stack elements before shutting the parser down. -** -** If the YYPARSEFREENEVERNULL macro exists (for example because it -** is defined in a %include section of the input grammar) then it is -** assumed that the input pointer is never NULL. -*/ -void NewParseFree( - void *p, /* The parser to be deleted */ - void (*freeProc)(void*) /* Function used to reclaim memory */ -){ -#ifndef YYPARSEFREENEVERNULL - if( p==0 ) return; -#endif - NewParseFinalize(p); - (*freeProc)(p); -} -#endif /* NewParse_ENGINEALWAYSONSTACK */ - -/* -** Return the peak depth of the stack for a parser. -*/ -#ifdef YYTRACKMAXSTACKDEPTH -int NewParseStackPeak(void *p){ - yyParser *pParser = (yyParser*)p; - return pParser->yyhwm; -} -#endif - -/* This array of booleans keeps track of the parser statement -** coverage. The element yycoverage[X][Y] is set when the parser -** is in state X and has a lookahead token Y. In a well-tested -** systems, every element of this matrix should end up being set. -*/ -#if defined(YYCOVERAGE) -static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; -#endif - -/* -** Write into out a description of every state/lookahead combination that -** -** (1) has not been used by the parser, and -** (2) is not a syntax error. -** -** Return the number of missed state/lookahead combinations. -*/ -#if defined(YYCOVERAGE) -int NewParseCoverage(FILE *out){ - int stateno, iLookAhead, i; - int nMissed = 0; - for(stateno=0; statenoYY_MAX_SHIFT ) return stateno; - assert( stateno <= YY_SHIFT_COUNT ); -#if defined(YYCOVERAGE) - yycoverage[stateno][iLookAhead] = 1; -#endif - do{ - i = yy_shift_ofst[stateno]; - assert( i>=0 ); - /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ - assert( iLookAhead!=YYNOCODE ); - assert( iLookAhead < YYNTOKEN ); - i += iLookAhead; - if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ -#ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; - } -#endif -#ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 - ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; - } - } -#endif /* YYWILDCARD */ - return yy_default[stateno]; - }else{ - return yy_action[i]; - } - }while(1); -} - -/* -** Find the appropriate action for a parser given the non-terminal -** look-ahead token iLookAhead. -*/ -static YYACTIONTYPE yy_find_reduce_action( - YYACTIONTYPE stateno, /* Current state number */ - YYCODETYPE iLookAhead /* The look-ahead token */ -){ - int i; -#ifdef YYERRORSYMBOL - if( stateno>YY_REDUCE_COUNT ){ - return yy_default[stateno]; - } -#else - assert( stateno<=YY_REDUCE_COUNT ); -#endif - i = yy_reduce_ofst[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; -#ifdef YYERRORSYMBOL - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - return yy_default[stateno]; - } -#else - assert( i>=0 && iyytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ -/******** Begin %stack_overflow code ******************************************/ -/******** End %stack_overflow code ********************************************/ - NewParseARG_STORE /* Suppress warning about unused %extra_argument var */ - NewParseCTX_STORE -} - -/* -** Print tracing information for a SHIFT action -*/ -#ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ - if( yyTraceFILE ){ - if( yyNewStateyytos->major], - yyNewState); - }else{ - fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", - yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], - yyNewState - YY_MIN_REDUCE); - } - } -} -#else -# define yyTraceShift(X,Y,Z) -#endif - -/* -** Perform a shift action. -*/ -static void yy_shift( - yyParser *yypParser, /* The parser to be shifted */ - YYACTIONTYPE yyNewState, /* The new state to shift in */ - YYCODETYPE yyMajor, /* The major token to shift in */ - NewParseTOKENTYPE yyMinor /* The minor token to shift in */ -){ - yyStackEntry *yytos; - yypParser->yytos++; -#ifdef YYTRACKMAXSTACKDEPTH - if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ - yypParser->yyhwm++; - assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); - } -#endif -#if YYSTACKDEPTH>0 - if( yypParser->yytos>yypParser->yystackEnd ){ - yypParser->yytos--; - yyStackOverflow(yypParser); - return; - } -#else - if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ - if( yyGrowStack(yypParser) ){ - yypParser->yytos--; - yyStackOverflow(yypParser); - return; - } - } -#endif - if( yyNewState > YY_MAX_SHIFT ){ - yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - } - yytos = yypParser->yytos; - yytos->stateno = yyNewState; - yytos->major = yyMajor; - yytos->minor.yy0 = yyMinor; - yyTraceShift(yypParser, yyNewState, "Shift"); -} - -/* The following table contains information about every rule that -** is used during the reduce. -*/ -static const struct { - YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - signed char nrhs; /* Negative of the number of RHS symbols in the rule */ -} yyRuleInfo[] = { - { 72, -2 }, /* (0) cmd ::= SHOW DATABASES */ - { 72, -1 }, /* (1) cmd ::= query_expression */ - { 74, -1 }, /* (2) literal ::= NK_INTEGER */ - { 74, -1 }, /* (3) literal ::= NK_FLOAT */ - { 74, -1 }, /* (4) literal ::= NK_STRING */ - { 74, -1 }, /* (5) literal ::= NK_BOOL */ - { 74, -2 }, /* (6) literal ::= TIMESTAMP NK_STRING */ - { 74, -1 }, /* (7) literal ::= duration_literal */ - { 75, -1 }, /* (8) duration_literal ::= NK_VARIABLE */ - { 76, -1 }, /* (9) literal_list ::= literal */ - { 76, -3 }, /* (10) literal_list ::= literal_list NK_COMMA literal */ - { 77, -1 }, /* (11) db_name ::= NK_ID */ - { 78, -1 }, /* (12) table_name ::= NK_ID */ - { 79, -1 }, /* (13) column_name ::= NK_ID */ - { 80, -1 }, /* (14) function_name ::= NK_ID */ - { 81, -1 }, /* (15) table_alias ::= NK_ID */ - { 82, -1 }, /* (16) column_alias ::= NK_ID */ - { 83, -1 }, /* (17) expression ::= literal */ - { 83, -1 }, /* (18) expression ::= column_reference */ - { 83, -4 }, /* (19) expression ::= function_name NK_LP expression_list NK_RP */ - { 83, -4 }, /* (20) expression ::= function_name NK_LP NK_STAR NK_RP */ - { 83, -1 }, /* (21) expression ::= subquery */ - { 83, -3 }, /* (22) expression ::= NK_LP expression NK_RP */ - { 83, -2 }, /* (23) expression ::= NK_PLUS expression */ - { 83, -2 }, /* (24) expression ::= NK_MINUS expression */ - { 83, -3 }, /* (25) expression ::= expression NK_PLUS expression */ - { 83, -3 }, /* (26) expression ::= expression NK_MINUS expression */ - { 83, -3 }, /* (27) expression ::= expression NK_STAR expression */ - { 83, -3 }, /* (28) expression ::= expression NK_SLASH expression */ - { 83, -3 }, /* (29) expression ::= expression NK_REM expression */ - { 85, -1 }, /* (30) expression_list ::= expression */ - { 85, -3 }, /* (31) expression_list ::= expression_list NK_COMMA expression */ - { 84, -1 }, /* (32) column_reference ::= column_name */ - { 84, -3 }, /* (33) column_reference ::= table_name NK_DOT column_name */ - { 87, -3 }, /* (34) predicate ::= expression compare_op expression */ - { 87, -5 }, /* (35) predicate ::= expression BETWEEN expression AND expression */ - { 87, -6 }, /* (36) predicate ::= expression NOT BETWEEN expression AND expression */ - { 87, -3 }, /* (37) predicate ::= expression IS NULL */ - { 87, -4 }, /* (38) predicate ::= expression IS NOT NULL */ - { 87, -3 }, /* (39) predicate ::= expression in_op in_predicate_value */ - { 88, -1 }, /* (40) compare_op ::= NK_LT */ - { 88, -1 }, /* (41) compare_op ::= NK_GT */ - { 88, -1 }, /* (42) compare_op ::= NK_LE */ - { 88, -1 }, /* (43) compare_op ::= NK_GE */ - { 88, -1 }, /* (44) compare_op ::= NK_NE */ - { 88, -1 }, /* (45) compare_op ::= NK_EQ */ - { 88, -1 }, /* (46) compare_op ::= LIKE */ - { 88, -2 }, /* (47) compare_op ::= NOT LIKE */ - { 88, -1 }, /* (48) compare_op ::= MATCH */ - { 88, -1 }, /* (49) compare_op ::= NMATCH */ - { 89, -1 }, /* (50) in_op ::= IN */ - { 89, -2 }, /* (51) in_op ::= NOT IN */ - { 90, -3 }, /* (52) in_predicate_value ::= NK_LP expression_list NK_RP */ - { 91, -1 }, /* (53) boolean_value_expression ::= boolean_primary */ - { 91, -2 }, /* (54) boolean_value_expression ::= NOT boolean_primary */ - { 91, -3 }, /* (55) boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */ - { 91, -3 }, /* (56) boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */ - { 92, -1 }, /* (57) boolean_primary ::= predicate */ - { 92, -3 }, /* (58) boolean_primary ::= NK_LP boolean_value_expression NK_RP */ - { 93, -1 }, /* (59) common_expression ::= expression */ - { 93, -1 }, /* (60) common_expression ::= boolean_value_expression */ - { 94, -2 }, /* (61) from_clause ::= FROM table_reference_list */ - { 95, -1 }, /* (62) table_reference_list ::= table_reference */ - { 95, -3 }, /* (63) table_reference_list ::= table_reference_list NK_COMMA table_reference */ - { 96, -1 }, /* (64) table_reference ::= table_primary */ - { 96, -1 }, /* (65) table_reference ::= joined_table */ - { 97, -2 }, /* (66) table_primary ::= table_name alias_opt */ - { 97, -4 }, /* (67) table_primary ::= db_name NK_DOT table_name alias_opt */ - { 97, -2 }, /* (68) table_primary ::= subquery alias_opt */ - { 97, -1 }, /* (69) table_primary ::= parenthesized_joined_table */ - { 99, 0 }, /* (70) alias_opt ::= */ - { 99, -1 }, /* (71) alias_opt ::= table_alias */ - { 99, -2 }, /* (72) alias_opt ::= AS table_alias */ - { 100, -3 }, /* (73) parenthesized_joined_table ::= NK_LP joined_table NK_RP */ - { 100, -3 }, /* (74) parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ - { 98, -6 }, /* (75) joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ - { 101, 0 }, /* (76) join_type ::= */ - { 101, -1 }, /* (77) join_type ::= INNER */ - { 103, -9 }, /* (78) query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ - { 104, 0 }, /* (79) set_quantifier_opt ::= */ - { 104, -1 }, /* (80) set_quantifier_opt ::= DISTINCT */ - { 104, -1 }, /* (81) set_quantifier_opt ::= ALL */ - { 105, -1 }, /* (82) select_list ::= NK_STAR */ - { 105, -1 }, /* (83) select_list ::= select_sublist */ - { 111, -1 }, /* (84) select_sublist ::= select_item */ - { 111, -3 }, /* (85) select_sublist ::= select_sublist NK_COMMA select_item */ - { 112, -1 }, /* (86) select_item ::= common_expression */ - { 112, -2 }, /* (87) select_item ::= common_expression column_alias */ - { 112, -3 }, /* (88) select_item ::= common_expression AS column_alias */ - { 112, -3 }, /* (89) select_item ::= table_name NK_DOT NK_STAR */ - { 106, 0 }, /* (90) where_clause_opt ::= */ - { 106, -2 }, /* (91) where_clause_opt ::= WHERE search_condition */ - { 107, 0 }, /* (92) partition_by_clause_opt ::= */ - { 107, -3 }, /* (93) partition_by_clause_opt ::= PARTITION BY expression_list */ - { 108, 0 }, /* (94) twindow_clause_opt ::= */ - { 108, -6 }, /* (95) twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA NK_INTEGER NK_RP */ - { 108, -4 }, /* (96) twindow_clause_opt ::= STATE_WINDOW NK_LP column_reference NK_RP */ - { 108, -6 }, /* (97) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ - { 108, -8 }, /* (98) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ - { 113, 0 }, /* (99) sliding_opt ::= */ - { 113, -4 }, /* (100) sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ - { 114, 0 }, /* (101) fill_opt ::= */ - { 114, -4 }, /* (102) fill_opt ::= FILL NK_LP fill_mode NK_RP */ - { 114, -6 }, /* (103) fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ - { 115, -1 }, /* (104) fill_mode ::= NONE */ - { 115, -1 }, /* (105) fill_mode ::= PREV */ - { 115, -1 }, /* (106) fill_mode ::= NULL */ - { 115, -1 }, /* (107) fill_mode ::= LINEAR */ - { 115, -1 }, /* (108) fill_mode ::= NEXT */ - { 109, 0 }, /* (109) group_by_clause_opt ::= */ - { 109, -3 }, /* (110) group_by_clause_opt ::= GROUP BY group_by_list */ - { 116, -1 }, /* (111) group_by_list ::= expression */ - { 116, -3 }, /* (112) group_by_list ::= group_by_list NK_COMMA expression */ - { 110, 0 }, /* (113) having_clause_opt ::= */ - { 110, -2 }, /* (114) having_clause_opt ::= HAVING search_condition */ - { 73, -4 }, /* (115) query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ - { 117, -1 }, /* (116) query_expression_body ::= query_primary */ - { 117, -4 }, /* (117) query_expression_body ::= query_expression_body UNION ALL query_expression_body */ - { 121, -1 }, /* (118) query_primary ::= query_specification */ - { 118, 0 }, /* (119) order_by_clause_opt ::= */ - { 118, -3 }, /* (120) order_by_clause_opt ::= ORDER BY sort_specification_list */ - { 119, 0 }, /* (121) slimit_clause_opt ::= */ - { 119, -2 }, /* (122) slimit_clause_opt ::= SLIMIT NK_INTEGER */ - { 119, -4 }, /* (123) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ - { 119, -4 }, /* (124) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - { 120, 0 }, /* (125) limit_clause_opt ::= */ - { 120, -2 }, /* (126) limit_clause_opt ::= LIMIT NK_INTEGER */ - { 120, -4 }, /* (127) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ - { 120, -4 }, /* (128) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - { 86, -3 }, /* (129) subquery ::= NK_LP query_expression NK_RP */ - { 102, -1 }, /* (130) search_condition ::= common_expression */ - { 122, -1 }, /* (131) sort_specification_list ::= sort_specification */ - { 122, -3 }, /* (132) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ - { 123, -3 }, /* (133) sort_specification ::= expression ordering_specification_opt null_ordering_opt */ - { 124, 0 }, /* (134) ordering_specification_opt ::= */ - { 124, -1 }, /* (135) ordering_specification_opt ::= ASC */ - { 124, -1 }, /* (136) ordering_specification_opt ::= DESC */ - { 125, 0 }, /* (137) null_ordering_opt ::= */ - { 125, -2 }, /* (138) null_ordering_opt ::= NULLS FIRST */ - { 125, -2 }, /* (139) null_ordering_opt ::= NULLS LAST */ -}; - -static void yy_accept(yyParser*); /* Forward Declaration */ - -/* -** Perform a reduce action and the shift that must immediately -** follow the reduce. -** -** The yyLookahead and yyLookaheadToken parameters provide reduce actions -** access to the lookahead token (if any). The yyLookahead will be YYNOCODE -** if the lookahead token has already been consumed. As this procedure is -** only called from one place, optimizing compilers will in-line it, which -** means that the extra parameters have no performance impact. -*/ -static YYACTIONTYPE yy_reduce( - yyParser *yypParser, /* The parser */ - unsigned int yyruleno, /* Number of the rule by which to reduce */ - int yyLookahead, /* Lookahead token, or YYNOCODE if none */ - NewParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ - NewParseCTX_PDECL /* %extra_context */ -){ - int yygoto; /* The next state */ - YYACTIONTYPE yyact; /* The next action */ - yyStackEntry *yymsp; /* The top of the parser's stack */ - int yysize; /* Amount to pop the stack */ - NewParseARG_FETCH - (void)yyLookahead; - (void)yyLookaheadToken; - yymsp = yypParser->yytos; -#ifndef NDEBUG - if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfo[yyruleno].nrhs; - if( yysize ){ - fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", - yyTracePrompt, - yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); - }else{ - fprintf(yyTraceFILE, "%sReduce %d [%s].\n", - yyTracePrompt, yyruleno, yyRuleName[yyruleno]); - } - } -#endif /* NDEBUG */ - - /* Check that the stack is large enough to grow by a single entry - ** if the RHS of the rule is empty. This ensures that there is room - ** enough on the stack to push the LHS value */ - if( yyRuleInfo[yyruleno].nrhs==0 ){ -#ifdef YYTRACKMAXSTACKDEPTH - if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ - yypParser->yyhwm++; - assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); - } -#endif -#if YYSTACKDEPTH>0 - if( yypParser->yytos>=yypParser->yystackEnd ){ - yyStackOverflow(yypParser); - /* The call to yyStackOverflow() above pops the stack until it is - ** empty, causing the main parser loop to exit. So the return value - ** is never used and does not matter. */ - return 0; - } -#else - if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ - if( yyGrowStack(yypParser) ){ - yyStackOverflow(yypParser); - /* The call to yyStackOverflow() above pops the stack until it is - ** empty, causing the main parser loop to exit. So the return value - ** is never used and does not matter. */ - return 0; - } - yymsp = yypParser->yytos; - } -#endif - } - - switch( yyruleno ){ - /* Beginning here are the reduction cases. A typical example - ** follows: - ** case 0: - ** #line - ** { ... } // User supplied code - ** #line - ** break; - */ -/********** Begin reduce actions **********************************************/ - YYMINORTYPE yylhsminor; - case 0: /* cmd ::= SHOW DATABASES */ -{ PARSER_TRACE; createShowStmt(pCxt, SHOW_TYPE_DATABASE); } - break; - case 1: /* cmd ::= query_expression */ -{ PARSER_TRACE; pCxt->pRootNode = yymsp[0].minor.yy56; } - break; - case 2: /* literal ::= NK_INTEGER */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 3: /* literal ::= NK_FLOAT */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 4: /* literal ::= NK_STRING */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 5: /* literal ::= NK_BOOL */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 6: /* literal ::= TIMESTAMP NK_STRING */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0)); } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 7: /* literal ::= duration_literal */ - case 17: /* expression ::= literal */ yytestcase(yyruleno==17); - case 18: /* expression ::= column_reference */ yytestcase(yyruleno==18); - case 21: /* expression ::= subquery */ yytestcase(yyruleno==21); - case 53: /* boolean_value_expression ::= boolean_primary */ yytestcase(yyruleno==53); - case 57: /* boolean_primary ::= predicate */ yytestcase(yyruleno==57); - case 62: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==62); - case 64: /* table_reference ::= table_primary */ yytestcase(yyruleno==64); - case 65: /* table_reference ::= joined_table */ yytestcase(yyruleno==65); - case 69: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==69); - case 116: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==116); - case 118: /* query_primary ::= query_specification */ yytestcase(yyruleno==118); -{ PARSER_TRACE; yylhsminor.yy56 = yymsp[0].minor.yy56; } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 8: /* duration_literal ::= NK_VARIABLE */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 9: /* literal_list ::= literal */ - case 30: /* expression_list ::= expression */ yytestcase(yyruleno==30); -{ PARSER_TRACE; yylhsminor.yy208 = createNodeList(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy56)); } - yymsp[0].minor.yy208 = yylhsminor.yy208; - break; - case 10: /* literal_list ::= literal_list NK_COMMA literal */ - case 31: /* expression_list ::= expression_list NK_COMMA expression */ yytestcase(yyruleno==31); -{ PARSER_TRACE; yylhsminor.yy208 = addNodeToList(pCxt, yymsp[-2].minor.yy208, releaseRawExprNode(pCxt, yymsp[0].minor.yy56)); } - yymsp[-2].minor.yy208 = yylhsminor.yy208; - break; - case 11: /* db_name ::= NK_ID */ - case 12: /* table_name ::= NK_ID */ yytestcase(yyruleno==12); - case 13: /* column_name ::= NK_ID */ yytestcase(yyruleno==13); - case 14: /* function_name ::= NK_ID */ yytestcase(yyruleno==14); - case 15: /* table_alias ::= NK_ID */ yytestcase(yyruleno==15); - case 16: /* column_alias ::= NK_ID */ yytestcase(yyruleno==16); -{ PARSER_TRACE; yylhsminor.yy29 = yymsp[0].minor.yy0; } - yymsp[0].minor.yy29 = yylhsminor.yy29; - break; - case 19: /* expression ::= function_name NK_LP expression_list NK_RP */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy29, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy29, yymsp[-1].minor.yy208)); } - yymsp[-3].minor.yy56 = yylhsminor.yy56; - break; - case 20: /* expression ::= function_name NK_LP NK_STAR NK_RP */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy29, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy29, createNodeList(pCxt, createColumnNode(pCxt, NULL, &yymsp[-1].minor.yy0)))); } - yymsp[-3].minor.yy56 = yylhsminor.yy56; - break; - case 22: /* expression ::= NK_LP expression NK_RP */ - case 58: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==58); -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, releaseRawExprNode(pCxt, yymsp[-1].minor.yy56)); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 23: /* expression ::= NK_PLUS expression */ -{ - PARSER_TRACE; - SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, releaseRawExprNode(pCxt, yymsp[0].minor.yy56)); - } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 24: /* expression ::= NK_MINUS expression */ -{ - PARSER_TRACE; - SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[0].minor.yy56), NULL)); - } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 25: /* expression ::= expression NK_PLUS expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 26: /* expression ::= expression NK_MINUS expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 27: /* expression ::= expression NK_STAR expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 28: /* expression ::= expression NK_SLASH expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 29: /* expression ::= expression NK_REM expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MOD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 32: /* column_reference ::= column_name */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNode(pCxt, &yymsp[0].minor.yy29, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy29)); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 33: /* column_reference ::= table_name NK_DOT column_name */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy29, &yymsp[0].minor.yy29, createColumnNode(pCxt, &yymsp[-2].minor.yy29, &yymsp[0].minor.yy29)); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 34: /* predicate ::= expression compare_op expression */ - case 39: /* predicate ::= expression in_op in_predicate_value */ yytestcase(yyruleno==39); -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, yymsp[-1].minor.yy128, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 35: /* predicate ::= expression BETWEEN expression AND expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-4].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-4].minor.yy56), releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-4].minor.yy56 = yylhsminor.yy56; - break; - case 36: /* predicate ::= expression NOT BETWEEN expression AND expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-5].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[-5].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-5].minor.yy56 = yylhsminor.yy56; - break; - case 37: /* predicate ::= expression IS NULL */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), NULL)); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 38: /* predicate ::= expression IS NOT NULL */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy56), NULL)); - } - yymsp[-3].minor.yy56 = yylhsminor.yy56; - break; - case 40: /* compare_op ::= NK_LT */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_LOWER_THAN; } - break; - case 41: /* compare_op ::= NK_GT */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_GREATER_THAN; } - break; - case 42: /* compare_op ::= NK_LE */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_LOWER_EQUAL; } - break; - case 43: /* compare_op ::= NK_GE */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_GREATER_EQUAL; } - break; - case 44: /* compare_op ::= NK_NE */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_NOT_EQUAL; } - break; - case 45: /* compare_op ::= NK_EQ */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_EQUAL; } - break; - case 46: /* compare_op ::= LIKE */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_LIKE; } - break; - case 47: /* compare_op ::= NOT LIKE */ -{ PARSER_TRACE; yymsp[-1].minor.yy128 = OP_TYPE_NOT_LIKE; } - break; - case 48: /* compare_op ::= MATCH */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_MATCH; } - break; - case 49: /* compare_op ::= NMATCH */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_NMATCH; } - break; - case 50: /* in_op ::= IN */ -{ PARSER_TRACE; yymsp[0].minor.yy128 = OP_TYPE_IN; } - break; - case 51: /* in_op ::= NOT IN */ -{ PARSER_TRACE; yymsp[-1].minor.yy128 = OP_TYPE_NOT_IN; } - break; - case 52: /* in_predicate_value ::= NK_LP expression_list NK_RP */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, createNodeListNode(pCxt, yymsp[-1].minor.yy208)); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 54: /* boolean_value_expression ::= NOT boolean_primary */ -{ - PARSER_TRACE; - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, yymsp[0].minor.yy56), NULL)); - } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 55: /* boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 56: /* boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */ -{ - PARSER_TRACE; - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); - } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 59: /* common_expression ::= expression */ - case 60: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==60); -{ yylhsminor.yy56 = yymsp[0].minor.yy56; } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 61: /* from_clause ::= FROM table_reference_list */ - case 91: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==91); - case 114: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==114); -{ PARSER_TRACE; yymsp[-1].minor.yy56 = yymsp[0].minor.yy56; } - break; - case 63: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */ -{ PARSER_TRACE; yylhsminor.yy56 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy56, yymsp[0].minor.yy56, NULL); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 66: /* table_primary ::= table_name alias_opt */ -{ PARSER_TRACE; yylhsminor.yy56 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy29, &yymsp[0].minor.yy29); } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 67: /* table_primary ::= db_name NK_DOT table_name alias_opt */ -{ PARSER_TRACE; yylhsminor.yy56 = createRealTableNode(pCxt, &yymsp[-3].minor.yy29, &yymsp[-1].minor.yy29, &yymsp[0].minor.yy29); } - yymsp[-3].minor.yy56 = yylhsminor.yy56; - break; - case 68: /* table_primary ::= subquery alias_opt */ -{ PARSER_TRACE; yylhsminor.yy56 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy56), &yymsp[0].minor.yy29); } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 70: /* alias_opt ::= */ -{ PARSER_TRACE; yymsp[1].minor.yy29 = nil_token; } - break; - case 71: /* alias_opt ::= table_alias */ -{ PARSER_TRACE; yylhsminor.yy29 = yymsp[0].minor.yy29; } - yymsp[0].minor.yy29 = yylhsminor.yy29; - break; - case 72: /* alias_opt ::= AS table_alias */ -{ PARSER_TRACE; yymsp[-1].minor.yy29 = yymsp[0].minor.yy29; } - break; - case 73: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */ - case 74: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==74); -{ PARSER_TRACE; yymsp[-2].minor.yy56 = yymsp[-1].minor.yy56; } - break; - case 75: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ -{ PARSER_TRACE; yylhsminor.yy56 = createJoinTableNode(pCxt, yymsp[-4].minor.yy36, yymsp[-5].minor.yy56, yymsp[-2].minor.yy56, yymsp[0].minor.yy56); } - yymsp[-5].minor.yy56 = yylhsminor.yy56; - break; - case 76: /* join_type ::= */ -{ PARSER_TRACE; yymsp[1].minor.yy36 = JOIN_TYPE_INNER; } - break; - case 77: /* join_type ::= INNER */ -{ PARSER_TRACE; yymsp[0].minor.yy36 = JOIN_TYPE_INNER; } - break; - case 78: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ -{ - PARSER_TRACE; - yymsp[-8].minor.yy56 = createSelectStmt(pCxt, yymsp[-7].minor.yy173, yymsp[-6].minor.yy208, yymsp[-5].minor.yy56); - yymsp[-8].minor.yy56 = addWhereClause(pCxt, yymsp[-8].minor.yy56, yymsp[-4].minor.yy56); - yymsp[-8].minor.yy56 = addPartitionByClause(pCxt, yymsp[-8].minor.yy56, yymsp[-3].minor.yy208); - yymsp[-8].minor.yy56 = addWindowClauseClause(pCxt, yymsp[-8].minor.yy56, yymsp[-2].minor.yy56); - yymsp[-8].minor.yy56 = addGroupByClause(pCxt, yymsp[-8].minor.yy56, yymsp[-1].minor.yy208); - yymsp[-8].minor.yy56 = addHavingClause(pCxt, yymsp[-8].minor.yy56, yymsp[0].minor.yy56); - } - break; - case 79: /* set_quantifier_opt ::= */ -{ PARSER_TRACE; yymsp[1].minor.yy173 = false; } - break; - case 80: /* set_quantifier_opt ::= DISTINCT */ -{ PARSER_TRACE; yymsp[0].minor.yy173 = true; } - break; - case 81: /* set_quantifier_opt ::= ALL */ -{ PARSER_TRACE; yymsp[0].minor.yy173 = false; } - break; - case 82: /* select_list ::= NK_STAR */ -{ PARSER_TRACE; yymsp[0].minor.yy208 = NULL; } - break; - case 83: /* select_list ::= select_sublist */ -{ PARSER_TRACE; yylhsminor.yy208 = yymsp[0].minor.yy208; } - yymsp[0].minor.yy208 = yylhsminor.yy208; - break; - case 84: /* select_sublist ::= select_item */ - case 131: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==131); -{ PARSER_TRACE; yylhsminor.yy208 = createNodeList(pCxt, yymsp[0].minor.yy56); } - yymsp[0].minor.yy208 = yylhsminor.yy208; - break; - case 85: /* select_sublist ::= select_sublist NK_COMMA select_item */ - case 132: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==132); -{ PARSER_TRACE; yylhsminor.yy208 = addNodeToList(pCxt, yymsp[-2].minor.yy208, yymsp[0].minor.yy56); } - yymsp[-2].minor.yy208 = yylhsminor.yy208; - break; - case 86: /* select_item ::= common_expression */ -{ - PARSER_TRACE; - SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy56); - yylhsminor.yy56 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy56), &t); - } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 87: /* select_item ::= common_expression column_alias */ -{ PARSER_TRACE; yylhsminor.yy56 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy56), &yymsp[0].minor.yy29); } - yymsp[-1].minor.yy56 = yylhsminor.yy56; - break; - case 88: /* select_item ::= common_expression AS column_alias */ -{ PARSER_TRACE; yylhsminor.yy56 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), &yymsp[0].minor.yy29); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 89: /* select_item ::= table_name NK_DOT NK_STAR */ -{ PARSER_TRACE; yylhsminor.yy56 = createColumnNode(pCxt, &yymsp[-2].minor.yy29, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 90: /* where_clause_opt ::= */ - case 94: /* twindow_clause_opt ::= */ yytestcase(yyruleno==94); - case 99: /* sliding_opt ::= */ yytestcase(yyruleno==99); - case 101: /* fill_opt ::= */ yytestcase(yyruleno==101); - case 113: /* having_clause_opt ::= */ yytestcase(yyruleno==113); - case 121: /* slimit_clause_opt ::= */ yytestcase(yyruleno==121); - case 125: /* limit_clause_opt ::= */ yytestcase(yyruleno==125); -{ PARSER_TRACE; yymsp[1].minor.yy56 = NULL; } - break; - case 92: /* partition_by_clause_opt ::= */ - case 109: /* group_by_clause_opt ::= */ yytestcase(yyruleno==109); - case 119: /* order_by_clause_opt ::= */ yytestcase(yyruleno==119); -{ PARSER_TRACE; yymsp[1].minor.yy208 = NULL; } - break; - case 93: /* partition_by_clause_opt ::= PARTITION BY expression_list */ - case 110: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==110); - case 120: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==120); -{ PARSER_TRACE; yymsp[-2].minor.yy208 = yymsp[0].minor.yy208; } - break; - case 95: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA NK_INTEGER NK_RP */ -{ PARSER_TRACE; yymsp[-5].minor.yy56 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy56), &yymsp[-1].minor.yy0); } - break; - case 96: /* twindow_clause_opt ::= STATE_WINDOW NK_LP column_reference NK_RP */ -{ PARSER_TRACE; yymsp[-3].minor.yy56 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy56)); } - break; - case 97: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ -{ PARSER_TRACE; yymsp[-5].minor.yy56 = createIntervalWindowNode(pCxt, yymsp[-3].minor.yy56, NULL, yymsp[-1].minor.yy56, yymsp[0].minor.yy56); } - break; - case 98: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ -{ PARSER_TRACE; yymsp[-7].minor.yy56 = createIntervalWindowNode(pCxt, yymsp[-5].minor.yy56, yymsp[-3].minor.yy56, yymsp[-1].minor.yy56, yymsp[0].minor.yy56); } - break; - case 100: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ -{ PARSER_TRACE; yymsp[-3].minor.yy56 = yymsp[-1].minor.yy56; } - break; - case 102: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */ -{ PARSER_TRACE; yymsp[-3].minor.yy56 = createFillNode(pCxt, yymsp[-1].minor.yy18, NULL); } - break; - case 103: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ -{ PARSER_TRACE; yymsp[-5].minor.yy56 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy208)); } - break; - case 104: /* fill_mode ::= NONE */ -{ PARSER_TRACE; yymsp[0].minor.yy18 = FILL_MODE_NONE; } - break; - case 105: /* fill_mode ::= PREV */ -{ PARSER_TRACE; yymsp[0].minor.yy18 = FILL_MODE_PREV; } - break; - case 106: /* fill_mode ::= NULL */ -{ PARSER_TRACE; yymsp[0].minor.yy18 = FILL_MODE_NULL; } - break; - case 107: /* fill_mode ::= LINEAR */ -{ PARSER_TRACE; yymsp[0].minor.yy18 = FILL_MODE_LINEAR; } - break; - case 108: /* fill_mode ::= NEXT */ -{ PARSER_TRACE; yymsp[0].minor.yy18 = FILL_MODE_NEXT; } - break; - case 111: /* group_by_list ::= expression */ -{ PARSER_TRACE; yylhsminor.yy208 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); } - yymsp[0].minor.yy208 = yylhsminor.yy208; - break; - case 112: /* group_by_list ::= group_by_list NK_COMMA expression */ -{ PARSER_TRACE; yylhsminor.yy208 = addNodeToList(pCxt, yymsp[-2].minor.yy208, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy56))); } - yymsp[-2].minor.yy208 = yylhsminor.yy208; - break; - case 115: /* query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ -{ - PARSER_TRACE; - yylhsminor.yy56 = addOrderByClause(pCxt, yymsp[-3].minor.yy56, yymsp[-2].minor.yy208); - yylhsminor.yy56 = addSlimitClause(pCxt, yylhsminor.yy56, yymsp[-1].minor.yy56); - yylhsminor.yy56 = addLimitClause(pCxt, yylhsminor.yy56, yymsp[0].minor.yy56); - } - yymsp[-3].minor.yy56 = yylhsminor.yy56; - break; - case 117: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */ -{ PARSER_TRACE; yylhsminor.yy56 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy56, yymsp[0].minor.yy56); } - yymsp[-3].minor.yy56 = yylhsminor.yy56; - break; - case 122: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */ - case 126: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==126); -{ PARSER_TRACE; yymsp[-1].minor.yy56 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); } - break; - case 123: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ - case 127: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==127); -{ PARSER_TRACE; yymsp[-3].minor.yy56 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - break; - case 124: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - case 128: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==128); -{ PARSER_TRACE; yymsp[-3].minor.yy56 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); } - break; - case 129: /* subquery ::= NK_LP query_expression NK_RP */ -{ PARSER_TRACE; yylhsminor.yy56 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy56); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 130: /* search_condition ::= common_expression */ -{ PARSER_TRACE; yylhsminor.yy56 = releaseRawExprNode(pCxt, yymsp[0].minor.yy56); } - yymsp[0].minor.yy56 = yylhsminor.yy56; - break; - case 133: /* sort_specification ::= expression ordering_specification_opt null_ordering_opt */ -{ PARSER_TRACE; yylhsminor.yy56 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), yymsp[-1].minor.yy218, yymsp[0].minor.yy109); } - yymsp[-2].minor.yy56 = yylhsminor.yy56; - break; - case 134: /* ordering_specification_opt ::= */ -{ PARSER_TRACE; yymsp[1].minor.yy218 = ORDER_ASC; } - break; - case 135: /* ordering_specification_opt ::= ASC */ -{ PARSER_TRACE; yymsp[0].minor.yy218 = ORDER_ASC; } - break; - case 136: /* ordering_specification_opt ::= DESC */ -{ PARSER_TRACE; yymsp[0].minor.yy218 = ORDER_DESC; } - break; - case 137: /* null_ordering_opt ::= */ -{ PARSER_TRACE; yymsp[1].minor.yy109 = NULL_ORDER_DEFAULT; } - break; - case 138: /* null_ordering_opt ::= NULLS FIRST */ -{ PARSER_TRACE; yymsp[-1].minor.yy109 = NULL_ORDER_FIRST; } - break; - case 139: /* null_ordering_opt ::= NULLS LAST */ -{ PARSER_TRACE; yymsp[-1].minor.yy109 = NULL_ORDER_LAST; } - break; - default: - break; -/********** End reduce actions ************************************************/ - }; - assert( yyrulenoYY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) ); - - /* It is not possible for a REDUCE to be followed by an error */ - assert( yyact!=YY_ERROR_ACTION ); - - yymsp += yysize+1; - yypParser->yytos = yymsp; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact, "... then shift"); - return yyact; -} - -/* -** The following code executes when the parse fails -*/ -#ifndef YYNOERRORRECOVERY -static void yy_parse_failed( - yyParser *yypParser /* The parser */ -){ - NewParseARG_FETCH - NewParseCTX_FETCH -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); - } -#endif - while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser fails */ -/************ Begin %parse_failure code ***************************************/ -/************ End %parse_failure code *****************************************/ - NewParseARG_STORE /* Suppress warning about unused %extra_argument variable */ - NewParseCTX_STORE -} -#endif /* YYNOERRORRECOVERY */ - -/* -** The following code executes when a syntax error first occurs. -*/ -static void yy_syntax_error( - yyParser *yypParser, /* The parser */ - int yymajor, /* The major type of the error token */ - NewParseTOKENTYPE yyminor /* The minor type of the error token */ -){ - NewParseARG_FETCH - NewParseCTX_FETCH -#define TOKEN yyminor -/************ Begin %syntax_error code ****************************************/ - - if(TOKEN.z) { - char msg[] = "syntax error near \"%s\""; - int32_t sqlLen = strlen(&TOKEN.z[0]); - - if (sqlLen + sizeof(msg)/sizeof(msg[0]) + 1 > pCxt->pQueryCxt->msgLen) { - char tmpstr[128] = {0}; - memcpy(tmpstr, &TOKEN.z[0], sizeof(tmpstr)/sizeof(tmpstr[0]) - 1); - sprintf(pCxt->pQueryCxt->pMsg, msg, tmpstr); - } else { - sprintf(pCxt->pQueryCxt->pMsg, msg, &TOKEN.z[0]); - } - } else { - sprintf(pCxt->pQueryCxt->pMsg, "Incomplete SQL statement"); - } - pCxt->valid = false; -/************ End %syntax_error code ******************************************/ - NewParseARG_STORE /* Suppress warning about unused %extra_argument variable */ - NewParseCTX_STORE -} - -/* -** The following is executed when the parser accepts -*/ -static void yy_accept( - yyParser *yypParser /* The parser */ -){ - NewParseARG_FETCH - NewParseCTX_FETCH -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); - } -#endif -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - assert( yypParser->yytos==yypParser->yystack ); - /* Here code is inserted which will be executed whenever the - ** parser accepts */ -/*********** Begin %parse_accept code *****************************************/ - PARSER_COMPLETE; -/*********** End %parse_accept code *******************************************/ - NewParseARG_STORE /* Suppress warning about unused %extra_argument variable */ - NewParseCTX_STORE -} - -/* The main parser program. -** The first argument is a pointer to a structure obtained from -** "NewParseAlloc" which describes the current state of the parser. -** The second argument is the major token number. The third is -** the minor token. The fourth optional argument is whatever the -** user wants (and specified in the grammar) and is available for -** use by the action routines. -** -** Inputs: -**
    -**
  • A pointer to the parser (an opaque structure.) -**
  • The major token number. -**
  • The minor token number. -**
  • An option argument of a grammar-specified type. -**
-** -** Outputs: -** None. -*/ -void NewParse( - void *yyp, /* The parser */ - int yymajor, /* The major token code number */ - NewParseTOKENTYPE yyminor /* The value for the token */ - NewParseARG_PDECL /* Optional %extra_argument parameter */ -){ - YYMINORTYPE yyminorunion; - YYACTIONTYPE yyact; /* The parser action. */ -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - int yyendofinput; /* True if we are at the end of input */ -#endif -#ifdef YYERRORSYMBOL - int yyerrorhit = 0; /* True if yymajor has invoked an error */ -#endif - yyParser *yypParser = (yyParser*)yyp; /* The parser */ - NewParseCTX_FETCH - NewParseARG_STORE - - assert( yypParser->yytos!=0 ); -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - yyendofinput = (yymajor==0); -#endif - - yyact = yypParser->yytos->stateno; -#ifndef NDEBUG - if( yyTraceFILE ){ - if( yyact < YY_MIN_REDUCE ){ - fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact); - }else{ - fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); - } - } -#endif - - do{ - assert( yyact==yypParser->yytos->stateno ); - yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); - if( yyact >= YY_MIN_REDUCE ){ - yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, - yyminor NewParseCTX_PARAM); - }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt--; -#endif - break; - }else if( yyact==YY_ACCEPT_ACTION ){ - yypParser->yytos--; - yy_accept(yypParser); - return; - }else{ - assert( yyact == YY_ERROR_ACTION ); - yyminorunion.yy0 = yyminor; -#ifdef YYERRORSYMBOL - int yymx; -#endif -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); - } -#endif -#ifdef YYERRORSYMBOL - /* A syntax error has occurred. - ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". - ** - ** This is what we do if the grammar does define ERROR: - ** - ** * Call the %syntax_error function. - ** - ** * Begin popping the stack until we enter a state where - ** it is legal to shift the error symbol, then shift - ** the error symbol. - ** - ** * Set the error count to three. - ** - ** * Begin accepting and shifting new tokens. No new error - ** processing will occur until three tokens have been - ** shifted successfully. - ** - */ - if( yypParser->yyerrcnt<0 ){ - yy_syntax_error(yypParser,yymajor,yyminor); - } - yymx = yypParser->yytos->major; - if( yymx==YYERRORSYMBOL || yyerrorhit ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sDiscard input token %s\n", - yyTracePrompt,yyTokenName[yymajor]); - } -#endif - yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); - yymajor = YYNOCODE; - }else{ - while( yypParser->yytos >= yypParser->yystack - && (yyact = yy_find_reduce_action( - yypParser->yytos->stateno, - YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE - ){ - yy_pop_parser_stack(yypParser); - } - if( yypParser->yytos < yypParser->yystack || yymajor==0 ){ - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yy_parse_failed(yypParser); -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - yymajor = YYNOCODE; - }else if( yymx!=YYERRORSYMBOL ){ - yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); - } - } - yypParser->yyerrcnt = 3; - yyerrorhit = 1; - if( yymajor==YYNOCODE ) break; - yyact = yypParser->yytos->stateno; -#elif defined(YYNOERRORRECOVERY) - /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to - ** do any kind of error recovery. Instead, simply invoke the syntax - ** error routine and continue going as if nothing had happened. - ** - ** Applications can set this macro (for example inside %include) if - ** they intend to abandon the parse upon the first syntax error seen. - */ - yy_syntax_error(yypParser,yymajor, yyminor); - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - break; -#else /* YYERRORSYMBOL is not defined */ - /* This is what we do if the grammar does not define ERROR: - ** - ** * Report an error message, and throw away the input token. - ** - ** * If the input token is $, then fail the parse. - ** - ** As before, subsequent error messages are suppressed until - ** three input tokens have been successfully shifted. - */ - if( yypParser->yyerrcnt<=0 ){ - yy_syntax_error(yypParser,yymajor, yyminor); - } - yypParser->yyerrcnt = 3; - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - if( yyendofinput ){ - yy_parse_failed(yypParser); -#ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; -#endif - } - break; -#endif - } - }while( yypParser->yytos>yypParser->yystack ); -#ifndef NDEBUG - if( yyTraceFILE ){ - yyStackEntry *i; - char cDiv = '['; - fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); - for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){ - fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); - cDiv = ' '; - } - fprintf(yyTraceFILE,"]\n"); - } -#endif - return; -} - -/* -** Return the fallback token corresponding to canonical token iToken, or -** 0 if iToken has no fallback. -*/ -int NewParseFallback(int iToken){ -#ifdef YYFALLBACK - if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ - return yyFallback[iToken]; - } -#else - (void)iToken; -#endif - return 0; -} diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c new file mode 100644 index 0000000000000000000000000000000000000000..f21db0f133096eb9065842275a5661939509a905 --- /dev/null +++ b/source/libs/parser/src/parAstCreater.c @@ -0,0 +1,994 @@ + +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "parAst.h" +#include "parUtil.h" + +#define CHECK_OUT_OF_MEM(p) \ + do { \ + if (NULL == (p)) { \ + pCxt->valid = false; \ + return NULL; \ + } \ + } while (0) + +#define CHECK_RAW_EXPR_NODE(node) \ + do { \ + if (NULL == (node) || QUERY_NODE_RAW_EXPR != nodeType(node)) { \ + pCxt->valid = false; \ + return NULL; \ + } \ + } while (0) + +SToken nil_token = { .type = TK_NK_NIL, .n = 0, .z = NULL }; + +typedef SDatabaseOptions* (*FSetDatabaseOption)(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal); +static FSetDatabaseOption setDbOptionFuncs[DB_OPTION_MAX]; + +typedef STableOptions* (*FSetTableOption)(SAstCreateContext* pCxt, STableOptions* pOptions, const SToken* pVal); +static FSetTableOption setTableOptionFuncs[TABLE_OPTION_MAX]; + +static SDatabaseOptions* setDbBlocks(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_TOTAL_BLOCKS || val > TSDB_MAX_TOTAL_BLOCKS) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option totalBlocks: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_TOTAL_BLOCKS, TSDB_MAX_TOTAL_BLOCKS); + pCxt->valid = false; + return pOptions; + } + pOptions->numOfBlocks = val; + return pOptions; +} + +static SDatabaseOptions* setDbCache(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_CACHE_BLOCK_SIZE || val > TSDB_MAX_CACHE_BLOCK_SIZE) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option cacheBlockSize: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_CACHE_BLOCK_SIZE, TSDB_MAX_CACHE_BLOCK_SIZE); + pCxt->valid = false; + return pOptions; + } + pOptions->cacheBlockSize = val; + return pOptions; +} + +static SDatabaseOptions* setDbCacheLast(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_CACHE_LAST_ROW || val > TSDB_MAX_DB_CACHE_LAST_ROW) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option cacheLast: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_DB_CACHE_LAST_ROW, TSDB_MAX_DB_CACHE_LAST_ROW); + pCxt->valid = false; + return pOptions; + } + pOptions->cachelast = val; + return pOptions; +} + +static SDatabaseOptions* setDbComp(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_COMP_LEVEL || val > TSDB_MAX_COMP_LEVEL) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option compression: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_COMP_LEVEL, TSDB_MAX_COMP_LEVEL); + pCxt->valid = false; + return pOptions; + } + pOptions->compressionLevel = val; + return pOptions; +} + +static SDatabaseOptions* setDbDays(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DAYS_PER_FILE || val > TSDB_MAX_DAYS_PER_FILE) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option daysPerFile: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_DAYS_PER_FILE, TSDB_MAX_DAYS_PER_FILE); + pCxt->valid = false; + return pOptions; + } + pOptions->daysPerFile = val; + return pOptions; +} + +static SDatabaseOptions* setDbFsync(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_FSYNC_PERIOD || val > TSDB_MAX_FSYNC_PERIOD) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option fsyncPeriod: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_FSYNC_PERIOD, TSDB_MAX_FSYNC_PERIOD); + pCxt->valid = false; + return pOptions; + } + pOptions->fsyncPeriod = val; + return pOptions; +} + +static SDatabaseOptions* setDbMaxRows(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_MAX_ROW_FBLOCK || val > TSDB_MAX_MAX_ROW_FBLOCK) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option maxRowsPerBlock: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_MAX_ROW_FBLOCK, TSDB_MAX_MAX_ROW_FBLOCK); + pCxt->valid = false; + return pOptions; + } + pOptions->maxRowsPerBlock = val; + return pOptions; +} + +static SDatabaseOptions* setDbMinRows(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_MIN_ROW_FBLOCK || val > TSDB_MAX_MIN_ROW_FBLOCK) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option minRowsPerBlock: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_MIN_ROW_FBLOCK, TSDB_MAX_MIN_ROW_FBLOCK); + pCxt->valid = false; + return pOptions; + } + pOptions->minRowsPerBlock = val; + return pOptions; +} + +static SDatabaseOptions* setDbKeep(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_KEEP || val > TSDB_MAX_KEEP) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option keep: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_KEEP, TSDB_MAX_KEEP); + pCxt->valid = false; + return pOptions; + } + pOptions->keep = val; + return pOptions; +} + +static SDatabaseOptions* setDbPrecision(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + char val[10] = {0}; + trimString(pVal->z, pVal->n, val, sizeof(val)); + if (0 == strcmp(val, TSDB_TIME_PRECISION_MILLI_STR)) { + pOptions->precision = TSDB_TIME_PRECISION_MILLI; + } else if (0 == strcmp(val, TSDB_TIME_PRECISION_MICRO_STR)) { + pOptions->precision = TSDB_TIME_PRECISION_MICRO; + } else if (0 == strcmp(val, TSDB_TIME_PRECISION_NANO_STR)) { + pOptions->precision = TSDB_TIME_PRECISION_NANO; + } else { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid db option precision: %s", val); + pCxt->valid = false; + } + return pOptions; +} + +static SDatabaseOptions* setDbQuorum(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_QUORUM_OPTION || val > TSDB_MAX_DB_QUORUM_OPTION) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option quorum: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_DB_QUORUM_OPTION, TSDB_MAX_DB_QUORUM_OPTION); + pCxt->valid = false; + return pOptions; + } + pOptions->quorum = val; + return pOptions; +} + +static SDatabaseOptions* setDbReplica(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_REPLICA_OPTION || val > TSDB_MAX_DB_REPLICA_OPTION) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option replications: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_DB_REPLICA_OPTION, TSDB_MAX_DB_REPLICA_OPTION); + pCxt->valid = false; + return pOptions; + } + pOptions->replica = val; + return pOptions; +} + +static SDatabaseOptions* setDbTtl(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_TTL_OPTION) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option ttl: %"PRId64", should be greater than or equal to %d", val, TSDB_MIN_DB_TTL_OPTION); + pCxt->valid = false; + return pOptions; + } + pOptions->ttl = val; + return pOptions; +} + +static SDatabaseOptions* setDbWal(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_WAL_LEVEL || val > TSDB_MAX_WAL_LEVEL) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid db option walLevel: %"PRId64", only 1-2 allowed", val); + pCxt->valid = false; + return pOptions; + } + pOptions->walLevel = val; + return pOptions; +} + +static SDatabaseOptions* setDbVgroups(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_VNODES_PER_DB || val > TSDB_MAX_VNODES_PER_DB) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid db option vgroups: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_VNODES_PER_DB, TSDB_MAX_VNODES_PER_DB); + pCxt->valid = false; + return pOptions; + } + pOptions->numOfVgroups = val; + return pOptions; +} + +static SDatabaseOptions* setDbSingleStable(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_SINGLE_STABLE_OPTION || val > TSDB_MAX_DB_SINGLE_STABLE_OPTION) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid db option singleStable: %"PRId64", only 0-1 allowed", val); + pCxt->valid = false; + return pOptions; + } + pOptions->singleStable = val; + return pOptions; +} + +static SDatabaseOptions* setDbStreamMode(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_STREAM_MODE_OPTION || val > TSDB_MAX_DB_STREAM_MODE_OPTION) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid db option streamMode: %"PRId64", only 0-1 allowed", val); + pCxt->valid = false; + return pOptions; + } + pOptions->streamMode = val; + return pOptions; +} + +static void initSetDatabaseOptionFp() { + setDbOptionFuncs[DB_OPTION_BLOCKS] = setDbBlocks; + setDbOptionFuncs[DB_OPTION_CACHE] = setDbCache; + setDbOptionFuncs[DB_OPTION_CACHELAST] = setDbCacheLast; + setDbOptionFuncs[DB_OPTION_COMP] = setDbComp; + setDbOptionFuncs[DB_OPTION_DAYS] = setDbDays; + setDbOptionFuncs[DB_OPTION_FSYNC] = setDbFsync; + setDbOptionFuncs[DB_OPTION_MAXROWS] = setDbMaxRows; + setDbOptionFuncs[DB_OPTION_MINROWS] = setDbMinRows; + setDbOptionFuncs[DB_OPTION_KEEP] = setDbKeep; + setDbOptionFuncs[DB_OPTION_PRECISION] = setDbPrecision; + setDbOptionFuncs[DB_OPTION_QUORUM] = setDbQuorum; + setDbOptionFuncs[DB_OPTION_REPLICA] = setDbReplica; + setDbOptionFuncs[DB_OPTION_TTL] = setDbTtl; + setDbOptionFuncs[DB_OPTION_WAL] = setDbWal; + setDbOptionFuncs[DB_OPTION_VGROUPS] = setDbVgroups; + setDbOptionFuncs[DB_OPTION_SINGLESTABLE] = setDbSingleStable; + setDbOptionFuncs[DB_OPTION_STREAMMODE] = setDbStreamMode; +} + +static STableOptions* setTableKeep(SAstCreateContext* pCxt, STableOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_KEEP || val > TSDB_MAX_KEEP) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid table option keep: %"PRId64" valid range: [%d, %d]", val, TSDB_MIN_KEEP, TSDB_MAX_KEEP); + pCxt->valid = false; + return pOptions; + } + pOptions->keep = val; + return pOptions; +} + +static STableOptions* setTableTtl(SAstCreateContext* pCxt, STableOptions* pOptions, const SToken* pVal) { + int64_t val = strtol(pVal->z, NULL, 10); + if (val < TSDB_MIN_DB_TTL_OPTION) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid table option ttl: %"PRId64", should be greater than or equal to %d", val, TSDB_MIN_DB_TTL_OPTION); + pCxt->valid = false; + return pOptions; + } + pOptions->ttl = val; + return pOptions; +} + +static STableOptions* setTableComment(SAstCreateContext* pCxt, STableOptions* pOptions, const SToken* pVal) { + if (pVal->n >= sizeof(pOptions->comments)) { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, + "invalid table option comment, length cannot exceed %d", (int32_t)(sizeof(pOptions->comments) - 1)); + pCxt->valid = false; + return pOptions; + } + trimString(pVal->z, pVal->n, pOptions->comments, sizeof(pOptions->comments)); + return pOptions; +} + +static void initSetTableOptionFp() { + setTableOptionFuncs[TABLE_OPTION_KEEP] = setTableKeep; + setTableOptionFuncs[TABLE_OPTION_TTL] = setTableTtl; + setTableOptionFuncs[TABLE_OPTION_COMMENT] = setTableComment; +} + +void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt) { + pCxt->pQueryCxt = pParseCxt; + pCxt->msgBuf.buf = pParseCxt->pMsg; + pCxt->msgBuf.len = pParseCxt->msgLen; + pCxt->notSupport = false; + pCxt->valid = true; + pCxt->pRootNode = NULL; + initSetDatabaseOptionFp(); + initSetTableOptionFp(); +} + +static bool checkUserName(SAstCreateContext* pCxt, const SToken* pUserName) { + if (NULL == pUserName) { + return false; + } + if (pUserName->n >= TSDB_USER_LEN) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); + pCxt->valid = false; + } + return pCxt->valid; +} + +static bool checkPassword(SAstCreateContext* pCxt, const SToken* pPasswordToken, char* pPassword) { + if (NULL == pPasswordToken) { + return false; + } + if (pPasswordToken->n >= (TSDB_USET_PASSWORD_LEN - 2)) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); + pCxt->valid = false; + return false; + } + strncpy(pPassword, pPasswordToken->z, pPasswordToken->n); + strdequote(pPassword); + if (strtrim(pPassword) <= 0) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_PASSWD_EMPTY); + pCxt->valid = false; + } + return pCxt->valid; +} + +static bool checkAndSplitEndpoint(SAstCreateContext* pCxt, const SToken* pEp, char* pFqdn, int32_t* pPort) { + if (NULL == pEp) { + return false; + } + if (pEp->n >= TSDB_FQDN_LEN + 2 + 6) { // format 'fqdn:port' + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); + pCxt->valid = false; + } + char ep[TSDB_FQDN_LEN + 2 + 6]; + strncpy(ep, pEp->z, pEp->n); + strdequote(ep); + strtrim(ep); + char* pColon = strchr(ep, ':'); + if (NULL == pColon) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ENDPOINT); + pCxt->valid = false; + } + strncpy(pFqdn, ep, pColon - ep); + *pPort = strtol(pColon + 1, NULL, 10); + if (*pPort >= UINT16_MAX || *pPort <= 0) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT); + pCxt->valid = false; + } + return pCxt->valid; +} + +static bool checkFqdn(SAstCreateContext* pCxt, const SToken* pFqdn) { + if (NULL == pFqdn) { + return false; + } + if (pFqdn->n >= TSDB_FQDN_LEN) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG); + pCxt->valid = false; + } + return pCxt->valid; +} + +static bool checkPort(SAstCreateContext* pCxt, const SToken* pPortToken, int32_t* pPort) { + if (NULL == pPortToken) { + return false; + } + *pPort = strtol(pPortToken->z, NULL, 10); + if (*pPort >= UINT16_MAX || *pPort <= 0) { + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT); + pCxt->valid = false; + } + return pCxt->valid; +} + +static bool checkDbName(SAstCreateContext* pCxt, const SToken* pDbName) { + if (NULL == pDbName) { + return true; + } + pCxt->valid = pDbName->n < TSDB_DB_NAME_LEN ? true : false; + return pCxt->valid; +} + +static bool checkTableName(SAstCreateContext* pCxt, const SToken* pTableName) { + if (NULL == pTableName) { + return true; + } + pCxt->valid = pTableName->n < TSDB_TABLE_NAME_LEN ? true : false; + return pCxt->valid; +} + +static bool checkColumnName(SAstCreateContext* pCxt, const SToken* pColumnName) { + if (NULL == pColumnName) { + return true; + } + pCxt->valid = pColumnName->n < TSDB_COL_NAME_LEN ? true : false; + return pCxt->valid; +} + +SNode* createRawExprNode(SAstCreateContext* pCxt, const SToken* pToken, SNode* pNode) { + SRawExprNode* target = (SRawExprNode*)nodesMakeNode(QUERY_NODE_RAW_EXPR); + CHECK_OUT_OF_MEM(target); + target->p = pToken->z; + target->n = pToken->n; + target->pNode = pNode; + return (SNode*)target; +} + +SNode* createRawExprNodeExt(SAstCreateContext* pCxt, const SToken* pStart, const SToken* pEnd, SNode* pNode) { + SRawExprNode* target = (SRawExprNode*)nodesMakeNode(QUERY_NODE_RAW_EXPR); + CHECK_OUT_OF_MEM(target); + target->p = pStart->z; + target->n = (pEnd->z + pEnd->n) - pStart->z; + target->pNode = pNode; + return (SNode*)target; +} + +SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { + CHECK_RAW_EXPR_NODE(pNode); + SNode* tmp = ((SRawExprNode*)pNode)->pNode; + tfree(pNode); + return tmp; +} + +SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { + if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) { + pCxt->valid = false; + return nil_token; + } + SRawExprNode* target = (SRawExprNode*)pNode; + SToken t = { .type = 0, .z = target->p, .n = target->n}; + return t; +} + +SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) { + SNodeList* list = nodesMakeList(); + CHECK_OUT_OF_MEM(list); + if (TSDB_CODE_SUCCESS != nodesListAppend(list, pNode)) { + pCxt->valid = false; + } + return list; +} + +SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) { + if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pNode)) { + pCxt->valid = false; + } + return pList; +} + +SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableAlias, const SToken* pColumnName) { + if (!checkTableName(pCxt, pTableAlias) || !checkColumnName(pCxt, pColumnName)) { + return NULL; + } + SColumnNode* col = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + CHECK_OUT_OF_MEM(col); + if (NULL != pTableAlias) { + strncpy(col->tableAlias, pTableAlias->z, pTableAlias->n); + } + strncpy(col->colName, pColumnName->z, pColumnName->n); + return (SNode*)col; +} + +SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral) { + SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + CHECK_OUT_OF_MEM(val); + val->literal = strndup(pLiteral->z, pLiteral->n); + CHECK_OUT_OF_MEM(val->literal); + val->node.resType.type = dataType; + val->node.resType.bytes = tDataTypes[dataType].bytes; + if (TSDB_DATA_TYPE_TIMESTAMP == dataType) { + val->node.resType.precision = TSDB_TIME_PRECISION_MILLI; + } + val->isDuration = false; + val->translate = false; + return (SNode*)val; +} + +SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) { + SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + CHECK_OUT_OF_MEM(val); + val->literal = strndup(pLiteral->z, pLiteral->n); + CHECK_OUT_OF_MEM(val->literal); + val->isDuration = true; + val->translate = false; + val->node.resType.type = TSDB_DATA_TYPE_BIGINT; + val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; + val->node.resType.precision = TSDB_TIME_PRECISION_MILLI; + return (SNode*)val; +} + +SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2) { + SLogicConditionNode* cond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); + CHECK_OUT_OF_MEM(cond); + cond->condType = type; + cond->pParameterList = nodesMakeList(); + nodesListAppend(cond->pParameterList, pParam1); + nodesListAppend(cond->pParameterList, pParam2); + return (SNode*)cond; +} + +SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight) { + SOperatorNode* op = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR); + CHECK_OUT_OF_MEM(op); + op->opType = type; + op->pLeft = pLeft; + op->pRight = pRight; + return (SNode*)op; +} + +SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight) { + return createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, + createOperatorNode(pCxt, OP_TYPE_GREATER_EQUAL, pExpr, pLeft), createOperatorNode(pCxt, OP_TYPE_LOWER_EQUAL, nodesCloneNode(pExpr), pRight)); +} + +SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight) { + return createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, + createOperatorNode(pCxt, OP_TYPE_LOWER_THAN, pExpr, pLeft), createOperatorNode(pCxt, OP_TYPE_GREATER_THAN, nodesCloneNode(pExpr), pRight)); +} + +SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList) { + SFunctionNode* func = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); + CHECK_OUT_OF_MEM(func); + strncpy(func->functionName, pFuncName->z, pFuncName->n); + func->pParameterList = pParameterList; + return (SNode*)func; +} + +SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList) { + SNodeListNode* list = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); + CHECK_OUT_OF_MEM(list); + list->pNodeList = pList; + return (SNode*)list; +} + +SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName, const SToken* pTableAlias) { + if (!checkDbName(pCxt, pDbName) || !checkTableName(pCxt, pTableName)) { + return NULL; + } + SRealTableNode* realTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE); + CHECK_OUT_OF_MEM(realTable); + if (NULL != pDbName) { + strncpy(realTable->table.dbName, pDbName->z, pDbName->n); + } else { + strcpy(realTable->table.dbName, pCxt->pQueryCxt->db); + } + if (NULL != pTableAlias && TK_NK_NIL != pTableAlias->type) { + strncpy(realTable->table.tableAlias, pTableAlias->z, pTableAlias->n); + } else { + strncpy(realTable->table.tableAlias, pTableName->z, pTableName->n); + } + strncpy(realTable->table.tableName, pTableName->z, pTableName->n); + return (SNode*)realTable; +} + +SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const SToken* pTableAlias) { + STempTableNode* tempTable = (STempTableNode*)nodesMakeNode(QUERY_NODE_TEMP_TABLE); + CHECK_OUT_OF_MEM(tempTable); + tempTable->pSubquery = pSubquery; + if (NULL != pTableAlias && TK_NK_NIL != pTableAlias->type) { + strncpy(tempTable->table.tableAlias, pTableAlias->z, pTableAlias->n); + } + return (SNode*)tempTable; +} + +SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, SNode* pLeft, SNode* pRight, SNode* pJoinCond) { + SJoinTableNode* joinTable = (SJoinTableNode*)nodesMakeNode(QUERY_NODE_JOIN_TABLE); + CHECK_OUT_OF_MEM(joinTable); + joinTable->joinType = type; + joinTable->pLeft = pLeft; + joinTable->pRight = pRight; + joinTable->pOnCond = pJoinCond; + return (SNode*)joinTable; +} + +SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset) { + SLimitNode* limitNode = (SLimitNode*)nodesMakeNode(QUERY_NODE_LIMIT); + CHECK_OUT_OF_MEM(limitNode); + // limitNode->limit = limit; + // limitNode->offset = offset; + return (SNode*)limitNode; +} + +SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder) { + SOrderByExprNode* orderByExpr = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR); + CHECK_OUT_OF_MEM(orderByExpr); + orderByExpr->pExpr = pExpr; + orderByExpr->order = order; + if (NULL_ORDER_DEFAULT == nullOrder) { + nullOrder = (ORDER_ASC == order ? NULL_ORDER_FIRST : NULL_ORDER_LAST); + } + orderByExpr->nullOrder = nullOrder; + return (SNode*)orderByExpr; +} + +SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, const SToken* pVal) { + SSessionWindowNode* session = (SSessionWindowNode*)nodesMakeNode(QUERY_NODE_SESSION_WINDOW); + CHECK_OUT_OF_MEM(session); + session->pCol = pCol; + // session->gap = getInteger(pVal); + return (SNode*)session; +} + +SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pCol) { + SStateWindowNode* state = (SStateWindowNode*)nodesMakeNode(QUERY_NODE_STATE_WINDOW); + CHECK_OUT_OF_MEM(state); + state->pCol = pCol; + return (SNode*)state; +} + +SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* pFill) { + SIntervalWindowNode* interval = (SIntervalWindowNode*)nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW); + CHECK_OUT_OF_MEM(interval); + interval->pInterval = pInterval; + interval->pOffset = pOffset; + interval->pSliding = pSliding; + interval->pFill = pFill; + return (SNode*)interval; +} + +SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) { + SFillNode* fill = (SFillNode*)nodesMakeNode(QUERY_NODE_FILL); + CHECK_OUT_OF_MEM(fill); + fill->mode = mode; + fill->pValues = pValues; + return (SNode*)fill; +} + +SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) { + SGroupingSetNode* groupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET); + CHECK_OUT_OF_MEM(groupingSet); + groupingSet->groupingSetType = GP_TYPE_NORMAL; + groupingSet->pParameterList = nodesMakeList(); + nodesListAppend(groupingSet->pParameterList, pNode); + return (SNode*)groupingSet; +} + +SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) { + if (NULL == pNode || !pCxt->valid) { + return pNode; + } + uint32_t maxLen = sizeof(((SExprNode*)pNode)->aliasName); + strncpy(((SExprNode*)pNode)->aliasName, pAlias->z, pAlias->n > maxLen ? maxLen : pAlias->n); + return pNode; +} + +SNode* addWhereClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWhere) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pWhere = pWhere; + } + return pStmt; +} + +SNode* addPartitionByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pPartitionByList) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pPartitionByList = pPartitionByList; + } + return pStmt; +} + +SNode* addWindowClauseClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWindow) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pWindow = pWindow; + } + return pStmt; +} + +SNode* addGroupByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pGroupByList) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pGroupByList = pGroupByList; + } + return pStmt; +} + +SNode* addHavingClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pHaving) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pHaving = pHaving; + } + return pStmt; +} + +SNode* addOrderByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrderByList) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pOrderByList = pOrderByList; + } + return pStmt; +} + +SNode* addSlimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pSlimit = pSlimit; + } + return pStmt; +} + +SNode* addLimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit) { + if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { + ((SSelectStmt*)pStmt)->pLimit = pLimit; + } + return pStmt; +} + +SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable) { + SSelectStmt* select = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT); + CHECK_OUT_OF_MEM(select); + select->isDistinct = isDistinct; + select->pProjectionList = pProjectionList; + select->pFromTable = pTable; + return (SNode*)select; +} + +SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) { + SSetOperator* setOp = (SSetOperator*)nodesMakeNode(QUERY_NODE_SET_OPERATOR); + CHECK_OUT_OF_MEM(setOp); + setOp->opType = type; + setOp->pLeft = pLeft; + setOp->pRight = pRight; + return (SNode*)setOp; +} + +SDatabaseOptions* createDefaultDatabaseOptions(SAstCreateContext* pCxt) { + SDatabaseOptions* pOptions = calloc(1, sizeof(SDatabaseOptions)); + CHECK_OUT_OF_MEM(pOptions); + pOptions->numOfBlocks = TSDB_DEFAULT_TOTAL_BLOCKS; + pOptions->cacheBlockSize = TSDB_DEFAULT_CACHE_BLOCK_SIZE; + pOptions->cachelast = TSDB_DEFAULT_CACHE_LAST_ROW; + pOptions->compressionLevel = TSDB_DEFAULT_COMP_LEVEL; + pOptions->daysPerFile = TSDB_DEFAULT_DAYS_PER_FILE; + pOptions->fsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD; + pOptions->maxRowsPerBlock = TSDB_DEFAULT_MAX_ROW_FBLOCK; + pOptions->minRowsPerBlock = TSDB_DEFAULT_MIN_ROW_FBLOCK; + pOptions->keep = TSDB_DEFAULT_KEEP; + pOptions->precision = TSDB_TIME_PRECISION_MILLI; + pOptions->quorum = TSDB_DEFAULT_DB_QUORUM_OPTION; + pOptions->replica = TSDB_DEFAULT_DB_REPLICA_OPTION; + pOptions->ttl = TSDB_DEFAULT_DB_TTL_OPTION; + pOptions->walLevel = TSDB_DEFAULT_WAL_LEVEL; + pOptions->numOfVgroups = TSDB_DEFAULT_VN_PER_DB; + pOptions->singleStable = TSDB_DEFAULT_DB_SINGLE_STABLE_OPTION; + pOptions->streamMode = TSDB_DEFAULT_DB_STREAM_MODE_OPTION; + return pOptions; +} + +SDatabaseOptions* setDatabaseOption(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, EDatabaseOptionType type, const SToken* pVal) { + return setDbOptionFuncs[type](pCxt, pOptions, pVal); +} + +SNode* createCreateDatabaseStmt(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pDbName, SDatabaseOptions* pOptions) { + if (!checkDbName(pCxt, pDbName)) { + return NULL; + } + SCreateDatabaseStmt* pStmt = (SCreateDatabaseStmt*)nodesMakeNode(QUERY_NODE_CREATE_DATABASE_STMT); + CHECK_OUT_OF_MEM(pStmt); + strncpy(pStmt->dbName, pDbName->z, pDbName->n); + pStmt->ignoreExists = ignoreExists; + pStmt->options = *pOptions; + tfree(pOptions); + return (SNode*)pStmt; +} + +SNode* createDropDatabaseStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pDbName) { + if (!checkDbName(pCxt, pDbName)) { + return NULL; + } + SDropDatabaseStmt* pStmt = (SDropDatabaseStmt*)nodesMakeNode(QUERY_NODE_DROP_DATABASE_STMT); + CHECK_OUT_OF_MEM(pStmt); + strncpy(pStmt->dbName, pDbName->z, pDbName->n); + pStmt->ignoreNotExists = ignoreNotExists; + return (SNode*)pStmt; +} + +STableOptions* createDefaultTableOptions(SAstCreateContext* pCxt) { + STableOptions* pOptions = calloc(1, sizeof(STableOptions)); + CHECK_OUT_OF_MEM(pOptions); + pOptions->keep = TSDB_DEFAULT_KEEP; + pOptions->ttl = TSDB_DEFAULT_DB_TTL_OPTION; + return pOptions; +} + +STableOptions* setTableOption(SAstCreateContext* pCxt, STableOptions* pOptions, ETableOptionType type, const SToken* pVal) { + return setTableOptionFuncs[type](pCxt, pOptions, pVal); +} + +STableOptions* setTableSmaOption(SAstCreateContext* pCxt, STableOptions* pOptions, SNodeList* pSma) { + pOptions->pSma = pSma; + return pOptions; +} + +SNode* createColumnDefNode(SAstCreateContext* pCxt, const SToken* pColName, SDataType dataType, const SToken* pComment) { + SColumnDefNode* pCol = (SColumnDefNode*)nodesMakeNode(QUERY_NODE_COLUMN_DEF); + CHECK_OUT_OF_MEM(pCol); + strncpy(pCol->colName, pColName->z, pColName->n); + pCol->dataType = dataType; + if (NULL != pComment) { + trimString(pComment->z, pComment->n, pCol->comments, sizeof(pCol->comments)); + } + return (SNode*)pCol; +} + +SDataType createDataType(uint8_t type) { + SDataType dt = { .type = type, .precision = 0, .scale = 0, .bytes = tDataTypes[type].bytes }; + return dt; +} + +SDataType createVarLenDataType(uint8_t type, const SToken* pLen) { + SDataType dt = { .type = type, .precision = 0, .scale = 0, .bytes = tDataTypes[type].bytes }; + return dt; +} + +SNode* createCreateTableStmt(SAstCreateContext* pCxt, + bool ignoreExists, SNode* pRealTable, SNodeList* pCols, SNodeList* pTags, STableOptions* pOptions) { + SCreateTableStmt* pStmt = (SCreateTableStmt*)nodesMakeNode(QUERY_NODE_CREATE_TABLE_STMT); + CHECK_OUT_OF_MEM(pStmt); + strcpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName); + strcpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName); + pStmt->ignoreExists = ignoreExists; + pStmt->pCols = pCols; + pStmt->pTags = pTags; + pStmt->options = *pOptions; + nodesDestroyList(pOptions->pSma); + tfree(pOptions); + nodesDestroyNode(pRealTable); + return (SNode*)pStmt; +} + +SNode* createCreateSubTableClause(SAstCreateContext* pCxt, + bool ignoreExists, SNode* pRealTable, SNode* pUseRealTable, SNodeList* pSpecificTags, SNodeList* pValsOfTags) { + SCreateSubTableClause* pStmt = nodesMakeNode(QUERY_NODE_CREATE_SUBTABLE_CLAUSE); + CHECK_OUT_OF_MEM(pStmt); + strcpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName); + strcpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName); + strcpy(pStmt->useDbName, ((SRealTableNode*)pUseRealTable)->table.dbName); + strcpy(pStmt->useTableName, ((SRealTableNode*)pUseRealTable)->table.tableName); + pStmt->ignoreExists = ignoreExists; + pStmt->pSpecificTags = pSpecificTags; + pStmt->pValsOfTags = pValsOfTags; + nodesDestroyNode(pRealTable); + nodesDestroyNode(pUseRealTable); + return (SNode*)pStmt; +} + +SNode* createCreateMultiTableStmt(SAstCreateContext* pCxt, SNodeList* pSubTables) { + SCreateMultiTableStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_MULTI_TABLE_STMT); + CHECK_OUT_OF_MEM(pStmt); + pStmt->pSubTables = pSubTables; + return (SNode*)pStmt; +} + +SNode* createDropTableClause(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable) { + SDropTableClause* pStmt = nodesMakeNode(QUERY_NODE_DROP_TABLE_CLAUSE); + CHECK_OUT_OF_MEM(pStmt); + strcpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName); + strcpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName); + pStmt->ignoreNotExists = ignoreNotExists; + nodesDestroyNode(pRealTable); + return (SNode*)pStmt; +} + +SNode* createDropTableStmt(SAstCreateContext* pCxt, SNodeList* pTables) { + SDropTableStmt* pStmt = nodesMakeNode(QUERY_NODE_DROP_TABLE_STMT); + CHECK_OUT_OF_MEM(pStmt); + pStmt->pTables = pTables; + return (SNode*)pStmt; +} + +SNode* createDropSuperTableStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable) { + SDropSuperTableStmt* pStmt = nodesMakeNode(QUERY_NODE_DROP_SUPER_TABLE_STMT); + CHECK_OUT_OF_MEM(pStmt); + strcpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName); + strcpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName); + pStmt->ignoreNotExists = ignoreNotExists; + nodesDestroyNode(pRealTable); + return (SNode*)pStmt; +} + +SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, const SToken* pDbName) { + SUseDatabaseStmt* pStmt = (SUseDatabaseStmt*)nodesMakeNode(QUERY_NODE_USE_DATABASE_STMT); + CHECK_OUT_OF_MEM(pStmt); + strncpy(pStmt->dbName, pDbName->z, pDbName->n); + return (SNode*)pStmt; +} + +SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDbName) { + if (!checkDbName(pCxt, pDbName)) { + return NULL; + } + SShowStmt* pStmt = nodesMakeNode(type);; + CHECK_OUT_OF_MEM(pStmt); + if (NULL != pDbName) { + strncpy(pStmt->dbName, pDbName->z, pDbName->n); + } else if (NULL != pCxt->pQueryCxt->db) { + strcpy(pStmt->dbName, pCxt->pQueryCxt->db); + } + return (SNode*)pStmt; +} + +SNode* createCreateUserStmt(SAstCreateContext* pCxt, const SToken* pUserName, const SToken* pPassword) { + char password[TSDB_USET_PASSWORD_LEN] = {0}; + if (!checkUserName(pCxt, pUserName) || !checkPassword(pCxt, pPassword, password)) { + return NULL; + } + SCreateUserStmt* pStmt = (SCreateUserStmt*)nodesMakeNode(QUERY_NODE_CREATE_USER_STMT); + CHECK_OUT_OF_MEM(pStmt); + strncpy(pStmt->useName, pUserName->z, pUserName->n); + strcpy(pStmt->password, password); + return (SNode*)pStmt; +} + +SNode* createAlterUserStmt(SAstCreateContext* pCxt, const SToken* pUserName, int8_t alterType, const SToken* pVal) { + if (!checkUserName(pCxt, pUserName)) { + return NULL; + } + SAlterUserStmt* pStmt = (SAlterUserStmt*)nodesMakeNode(QUERY_NODE_ALTER_USER_STMT); + CHECK_OUT_OF_MEM(pStmt); + strncpy(pStmt->useName, pUserName->z, pUserName->n); + if (TSDB_ALTER_USER_PASSWD == alterType) { + char password[TSDB_USET_PASSWORD_LEN] = {0}; + if (!checkPassword(pCxt, pVal, password)) { + nodesDestroyNode(pStmt); + return NULL; + } + strcpy(pStmt->password, password); + } + pStmt->alterType = alterType; + return (SNode*)pStmt; +} + +SNode* createDropUserStmt(SAstCreateContext* pCxt, const SToken* pUserName) { + if (!checkUserName(pCxt, pUserName)) { + return NULL; + } + SDropUserStmt* pStmt = (SDropUserStmt*)nodesMakeNode(QUERY_NODE_DROP_USER_STMT); + CHECK_OUT_OF_MEM(pStmt); + strncpy(pStmt->useName, pUserName->z, pUserName->n); + return (SNode*)pStmt; +} + +SNode* createCreateDnodeStmt(SAstCreateContext* pCxt, const SToken* pFqdn, const SToken* pPort) { + int32_t port = 0; + char fqdn[TSDB_FQDN_LEN] = {0}; + if (NULL == pPort) { + if (!checkAndSplitEndpoint(pCxt, pFqdn, fqdn, &port)) { + return NULL; + } + } else if (!checkFqdn(pCxt, pFqdn) || !checkPort(pCxt, pPort, &port)) { + return NULL; + } + SCreateDnodeStmt* pStmt = (SCreateDnodeStmt*)nodesMakeNode(QUERY_NODE_CREATE_DNODE_STMT); + CHECK_OUT_OF_MEM(pStmt); + if (NULL == pPort) { + strcpy(pStmt->fqdn, fqdn); + } else { + strncpy(pStmt->fqdn, pFqdn->z, pFqdn->n); + } + pStmt->port = port; + return (SNode*)pStmt; +} + +SNode* createDropDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode) { + SDropDnodeStmt* pStmt = (SDropDnodeStmt*)nodesMakeNode(QUERY_NODE_DROP_DNODE_STMT); + CHECK_OUT_OF_MEM(pStmt); + if (TK_NK_INTEGER == pDnode->type) { + pStmt->dnodeId = strtol(pDnode->z, NULL, 10); + } else { + if (!checkAndSplitEndpoint(pCxt, pDnode, pStmt->fqdn, &pStmt->port)) { + nodesDestroyNode(pStmt); + return NULL; + } + } + return (SNode*)pStmt; +} diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c new file mode 100644 index 0000000000000000000000000000000000000000..e992f150aae875eb2620dcd5f40c347054f9f820 --- /dev/null +++ b/source/libs/parser/src/parAstParser.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "parInt.h" + +#include "parAst.h" +#include "parToken.h" + +typedef void* (*FMalloc)(size_t); +typedef void (*FFree)(void*); + +extern void* ParseAlloc(FMalloc); +extern void Parse(void*, int, SToken, void*); +extern void ParseFree(void*, FFree); +extern void ParseTrace(FILE*, char*); + +int32_t doParse(SParseContext* pParseCxt, SQuery** pQuery) { + SAstCreateContext cxt; + initAstCreateContext(pParseCxt, &cxt); + void *pParser = ParseAlloc(malloc); + int32_t i = 0; + while (1) { + SToken t0 = {0}; + if (cxt.pQueryCxt->pSql[i] == 0) { + Parse(pParser, 0, t0, &cxt); + goto abort_parse; + } + t0.n = tGetToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type); + t0.z = (char *)(cxt.pQueryCxt->pSql + i); + i += t0.n; + + switch (t0.type) { + case TK_NK_SPACE: + case TK_NK_COMMENT: { + break; + } + case TK_NK_SEMI: { + Parse(pParser, 0, t0, &cxt); + goto abort_parse; + } + case TK_NK_QUESTION: + case TK_NK_ILLEGAL: { + snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z); + cxt.valid = false; + goto abort_parse; + } + case TK_NK_HEX: + case TK_NK_OCT: + case TK_NK_BIN: { + snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unsupported token: \"%s\"", t0.z); + cxt.valid = false; + goto abort_parse; + } + default: + Parse(pParser, t0.type, t0, &cxt); + // ParseTrace(stdout, ""); + if (!cxt.valid) { + goto abort_parse; + } + } + } + +abort_parse: + ParseFree(pParser, free); + if (cxt.valid) { + *pQuery = calloc(1, sizeof(SQuery)); + if (NULL == *pQuery) { + return TSDB_CODE_OUT_OF_MEMORY; + } + (*pQuery)->pRoot = cxt.pRootNode; + } + return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; +} diff --git a/source/libs/parser/src/insertParser.c b/source/libs/parser/src/parInsert.c similarity index 60% rename from source/libs/parser/src/insertParser.c rename to source/libs/parser/src/parInsert.c index 4b58bc4e696dbea92a9851888801e4f529f13638..43cc30848365c11322a4495ab14291e2e01bf453 100644 --- a/source/libs/parser/src/insertParser.c +++ b/source/libs/parser/src/parInsert.c @@ -13,15 +13,12 @@ * along with this program. If not, see . */ -#include "insertParser.h" - -#include "dataBlockMgt.h" -#include "parserInt.h" -#include "parserUtil.h" -#include "queryInfoUtil.h" +#include "parInsertData.h" +#include "parInt.h" +#include "parUtil.h" +#include "parToken.h" #include "tglobal.h" #include "ttime.h" -#include "ttoken.h" #include "ttypes.h" #define NEXT_TOKEN(pSql, sToken) \ @@ -61,9 +58,14 @@ typedef struct SInsertParseContext { SArray* pTableDataBlocks; // global SArray* pVgDataBlocks; // global int32_t totalNum; - SVnodeModifOpStmtInfo* pOutput; + SVnodeModifOpStmt* pOutput; } SInsertParseContext; +typedef int32_t (*_row_append_fn_t)(const void *value, int32_t len, void *param); + +static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE; +static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE; + static int32_t skipInsertInto(SInsertParseContext* pCxt) { SToken sToken; NEXT_TOKEN(pCxt->pSql, sToken); @@ -77,6 +79,68 @@ static int32_t skipInsertInto(SInsertParseContext* pCxt) { return TSDB_CODE_SUCCESS; } +static int32_t parserValidateIdToken(SToken* pToken) { + if (pToken == NULL || pToken->z == NULL || pToken->type != TK_NK_ID) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + // it is a token quoted with escape char '`' + if (pToken->z[0] == TS_ESCAPE_CHAR && pToken->z[pToken->n - 1] == TS_ESCAPE_CHAR) { + return TSDB_CODE_SUCCESS; + } + + char* sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true); + if (sep == NULL) { // It is a single part token, not a complex type + if (isNumber(pToken)) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + strntolower(pToken->z, pToken->z, pToken->n); + } else { // two part + int32_t oldLen = pToken->n; + char* pStr = pToken->z; + + if (pToken->type == TK_NK_SPACE) { + pToken->n = (uint32_t)strtrim(pToken->z); + } + + pToken->n = tGetToken(pToken->z, &pToken->type); + if (pToken->z[pToken->n] != TS_PATH_DELIMITER[0]) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + if (pToken->type != TK_NK_ID) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + int32_t firstPartLen = pToken->n; + + pToken->z = sep + 1; + pToken->n = (uint32_t)(oldLen - (sep - pStr) - 1); + int32_t len = tGetToken(pToken->z, &pToken->type); + if (len != pToken->n || pToken->type != TK_NK_ID) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + // re-build the whole name string + if (pStr[firstPartLen] == TS_PATH_DELIMITER[0]) { + // first part do not have quote do nothing + } else { + pStr[firstPartLen] = TS_PATH_DELIMITER[0]; + memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n); + uint32_t offset = (uint32_t)(pToken->z - (pStr + firstPartLen + 1)); + memset(pToken->z + pToken->n - offset, ' ', offset); + } + + pToken->n += (firstPartLen + sizeof(TS_PATH_DELIMITER[0])); + pToken->z = pStr; + + strntolower(pToken->z, pToken->z, pToken->n); + } + + return TSDB_CODE_SUCCESS; +} + static int32_t buildName(SInsertParseContext* pCxt, SToken* pStname, char* fullDbName, char* tableName) { if (parserValidateIdToken(pStname) != TSDB_CODE_SUCCESS) { return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pStname->z); @@ -95,13 +159,70 @@ static int32_t buildName(SInsertParseContext* pCxt, SToken* pStname, char* fullD return TSDB_CODE_SUCCESS; } -static int32_t getTableMeta(SInsertParseContext* pCxt, SToken* pTname) { - SName name = {0}; - createSName(&name, pTname, pCxt->pComCxt, &pCxt->msg); +static int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) { + const char* msg1 = "name too long"; + const char* msg2 = "invalid database name"; + const char* msg3 = "db is not specified"; + + int32_t code = TSDB_CODE_SUCCESS; + char* p = strnchr(pTableName->z, TS_PATH_DELIMITER[0], pTableName->n, true); + + if (p != NULL) { // db has been specified in sql string so we ignore current db path + assert(*p == TS_PATH_DELIMITER[0]); + + int32_t dbLen = p - pTableName->z; + char name[TSDB_DB_FNAME_LEN] = {0}; + strncpy(name, pTableName->z, dbLen); + dbLen = strdequote(name); - char tableName[TSDB_TABLE_FNAME_LEN] = {0}; - tNameExtractFullName(&name, tableName); + code = tNameSetDbName(pName, pParseCtx->acctId, name, dbLen); + if (code != TSDB_CODE_SUCCESS) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + + int32_t tbLen = pTableName->n - dbLen - 1; + char tbname[TSDB_TABLE_FNAME_LEN] = {0}; + strncpy(tbname, p + 1, tbLen); + /*tbLen = */strdequote(tbname); + + code = tNameFromString(pName, tbname, T_NAME_TABLE); + if (code != 0) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + } else { // get current DB name first, and then set it into path + if (pTableName->n >= TSDB_TABLE_NAME_LEN) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + + assert(pTableName->n < TSDB_TABLE_FNAME_LEN); + + char name[TSDB_TABLE_FNAME_LEN] = {0}; + strncpy(name, pTableName->z, pTableName->n); + strdequote(name); + + if (pParseCtx->db == NULL) { + return buildInvalidOperationMsg(pMsgBuf, msg3); + } + + code = tNameSetDbName(pName, pParseCtx->acctId, pParseCtx->db, strlen(pParseCtx->db)); + if (code != TSDB_CODE_SUCCESS) { + code = buildInvalidOperationMsg(pMsgBuf, msg2); + return code; + } + + code = tNameFromString(pName, name, T_NAME_TABLE); + if (code != 0) { + code = buildInvalidOperationMsg(pMsgBuf, msg1); + } + } + + return code; +} + +static int32_t getTableMeta(SInsertParseContext* pCxt, SToken* pTname) { SParseContext* pBasicCtx = pCxt->pComCxt; + SName name = {0}; + createSName(&name, pTname, pBasicCtx, &pCxt->msg); CHECK_CODE(catalogGetTableMeta(pBasicCtx->pCatalog, pBasicCtx->pTransporter, &pBasicCtx->mgmtEpSet, &name, &pCxt->pTableMeta)); SVgroupInfo vg; CHECK_CODE(catalogGetTableHashVgroup(pBasicCtx->pCatalog, pBasicCtx->pTransporter, &pBasicCtx->mgmtEpSet, &name, &vg)); @@ -200,7 +321,7 @@ static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time if (pToken->type == TK_NOW) { ts = taosGetTimestamp(timePrec); - } else if (pToken->type == TK_INTEGER) { + } else if (pToken->type == TK_NK_INTEGER) { bool isSigned = false; toInteger(pToken->z, pToken->n, 10, &ts, &isSigned); } else { // parse the RFC-3339/ISO-8601 timestamp format string @@ -231,7 +352,7 @@ static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time sToken = tStrGetToken(pTokenEnd, &index, false); pTokenEnd += index; - if (sToken.type == TK_MINUS || sToken.type == TK_PLUS) { + if (sToken.type == TK_MINUS || sToken.type == TK_NK_PLUS) { index = 0; valueToken = tStrGetToken(pTokenEnd, &index, false); pTokenEnd += index; @@ -245,7 +366,7 @@ static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time return TSDB_CODE_TSC_INVALID_OPERATION; } - if (sToken.type == TK_PLUS) { + if (sToken.type == TK_NK_PLUS) { ts += interval; } else { ts = ts - interval; @@ -258,6 +379,231 @@ static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time return TSDB_CODE_SUCCESS; } +static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, uint32_t type, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { + if ((pToken->type != TK_NOW && pToken->type != TK_NK_INTEGER && pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL && + pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN) || + (pToken->n == 0) || (pToken->type == TK_NK_RP)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); + } + + if (IS_NUMERIC_TYPE(type) && pToken->n == 0) { + return buildSyntaxErrMsg(pMsgBuf, "invalid numeric data", pToken->z); + } + + // Remove quotation marks + if (TSDB_DATA_TYPE_BINARY == type) { + if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { + return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z); + } + + // delete escape character: \\, \', \" + char delim = pToken->z[0]; + int32_t cnt = 0; + int32_t j = 0; + for (uint32_t k = 1; k < pToken->n - 1; ++k) { + if (pToken->z[k] == '\\' || (pToken->z[k] == delim && pToken->z[k + 1] == delim)) { + tmpTokenBuf[j] = pToken->z[k + 1]; + cnt++; + j++; + k++; + continue; + } + tmpTokenBuf[j] = pToken->z[k]; + j++; + } + + tmpTokenBuf[j] = 0; + pToken->z = tmpTokenBuf; + pToken->n -= 2 + cnt; + } + + return TSDB_CODE_SUCCESS; +} + +static bool isNullStr(SToken *pToken) { + return (pToken->type == TK_NULL) || ((pToken->type == TK_NK_STRING) && (pToken->n != 0) && + (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0)); +} + +static FORCE_INLINE int32_t toDouble(SToken *pToken, double *value, char **endPtr) { + errno = 0; + *value = strtold(pToken->z, endPtr); + + // not a valid integer number, return error + if ((*endPtr - pToken->z) != pToken->n) { + return TK_NK_ILLEGAL; + } + + return pToken->type; +} + +static int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf) { + int64_t iv; + char *endptr = NULL; + bool isSigned = false; + + int32_t code = checkAndTrimValue(pToken, pSchema->type, tmpTokenBuf, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + if (isNullStr(pToken)) { + if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { + int64_t tmpVal = 0; + return func(&tmpVal, pSchema->bytes, param); + } + + return func(getNullValue(pSchema->type), 0, param); + } + + switch (pSchema->type) { + case TSDB_DATA_TYPE_BOOL: { + if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) { + if (strncmp(pToken->z, "true", pToken->n) == 0) { + return func(&TRUE_VALUE, pSchema->bytes, param); + } else if (strncmp(pToken->z, "false", pToken->n) == 0) { + return func(&FALSE_VALUE, pSchema->bytes, param); + } else { + return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); + } + } else if (pToken->type == TK_NK_INTEGER) { + return func(((strtoll(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); + } else if (pToken->type == TK_NK_FLOAT) { + return func(((strtod(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); + } else { + return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); + } + } + + case TSDB_DATA_TYPE_TINYINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z); + } else if (!IS_VALID_TINYINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z); + } + + uint8_t tmpVal = (uint8_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_UTINYINT:{ + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z); + } else if (!IS_VALID_UTINYINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z); + } + uint8_t tmpVal = (uint8_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_SMALLINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z); + } else if (!IS_VALID_SMALLINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z); + } + int16_t tmpVal = (int16_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_USMALLINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z); + } else if (!IS_VALID_USMALLINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z); + } + uint16_t tmpVal = (uint16_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_INT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z); + } else if (!IS_VALID_INT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z); + } + int32_t tmpVal = (int32_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_UINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z); + } else if (!IS_VALID_UINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z); + } + uint32_t tmpVal = (uint32_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_BIGINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z); + } else if (!IS_VALID_BIGINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "bigint data overflow", pToken->z); + } + return func(&iv, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_UBIGINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z); + } else if (!IS_VALID_UBIGINT((uint64_t)iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned bigint data overflow", pToken->z); + } + uint64_t tmpVal = (uint64_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_FLOAT: { + double dv; + if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); + } + if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); + } + float tmpVal = (float)dv; + return func(&tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_DOUBLE: { + double dv; + if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); + } + if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); + } + return func(&dv, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_BINARY: { + // Too long values will raise the invalid sql error message + if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { + return buildSyntaxErrMsg(pMsgBuf, "string data overflow", pToken->z); + } + + return func(pToken->z, pToken->n, param); + } + + case TSDB_DATA_TYPE_NCHAR: { + return func(pToken->z, pToken->n, param); + } + + case TSDB_DATA_TYPE_TIMESTAMP: { + int64_t tmpVal; + if (parseTime(end, pToken, timePrec, &tmpVal, pMsgBuf) != TSDB_CODE_SUCCESS) { + return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z); + } + + return func(&tmpVal, pSchema->bytes, param); + } + } + + return TSDB_CODE_FAILED; +} + typedef struct SMemParam { SRowBuilder* rb; SSchema* schema; @@ -304,7 +650,7 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo* while (1) { NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_RP == sToken.type) { + if (TK_NK_RP == sToken.type) { break; } @@ -361,6 +707,37 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo* return TSDB_CODE_SUCCESS; } +typedef struct SKvParam { + SKVRowBuilder *builder; + SSchema *schema; + char buf[TSDB_MAX_TAGS_LEN]; +} SKvParam; + +static int32_t KvRowAppend(const void *value, int32_t len, void *param) { + SKvParam* pa = (SKvParam*) param; + + int32_t type = pa->schema->type; + int32_t colId = pa->schema->colId; + + if (TSDB_DATA_TYPE_BINARY == type) { + STR_WITH_SIZE_TO_VARSTR(pa->buf, value, len); + tdAddColToKVRow(pa->builder, colId, type, pa->buf); + } else if (TSDB_DATA_TYPE_NCHAR == type) { + // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long' + int32_t output = 0; + if (!taosMbsToUcs4(value, len, varDataVal(pa->buf), pa->schema->bytes - VARSTR_HEADER_SIZE, &output)) { + return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; + } + + varDataSetLen(pa->buf, output); + tdAddColToKVRow(pa->builder, colId, type, pa->buf); + } else { + tdAddColToKVRow(pa->builder, colId, type, value); + } + + return TSDB_CODE_SUCCESS; +} + // pSql -> tag1_value, ...) static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pTagsSchema, uint8_t precision) { if (tdInitKVRowBuilder(&pCxt->tagsBuilder) < 0) { @@ -404,7 +781,7 @@ static int32_t parseUsingClause(SInsertParseContext* pCxt, SToken* pTbnameToken) // pSql -> [(tag1_name, ...)] TAGS (tag1_value, ...) NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_LP == sToken.type) { + if (TK_NK_LP == sToken.type) { CHECK_CODE(parseBoundColumns(pCxt, &pCxt->tags, pTagsSchema)); NEXT_TOKEN(pCxt->pSql, sToken); } @@ -414,7 +791,7 @@ static int32_t parseUsingClause(SInsertParseContext* pCxt, SToken* pTbnameToken) } // pSql -> (tag1_value, ...) NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_LP != sToken.type) { + if (TK_NK_LP != sToken.type) { return buildSyntaxErrMsg(&pCxt->msg, "( is expected", sToken.z); } CHECK_CODE(parseTagsClause(pCxt, pTagsSchema, getTableInfo(pCxt->pTableMeta).precision)); @@ -478,7 +855,7 @@ static int32_t parseValues(SInsertParseContext* pCxt, STableDataBlocks* pDataBlo while (1) { int32_t index = 0; NEXT_TOKEN_KEEP_SQL(pCxt->pSql, sToken, index); - if (TK_LP != sToken.type) { + if (TK_NK_LP != sToken.type) { break; } pCxt->pSql += index; @@ -495,7 +872,7 @@ static int32_t parseValues(SInsertParseContext* pCxt, STableDataBlocks* pDataBlo pDataBlock->size += extendedRowSize; //len; NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_RP != sToken.type) { + if (TK_NK_RP != sToken.type) { return buildSyntaxErrMsg(&pCxt->msg, ") expected", sToken.z); } @@ -594,7 +971,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) { CHECK_CODE(getDataBlockFromList(pCxt->pTableBlockHashObj, pCxt->pTableMeta->uid, TSDB_DEFAULT_PAYLOAD_SIZE, sizeof(SSubmitBlk), getTableInfo(pCxt->pTableMeta).rowSize, pCxt->pTableMeta, &dataBuf, NULL)); - if (TK_LP == sToken.type) { + if (TK_NK_LP == sToken.type) { // pSql -> field1_name, ...) CHECK_CODE(parseBoundColumns(pCxt, &dataBuf->boundColumnInfo, getTableColumnSchema(pCxt->pTableMeta))); NEXT_TOKEN(pCxt->pSql, sToken); @@ -608,10 +985,10 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) { } // FILE csv_file_path - if (TK_FILE == sToken.type) { + if (TK_NK_FILE == sToken.type) { // pSql -> csv_file_path NEXT_TOKEN(pCxt->pSql, sToken); - if (0 == sToken.n || (TK_STRING != sToken.type && TK_ID != sToken.type)) { + if (0 == sToken.n || (TK_NK_STRING != sToken.type && TK_NK_ID != sToken.type)) { return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", sToken.z); } // todo @@ -634,7 +1011,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) { // [(field1_name, ...)] // VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path // [...]; -int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo) { +int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery) { SInsertParseContext context = { .pComCxt = pContext, .pSql = (char*) pContext->pSql, @@ -643,7 +1020,7 @@ int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo) { .pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false), .pTableBlockHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false), .totalNum = 0, - .pOutput = calloc(1, sizeof(SVnodeModifOpStmtInfo)) + .pOutput = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT) }; if (NULL == context.pVgroupsHashObj || NULL == context.pTableBlockHashObj || NULL == context.pOutput) { @@ -651,8 +1028,14 @@ int32_t parseInsertSql(SParseContext* pContext, SVnodeModifOpStmtInfo** pInfo) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } - *pInfo = context.pOutput; - context.pOutput->nodeType = TSDB_SQL_INSERT; + *pQuery = calloc(1, sizeof(SQuery)); + if (NULL == *pQuery) { + return TSDB_CODE_OUT_OF_MEMORY; + } + (*pQuery)->directRpc = false; + (*pQuery)->haveResultSet = false; + (*pQuery)->msgType = TDMT_VND_SUBMIT; + (*pQuery)->pRoot = (SNode*)context.pOutput; context.pOutput->payloadType = PAYLOAD_TYPE_KV; int32_t code = skipInsertInto(&context); diff --git a/source/libs/parser/src/dataBlockMgt.c b/source/libs/parser/src/parInsertData.c similarity index 99% rename from source/libs/parser/src/dataBlockMgt.c rename to source/libs/parser/src/parInsertData.c index 381dec4f15562b4d2596222e4767c0dfe6585272..da5a652018f7066b7f176462e5ad633cfb834bd1 100644 --- a/source/libs/parser/src/dataBlockMgt.c +++ b/source/libs/parser/src/parInsertData.c @@ -13,12 +13,11 @@ * along with this program. If not, see . */ -#include "dataBlockMgt.h" +#include "parInsertData.h" #include "catalog.h" -#include "parserUtil.h" -#include "queryInfoUtil.h" -#include "tmsg.h" +#include "parUtil.h" +#include "querynodes.h" #define IS_RAW_PAYLOAD(t) \ (((int)(t)) == PAYLOAD_TYPE_RAW) // 0: K-V payload for non-prepare insert, 1: rawPayload for prepare insert diff --git a/source/libs/parser/src/ttokenizer.c b/source/libs/parser/src/parTokenizer.c similarity index 53% rename from source/libs/parser/src/ttokenizer.c rename to source/libs/parser/src/parTokenizer.c index d54da5aa26f20168623c7a63fa67798161811e95..eefa99dae0436834e60e72c5ddbe1e716a2ba4c9 100644 --- a/source/libs/parser/src/ttokenizer.c +++ b/source/libs/parser/src/parTokenizer.c @@ -14,10 +14,9 @@ */ #include "os.h" - +#include "parToken.h" #include "thash.h" #include "taosdef.h" -#include "ttoken.h" #include "ttokendef.h" // All the keywords of the SQL language are stored in a hash table @@ -29,208 +28,214 @@ typedef struct SKeyword { // keywords in sql string static SKeyword keywordTable[] = { - {"ID", TK_ID}, - {"BOOL", TK_BOOL}, -// {"TINYINT", TK_TINYINT}, -// {"SMALLINT", TK_SMALLINT}, - {"INTEGER", TK_INTEGER}, - {"INT", TK_INTEGER}, -// {"BIGINT", TK_BIGINT}, - {"FLOAT", TK_FLOAT}, -// {"DOUBLE", TK_DOUBLE}, - {"STRING", TK_STRING}, - {"TIMESTAMP", TK_TIMESTAMP}, -// {"BINARY", TK_BINARY}, -// {"NCHAR", TK_NCHAR}, - {"OR", TK_OR}, - {"AND", TK_AND}, - {"NOT", TK_NOT}, - {"EQ", TK_EQ}, - {"NE", TK_NE}, - {"ISNULL", TK_ISNULL}, - {"NOTNULL", TK_NOTNULL}, - {"IS", TK_IS}, - {"LIKE", TK_LIKE}, - {"MATCH", TK_MATCH}, - {"GLOB", TK_GLOB}, - {"BETWEEN", TK_BETWEEN}, - {"IN", TK_IN}, - {"GT", TK_GT}, - {"GE", TK_GE}, - {"LT", TK_LT}, - {"LE", TK_LE}, - {"BITAND", TK_BITAND}, - {"BITOR", TK_BITOR}, - {"LSHIFT", TK_LSHIFT}, - {"RSHIFT", TK_RSHIFT}, - {"PLUS", TK_PLUS}, - {"MINUS", TK_MINUS}, - {"DIVIDE", TK_DIVIDE}, - {"TIMES", TK_TIMES}, - {"STAR", TK_STAR}, - {"SLASH", TK_SLASH}, - {"REM ", TK_REM}, - {"||", TK_CONCAT}, - {"UMINUS", TK_UMINUS}, - {"UPLUS", TK_UPLUS}, - {"BITNOT", TK_BITNOT}, - {"SHOW", TK_SHOW}, - {"DATABASES", TK_DATABASES}, - {"MNODES", TK_MNODES}, - {"DNODES", TK_DNODES}, - {"ACCOUNTS", TK_ACCOUNTS}, - {"USERS", TK_USERS}, - {"MODULES", TK_MODULES}, - {"QUERIES", TK_QUERIES}, - {"CONNECTIONS", TK_CONNECTIONS}, - {"STREAMS", TK_STREAMS}, - {"VARIABLES", TK_VARIABLES}, - {"SCORES", TK_SCORES}, - {"GRANTS", TK_GRANTS}, - {"DOT", TK_DOT}, - {"TABLES", TK_TABLES}, - {"STABLES", TK_STABLES}, - {"VGROUPS", TK_VGROUPS}, - {"DROP", TK_DROP}, - {"TABLE", TK_TABLE}, - {"DATABASE", TK_DATABASE}, - {"DNODE", TK_DNODE}, - {"USER", TK_USER}, - {"ACCOUNT", TK_ACCOUNT}, - {"USE", TK_USE}, - {"DESCRIBE", TK_DESCRIBE}, - {"SYNCDB", TK_SYNCDB}, - {"ALTER", TK_ALTER}, - {"PASS", TK_PASS}, - {"PRIVILEGE", TK_PRIVILEGE}, - {"LOCAL", TK_LOCAL}, - {"IF", TK_IF}, - {"EXISTS", TK_EXISTS}, - {"CREATE", TK_CREATE}, - {"PPS", TK_PPS}, - {"TSERIES", TK_TSERIES}, - {"DBS", TK_DBS}, - {"STORAGE", TK_STORAGE}, - {"QTIME", TK_QTIME}, - {"CONNS", TK_CONNS}, - {"STATE", TK_STATE}, - {"KEEP", TK_KEEP}, - {"REPLICA", TK_REPLICA}, - {"QUORUM", TK_QUORUM}, - {"DAYS", TK_DAYS}, - {"MINROWS", TK_MINROWS}, - {"MAXROWS", TK_MAXROWS}, - {"BLOCKS", TK_BLOCKS}, - {"CACHE", TK_CACHE}, - {"CTIME", TK_CTIME}, - {"WAL", TK_WAL}, - {"FSYNC", TK_FSYNC}, - {"COMP", TK_COMP}, - {"PRECISION", TK_PRECISION}, - {"LP", TK_LP}, - {"RP", TK_RP}, - {"UNSIGNED", TK_UNSIGNED}, - {"TAGS", TK_TAGS}, - {"USING", TK_USING}, - {"AS", TK_AS}, - {"COMMA", TK_COMMA}, - {"NULL", TK_NULL}, - {"SELECT", TK_SELECT}, - {"EVERY", TK_EVERY}, - {"FROM", TK_FROM}, - {"VARIABLE", TK_VARIABLE}, - {"INTERVAL", TK_INTERVAL}, - {"SESSION", TK_SESSION}, - {"STATE_WINDOW", TK_STATE_WINDOW}, - {"FILL", TK_FILL}, - {"SLIDING", TK_SLIDING}, - {"ORDER", TK_ORDER}, - {"BY", TK_BY}, - {"ASC", TK_ASC}, - {"DESC", TK_DESC}, - {"GROUP", TK_GROUP}, - {"HAVING", TK_HAVING}, - {"LIMIT", TK_LIMIT}, - {"OFFSET", TK_OFFSET}, - {"SLIMIT", TK_SLIMIT}, - {"SOFFSET", TK_SOFFSET}, - {"WHERE", TK_WHERE}, - {"NOW", TK_NOW}, - {"INSERT", TK_INSERT}, - {"INTO", TK_INTO}, - {"VALUES", TK_VALUES}, - {"UPDATE", TK_UPDATE}, - {"RESET", TK_RESET}, - {"QUERY", TK_QUERY}, - {"ADD", TK_ADD}, - {"COLUMN", TK_COLUMN}, - {"TAG", TK_TAG}, - {"CHANGE", TK_CHANGE}, - {"SET", TK_SET}, - {"KILL", TK_KILL}, - {"CONNECTION", TK_CONNECTION}, - {"COLON", TK_COLON}, - {"STREAM", TK_STREAM}, - {"ABORT", TK_ABORT}, - {"AFTER", TK_AFTER}, - {"ATTACH", TK_ATTACH}, - {"BEFORE", TK_BEFORE}, - {"BEGIN", TK_BEGIN}, - {"CASCADE", TK_CASCADE}, - {"CLUSTER", TK_CLUSTER}, - {"CONFLICT", TK_CONFLICT}, - {"COPY", TK_COPY}, - {"DEFERRED", TK_DEFERRED}, - {"DELIMITERS", TK_DELIMITERS}, - {"DETACH", TK_DETACH}, - {"EACH", TK_EACH}, - {"END", TK_END}, - {"EXPLAIN", TK_EXPLAIN}, - {"FAIL", TK_FAIL}, - {"FOR", TK_FOR}, - {"IGNORE", TK_IGNORE}, - {"IMMEDIATE", TK_IMMEDIATE}, - {"INITIALLY", TK_INITIALLY}, - {"INSTEAD", TK_INSTEAD}, - {"MATCH", TK_MATCH}, - {"NMATCH", TK_NMATCH}, - {"KEY", TK_KEY}, - {"OF", TK_OF}, - {"RAISE", TK_RAISE}, - {"REPLACE", TK_REPLACE}, - {"RESTRICT", TK_RESTRICT}, - {"ROW", TK_ROW}, - {"STATEMENT", TK_STATEMENT}, - {"TRIGGER", TK_TRIGGER}, - {"VIEW", TK_VIEW}, - {"ALL", TK_ALL}, - {"SEMI", TK_SEMI}, - {"NONE", TK_NONE}, - {"PREV", TK_PREV}, - {"LINEAR", TK_LINEAR}, - {"IMPORT", TK_IMPORT}, - {"TBNAME", TK_TBNAME}, - {"JOIN", TK_JOIN}, - {"STABLE", TK_STABLE}, - {"FILE", TK_FILE}, - {"VNODES", TK_VNODES}, - {"UNION", TK_UNION}, - {"CACHELAST", TK_CACHELAST}, - {"DISTINCT", TK_DISTINCT}, + {"ALL", TK_ALL}, + {"ALTER", TK_ALTER}, + {"AND", TK_AND}, + {"AS", TK_AS}, + {"ASC", TK_ASC}, + {"BETWEEN", TK_BETWEEN}, + {"BINARY", TK_BINARY}, + {"BIGINT", TK_BIGINT}, + {"BLOCKS", TK_BLOCKS}, + {"BOOL", TK_BOOL}, + {"BY", TK_BY}, + {"CACHE", TK_CACHE}, + {"CACHELAST", TK_CACHELAST}, + {"COMMENT", TK_COMMENT}, + {"COMP", TK_COMP}, + {"CREATE", TK_CREATE}, + {"DATABASE", TK_DATABASE}, + {"DATABASES", TK_DATABASES}, + {"DAYS", TK_DAYS}, + {"DESC", TK_DESC}, + {"DISTINCT", TK_DISTINCT}, + {"DNODE", TK_DNODE}, + {"DNODES", TK_DNODES}, + {"DOUBLE", TK_DOUBLE}, + {"DROP", TK_DROP}, + {"EXISTS", TK_EXISTS}, + // {"FILE", TK_FILE}, + {"FILL", TK_FILL}, + {"FLOAT", TK_FLOAT}, + {"FROM", TK_FROM}, + {"FSYNC", TK_FSYNC}, + {"GROUP", TK_GROUP}, + {"HAVING", TK_HAVING}, + {"IF", TK_IF}, + {"IMPORT", TK_IMPORT}, + {"IN", TK_IN}, + {"INNER", TK_INNER}, + {"INT", TK_INT}, + {"INSERT", TK_INSERT}, + {"INTEGER", TK_INTEGER}, + {"INTERVAL", TK_INTERVAL}, + {"INTO", TK_INTO}, + {"IS", TK_IS}, + {"JOIN", TK_JOIN}, + {"JSON", TK_JSON}, + {"KEEP", TK_KEEP}, + {"LIKE", TK_LIKE}, + {"LIMIT", TK_LIMIT}, + {"LINEAR", TK_LINEAR}, + {"MATCH", TK_MATCH}, + {"MAXROWS", TK_MAXROWS}, + {"MINROWS", TK_MINROWS}, + {"MINUS", TK_MINUS}, + {"MNODES", TK_MNODES}, + {"NCHAR", TK_NCHAR}, + {"NMATCH", TK_NMATCH}, + {"NONE", TK_NONE}, + {"NOT", TK_NOT}, + {"NOW", TK_NOW}, + {"NULL", TK_NULL}, + {"OFFSET", TK_OFFSET}, + {"ON", TK_ON}, + {"OR", TK_OR}, + {"ORDER", TK_ORDER}, + {"PASS", TK_PASS}, + {"PORT", TK_PORT}, + {"PRECISION", TK_PRECISION}, + {"PRIVILEGE", TK_PRIVILEGE}, + {"PREV", TK_PREV}, + {"QUORUM", TK_QUORUM}, + {"REPLICA", TK_REPLICA}, + {"SELECT", TK_SELECT}, + {"SESSION", TK_SESSION}, + {"SHOW", TK_SHOW}, + {"SINGLE_STABLE", TK_SINGLE_STABLE}, + {"SLIDING", TK_SLIDING}, + {"SLIMIT", TK_SLIMIT}, + {"SMA", TK_SMA}, + {"SMALLINT", TK_SMALLINT}, + {"SOFFSET", TK_SOFFSET}, + {"STABLE", TK_STABLE}, + {"STABLES", TK_STABLES}, + {"STATE_WINDOW", TK_STATE_WINDOW}, + {"STREAM_MODE", TK_STREAM_MODE}, + {"TABLE", TK_TABLE}, + {"TABLES", TK_TABLES}, + {"TAGS", TK_TAGS}, + {"TIMESTAMP", TK_TIMESTAMP}, + {"TINYINT", TK_TINYINT}, + {"TTL", TK_TTL}, + {"UNION", TK_UNION}, + {"UNSIGNED", TK_UNSIGNED}, + {"USE", TK_USE}, + {"USER", TK_USER}, + {"USERS", TK_USERS}, + {"USING", TK_USING}, + {"VALUES", TK_VALUES}, + {"VARCHAR", TK_VARCHAR}, + {"VGROUPS", TK_VGROUPS}, + {"WAL", TK_WAL}, + {"WHERE", TK_WHERE}, + // {"ID", TK_ID}, + // {"STRING", TK_STRING}, + // {"EQ", TK_EQ}, + // {"NE", TK_NE}, + // {"ISNULL", TK_ISNULL}, + // {"NOTNULL", TK_NOTNULL}, + // {"GLOB", TK_GLOB}, + // {"GT", TK_GT}, + // {"GE", TK_GE}, + // {"LT", TK_LT}, + // {"LE", TK_LE}, + // {"BITAND", TK_BITAND}, + // {"BITOR", TK_BITOR}, + // {"LSHIFT", TK_LSHIFT}, + // {"RSHIFT", TK_RSHIFT}, + // {"PLUS", TK_PLUS}, + // {"DIVIDE", TK_DIVIDE}, + // {"TIMES", TK_TIMES}, + // {"STAR", TK_STAR}, + // {"SLASH", TK_SLASH}, + // {"REM ", TK_REM}, + // {"||", TK_CONCAT}, + // {"UMINUS", TK_UMINUS}, + // {"UPLUS", TK_UPLUS}, + // {"BITNOT", TK_BITNOT}, + // {"ACCOUNTS", TK_ACCOUNTS}, + // {"MODULES", TK_MODULES}, + // {"QUERIES", TK_QUERIES}, + // {"CONNECTIONS", TK_CONNECTIONS}, + // {"STREAMS", TK_STREAMS}, + // {"VARIABLES", TK_VARIABLES}, + // {"SCORES", TK_SCORES}, + // {"GRANTS", TK_GRANTS}, + // {"DOT", TK_DOT}, + // {"ACCOUNT", TK_ACCOUNT}, + // {"DESCRIBE", TK_DESCRIBE}, + // {"SYNCDB", TK_SYNCDB}, + // {"LOCAL", TK_LOCAL}, + // {"PPS", TK_PPS}, + // {"TSERIES", TK_TSERIES}, + // {"DBS", TK_DBS}, + // {"STORAGE", TK_STORAGE}, + // {"QTIME", TK_QTIME}, + // {"CONNS", TK_CONNS}, + // {"STATE", TK_STATE}, + // {"CTIME", TK_CTIME}, + // {"LP", TK_LP}, + // {"RP", TK_RP}, + // {"COMMA", TK_COMMA}, + // {"EVERY", TK_EVERY}, + // {"VARIABLE", TK_VARIABLE}, + // {"UPDATE", TK_UPDATE}, + // {"RESET", TK_RESET}, + // {"QUERY", TK_QUERY}, + // {"ADD", TK_ADD}, + // {"COLUMN", TK_COLUMN}, + // {"TAG", TK_TAG}, + // {"CHANGE", TK_CHANGE}, + // {"SET", TK_SET}, + // {"KILL", TK_KILL}, + // {"CONNECTION", TK_CONNECTION}, + // {"COLON", TK_COLON}, + // {"STREAM", TK_STREAM}, + // {"ABORT", TK_ABORT}, + // {"AFTER", TK_AFTER}, + // {"ATTACH", TK_ATTACH}, + // {"BEFORE", TK_BEFORE}, + // {"BEGIN", TK_BEGIN}, + // {"CASCADE", TK_CASCADE}, + // {"CLUSTER", TK_CLUSTER}, + // {"CONFLICT", TK_CONFLICT}, + // {"COPY", TK_COPY}, + // {"DEFERRED", TK_DEFERRED}, + // {"DELIMITERS", TK_DELIMITERS}, + // {"DETACH", TK_DETACH}, + // {"EACH", TK_EACH}, + // {"END", TK_END}, + // {"EXPLAIN", TK_EXPLAIN}, + // {"FAIL", TK_FAIL}, + // {"FOR", TK_FOR}, + // {"IGNORE", TK_IGNORE}, + // {"IMMEDIATE", TK_IMMEDIATE}, + // {"INITIALLY", TK_INITIALLY}, + // {"INSTEAD", TK_INSTEAD}, + // {"KEY", TK_KEY}, + // {"OF", TK_OF}, + // {"RAISE", TK_RAISE}, + // {"REPLACE", TK_REPLACE}, + // {"RESTRICT", TK_RESTRICT}, + // {"ROW", TK_ROW}, + // {"STATEMENT", TK_STATEMENT}, + // {"TRIGGER", TK_TRIGGER}, + // {"VIEW", TK_VIEW}, + // {"SEMI", TK_SEMI}, + // {"TBNAME", TK_TBNAME}, + // {"VNODES", TK_VNODES}, // {"PARTITIONS", TK_PARTITIONS}, - {"TOPIC", TK_TOPIC}, - {"TOPICS", TK_TOPICS}, - {"COMPACT", TK_COMPACT}, - {"MODIFY", TK_MODIFY}, - {"FUNCTION", TK_FUNCTION}, - {"FUNCTIONS", TK_FUNCTIONS}, - {"OUTPUTTYPE", TK_OUTPUTTYPE}, - {"AGGREGATE", TK_AGGREGATE}, - {"BUFSIZE", TK_BUFSIZE}, - {"PORT", TK_PORT}, - {"INNER", NEW_TK_INNER}, - {"ON", NEW_TK_ON}, - {"MODE", TK_MODE}, + // {"TOPIC", TK_TOPIC}, + // {"TOPICS", TK_TOPICS}, + // {"COMPACT", TK_COMPACT}, + // {"MODIFY", TK_MODIFY}, + // {"FUNCTION", TK_FUNCTION}, + // {"FUNCTIONS", TK_FUNCTIONS}, + // {"OUTPUTTYPE", TK_OUTPUTTYPE}, + // {"AGGREGATE", TK_AGGREGATE}, + // {"BUFSIZE", TK_BUFSIZE}, + // {"MODE", TK_MODE}, }; static const char isIdChar[] = { @@ -265,7 +270,7 @@ static int32_t tKeywordCode(const char* z, int n) { char key[512] = {0}; if (n > tListLen(key)) { // too long token, can not be any other token type - return TK_ID; + return TK_NK_ID; } for (int32_t j = 0; j < n; ++j) { @@ -277,11 +282,11 @@ static int32_t tKeywordCode(const char* z, int n) { } if (keywordHashTable == NULL) { - return TK_ILLEGAL; + return TK_NK_ILLEGAL; } SKeyword** pKey = (SKeyword**)taosHashGet(keywordHashTable, key, n); - return (pKey != NULL)? (*pKey)->type:TK_ID; + return (pKey != NULL)? (*pKey)->type:TK_NK_ID; } /* @@ -298,121 +303,121 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { case '\r': { for (i = 1; isspace(z[i]); i++) { } - *tokenId = TK_SPACE; + *tokenId = TK_NK_SPACE; return i; } case ':': { - *tokenId = TK_COLON; + *tokenId = TK_NK_COLON; return 1; } case '-': { if (z[1] == '-') { for (i = 2; z[i] && z[i] != '\n'; i++) { } - *tokenId = TK_COMMENT; + *tokenId = TK_NK_COMMENT; return i; } *tokenId = TK_MINUS; return 1; } case '(': { - *tokenId = TK_LP; + *tokenId = TK_NK_LP; return 1; } case ')': { - *tokenId = TK_RP; + *tokenId = TK_NK_RP; return 1; } case ';': { - *tokenId = TK_SEMI; + *tokenId = TK_NK_SEMI; return 1; } case '+': { - *tokenId = TK_PLUS; + *tokenId = TK_NK_PLUS; return 1; } case '*': { - *tokenId = TK_STAR; + *tokenId = TK_NK_STAR; return 1; } case '/': { if (z[1] != '*' || z[2] == 0) { - *tokenId = TK_SLASH; + *tokenId = TK_NK_SLASH; return 1; } for (i = 3; z[i] && (z[i] != '/' || z[i - 1] != '*'); i++) { } if (z[i]) i++; - *tokenId = TK_COMMENT; + *tokenId = TK_NK_COMMENT; return i; } case '%': { - *tokenId = TK_REM; + *tokenId = TK_NK_REM; return 1; } case '=': { - *tokenId = TK_EQ; + *tokenId = TK_NK_EQ; return 1 + (z[1] == '='); } case '<': { if (z[1] == '=') { - *tokenId = TK_LE; + *tokenId = TK_NK_LE; return 2; } else if (z[1] == '>') { - *tokenId = TK_NE; + *tokenId = TK_NK_NE; return 2; } else if (z[1] == '<') { - *tokenId = TK_LSHIFT; + *tokenId = TK_NK_LSHIFT; return 2; } else { - *tokenId = TK_LT; + *tokenId = TK_NK_LT; return 1; } } case '>': { if (z[1] == '=') { - *tokenId = TK_GE; + *tokenId = TK_NK_GE; return 2; } else if (z[1] == '>') { - *tokenId = TK_RSHIFT; + *tokenId = TK_NK_RSHIFT; return 2; } else { - *tokenId = TK_GT; + *tokenId = TK_NK_GT; return 1; } } case '!': { if (z[1] != '=') { - *tokenId = TK_ILLEGAL; + *tokenId = TK_NK_ILLEGAL; return 2; } else { - *tokenId = TK_NE; + *tokenId = TK_NK_NE; return 2; } } case '|': { if (z[1] != '|') { - *tokenId = TK_BITOR; + *tokenId = TK_NK_BITOR; return 1; } else { - *tokenId = TK_CONCAT; + *tokenId = TK_NK_CONCAT; return 2; } } case ',': { - *tokenId = TK_COMMA; + *tokenId = TK_NK_COMMA; return 1; } case '&': { - *tokenId = TK_BITAND; + *tokenId = TK_NK_BITAND; return 1; } case '~': { - *tokenId = TK_BITNOT; + *tokenId = TK_NK_BITNOT; return 1; } case '?': { - *tokenId = TK_QUESTION; + *tokenId = TK_NK_QUESTION; return 1; } case '`': @@ -439,7 +444,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { if (z[i]) i++; if (strEnd) { - *tokenId = (delim == '`')? TK_ID:TK_STRING; + *tokenId = (delim == '`')? TK_NK_ID:TK_NK_STRING; return i; } @@ -463,10 +468,10 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { } } - *tokenId = TK_FLOAT; + *tokenId = TK_NK_FLOAT; return i; } else { - *tokenId = TK_DOT; + *tokenId = TK_NK_DOT; return 1; } } @@ -475,7 +480,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { char next = z[1]; if (next == 'b') { // bin number - *tokenId = TK_BIN; + *tokenId = TK_NK_BIN; for (i = 2; (z[i] == '0' || z[i] == '1'); ++i) { } @@ -485,7 +490,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { return i; } else if (next == 'x') { //hex number - *tokenId = TK_HEX; + *tokenId = TK_NK_HEX; for (i = 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) { } @@ -505,7 +510,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { case '7': case '8': case '9': { - *tokenId = TK_INTEGER; + *tokenId = TK_NK_INTEGER; for (i = 1; isdigit(z[i]); i++) { } @@ -515,7 +520,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { z[i] == 'B' || z[i] == 'U' || z[i] == 'A' || z[i] == 'S' || z[i] == 'M' || z[i] == 'H' || z[i] == 'D' || z[i] == 'N' || z[i] == 'Y' || z[i] == 'W') && (isIdChar[(uint8_t)z[i + 1]] == 0)) { - *tokenId = TK_VARIABLE; + *tokenId = TK_NK_VARIABLE; i += 1; return i; } @@ -526,12 +531,12 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { while (isdigit(z[i])) { i++; } - *tokenId = TK_FLOAT; + *tokenId = TK_NK_FLOAT; seg++; } if (seg == 4) { // ip address - *tokenId = TK_IPTOKEN; + *tokenId = TK_NK_IPTOKEN; return i; } @@ -541,14 +546,14 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { while (isdigit(z[i])) { i++; } - *tokenId = TK_FLOAT; + *tokenId = TK_NK_FLOAT; } return i; } case '[': { for (i = 1; z[i] && z[i - 1] != ']'; i++) { } - *tokenId = TK_ID; + *tokenId = TK_NK_ID; return i; } case 'T': @@ -559,7 +564,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { } if ((i == 4 && strncasecmp(z, "true", 4) == 0) || (i == 5 && strncasecmp(z, "false", 5) == 0)) { - *tokenId = TK_BOOL; + *tokenId = TK_NK_BOOL; return i; } } @@ -574,7 +579,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { } } - *tokenId = TK_ILLEGAL; + *tokenId = TK_NK_ILLEGAL; return 0; } @@ -608,7 +613,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { return t0; } - // IGNORE TK_SPACE, TK_COMMA, and specified tokens + // IGNORE TK_NK_SPACE, TK_NK_COMMA, and specified tokens while (1) { *i += t0.n; @@ -642,7 +647,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { #endif } - if (t0.type == TK_SEMI) { + if (t0.type == TK_NK_SEMI) { t0.n = 0; return t0; } @@ -655,8 +660,8 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { len = tGetToken(&str[*i + t0.n + 1], &type); // only id and string are valid - if ((TK_STRING != t0.type) && (TK_ID != t0.type)) { - t0.type = TK_ILLEGAL; + if ((TK_NK_STRING != t0.type) && (TK_NK_ID != t0.type)) { + t0.type = TK_NK_ILLEGAL; t0.n = 0; return t0; @@ -666,9 +671,9 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { } else { // support parse the -/+number format - if ((isPrevOptr) && (t0.type == TK_MINUS || t0.type == TK_PLUS)) { + if ((isPrevOptr) && (t0.type == TK_MINUS || t0.type == TK_NK_PLUS)) { len = tGetToken(&str[*i + t0.n], &type); - if (type == TK_INTEGER || type == TK_FLOAT) { + if (type == TK_NK_INTEGER || type == TK_NK_FLOAT) { t0.type = type; t0.n += len; } @@ -682,7 +687,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { } bool taosIsKeyWordToken(const char* z, int32_t len) { - return (tKeywordCode((char*)z, len) != TK_ID); + return (tKeywordCode((char*)z, len) != TK_NK_ID); } void taosCleanupKeywordsTable() { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c new file mode 100644 index 0000000000000000000000000000000000000000..c1ba59dd8409b70cd81b6bb085149b8853ac8849 --- /dev/null +++ b/source/libs/parser/src/parTranslater.c @@ -0,0 +1,1676 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "parInt.h" + +#include "catalog.h" +#include "cmdnodes.h" +#include "functionMgt.h" +#include "parUtil.h" +#include "ttime.h" + +static bool afterGroupBy(ESqlClause clause) { + return clause > SQL_CLAUSE_GROUP_BY; +} + +static bool beforeHaving(ESqlClause clause) { + return clause < SQL_CLAUSE_HAVING; +} + +typedef struct STranslateContext { + SParseContext* pParseCxt; + int32_t errCode; + SMsgBuf msgBuf; + SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode* + int32_t currLevel; + ESqlClause currClause; + SSelectStmt* pCurrStmt; + SCmdMsgInfo* pCmdMsg; +} STranslateContext; + +static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode); + +static EDealRes generateDealNodeErrMsg(STranslateContext* pCxt, int32_t errCode, ...) { + va_list vArgList; + va_start(vArgList, errCode); + generateSyntaxErrMsg(&pCxt->msgBuf, errCode, vArgList); + va_end(vArgList); + pCxt->errCode = errCode; + return DEAL_RES_ERROR; +} + +static int32_t addNamespace(STranslateContext* pCxt, void* pTable) { + size_t currTotalLevel = taosArrayGetSize(pCxt->pNsLevel); + if (currTotalLevel > pCxt->currLevel) { + SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + taosArrayPush(pTables, &pTable); + } else { + do { + SArray* pTables = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); + if (pCxt->currLevel == currTotalLevel) { + taosArrayPush(pTables, &pTable); + } + taosArrayPush(pCxt->pNsLevel, &pTables); + ++currTotalLevel; + } while (currTotalLevel <= pCxt->currLevel); + } + return TSDB_CODE_SUCCESS; +} + +static SName* toName(int32_t acctId, const SRealTableNode* pRealTable, SName* pName) { + pName->type = TSDB_TABLE_NAME_T; + pName->acctId = acctId; + strcpy(pName->dbname, pRealTable->table.dbName); + strcpy(pName->tname, pRealTable->table.tableName); + return pName; +} + +static bool belongTable(const char* currentDb, const SColumnNode* pCol, const STableNode* pTable) { + int cmp = 0; + if ('\0' != pCol->dbName[0]) { + cmp = strcmp(pCol->dbName, pTable->dbName); + } else { + cmp = (QUERY_NODE_REAL_TABLE == nodeType(pTable) ? strcmp(currentDb, pTable->dbName) : 0); + } + if (0 == cmp) { + cmp = strcmp(pCol->tableAlias, pTable->tableAlias); + } + return (0 == cmp); +} + +static SNodeList* getProjectList(SNode* pNode) { + if (QUERY_NODE_SELECT_STMT == nodeType(pNode)) { + return ((SSelectStmt*)pNode)->pProjectionList; + } + return NULL; +} + +static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, bool isTag, SColumnNode* pCol) { + strcpy(pCol->dbName, pTable->table.dbName); + strcpy(pCol->tableAlias, pTable->table.tableAlias); + strcpy(pCol->tableName, pTable->table.tableName); + strcpy(pCol->colName, pColSchema->name); + if ('\0' == pCol->node.aliasName[0]) { + strcpy(pCol->node.aliasName, pColSchema->name); + } + pCol->tableId = pTable->pMeta->uid; + pCol->colId = pColSchema->colId; + pCol->colType = isTag ? COLUMN_TYPE_TAG : COLUMN_TYPE_COLUMN; + pCol->node.resType.type = pColSchema->type; + pCol->node.resType.bytes = pColSchema->bytes; +} + +static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode* pCol) { + pCol->pProjectRef = (SNode*)pExpr; + nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); + if (NULL != pTable) { + strcpy(pCol->tableAlias, pTable->tableAlias); + } + strcpy(pCol->colName, pExpr->aliasName); + pCol->node.resType = pExpr->resType; +} + +static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode* pTable, SNodeList* pList) { + if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { + const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; + int32_t nums = pMeta->tableInfo.numOfColumns + ((TSDB_SUPER_TABLE == pMeta->tableType)? pMeta->tableInfo.numOfTags:0); + for (int32_t i = 0; i < nums; ++i) { + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY); + } + setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i >= pMeta->tableInfo.numOfColumns), pCol); + nodesListAppend(pList, (SNode*)pCol); + } + } else { + SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery); + SNode* pNode; + FOREACH(pNode, pProjectList) { + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY); + } + setColumnInfoByExpr(pTable, (SExprNode*)pNode, pCol); + nodesListAppend(pList, (SNode*)pCol); + } + } + return TSDB_CODE_SUCCESS; +} + +static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) { + bool found = false; + if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { + const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; + int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns; + for (int32_t i = 0; i < nums; ++i) { + if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) { + setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i >= pMeta->tableInfo.numOfColumns), pCol); + found = true; + break; + } + } + } else { + SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery); + SNode* pNode; + FOREACH(pNode, pProjectList) { + SExprNode* pExpr = (SExprNode*)pNode; + if (0 == strcmp(pCol->colName, pExpr->aliasName)) { + setColumnInfoByExpr(pTable, pExpr, pCol); + found = true; + break; + } + } + } + return found; +} + +static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol) { + SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + size_t nums = taosArrayGetSize(pTables); + bool foundTable = false; + for (size_t i = 0; i < nums; ++i) { + STableNode* pTable = taosArrayGetP(pTables, i); + if (belongTable(pCxt->pParseCxt->db, pCol, pTable)) { + foundTable = true; + if (findAndSetColumn(pCol, pTable)) { + break; + } + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName); + } + } + if (!foundTable) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_TABLE_NOT_EXIST, pCol->tableAlias); + } + return DEAL_RES_CONTINUE; +} + +static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNode* pCol) { + SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + size_t nums = taosArrayGetSize(pTables); + bool found = false; + for (size_t i = 0; i < nums; ++i) { + STableNode* pTable = taosArrayGetP(pTables, i); + if (findAndSetColumn(pCol, pTable)) { + if (found) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName); + } + found = true; + } + } + if (!found) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName); + } + return DEAL_RES_CONTINUE; +} + +static bool translateColumnUseAlias(STranslateContext* pCxt, SColumnNode* pCol) { + SNodeList* pProjectionList = pCxt->pCurrStmt->pProjectionList; + SNode* pNode; + FOREACH(pNode, pProjectionList) { + SExprNode* pExpr = (SExprNode*)pNode; + if (0 == strcmp(pCol->colName, pExpr->aliasName)) { + setColumnInfoByExpr(NULL, pExpr, pCol); + return true; + } + } + return false; +} + +static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode* pCol) { + // count(*)/first(*)/last(*) + if (0 == strcmp(pCol->colName, "*")) { + return DEAL_RES_CONTINUE; + } + if ('\0' != pCol->tableAlias[0]) { + return translateColumnWithPrefix(pCxt, pCol); + } + bool found = false; + if (SQL_CLAUSE_ORDER_BY == pCxt->currClause) { + found = translateColumnUseAlias(pCxt, pCol); + } + return found ? DEAL_RES_CONTINUE : translateColumnWithoutPrefix(pCxt, pCol); +} + +static int32_t trimStringWithVarFormat(const char* src, int32_t len, bool format, char* dst) { + char* dstVal = dst; + if (format) { + varDataSetLen(dst, len); + dstVal = varDataVal(dst); + } + return trimString(src, len, dstVal, len); +} + +static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) { + if (pVal->isDuration) { + char unit = 0; + if (parseAbsoluteDuration(pVal->literal, strlen(pVal->literal), &pVal->datum.i, &unit, pVal->node.resType.precision) != TSDB_CODE_SUCCESS) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal); + } + } else { + switch (pVal->node.resType.type) { + case TSDB_DATA_TYPE_NULL: + break; + case TSDB_DATA_TYPE_BOOL: + pVal->datum.b = (0 == strcasecmp(pVal->literal, "true")); + break; + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_BIGINT: { + char* endPtr = NULL; + pVal->datum.i = strtoll(pVal->literal, &endPtr, 10); + break; + } + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_UBIGINT: { + char* endPtr = NULL; + pVal->datum.u = strtoull(pVal->literal, &endPtr, 10); + break; + } + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_DOUBLE: { + char* endPtr = NULL; + pVal->datum.d = strtold(pVal->literal, &endPtr); + break; + } + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_VARBINARY: { + int32_t n = strlen(pVal->literal); + pVal->datum.p = calloc(1, n + VARSTR_HEADER_SIZE); + if (NULL == pVal->datum.p) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); + } + trimStringWithVarFormat(pVal->literal, n, true, pVal->datum.p); + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: { + int32_t n = strlen(pVal->literal); + char* tmp = calloc(1, n); + if (NULL == tmp) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); + } + int32_t len = trimStringWithVarFormat(pVal->literal, n, false, tmp); + if (taosParseTime(tmp, &pVal->datum.i, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) { + tfree(tmp); + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal); + } + tfree(tmp); + break; + } + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + // todo + default: + break; + } + } + pVal->translate = true; + return DEAL_RES_CONTINUE; +} + +static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) { + SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType; + SDataType rdt = ((SExprNode*)(pOp->pRight))->resType; + if (nodesIsArithmeticOp(pOp)) { + if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || + TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); + } + pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE; + pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; + } else if (nodesIsComparisonOp(pOp)) { + if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || + TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); + } + pOp->node.resType.type = TSDB_DATA_TYPE_BOOL; + pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; + } else { + // todo json operator + } + return DEAL_RES_CONTINUE; +} + +static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) { + if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName); + } + int32_t code = fmGetFuncResultType(pFunc); + if (TSDB_CODE_SUCCESS != code) { + return generateDealNodeErrMsg(pCxt, code, pFunc->functionName); + } + if (fmIsAggFunc(pFunc->funcId) && beforeHaving(pCxt->currClause)) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION); + } + return DEAL_RES_CONTINUE; +} + +static EDealRes translateExprSubquery(STranslateContext* pCxt, SNode* pNode) { + return (TSDB_CODE_SUCCESS == translateSubquery(pCxt, pNode) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR); +} + +static EDealRes translateLogicCond(STranslateContext* pCxt, SLogicConditionNode* pCond) { + pCond->node.resType.type = TSDB_DATA_TYPE_BOOL; + pCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; + return DEAL_RES_CONTINUE; +} + +static EDealRes doTranslateExpr(SNode* pNode, void* pContext) { + STranslateContext* pCxt = (STranslateContext*)pContext; + switch (nodeType(pNode)) { + case QUERY_NODE_COLUMN: + return translateColumn(pCxt, (SColumnNode*)pNode); + case QUERY_NODE_VALUE: + return translateValue(pCxt, (SValueNode*)pNode); + case QUERY_NODE_OPERATOR: + return translateOperator(pCxt, (SOperatorNode*)pNode); + case QUERY_NODE_FUNCTION: + return translateFunction(pCxt, (SFunctionNode*)pNode); + case QUERY_NODE_LOGIC_CONDITION: + return translateLogicCond(pCxt, (SLogicConditionNode*)pNode); + case QUERY_NODE_TEMP_TABLE: + return translateExprSubquery(pCxt, ((STempTableNode*)pNode)->pSubquery); + default: + break; + } + return DEAL_RES_CONTINUE; +} + +static int32_t translateExpr(STranslateContext* pCxt, SNode* pNode) { + nodesWalkNodePostOrder(pNode, doTranslateExpr, pCxt); + return pCxt->errCode; +} + +static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) { + nodesWalkListPostOrder(pList, doTranslateExpr, pCxt); + return pCxt->errCode; +} + +static bool isAliasColumn(SColumnNode* pCol) { + return ('\0' == pCol->tableAlias[0]); +} + +static bool isDistinctOrderBy(STranslateContext* pCxt) { + return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct); +} + +static SNodeList* getGroupByList(STranslateContext* pCxt) { + if (isDistinctOrderBy(pCxt)) { + return pCxt->pCurrStmt->pProjectionList; + } + return pCxt->pCurrStmt->pGroupByList; +} + +static SNode* getGroupByNode(SNode* pNode) { + if (QUERY_NODE_GROUPING_SET == nodeType(pNode)) { + return nodesListGetNode(((SGroupingSetNode*)pNode)->pParameterList, 0); + } + return pNode; +} + +static int32_t getGroupByErrorCode(STranslateContext* pCxt) { + if (isDistinctOrderBy(pCxt)) { + return TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION; + } + return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION; +} + +static EDealRes doCheckExprForGroupBy(SNode* pNode, void* pContext) { + STranslateContext* pCxt = (STranslateContext*)pContext; + if (!nodesIsExprNode(pNode) || (QUERY_NODE_COLUMN == nodeType(pNode) && isAliasColumn((SColumnNode*)pNode))) { + return DEAL_RES_CONTINUE; + } + if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId) && !isDistinctOrderBy(pCxt)) { + return DEAL_RES_IGNORE_CHILD; + } + SNode* pGroupNode; + FOREACH(pGroupNode, getGroupByList(pCxt)) { + if (nodesEqualNode(getGroupByNode(pGroupNode), pNode)) { + return DEAL_RES_IGNORE_CHILD; + } + } + if (QUERY_NODE_COLUMN == nodeType(pNode) || + (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId) && isDistinctOrderBy(pCxt))) { + return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt)); + } + return DEAL_RES_CONTINUE; +} + +static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode* pNode) { + nodesWalkNode(pNode, doCheckExprForGroupBy, pCxt); + return pCxt->errCode; +} + +static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList) { + if (NULL == getGroupByList(pCxt)) { + return TSDB_CODE_SUCCESS; + } + nodesWalkList(pList, doCheckExprForGroupBy, pCxt); + return pCxt->errCode; +} + +typedef struct CheckAggColCoexistCxt { + STranslateContext* pTranslateCxt; + bool existAggFunc; + bool existCol; +} CheckAggColCoexistCxt; + +static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) { + CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext; + if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) { + pCxt->existAggFunc = true; + return DEAL_RES_IGNORE_CHILD; + } + if (QUERY_NODE_COLUMN == nodeType(pNode)) { + pCxt->existCol = true; + } + return DEAL_RES_CONTINUE; +} + +static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) { + if (NULL != pSelect->pGroupByList) { + return TSDB_CODE_SUCCESS; + } + CheckAggColCoexistCxt cxt = { .pTranslateCxt = pCxt, .existAggFunc = false, .existCol = false }; + nodesWalkList(pSelect->pProjectionList, doCheckAggColCoexist, &cxt); + if (!pSelect->isDistinct) { + nodesWalkList(pSelect->pOrderByList, doCheckAggColCoexist, &cxt); + } + if (cxt.existAggFunc && cxt.existCol) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SINGLE_GROUP); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t setTableVgroupList(SParseContext* pCxt, SName* name, SRealTableNode* pRealTable) { + if (TSDB_SUPER_TABLE == pRealTable->pMeta->tableType) { + SArray* vgroupList = NULL; + int32_t code = catalogGetTableDistVgInfo(pCxt->pCatalog, pCxt->pTransporter, &pCxt->mgmtEpSet, name, &vgroupList); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + size_t vgroupNum = taosArrayGetSize(vgroupList); + pRealTable->pVgroupList = calloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo) * vgroupNum); + if (NULL == pRealTable->pVgroupList) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pRealTable->pVgroupList->numOfVgroups = vgroupNum; + for (int32_t i = 0; i < vgroupNum; ++i) { + SVgroupInfo *vg = taosArrayGet(vgroupList, i); + pRealTable->pVgroupList->vgroups[i] = *vg; + } + + taosArrayDestroy(vgroupList); + } else { + pRealTable->pVgroupList = calloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo)); + if (NULL == pRealTable->pVgroupList) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pRealTable->pVgroupList->numOfVgroups = 1; + int32_t code = catalogGetTableHashVgroup(pCxt->pCatalog, pCxt->pTransporter, &pCxt->mgmtEpSet, name, pRealTable->pVgroupList->vgroups); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pTable)) { + case QUERY_NODE_REAL_TABLE: { + SRealTableNode* pRealTable = (SRealTableNode*)pTable; + SName name; + code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &(pCxt->pParseCxt->mgmtEpSet), + toName(pCxt->pParseCxt->acctId, pRealTable, &name), &(pRealTable->pMeta)); + if (TSDB_CODE_SUCCESS != code) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TABLE_NOT_EXIST, pRealTable->table.tableName); + } + code = setTableVgroupList(pCxt->pParseCxt, &name, pRealTable); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + code = addNamespace(pCxt, pRealTable); + break; + } + case QUERY_NODE_TEMP_TABLE: { + STempTableNode* pTempTable = (STempTableNode*)pTable; + code = translateSubquery(pCxt, pTempTable->pSubquery); + if (TSDB_CODE_SUCCESS == code) { + code = addNamespace(pCxt, pTempTable); + } + break; + } + case QUERY_NODE_JOIN_TABLE: { + SJoinTableNode* pJoinTable = (SJoinTableNode*)pTable; + code = translateTable(pCxt, pJoinTable->pLeft); + if (TSDB_CODE_SUCCESS == code) { + code = translateTable(pCxt, pJoinTable->pRight); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateExpr(pCxt, pJoinTable->pOnCond); + } + break; + } + default: + break; + } + return code; +} + +static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool* pIsSelectStar) { + if (NULL == pSelect->pProjectionList) { // select * ... + SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + size_t nums = taosArrayGetSize(pTables); + pSelect->pProjectionList = nodesMakeList(); + if (NULL == pSelect->pProjectionList) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY); + } + for (size_t i = 0; i < nums; ++i) { + STableNode* pTable = taosArrayGetP(pTables, i); + int32_t code = createColumnNodeByTable(pCxt, pTable, pSelect->pProjectionList); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + *pIsSelectStar = true; + } else { + // todo : t.* + } + return TSDB_CODE_SUCCESS; +} + +static int32_t getPositionValue(const SValueNode* pVal) { + switch (pVal->node.resType.type) { + case TSDB_DATA_TYPE_NULL: + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_JSON: + return -1; + case TSDB_DATA_TYPE_BOOL: + return (pVal->datum.b ? 1 : 0); + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_BIGINT: + return pVal->datum.i; + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_DOUBLE: + return pVal->datum.d; + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_UBIGINT: + return pVal->datum.u; + default: + break; + } + return -1; +} + +static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) { + *pOther = false; + SNode* pNode; + FOREACH(pNode, pOrderByList) { + SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr; + if (QUERY_NODE_VALUE == nodeType(pExpr)) { + SValueNode* pVal = (SValueNode*)pExpr; + if (DEAL_RES_ERROR == translateValue(pCxt, pVal)) { + return pCxt->errCode; + } + int32_t pos = getPositionValue(pVal); + if (pos < 0) { + ERASE_NODE(pOrderByList); + continue; + } else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT); + } else { + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY); + } + setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), pCol); + ((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol; + nodesDestroyNode(pExpr); + } + } else { + *pOther = true; + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) { + bool other; + int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + if (!other) { + return TSDB_CODE_SUCCESS; + } + pCxt->currClause = SQL_CLAUSE_ORDER_BY; + code = translateExprList(pCxt, pSelect->pOrderByList); + if (TSDB_CODE_SUCCESS == code) { + code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList); + } + return code; +} + +static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) { + bool isSelectStar = false; + int32_t code = translateStar(pCxt, pSelect, &isSelectStar); + if (TSDB_CODE_SUCCESS == code && !isSelectStar) { + pCxt->currClause = SQL_CLAUSE_SELECT; + code = translateExprList(pCxt, pSelect->pProjectionList); + } + if (TSDB_CODE_SUCCESS == code) { + code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList); + } + return code; +} + +static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) { + if (NULL == pSelect->pGroupByList && NULL != pSelect->pHaving) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION); + } + pCxt->currClause = SQL_CLAUSE_HAVING; + int32_t code = translateExpr(pCxt, pSelect->pHaving); + if (TSDB_CODE_SUCCESS == code) { + code = checkExprForGroupBy(pCxt, pSelect->pHaving); + } + return code; +} + +static int32_t translateGroupBy(STranslateContext* pCxt, SNodeList* pGroupByList) { + pCxt->currClause = SQL_CLAUSE_GROUP_BY; + return translateExprList(pCxt, pGroupByList); +} + +static int32_t doTranslateWindow(STranslateContext* pCxt, SNode* pWindow) { + return TSDB_CODE_SUCCESS; +} + +static int32_t translateWindow(STranslateContext* pCxt, SNode* pWindow) { + pCxt->currClause = SQL_CLAUSE_WINDOW; + int32_t code = translateExpr(pCxt, pWindow); + if (TSDB_CODE_SUCCESS == code) { + code = doTranslateWindow(pCxt, pWindow); + } + return code; +} + +static int32_t translatePartitionBy(STranslateContext* pCxt, SNodeList* pPartitionByList) { + pCxt->currClause = SQL_CLAUSE_PARTITION_BY; + return translateExprList(pCxt, pPartitionByList); +} + +static int32_t translateWhere(STranslateContext* pCxt, SNode* pWhere) { + pCxt->currClause = SQL_CLAUSE_WHERE; + return translateExpr(pCxt, pWhere); +} + +static int32_t translateFrom(STranslateContext* pCxt, SNode* pTable) { + pCxt->currClause = SQL_CLAUSE_FROM; + return translateTable(pCxt, pTable); +} + +static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) { + pCxt->pCurrStmt = pSelect; + int32_t code = translateFrom(pCxt, pSelect->pFromTable); + if (TSDB_CODE_SUCCESS == code) { + code = translateWhere(pCxt, pSelect->pWhere); + } + if (TSDB_CODE_SUCCESS == code) { + code = translatePartitionBy(pCxt, pSelect->pPartitionByList); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateWindow(pCxt, pSelect->pWindow); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateGroupBy(pCxt, pSelect->pGroupByList); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateHaving(pCxt, pSelect); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateSelectList(pCxt, pSelect); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateOrderBy(pCxt, pSelect); + } + if (TSDB_CODE_SUCCESS == code) { + code = checkAggColCoexist(pCxt, pSelect); + } + return code; +} + +static void buildCreateDbReq(STranslateContext* pCxt, SCreateDatabaseStmt* pStmt, SCreateDbReq* pReq) { + SName name = {0}; + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + tNameGetFullDbName(&name, pReq->db); + pReq->numOfVgroups = pStmt->options.numOfVgroups; + pReq->cacheBlockSize = pStmt->options.cacheBlockSize; + pReq->totalBlocks = pStmt->options.numOfBlocks; + pReq->daysPerFile = pStmt->options.daysPerFile; + pReq->daysToKeep0 = pStmt->options.keep; + pReq->daysToKeep1 = -1; + pReq->daysToKeep2 = -1; + pReq->minRows = pStmt->options.minRowsPerBlock; + pReq->maxRows = pStmt->options.maxRowsPerBlock; + pReq->commitTime = -1; + pReq->fsyncPeriod = pStmt->options.fsyncPeriod; + pReq->walLevel = pStmt->options.walLevel; + pReq->precision = pStmt->options.precision; + pReq->compression = pStmt->options.compressionLevel; + pReq->replications = pStmt->options.replica; + pReq->quorum = pStmt->options.quorum; + pReq->update = -1; + pReq->cacheLastRow = pStmt->options.cachelast; + pReq->ignoreExist = pStmt->ignoreExists; + pReq->streamMode = pStmt->options.streamMode; + return; +} + +static int32_t translateCreateDatabase(STranslateContext* pCxt, SCreateDatabaseStmt* pStmt) { + SCreateDbReq createReq = {0}; + buildCreateDbReq(pCxt, pStmt, &createReq); + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_CREATE_DB; + pCxt->pCmdMsg->msgLen = tSerializeSCreateDbReq(NULL, 0, &createReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSCreateDbReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &createReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateDropDatabase(STranslateContext* pCxt, SDropDatabaseStmt* pStmt) { + SDropDbReq dropReq = {0}; + SName name = {0}; + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + tNameGetFullDbName(&name, dropReq.db); + dropReq.ignoreNotExists = pStmt->ignoreNotExists; + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_DROP_DB; + pCxt->pCmdMsg->msgLen = tSerializeSDropDbReq(NULL, 0, &dropReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSDropDbReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &dropReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t columnNodeToField(SNodeList* pList, SArray** pArray) { + *pArray = taosArrayInit(LIST_LENGTH(pList), sizeof(SField)); + SNode* pNode; + FOREACH(pNode, pList) { + SColumnDefNode* pCol = (SColumnDefNode*)pNode; + SField field = { .type = pCol->dataType.type, .bytes = pCol->dataType.bytes }; + strcpy(field.name, pCol->colName); + taosArrayPush(*pArray, &field); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t translateCreateSuperTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) { + SMCreateStbReq createReq = {0}; + createReq.igExists = pStmt->ignoreExists; + columnNodeToField(pStmt->pCols, &createReq.pColumns); + columnNodeToField(pStmt->pTags, &createReq.pTags); + createReq.numOfColumns = LIST_LENGTH(pStmt->pCols); + createReq.numOfTags = LIST_LENGTH(pStmt->pTags); + + SName tableName = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId }; + strcpy(tableName.dbname, pStmt->dbName); + strcpy(tableName.tname, pStmt->tableName); + tNameExtractFullName(&tableName, createReq.name); + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + tFreeSMCreateStbReq(&createReq); + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_CREATE_STB; + pCxt->pCmdMsg->msgLen = tSerializeSMCreateStbReq(NULL, 0, &createReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + tFreeSMCreateStbReq(&createReq); + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSMCreateStbReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &createReq); + + tFreeSMCreateStbReq(&createReq); + return TSDB_CODE_SUCCESS; +} + +static int32_t doTranslateDropSuperTable(STranslateContext* pCxt, const SName* pTableName, bool ignoreNotExists) { + SMDropStbReq dropReq = {0}; + tNameExtractFullName(pTableName, dropReq.name); + dropReq.igNotExists = ignoreNotExists; + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_DROP_STB; + pCxt->pCmdMsg->msgLen = tSerializeSMDropStbReq(NULL, 0, &dropReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSMDropStbReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &dropReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateDropTable(STranslateContext* pCxt, SDropTableStmt* pStmt) { + SDropTableClause* pClause = nodesListGetNode(pStmt->pTables, 0); + + SName tableName = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId }; + strcpy(tableName.dbname, pClause->dbName); + strcpy(tableName.tname, pClause->tableName); + STableMeta* pTableMeta = NULL; + int32_t code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &(pCxt->pParseCxt->mgmtEpSet), &tableName, &pTableMeta); + if (TSDB_CODE_SUCCESS == code) { + if (TSDB_SUPER_TABLE == pTableMeta->tableType) { + code = doTranslateDropSuperTable(pCxt, &tableName, pClause->ignoreNotExists); + } else { + // todo : drop normal table or child table + code = TSDB_CODE_FAILED; + } + } + tfree(pTableMeta); + + return code; +} + +static int32_t translateDropSuperTable(STranslateContext* pCxt, SDropSuperTableStmt* pStmt) { + SName tableName = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId }; + strcpy(tableName.dbname, pStmt->dbName); + strcpy(tableName.tname, pStmt->tableName); + return doTranslateDropSuperTable(pCxt, &tableName, pStmt->ignoreNotExists); +} + +static int32_t translateUseDatabase(STranslateContext* pCxt, SUseDatabaseStmt* pStmt) { + SName name = {0}; + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + + SUseDbReq usedbReq = {0}; + tNameExtractFullName(&name, usedbReq.db); + + catalogGetDBVgVersion(pCxt->pParseCxt->pCatalog, usedbReq.db, &usedbReq.vgVersion, &usedbReq.dbId, &usedbReq.numOfTable); + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_USE_DB; + pCxt->pCmdMsg->msgLen = tSerializeSUseDbReq(NULL, 0, &usedbReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSUseDbReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &usedbReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateCreateUser(STranslateContext* pCxt, SCreateUserStmt* pStmt) { + SCreateUserReq createReq = {0}; + strcpy(createReq.user, pStmt->useName); + createReq.createType = 0; + createReq.superUser = 0; + strcpy(createReq.pass, pStmt->password); + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_CREATE_USER; + pCxt->pCmdMsg->msgLen = tSerializeSCreateUserReq(NULL, 0, &createReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSCreateUserReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &createReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateAlterUser(STranslateContext* pCxt, SAlterUserStmt* pStmt) { + SAlterUserReq alterReq = {0}; + strcpy(alterReq.user, pStmt->useName); + alterReq.alterType = pStmt->alterType; + alterReq.superUser = 0; + strcpy(alterReq.pass, pStmt->password); + if (NULL != pCxt->pParseCxt->db) { + strcpy(alterReq.dbname, pCxt->pParseCxt->db); + } + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_ALTER_USER; + pCxt->pCmdMsg->msgLen = tSerializeSAlterUserReq(NULL, 0, &alterReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSAlterUserReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &alterReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateDropUser(STranslateContext* pCxt, SDropUserStmt* pStmt) { + SDropUserReq dropReq = {0}; + strcpy(dropReq.user, pStmt->useName); + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_DROP_USER; + pCxt->pCmdMsg->msgLen = tSerializeSDropUserReq(NULL, 0, &dropReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSDropUserReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &dropReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateCreateDnode(STranslateContext* pCxt, SCreateDnodeStmt* pStmt) { + SCreateDnodeReq createReq = {0}; + strcpy(createReq.fqdn, pStmt->fqdn); + createReq.port = pStmt->port; + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_CREATE_DNODE; + pCxt->pCmdMsg->msgLen = tSerializeSCreateDnodeReq(NULL, 0, &createReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSCreateDnodeReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &createReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateDropDnode(STranslateContext* pCxt, SDropDnodeStmt* pStmt) { + SDropDnodeReq dropReq = {0}; + dropReq.dnodeId = pStmt->dnodeId; + strcpy(dropReq.fqdn, pStmt->fqdn); + dropReq.port = pStmt->port; + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_DROP_DNODE; + pCxt->pCmdMsg->msgLen = tSerializeSDropDnodeReq(NULL, 0, &dropReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSDropDnodeReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &dropReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t nodeTypeToShowType(ENodeType nt) { + switch (nt) { + case QUERY_NODE_SHOW_DATABASES_STMT: + return TSDB_MGMT_TABLE_DB; + case QUERY_NODE_SHOW_STABLES_STMT: + return TSDB_MGMT_TABLE_STB; + case QUERY_NODE_SHOW_USERS_STMT: + return TSDB_MGMT_TABLE_USER; + case QUERY_NODE_SHOW_DNODES_STMT: + return TSDB_MGMT_TABLE_DNODE; + case QUERY_NODE_SHOW_VGROUPS_STMT: + return TSDB_MGMT_TABLE_VGROUP; + case QUERY_NODE_SHOW_MNODES_STMT: + return TSDB_MGMT_TABLE_MNODE; + default: + break; + } + return 0; +} + +static int32_t translateShow(STranslateContext* pCxt, SShowStmt* pStmt) { + SShowReq showReq = { .type = nodeTypeToShowType(nodeType(pStmt)) }; + if ('\0' != pStmt->dbName[0]) { + SName name = {0}; + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + char dbFname[TSDB_DB_FNAME_LEN] = {0}; + tNameGetFullDbName(&name, showReq.db); + } + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet; + pCxt->pCmdMsg->msgType = TDMT_MND_SHOW; + pCxt->pCmdMsg->msgLen = tSerializeSShowReq(NULL, 0, &showReq); + pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen); + if (NULL== pCxt->pCmdMsg->pMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tSerializeSShowReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &showReq); + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateShowTables(STranslateContext* pCxt) { + SName name = {0}; + SVShowTablesReq* pShowReq = calloc(1, sizeof(SVShowTablesReq)); + if (pCxt->pParseCxt->db == NULL || strlen(pCxt->pParseCxt->db) == 0) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_TSC_INVALID_OPERATION, "db not specified"); + } + + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pCxt->pParseCxt->db, strlen(pCxt->pParseCxt->db)); + char dbFname[TSDB_DB_FNAME_LEN] = {0}; + tNameGetFullDbName(&name, dbFname); + + SArray* array = NULL; + int32_t code = catalogGetDBVgInfo(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &pCxt->pParseCxt->mgmtEpSet, dbFname, false, &array); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + SVgroupInfo* info = taosArrayGet(array, 0); + pShowReq->head.vgId = htonl(info->vgId); + + pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo)); + if (NULL== pCxt->pCmdMsg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pCxt->pCmdMsg->epSet = info->epSet; + pCxt->pCmdMsg->msgType = TDMT_VND_SHOW_TABLES; + pCxt->pCmdMsg->msgLen = sizeof(SVShowTablesReq); + pCxt->pCmdMsg->pMsg = pShowReq; + pCxt->pCmdMsg->pExtension = array; + + return TSDB_CODE_SUCCESS; +} + +static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pNode)) { + case QUERY_NODE_SELECT_STMT: + code = translateSelect(pCxt, (SSelectStmt*)pNode); + break; + case QUERY_NODE_CREATE_DATABASE_STMT: + code = translateCreateDatabase(pCxt, (SCreateDatabaseStmt*)pNode); + break; + case QUERY_NODE_DROP_DATABASE_STMT: + code = translateDropDatabase(pCxt, (SDropDatabaseStmt*)pNode); + break; + case QUERY_NODE_CREATE_TABLE_STMT: + code = translateCreateSuperTable(pCxt, (SCreateTableStmt*)pNode); + break; + case QUERY_NODE_DROP_TABLE_STMT: + code = translateDropTable(pCxt, (SDropTableStmt*)pNode); + break; + case QUERY_NODE_DROP_SUPER_TABLE_STMT: + code = translateDropSuperTable(pCxt, (SDropSuperTableStmt*)pNode); + break; + case QUERY_NODE_CREATE_USER_STMT: + code = translateCreateUser(pCxt, (SCreateUserStmt*)pNode); + break; + case QUERY_NODE_ALTER_USER_STMT: + code = translateAlterUser(pCxt, (SAlterUserStmt*)pNode); + break; + case QUERY_NODE_DROP_USER_STMT: + code = translateDropUser(pCxt, (SDropUserStmt*)pNode); + break; + case QUERY_NODE_USE_DATABASE_STMT: + code = translateUseDatabase(pCxt, (SUseDatabaseStmt*)pNode); + break; + case QUERY_NODE_CREATE_DNODE_STMT: + code = translateCreateDnode(pCxt, (SCreateDnodeStmt*)pNode); + break; + case QUERY_NODE_DROP_DNODE_STMT: + code = translateDropDnode(pCxt, (SDropDnodeStmt*)pNode); + break; + case QUERY_NODE_SHOW_DATABASES_STMT: + case QUERY_NODE_SHOW_STABLES_STMT: + case QUERY_NODE_SHOW_USERS_STMT: + case QUERY_NODE_SHOW_DNODES_STMT: + case QUERY_NODE_SHOW_VGROUPS_STMT: + case QUERY_NODE_SHOW_MNODES_STMT: + code = translateShow(pCxt, (SShowStmt*)pNode); + break; + case QUERY_NODE_SHOW_TABLES_STMT: + code = translateShowTables(pCxt); + break; + default: + break; + } + return code; +} + +static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) { + ++(pCxt->currLevel); + ESqlClause currClause = pCxt->currClause; + SSelectStmt* pCurrStmt = pCxt->pCurrStmt; + int32_t code = translateQuery(pCxt, pNode); + --(pCxt->currLevel); + pCxt->currClause = currClause; + pCxt->pCurrStmt = pCurrStmt; + return code; +} + +static int32_t setReslutSchema(STranslateContext* pCxt, SQuery* pQuery) { + if (QUERY_NODE_SELECT_STMT == nodeType(pQuery->pRoot)) { + SSelectStmt* pSelect = (SSelectStmt*)pQuery->pRoot; + pQuery->numOfResCols = LIST_LENGTH(pSelect->pProjectionList); + pQuery->pResSchema = calloc(pQuery->numOfResCols, sizeof(SSchema)); + if (NULL == pQuery->pResSchema) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY); + } + SNode* pNode; + int32_t index = 0; + FOREACH(pNode, pSelect->pProjectionList) { + SExprNode* pExpr = (SExprNode*)pNode; + pQuery->pResSchema[index].type = pExpr->resType.type; + pQuery->pResSchema[index].bytes = pExpr->resType.bytes; + strcpy(pQuery->pResSchema[index].name, pExpr->aliasName); + index +=1; + } + } + return TSDB_CODE_SUCCESS; +} + +static void destroyTranslateContext(STranslateContext* pCxt) { + if (NULL != pCxt->pNsLevel) { + size_t size = taosArrayGetSize(pCxt->pNsLevel); + for (size_t i = 0; i < size; ++i) { + taosArrayDestroy(taosArrayGetP(pCxt->pNsLevel, i)); + } + taosArrayDestroy(pCxt->pNsLevel); + } + + if (NULL != pCxt->pCmdMsg) { + tfree(pCxt->pCmdMsg->pMsg); + tfree(pCxt->pCmdMsg); + } +} + +typedef struct SVgroupTablesBatch { + SVCreateTbBatchReq req; + SVgroupInfo info; +} SVgroupTablesBatch; + +static void toSchema(const SColumnDefNode* pCol, int32_t colId, SSchema* pSchema) { + pSchema->colId = colId; + pSchema->type = pCol->dataType.type; + pSchema->bytes = pCol->dataType.bytes; + strcpy(pSchema->name, pCol->colName); +} + +static void destroyCreateTbReq(SVCreateTbReq* pReq) { + tfree(pReq->name); + tfree(pReq->ntbCfg.pSchema); +} + +static int32_t buildNormalTableBatchReq( + const char* pTableName, const SNodeList* pColumns, const SVgroupInfo* pVgroupInfo, SVgroupTablesBatch* pBatch) { + SVCreateTbReq req = {0}; + req.type = TD_NORMAL_TABLE; + req.name = strdup(pTableName); + req.ntbCfg.nCols = LIST_LENGTH(pColumns); + req.ntbCfg.pSchema = calloc(req.ntbCfg.nCols, sizeof(SSchema)); + if (NULL == req.name || NULL == req.ntbCfg.pSchema) { + destroyCreateTbReq(&req); + return TSDB_CODE_OUT_OF_MEMORY; + } + SNode* pCol; + int32_t index = 0; + FOREACH(pCol, pColumns) { + toSchema((SColumnDefNode*)pCol, index + 1, req.ntbCfg.pSchema + index); + ++index; + } + + pBatch->info = *pVgroupInfo; + pBatch->req.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq)); + if (NULL == pBatch->req.pArray) { + destroyCreateTbReq(&req); + return TSDB_CODE_OUT_OF_MEMORY; + } + taosArrayPush(pBatch->req.pArray, &req); + + return TSDB_CODE_SUCCESS; +} + +static int32_t serializeVgroupTablesBatch(SVgroupTablesBatch* pTbBatch, SArray* pBufArray) { + int tlen = sizeof(SMsgHead) + tSerializeSVCreateTbBatchReq(NULL, &(pTbBatch->req)); + void* buf = malloc(tlen); + if (NULL == buf) { + return TSDB_CODE_OUT_OF_MEMORY; + } + ((SMsgHead*)buf)->vgId = htonl(pTbBatch->info.vgId); + ((SMsgHead*)buf)->contLen = htonl(tlen); + void* pBuf = POINTER_SHIFT(buf, sizeof(SMsgHead)); + tSerializeSVCreateTbBatchReq(&pBuf, &(pTbBatch->req)); + + SVgDataBlocks* pVgData = calloc(1, sizeof(SVgDataBlocks)); + if (NULL == pVgData) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pVgData->vg = pTbBatch->info; + pVgData->pData = buf; + pVgData->size = tlen; + pVgData->numOfTables = (int32_t) taosArrayGetSize(pTbBatch->req.pArray); + taosArrayPush(pBufArray, &pVgData); + + return TSDB_CODE_SUCCESS; +} + +static void destroyCreateTbReqBatch(SVgroupTablesBatch* pTbBatch) { + size_t size = taosArrayGetSize(pTbBatch->req.pArray); + for(int32_t i = 0; i < size; ++i) { + SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i); + tfree(pTableReq->name); + + if (pTableReq->type == TSDB_NORMAL_TABLE) { + tfree(pTableReq->ntbCfg.pSchema); + } else if (pTableReq->type == TSDB_CHILD_TABLE) { + tfree(pTableReq->ctbCfg.pTag); + } + } + + taosArrayDestroy(pTbBatch->req.pArray); +} + +static int32_t getTableHashVgroup(SParseContext* pCxt, const char* pDbName, const char* pTableName, SVgroupInfo* pInfo) { + SName name = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->acctId }; + strcpy(name.dbname, pDbName); + strcpy(name.tname, pTableName); + return catalogGetTableHashVgroup(pCxt->pCatalog, pCxt->pTransporter, &pCxt->mgmtEpSet, &name, pInfo); +} + +static int32_t rewriteToVnodeModifOpStmt(SQuery* pQuery, SArray* pBufArray) { + SVnodeModifOpStmt* pNewStmt = nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); + if (pNewStmt == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pNewStmt->sqlNodeType = nodeType(pQuery->pRoot); + pNewStmt->pDataBlocks = pBufArray; + nodesDestroyNode(pQuery->pRoot); + pQuery->pRoot = (SNode*)pNewStmt; + return TSDB_CODE_SUCCESS; +} + +static void destroyCreateTbReqArray(SArray* pArray) { + size_t size = taosArrayGetSize(pArray); + for (size_t i = 0; i < size; ++i) { + SVgDataBlocks* pVg = taosArrayGetP(pArray, i); + tfree(pVg->pData); + tfree(pVg); + } + taosArrayDestroy(pArray); +} + +static int32_t buildCreateTableDataBlock(const SCreateTableStmt* pStmt, const SVgroupInfo* pInfo, SArray** pBufArray) { + *pBufArray = taosArrayInit(1, POINTER_BYTES); + if (NULL == *pBufArray) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SVgroupTablesBatch tbatch = {0}; + int32_t code = buildNormalTableBatchReq(pStmt->tableName, pStmt->pCols, pInfo, &tbatch); + if (TSDB_CODE_SUCCESS == code) { + code = serializeVgroupTablesBatch(&tbatch, *pBufArray); + } + + destroyCreateTbReqBatch(&tbatch); + if (TSDB_CODE_SUCCESS != code) { + destroyCreateTbReqArray(*pBufArray); + } + return code; +} + +static int32_t rewriteCreateTable(STranslateContext* pCxt, SQuery* pQuery) { + SCreateTableStmt* pStmt = (SCreateTableStmt*)pQuery->pRoot; + + SVgroupInfo info = {0}; + int32_t code = getTableHashVgroup(pCxt->pParseCxt, pStmt->dbName, pStmt->tableName, &info); + SArray* pBufArray = NULL; + if (TSDB_CODE_SUCCESS == code) { + code = buildCreateTableDataBlock(pStmt, &info, &pBufArray); + } + if (TSDB_CODE_SUCCESS == code) { + code = rewriteToVnodeModifOpStmt(pQuery, pBufArray); + if (TSDB_CODE_SUCCESS != code) { + destroyCreateTbReqArray(pBufArray); + } + } + + return code; +} + +static void addCreateTbReqIntoVgroup(SHashObj* pVgroupHashmap, const char* pTableName, SKVRow row, uint64_t suid, SVgroupInfo* pVgInfo) { + struct SVCreateTbReq req = {0}; + req.type = TD_CHILD_TABLE; + req.name = strdup(pTableName); + req.ctbCfg.suid = suid; + req.ctbCfg.pTag = row; + + SVgroupTablesBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId)); + if (pTableBatch == NULL) { + SVgroupTablesBatch tBatch = {0}; + tBatch.info = *pVgInfo; + + tBatch.req.pArray = taosArrayInit(4, sizeof(struct SVCreateTbReq)); + taosArrayPush(tBatch.req.pArray, &req); + + taosHashPut(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId), &tBatch, sizeof(tBatch)); + } else { // add to the correct vgroup + taosArrayPush(pTableBatch->req.pArray, &req); + } +} + +static void valueNodeToVariant(const SValueNode* pNode, SVariant* pVal) { + pVal->nType = pNode->node.resType.type; + pVal->nLen = pNode->node.resType.bytes; + switch (pNode->node.resType.type) { + case TSDB_DATA_TYPE_NULL: + break; + case TSDB_DATA_TYPE_BOOL: + pVal->i = pNode->datum.b; + break; + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + pVal->i = pNode->datum.i; + break; + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_UBIGINT: + pVal->u = pNode->datum.u; + break; + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_DOUBLE: + pVal->d = pNode->datum.d; + break; + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_VARBINARY: + pVal->pz = pNode->datum.p; + break; + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + // todo + default: + break; + } +} + +static int32_t addValToKVRow(STranslateContext* pCxt, SValueNode* pVal, const SSchema* pSchema, SKVRowBuilder* pBuilder) { + if (DEAL_RES_ERROR == translateValue(pCxt, pVal)) { + return pCxt->errCode; + } + SVariant var; + valueNodeToVariant(pVal, &var); + char tagVal[TSDB_MAX_TAGS_LEN] = {0}; + int32_t code = taosVariantDump(&var, tagVal, pSchema->type, true); + if (TSDB_CODE_SUCCESS == code) { + tdAddColToKVRow(pBuilder, pSchema->colId, pSchema->type, tagVal); + } + return code; +} + +static int32_t buildKVRowForBindTags(STranslateContext* pCxt, SCreateSubTableClause* pStmt, STableMeta* pSuperTableMeta, SKVRowBuilder* pBuilder) { + int32_t numOfTags = getNumOfTags(pSuperTableMeta); + if (LIST_LENGTH(pStmt->pValsOfTags) != LIST_LENGTH(pStmt->pSpecificTags) || numOfTags < LIST_LENGTH(pStmt->pValsOfTags)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TAGS_NOT_MATCHED); + } + + SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta); + SNode* pTag, *pVal; + FORBOTH(pTag, pStmt->pSpecificTags, pVal, pStmt->pValsOfTags) { + SColumnNode* pCol = (SColumnNode*)pTag; + SSchema* pSchema = NULL; + for (int32_t i = 0; i < numOfTags; ++i) { + if (0 == strcmp(pCol->colName, pTagSchema[i].name)) { + pSchema = pTagSchema + i; + break; + } + } + if (NULL == pSchema) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAG_NAME, pCol->colName); + } + int32_t code = addValToKVRow(pCxt, (SValueNode*)pVal, pSchema, pBuilder); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t buildKVRowForAllTags(STranslateContext* pCxt, SCreateSubTableClause* pStmt, STableMeta* pSuperTableMeta, SKVRowBuilder* pBuilder) { + if (getNumOfTags(pSuperTableMeta) != LIST_LENGTH(pStmt->pValsOfTags)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TAGS_NOT_MATCHED); + } + + SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta); + SNode* pVal; + int32_t index = 0; + FOREACH(pVal, pStmt->pValsOfTags) { + int32_t code = addValToKVRow(pCxt, (SValueNode*)pVal, pTagSchema + index++, pBuilder); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t rewriteCreateSubTable(STranslateContext* pCxt, SCreateSubTableClause* pStmt, SHashObj* pVgroupHashmap) { + SName name = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId }; + strcpy(name.dbname, pStmt->useDbName); + strcpy(name.tname, pStmt->useTableName); + STableMeta* pSuperTableMeta = NULL; + int32_t code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &pCxt->pParseCxt->mgmtEpSet, &name, &pSuperTableMeta); + + SKVRowBuilder kvRowBuilder = {0}; + if (TSDB_CODE_SUCCESS == code) { + code = tdInitKVRowBuilder(&kvRowBuilder); + } + + if (TSDB_CODE_SUCCESS == code) { + if (NULL != pStmt->pSpecificTags) { + code = buildKVRowForBindTags(pCxt, pStmt, pSuperTableMeta, &kvRowBuilder); + } else { + code = buildKVRowForAllTags(pCxt, pStmt, pSuperTableMeta, &kvRowBuilder); + } + } + + SKVRow row = NULL; + if (TSDB_CODE_SUCCESS == code) { + row = tdGetKVRowFromBuilder(&kvRowBuilder); + if (NULL == row) { + code = TSDB_CODE_OUT_OF_MEMORY; + } else { + tdSortKVRowByColIdx(row); + } + } + + SVgroupInfo info = {0}; + if (TSDB_CODE_SUCCESS == code) { + code = getTableHashVgroup(pCxt->pParseCxt, pStmt->dbName, pStmt->tableName, &info); + } + if (TSDB_CODE_SUCCESS == code) { + addCreateTbReqIntoVgroup(pVgroupHashmap, pStmt->tableName, row, pSuperTableMeta->uid, &info); + } + + tfree(pSuperTableMeta); + tdDestroyKVRowBuilder(&kvRowBuilder); + return code; +} + +static SArray* serializeVgroupsTablesBatch(SHashObj* pVgroupHashmap) { + SArray* pBufArray = taosArrayInit(taosHashGetSize(pVgroupHashmap), sizeof(void*)); + if (NULL == pBufArray) { + return NULL; + } + + int32_t code = TSDB_CODE_SUCCESS; + SVgroupTablesBatch* pTbBatch = NULL; + do { + pTbBatch = taosHashIterate(pVgroupHashmap, pTbBatch); + if (pTbBatch == NULL) { + break; + } + + serializeVgroupTablesBatch(pTbBatch, pBufArray); + destroyCreateTbReqBatch(pTbBatch); + } while (true); + + return pBufArray; +} + +static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery) { + SCreateMultiTableStmt* pStmt = (SCreateMultiTableStmt*)pQuery->pRoot; + + SHashObj* pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); + if (NULL == pVgroupHashmap) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + int32_t code = TSDB_CODE_SUCCESS; + SNode* pNode; + FOREACH(pNode, pStmt->pSubTables) { + code = rewriteCreateSubTable(pCxt, (SCreateSubTableClause*)pNode, pVgroupHashmap); + if (TSDB_CODE_SUCCESS != code) { + taosHashCleanup(pVgroupHashmap); + return code; + } + } + + SArray* pBufArray = serializeVgroupsTablesBatch(pVgroupHashmap); + taosHashCleanup(pVgroupHashmap); + if (NULL == pBufArray) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + return rewriteToVnodeModifOpStmt(pQuery, pBufArray); +} + +static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pQuery->pRoot)) { + case QUERY_NODE_CREATE_TABLE_STMT: + if (NULL == ((SCreateTableStmt*)pQuery->pRoot)->pTags) { + code = rewriteCreateTable(pCxt, pQuery); + } + break; + case QUERY_NODE_CREATE_MULTI_TABLE_STMT: + code = rewriteCreateMultiTable(pCxt, pQuery); + break; + default: + break; + } + return code; +} + +static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pQuery->pRoot)) { + case QUERY_NODE_SELECT_STMT: + pQuery->haveResultSet = true; + pQuery->directRpc = false; + pQuery->msgType = TDMT_VND_QUERY; + code = setReslutSchema(pCxt, pQuery); + break; + case QUERY_NODE_VNODE_MODIF_STMT: + pQuery->haveResultSet = false; + pQuery->directRpc = false; + pQuery->msgType = TDMT_VND_CREATE_TABLE; + break; + default: + pQuery->haveResultSet = false; + pQuery->directRpc = true; + pQuery->pCmdMsg = pCxt->pCmdMsg; + pCxt->pCmdMsg = NULL; + pQuery->msgType = pQuery->pCmdMsg->msgType; + break; + } + return code; +} + +int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) { + STranslateContext cxt = { + .pParseCxt = pParseCxt, + .errCode = TSDB_CODE_SUCCESS, + .msgBuf = { .buf = pParseCxt->pMsg, .len = pParseCxt->msgLen }, + .pNsLevel = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES), + .currLevel = 0, + .currClause = 0 + }; + int32_t code = fmFuncMgtInit(); + if (TSDB_CODE_SUCCESS == code) { + code = rewriteQuery(&cxt, pQuery); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateQuery(&cxt, pQuery->pRoot); + } + if (TSDB_CODE_SUCCESS == code) { + code = setQuery(&cxt, pQuery); + } + destroyTranslateContext(&cxt); + return code; +} diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c new file mode 100644 index 0000000000000000000000000000000000000000..aa2516e2b931557816182e363f73c0f80ab9bec2 --- /dev/null +++ b/source/libs/parser/src/parUtil.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "parUtil.h" + +static char* getSyntaxErrFormat(int32_t errCode) { + switch (errCode) { + case TSDB_CODE_PAR_SYNTAX_ERROR: + return "syntax error near \"%s\""; + case TSDB_CODE_PAR_INCOMPLETE_SQL: + return "Incomplete SQL statement"; + case TSDB_CODE_PAR_INVALID_COLUMN: + return "Invalid column name : %s"; + case TSDB_CODE_PAR_TABLE_NOT_EXIST: + return "Table does not exist : %s"; + case TSDB_CODE_PAR_AMBIGUOUS_COLUMN: + return "Column ambiguously defined : %s"; + case TSDB_CODE_PAR_WRONG_VALUE_TYPE: + return "Invalid value type : %s"; + case TSDB_CODE_PAR_INVALID_FUNTION: + return "Invalid function name : %s"; + case TSDB_CODE_PAR_FUNTION_PARA_NUM: + return "Invalid number of arguments : %s"; + case TSDB_CODE_PAR_FUNTION_PARA_TYPE: + return "Inconsistent datatypes : %s"; + case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION: + return "There mustn't be aggregation"; + case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT: + return "ORDER BY item must be the number of a SELECT-list expression"; + case TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION: + return "Not a GROUP BY expression"; + case TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION: + return "Not SELECTed expression"; + case TSDB_CODE_PAR_NOT_SINGLE_GROUP: + return "Not a single-group group function"; + case TSDB_CODE_PAR_TAGS_NOT_MATCHED: + return "tags number not matched"; + case TSDB_CODE_PAR_INVALID_TAG_NAME: + return "invalid tag name : %s"; + case TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG: + return "name or password too long"; + case TSDB_CODE_PAR_PASSWD_EMPTY: + return "password can not be empty"; + case TSDB_CODE_PAR_INVALID_PORT: + return "port should be an integer that is less than 65535 and greater than 0"; + case TSDB_CODE_PAR_INVALID_ENDPOINT: + return "endpoint should be in the format of 'fqdn:port'"; + case TSDB_CODE_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "Unknown error"; + } +} + +int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...) { + va_list vArgList; + va_start(vArgList, errCode); + vsnprintf(pBuf->buf, pBuf->len, getSyntaxErrFormat(errCode), vArgList); + va_end(vArgList); + return errCode; +} + +int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) { + strncpy(pBuf->buf, msg, pBuf->len); + return TSDB_CODE_TSC_INVALID_OPERATION; +} + +int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) { + const char* msgFormat1 = "syntax error near \'%s\'"; + const char* msgFormat2 = "syntax error near \'%s\' (%s)"; + const char* msgFormat3 = "%s"; + + const char* prefix = "syntax error"; + if (sourceStr == NULL) { + assert(additionalInfo != NULL); + snprintf(pBuf->buf, pBuf->len, msgFormat1, additionalInfo); + return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; + } + + char buf[64] = {0}; // only extract part of sql string + strncpy(buf, sourceStr, tListLen(buf) - 1); + + if (additionalInfo != NULL) { + snprintf(pBuf->buf, pBuf->len, msgFormat2, buf, additionalInfo); + } else { + const char* msgFormat = (0 == strncmp(sourceStr, prefix, strlen(prefix))) ? msgFormat3 : msgFormat1; + snprintf(pBuf->buf, pBuf->len, msgFormat, buf); + } + + return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; +} + +static uint32_t getTableMetaSize(const STableMeta* pTableMeta) { + assert(pTableMeta != NULL); + + int32_t totalCols = 0; + if (pTableMeta->tableInfo.numOfColumns >= 0) { + totalCols = pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; + } + + return sizeof(STableMeta) + totalCols * sizeof(SSchema); +} + +STableMeta* tableMetaDup(const STableMeta* pTableMeta) { + assert(pTableMeta != NULL); + size_t size = getTableMetaSize(pTableMeta); + + STableMeta* p = malloc(size); + memcpy(p, pTableMeta, size); + return p; +} + +SSchema *getTableColumnSchema(const STableMeta *pTableMeta) { + assert(pTableMeta != NULL); + return (SSchema*) pTableMeta->schema; +} + +static SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) { + assert(pTableMeta != NULL && pTableMeta->schema != NULL && colIndex >= 0 && colIndex < (getNumOfColumns(pTableMeta) + getNumOfTags(pTableMeta))); + + SSchema* pSchema = (SSchema*) pTableMeta->schema; + return &pSchema[colIndex]; +} + +SSchema* getTableTagSchema(const STableMeta* pTableMeta) { + assert(pTableMeta != NULL && (pTableMeta->tableType == TSDB_SUPER_TABLE || pTableMeta->tableType == TSDB_CHILD_TABLE)); + return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns); +} + +int32_t getNumOfColumns(const STableMeta* pTableMeta) { + assert(pTableMeta != NULL); + // table created according to super table, use data from super table + return getTableInfo(pTableMeta).numOfColumns; +} + +int32_t getNumOfTags(const STableMeta* pTableMeta) { + assert(pTableMeta != NULL); + return getTableInfo(pTableMeta).numOfTags; +} + +STableComInfo getTableInfo(const STableMeta* pTableMeta) { + assert(pTableMeta != NULL); + return pTableMeta->tableInfo; +} + +int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen) { + // delete escape character: \\, \', \" + char delim = src[0]; + int32_t cnt = 0; + int32_t j = 0; + for (uint32_t k = 1; k < len - 1; ++k) { + if (j >= dlen) { + break; + } + if (src[k] == '\\' || (src[k] == delim && src[k + 1] == delim)) { + dst[j] = src[k + 1]; + cnt++; + j++; + k++; + continue; + } + dst[j] = src[k]; + j++; + } + dst[j] = '\0'; + return j; +} diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index 3b79a2de9292ce43c30e5997181999b41d3541f7..868bd755208ed1ac0cdafe3774f4d979dc3d197a 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -13,250 +13,47 @@ * along with this program. If not, see . */ -#include "astGenerator.h" -#include "parserInt.h" -#include "parserUtil.h" -#include "ttoken.h" -#include "function.h" -#include "insertParser.h" +#include "parser.h" -bool isInsertSql(const char* pStr, size_t length) { +#include "parInt.h" +#include "parToken.h" + +static bool isInsertSql(const char* pStr, size_t length) { int32_t index = 0; do { SToken t0 = tStrGetToken((char*) pStr, &index, false); - if (t0.type != TK_LP) { + if (t0.type != TK_NK_LP) { return t0.type == TK_INSERT || t0.type == TK_IMPORT; } } while (1); } -bool qIsDdlQuery(const SQueryNode* pQueryNode) { - return TSDB_SQL_INSERT != pQueryNode->type && TSDB_SQL_SELECT != pQueryNode->type && TSDB_SQL_CREATE_TABLE != pQueryNode->type; -} - -int32_t parseQuerySql(SParseContext* pCxt, SQueryNode** pQuery) { - int32_t code = TSDB_CODE_SUCCESS; - - SSqlInfo info = doGenerateAST(pCxt->pSql); - if (!info.valid) { - strncpy(pCxt->pMsg, info.msg, pCxt->msgLen); - code = TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - goto _end; - } - - if (!isDqlSqlStatement(&info)) { - if (info.type == TSDB_SQL_CREATE_TABLE) { - SVnodeModifOpStmtInfo * pModifStmtInfo = qParserValidateCreateTbSqlNode(&info, pCxt, pCxt->pMsg, pCxt->msgLen); - if (pModifStmtInfo == NULL) { - code = terrno; - goto _end; - } - - *pQuery = (SQueryNode*)pModifStmtInfo; - } else { - SDclStmtInfo* pDcl = qParserValidateDclSqlNode(&info, pCxt, pCxt->pMsg, pCxt->msgLen); - if (pDcl == NULL) { - code = terrno; - goto _end; - } - - *pQuery = (SQueryNode*)pDcl; - pDcl->nodeType = info.type; - } - } else { - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - if (pQueryInfo == NULL) { - code = TSDB_CODE_QRY_OUT_OF_MEMORY; // set correct error code. - goto _end; - } - - code = qParserValidateSqlNode(pCxt, &info, pQueryInfo, pCxt->pMsg, pCxt->msgLen); - if (code == TSDB_CODE_SUCCESS) { - *pQuery = (SQueryNode*)pQueryInfo; - } else { - goto _end; - } +static int32_t parseSqlIntoAst(SParseContext* pCxt, SQuery** pQuery) { + int32_t code = doParse(pCxt, pQuery); + if (TSDB_CODE_SUCCESS == code) { + code = doTranslate(pCxt, *pQuery); } - - _end: - destroySqlInfo(&info); - terrno = code; return code; } -int32_t qParseQuerySql(SParseContext* pCxt, SQueryNode** pQueryNode) { +int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery) { if (isInsertSql(pCxt->pSql, pCxt->sqlLen)) { - return parseInsertSql(pCxt, (SVnodeModifOpStmtInfo**)pQueryNode); + return parseInsertSql(pCxt, pQuery); } else { - return parseQuerySql(pCxt, pQueryNode); - } -} - -int32_t qParserConvertSql(const char* pStr, size_t length, char** pConvertSql) { - return 0; -} - -static int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SParseContext *pCtx, SMsgBuf* pMsgBuf); - -static int32_t tnameComparFn(const void* p1, const void* p2) { - SName* pn1 = (SName*)p1; - SName* pn2 = (SName*)p2; - - int32_t ret = pn1->acctId - pn2->acctId; - if (ret != 0) { - return ret > 0? 1:-1; - } else { - ret = strncmp(pn1->dbname, pn2->dbname, tListLen(pn1->dbname)); - if (ret != 0) { - return ret > 0? 1:-1; - } else { - ret = strncmp(pn1->tname, pn2->tname, tListLen(pn1->tname)); - if (ret != 0) { - return ret > 0? 1:-1; - } else { - return 0; - } - } - } -} - -static int32_t getTableNameFromSubquery(SSqlNode* pSqlNode, SArray* tableNameList, SParseContext *pCtx, SMsgBuf* pMsgBuf) { - int32_t numOfSub = (int32_t)taosArrayGetSize(pSqlNode->from->list); - - for (int32_t j = 0; j < numOfSub; ++j) { - SRelElement* sub = taosArrayGet(pSqlNode->from->list, j); - - int32_t num = (int32_t)taosArrayGetSize(sub->pSubquery->node); - for (int32_t i = 0; i < num; ++i) { - SSqlNode* p = taosArrayGetP(sub->pSubquery->node, i); - if (p->from->type == SQL_FROM_NODE_TABLES) { - int32_t code = getTableNameFromSqlNode(p, tableNameList, pCtx, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else { - getTableNameFromSubquery(p, tableNameList, pCtx, pMsgBuf); - } - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SParseContext *pParseCtx, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid table name"; - - int32_t numOfTables = (int32_t) taosArrayGetSize(pSqlNode->from->list); - assert(pSqlNode->from->type == SQL_FROM_NODE_TABLES); - - for(int32_t j = 0; j < numOfTables; ++j) { - SRelElement* item = taosArrayGet(pSqlNode->from->list, j); - - SToken* t = &item->tableName; - if (t->type == TK_INTEGER || t->type == TK_FLOAT || t->type == TK_STRING) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (parserValidateIdToken(t) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - SName name = {0}; - int32_t code = createSName(&name, t, pParseCtx, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - taosArrayPush(tableNameList, &name); + return parseSqlIntoAst(pCxt, pQuery); } - - return TSDB_CODE_SUCCESS; -} - -static void freePtrElem(void* p) { - tfree(*(char**)p); } -int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SCatalogReq* pMetaInfo, SParseContext *pCtx, char* msg, int32_t msgBufLen) { - int32_t code = TSDB_CODE_SUCCESS; - SMsgBuf msgBuf = {.buf = msg, .len = msgBufLen}; - - pMetaInfo->pTableName = taosArrayInit(4, sizeof(SName)); - pMetaInfo->pUdf = taosArrayInit(4, POINTER_BYTES); - - size_t size = taosArrayGetSize(pSqlInfo->sub.node); - for (int32_t i = 0; i < size; ++i) { - SSqlNode* pSqlNode = taosArrayGetP(pSqlInfo->sub.node, i); - if (pSqlNode->from == NULL) { - return buildInvalidOperationMsg(&msgBuf, "invalid from clause"); - } - - // load the table meta in the FROM clause - if (pSqlNode->from->type == SQL_FROM_NODE_TABLES) { - code = getTableNameFromSqlNode(pSqlNode, pMetaInfo->pTableName, pCtx, &msgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else { - code = getTableNameFromSubquery(pSqlNode, pMetaInfo->pTableName, pCtx, &msgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - } - - taosArraySort(pMetaInfo->pTableName, tnameComparFn); - taosArrayRemoveDuplicate(pMetaInfo->pTableName, tnameComparFn, NULL); - - size_t funcSize = 0; - if (pSqlInfo->funcs) { - funcSize = taosArrayGetSize(pSqlInfo->funcs); - } - - if (funcSize > 0) { - for (size_t i = 0; i < funcSize; ++i) { - SToken* t = taosArrayGet(pSqlInfo->funcs, i); - assert(t != NULL); - - if (t->n >= TSDB_FUNC_NAME_LEN) { - return buildSyntaxErrMsg(&msgBuf, "too long function name", t->z); - } - - // Let's assume that it is an UDF/UDAF, if it is not a built-in function. - bool scalarFunc = false; - if (qIsBuiltinFunction(t->z, t->n, &scalarFunc) < 0) { - char* fname = strndup(t->z, t->n); - taosArrayPush(pMetaInfo->pUdf, &fname); - } - } - } - - return code; -} - -void qParserCleanupMetaRequestInfo(SCatalogReq* pMetaReq) { - if (pMetaReq == NULL) { - return; - } - - taosArrayDestroy(pMetaReq->pTableName); - taosArrayDestroy(pMetaReq->pUdf); -} - -void qDestroyQuery(SQueryNode* pQueryNode) { +void qDestroyQuery(SQuery* pQueryNode) { if (NULL == pQueryNode) { return; } - - int32_t type = queryNodeType(pQueryNode); - if (type == TSDB_SQL_INSERT || type == TSDB_SQL_CREATE_TABLE) { - SVnodeModifOpStmtInfo* pModifInfo = (SVnodeModifOpStmtInfo*)pQueryNode; - taosArrayDestroy(pModifInfo->pDataBlocks); - - tfree(pQueryNode); - } else if (type == TSDB_SQL_SELECT) { - SQueryStmtInfo* pQueryStmtInfo = (SQueryStmtInfo*) pQueryNode; - destroyQueryInfo(pQueryStmtInfo); + nodesDestroyNode(pQueryNode->pRoot); + tfree(pQueryNode->pResSchema); + if (NULL != pQueryNode->pCmdMsg) { + tfree(pQueryNode->pCmdMsg->pMsg); + tfree(pQueryNode->pCmdMsg); } + tfree(pQueryNode); } diff --git a/source/libs/parser/src/parserImpl.c b/source/libs/parser/src/parserImpl.c deleted file mode 100644 index ef040fdff47ff925acfbdc08071147d2eb56bf74..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/parserImpl.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "parserImpl.h" - -#include "astCreateContext.h" -#include "functionMgt.h" -#include "parserInt.h" -#include "tglobal.h" -#include "ttime.h" -#include "ttoken.h" - -typedef void* (*FMalloc)(size_t); -typedef void (*FFree)(void*); - -extern void* NewParseAlloc(FMalloc); -extern void NewParse(void*, int, SToken, void*); -extern void NewParseFree(void*, FFree); -extern void NewParseTrace(FILE*, char*); - -static uint32_t toNewTokenId(uint32_t tokenId) { - switch (tokenId) { - case TK_OR: - return NEW_TK_OR; - case TK_AND: - return NEW_TK_AND; - case TK_UNION: - return NEW_TK_UNION; - case TK_ALL: - return NEW_TK_ALL; - case TK_MINUS: - return NEW_TK_NK_MINUS; - case TK_PLUS: - return NEW_TK_NK_PLUS; - case TK_STAR: - return NEW_TK_NK_STAR; - case TK_SLASH: - return NEW_TK_NK_SLASH; - case TK_REM: - return NEW_TK_NK_REM; - case TK_SHOW: - return NEW_TK_SHOW; - case TK_DATABASES: - return NEW_TK_DATABASES; - case TK_INTEGER: - return NEW_TK_NK_INTEGER; - case TK_FLOAT: - return NEW_TK_NK_FLOAT; - case TK_STRING: - return NEW_TK_NK_STRING; - case TK_BOOL: - return NEW_TK_NK_BOOL; - case TK_TIMESTAMP: - return NEW_TK_TIMESTAMP; - case TK_VARIABLE: - return NEW_TK_NK_VARIABLE; - case TK_COMMA: - return NEW_TK_NK_COMMA; - case TK_ID: - return NEW_TK_NK_ID; - case TK_LP: - return NEW_TK_NK_LP; - case TK_RP: - return NEW_TK_NK_RP; - case TK_DOT: - return NEW_TK_NK_DOT; - case TK_BETWEEN: - return NEW_TK_BETWEEN; - case TK_NOT: - return NEW_TK_NOT; - case TK_IS: - return NEW_TK_IS; - case TK_NULL: - return NEW_TK_NULL; - case TK_LT: - return NEW_TK_NK_LT; - case TK_GT: - return NEW_TK_NK_GT; - case TK_LE: - return NEW_TK_NK_LE; - case TK_GE: - return NEW_TK_NK_GE; - case TK_NE: - return NEW_TK_NK_NE; - case TK_EQ: - return NEW_TK_NK_EQ; - case TK_LIKE: - return NEW_TK_LIKE; - case TK_MATCH: - return NEW_TK_MATCH; - case TK_NMATCH: - return NEW_TK_NMATCH; - case TK_IN: - return NEW_TK_IN; - case TK_SELECT: - return NEW_TK_SELECT; - case TK_DISTINCT: - return NEW_TK_DISTINCT; - case TK_WHERE: - return NEW_TK_WHERE; - case TK_AS: - return NEW_TK_AS; - case TK_FROM: - return NEW_TK_FROM; - case TK_JOIN: - return NEW_TK_JOIN; - // case TK_PARTITION: - // return NEW_TK_PARTITION; - case TK_SESSION: - return NEW_TK_SESSION; - case TK_STATE_WINDOW: - return NEW_TK_STATE_WINDOW; - case TK_INTERVAL: - return NEW_TK_INTERVAL; - case TK_SLIDING: - return NEW_TK_SLIDING; - case TK_FILL: - return NEW_TK_FILL; - // case TK_VALUE: - // return NEW_TK_VALUE; - case TK_NONE: - return NEW_TK_NONE; - case TK_PREV: - return NEW_TK_PREV; - case TK_LINEAR: - return NEW_TK_LINEAR; - // case TK_NEXT: - // return NEW_TK_NEXT; - case TK_GROUP: - return NEW_TK_GROUP; - case TK_HAVING: - return NEW_TK_HAVING; - case TK_ORDER: - return NEW_TK_ORDER; - case TK_BY: - return NEW_TK_BY; - case TK_ASC: - return NEW_TK_ASC; - case TK_DESC: - return NEW_TK_DESC; - case TK_SLIMIT: - return NEW_TK_SLIMIT; - case TK_SOFFSET: - return NEW_TK_SOFFSET; - case TK_LIMIT: - return NEW_TK_LIMIT; - case TK_OFFSET: - return NEW_TK_OFFSET; - case TK_SPACE: - case NEW_TK_ON: - case NEW_TK_INNER: - break; - default: - printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!tokenId = %d\n", tokenId); - } - return tokenId; -} - -static uint32_t getToken(const char* z, uint32_t* tokenId) { - uint32_t n = tGetToken(z, tokenId); - *tokenId = toNewTokenId(*tokenId); - return n; -} - -static EStmtType getStmtType(const SNode* pRootNode) { - if (NULL == pRootNode) { - return STMT_TYPE_CMD; - } - switch (nodeType(pRootNode)) { - case QUERY_NODE_SELECT_STMT: - return STMT_TYPE_QUERY; - default: - break; - } - return STMT_TYPE_CMD; -} - -int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) { - SAstCreateContext cxt; - createAstCreateContext(pParseCxt, &cxt); - void *pParser = NewParseAlloc(malloc); - int32_t i = 0; - while (1) { - SToken t0 = {0}; - if (cxt.pQueryCxt->pSql[i] == 0) { - NewParse(pParser, 0, t0, &cxt); - goto abort_parse; - } - t0.n = getToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type); - t0.z = (char *)(cxt.pQueryCxt->pSql + i); - i += t0.n; - - switch (t0.type) { - case TK_SPACE: - case TK_COMMENT: { - break; - } - case TK_SEMI: { - NewParse(pParser, 0, t0, &cxt); - goto abort_parse; - } - case TK_QUESTION: - case TK_ILLEGAL: { - snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z); - cxt.valid = false; - goto abort_parse; - } - case TK_HEX: - case TK_OCT: - case TK_BIN: { - snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unsupported token: \"%s\"", t0.z); - cxt.valid = false; - goto abort_parse; - } - default: - NewParse(pParser, t0.type, t0, &cxt); - // NewParseTrace(stdout, ""); - if (!cxt.valid) { - goto abort_parse; - } - } - } - -abort_parse: - NewParseFree(pParser, free); - destroyAstCreateContext(&cxt); - pQuery->stmtType = getStmtType(cxt.pRootNode); - pQuery->pRoot = cxt.pRootNode; - return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; -} - -static bool afterGroupBy(ESqlClause clause) { - return clause > SQL_CLAUSE_GROUP_BY; -} - -static bool beforeHaving(ESqlClause clause) { - return clause < SQL_CLAUSE_HAVING; -} - -typedef struct STranslateContext { - SParseContext* pParseCxt; - int32_t errCode; - SMsgBuf msgBuf; - SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode* - int32_t currLevel; - ESqlClause currClause; - SSelectStmt* pCurrStmt; -} STranslateContext; - -static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode); - -static char* getSyntaxErrFormat(int32_t errCode) { - switch (errCode) { - case TSDB_CODE_PAR_INVALID_COLUMN: - return "Invalid column name : %s"; - case TSDB_CODE_PAR_TABLE_NOT_EXIST: - return "Table does not exist : %s"; - case TSDB_CODE_PAR_AMBIGUOUS_COLUMN: - return "Column ambiguously defined : %s"; - case TSDB_CODE_PAR_WRONG_VALUE_TYPE: - return "Invalid value type : %s"; - case TSDB_CODE_PAR_INVALID_FUNTION: - return "Invalid function name : %s"; - case TSDB_CODE_PAR_FUNTION_PARA_NUM: - return "Invalid number of arguments : %s"; - case TSDB_CODE_PAR_FUNTION_PARA_TYPE: - return "Inconsistent datatypes : %s"; - case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION: - return "There mustn't be aggregation"; - case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT: - return "ORDER BY item must be the number of a SELECT-list expression"; - case TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION: - return "Not a GROUP BY expression"; - case TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION: - return "Not SELECTed expression"; - case TSDB_CODE_PAR_NOT_SINGLE_GROUP: - return "Not a single-group group function"; - case TSDB_CODE_OUT_OF_MEMORY: - return "Out of memory"; - default: - return "Unknown error"; - } -} - -static int32_t generateSyntaxErrMsg(STranslateContext* pCxt, int32_t errCode, ...) { - va_list vArgList; - va_start(vArgList, errCode); - vsnprintf(pCxt->msgBuf.buf, pCxt->msgBuf.len, getSyntaxErrFormat(errCode), vArgList); - va_end(vArgList); - pCxt->errCode = errCode; - return errCode; -} - -static int32_t addNamespace(STranslateContext* pCxt, void* pTable) { - size_t currTotalLevel = taosArrayGetSize(pCxt->pNsLevel); - if (currTotalLevel > pCxt->currLevel) { - SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); - taosArrayPush(pTables, &pTable); - } else { - do { - SArray* pTables = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); - if (pCxt->currLevel == currTotalLevel) { - taosArrayPush(pTables, &pTable); - } - taosArrayPush(pCxt->pNsLevel, &pTables); - ++currTotalLevel; - } while (currTotalLevel <= pCxt->currLevel); - } - return TSDB_CODE_SUCCESS; -} - -static SName* toName(int32_t acctId, const SRealTableNode* pRealTable, SName* pName) { - pName->type = TSDB_TABLE_NAME_T; - pName->acctId = acctId; - strcpy(pName->dbname, pRealTable->table.dbName); - strcpy(pName->tname, pRealTable->table.tableName); - return pName; -} - -static bool belongTable(const char* currentDb, const SColumnNode* pCol, const STableNode* pTable) { - int cmp = 0; - if ('\0' != pCol->dbName[0]) { - cmp = strcmp(pCol->dbName, pTable->dbName); - } else { - cmp = (QUERY_NODE_REAL_TABLE == nodeType(pTable) ? strcmp(currentDb, pTable->dbName) : 0); - } - if (0 == cmp) { - cmp = strcmp(pCol->tableAlias, pTable->tableAlias); - } - return (0 == cmp); -} - -static SNodeList* getProjectList(SNode* pNode) { - if (QUERY_NODE_SELECT_STMT == nodeType(pNode)) { - return ((SSelectStmt*)pNode)->pProjectionList; - } - return NULL; -} - -static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, bool isTag, SColumnNode* pCol) { - strcpy(pCol->dbName, pTable->table.dbName); - strcpy(pCol->tableAlias, pTable->table.tableAlias); - strcpy(pCol->tableName, pTable->table.tableName); - strcpy(pCol->colName, pColSchema->name); - if ('\0' == pCol->node.aliasName[0]) { - strcpy(pCol->node.aliasName, pColSchema->name); - } - pCol->tableId = pTable->pMeta->uid; - pCol->colId = pColSchema->colId; - pCol->colType = isTag ? COLUMN_TYPE_TAG : COLUMN_TYPE_COLUMN; - pCol->node.resType.type = pColSchema->type; - pCol->node.resType.bytes = pColSchema->bytes; -} - -static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode* pCol) { - pCol->pProjectRef = (SNode*)pExpr; - nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); - if (NULL != pTable) { - strcpy(pCol->tableAlias, pTable->tableAlias); - } - strcpy(pCol->colName, pExpr->aliasName); - pCol->node.resType = pExpr->resType; -} - -static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode* pTable, SNodeList* pList) { - if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { - const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; - int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns; - for (int32_t i = 0; i < nums; ++i) { - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - } - setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i < pMeta->tableInfo.numOfTags), pCol); - nodesListAppend(pList, (SNode*)pCol); - } - } else { - SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery); - SNode* pNode; - FOREACH(pNode, pProjectList) { - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - } - setColumnInfoByExpr(pTable, (SExprNode*)pNode, pCol); - nodesListAppend(pList, (SNode*)pCol); - } - } - return TSDB_CODE_SUCCESS; -} - -static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) { - bool found = false; - if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { - const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; - int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns; - for (int32_t i = 0; i < nums; ++i) { - if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) { - setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i < pMeta->tableInfo.numOfTags), pCol); - found = true; - break; - } - } - } else { - SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery); - SNode* pNode; - FOREACH(pNode, pProjectList) { - SExprNode* pExpr = (SExprNode*)pNode; - if (0 == strcmp(pCol->colName, pExpr->aliasName)) { - setColumnInfoByExpr(pTable, pExpr, pCol); - found = true; - break; - } - } - } - return found; -} - -static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol) { - SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); - size_t nums = taosArrayGetSize(pTables); - bool foundTable = false; - for (size_t i = 0; i < nums; ++i) { - STableNode* pTable = taosArrayGetP(pTables, i); - if (belongTable(pCxt->pParseCxt->db, pCol, pTable)) { - foundTable = true; - if (findAndSetColumn(pCol, pTable)) { - break; - } - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName); - return DEAL_RES_ERROR; - } - } - if (!foundTable) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_TABLE_NOT_EXIST, pCol->tableAlias); - return DEAL_RES_ERROR; - } - return DEAL_RES_CONTINUE; -} - -static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNode* pCol) { - SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); - size_t nums = taosArrayGetSize(pTables); - bool found = false; - for (size_t i = 0; i < nums; ++i) { - STableNode* pTable = taosArrayGetP(pTables, i); - if (findAndSetColumn(pCol, pTable)) { - if (found) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName); - return DEAL_RES_ERROR; - } - found = true; - } - } - if (!found) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName); - return DEAL_RES_ERROR; - } - return DEAL_RES_CONTINUE; -} - -static bool translateColumnUseAlias(STranslateContext* pCxt, SColumnNode* pCol) { - SNodeList* pProjectionList = pCxt->pCurrStmt->pProjectionList; - SNode* pNode; - FOREACH(pNode, pProjectionList) { - SExprNode* pExpr = (SExprNode*)pNode; - if (0 == strcmp(pCol->colName, pExpr->aliasName)) { - setColumnInfoByExpr(NULL, pExpr, pCol); - return true; - } - } - return false; -} - -static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode* pCol) { - // count(*)/first(*)/last(*) - if (0 == strcmp(pCol->colName, "*")) { - return DEAL_RES_CONTINUE; - } - if ('\0' != pCol->tableAlias[0]) { - return translateColumnWithPrefix(pCxt, pCol); - } - bool found = false; - if (SQL_CLAUSE_ORDER_BY == pCxt->currClause) { - found = translateColumnUseAlias(pCxt, pCol); - } - return found ? DEAL_RES_CONTINUE : translateColumnWithoutPrefix(pCxt, pCol); -} - -static int32_t trimStringCopy(const char* src, int32_t len, char* dst) { - varDataSetLen(dst, len); - char* dstVal = varDataVal(dst); - // delete escape character: \\, \', \" - char delim = src[0]; - int32_t cnt = 0; - int32_t j = 0; - for (uint32_t k = 1; k < len - 1; ++k) { - if (src[k] == '\\' || (src[k] == delim && src[k + 1] == delim)) { - dstVal[j] = src[k + 1]; - cnt++; - j++; - k++; - continue; - } - dstVal[j] = src[k]; - j++; - } - dstVal[j] = '\0'; - return j; -} - -static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) { - if (pVal->isDuration) { - char unit = 0; - if (parseAbsoluteDuration(pVal->literal, strlen(pVal->literal), &pVal->datum.i, &unit, pVal->node.resType.precision) != TSDB_CODE_SUCCESS) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal); - return DEAL_RES_ERROR; - } - } else { - switch (pVal->node.resType.type) { - case TSDB_DATA_TYPE_NULL: - break; - case TSDB_DATA_TYPE_BOOL: - pVal->datum.b = (0 == strcasecmp(pVal->literal, "true")); - break; - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_BIGINT: { - char* endPtr = NULL; - pVal->datum.i = strtoll(pVal->literal, &endPtr, 10); - break; - } - case TSDB_DATA_TYPE_UTINYINT: - case TSDB_DATA_TYPE_USMALLINT: - case TSDB_DATA_TYPE_UINT: - case TSDB_DATA_TYPE_UBIGINT: { - char* endPtr = NULL; - pVal->datum.u = strtoull(pVal->literal, &endPtr, 10); - break; - } - case TSDB_DATA_TYPE_FLOAT: - case TSDB_DATA_TYPE_DOUBLE: { - char* endPtr = NULL; - pVal->datum.d = strtold(pVal->literal, &endPtr); - break; - } - case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_NCHAR: - case TSDB_DATA_TYPE_VARCHAR: - case TSDB_DATA_TYPE_VARBINARY: { - int32_t n = strlen(pVal->literal); - pVal->datum.p = calloc(1, n + VARSTR_HEADER_SIZE); - if (NULL == pVal->datum.p) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - return DEAL_RES_ERROR; - } - trimStringCopy(pVal->literal, n, pVal->datum.p); - break; - } - case TSDB_DATA_TYPE_TIMESTAMP: { - int32_t n = strlen(pVal->literal); - char* tmp = calloc(1, n); - if (NULL == tmp) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - return DEAL_RES_ERROR; - } - int32_t len = trimStringCopy(pVal->literal, n, tmp); - if (taosParseTime(tmp, &pVal->datum.i, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) { - tfree(tmp); - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal); - return DEAL_RES_ERROR; - } - tfree(tmp); - break; - } - case TSDB_DATA_TYPE_JSON: - case TSDB_DATA_TYPE_DECIMAL: - case TSDB_DATA_TYPE_BLOB: - // todo - default: - break; - } - } - return DEAL_RES_CONTINUE; -} - -static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) { - SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType; - SDataType rdt = ((SExprNode*)(pOp->pRight))->resType; - if (nodesIsArithmeticOp(pOp)) { - if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || - TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); - return DEAL_RES_ERROR; - } - pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE; - pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; - } else if (nodesIsComparisonOp(pOp)) { - if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || - TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); - return DEAL_RES_ERROR; - } - pOp->node.resType.type = TSDB_DATA_TYPE_BOOL; - pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; - } else { - // todo json operator - } - return DEAL_RES_CONTINUE; -} - -static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) { - if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName); - return DEAL_RES_ERROR; - } - int32_t code = fmGetFuncResultType(pFunc); - if (TSDB_CODE_SUCCESS != code) { - generateSyntaxErrMsg(pCxt, code, pFunc->functionName); - return DEAL_RES_ERROR; - } - if (fmIsAggFunc(pFunc->funcId) && beforeHaving(pCxt->currClause)) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION); - return DEAL_RES_ERROR; - } - return DEAL_RES_CONTINUE; -} - -static EDealRes translateExprSubquery(STranslateContext* pCxt, SNode* pNode) { - return (TSDB_CODE_SUCCESS == translateSubquery(pCxt, pNode) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR); -} - -static EDealRes translateLogicCond(STranslateContext* pCxt, SLogicConditionNode* pCond) { - pCond->node.resType.type = TSDB_DATA_TYPE_BOOL; - pCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; - return DEAL_RES_CONTINUE; -} - -static EDealRes doTranslateExpr(SNode* pNode, void* pContext) { - STranslateContext* pCxt = (STranslateContext*)pContext; - switch (nodeType(pNode)) { - case QUERY_NODE_COLUMN: - return translateColumn(pCxt, (SColumnNode*)pNode); - case QUERY_NODE_VALUE: - return translateValue(pCxt, (SValueNode*)pNode); - case QUERY_NODE_OPERATOR: - return translateOperator(pCxt, (SOperatorNode*)pNode); - case QUERY_NODE_FUNCTION: - return translateFunction(pCxt, (SFunctionNode*)pNode); - case QUERY_NODE_LOGIC_CONDITION: - return translateLogicCond(pCxt, (SLogicConditionNode*)pNode); - case QUERY_NODE_TEMP_TABLE: - return translateExprSubquery(pCxt, ((STempTableNode*)pNode)->pSubquery); - default: - break; - } - return DEAL_RES_CONTINUE; -} - -static int32_t translateExpr(STranslateContext* pCxt, SNode* pNode) { - nodesWalkNodePostOrder(pNode, doTranslateExpr, pCxt); - return pCxt->errCode; -} - -static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) { - nodesWalkListPostOrder(pList, doTranslateExpr, pCxt); - return pCxt->errCode; -} - -static bool isAliasColumn(SColumnNode* pCol) { - return ('\0' == pCol->tableAlias[0]); -} - -static bool isDistinctOrderBy(STranslateContext* pCxt) { - return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct); -} - -static SNodeList* getGroupByList(STranslateContext* pCxt) { - if (isDistinctOrderBy(pCxt)) { - return pCxt->pCurrStmt->pProjectionList; - } - return pCxt->pCurrStmt->pGroupByList; -} - -static SNode* getGroupByNode(SNode* pNode) { - if (QUERY_NODE_GROUPING_SET == nodeType(pNode)) { - return nodesListGetNode(((SGroupingSetNode*)pNode)->pParameterList, 0); - } - return pNode; -} - -static int32_t getGroupByErrorCode(STranslateContext* pCxt) { - if (isDistinctOrderBy(pCxt)) { - return TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION; - } - return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION; -} - -static EDealRes doCheckExprForGroupBy(SNode* pNode, void* pContext) { - STranslateContext* pCxt = (STranslateContext*)pContext; - if (!nodesIsExprNode(pNode) || (QUERY_NODE_COLUMN == nodeType(pNode) && isAliasColumn((SColumnNode*)pNode))) { - return DEAL_RES_CONTINUE; - } - if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId) && !isDistinctOrderBy(pCxt)) { - return DEAL_RES_IGNORE_CHILD; - } - SNode* pGroupNode; - FOREACH(pGroupNode, getGroupByList(pCxt)) { - if (nodesEqualNode(getGroupByNode(pGroupNode), pNode)) { - return DEAL_RES_IGNORE_CHILD; - } - } - if (QUERY_NODE_COLUMN == nodeType(pNode) || - (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId) && isDistinctOrderBy(pCxt))) { - generateSyntaxErrMsg(pCxt, getGroupByErrorCode(pCxt)); - return DEAL_RES_ERROR; - } - return DEAL_RES_CONTINUE; -} - -static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode* pNode) { - nodesWalkNode(pNode, doCheckExprForGroupBy, pCxt); - return pCxt->errCode; -} - -static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList) { - if (NULL == getGroupByList(pCxt)) { - return TSDB_CODE_SUCCESS; - } - nodesWalkList(pList, doCheckExprForGroupBy, pCxt); - return pCxt->errCode; -} - -typedef struct CheckAggColCoexistCxt { - STranslateContext* pTranslateCxt; - bool existAggFunc; - bool existCol; -} CheckAggColCoexistCxt; - -static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) { - CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext; - if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) { - pCxt->existAggFunc = true; - return DEAL_RES_IGNORE_CHILD; - } - if (QUERY_NODE_COLUMN == nodeType(pNode)) { - pCxt->existCol = true; - } - return DEAL_RES_CONTINUE; -} - -static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) { - if (NULL != pSelect->pGroupByList) { - return TSDB_CODE_SUCCESS; - } - CheckAggColCoexistCxt cxt = { .pTranslateCxt = pCxt, .existAggFunc = false, .existCol = false }; - nodesWalkList(pSelect->pProjectionList, doCheckAggColCoexist, &cxt); - if (!pSelect->isDistinct) { - nodesWalkList(pSelect->pOrderByList, doCheckAggColCoexist, &cxt); - } - if (cxt.existAggFunc && cxt.existCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_NOT_SINGLE_GROUP); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) { - int32_t code = TSDB_CODE_SUCCESS; - switch (nodeType(pTable)) { - case QUERY_NODE_REAL_TABLE: { - SRealTableNode* pRealTable = (SRealTableNode*)pTable; - SName name; - code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &(pCxt->pParseCxt->mgmtEpSet), - toName(pCxt->pParseCxt->acctId, pRealTable, &name), &(pRealTable->pMeta)); - if (TSDB_CODE_SUCCESS != code) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_TABLE_NOT_EXIST, pRealTable->table.tableName); - } - code = addNamespace(pCxt, pRealTable); - break; - } - case QUERY_NODE_TEMP_TABLE: { - STempTableNode* pTempTable = (STempTableNode*)pTable; - code = translateSubquery(pCxt, pTempTable->pSubquery); - if (TSDB_CODE_SUCCESS == code) { - code = addNamespace(pCxt, pTempTable); - } - break; - } - case QUERY_NODE_JOIN_TABLE: { - SJoinTableNode* pJoinTable = (SJoinTableNode*)pTable; - code = translateTable(pCxt, pJoinTable->pLeft); - if (TSDB_CODE_SUCCESS == code) { - code = translateTable(pCxt, pJoinTable->pRight); - } - if (TSDB_CODE_SUCCESS == code) { - code = translateExpr(pCxt, pJoinTable->pOnCond); - } - break; - } - default: - break; - } - return code; -} - -static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool* pIsSelectStar) { - if (NULL == pSelect->pProjectionList) { // select * ... - SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); - size_t nums = taosArrayGetSize(pTables); - pSelect->pProjectionList = nodesMakeList(); - if (NULL == pSelect->pProjectionList) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - } - for (size_t i = 0; i < nums; ++i) { - STableNode* pTable = taosArrayGetP(pTables, i); - int32_t code = createColumnNodeByTable(pCxt, pTable, pSelect->pProjectionList); - if (TSDB_CODE_SUCCESS != code) { - return code; - } - } - *pIsSelectStar = true; - } else { - - } - return TSDB_CODE_SUCCESS; -} - -static int32_t getPositionValue(const SValueNode* pVal) { - switch (pVal->node.resType.type) { - case TSDB_DATA_TYPE_NULL: - case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_TIMESTAMP: - case TSDB_DATA_TYPE_NCHAR: - case TSDB_DATA_TYPE_VARCHAR: - case TSDB_DATA_TYPE_VARBINARY: - case TSDB_DATA_TYPE_JSON: - return -1; - case TSDB_DATA_TYPE_BOOL: - return (pVal->datum.b ? 1 : 0); - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_BIGINT: - return pVal->datum.i; - case TSDB_DATA_TYPE_FLOAT: - case TSDB_DATA_TYPE_DOUBLE: - return pVal->datum.d; - case TSDB_DATA_TYPE_UTINYINT: - case TSDB_DATA_TYPE_USMALLINT: - case TSDB_DATA_TYPE_UINT: - case TSDB_DATA_TYPE_UBIGINT: - return pVal->datum.u; - default: - break; - } - return -1; -} - -static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) { - *pOther = false; - SNode* pNode; - FOREACH(pNode, pOrderByList) { - SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr; - if (QUERY_NODE_VALUE == nodeType(pExpr)) { - SValueNode* pVal = (SValueNode*)pExpr; - if (!translateValue(pCxt, pVal)) { - return pCxt->errCode; - } - int32_t pos = getPositionValue(pVal); - if (pos < 0) { - ERASE_NODE(pOrderByList); - continue; - } else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT); - } else { - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - } - setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), pCol); - ((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol; - nodesDestroyNode(pExpr); - } - } else { - *pOther = true; - } - } - return TSDB_CODE_SUCCESS; -} - -static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) { - bool other; - int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other); - if (TSDB_CODE_SUCCESS != code) { - return code; - } - if (!other) { - return TSDB_CODE_SUCCESS; - } - pCxt->currClause = SQL_CLAUSE_ORDER_BY; - code = translateExprList(pCxt, pSelect->pOrderByList); - if (TSDB_CODE_SUCCESS == code) { - code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList); - } - return code; -} - -static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) { - bool isSelectStar = false; - int32_t code = translateStar(pCxt, pSelect, &isSelectStar); - if (TSDB_CODE_SUCCESS == code && !isSelectStar) { - pCxt->currClause = SQL_CLAUSE_SELECT; - code = translateExprList(pCxt, pSelect->pProjectionList); - } - if (TSDB_CODE_SUCCESS == code) { - code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList); - } - return code; -} - -static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) { - if (NULL == pSelect->pGroupByList && NULL != pSelect->pHaving) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION); - } - pCxt->currClause = SQL_CLAUSE_HAVING; - int32_t code = translateExpr(pCxt, pSelect->pHaving); - if (TSDB_CODE_SUCCESS == code) { - code = checkExprForGroupBy(pCxt, pSelect->pHaving); - } - return code; -} - -static int32_t translateGroupBy(STranslateContext* pCxt, SNodeList* pGroupByList) { - pCxt->currClause = SQL_CLAUSE_GROUP_BY; - return translateExprList(pCxt, pGroupByList); -} - -static int32_t translateWindow(STranslateContext* pCxt, SNode* pWindow) { - pCxt->currClause = SQL_CLAUSE_WINDOW; - return translateExpr(pCxt, pWindow); -} - -static int32_t translatePartitionBy(STranslateContext* pCxt, SNodeList* pPartitionByList) { - pCxt->currClause = SQL_CLAUSE_PARTITION_BY; - return translateExprList(pCxt, pPartitionByList); -} - -static int32_t translateWhere(STranslateContext* pCxt, SNode* pWhere) { - pCxt->currClause = SQL_CLAUSE_WHERE; - return translateExpr(pCxt, pWhere); -} - -static int32_t translateFrom(STranslateContext* pCxt, SNode* pTable) { - pCxt->currClause = SQL_CLAUSE_FROM; - return translateTable(pCxt, pTable); -} - -static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) { - pCxt->pCurrStmt = pSelect; - int32_t code = translateFrom(pCxt, pSelect->pFromTable); - if (TSDB_CODE_SUCCESS == code) { - code = translateWhere(pCxt, pSelect->pWhere); - } - if (TSDB_CODE_SUCCESS == code) { - code = translatePartitionBy(pCxt, pSelect->pPartitionByList); - } - if (TSDB_CODE_SUCCESS == code) { - code = translateWindow(pCxt, pSelect->pWindow); - } - if (TSDB_CODE_SUCCESS == code) { - code = translateGroupBy(pCxt, pSelect->pGroupByList); - } - if (TSDB_CODE_SUCCESS == code) { - code = translateHaving(pCxt, pSelect); - } - if (TSDB_CODE_SUCCESS == code) { - code = translateSelectList(pCxt, pSelect); - } - if (TSDB_CODE_SUCCESS == code) { - code = translateOrderBy(pCxt, pSelect); - } - if (TSDB_CODE_SUCCESS == code) { - code = checkAggColCoexist(pCxt, pSelect); - } - return code; -} - -static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { - int32_t code = TSDB_CODE_SUCCESS; - switch (nodeType(pNode)) { - case QUERY_NODE_SELECT_STMT: - code = translateSelect(pCxt, (SSelectStmt*)pNode); - break; - default: - break; - } - return code; -} - -static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) { - ++(pCxt->currLevel); - ESqlClause currClause = pCxt->currClause; - SSelectStmt* pCurrStmt = pCxt->pCurrStmt; - int32_t code = translateQuery(pCxt, pNode); - --(pCxt->currLevel); - pCxt->currClause = currClause; - pCxt->pCurrStmt = pCurrStmt; - return code; -} - -int32_t setReslutSchema(STranslateContext* pCxt, SQuery* pQuery) { - if (QUERY_NODE_SELECT_STMT == nodeType(pQuery->pRoot)) { - SSelectStmt* pSelect = (SSelectStmt*)pQuery->pRoot; - pQuery->numOfResCols = LIST_LENGTH(pSelect->pProjectionList); - pQuery->pResSchema = calloc(pQuery->numOfResCols, sizeof(SSchema)); - if (NULL == pQuery->pResSchema) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); - } - SNode* pNode; - int32_t index = 0; - FOREACH(pNode, pSelect->pProjectionList) { - SExprNode* pExpr = (SExprNode*)pNode; - pQuery->pResSchema[index].type = pExpr->resType.type; - pQuery->pResSchema[index].bytes = pExpr->resType.bytes; - strcpy(pQuery->pResSchema[index].name, pExpr->aliasName); - } - } - return TSDB_CODE_SUCCESS; -} - -int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) { - STranslateContext cxt = { - .pParseCxt = pParseCxt, - .errCode = TSDB_CODE_SUCCESS, - .msgBuf = { .buf = pParseCxt->pMsg, .len = pParseCxt->msgLen }, - .pNsLevel = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES), - .currLevel = 0, - .currClause = 0 - }; - int32_t code = fmFuncMgtInit(); - if (TSDB_CODE_SUCCESS == code) { - code = translateQuery(&cxt, pQuery->pRoot); - } - if (TSDB_CODE_SUCCESS == code && STMT_TYPE_QUERY == pQuery->stmtType) { - code = setReslutSchema(&cxt, pQuery); - } - return code; -} - -int32_t parser(SParseContext* pParseCxt, SQuery* pQuery) { - int32_t code = doParse(pParseCxt, pQuery); - if (TSDB_CODE_SUCCESS == code) { - code = doTranslate(pParseCxt, pQuery); - } - return code; -} diff --git a/source/libs/parser/src/parserUtil.c b/source/libs/parser/src/parserUtil.c deleted file mode 100644 index ec68980c447ac5324660779949533d0826480480..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/parserUtil.c +++ /dev/null @@ -1,1946 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "parserUtil.h" -#include -#include -#include "function.h" -#include "parser.h" -#include "parserInt.h" -#include "queryInfoUtil.h" -#include "taoserror.h" -#include "tbuffer.h" -#include "thash.h" -#include "tmsg.h" -#include "tmsgtype.h" -#include "ttypes.h" -#include "tutil.h" - -typedef struct STableFilterCond { - uint64_t uid; - int16_t idx; //table index - int32_t len; // length of tag query condition data - char * cond; -} STableFilterCond; - -static STableMetaInfo* addTableMetaInfo(SQueryStmtInfo* pQueryInfo, SName* name, STableMeta* pTableMeta, - SVgroupsInfo* vgroupList, SArray* pTagCols, SArray* pVgroupTables); - -int32_t parserValidateIdToken(SToken* pToken) { - if (pToken == NULL || pToken->z == NULL || pToken->type != TK_ID) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // it is a token quoted with escape char '`' - if (pToken->z[0] == TS_ESCAPE_CHAR && pToken->z[pToken->n - 1] == TS_ESCAPE_CHAR) { - return TSDB_CODE_SUCCESS; - } - - char* sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true); - if (sep == NULL) { // It is a single part token, not a complex type - if (isNumber(pToken)) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - strntolower(pToken->z, pToken->z, pToken->n); - } else { // two part - int32_t oldLen = pToken->n; - char* pStr = pToken->z; - - if (pToken->type == TK_SPACE) { - pToken->n = (uint32_t)strtrim(pToken->z); - } - - pToken->n = tGetToken(pToken->z, &pToken->type); - if (pToken->z[pToken->n] != TS_PATH_DELIMITER[0]) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (pToken->type != TK_ID) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - int32_t firstPartLen = pToken->n; - - pToken->z = sep + 1; - pToken->n = (uint32_t)(oldLen - (sep - pStr) - 1); - int32_t len = tGetToken(pToken->z, &pToken->type); - if (len != pToken->n || pToken->type != TK_ID) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // re-build the whole name string - if (pStr[firstPartLen] == TS_PATH_DELIMITER[0]) { - // first part do not have quote do nothing - } else { - pStr[firstPartLen] = TS_PATH_DELIMITER[0]; - memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n); - uint32_t offset = (uint32_t)(pToken->z - (pStr + firstPartLen + 1)); - memset(pToken->z + pToken->n - offset, ' ', offset); - } - - pToken->n += (firstPartLen + sizeof(TS_PATH_DELIMITER[0])); - pToken->z = pStr; - - strntolower(pToken->z, pToken->z, pToken->n); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t parserValidatePassword(SToken* pToken, SMsgBuf* pMsgBuf) { - const char* msg1 = "password can not be empty"; - const char* msg2 = "name or password too long"; - const char* msg3 = "password needs single quote marks enclosed"; - - if (pToken->type != TK_STRING) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - strdequote(pToken->z); - - pToken->n = (uint32_t)strtrim(pToken->z); // trim space before and after passwords - if (pToken->n <= 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - if (pToken->n >= TSDB_USET_PASSWORD_LEN) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t parserValidateNameToken(SToken* pToken) { - if (pToken == NULL || pToken->z == NULL || pToken->type != TK_ID || pToken->n == 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // it is a token quoted with escape char '`' - if (pToken->z[0] == TS_ESCAPE_CHAR && pToken->z[pToken->n - 1] == TS_ESCAPE_CHAR) { - pToken->n = strdequote(pToken->z); - return TSDB_CODE_SUCCESS; - } - - char* sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true); - if (sep != NULL) { // It is a complex type, not allow - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - strntolower(pToken->z, pToken->z, pToken->n); - return TSDB_CODE_SUCCESS; -} - -int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) { - strncpy(pBuf->buf, msg, pBuf->len); - return TSDB_CODE_TSC_INVALID_OPERATION; -} - -int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) { - const char* msgFormat1 = "syntax error near \'%s\'"; - const char* msgFormat2 = "syntax error near \'%s\' (%s)"; - const char* msgFormat3 = "%s"; - - const char* prefix = "syntax error"; - if (sourceStr == NULL) { - assert(additionalInfo != NULL); - snprintf(pBuf->buf, pBuf->len, msgFormat1, additionalInfo); - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - } - - char buf[64] = {0}; // only extract part of sql string - strncpy(buf, sourceStr, tListLen(buf) - 1); - - if (additionalInfo != NULL) { - snprintf(pBuf->buf, pBuf->len, msgFormat2, buf, additionalInfo); - } else { - const char* msgFormat = (0 == strncmp(sourceStr, prefix, strlen(prefix))) ? msgFormat3 : msgFormat1; - snprintf(pBuf->buf, pBuf->len, msgFormat, buf); - } - - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; -} - -SCond* getSTableQueryCond(STagCond* pTagCond, uint64_t uid) { - if (pTagCond->pCond == NULL) { - return NULL; - } - - size_t size = taosArrayGetSize(pTagCond->pCond); - for (int32_t i = 0; i < size; ++i) { - SCond* pCond = taosArrayGet(pTagCond->pCond, i); - - if (uid == pCond->uid) { - return pCond; - } - } - - return NULL; -} - -STableFilterCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx) { - if (filters == NULL) { - return NULL; - } - - size_t size = taosArrayGetSize(filters); - for (int32_t i = 0; i < size; ++i) { - STableFilterCond* cond = taosArrayGet(filters, i); - - if (uid == cond->uid && (idx >= 0 && cond->idx == idx)) { - return cond; - } - } - - return NULL; -} - -void setSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) { - if (tbufTell(bw) == 0) { - return; - } - - SCond cond = { - .uid = uid, - .len = (int32_t)(tbufTell(bw)), - .cond = NULL, - }; - - cond.cond = tbufGetData(bw, true); - - if (pTagCond->pCond == NULL) { - pTagCond->pCond = taosArrayInit(3, sizeof(SCond)); - } - - taosArrayPush(pTagCond->pCond, &cond); -} - -//typedef struct SJoinStatus { -// SSDataBlock* pBlock; // point to the upstream block -// int32_t index; -// bool completed;// current upstream is completed or not -//} SJoinStatus; - -/* -static void createInputDataFilterInfo(SQueryStmtInfo* px, int32_t numOfCol1, int32_t* numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo) { - SColumnInfo* tableCols = calloc(numOfCol1, sizeof(SColumnInfo)); - for(int32_t i = 0; i < numOfCol1; ++i) { - SColumn* pCol = taosArrayGetP(px->colList, i); - if (pCol->info.flist.numOfFilters > 0) { - (*numOfFilterCols) += 1; - } - - tableCols[i] = pCol->info; - } - - if ((*numOfFilterCols) > 0) { - doCreateFilterInfo(tableCols, numOfCol1, (*numOfFilterCols), pFilterInfo, 0); - } - - tfree(tableCols); -} -*/ - -//void destroyTableNameList(SInsertStatementParam* pInsertParam) { -// if (pInsertParam->numOfTables == 0) { -// assert(pInsertParam->pTableNameList == NULL); -// return; -// } -// -// for(int32_t i = 0; i < pInsertParam->numOfTables; ++i) { -// tfree(pInsertParam->pTableNameList[i]); -// } -// -// pInsertParam->numOfTables = 0; -// tfree(pInsertParam->pTableNameList); -//} - -//void tscDestroyBoundColumnInfo(SParsedDataColInfo* pColInfo) { -// tfree(pColInfo->boundedColumns); -// tfree(pColInfo->cols); -// tfree(pColInfo->colIdxInfo); -//} -// -//void tscDestroyDataBlock(STableDataBlocks* pDataBlock, bool removeMeta) { -// if (pDataBlock == NULL) { -// return; -// } -// -// tfree(pDataBlock->pData); -// -// if (removeMeta) { -// char name[TSDB_TABLE_FNAME_LEN] = {0}; -// tNameExtractFullName(&pDataBlock->tableName, name); -// -// taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN)); -// } -// -// if (!pDataBlock->cloned) { -// tfree(pDataBlock->params); -// -// // free the refcount for metermeta -// if (pDataBlock->pTableMeta != NULL) { -// tfree(pDataBlock->pTableMeta); -// } -// -// tscDestroyBoundColumnInfo(&pDataBlock->boundColumnInfo); -// } -// -// tfree(pDataBlock); -//} - -//SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, int16_t bytes, -// uint32_t offset) { -// uint32_t needed = pDataBlock->numOfParams + 1; -// if (needed > pDataBlock->numOfAllocedParams) { -// needed *= 2; -// void* tmp = realloc(pDataBlock->params, needed * sizeof(SParamInfo)); -// if (tmp == NULL) { -// return NULL; -// } -// pDataBlock->params = (SParamInfo*)tmp; -// pDataBlock->numOfAllocedParams = needed; -// } -// -// SParamInfo* param = pDataBlock->params + pDataBlock->numOfParams; -// param->idx = -1; -// param->type = type; -// param->timePrec = timePrec; -// param->bytes = bytes; -// param->offset = offset; -// -// ++pDataBlock->numOfParams; -// return param; -//} - -//void* tscDestroyBlockArrayList(SArray* pDataBlockList) { -// if (pDataBlockList == NULL) { -// return NULL; -// } -// -// size_t size = taosArrayGetSize(pDataBlockList); -// for (int32_t i = 0; i < size; i++) { -// void* d = taosArrayGetP(pDataBlockList, i); -// tscDestroyDataBlock(d, false); -// } -// -// taosArrayDestroy(pDataBlockList); -// return NULL; -//} - - -//void freeUdfInfo(SUdfInfo* pUdfInfo) { -// if (pUdfInfo == NULL) { -// return; -// } -// -// if (pUdfInfo->funcs[TSDB_UDF_FUNC_DESTROY]) { -// (*(udfDestroyFunc)pUdfInfo->funcs[TSDB_UDF_FUNC_DESTROY])(&pUdfInfo->init); -// } -// -// tfree(pUdfInfo->name); -// -// if (pUdfInfo->path) { -// unlink(pUdfInfo->path); -// } -// -// tfree(pUdfInfo->path); -// -// tfree(pUdfInfo->content); -// -// taosCloseDll(pUdfInfo->handle); -//} - -//void* tscDestroyUdfArrayList(SArray* pUdfList) { -// if (pUdfList == NULL) { -// return NULL; -// } -// -// size_t size = taosArrayGetSize(pUdfList); -// for (int32_t i = 0; i < size; i++) { -// SUdfInfo* udf = taosArrayGet(pUdfList, i); -// freeUdfInfo(udf); -// } -// -// taosArrayDestroy(pUdfList); -// return NULL; -//} - -//void* tscDestroyBlockHashTable(SHashObj* pBlockHashTable, bool removeMeta) { -// if (pBlockHashTable == NULL) { -// return NULL; -// } -// -// STableDataBlocks** p = taosHashIterate(pBlockHashTable, NULL); -// while(p) { -// tscDestroyDataBlock(*p, removeMeta); -// p = taosHashIterate(pBlockHashTable, p); -// } -// -// taosHashCleanup(pBlockHashTable); -// return NULL; -//} - -/** - * create the in-memory buffer for each table to keep the submitted data block - * @param initialSize - * @param rowSize - * @param startOffset - * @param name - * @param dataBlocks - * @return - */ -// int32_t tscCreateDataBlock(size_t defaultSize, int32_t rowSize, int32_t startOffset, SName* name, -// STableMeta* pTableMeta, STableDataBlocks** dataBlocks) { -// STableDataBlocks* dataBuf = (STableDataBlocks*)calloc(1, sizeof(STableDataBlocks)); -// if (dataBuf == NULL) { -// tscError("failed to allocated memory, reason:%s", strerror(errno)); -// return TSDB_CODE_TSC_OUT_OF_MEMORY; -// } -// -// dataBuf->nAllocSize = (uint32_t)defaultSize; -// dataBuf->headerSize = startOffset; -// -// // the header size will always be the startOffset value, reserved for the subumit block header -// if (dataBuf->nAllocSize <= dataBuf->headerSize) { -// dataBuf->nAllocSize = dataBuf->headerSize * 2; -// } -// -// //dataBuf->pData = calloc(1, dataBuf->nAllocSize); -// dataBuf->pData = malloc(dataBuf->nAllocSize); -// if (dataBuf->pData == NULL) { -// tscError("failed to allocated memory, reason:%s", strerror(errno)); -// tfree(dataBuf); -// return TSDB_CODE_TSC_OUT_OF_MEMORY; -// } -// memset(dataBuf->pData, 0, sizeof(SSubmitBlk)); -// -// //Here we keep the tableMeta to avoid it to be remove by other threads. -// dataBuf->pTableMeta = tscTableMetaDup(pTableMeta); -// -// SParsedDataColInfo* pColInfo = &dataBuf->boundColumnInfo; -// SSchema* pSchema = getTableColumnSchema(dataBuf->pTableMeta); -// tscSetBoundColumnInfo(pColInfo, pSchema, dataBuf->pTableMeta->tableInfo.numOfColumns); -// -// dataBuf->ordered = true; -// dataBuf->prevTS = INT64_MIN; -// dataBuf->rowSize = rowSize; -// dataBuf->size = startOffset; -// dataBuf->tsSource = -1; -// dataBuf->vgId = dataBuf->pTableMeta->vgId; -// -// tNameAssign(&dataBuf->tableName, name); -// -// assert(defaultSize > 0 && pTableMeta != NULL && dataBuf->pTableMeta != NULL); -// -// *dataBlocks = dataBuf; -// return TSDB_CODE_SUCCESS; -//} -// -// int32_t tscGetDataBlockFromList(SHashObj* pHashList, int64_t id, int32_t size, int32_t startOffset, int32_t rowSize, -// SName* name, STableMeta* pTableMeta, STableDataBlocks** dataBlocks, -// SArray* pBlockList) { -// *dataBlocks = NULL; -// STableDataBlocks** t1 = (STableDataBlocks**)taosHashGet(pHashList, (const char*)&id, sizeof(id)); -// if (t1 != NULL) { -// *dataBlocks = *t1; -// } -// -// if (*dataBlocks == NULL) { -// int32_t ret = tscCreateDataBlock((size_t)size, rowSize, startOffset, name, pTableMeta, dataBlocks); -// if (ret != TSDB_CODE_SUCCESS) { -// return ret; -// } -// -// taosHashPut(pHashList, (const char*)&id, sizeof(int64_t), (char*)dataBlocks, POINTER_BYTES); -// if (pBlockList) { -// taosArrayPush(pBlockList, dataBlocks); -// } -// } -// -// return TSDB_CODE_SUCCESS; -//} -// -//// Erase the empty space reserved for binary data -// static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SInsertStatementParam* insertParam, -// SBlockKeyTuple* blkKeyTuple) { -// // TODO: optimize this function, handle the case while binary is not presented -// STableMeta* pTableMeta = pTableDataBlock->pTableMeta; -// STableComInfo tinfo = tscGetTableInfo(pTableMeta); -// SSchema* pSchema = getTableColumnSchema(pTableMeta); -// -// SSubmitBlk* pBlock = pDataBlock; -// memcpy(pDataBlock, pTableDataBlock->pData, sizeof(SSubmitBlk)); -// pDataBlock = (char*)pDataBlock + sizeof(SSubmitBlk); -// -// int32_t flen = 0; // original total length of row -// -// // schema needs to be included into the submit data block -// if (insertParam->schemaAttached) { -// int32_t numOfCols = tscGetNumOfColumns(pTableDataBlock->pTableMeta); -// for(int32_t j = 0; j < numOfCols; ++j) { -// STColumn* pCol = (STColumn*) pDataBlock; -// pCol->colId = htons(pSchema[j].colId); -// pCol->type = pSchema[j].type; -// pCol->bytes = htons(pSchema[j].bytes); -// pCol->offset = 0; -// -// pDataBlock = (char*)pDataBlock + sizeof(STColumn); -// flen += TYPE_BYTES[pSchema[j].type]; -// } -// -// int32_t schemaSize = sizeof(STColumn) * numOfCols; -// pBlock->schemaLen = schemaSize; -// } else { -// if (IS_RAW_PAYLOAD(insertParam->payloadType)) { -// for (int32_t j = 0; j < tinfo.numOfColumns; ++j) { -// flen += TYPE_BYTES[pSchema[j].type]; -// } -// } -// pBlock->schemaLen = 0; -// } -// -// char* p = pTableDataBlock->pData + sizeof(SSubmitBlk); -// pBlock->dataLen = 0; -// int32_t numOfRows = htons(pBlock->numOfRows); -// -// if (IS_RAW_PAYLOAD(insertParam->payloadType)) { -// for (int32_t i = 0; i < numOfRows; ++i) { -// STSRow* memRow = (STSRow*)pDataBlock; -// memRowSetType(memRow, SMEM_ROW_DATA); -// SDataRow trow = memRowDataBody(memRow); -// dataRowSetLen(trow, (uint16_t)(TD_DATA_ROW_HEAD_SIZE + flen)); -// dataRowSetVersion(trow, pTableMeta->sversion); -// -// int toffset = 0; -// for (int32_t j = 0; j < tinfo.numOfColumns; j++) { -// tdAppendColVal(trow, p, pSchema[j].type, toffset); -// toffset += TYPE_BYTES[pSchema[j].type]; -// p += pSchema[j].bytes; -// } -// -// pDataBlock = (char*)pDataBlock + TD_ROW_LEN(memRow); -// pBlock->dataLen += TD_ROW_LEN(memRow); -// } -// } else { -// for (int32_t i = 0; i < numOfRows; ++i) { -// char* payload = (blkKeyTuple + i)->payloadAddr; -// TDRowLenT rowTLen = TD_ROW_LEN(payload); -// memcpy(pDataBlock, payload, rowTLen); -// pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen); -// pBlock->dataLen += rowTLen; -// } -// } - -// int32_t len = pBlock->dataLen + pBlock->schemaLen; -// pBlock->dataLen = htonl(pBlock->dataLen); -// pBlock->schemaLen = htonl(pBlock->schemaLen); - -// return len; -// } - -TAOS_FIELD createField(const SSchema* pSchema) { - TAOS_FIELD f = { .type = pSchema->type, .bytes = pSchema->bytes, }; - tstrncpy(f.name, pSchema->name, sizeof(f.name)); - return f; -} - -void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema) { - pColumn->uid = uid; - pColumn->flag = flag; - pColumn->info.colId = pSchema->colId; - pColumn->info.bytes = pSchema->bytes; - pColumn->info.type = pSchema->type; - - if (tableName != NULL) { - char n[TSDB_COL_NAME_LEN + 1 + TSDB_TABLE_NAME_LEN] = {0}; - snprintf(n, tListLen(n), "%s.%s", tableName, pSchema->name); - tstrncpy(pColumn->name, n, tListLen(pColumn->name)); - } else { - tstrncpy(pColumn->name, pSchema->name, tListLen(pColumn->name)); - } -} - -SColumn createColumn(uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema) { - SColumn c; - c.uid = uid; - c.flag = flag; - c.info.colId = pSchema->colId; - c.info.bytes = pSchema->bytes; - c.info.type = pSchema->type; - - if (tableName != NULL) { - char n[TSDB_COL_NAME_LEN + 1 + TSDB_TABLE_NAME_LEN] = {0}; - snprintf(n, tListLen(n), "%s.%s", tableName, pSchema->name); - - tstrncpy(c.name, n, tListLen(c.name)); - } else { - tstrncpy(c.name, pSchema->name, tListLen(c.name)); - } - - return c; -} - -void addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn) { - assert(pSourceParam != NULL); - pSourceParam->num += 1; - - if (pSourceParam->pExprNodeList != NULL) { - assert(pNode != NULL && pColumn == NULL); - if (pSourceParam->pExprNodeList == NULL) { - pSourceParam->pExprNodeList = taosArrayInit(4, POINTER_BYTES); - } - - taosArrayPush(pSourceParam->pExprNodeList, &pNode); - } else { - assert(pColumn != NULL); - if (pSourceParam->pColumnList == NULL) { - pSourceParam->pColumnList = taosArrayInit(4, POINTER_BYTES); - } - - taosArrayPush(pSourceParam->pColumnList, &pColumn); - } -} - -int32_t getNumOfFields(SFieldInfo* pFieldInfo) { - return pFieldInfo->numOfOutput; -} - -SInternalField* appendFieldInfo(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) { - assert(pFieldInfo != NULL); - pFieldInfo->numOfOutput++; - - struct SInternalField info = { .pExpr = NULL, .visible = true }; - - info.field = *pField; - return taosArrayPush(pFieldInfo->internalField, &info); -} - -SInternalField* insertFieldInfo(SFieldInfo* pFieldInfo, int32_t index, SSchema* pSchema) { - pFieldInfo->numOfOutput++; - struct SInternalField info = { .pExpr = NULL, .visible = true }; - - info.field.type = pSchema->type; - info.field.bytes = pSchema->bytes; - tstrncpy(info.field.name, pSchema->name, tListLen(pSchema->name)); - - return taosArrayInsert(pFieldInfo->internalField, index, &info); -} - -void fieldInfoUpdateOffset(SQueryStmtInfo* pQueryInfo) { - int32_t offset = 0; - size_t numOfExprs = getNumOfExprs(pQueryInfo); - - SArray* pList = getCurrentExprList(pQueryInfo); - for (int32_t i = 0; i < numOfExprs; ++i) { - SExprInfo* p = taosArrayGetP(pList, i); - -// p->base.offset = offset; - offset += p->base.resSchema.bytes; - } -} - -SInternalField* getInternalField(SFieldInfo* pFieldInfo, int32_t index) { - assert(index < pFieldInfo->numOfOutput); - return TARRAY_GET_ELEM(pFieldInfo->internalField, index); -} - -TAOS_FIELD* getFieldInfo(SFieldInfo* pFieldInfo, int32_t index) { - assert(index < pFieldInfo->numOfOutput); - return &((SInternalField*)TARRAY_GET_ELEM(pFieldInfo->internalField, index))->field; -} - -int32_t fieldInfoCompare(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2, int32_t *diffSize) { - assert(pFieldInfo1 != NULL && pFieldInfo2 != NULL); - - if (pFieldInfo1->numOfOutput != pFieldInfo2->numOfOutput) { - return pFieldInfo1->numOfOutput - pFieldInfo2->numOfOutput; - } - - for (int32_t i = 0; i < pFieldInfo1->numOfOutput; ++i) { - TAOS_FIELD* pField1 = getFieldInfo((SFieldInfo*) pFieldInfo1, i); - TAOS_FIELD* pField2 = getFieldInfo((SFieldInfo*) pFieldInfo2, i); - - if (pField1->type != pField2->type || - strcasecmp(pField1->name, pField2->name) != 0) { - return 1; - } - - if (pField1->bytes != pField2->bytes) { - *diffSize = 1; - - if (pField2->bytes > pField1->bytes) { - assert(IS_VAR_DATA_TYPE(pField1->type)); - pField1->bytes = pField2->bytes; - } - } - } - - return 0; -} - -int32_t getFieldInfoSize(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2) { - assert(pFieldInfo1 != NULL && pFieldInfo2 != NULL); - - for (int32_t i = 0; i < pFieldInfo1->numOfOutput; ++i) { - TAOS_FIELD* pField1 = getFieldInfo((SFieldInfo*) pFieldInfo1, i); - TAOS_FIELD* pField2 = getFieldInfo((SFieldInfo*) pFieldInfo2, i); - - pField2->bytes = pField1->bytes; - } - - return 0; -} - -static void destroyFilterInfo(SColumnFilterList* pFilterList) { - if (pFilterList->filterInfo == NULL) { - pFilterList->numOfFilters = 0; - return; - } - - for(int32_t i = 0; i < pFilterList->numOfFilters; ++i) { - if (pFilterList->filterInfo[i].filterstr) { - tfree(pFilterList->filterInfo[i].pz); - } - } - - tfree(pFilterList->filterInfo); - pFilterList->numOfFilters = 0; -} - -void cleanupFieldInfo(SFieldInfo* pFieldInfo) { - if (pFieldInfo == NULL) { - return; - } - - taosArrayDestroy(pFieldInfo->internalField); - tfree(pFieldInfo->final); - - memset(pFieldInfo, 0, sizeof(SFieldInfo)); -} - -void copyFieldInfo(SFieldInfo* pFieldInfo, const SFieldInfo* pSrc, const SArray* pExprList) { - assert(pFieldInfo != NULL && pSrc != NULL && pExprList != NULL); - pFieldInfo->numOfOutput = pSrc->numOfOutput; - - if (pSrc->final != NULL) { - pFieldInfo->final = calloc(pSrc->numOfOutput, sizeof(TAOS_FIELD)); - memcpy(pFieldInfo->final, pSrc->final, sizeof(TAOS_FIELD) * pSrc->numOfOutput); - } - - if (pSrc->internalField != NULL) { - size_t num = taosArrayGetSize(pSrc->internalField); - size_t numOfExpr = taosArrayGetSize(pExprList); - - for (int32_t i = 0; i < num; ++i) { - SInternalField* pfield = taosArrayGet(pSrc->internalField, i); - - SInternalField p = {.visible = pfield->visible, .field = pfield->field}; - - bool found = false; - int32_t resColId = pfield->pExpr->base.resSchema.colId; - for(int32_t j = 0; j < numOfExpr; ++j) { - SExprInfo* pExpr = taosArrayGetP(pExprList, j); - if (pExpr->base.resSchema.colId == resColId) { - p.pExpr = pExpr; - found = true; - break; - } - } - - if (!found) { - assert(pfield->pExpr->pExpr != NULL); - p.pExpr = calloc(1, sizeof(SExprInfo)); - assignExprInfo(p.pExpr, pfield->pExpr); - } - - taosArrayPush(pFieldInfo->internalField, &p); - } - } -} - -// ignore the tbname columnIndex to be inserted into source list -int32_t columnExists(SArray* pColumnList, int32_t columnId, uint64_t uid) { - size_t numOfCols = taosArrayGetSize(pColumnList); - - int32_t i = 0; - while (i < numOfCols) { - SColumn* pCol = taosArrayGetP(pColumnList, i); - if ((pCol->info.colId != columnId) || (pCol->uid != uid)) { - ++i; - continue; - } else { - break; - } - } - - if (i >= numOfCols || numOfCols == 0) { - return -1; - } - - return i; -} - -static int32_t doFindPosition(const SArray* pColumnList, uint64_t uid, const SSchema* pSchema) { - int32_t i = 0; - - size_t numOfCols = taosArrayGetSize(pColumnList); - while (i < numOfCols) { - SColumn* pCol = taosArrayGetP(pColumnList, i); - if (pCol->uid < uid) { - i++; - continue; - } - - if (pCol->info.colId < pSchema->colId) { - i++; - continue; - } - - break; - } - - return i; -} - -SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag) { - // ignore the tbname columnIndex to be inserted into source list - assert(pSchema != NULL && pColumnList != NULL); - - int32_t i = doFindPosition(pColumnList, uid, pSchema); - size_t size = taosArrayGetSize(pColumnList); - if (size > 0 && i < size) { - SColumn* pCol = taosArrayGetP(pColumnList, i); - if (pCol->uid == uid && pCol->info.colId == pSchema->colId) { - return pCol; - } - } - - SColumn* b = calloc(1, sizeof(SColumn)); - if (b == NULL) { - return NULL; - } - - b->uid = uid; - b->flag = flag; - b->info.colId = pSchema->colId; - b->info.bytes = pSchema->bytes; - b->info.type = pSchema->type; - tstrncpy(b->name, pSchema->name, tListLen(b->name)); - taosArrayInsert(pColumnList, i, &b); - - return b; -} - -SColumn* insertPrimaryTsColumn(SArray* pColumnList, const char* colName, uint64_t tableUid) { - SSchema s = {.type = TSDB_DATA_TYPE_TIMESTAMP, .bytes = TSDB_KEYSIZE, .colId = PRIMARYKEY_TIMESTAMP_COL_ID}; - strncpy(s.name, colName, tListLen(s.name)); - - return columnListInsert(pColumnList, tableUid, &s, TSDB_COL_NORMAL); -} - -void columnCopy(SColumn* pDest, const SColumn* pSrc); - -SColumn* columnClone(const SColumn* src) { - assert(src != NULL); - - SColumn* dst = calloc(1, sizeof(SColumn)); - if (dst == NULL) { - return NULL; - } - - columnCopy(dst, src); - return dst; -} - -SColumnFilterInfo* tFilterInfoDup(const SColumnFilterInfo* src, int32_t numOfFilters) { - if (numOfFilters == 0 || src == NULL) { - assert(src == NULL); - return NULL; - } - - SColumnFilterInfo* pFilter = calloc(1, numOfFilters * sizeof(SColumnFilterInfo)); - - memcpy(pFilter, src, sizeof(SColumnFilterInfo) * numOfFilters); - for (int32_t j = 0; j < numOfFilters; ++j) { - if (pFilter[j].filterstr) { - size_t len = (size_t) pFilter[j].len + 1 * TSDB_NCHAR_SIZE; - pFilter[j].pz = (int64_t) calloc(1, len); - - memcpy((char*)pFilter[j].pz, (char*)src[j].pz, (size_t) pFilter[j].len); - } - } - - assert(src->filterstr == 0 || src->filterstr == 1); - assert(!(src->lowerRelOptr == 0 && src->upperRelOptr == 0)); - - return pFilter; -} - -void columnCopy(SColumn* pDest, const SColumn* pSrc) { - destroyFilterInfo(&pDest->info.flist); - - pDest->uid = pSrc->uid; - pDest->info.flist.numOfFilters = pSrc->info.flist.numOfFilters; - pDest->info.flist.filterInfo = tFilterInfoDup(pSrc->info.flist.filterInfo, pSrc->info.flist.numOfFilters); - pDest->info.type = pSrc->info.type; - pDest->info.colId = pSrc->info.colId; - pDest->info.bytes = pSrc->info.bytes; -} - -void columnListCopyAll(SArray* dst, const SArray* src) { - assert(src != NULL && dst != NULL); - - size_t num = taosArrayGetSize(src); - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGetP(src, i); - SColumn* p = columnClone(pCol); - taosArrayPush(dst, &p); - } -} - -void columnListCopy(SArray* dst, const SArray* src, uint64_t uid) { - assert(src != NULL && dst != NULL); - - size_t num = taosArrayGetSize(src); - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGetP(src, i); - - if (pCol->uid == uid) { - SColumn* p = columnClone(pCol); - taosArrayPush(dst, &p); - } - } -} - -static void columnDestroy(SColumn* pCol) { - destroyFilterInfo(&pCol->info.flist); - free(pCol); -} - -void columnListDestroy(SArray* pColumnList) { - if (pColumnList == NULL) { - return; - } - - size_t num = taosArrayGetSize(pColumnList); - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGetP(pColumnList, i); - columnDestroy(pCol); - } - - taosArrayDestroy(pColumnList); -} - -bool validateColumnId(STableMetaInfo* pTableMetaInfo, int32_t colId, int32_t numOfParams) { - if (pTableMetaInfo->pTableMeta == NULL) { - return false; - } - - if (colId == TSDB_TBNAME_COLUMN_INDEX || (colId <= TSDB_UD_COLUMN_INDEX && numOfParams == 2)) { - return true; - } - - SSchema* pSchema = getTableColumnSchema(pTableMetaInfo->pTableMeta); - STableComInfo tinfo = getTableInfo(pTableMetaInfo->pTableMeta); - - int32_t numOfTotal = tinfo.numOfTags + tinfo.numOfColumns; - - for (int32_t i = 0; i < numOfTotal; ++i) { - if (pSchema[i].colId == colId) { - return true; - } - } - - return false; -} - -int32_t tscTagCondCopy(STagCond* dest, const STagCond* src) { - memset(dest, 0, sizeof(STagCond)); - - if (src->tbnameCond.cond != NULL) { - dest->tbnameCond.cond = strdup(src->tbnameCond.cond); - if (dest->tbnameCond.cond == NULL) { - return -1; - } - } - - dest->tbnameCond.uid = src->tbnameCond.uid; - dest->tbnameCond.len = src->tbnameCond.len; - - dest->joinInfo.hasJoin = src->joinInfo.hasJoin; - - for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) { - if (src->joinInfo.joinTables[i]) { - dest->joinInfo.joinTables[i] = calloc(1, sizeof(SJoinNode)); - - memcpy(dest->joinInfo.joinTables[i], src->joinInfo.joinTables[i], sizeof(SJoinNode)); - - if (src->joinInfo.joinTables[i]->tsJoin) { - dest->joinInfo.joinTables[i]->tsJoin = taosArrayDup(src->joinInfo.joinTables[i]->tsJoin); - } - - if (src->joinInfo.joinTables[i]->tagJoin) { - dest->joinInfo.joinTables[i]->tagJoin = taosArrayDup(src->joinInfo.joinTables[i]->tagJoin); - } - } - } - - - dest->relType = src->relType; - - if (src->pCond == NULL) { - return 0; - } - - size_t s = taosArrayGetSize(src->pCond); - dest->pCond = taosArrayInit(s, sizeof(SCond)); - - for (int32_t i = 0; i < s; ++i) { - SCond* pCond = taosArrayGet(src->pCond, i); - - SCond c = {0}; - c.len = pCond->len; - c.uid = pCond->uid; - - if (pCond->len > 0) { - assert(pCond->cond != NULL); - c.cond = malloc(c.len); - if (c.cond == NULL) { - return -1; - } - - memcpy(c.cond, pCond->cond, c.len); - } - - taosArrayPush(dest->pCond, &c); - } - - return 0; -} - -int32_t tscColCondCopy(SArray** dest, const SArray* src, uint64_t uid, int16_t tidx) { - if (src == NULL) { - return 0; - } - - size_t s = taosArrayGetSize(src); - *dest = taosArrayInit(s, sizeof(SCond)); - - for (int32_t i = 0; i < s; ++i) { - STableFilterCond* pCond = taosArrayGet(src, i); - STableFilterCond c = {0}; - - if (tidx > 0) { - if (!(pCond->uid == uid && pCond->idx == tidx)) { - continue; - } - - c.idx = 0; - } else { - c.idx = pCond->idx; - } - - c.len = pCond->len; - c.uid = pCond->uid; - - if (pCond->len > 0) { - assert(pCond->cond != NULL); - c.cond = malloc(c.len); - if (c.cond == NULL) { - return -1; - } - - memcpy(c.cond, pCond->cond, c.len); - } - - taosArrayPush(*dest, &c); - } - - return 0; -} - -void cleanupColumnCond(SArray** pCond) { - if (*pCond == NULL) { - return; - } - - size_t s = taosArrayGetSize(*pCond); - for (int32_t i = 0; i < s; ++i) { - STableFilterCond* p = taosArrayGet(*pCond, i); - tfree(p->cond); - } - - taosArrayDestroy(*pCond); - - *pCond = NULL; -} - -void cleanupTagCond(STagCond* pTagCond) { - free(pTagCond->tbnameCond.cond); - - if (pTagCond->pCond != NULL) { - size_t s = taosArrayGetSize(pTagCond->pCond); - for (int32_t i = 0; i < s; ++i) { - SCond* p = taosArrayGet(pTagCond->pCond, i); - tfree(p->cond); - } - - taosArrayDestroy(pTagCond->pCond); - } - - for (int32_t i = 0; i < TSDB_MAX_JOIN_TABLE_NUM; ++i) { - SJoinNode *node = pTagCond->joinInfo.joinTables[i]; - if (node == NULL) { - continue; - } - - if (node->tsJoin != NULL) { - taosArrayDestroy(node->tsJoin); - } - - if (node->tagJoin != NULL) { - taosArrayDestroy(node->tagJoin); - } - - tfree(node); - } - - memset(pTagCond, 0, sizeof(STagCond)); -} - -//void tscGetSrcColumnInfo(SSrcColumnInfo* pColInfo, SQueryStmtInfo* pQueryInfo) { -// STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); -// SSchema* pSchema = getTableColumnSchema(pTableMetaInfo->pTableMeta); -// -// size_t numOfExprs = getNumOfExprs(pQueryInfo); -// for (int32_t i = 0; i < numOfExprs; ++i) { -// SExprInfo* pExpr = getExprInfo(pQueryInfo, i); -// pColInfo[i].functionId = pExpr->base.functionId; -// -// if (TSDB_COL_IS_TAG(pExpr->base.colInfo.flag)) { -// SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); -// -// int16_t index = pExpr->base.colInfo.colIndex; -// pColInfo[i].type = (index != -1) ? pTagSchema[index].type : TSDB_DATA_TYPE_BINARY; -// } else { -// pColInfo[i].type = pSchema[pExpr->base.colInfo.colIndex].type; -// } -// } -//} - -/** - * - * @param clauseIndex denote the index of the union sub clause, usually are 0, if no union query exists. - * @param tableIndex denote the table index for join query, where more than one table exists - * @return - */ -STableMetaInfo* getMetaInfo(const SQueryStmtInfo* pQueryInfo, int32_t tableIndex) { - assert(pQueryInfo != NULL); - if (pQueryInfo->pTableMetaInfo == NULL) { - assert(pQueryInfo->numOfTables == 0); - return NULL; - } - - assert(tableIndex >= 0 && tableIndex <= pQueryInfo->numOfTables && pQueryInfo->pTableMetaInfo != NULL); - return pQueryInfo->pTableMetaInfo[tableIndex]; -} - -STableMetaInfo* getTableMetaInfoByUid(SQueryStmtInfo* pQueryInfo, uint64_t uid, int32_t* index) { - int32_t k = -1; - - for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { - if (pQueryInfo->pTableMetaInfo[i]->pTableMeta->uid == uid) { - k = i; - break; - } - } - - if (index != NULL) { - *index = k; - } - - assert(k != -1); - return getMetaInfo(pQueryInfo, k); -} - -int32_t queryInfoCopy(SQueryStmtInfo* pQueryInfo, const SQueryStmtInfo* pSrc) { - assert(pQueryInfo != NULL && pSrc != NULL); - int32_t code = TSDB_CODE_SUCCESS; - - memcpy(&pQueryInfo->interval, &pSrc->interval, sizeof(pQueryInfo->interval)); - - pQueryInfo->command = pSrc->command; - pQueryInfo->type = pSrc->type; - pQueryInfo->window = pSrc->window; - pQueryInfo->limit = pSrc->limit; - pQueryInfo->slimit = pSrc->slimit; - pQueryInfo->order = pSrc->order; - pQueryInfo->vgroupLimit = pSrc->vgroupLimit; - pQueryInfo->tsBuf = NULL; - pQueryInfo->fillType = pSrc->fillType; - pQueryInfo->fillVal = NULL; - pQueryInfo->numOfFillVal = 0;; - pQueryInfo->clauseLimit = pSrc->clauseLimit; - pQueryInfo->prjOffset = pSrc->prjOffset; - pQueryInfo->numOfTables = 0; - pQueryInfo->window = pSrc->window; - pQueryInfo->sessionWindow = pSrc->sessionWindow; - pQueryInfo->pTableMetaInfo = NULL; - - pQueryInfo->bufLen = pSrc->bufLen; -// pQueryInfo->orderProjectQuery = pSrc->orderProjectQuery; -// pQueryInfo->arithmeticOnAgg = pSrc->arithmeticOnAgg; - pQueryInfo->buf = malloc(pSrc->bufLen); - if (pQueryInfo->buf == NULL) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - - if (pSrc->bufLen > 0) { - memcpy(pQueryInfo->buf, pSrc->buf, pSrc->bufLen); - } - - pQueryInfo->groupbyExpr = pSrc->groupbyExpr; - if (pSrc->groupbyExpr.columnInfo != NULL) { - pQueryInfo->groupbyExpr.columnInfo = taosArrayDup(pSrc->groupbyExpr.columnInfo); - if (pQueryInfo->groupbyExpr.columnInfo == NULL) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - } - - if (tscTagCondCopy(&pQueryInfo->tagCond, &pSrc->tagCond) != 0) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - - if (tscColCondCopy(&pQueryInfo->colCond, pSrc->colCond, 0, -1) != 0) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - - if (pSrc->fillType != TSDB_FILL_NONE) { - pQueryInfo->fillVal = calloc(1, pSrc->fieldsInfo.numOfOutput * sizeof(int64_t)); - if (pQueryInfo->fillVal == NULL) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - pQueryInfo->numOfFillVal = pSrc->fieldsInfo.numOfOutput; - - memcpy(pQueryInfo->fillVal, pSrc->fillVal, pSrc->fieldsInfo.numOfOutput * sizeof(int64_t)); - } - - if (copyAllExprInfo(pQueryInfo->exprList[0], pSrc->exprList[0], true) != 0) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - goto _error; - } - - columnListCopyAll(pQueryInfo->colList, pSrc->colList); - copyFieldInfo(&pQueryInfo->fieldsInfo, &pSrc->fieldsInfo, pQueryInfo->exprList[0]); - - for(int32_t i = 0; i < pSrc->numOfTables; ++i) { - STableMetaInfo* p1 = getMetaInfo((SQueryStmtInfo*) pSrc, i); - - STableMeta* pMeta = tableMetaDup(p1->pTableMeta); - if (pMeta == NULL) { - // todo handle the error - } - - addTableMetaInfo(pQueryInfo, &p1->name, pMeta, p1->vgroupList, p1->tagColList, NULL); - } - - SArray *pUdfInfo = NULL; - if (pSrc->pUdfInfo) { - pUdfInfo = taosArrayDup(pSrc->pUdfInfo); - } - - pQueryInfo->pUdfInfo = pUdfInfo; - - _error: - return code; -} - -void clearAllTableMetaInfo(SQueryStmtInfo* pQueryInfo, bool removeMeta, uint64_t id) { - for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, i); - clearTableMetaInfo(pTableMetaInfo); - } - - tfree(pQueryInfo->pTableMetaInfo); -} - -STableMetaInfo* addTableMetaInfo(SQueryStmtInfo* pQueryInfo, SName* name, STableMeta* pTableMeta, - SVgroupsInfo* vgroupList, SArray* pTagCols, SArray* pVgroupTables) { - void* tmp = realloc(pQueryInfo->pTableMetaInfo, (pQueryInfo->numOfTables + 1) * POINTER_BYTES); - if (tmp == NULL) { - terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; - return NULL; - } - - pQueryInfo->pTableMetaInfo = tmp; - STableMetaInfo* pTableMetaInfo = calloc(1, sizeof(STableMetaInfo)); - - if (pTableMetaInfo == NULL) { - terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; - return NULL; - } - - pQueryInfo->pTableMetaInfo[pQueryInfo->numOfTables] = pTableMetaInfo; - - if (name != NULL) { - tNameAssign(&pTableMetaInfo->name, name); - } - - pTableMetaInfo->pTableMeta = pTableMeta; - - if (vgroupList != NULL) { -// pTableMetaInfo->vgroupList = vgroupInfoClone(vgroupList); - } - - // TODO handle malloc failure - pTableMetaInfo->tagColList = taosArrayInit(4, POINTER_BYTES); - if (pTableMetaInfo->tagColList == NULL) { - return NULL; - } - - if (pTagCols != NULL && pTableMetaInfo->pTableMeta != NULL) { - columnListCopy(pTableMetaInfo->tagColList, pTagCols, pTableMetaInfo->pTableMeta->uid); - } - - pQueryInfo->numOfTables += 1; - return pTableMetaInfo; -} - -STableMetaInfo* addEmptyMetaInfo(SQueryStmtInfo* pQueryInfo) { - return addTableMetaInfo(pQueryInfo, NULL, NULL, NULL, NULL, NULL); -} - -SInternalField* getInternalFieldInfo(SFieldInfo* pFieldInfo, int32_t index) { - assert(index < pFieldInfo->numOfOutput); - return TARRAY_GET_ELEM(pFieldInfo->internalField, index); -} - -int32_t getNumOfInternalField(SFieldInfo* pFieldInfo) { - return (int32_t) taosArrayGetSize(pFieldInfo->internalField); -} - -static void doSetSqlExprAndResultFieldInfo(SQueryStmtInfo* pNewQueryInfo, int64_t uid) { - int32_t numOfOutput = (int32_t)getNumOfExprs(pNewQueryInfo); - if (numOfOutput == 0) { - return; - } - - // set the field info in pNewQueryInfo object according to sqlExpr information - for (int32_t i = 0; i < numOfOutput; ++i) { - SExprInfo* pExpr = getExprInfo(pNewQueryInfo, i); - - TAOS_FIELD f = createField(&pExpr->base.resSchema); - SInternalField* pInfo1 = appendFieldInfo(&pNewQueryInfo->fieldsInfo, &f); - pInfo1->pExpr = pExpr; - } - - // update the pSqlExpr pointer in SInternalField according the field name - // make sure the pSqlExpr point to the correct SqlExpr in pNewQueryInfo, not SqlExpr in pQueryInfo - for (int32_t f = 0; f < pNewQueryInfo->fieldsInfo.numOfOutput; ++f) { - TAOS_FIELD* field = getFieldInfo(&pNewQueryInfo->fieldsInfo, f); - - bool matched = false; - for (int32_t k1 = 0; k1 < numOfOutput; ++k1) { - SExprInfo* pExpr1 = getExprInfo(pNewQueryInfo, k1); - - if (strcmp(field->name, pExpr1->base.resSchema.name) == 0) { // establish link according to the result field name - SInternalField* pInfo = getInternalFieldInfo(&pNewQueryInfo->fieldsInfo, f); - pInfo->pExpr = pExpr1; - - matched = true; - break; - } - } - - assert(matched); - (void)matched; - } - -// updateFieldInfoOffset(pNewQueryInfo); -} - -int16_t getJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) { - int32_t i = 0; - while (i < TSDB_MAX_JOIN_TABLE_NUM) { - SJoinNode* node = pTagCond->joinInfo.joinTables[i]; - if (node && node->uid == uid) { - return node->tagColId; - } - - i++; - } - - assert(0); - return -1; -} - -int16_t getTagColIndexById(STableMeta* pTableMeta, int16_t colId) { - int32_t numOfTags = getNumOfTags(pTableMeta); - - SSchema* pSchema = getTableTagSchema(pTableMeta); - for(int32_t i = 0; i < numOfTags; ++i) { - if (pSchema[i].colId == colId) { - return i; - } - } - - // can not reach here - assert(0); - return INT16_MIN; -} - -bool isQueryWithLimit(SQueryStmtInfo* pQueryInfo) { - while(pQueryInfo != NULL) { - if (pQueryInfo->limit.limit > 0) { - return true; - } - - pQueryInfo = pQueryInfo->sibling; - } - - return false; -} - -void* vgroupInfoClear(SVgroupsInfo *vgroupList) { - if (vgroupList == NULL) { - return NULL; - } - - tfree(vgroupList); - return NULL; -} - -int32_t copyTagData(STagData* dst, const STagData* src) { - dst->dataLen = src->dataLen; - tstrncpy(dst->name, src->name, tListLen(dst->name)); - - if (dst->dataLen > 0) { - dst->data = malloc(dst->dataLen); - if (dst->data == NULL) { - return -1; - } - - memcpy(dst->data, src->data, dst->dataLen); - } - - return 0; -} - - -uint32_t getTableMetaSize(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - - int32_t totalCols = 0; - if (pTableMeta->tableInfo.numOfColumns >= 0) { - totalCols = pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; - } - - return sizeof(STableMeta) + totalCols * sizeof(SSchema); -} - -uint32_t getTableMetaMaxSize() { - return sizeof(STableMeta) + TSDB_MAX_COLUMNS * sizeof(SSchema); -} - -STableMeta* tableMetaDup(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - size_t size = getTableMetaSize(pTableMeta); - - STableMeta* p = malloc(size); - memcpy(p, pTableMeta, size); - return p; -} - -int32_t getNumOfOutput(SFieldInfo* pFieldInfo) { - return pFieldInfo->numOfOutput; -} - -int32_t getColFilterSerializeLen(SQueryStmtInfo* pQueryInfo) { - int16_t numOfCols = (int16_t)taosArrayGetSize(pQueryInfo->colList); - int32_t len = 0; - - for(int32_t i = 0; i < numOfCols; ++i) { - SColumn* pCol = taosArrayGetP(pQueryInfo->colList, i); - for (int32_t j = 0; j < pCol->info.flist.numOfFilters; ++j) { - len += sizeof(SColumnFilterInfo); - if (pCol->info.flist.filterInfo[j].filterstr) { - len += (int32_t)pCol->info.flist.filterInfo[j].len + 1 * TSDB_NCHAR_SIZE; - } - } - } - return len; -} - -int32_t getTagFilterSerializeLen(SQueryStmtInfo* pQueryInfo) { - // serialize tag column query condition - if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0) { - STagCond* pTagCond = &pQueryInfo->tagCond; - - STableMetaInfo *pTableMetaInfo = getMetaInfo(pQueryInfo, 0); - STableMeta * pTableMeta = pTableMetaInfo->pTableMeta; - SCond *pCond = getSTableQueryCond(pTagCond, pTableMeta->uid); - if (pCond != NULL && pCond->cond != NULL) { - return pCond->len; - } - } - return 0; -} - -uint32_t convertRelationalOperator(SToken *pToken) { - switch (pToken->type) { - case TK_LT: - return OP_TYPE_LOWER_THAN; - case TK_LE: - return OP_TYPE_LOWER_EQUAL; - case TK_GT: - return OP_TYPE_GREATER_THAN; - case TK_GE: - return OP_TYPE_GREATER_EQUAL; - case TK_NE: - return OP_TYPE_NOT_EQUAL; - case TK_AND: - return LOGIC_COND_TYPE_AND; - case TK_OR: - return LOGIC_COND_TYPE_OR; - case TK_EQ: - return OP_TYPE_EQUAL; - - case TK_PLUS: - return OP_TYPE_ADD; - case TK_MINUS: - return OP_TYPE_SUB; - case TK_STAR: - return OP_TYPE_MULTI; - case TK_SLASH: - case TK_DIVIDE: - return OP_TYPE_DIV; - case TK_REM: - return OP_TYPE_MOD; - case TK_LIKE: - return OP_TYPE_LIKE; - case TK_MATCH: - return OP_TYPE_MATCH; - case TK_NMATCH: - return OP_TYPE_NMATCH; - case TK_ISNULL: - return OP_TYPE_IS_NULL; - case TK_NOTNULL: - return OP_TYPE_IS_NOT_NULL; - case TK_IN: - return OP_TYPE_IN; - default: { return 0; } - } -} - -bool isDclSqlStatement(SSqlInfo* pSqlInfo) { - int32_t type = pSqlInfo->type; - return (type == TSDB_SQL_CREATE_USER || type == TSDB_SQL_CREATE_ACCT || type == TSDB_SQL_DROP_USER || - type == TSDB_SQL_DROP_ACCT || type == TSDB_SQL_SHOW); -} - -bool isDdlSqlStatement(SSqlInfo* pSqlInfo) { - int32_t type = pSqlInfo->type; - return (type == TSDB_SQL_CREATE_TABLE || type == TSDB_SQL_CREATE_DB || type == TSDB_SQL_DROP_DB); -} - -bool isDqlSqlStatement(SSqlInfo* pSqlInfo) { - return pSqlInfo->type == TSDB_SQL_SELECT; -} - -static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE; -static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE; - -static FORCE_INLINE int32_t toDouble(SToken *pToken, double *value, char **endPtr) { - errno = 0; - *value = strtold(pToken->z, endPtr); - - // not a valid integer number, return error - if ((*endPtr - pToken->z) != pToken->n) { - return TK_ILLEGAL; - } - - return pToken->type; -} - -static bool isNullStr(SToken *pToken) { - return (pToken->type == TK_NULL) || ((pToken->type == TK_STRING) && (pToken->n != 0) && - (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0)); -} - -static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, uint32_t type, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { - if ((pToken->type != TK_NOW && pToken->type != TK_INTEGER && pToken->type != TK_STRING && pToken->type != TK_FLOAT && pToken->type != TK_BOOL && - pToken->type != TK_NULL && pToken->type != TK_HEX && pToken->type != TK_OCT && pToken->type != TK_BIN) || - (pToken->n == 0) || (pToken->type == TK_RP)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); - } - - if (IS_NUMERIC_TYPE(type) && pToken->n == 0) { - return buildSyntaxErrMsg(pMsgBuf, "invalid numeric data", pToken->z); - } - - // Remove quotation marks - if (TSDB_DATA_TYPE_BINARY == type) { - if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { - return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z); - } - - // delete escape character: \\, \', \" - char delim = pToken->z[0]; - int32_t cnt = 0; - int32_t j = 0; - for (uint32_t k = 1; k < pToken->n - 1; ++k) { - if (pToken->z[k] == '\\' || (pToken->z[k] == delim && pToken->z[k + 1] == delim)) { - tmpTokenBuf[j] = pToken->z[k + 1]; - cnt++; - j++; - k++; - continue; - } - tmpTokenBuf[j] = pToken->z[k]; - j++; - } - - tmpTokenBuf[j] = 0; - pToken->z = tmpTokenBuf; - pToken->n -= 2 + cnt; - } - - return TSDB_CODE_SUCCESS; -} - -static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time, SMsgBuf* pMsgBuf) { - int32_t index = 0; - SToken sToken; - int64_t interval; - int64_t ts = 0; - char* pTokenEnd = *end; - - if (pToken->type == TK_NOW) { - ts = taosGetTimestamp(timePrec); - } else if (pToken->type == TK_INTEGER) { - bool isSigned = false; - toInteger(pToken->z, pToken->n, 10, &ts, &isSigned); - } else { // parse the RFC-3339/ISO-8601 timestamp format string - if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { - return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); - } - - return TSDB_CODE_SUCCESS; - } - - for (int k = pToken->n; pToken->z[k] != '\0'; k++) { - if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue; - if (pToken->z[k] == ',') { - *end = pTokenEnd; - *time = ts; - return 0; - } - - break; - } - - /* - * time expression: - * e.g., now+12a, now-5h - */ - SToken valueToken; - index = 0; - sToken = tStrGetToken(pTokenEnd, &index, false); - pTokenEnd += index; - - if (sToken.type == TK_MINUS || sToken.type == TK_PLUS) { - index = 0; - valueToken = tStrGetToken(pTokenEnd, &index, false); - pTokenEnd += index; - - if (valueToken.n < 2) { - return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", sToken.z); - } - - char unit = 0; - if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, &unit, timePrec) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (sToken.type == TK_PLUS) { - ts += interval; - } else { - ts = ts - interval; - } - - *end = pTokenEnd; - } - - *time = ts; - return TSDB_CODE_SUCCESS; -} - -int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf) { - int64_t iv; - char *endptr = NULL; - bool isSigned = false; - - int32_t code = checkAndTrimValue(pToken, pSchema->type, tmpTokenBuf, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - if (isNullStr(pToken)) { - if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { - int64_t tmpVal = 0; - return func(&tmpVal, pSchema->bytes, param); - } - - return func(getNullValue(pSchema->type), 0, param); - } - - switch (pSchema->type) { - case TSDB_DATA_TYPE_BOOL: { - if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) { - if (strncmp(pToken->z, "true", pToken->n) == 0) { - return func(&TRUE_VALUE, pSchema->bytes, param); - } else if (strncmp(pToken->z, "false", pToken->n) == 0) { - return func(&FALSE_VALUE, pSchema->bytes, param); - } else { - return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); - } - } else if (pToken->type == TK_INTEGER) { - return func(((strtoll(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); - } else if (pToken->type == TK_FLOAT) { - return func(((strtod(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); - } else { - return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); - } - } - - case TSDB_DATA_TYPE_TINYINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z); - } else if (!IS_VALID_TINYINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z); - } - - uint8_t tmpVal = (uint8_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_UTINYINT:{ - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z); - } else if (!IS_VALID_UTINYINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z); - } - uint8_t tmpVal = (uint8_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_SMALLINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z); - } else if (!IS_VALID_SMALLINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z); - } - int16_t tmpVal = (int16_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_USMALLINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z); - } else if (!IS_VALID_USMALLINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z); - } - uint16_t tmpVal = (uint16_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_INT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z); - } else if (!IS_VALID_INT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z); - } - int32_t tmpVal = (int32_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_UINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z); - } else if (!IS_VALID_UINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z); - } - uint32_t tmpVal = (uint32_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_BIGINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z); - } else if (!IS_VALID_BIGINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "bigint data overflow", pToken->z); - } - return func(&iv, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_UBIGINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv, &isSigned)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z); - } else if (!IS_VALID_UBIGINT((uint64_t)iv)) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned bigint data overflow", pToken->z); - } - uint64_t tmpVal = (uint64_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_FLOAT: { - double dv; - if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); - } - if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); - } - float tmpVal = (float)dv; - return func(&tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_DOUBLE: { - double dv; - if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); - } - if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); - } - return func(&dv, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_BINARY: { - // Too long values will raise the invalid sql error message - if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { - return buildSyntaxErrMsg(pMsgBuf, "string data overflow", pToken->z); - } - - return func(pToken->z, pToken->n, param); - } - - case TSDB_DATA_TYPE_NCHAR: { - return func(pToken->z, pToken->n, param); - } - - case TSDB_DATA_TYPE_TIMESTAMP: { - int64_t tmpVal; - if (parseTime(end, pToken, timePrec, &tmpVal, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z); - } - - return func(&tmpVal, pSchema->bytes, param); - } - } - - return TSDB_CODE_FAILED; -} - -int32_t KvRowAppend(const void *value, int32_t len, void *param) { - SKvParam* pa = (SKvParam*) param; - - int32_t type = pa->schema->type; - int32_t colId = pa->schema->colId; - - if (TSDB_DATA_TYPE_BINARY == type) { - STR_WITH_SIZE_TO_VARSTR(pa->buf, value, len); - tdAddColToKVRow(pa->builder, colId, type, pa->buf); - } else if (TSDB_DATA_TYPE_NCHAR == type) { - // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long' - int32_t output = 0; - if (!taosMbsToUcs4(value, len, varDataVal(pa->buf), pa->schema->bytes - VARSTR_HEADER_SIZE, &output)) { - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - } - - varDataSetLen(pa->buf, output); - tdAddColToKVRow(pa->builder, colId, type, pa->buf); - } else { - tdAddColToKVRow(pa->builder, colId, type, value); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) { - const char* msg1 = "name too long"; - const char* msg2 = "invalid database name"; - const char* msg3 = "db is not specified"; - - int32_t code = TSDB_CODE_SUCCESS; - char* p = strnchr(pTableName->z, TS_PATH_DELIMITER[0], pTableName->n, true); - - if (p != NULL) { // db has been specified in sql string so we ignore current db path - assert(*p == TS_PATH_DELIMITER[0]); - - int32_t dbLen = p - pTableName->z; - char name[TSDB_DB_FNAME_LEN] = {0}; - strncpy(name, pTableName->z, dbLen); - dbLen = strdequote(name); - - code = tNameSetDbName(pName, pParseCtx->acctId, name, dbLen); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - int32_t tbLen = pTableName->n - dbLen - 1; - char tbname[TSDB_TABLE_FNAME_LEN] = {0}; - strncpy(tbname, p + 1, tbLen); - /*tbLen = */strdequote(tbname); - - code = tNameFromString(pName, tbname, T_NAME_TABLE); - if (code != 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } else { // get current DB name first, and then set it into path - if (pTableName->n >= TSDB_TABLE_NAME_LEN) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - assert(pTableName->n < TSDB_TABLE_FNAME_LEN); - - char name[TSDB_TABLE_FNAME_LEN] = {0}; - strncpy(name, pTableName->z, pTableName->n); - strdequote(name); - - if (pParseCtx->db == NULL) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - code = tNameSetDbName(pName, pParseCtx->acctId, pParseCtx->db, strlen(pParseCtx->db)); - if (code != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg2); - return code; - } - - code = tNameFromString(pName, name, T_NAME_TABLE); - if (code != 0) { - code = buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - return code; -} diff --git a/source/libs/parser/src/queryInfoUtil.c b/source/libs/parser/src/queryInfoUtil.c deleted file mode 100644 index 05aebb2cb2c35678512b75079d05656ce40f4399..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/queryInfoUtil.c +++ /dev/null @@ -1,381 +0,0 @@ -#include "os.h" -#include "queryInfoUtil.h" -#include "function.h" -#include "parser.h" -#include "parserUtil.h" - -static struct SSchema _s = { - .colId = TSDB_TBNAME_COLUMN_INDEX, - .type = TSDB_DATA_TYPE_BINARY, - .bytes = TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE, - .name = "tbname", -}; - -SSchema* getTbnameColumnSchema() { - return &_s; -} - -SArray* getCurrentExprList(SQueryStmtInfo* pQueryInfo) { - assert(pQueryInfo != NULL && pQueryInfo->exprListLevelIndex >= 0 && pQueryInfo->exprListLevelIndex < 10); - return pQueryInfo->exprList[pQueryInfo->exprListLevelIndex]; -} - -size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo) { - SArray* pExprList = getCurrentExprList(pQueryInfo); - return taosArrayGetSize(pExprList); -} - -SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) { - assert(pTableMeta != NULL && pTableMeta->schema != NULL && colIndex >= 0 && colIndex < (getNumOfColumns(pTableMeta) + getNumOfTags(pTableMeta))); - - SSchema* pSchema = (SSchema*) pTableMeta->schema; - return &pSchema[colIndex]; -} - -STableComInfo getTableInfo(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - return pTableMeta->tableInfo; -} - -int32_t getNumOfColumns(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - // table created according to super table, use data from super table - return getTableInfo(pTableMeta).numOfColumns; -} - -int32_t getNumOfTags(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - return getTableInfo(pTableMeta).numOfTags; -} - -SSchema *getTableColumnSchema(const STableMeta *pTableMeta) { - assert(pTableMeta != NULL); - return (SSchema*) pTableMeta->schema; -} - -SSchema* getTableTagSchema(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL && (pTableMeta->tableType == TSDB_SUPER_TABLE || pTableMeta->tableType == TSDB_CHILD_TABLE)); - return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns); -} - -static tExprNode* createFunctionExprNode(const char* funcName, struct SSourceParam *pParam) { - tExprNode** p = malloc(pParam->num * POINTER_BYTES); - - if (pParam->pColumnList != NULL) { - for(int32_t i = 0; i < pParam->num; ++i) { - p[i] = calloc(1, sizeof(tExprNode)); - p[i]->nodeType = TEXPR_COL_NODE; - - SColumn* pSrc = taosArrayGetP(pParam->pColumnList, i); - SSchema* pSchema = calloc(1, sizeof(SSchema)); - - tstrncpy(pSchema->name, pSrc->name, tListLen(pSchema->name)); - pSchema->type = pSrc->info.type; - pSchema->bytes = pSrc->info.bytes; - pSchema->colId = pSrc->info.colId; - p[i]->pSchema = pSchema; - } - } else { - assert(pParam->pColumnList == NULL); - for(int32_t i = 0; i < pParam->num; ++i) { - p[i] = taosArrayGetP(pParam->pExprNodeList, i); - } - } - - tExprNode* pNode = calloc(1, sizeof(tExprNode)); - - pNode->nodeType = TEXPR_FUNCTION_NODE; - tstrncpy(pNode->_function.functionName, funcName, tListLen(pNode->_function.functionName)); - pNode->_function.pChild = p; - pNode->_function.num = pParam->num; - - return pNode; -} - -SExprInfo* createBinaryExprInfo(tExprNode* pNode, SSchema* pResSchema) { - assert(pNode != NULL && pResSchema != NULL); - - SExprInfo* pExpr = calloc(1, sizeof(SExprInfo)); - if (pExpr == NULL) { - return NULL; - } - - pExpr->pExpr = pNode; - memcpy(&pExpr->base.resSchema, pResSchema, sizeof(SSchema)); - return pExpr; -} - -SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, const char* funcName, SSourceParam* pSourceParam, SSchema* pResSchema, int16_t interSize) { - SExprInfo* pExpr = calloc(1, sizeof(SExprInfo)); - if (pExpr == NULL) { - return NULL; - } - - uint64_t uid = 0; - if (pTableMetaInfo->pTableMeta) { - uid = pTableMetaInfo->pTableMeta->uid; - } - - SSqlExpr* p = &pExpr->base; - - p->pColumns = calloc(pSourceParam->num, sizeof(SColumn)); - p->numOfCols = pSourceParam->num; - p->interBytes = interSize; - memcpy(&p->resSchema, pResSchema, sizeof(SSchema)); - - if (pSourceParam->pExprNodeList != NULL) { - pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam); - return pExpr; - } - - SColumn* pCol = taosArrayGetP(pSourceParam->pColumnList, 0); - if (pCol->info.colId == TSDB_TBNAME_COLUMN_INDEX) { - assert(pSourceParam->num == 1); - - SSchema* s = getTbnameColumnSchema(); - setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, s); - - pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam); - } else if (TSDB_COL_IS_UD_COL(pCol->flag) || strcmp(funcName, "block_dist") == 0) { - setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_UDC, pResSchema); - pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam); - } else { - for(int32_t i = 0; i < pSourceParam->num; ++i) { - SColumn* c = taosArrayGetP(pSourceParam->pColumnList, i); - p->pColumns[i] = *c; - } - pExpr->pExpr = createFunctionExprNode(funcName, pSourceParam); - } - - return pExpr; -} - -void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level) { - assert(pExprList != NULL ); - - int32_t num = (int32_t) taosArrayGetSize(pExprList); - if (index == num) { - taosArrayPush(pExprList, &pExprInfo); - } else { - taosArrayInsert(pExprList, index, &pExprInfo); - } - -#if 0 - if (pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE) { - printf("add function: %s, level:%d, total:%ld\n", pExprInfo->pExpr->_function.functionName, level, taosArrayGetSize(pExprList)); - } else { - printf("add operator: %s, level:%d, total:%ld\n", pExprInfo->base.resSchema.name, level, taosArrayGetSize(pExprList)); - } -#endif - -} - -void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize) { - assert(pExprInfo != NULL); - - SSqlExpr* pse = &pExprInfo->base; - assert(0); - - pse->resSchema.type = resType; - pse->resSchema.bytes = resSize; -} - -SExprInfo* getExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index) { - assert(pQueryInfo != NULL && pQueryInfo->exprList && index >= 0); - return taosArrayGetP(getCurrentExprList(pQueryInfo), index); -} - -void destroyExprInfo(SExprInfo* pExprInfo) { - tExprTreeDestroy(pExprInfo->pExpr, NULL); - - for(int32_t i = 0; i < pExprInfo->base.numOfParams; ++i) { - taosVariantDestroy(&pExprInfo->base.param[i]); - } - - tfree(pExprInfo->base.pColumns); - tfree(pExprInfo); -} - -void dropOneLevelExprInfo(SArray* pExprInfo) { - size_t size = taosArrayGetSize(pExprInfo); - - for (int32_t i = 0; i < size; ++i) { - SExprInfo* pExpr = taosArrayGetP(pExprInfo, i); - destroyExprInfo(pExpr); - } - - taosArrayDestroy(pExprInfo); -} - -void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel) { - for(int32_t i = 0; i < numOfLevel; ++i) { - dropOneLevelExprInfo(pExprInfo[i]); - } -} - -void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes) { - assert (pExpr != NULL || argument != NULL || bytes != 0); - - // set parameter value - // transfer to tVariant from byte data/no ascii data - taosVariantCreateFromBinary(&pExpr->param[pExpr->numOfParams], argument, bytes, type); - pExpr->numOfParams += 1; - - assert(pExpr->numOfParams <= 3); -} - -int32_t getExprFunctionId(SExprInfo *pExprInfo) { - assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE); - return 0; -} - -void assignExprInfo(SExprInfo* dst, const SExprInfo* src) { - assert(dst != NULL && src != NULL/* && src->base.numOfCols > 0*/); - - *dst = *src; -#if 0 - if (src->base.flist.numOfFilters > 0) { - dst->base.flist.filterInfo = calloc(src->base.flist.numOfFilters, sizeof(SColumnFilterInfo)); - memcpy(dst->base.flist.filterInfo, src->base.flist.filterInfo, sizeof(SColumnFilterInfo) * src->base.flist.numOfFilters); - } -#endif - - dst->pExpr = exprdup(src->pExpr); - if (src->base.numOfCols > 0) { - dst->base.pColumns = calloc(src->base.numOfCols, sizeof(SColumn)); - memcpy(dst->base.pColumns, src->base.pColumns, sizeof(SColumn) * src->base.numOfCols); - } else { - dst->base.pColumns = NULL; - } - - memset(dst->base.param, 0, sizeof(SVariant) * tListLen(dst->base.param)); - for (int32_t j = 0; j < src->base.numOfParams; ++j) { - taosVariantAssign(&dst->base.param[j], &src->base.param[j]); - } -} - -int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy) { - assert(src != NULL && dst != NULL); - - size_t size = taosArrayGetSize(src); - for (int32_t i = 0; i < size; ++i) { - SExprInfo* pExpr = taosArrayGetP(src, i); - uint64_t exprUid = pExpr->base.pColumns->uid; - - if (exprUid == uid) { - if (deepcopy) { - SExprInfo* p1 = calloc(1, sizeof(SExprInfo)); - assignExprInfo(p1, pExpr); - - taosArrayPush(dst, &p1); - } else { - taosArrayPush(dst, &pExpr); - } - } - } - - return 0; -} - -int32_t copyAllExprInfo(SArray* dst, const SArray* src, bool deepcopy) { - assert(src != NULL && dst != NULL); - - size_t size = taosArrayGetSize(src); - for (int32_t i = 0; i < size; ++i) { - SExprInfo* pExpr = taosArrayGetP(src, i); - - SExprInfo* p1 = calloc(1, sizeof(SExprInfo)); - assignExprInfo(p1, pExpr); - taosArrayPush(dst, &p1); - } - - return 0; -} - -//void* tSqlExprDestroy(SExprInfo* pExpr) { -// if (pExpr == NULL) { -// return NULL; -// } -// -// SSqlExpr* p = &pExpr->base; -// for(int32_t i = 0; i < tListLen(p->param); ++i) { -// taosVariantDestroy(&p->param[i]); -// } -// -// if (p->flist.numOfFilters > 0) { -// tfree(p->flist.filterInfo); -// } -// -// if (pExpr->pExpr != NULL) { -// tExprTreeDestroy(pExpr->pExpr, NULL); -// } -// -// tfree(pExpr); -// return NULL; -//} - -int32_t getResRowLength(SArray* pExprList) { - size_t num = taosArrayGetSize(pExprList); - if (num == 0) { - return 0; - } - - int32_t size = 0; - for(int32_t i = 0; i < num; ++i) { - SExprInfo* pExpr = taosArrayGetP(pExprList, i); - size += pExpr->base.resSchema.bytes; - } - - return size; -} - -SArray* extractFunctionList(SArray* pExprInfoList) { - assert(pExprInfoList != NULL); - - size_t len = taosArrayGetSize(pExprInfoList); - SArray* p = taosArrayInit(len, POINTER_BYTES); - - for(int32_t i = 0; i < len; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pExprInfoList, i); - if (pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE) { - char* name = strdup(pExprInfo->pExpr->_function.functionName); - taosArrayPush(p, &name); - } else { - char* name = strdup("project"); - taosArrayPush(p, &name); - } - } - - return p; -} - -bool tscHasColumnFilter(SQueryStmtInfo* pQueryInfo) { - // filter on primary timestamp column - if (pQueryInfo->window.skey != INT64_MIN || pQueryInfo->window.ekey != INT64_MAX) { - return true; - } - - size_t size = taosArrayGetSize(pQueryInfo->colList); - for (int32_t i = 0; i < size; ++i) { - SColumn* pCol = taosArrayGetP(pQueryInfo->colList, i); - if (pCol->info.flist.numOfFilters > 0) { - return true; - } - } - - return false; -} - -int32_t getExprFunctionLevel(const SQueryStmtInfo* pQueryInfo) { - int32_t n = 10; - - int32_t level = 0; - for(int32_t i = 0; i < n; ++i) { - SArray* pList = pQueryInfo->exprList[i]; - if (taosArrayGetSize(pList) > 0) { - level += 1; - } - } - - return level; -} \ No newline at end of file diff --git a/source/libs/parser/src/sql.c b/source/libs/parser/src/sql.c index 3ca9a26f1e248709dabdd878dffba409227eae58..c54bbd41cc57348d2ace331f2ae7f23093273f09 100644 --- a/source/libs/parser/src/sql.c +++ b/source/libs/parser/src/sql.c @@ -23,6 +23,7 @@ ** input grammar file: */ #include +#include /************ Begin %include sections from the grammar ************************/ #include @@ -30,12 +31,11 @@ #include #include #include -#include "astGenerator.h" -#include "tmsgtype.h" -#include "ttoken.h" + +#include "nodes.h" +#include "parToken.h" #include "ttokendef.h" -#include "tvariant.h" -#include "parserInt.h" +#include "parAst.h" /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols ** in a format understandable to "makeheaders". This section is blank unless @@ -76,8 +76,10 @@ ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument +** ParseARG_PARAM Code to pass %extra_argument as a subroutine parameter ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser +** ParseCTX_* As ParseARG_ except for %extra_context ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** YYNSTATE the combined number of states. @@ -96,52 +98,52 @@ # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ -#define YYCODETYPE unsigned short int -#define YYNOCODE 276 +#define YYCODETYPE unsigned char +#define YYNOCODE 209 #define YYACTIONTYPE unsigned short int -#define ParseTOKENTYPE SToken +#define ParseTOKENTYPE SToken typedef union { int yyinit; ParseTOKENTYPE yy0; - SSessionWindowVal yy39; - SCreateDbInfo yy42; - SVariant yy43; - int yy44; - tSqlExpr* yy46; - SLimit yy55; - SCreatedTableInfo yy96; - SArray* yy131; - SSqlNode* yy256; - SCreateTableSql* yy272; - SField yy290; - SSubclause* yy303; - int32_t yy310; - SCreateAcctInfo yy341; - int64_t yy459; - SIntervalVal yy530; - SWindowStateVal yy538; - SRelationInfo* yy544; + SNodeList* yy46; + SDataType yy70; + SToken yy129; + ENullOrder yy147; + bool yy185; + EOrder yy202; + SNode* yy256; + EJoinType yy266; + EOperatorType yy326; + STableOptions* yy340; + EFillMode yy360; + SDatabaseOptions* yy391; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif -#define ParseARG_SDECL SSqlInfo* pInfo; -#define ParseARG_PDECL ,SSqlInfo* pInfo -#define ParseARG_FETCH SSqlInfo* pInfo = yypParser->pInfo -#define ParseARG_STORE yypParser->pInfo = pInfo -#define YYFALLBACK 1 -#define YYNSTATE 368 -#define YYNRULE 304 -#define YYNTOKEN 192 -#define YY_MAX_SHIFT 367 -#define YY_MIN_SHIFTREDUCE 590 -#define YY_MAX_SHIFTREDUCE 893 -#define YY_ERROR_ACTION 894 -#define YY_ACCEPT_ACTION 895 -#define YY_NO_ACTION 896 -#define YY_MIN_REDUCE 897 -#define YY_MAX_REDUCE 1200 +#define ParseARG_SDECL SAstCreateContext* pCxt ; +#define ParseARG_PDECL , SAstCreateContext* pCxt +#define ParseARG_PARAM ,pCxt +#define ParseARG_FETCH SAstCreateContext* pCxt =yypParser->pCxt ; +#define ParseARG_STORE yypParser->pCxt =pCxt ; +#define ParseCTX_SDECL +#define ParseCTX_PDECL +#define ParseCTX_PARAM +#define ParseCTX_FETCH +#define ParseCTX_STORE +#define YYNSTATE 279 +#define YYNRULE 237 +#define YYNTOKEN 135 +#define YY_MAX_SHIFT 278 +#define YY_MIN_SHIFTREDUCE 439 +#define YY_MAX_SHIFTREDUCE 675 +#define YY_ERROR_ACTION 676 +#define YY_ACCEPT_ACTION 677 +#define YY_NO_ACTION 678 +#define YY_MIN_REDUCE 679 +#define YY_MAX_REDUCE 915 /************* End control #defines *******************************************/ +#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. @@ -206,294 +208,285 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (781) +#define YY_ACTTAB_COUNT (905) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 91, 641, 242, 1085, 676, 249, 1050, 55, 56, 641, - /* 10 */ 59, 60, 895, 367, 252, 49, 48, 47, 1075, 58, - /* 20 */ 325, 63, 61, 64, 62, 641, 641, 366, 230, 54, - /* 30 */ 53, 206, 248, 52, 51, 50, 233, 55, 56, 246, - /* 40 */ 59, 60, 1176, 1050, 252, 49, 48, 47, 104, 58, - /* 50 */ 325, 63, 61, 64, 62, 1022, 21, 1020, 1021, 54, - /* 60 */ 53, 1075, 1023, 52, 51, 50, 1024, 206, 1025, 1026, - /* 70 */ 280, 279, 1082, 55, 56, 203, 59, 60, 1177, 274, - /* 80 */ 252, 49, 48, 47, 89, 58, 325, 63, 61, 64, - /* 90 */ 62, 39, 236, 1062, 206, 54, 53, 362, 982, 52, - /* 100 */ 51, 50, 27, 55, 57, 1177, 59, 60, 323, 830, - /* 110 */ 252, 49, 48, 47, 1075, 58, 325, 63, 61, 64, - /* 120 */ 62, 121, 294, 80, 81, 54, 53, 795, 796, 52, - /* 130 */ 51, 50, 234, 116, 56, 232, 59, 60, 311, 1047, - /* 140 */ 252, 49, 48, 47, 104, 58, 325, 63, 61, 64, - /* 150 */ 62, 42, 952, 361, 360, 54, 53, 1038, 359, 52, - /* 160 */ 51, 50, 358, 43, 357, 356, 1033, 1034, 30, 1037, - /* 170 */ 253, 42, 319, 361, 360, 318, 317, 316, 359, 315, - /* 180 */ 314, 313, 358, 312, 357, 356, 310, 1014, 1002, 1003, - /* 190 */ 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, - /* 200 */ 1015, 1016, 1017, 1018, 641, 59, 60, 159, 113, 252, - /* 210 */ 49, 48, 47, 355, 58, 325, 63, 61, 64, 62, - /* 220 */ 1124, 355, 292, 39, 54, 53, 282, 80, 52, 51, - /* 230 */ 50, 321, 206, 54, 53, 945, 88, 52, 51, 50, - /* 240 */ 776, 158, 22, 1177, 591, 592, 593, 594, 595, 596, - /* 250 */ 597, 598, 599, 600, 601, 602, 603, 604, 199, 215, - /* 260 */ 231, 251, 845, 834, 837, 840, 216, 43, 261, 79, - /* 270 */ 1035, 1046, 175, 174, 172, 217, 275, 124, 723, 330, - /* 280 */ 80, 251, 845, 834, 837, 840, 52, 51, 50, 228, - /* 290 */ 229, 321, 40, 326, 63, 61, 64, 62, 759, 756, - /* 300 */ 757, 758, 54, 53, 345, 344, 52, 51, 50, 228, - /* 310 */ 229, 255, 751, 748, 749, 750, 746, 747, 836, 839, - /* 320 */ 43, 3, 32, 131, 204, 257, 258, 39, 780, 129, - /* 330 */ 85, 123, 133, 1044, 39, 209, 39, 39, 65, 244, - /* 340 */ 245, 104, 273, 39, 86, 39, 835, 838, 104, 305, - /* 350 */ 260, 224, 189, 186, 183, 149, 142, 162, 65, 181, - /* 360 */ 179, 178, 177, 176, 167, 170, 160, 39, 269, 77, - /* 370 */ 39, 240, 39, 164, 773, 1047, 846, 841, 241, 243, - /* 380 */ 334, 335, 1047, 842, 1047, 1047, 812, 336, 39, 337, - /* 390 */ 256, 1047, 254, 1047, 333, 332, 846, 841, 266, 955, - /* 400 */ 12, 7, 327, 842, 722, 158, 84, 270, 365, 364, - /* 410 */ 190, 341, 760, 761, 342, 1047, 343, 1123, 1047, 946, - /* 420 */ 1047, 198, 195, 193, 82, 158, 752, 753, 83, 262, - /* 430 */ 261, 259, 347, 340, 339, 261, 1047, 119, 843, 127, - /* 440 */ 92, 93, 78, 792, 1048, 802, 811, 803, 71, 74, - /* 450 */ 832, 733, 297, 735, 299, 744, 745, 734, 35, 97, - /* 460 */ 868, 66, 847, 24, 250, 1077, 844, 40, 40, 67, - /* 470 */ 117, 640, 14, 67, 13, 140, 23, 139, 23, 210, - /* 480 */ 70, 70, 833, 16, 211, 15, 4, 23, 169, 168, - /* 490 */ 75, 72, 1171, 1170, 300, 764, 765, 1169, 762, 763, - /* 500 */ 18, 147, 17, 146, 20, 226, 19, 227, 207, 849, - /* 510 */ 1061, 208, 212, 205, 213, 214, 1049, 219, 220, 221, - /* 520 */ 1196, 218, 202, 1188, 1134, 1076, 1133, 238, 44, 1130, - /* 530 */ 277, 1045, 1129, 239, 346, 114, 324, 1116, 196, 1115, - /* 540 */ 271, 276, 791, 87, 1084, 1095, 76, 1092, 90, 281, - /* 550 */ 1093, 235, 283, 1097, 73, 295, 94, 46, 291, 107, - /* 560 */ 95, 1073, 105, 106, 286, 101, 288, 293, 285, 289, - /* 570 */ 110, 108, 109, 1117, 287, 111, 284, 112, 45, 29, - /* 580 */ 115, 225, 1043, 247, 118, 301, 120, 306, 150, 959, - /* 590 */ 302, 303, 304, 980, 307, 958, 308, 200, 38, 322, - /* 600 */ 954, 953, 130, 957, 331, 1195, 348, 137, 1194, 349, - /* 610 */ 1191, 350, 351, 222, 352, 141, 338, 1187, 353, 144, - /* 620 */ 151, 1186, 1183, 354, 148, 223, 979, 363, 893, 265, - /* 630 */ 152, 892, 264, 41, 268, 31, 891, 874, 201, 943, - /* 640 */ 153, 163, 157, 180, 154, 155, 941, 156, 165, 166, - /* 650 */ 939, 938, 263, 1, 171, 937, 267, 981, 936, 173, - /* 660 */ 935, 934, 933, 932, 931, 930, 929, 873, 184, 272, - /* 670 */ 182, 928, 70, 185, 927, 187, 188, 8, 926, 924, - /* 680 */ 922, 920, 296, 194, 919, 917, 918, 767, 197, 28, - /* 690 */ 2, 913, 278, 96, 793, 98, 100, 804, 99, 237, - /* 700 */ 798, 102, 33, 800, 9, 103, 10, 290, 34, 298, - /* 710 */ 11, 119, 25, 26, 122, 36, 126, 654, 693, 692, - /* 720 */ 125, 309, 37, 128, 689, 687, 686, 685, 683, 682, - /* 730 */ 681, 678, 644, 132, 134, 135, 5, 328, 320, 848, - /* 740 */ 6, 329, 68, 40, 69, 725, 136, 724, 138, 143, - /* 750 */ 145, 721, 670, 668, 850, 660, 666, 662, 664, 658, - /* 760 */ 656, 691, 690, 688, 684, 680, 679, 608, 161, 642, - /* 770 */ 897, 896, 896, 896, 896, 896, 896, 896, 896, 191, - /* 780 */ 192, + /* 0 */ 137, 149, 23, 95, 772, 721, 770, 247, 150, 784, + /* 10 */ 782, 148, 30, 28, 26, 25, 24, 784, 782, 194, + /* 20 */ 177, 808, 201, 735, 66, 30, 28, 26, 25, 24, + /* 30 */ 692, 166, 194, 222, 808, 60, 208, 132, 793, 782, + /* 40 */ 195, 209, 222, 54, 794, 730, 797, 833, 733, 58, + /* 50 */ 132, 139, 829, 906, 19, 785, 782, 733, 558, 73, + /* 60 */ 840, 841, 867, 845, 30, 28, 26, 25, 24, 271, + /* 70 */ 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, + /* 80 */ 260, 259, 258, 257, 256, 255, 26, 25, 24, 550, + /* 90 */ 22, 141, 171, 576, 577, 578, 579, 580, 581, 582, + /* 100 */ 584, 585, 586, 22, 141, 617, 576, 577, 578, 579, + /* 110 */ 580, 581, 582, 584, 585, 586, 275, 274, 499, 245, + /* 120 */ 244, 243, 503, 242, 505, 506, 241, 508, 238, 41, + /* 130 */ 514, 235, 516, 517, 232, 229, 194, 194, 808, 808, + /* 140 */ 729, 184, 793, 782, 195, 77, 45, 53, 794, 170, + /* 150 */ 797, 833, 194, 719, 808, 131, 829, 726, 793, 782, + /* 160 */ 195, 104, 93, 125, 794, 145, 797, 894, 153, 78, + /* 170 */ 221, 772, 180, 770, 808, 103, 736, 66, 793, 782, + /* 180 */ 195, 76, 209, 54, 794, 892, 797, 833, 194, 254, + /* 190 */ 808, 139, 829, 71, 793, 782, 195, 221, 42, 54, + /* 200 */ 794, 101, 797, 833, 772, 94, 771, 139, 829, 906, + /* 210 */ 616, 156, 860, 894, 180, 254, 808, 551, 890, 50, + /* 220 */ 793, 782, 195, 10, 47, 54, 794, 893, 797, 833, + /* 230 */ 194, 892, 808, 139, 829, 71, 793, 782, 195, 29, + /* 240 */ 27, 54, 794, 677, 797, 833, 41, 187, 539, 139, + /* 250 */ 829, 906, 114, 61, 861, 763, 537, 728, 146, 221, + /* 260 */ 851, 29, 27, 618, 11, 194, 182, 808, 196, 548, + /* 270 */ 539, 793, 782, 195, 77, 639, 121, 794, 537, 797, + /* 280 */ 146, 194, 56, 808, 1, 10, 11, 793, 782, 195, + /* 290 */ 79, 51, 55, 794, 894, 797, 833, 9, 8, 62, + /* 300 */ 832, 829, 725, 223, 222, 449, 1, 219, 76, 173, + /* 310 */ 248, 152, 892, 212, 538, 540, 543, 720, 191, 733, + /* 320 */ 194, 573, 808, 735, 66, 223, 793, 782, 195, 6, + /* 330 */ 613, 125, 794, 157, 797, 77, 538, 540, 543, 194, + /* 340 */ 222, 808, 96, 220, 184, 793, 782, 195, 29, 27, + /* 350 */ 119, 794, 163, 797, 594, 733, 847, 539, 172, 167, + /* 360 */ 165, 88, 29, 27, 251, 537, 188, 146, 250, 186, + /* 370 */ 894, 539, 222, 11, 844, 109, 847, 177, 852, 537, + /* 380 */ 613, 146, 192, 252, 76, 863, 154, 733, 892, 194, + /* 390 */ 177, 808, 60, 1, 843, 793, 782, 195, 735, 66, + /* 400 */ 55, 794, 249, 797, 833, 60, 58, 7, 181, 829, + /* 410 */ 184, 449, 223, 9, 8, 179, 72, 840, 841, 58, + /* 420 */ 845, 450, 451, 538, 540, 543, 223, 85, 189, 91, + /* 430 */ 840, 176, 625, 175, 82, 847, 894, 538, 540, 543, + /* 440 */ 178, 98, 29, 27, 183, 222, 29, 27, 155, 548, + /* 450 */ 76, 539, 809, 842, 892, 539, 674, 675, 77, 537, + /* 460 */ 733, 146, 194, 537, 808, 146, 20, 2, 793, 782, + /* 470 */ 195, 29, 27, 55, 794, 583, 797, 833, 587, 211, + /* 480 */ 539, 217, 830, 551, 215, 642, 539, 7, 537, 588, + /* 490 */ 146, 1, 864, 194, 537, 808, 31, 164, 161, 793, + /* 500 */ 782, 195, 555, 874, 68, 794, 223, 797, 80, 31, + /* 510 */ 223, 162, 640, 641, 643, 644, 7, 538, 540, 543, + /* 520 */ 789, 538, 540, 543, 106, 543, 194, 787, 808, 492, + /* 530 */ 159, 63, 793, 782, 195, 223, 64, 125, 794, 140, + /* 540 */ 797, 223, 873, 185, 907, 718, 538, 540, 543, 194, + /* 550 */ 160, 808, 538, 540, 543, 793, 782, 195, 487, 84, + /* 560 */ 68, 794, 138, 797, 194, 56, 808, 5, 854, 174, + /* 570 */ 793, 782, 195, 520, 70, 120, 794, 524, 797, 194, + /* 580 */ 227, 808, 4, 87, 63, 793, 782, 195, 158, 613, + /* 590 */ 122, 794, 251, 797, 89, 194, 250, 808, 529, 547, + /* 600 */ 908, 793, 782, 195, 59, 64, 117, 794, 65, 797, + /* 610 */ 194, 252, 808, 550, 848, 63, 793, 782, 195, 32, + /* 620 */ 16, 123, 794, 142, 797, 194, 815, 808, 90, 909, + /* 630 */ 249, 793, 782, 195, 193, 891, 118, 794, 194, 797, + /* 640 */ 808, 97, 546, 190, 793, 782, 195, 197, 210, 124, + /* 650 */ 794, 194, 797, 808, 40, 102, 552, 793, 782, 195, + /* 660 */ 734, 213, 805, 794, 147, 797, 194, 46, 808, 113, + /* 670 */ 44, 225, 793, 782, 195, 115, 110, 804, 794, 194, + /* 680 */ 797, 808, 278, 3, 128, 793, 782, 195, 129, 116, + /* 690 */ 803, 794, 31, 797, 194, 14, 808, 81, 636, 83, + /* 700 */ 793, 782, 195, 35, 638, 135, 794, 194, 797, 808, + /* 710 */ 69, 86, 37, 793, 782, 195, 632, 631, 134, 794, + /* 720 */ 194, 797, 808, 168, 38, 169, 793, 782, 195, 787, + /* 730 */ 610, 136, 794, 18, 797, 194, 15, 808, 609, 92, + /* 740 */ 207, 793, 782, 195, 206, 546, 133, 794, 205, 797, + /* 750 */ 33, 194, 34, 808, 75, 8, 574, 793, 782, 195, + /* 760 */ 556, 665, 126, 794, 17, 797, 177, 202, 12, 39, + /* 770 */ 660, 659, 143, 664, 204, 203, 30, 28, 26, 25, + /* 780 */ 24, 60, 99, 663, 130, 144, 13, 776, 218, 695, + /* 790 */ 127, 67, 775, 774, 112, 58, 200, 773, 199, 724, + /* 800 */ 198, 100, 57, 21, 723, 74, 840, 841, 111, 845, + /* 810 */ 694, 688, 683, 30, 28, 26, 25, 24, 30, 28, + /* 820 */ 26, 25, 24, 722, 458, 693, 30, 28, 26, 25, + /* 830 */ 24, 52, 687, 686, 107, 682, 681, 214, 680, 216, + /* 840 */ 105, 43, 47, 786, 226, 108, 224, 541, 36, 151, + /* 850 */ 513, 230, 521, 228, 512, 511, 518, 231, 233, 236, + /* 860 */ 515, 509, 234, 239, 558, 237, 510, 507, 498, 528, + /* 870 */ 240, 527, 526, 246, 77, 456, 48, 477, 253, 476, + /* 880 */ 470, 49, 475, 474, 473, 472, 471, 469, 685, 468, + /* 890 */ 467, 466, 465, 464, 671, 672, 463, 462, 461, 272, + /* 900 */ 273, 684, 679, 276, 277, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 195, 1, 240, 195, 3, 201, 244, 7, 8, 1, - /* 10 */ 10, 11, 193, 194, 14, 15, 16, 17, 242, 19, - /* 20 */ 20, 21, 22, 23, 24, 1, 1, 195, 196, 29, - /* 30 */ 30, 263, 201, 33, 34, 35, 260, 7, 8, 240, - /* 40 */ 10, 11, 274, 244, 14, 15, 16, 17, 195, 19, - /* 50 */ 20, 21, 22, 23, 24, 217, 263, 219, 220, 29, - /* 60 */ 30, 242, 224, 33, 34, 35, 228, 263, 230, 231, - /* 70 */ 265, 266, 264, 7, 8, 263, 10, 11, 274, 260, - /* 80 */ 14, 15, 16, 17, 84, 19, 20, 21, 22, 23, - /* 90 */ 24, 195, 245, 246, 263, 29, 30, 215, 216, 33, - /* 100 */ 34, 35, 78, 7, 8, 274, 10, 11, 83, 79, - /* 110 */ 14, 15, 16, 17, 242, 19, 20, 21, 22, 23, - /* 120 */ 24, 202, 269, 78, 271, 29, 30, 124, 125, 33, - /* 130 */ 34, 35, 260, 202, 8, 239, 10, 11, 63, 243, - /* 140 */ 14, 15, 16, 17, 195, 19, 20, 21, 22, 23, - /* 150 */ 24, 96, 1, 98, 99, 29, 30, 238, 103, 33, - /* 160 */ 34, 35, 107, 118, 109, 110, 235, 236, 237, 238, - /* 170 */ 201, 96, 97, 98, 99, 100, 101, 102, 103, 104, - /* 180 */ 105, 106, 107, 108, 109, 110, 111, 217, 218, 219, - /* 190 */ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - /* 200 */ 230, 231, 232, 233, 1, 10, 11, 74, 250, 14, - /* 210 */ 15, 16, 17, 88, 19, 20, 21, 22, 23, 24, - /* 220 */ 271, 88, 273, 195, 29, 30, 268, 78, 33, 34, - /* 230 */ 35, 80, 263, 29, 30, 200, 202, 33, 34, 35, - /* 240 */ 33, 206, 40, 274, 41, 42, 43, 44, 45, 46, - /* 250 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, - /* 260 */ 57, 1, 2, 3, 4, 5, 64, 118, 195, 120, - /* 270 */ 236, 243, 70, 71, 72, 73, 79, 204, 3, 77, - /* 280 */ 78, 1, 2, 3, 4, 5, 33, 34, 35, 29, - /* 290 */ 30, 80, 95, 33, 21, 22, 23, 24, 2, 3, - /* 300 */ 4, 5, 29, 30, 29, 30, 33, 34, 35, 29, - /* 310 */ 30, 64, 2, 3, 4, 5, 3, 4, 3, 4, - /* 320 */ 118, 58, 59, 60, 263, 29, 30, 195, 121, 66, - /* 330 */ 67, 68, 69, 195, 195, 263, 195, 195, 78, 29, - /* 340 */ 30, 195, 140, 195, 142, 195, 3, 4, 195, 86, - /* 350 */ 64, 149, 58, 59, 60, 58, 59, 60, 78, 65, - /* 360 */ 66, 67, 68, 69, 67, 68, 69, 195, 111, 78, - /* 370 */ 195, 239, 195, 76, 95, 243, 116, 117, 239, 241, - /* 380 */ 239, 239, 243, 123, 243, 243, 72, 239, 195, 239, - /* 390 */ 143, 243, 145, 243, 147, 148, 116, 117, 141, 200, - /* 400 */ 78, 122, 9, 123, 113, 206, 84, 150, 61, 62, - /* 410 */ 63, 239, 116, 117, 239, 243, 239, 271, 243, 200, - /* 420 */ 243, 58, 59, 60, 271, 206, 116, 117, 247, 143, - /* 430 */ 195, 145, 239, 147, 148, 195, 243, 115, 123, 204, - /* 440 */ 79, 79, 261, 79, 204, 79, 132, 79, 95, 95, - /* 450 */ 1, 79, 79, 79, 79, 3, 4, 79, 78, 95, - /* 460 */ 79, 95, 79, 95, 56, 242, 123, 95, 95, 95, - /* 470 */ 95, 79, 144, 95, 146, 144, 95, 146, 95, 263, - /* 480 */ 119, 119, 33, 144, 263, 146, 78, 95, 74, 75, - /* 490 */ 136, 138, 263, 263, 114, 3, 4, 263, 3, 4, - /* 500 */ 144, 144, 146, 146, 144, 263, 146, 263, 263, 116, - /* 510 */ 246, 263, 263, 263, 263, 263, 244, 263, 263, 263, - /* 520 */ 246, 263, 263, 246, 234, 242, 234, 234, 262, 234, - /* 530 */ 242, 242, 234, 234, 234, 248, 195, 272, 56, 272, - /* 540 */ 195, 197, 123, 195, 195, 195, 135, 195, 197, 267, - /* 550 */ 195, 267, 267, 195, 137, 130, 197, 134, 128, 256, - /* 560 */ 195, 259, 258, 257, 197, 195, 195, 133, 267, 127, - /* 570 */ 253, 255, 254, 197, 126, 252, 129, 251, 139, 249, - /* 580 */ 195, 197, 195, 197, 195, 197, 195, 87, 94, 195, - /* 590 */ 195, 195, 195, 214, 195, 205, 195, 195, 195, 195, - /* 600 */ 195, 195, 202, 205, 195, 195, 93, 195, 195, 47, - /* 610 */ 195, 90, 92, 197, 51, 195, 195, 195, 91, 195, - /* 620 */ 213, 195, 195, 89, 195, 197, 195, 80, 3, 3, - /* 630 */ 212, 3, 151, 195, 3, 195, 3, 98, 195, 195, - /* 640 */ 208, 195, 207, 198, 211, 209, 195, 210, 195, 195, - /* 650 */ 195, 195, 195, 203, 195, 197, 151, 216, 197, 195, - /* 660 */ 195, 195, 195, 195, 195, 195, 195, 97, 195, 141, - /* 670 */ 198, 197, 119, 198, 197, 195, 198, 78, 195, 195, - /* 680 */ 195, 195, 114, 195, 197, 195, 197, 79, 195, 78, - /* 690 */ 199, 195, 95, 95, 79, 78, 95, 79, 78, 1, - /* 700 */ 79, 78, 95, 79, 131, 78, 131, 78, 95, 114, - /* 710 */ 78, 115, 78, 78, 74, 85, 66, 3, 3, 3, - /* 720 */ 84, 112, 85, 84, 5, 3, 3, 3, 3, 3, - /* 730 */ 3, 3, 81, 74, 82, 82, 78, 20, 9, 79, - /* 740 */ 78, 55, 10, 95, 10, 3, 146, 3, 146, 146, - /* 750 */ 146, 79, 3, 3, 116, 3, 3, 3, 3, 3, - /* 760 */ 3, 3, 3, 3, 3, 3, 3, 56, 95, 81, - /* 770 */ 0, 275, 275, 275, 275, 275, 275, 275, 275, 15, - /* 780 */ 15, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 790 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 800 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 810 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 820 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 830 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 840 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 850 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 860 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 870 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 880 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 890 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 900 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 910 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 920 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 930 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 940 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 950 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 960 */ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - /* 970 */ 275, 275, 275, + /* 0 */ 152, 154, 171, 172, 157, 0, 159, 158, 152, 161, + /* 10 */ 162, 144, 12, 13, 14, 15, 16, 161, 162, 155, + /* 20 */ 140, 157, 140, 156, 157, 12, 13, 14, 15, 16, + /* 30 */ 0, 167, 155, 140, 157, 155, 143, 37, 161, 162, + /* 40 */ 163, 36, 140, 166, 167, 143, 169, 170, 155, 169, + /* 50 */ 37, 174, 175, 176, 2, 161, 162, 155, 58, 179, + /* 60 */ 180, 181, 185, 183, 12, 13, 14, 15, 16, 39, + /* 70 */ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + /* 80 */ 50, 51, 52, 53, 54, 55, 14, 15, 16, 31, + /* 90 */ 90, 91, 31, 93, 94, 95, 96, 97, 98, 99, + /* 100 */ 100, 101, 102, 90, 91, 4, 93, 94, 95, 96, + /* 110 */ 97, 98, 99, 100, 101, 102, 137, 138, 67, 68, + /* 120 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 142, + /* 130 */ 79, 80, 81, 82, 83, 84, 155, 155, 157, 157, + /* 140 */ 153, 160, 161, 162, 163, 108, 139, 166, 167, 167, + /* 150 */ 169, 170, 155, 0, 157, 174, 175, 150, 161, 162, + /* 160 */ 163, 19, 104, 166, 167, 168, 169, 186, 154, 27, + /* 170 */ 31, 157, 155, 159, 157, 33, 156, 157, 161, 162, + /* 180 */ 163, 200, 36, 166, 167, 204, 169, 170, 155, 36, + /* 190 */ 157, 174, 175, 176, 161, 162, 163, 31, 56, 166, + /* 200 */ 167, 59, 169, 170, 157, 188, 159, 174, 175, 176, + /* 210 */ 109, 194, 195, 186, 155, 36, 157, 31, 185, 57, + /* 220 */ 161, 162, 163, 57, 62, 166, 167, 200, 169, 170, + /* 230 */ 155, 204, 157, 174, 175, 176, 161, 162, 163, 12, + /* 240 */ 13, 166, 167, 135, 169, 170, 142, 3, 21, 174, + /* 250 */ 175, 176, 145, 149, 195, 148, 29, 153, 31, 31, + /* 260 */ 185, 12, 13, 14, 37, 155, 37, 157, 160, 31, + /* 270 */ 21, 161, 162, 163, 108, 58, 166, 167, 29, 169, + /* 280 */ 31, 155, 65, 157, 57, 57, 37, 161, 162, 163, + /* 290 */ 104, 139, 166, 167, 186, 169, 170, 1, 2, 147, + /* 300 */ 174, 175, 150, 76, 140, 21, 57, 143, 200, 199, + /* 310 */ 63, 144, 204, 29, 87, 88, 89, 0, 65, 155, + /* 320 */ 155, 92, 157, 156, 157, 76, 161, 162, 163, 106, + /* 330 */ 107, 166, 167, 168, 169, 108, 87, 88, 89, 155, + /* 340 */ 140, 157, 207, 143, 160, 161, 162, 163, 12, 13, + /* 350 */ 166, 167, 198, 169, 58, 155, 164, 21, 113, 114, + /* 360 */ 115, 191, 12, 13, 47, 29, 65, 31, 51, 125, + /* 370 */ 186, 21, 140, 37, 182, 143, 164, 140, 105, 29, + /* 380 */ 107, 31, 129, 66, 200, 165, 144, 155, 204, 155, + /* 390 */ 140, 157, 155, 57, 182, 161, 162, 163, 156, 157, + /* 400 */ 166, 167, 85, 169, 170, 155, 169, 57, 174, 175, + /* 410 */ 160, 21, 76, 1, 2, 178, 179, 180, 181, 169, + /* 420 */ 183, 31, 32, 87, 88, 89, 76, 58, 127, 179, + /* 430 */ 180, 181, 14, 183, 65, 164, 186, 87, 88, 89, + /* 440 */ 184, 201, 12, 13, 14, 140, 12, 13, 143, 31, + /* 450 */ 200, 21, 157, 182, 204, 21, 133, 134, 108, 29, + /* 460 */ 155, 31, 155, 29, 157, 31, 90, 187, 161, 162, + /* 470 */ 163, 12, 13, 166, 167, 99, 169, 170, 102, 137, + /* 480 */ 21, 20, 175, 31, 23, 92, 21, 57, 29, 58, + /* 490 */ 31, 57, 165, 155, 29, 157, 65, 117, 116, 161, + /* 500 */ 162, 163, 58, 197, 166, 167, 76, 169, 196, 65, + /* 510 */ 76, 118, 119, 120, 121, 122, 57, 87, 88, 89, + /* 520 */ 57, 87, 88, 89, 58, 89, 155, 64, 157, 58, + /* 530 */ 162, 65, 161, 162, 163, 76, 65, 166, 167, 168, + /* 540 */ 169, 76, 197, 205, 206, 0, 87, 88, 89, 155, + /* 550 */ 162, 157, 87, 88, 89, 161, 162, 163, 58, 196, + /* 560 */ 166, 167, 162, 169, 155, 65, 157, 124, 193, 123, + /* 570 */ 161, 162, 163, 58, 190, 166, 167, 58, 169, 155, + /* 580 */ 65, 157, 110, 192, 65, 161, 162, 163, 111, 107, + /* 590 */ 166, 167, 47, 169, 189, 155, 51, 157, 58, 31, + /* 600 */ 206, 161, 162, 163, 155, 65, 166, 167, 58, 169, + /* 610 */ 155, 66, 157, 31, 164, 65, 161, 162, 163, 103, + /* 620 */ 57, 166, 167, 132, 169, 155, 173, 157, 177, 208, + /* 630 */ 85, 161, 162, 163, 128, 203, 166, 167, 155, 169, + /* 640 */ 157, 202, 31, 126, 161, 162, 163, 140, 140, 166, + /* 650 */ 167, 155, 169, 157, 142, 142, 31, 161, 162, 163, + /* 660 */ 155, 136, 166, 167, 136, 169, 155, 57, 157, 148, + /* 670 */ 139, 151, 161, 162, 163, 140, 139, 166, 167, 155, + /* 680 */ 169, 157, 136, 65, 146, 161, 162, 163, 146, 141, + /* 690 */ 166, 167, 65, 169, 155, 112, 157, 58, 58, 57, + /* 700 */ 161, 162, 163, 65, 58, 166, 167, 155, 169, 157, + /* 710 */ 57, 57, 57, 161, 162, 163, 58, 58, 166, 167, + /* 720 */ 155, 169, 157, 29, 57, 65, 161, 162, 163, 64, + /* 730 */ 58, 166, 167, 65, 169, 155, 112, 157, 58, 64, + /* 740 */ 26, 161, 162, 163, 30, 31, 166, 167, 34, 169, + /* 750 */ 105, 155, 65, 157, 64, 2, 92, 161, 162, 163, + /* 760 */ 58, 58, 166, 167, 65, 169, 140, 53, 112, 4, + /* 770 */ 29, 29, 29, 29, 60, 61, 12, 13, 14, 15, + /* 780 */ 16, 155, 64, 29, 18, 29, 57, 0, 22, 0, + /* 790 */ 24, 25, 0, 0, 19, 169, 64, 0, 53, 0, + /* 800 */ 86, 35, 27, 2, 0, 179, 180, 181, 33, 183, + /* 810 */ 0, 0, 0, 12, 13, 14, 15, 16, 12, 13, + /* 820 */ 14, 15, 16, 0, 38, 0, 12, 13, 14, 15, + /* 830 */ 16, 56, 0, 0, 59, 0, 0, 21, 0, 21, + /* 840 */ 19, 57, 62, 64, 29, 64, 63, 21, 57, 29, + /* 850 */ 78, 29, 58, 57, 78, 78, 58, 57, 29, 29, + /* 860 */ 58, 58, 57, 29, 58, 57, 78, 58, 21, 29, + /* 870 */ 57, 29, 21, 66, 108, 38, 57, 29, 37, 29, + /* 880 */ 21, 57, 29, 29, 29, 29, 29, 29, 0, 29, + /* 890 */ 29, 29, 29, 29, 130, 131, 29, 29, 29, 29, + /* 900 */ 28, 0, 0, 21, 20, 209, 209, 209, 209, 209, + /* 910 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 920 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 930 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 940 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 950 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 960 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 970 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 980 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 990 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 1000 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 1010 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 1020 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + /* 1030 */ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, }; -#define YY_SHIFT_COUNT (367) +#define YY_SHIFT_COUNT (278) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (770) +#define YY_SHIFT_MAX (902) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 202, 75, 55, 211, 260, 280, 280, 24, 8, 8, - /* 10 */ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - /* 20 */ 8, 0, 203, 280, 296, 310, 310, 45, 45, 3, - /* 30 */ 151, 133, 211, 8, 8, 8, 8, 8, 125, 8, - /* 40 */ 8, 125, 1, 781, 280, 280, 280, 280, 280, 280, - /* 50 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - /* 60 */ 280, 280, 280, 280, 280, 280, 296, 310, 296, 296, - /* 70 */ 149, 275, 275, 275, 275, 275, 275, 275, 207, 45, - /* 80 */ 45, 314, 314, 279, 45, 25, 8, 482, 8, 8, - /* 90 */ 8, 482, 8, 8, 8, 482, 8, 419, 419, 419, - /* 100 */ 419, 482, 8, 8, 482, 411, 417, 425, 423, 434, - /* 110 */ 430, 442, 448, 447, 439, 482, 8, 8, 482, 8, - /* 120 */ 482, 8, 8, 8, 500, 8, 8, 500, 8, 8, - /* 130 */ 8, 211, 8, 8, 8, 8, 8, 8, 8, 8, - /* 140 */ 8, 482, 8, 8, 8, 8, 8, 8, 482, 8, - /* 150 */ 8, 494, 513, 562, 521, 520, 563, 527, 534, 8, - /* 160 */ 8, 1, 8, 8, 8, 8, 8, 8, 8, 8, - /* 170 */ 8, 482, 8, 482, 8, 8, 8, 8, 8, 8, - /* 180 */ 8, 547, 8, 547, 482, 8, 547, 482, 8, 547, - /* 190 */ 8, 8, 8, 8, 482, 8, 8, 482, 8, 8, - /* 200 */ 781, 781, 30, 66, 66, 96, 66, 126, 195, 273, - /* 210 */ 273, 273, 273, 273, 273, 263, 294, 297, 204, 204, - /* 220 */ 204, 204, 247, 286, 257, 322, 253, 253, 315, 343, - /* 230 */ 347, 363, 197, 361, 362, 364, 366, 368, 353, 354, - /* 240 */ 372, 373, 374, 375, 313, 452, 378, 380, 381, 383, - /* 250 */ 449, 408, 393, 392, 328, 331, 339, 492, 495, 356, - /* 260 */ 357, 291, 360, 414, 625, 481, 626, 628, 505, 631, - /* 270 */ 633, 539, 570, 528, 553, 568, 599, 608, 611, 597, - /* 280 */ 598, 615, 617, 618, 620, 621, 601, 623, 624, 627, - /* 290 */ 698, 629, 607, 573, 613, 575, 632, 568, 634, 595, - /* 300 */ 635, 596, 640, 630, 636, 650, 714, 637, 639, 715, - /* 310 */ 609, 716, 719, 722, 723, 724, 725, 726, 727, 728, - /* 320 */ 651, 729, 659, 652, 653, 658, 660, 638, 662, 717, - /* 330 */ 686, 732, 600, 602, 648, 648, 648, 648, 734, 603, - /* 340 */ 604, 648, 648, 648, 742, 744, 672, 648, 749, 750, - /* 350 */ 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, - /* 360 */ 762, 763, 673, 688, 764, 765, 711, 770, + /* 0 */ 766, 227, 249, 336, 336, 336, 336, 350, 336, 336, + /* 10 */ 166, 434, 459, 430, 459, 459, 459, 459, 459, 459, + /* 20 */ 459, 459, 459, 459, 459, 459, 459, 459, 459, 459, + /* 30 */ 459, 459, 228, 228, 228, 465, 465, 61, 61, 37, + /* 40 */ 139, 139, 146, 238, 139, 139, 238, 139, 238, 238, + /* 50 */ 238, 139, 179, 0, 13, 13, 465, 390, 58, 58, + /* 60 */ 58, 5, 153, 238, 238, 247, 51, 714, 764, 393, + /* 70 */ 245, 186, 273, 223, 273, 418, 244, 101, 284, 452, + /* 80 */ 380, 382, 436, 436, 380, 382, 436, 443, 446, 477, + /* 90 */ 472, 482, 568, 582, 516, 563, 491, 506, 517, 238, + /* 100 */ 611, 146, 611, 146, 625, 625, 247, 179, 568, 610, + /* 110 */ 611, 179, 625, 905, 905, 905, 30, 52, 801, 806, + /* 120 */ 814, 814, 814, 814, 814, 814, 814, 142, 317, 545, + /* 130 */ 775, 296, 376, 72, 72, 72, 72, 217, 369, 412, + /* 140 */ 431, 229, 323, 301, 253, 444, 463, 461, 466, 471, + /* 150 */ 500, 515, 519, 540, 550, 162, 618, 627, 583, 639, + /* 160 */ 640, 642, 638, 646, 653, 654, 658, 655, 659, 694, + /* 170 */ 660, 665, 667, 668, 624, 672, 680, 675, 645, 687, + /* 180 */ 690, 753, 664, 702, 703, 699, 656, 765, 741, 742, + /* 190 */ 743, 744, 754, 756, 718, 729, 787, 789, 792, 793, + /* 200 */ 745, 732, 797, 799, 804, 810, 811, 812, 823, 786, + /* 210 */ 825, 832, 833, 835, 836, 816, 838, 818, 821, 784, + /* 220 */ 780, 779, 781, 826, 791, 783, 794, 815, 820, 796, + /* 230 */ 798, 822, 800, 802, 829, 805, 803, 830, 808, 809, + /* 240 */ 834, 813, 772, 776, 777, 788, 847, 807, 819, 824, + /* 250 */ 840, 842, 851, 837, 841, 848, 850, 853, 854, 855, + /* 260 */ 856, 857, 859, 858, 860, 861, 862, 863, 864, 867, + /* 270 */ 868, 869, 888, 870, 872, 901, 902, 882, 884, }; -#define YY_REDUCE_COUNT (201) -#define YY_REDUCE_MIN (-238) -#define YY_REDUCE_MAX (496) +#define YY_REDUCE_COUNT (115) +#define YY_REDUCE_MIN (-169) +#define YY_REDUCE_MAX (626) static const short yy_reduce_ofst[] = { - /* 0 */ -181, -30, -162, -69, -196, -169, -31, -195, -104, -51, - /* 10 */ -147, 132, 139, 141, 142, 148, 150, 172, 175, 177, - /* 20 */ 193, -192, -168, -232, -153, -238, -201, -224, -128, -42, - /* 30 */ -81, 35, 34, 146, 153, 138, 73, 235, 199, 240, - /* 40 */ 28, 219, -118, 181, -207, -188, 61, 72, 216, 221, - /* 50 */ 229, 230, 234, 242, 244, 245, 248, 249, 250, 251, - /* 60 */ 252, 254, 255, 256, 258, 259, 264, 272, 274, 277, - /* 70 */ 223, 290, 292, 293, 295, 298, 299, 300, 266, 283, - /* 80 */ 288, 265, 267, 287, 289, 341, 345, 344, 348, 349, - /* 90 */ 350, 351, 352, 355, 358, 359, 365, 282, 284, 285, - /* 100 */ 301, 367, 370, 371, 376, 302, 304, 306, 303, 316, - /* 110 */ 318, 317, 323, 326, 330, 384, 385, 387, 386, 389, - /* 120 */ 388, 391, 394, 395, 390, 396, 397, 398, 399, 401, - /* 130 */ 402, 400, 403, 404, 405, 406, 409, 410, 412, 413, - /* 140 */ 415, 416, 420, 421, 422, 424, 426, 427, 428, 429, - /* 150 */ 431, 379, 407, 418, 432, 433, 436, 437, 435, 438, - /* 160 */ 440, 441, 443, 444, 446, 451, 453, 454, 455, 456, - /* 170 */ 457, 458, 459, 461, 464, 465, 466, 467, 468, 469, - /* 180 */ 470, 445, 471, 472, 474, 473, 475, 477, 480, 478, - /* 190 */ 483, 484, 485, 486, 487, 488, 490, 489, 493, 496, - /* 200 */ 450, 491, + /* 0 */ 108, -19, 17, 59, -123, 33, 75, 184, 126, 234, + /* 10 */ 250, 307, 338, -3, 165, 110, 371, 394, 409, 424, + /* 20 */ 440, 455, 470, 483, 496, 511, 524, 539, 552, 565, + /* 30 */ 580, 596, 237, -120, 626, -152, -144, -136, -18, 27, + /* 40 */ -107, -98, 104, -133, 164, 200, -153, 232, 167, 14, + /* 50 */ 242, 305, 152, -169, -169, -169, -106, -21, 192, 212, + /* 60 */ 271, -13, 7, 20, 47, 107, -151, -118, 135, 154, + /* 70 */ 170, 220, 256, 256, 256, 295, 240, 280, 342, 327, + /* 80 */ 306, 312, 368, 388, 345, 363, 400, 375, 391, 384, + /* 90 */ 405, 256, 449, 450, 451, 453, 421, 432, 439, 295, + /* 100 */ 507, 512, 508, 513, 525, 528, 521, 531, 505, 520, + /* 110 */ 535, 537, 546, 538, 542, 548, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 894, 956, 944, 952, 1179, 1179, 1179, 894, 894, 894, - /* 10 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 20 */ 894, 1086, 914, 1179, 894, 894, 894, 894, 894, 1101, - /* 30 */ 1036, 962, 952, 894, 894, 894, 894, 894, 962, 894, - /* 40 */ 894, 962, 894, 1081, 894, 894, 894, 894, 894, 894, - /* 50 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 60 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 70 */ 894, 894, 894, 894, 894, 894, 894, 894, 1088, 894, - /* 80 */ 894, 1120, 1120, 1079, 894, 894, 894, 916, 894, 894, - /* 90 */ 1094, 916, 1091, 894, 1096, 916, 894, 894, 894, 894, - /* 100 */ 894, 916, 894, 894, 916, 1127, 1131, 1113, 1125, 1121, - /* 110 */ 1108, 1106, 1104, 1112, 1135, 916, 894, 894, 916, 894, - /* 120 */ 916, 894, 894, 894, 960, 894, 894, 960, 894, 894, - /* 130 */ 894, 952, 894, 894, 894, 894, 894, 894, 894, 894, - /* 140 */ 894, 916, 894, 894, 894, 894, 894, 894, 916, 894, - /* 150 */ 894, 978, 976, 974, 966, 972, 968, 970, 964, 894, - /* 160 */ 894, 894, 894, 942, 894, 940, 894, 894, 894, 894, - /* 170 */ 894, 916, 894, 916, 894, 894, 894, 894, 894, 894, - /* 180 */ 894, 950, 894, 950, 916, 894, 950, 916, 894, 950, - /* 190 */ 925, 894, 894, 894, 916, 894, 894, 916, 894, 912, - /* 200 */ 1001, 1019, 894, 1136, 1126, 894, 1178, 1166, 1165, 1174, - /* 210 */ 1173, 1172, 1164, 1163, 1162, 894, 894, 894, 1158, 1161, - /* 220 */ 1160, 1159, 894, 894, 894, 894, 1168, 1167, 894, 894, - /* 230 */ 894, 894, 894, 894, 894, 894, 894, 894, 1132, 1128, - /* 240 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 250 */ 894, 1138, 894, 894, 894, 894, 894, 894, 894, 894, - /* 260 */ 894, 1027, 894, 894, 894, 894, 894, 894, 894, 894, - /* 270 */ 894, 894, 894, 894, 1078, 894, 894, 894, 894, 1090, - /* 280 */ 1089, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 290 */ 894, 894, 1122, 894, 1114, 894, 894, 1039, 894, 894, - /* 300 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 310 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 320 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 330 */ 894, 894, 894, 894, 1197, 1192, 1193, 1190, 894, 894, - /* 340 */ 894, 1189, 1184, 1185, 894, 894, 894, 1182, 894, 894, - /* 350 */ 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, - /* 360 */ 894, 894, 984, 894, 923, 921, 894, 894, + /* 0 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 10 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 20 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 30 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 40 */ 676, 676, 699, 676, 676, 676, 676, 676, 676, 676, + /* 50 */ 676, 676, 697, 676, 835, 676, 676, 676, 846, 846, + /* 60 */ 846, 699, 697, 676, 676, 762, 676, 676, 910, 676, + /* 70 */ 870, 862, 838, 852, 839, 676, 895, 855, 676, 676, + /* 80 */ 877, 875, 676, 676, 877, 875, 676, 889, 885, 868, + /* 90 */ 866, 852, 676, 676, 676, 676, 913, 901, 897, 676, + /* 100 */ 676, 699, 676, 699, 676, 676, 676, 697, 676, 731, + /* 110 */ 676, 697, 676, 765, 765, 700, 676, 676, 676, 676, + /* 120 */ 888, 887, 812, 811, 810, 806, 807, 676, 676, 676, + /* 130 */ 676, 676, 676, 801, 802, 800, 799, 676, 676, 836, + /* 140 */ 676, 676, 676, 898, 902, 676, 788, 676, 676, 676, + /* 150 */ 676, 676, 676, 676, 676, 676, 859, 869, 676, 676, + /* 160 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 170 */ 676, 788, 676, 886, 676, 845, 841, 676, 676, 837, + /* 180 */ 676, 831, 676, 676, 676, 896, 676, 676, 676, 676, + /* 190 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 200 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 210 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 220 */ 676, 787, 676, 676, 676, 676, 676, 676, 676, 759, + /* 230 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 240 */ 676, 676, 744, 742, 741, 740, 676, 737, 676, 676, + /* 250 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 260 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + /* 270 */ 676, 676, 676, 676, 676, 676, 676, 676, 676, }; /********** End of lemon-generated parsing tables *****************************/ @@ -513,198 +506,6 @@ static const YYACTIONTYPE yy_default[] = { */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { - 0, /* $ => nothing */ - 0, /* ID => nothing */ - 1, /* BOOL => ID */ - 1, /* INTEGER => ID */ - 1, /* FLOAT => ID */ - 1, /* STRING => ID */ - 1, /* TIMESTAMP => ID */ - 0, /* OR => nothing */ - 0, /* AND => nothing */ - 0, /* NOT => nothing */ - 0, /* EQ => nothing */ - 0, /* NE => nothing */ - 0, /* ISNULL => nothing */ - 0, /* NOTNULL => nothing */ - 0, /* IS => nothing */ - 1, /* LIKE => ID */ - 1, /* MATCH => ID */ - 1, /* NMATCH => ID */ - 1, /* GLOB => ID */ - 0, /* BETWEEN => nothing */ - 0, /* IN => nothing */ - 0, /* GT => nothing */ - 0, /* GE => nothing */ - 0, /* LT => nothing */ - 0, /* LE => nothing */ - 0, /* BITAND => nothing */ - 0, /* BITOR => nothing */ - 0, /* LSHIFT => nothing */ - 0, /* RSHIFT => nothing */ - 0, /* PLUS => nothing */ - 0, /* MINUS => nothing */ - 0, /* DIVIDE => nothing */ - 0, /* TIMES => nothing */ - 0, /* STAR => nothing */ - 0, /* SLASH => nothing */ - 0, /* REM => nothing */ - 0, /* CONCAT => nothing */ - 0, /* UMINUS => nothing */ - 0, /* UPLUS => nothing */ - 0, /* BITNOT => nothing */ - 0, /* SHOW => nothing */ - 0, /* DATABASES => nothing */ - 0, /* TOPICS => nothing */ - 0, /* FUNCTIONS => nothing */ - 0, /* MNODES => nothing */ - 0, /* DNODES => nothing */ - 0, /* ACCOUNTS => nothing */ - 0, /* USERS => nothing */ - 0, /* MODULES => nothing */ - 0, /* QUERIES => nothing */ - 0, /* CONNECTIONS => nothing */ - 0, /* STREAMS => nothing */ - 0, /* VARIABLES => nothing */ - 0, /* SCORES => nothing */ - 0, /* GRANTS => nothing */ - 0, /* VNODES => nothing */ - 0, /* DOT => nothing */ - 0, /* CREATE => nothing */ - 0, /* TABLE => nothing */ - 1, /* STABLE => ID */ - 1, /* DATABASE => ID */ - 0, /* TABLES => nothing */ - 0, /* STABLES => nothing */ - 0, /* VGROUPS => nothing */ - 0, /* DROP => nothing */ - 0, /* TOPIC => nothing */ - 0, /* FUNCTION => nothing */ - 0, /* DNODE => nothing */ - 0, /* USER => nothing */ - 0, /* ACCOUNT => nothing */ - 0, /* USE => nothing */ - 0, /* DESCRIBE => nothing */ - 1, /* DESC => ID */ - 0, /* ALTER => nothing */ - 0, /* PASS => nothing */ - 0, /* PRIVILEGE => nothing */ - 0, /* LOCAL => nothing */ - 0, /* COMPACT => nothing */ - 0, /* LP => nothing */ - 0, /* RP => nothing */ - 0, /* IF => nothing */ - 0, /* EXISTS => nothing */ - 0, /* PORT => nothing */ - 1, /* IPTOKEN => ID */ - 0, /* AS => nothing */ - 0, /* OUTPUTTYPE => nothing */ - 0, /* AGGREGATE => nothing */ - 0, /* BUFSIZE => nothing */ - 0, /* PPS => nothing */ - 0, /* TSERIES => nothing */ - 0, /* DBS => nothing */ - 0, /* STORAGE => nothing */ - 0, /* QTIME => nothing */ - 0, /* CONNS => nothing */ - 0, /* STATE => nothing */ - 0, /* COMMA => nothing */ - 0, /* KEEP => nothing */ - 0, /* CACHE => nothing */ - 0, /* REPLICA => nothing */ - 0, /* QUORUM => nothing */ - 0, /* DAYS => nothing */ - 0, /* MINROWS => nothing */ - 0, /* MAXROWS => nothing */ - 0, /* BLOCKS => nothing */ - 0, /* CTIME => nothing */ - 0, /* WAL => nothing */ - 0, /* FSYNC => nothing */ - 0, /* COMP => nothing */ - 0, /* PRECISION => nothing */ - 0, /* UPDATE => nothing */ - 0, /* CACHELAST => nothing */ - 0, /* STREAM => nothing */ - 0, /* MODE => nothing */ - 0, /* UNSIGNED => nothing */ - 0, /* TAGS => nothing */ - 0, /* USING => nothing */ - 1, /* NULL => ID */ - 1, /* NOW => ID */ - 0, /* SELECT => nothing */ - 0, /* UNION => nothing */ - 1, /* ALL => ID */ - 0, /* DISTINCT => nothing */ - 0, /* FROM => nothing */ - 0, /* VARIABLE => nothing */ - 0, /* INTERVAL => nothing */ - 0, /* EVERY => nothing */ - 0, /* SESSION => nothing */ - 0, /* STATE_WINDOW => nothing */ - 0, /* FILL => nothing */ - 0, /* SLIDING => nothing */ - 0, /* ORDER => nothing */ - 0, /* BY => nothing */ - 1, /* ASC => ID */ - 0, /* GROUP => nothing */ - 0, /* HAVING => nothing */ - 0, /* LIMIT => nothing */ - 1, /* OFFSET => ID */ - 0, /* SLIMIT => nothing */ - 0, /* SOFFSET => nothing */ - 0, /* WHERE => nothing */ - 0, /* RESET => nothing */ - 0, /* QUERY => nothing */ - 0, /* SYNCDB => nothing */ - 0, /* ADD => nothing */ - 0, /* COLUMN => nothing */ - 0, /* MODIFY => nothing */ - 0, /* TAG => nothing */ - 0, /* CHANGE => nothing */ - 0, /* SET => nothing */ - 0, /* KILL => nothing */ - 0, /* CONNECTION => nothing */ - 0, /* COLON => nothing */ - 1, /* ABORT => ID */ - 1, /* AFTER => ID */ - 1, /* ATTACH => ID */ - 1, /* BEFORE => ID */ - 1, /* BEGIN => ID */ - 1, /* CASCADE => ID */ - 1, /* CLUSTER => ID */ - 1, /* CONFLICT => ID */ - 1, /* COPY => ID */ - 1, /* DEFERRED => ID */ - 1, /* DELIMITERS => ID */ - 1, /* DETACH => ID */ - 1, /* EACH => ID */ - 1, /* END => ID */ - 1, /* EXPLAIN => ID */ - 1, /* FAIL => ID */ - 1, /* FOR => ID */ - 1, /* IGNORE => ID */ - 1, /* IMMEDIATE => ID */ - 1, /* INITIALLY => ID */ - 1, /* INSTEAD => ID */ - 1, /* KEY => ID */ - 1, /* OF => ID */ - 1, /* RAISE => ID */ - 1, /* REPLACE => ID */ - 1, /* RESTRICT => ID */ - 1, /* ROW => ID */ - 1, /* STATEMENT => ID */ - 1, /* TRIGGER => ID */ - 1, /* VIEW => ID */ - 1, /* SEMI => ID */ - 1, /* NONE => ID */ - 1, /* PREV => ID */ - 1, /* LINEAR => ID */ - 1, /* IMPORT => ID */ - 1, /* TBNAME => ID */ - 1, /* JOIN => ID */ - 1, /* INSERT => ID */ - 1, /* INTO => ID */ - 1, /* VALUES => ID */ }; #endif /* YYFALLBACK */ @@ -744,6 +545,7 @@ struct yyParser { int yyerrcnt; /* Shifts left before out of the error */ #endif ParseARG_SDECL /* A place to hold %extra_argument */ + ParseCTX_SDECL /* A place to hold %extra_context */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ @@ -792,280 +594,214 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { /* 0 */ "$", - /* 1 */ "ID", - /* 2 */ "BOOL", - /* 3 */ "INTEGER", - /* 4 */ "FLOAT", - /* 5 */ "STRING", - /* 6 */ "TIMESTAMP", - /* 7 */ "OR", - /* 8 */ "AND", - /* 9 */ "NOT", - /* 10 */ "EQ", - /* 11 */ "NE", - /* 12 */ "ISNULL", - /* 13 */ "NOTNULL", - /* 14 */ "IS", - /* 15 */ "LIKE", - /* 16 */ "MATCH", - /* 17 */ "NMATCH", - /* 18 */ "GLOB", - /* 19 */ "BETWEEN", - /* 20 */ "IN", - /* 21 */ "GT", - /* 22 */ "GE", - /* 23 */ "LT", - /* 24 */ "LE", - /* 25 */ "BITAND", - /* 26 */ "BITOR", - /* 27 */ "LSHIFT", - /* 28 */ "RSHIFT", - /* 29 */ "PLUS", - /* 30 */ "MINUS", - /* 31 */ "DIVIDE", - /* 32 */ "TIMES", - /* 33 */ "STAR", - /* 34 */ "SLASH", - /* 35 */ "REM", - /* 36 */ "CONCAT", - /* 37 */ "UMINUS", - /* 38 */ "UPLUS", - /* 39 */ "BITNOT", - /* 40 */ "SHOW", - /* 41 */ "DATABASES", - /* 42 */ "TOPICS", - /* 43 */ "FUNCTIONS", - /* 44 */ "MNODES", - /* 45 */ "DNODES", - /* 46 */ "ACCOUNTS", - /* 47 */ "USERS", - /* 48 */ "MODULES", - /* 49 */ "QUERIES", - /* 50 */ "CONNECTIONS", - /* 51 */ "STREAMS", - /* 52 */ "VARIABLES", - /* 53 */ "SCORES", - /* 54 */ "GRANTS", - /* 55 */ "VNODES", - /* 56 */ "DOT", - /* 57 */ "CREATE", - /* 58 */ "TABLE", + /* 1 */ "OR", + /* 2 */ "AND", + /* 3 */ "UNION", + /* 4 */ "ALL", + /* 5 */ "MINUS", + /* 6 */ "EXCEPT", + /* 7 */ "INTERSECT", + /* 8 */ "NK_BITAND", + /* 9 */ "NK_BITOR", + /* 10 */ "NK_LSHIFT", + /* 11 */ "NK_RSHIFT", + /* 12 */ "NK_PLUS", + /* 13 */ "NK_MINUS", + /* 14 */ "NK_STAR", + /* 15 */ "NK_SLASH", + /* 16 */ "NK_REM", + /* 17 */ "NK_CONCAT", + /* 18 */ "CREATE", + /* 19 */ "USER", + /* 20 */ "PASS", + /* 21 */ "NK_STRING", + /* 22 */ "ALTER", + /* 23 */ "PRIVILEGE", + /* 24 */ "DROP", + /* 25 */ "SHOW", + /* 26 */ "USERS", + /* 27 */ "DNODE", + /* 28 */ "PORT", + /* 29 */ "NK_INTEGER", + /* 30 */ "DNODES", + /* 31 */ "NK_ID", + /* 32 */ "NK_IPTOKEN", + /* 33 */ "DATABASE", + /* 34 */ "DATABASES", + /* 35 */ "USE", + /* 36 */ "IF", + /* 37 */ "NOT", + /* 38 */ "EXISTS", + /* 39 */ "BLOCKS", + /* 40 */ "CACHE", + /* 41 */ "CACHELAST", + /* 42 */ "COMP", + /* 43 */ "DAYS", + /* 44 */ "FSYNC", + /* 45 */ "MAXROWS", + /* 46 */ "MINROWS", + /* 47 */ "KEEP", + /* 48 */ "PRECISION", + /* 49 */ "QUORUM", + /* 50 */ "REPLICA", + /* 51 */ "TTL", + /* 52 */ "WAL", + /* 53 */ "VGROUPS", + /* 54 */ "SINGLE_STABLE", + /* 55 */ "STREAM_MODE", + /* 56 */ "TABLE", + /* 57 */ "NK_LP", + /* 58 */ "NK_RP", /* 59 */ "STABLE", - /* 60 */ "DATABASE", - /* 61 */ "TABLES", - /* 62 */ "STABLES", - /* 63 */ "VGROUPS", - /* 64 */ "DROP", - /* 65 */ "TOPIC", - /* 66 */ "FUNCTION", - /* 67 */ "DNODE", - /* 68 */ "USER", - /* 69 */ "ACCOUNT", - /* 70 */ "USE", - /* 71 */ "DESCRIBE", - /* 72 */ "DESC", - /* 73 */ "ALTER", - /* 74 */ "PASS", - /* 75 */ "PRIVILEGE", - /* 76 */ "LOCAL", - /* 77 */ "COMPACT", - /* 78 */ "LP", - /* 79 */ "RP", - /* 80 */ "IF", - /* 81 */ "EXISTS", - /* 82 */ "PORT", - /* 83 */ "IPTOKEN", - /* 84 */ "AS", - /* 85 */ "OUTPUTTYPE", - /* 86 */ "AGGREGATE", - /* 87 */ "BUFSIZE", - /* 88 */ "PPS", - /* 89 */ "TSERIES", - /* 90 */ "DBS", - /* 91 */ "STORAGE", - /* 92 */ "QTIME", - /* 93 */ "CONNS", - /* 94 */ "STATE", - /* 95 */ "COMMA", - /* 96 */ "KEEP", - /* 97 */ "CACHE", - /* 98 */ "REPLICA", - /* 99 */ "QUORUM", - /* 100 */ "DAYS", - /* 101 */ "MINROWS", - /* 102 */ "MAXROWS", - /* 103 */ "BLOCKS", - /* 104 */ "CTIME", - /* 105 */ "WAL", - /* 106 */ "FSYNC", - /* 107 */ "COMP", - /* 108 */ "PRECISION", - /* 109 */ "UPDATE", - /* 110 */ "CACHELAST", - /* 111 */ "STREAM", - /* 112 */ "MODE", - /* 113 */ "UNSIGNED", - /* 114 */ "TAGS", - /* 115 */ "USING", - /* 116 */ "NULL", - /* 117 */ "NOW", - /* 118 */ "SELECT", - /* 119 */ "UNION", - /* 120 */ "ALL", - /* 121 */ "DISTINCT", - /* 122 */ "FROM", - /* 123 */ "VARIABLE", - /* 124 */ "INTERVAL", - /* 125 */ "EVERY", - /* 126 */ "SESSION", - /* 127 */ "STATE_WINDOW", - /* 128 */ "FILL", - /* 129 */ "SLIDING", - /* 130 */ "ORDER", - /* 131 */ "BY", - /* 132 */ "ASC", - /* 133 */ "GROUP", - /* 134 */ "HAVING", - /* 135 */ "LIMIT", - /* 136 */ "OFFSET", - /* 137 */ "SLIMIT", - /* 138 */ "SOFFSET", - /* 139 */ "WHERE", - /* 140 */ "RESET", - /* 141 */ "QUERY", - /* 142 */ "SYNCDB", - /* 143 */ "ADD", - /* 144 */ "COLUMN", - /* 145 */ "MODIFY", - /* 146 */ "TAG", - /* 147 */ "CHANGE", - /* 148 */ "SET", - /* 149 */ "KILL", - /* 150 */ "CONNECTION", - /* 151 */ "COLON", - /* 152 */ "ABORT", - /* 153 */ "AFTER", - /* 154 */ "ATTACH", - /* 155 */ "BEFORE", - /* 156 */ "BEGIN", - /* 157 */ "CASCADE", - /* 158 */ "CLUSTER", - /* 159 */ "CONFLICT", - /* 160 */ "COPY", - /* 161 */ "DEFERRED", - /* 162 */ "DELIMITERS", - /* 163 */ "DETACH", - /* 164 */ "EACH", - /* 165 */ "END", - /* 166 */ "EXPLAIN", - /* 167 */ "FAIL", - /* 168 */ "FOR", - /* 169 */ "IGNORE", - /* 170 */ "IMMEDIATE", - /* 171 */ "INITIALLY", - /* 172 */ "INSTEAD", - /* 173 */ "KEY", - /* 174 */ "OF", - /* 175 */ "RAISE", - /* 176 */ "REPLACE", - /* 177 */ "RESTRICT", - /* 178 */ "ROW", - /* 179 */ "STATEMENT", - /* 180 */ "TRIGGER", - /* 181 */ "VIEW", - /* 182 */ "SEMI", - /* 183 */ "NONE", - /* 184 */ "PREV", - /* 185 */ "LINEAR", - /* 186 */ "IMPORT", - /* 187 */ "TBNAME", - /* 188 */ "JOIN", - /* 189 */ "INSERT", - /* 190 */ "INTO", - /* 191 */ "VALUES", - /* 192 */ "error", - /* 193 */ "program", - /* 194 */ "cmd", - /* 195 */ "ids", - /* 196 */ "dbPrefix", - /* 197 */ "cpxName", - /* 198 */ "ifexists", - /* 199 */ "alter_db_optr", - /* 200 */ "acct_optr", - /* 201 */ "exprlist", - /* 202 */ "ifnotexists", - /* 203 */ "db_optr", - /* 204 */ "typename", - /* 205 */ "bufsize", - /* 206 */ "pps", - /* 207 */ "tseries", - /* 208 */ "dbs", - /* 209 */ "streams", - /* 210 */ "storage", - /* 211 */ "qtime", - /* 212 */ "users", - /* 213 */ "conns", - /* 214 */ "state", - /* 215 */ "intitemlist", - /* 216 */ "intitem", - /* 217 */ "keep", - /* 218 */ "cache", - /* 219 */ "replica", - /* 220 */ "quorum", - /* 221 */ "days", - /* 222 */ "minrows", - /* 223 */ "maxrows", - /* 224 */ "blocks", - /* 225 */ "ctime", - /* 226 */ "wal", - /* 227 */ "fsync", - /* 228 */ "comp", - /* 229 */ "prec", - /* 230 */ "update", - /* 231 */ "cachelast", - /* 232 */ "vgroups", - /* 233 */ "stream_mode", - /* 234 */ "signed", - /* 235 */ "create_table_args", - /* 236 */ "create_stable_args", - /* 237 */ "create_table_list", - /* 238 */ "create_from_stable", - /* 239 */ "columnlist", - /* 240 */ "tagitemlist1", - /* 241 */ "tagNamelist", - /* 242 */ "select", - /* 243 */ "column", - /* 244 */ "tagitem1", - /* 245 */ "tagitemlist", - /* 246 */ "tagitem", - /* 247 */ "selcollist", - /* 248 */ "from", - /* 249 */ "where_opt", - /* 250 */ "interval_option", - /* 251 */ "sliding_opt", - /* 252 */ "session_option", - /* 253 */ "windowstate_option", - /* 254 */ "fill_opt", - /* 255 */ "groupby_opt", - /* 256 */ "having_opt", - /* 257 */ "orderby_opt", - /* 258 */ "slimit_opt", - /* 259 */ "limit_opt", - /* 260 */ "union", - /* 261 */ "sclp", - /* 262 */ "distinct", - /* 263 */ "expr", - /* 264 */ "as", - /* 265 */ "tablelist", - /* 266 */ "sub", - /* 267 */ "tmvar", - /* 268 */ "intervalKey", - /* 269 */ "sortlist", - /* 270 */ "sortitem", - /* 271 */ "item", - /* 272 */ "sortorder", - /* 273 */ "grouplist", - /* 274 */ "expritem", + /* 60 */ "TABLES", + /* 61 */ "STABLES", + /* 62 */ "USING", + /* 63 */ "TAGS", + /* 64 */ "NK_DOT", + /* 65 */ "NK_COMMA", + /* 66 */ "COMMENT", + /* 67 */ "BOOL", + /* 68 */ "TINYINT", + /* 69 */ "SMALLINT", + /* 70 */ "INT", + /* 71 */ "INTEGER", + /* 72 */ "BIGINT", + /* 73 */ "FLOAT", + /* 74 */ "DOUBLE", + /* 75 */ "BINARY", + /* 76 */ "TIMESTAMP", + /* 77 */ "NCHAR", + /* 78 */ "UNSIGNED", + /* 79 */ "JSON", + /* 80 */ "VARCHAR", + /* 81 */ "MEDIUMBLOB", + /* 82 */ "BLOB", + /* 83 */ "VARBINARY", + /* 84 */ "DECIMAL", + /* 85 */ "SMA", + /* 86 */ "MNODES", + /* 87 */ "NK_FLOAT", + /* 88 */ "NK_BOOL", + /* 89 */ "NK_VARIABLE", + /* 90 */ "BETWEEN", + /* 91 */ "IS", + /* 92 */ "NULL", + /* 93 */ "NK_LT", + /* 94 */ "NK_GT", + /* 95 */ "NK_LE", + /* 96 */ "NK_GE", + /* 97 */ "NK_NE", + /* 98 */ "NK_EQ", + /* 99 */ "LIKE", + /* 100 */ "MATCH", + /* 101 */ "NMATCH", + /* 102 */ "IN", + /* 103 */ "FROM", + /* 104 */ "AS", + /* 105 */ "JOIN", + /* 106 */ "ON", + /* 107 */ "INNER", + /* 108 */ "SELECT", + /* 109 */ "DISTINCT", + /* 110 */ "WHERE", + /* 111 */ "PARTITION", + /* 112 */ "BY", + /* 113 */ "SESSION", + /* 114 */ "STATE_WINDOW", + /* 115 */ "INTERVAL", + /* 116 */ "SLIDING", + /* 117 */ "FILL", + /* 118 */ "VALUE", + /* 119 */ "NONE", + /* 120 */ "PREV", + /* 121 */ "LINEAR", + /* 122 */ "NEXT", + /* 123 */ "GROUP", + /* 124 */ "HAVING", + /* 125 */ "ORDER", + /* 126 */ "SLIMIT", + /* 127 */ "SOFFSET", + /* 128 */ "LIMIT", + /* 129 */ "OFFSET", + /* 130 */ "ASC", + /* 131 */ "DESC", + /* 132 */ "NULLS", + /* 133 */ "FIRST", + /* 134 */ "LAST", + /* 135 */ "cmd", + /* 136 */ "user_name", + /* 137 */ "dnode_endpoint", + /* 138 */ "dnode_host_name", + /* 139 */ "not_exists_opt", + /* 140 */ "db_name", + /* 141 */ "db_options", + /* 142 */ "exists_opt", + /* 143 */ "full_table_name", + /* 144 */ "column_def_list", + /* 145 */ "tags_def_opt", + /* 146 */ "table_options", + /* 147 */ "multi_create_clause", + /* 148 */ "tags_def", + /* 149 */ "multi_drop_clause", + /* 150 */ "create_subtable_clause", + /* 151 */ "specific_tags_opt", + /* 152 */ "literal_list", + /* 153 */ "drop_table_clause", + /* 154 */ "col_name_list", + /* 155 */ "table_name", + /* 156 */ "column_def", + /* 157 */ "column_name", + /* 158 */ "type_name", + /* 159 */ "col_name", + /* 160 */ "query_expression", + /* 161 */ "literal", + /* 162 */ "duration_literal", + /* 163 */ "function_name", + /* 164 */ "table_alias", + /* 165 */ "column_alias", + /* 166 */ "expression", + /* 167 */ "column_reference", + /* 168 */ "expression_list", + /* 169 */ "subquery", + /* 170 */ "predicate", + /* 171 */ "compare_op", + /* 172 */ "in_op", + /* 173 */ "in_predicate_value", + /* 174 */ "boolean_value_expression", + /* 175 */ "boolean_primary", + /* 176 */ "common_expression", + /* 177 */ "from_clause", + /* 178 */ "table_reference_list", + /* 179 */ "table_reference", + /* 180 */ "table_primary", + /* 181 */ "joined_table", + /* 182 */ "alias_opt", + /* 183 */ "parenthesized_joined_table", + /* 184 */ "join_type", + /* 185 */ "search_condition", + /* 186 */ "query_specification", + /* 187 */ "set_quantifier_opt", + /* 188 */ "select_list", + /* 189 */ "where_clause_opt", + /* 190 */ "partition_by_clause_opt", + /* 191 */ "twindow_clause_opt", + /* 192 */ "group_by_clause_opt", + /* 193 */ "having_clause_opt", + /* 194 */ "select_sublist", + /* 195 */ "select_item", + /* 196 */ "sliding_opt", + /* 197 */ "fill_opt", + /* 198 */ "fill_mode", + /* 199 */ "group_by_list", + /* 200 */ "query_expression_body", + /* 201 */ "order_by_clause_opt", + /* 202 */ "slimit_clause_opt", + /* 203 */ "limit_clause_opt", + /* 204 */ "query_primary", + /* 205 */ "sort_specification_list", + /* 206 */ "sort_specification", + /* 207 */ "ordering_specification_opt", + /* 208 */ "null_ordering_opt", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -1073,310 +809,243 @@ static const char *const yyTokenName[] = { /* For tracing reduce actions, the names of all rules are required. */ static const char *const yyRuleName[] = { - /* 0 */ "program ::= cmd", - /* 1 */ "cmd ::= SHOW DATABASES", - /* 2 */ "cmd ::= SHOW TOPICS", - /* 3 */ "cmd ::= SHOW FUNCTIONS", - /* 4 */ "cmd ::= SHOW MNODES", - /* 5 */ "cmd ::= SHOW DNODES", - /* 6 */ "cmd ::= SHOW ACCOUNTS", - /* 7 */ "cmd ::= SHOW USERS", - /* 8 */ "cmd ::= SHOW MODULES", - /* 9 */ "cmd ::= SHOW QUERIES", - /* 10 */ "cmd ::= SHOW CONNECTIONS", - /* 11 */ "cmd ::= SHOW STREAMS", - /* 12 */ "cmd ::= SHOW VARIABLES", - /* 13 */ "cmd ::= SHOW SCORES", - /* 14 */ "cmd ::= SHOW GRANTS", - /* 15 */ "cmd ::= SHOW VNODES", - /* 16 */ "cmd ::= SHOW VNODES ids", - /* 17 */ "dbPrefix ::=", - /* 18 */ "dbPrefix ::= ids DOT", - /* 19 */ "cpxName ::=", - /* 20 */ "cpxName ::= DOT ids", - /* 21 */ "cmd ::= SHOW CREATE TABLE ids cpxName", - /* 22 */ "cmd ::= SHOW CREATE STABLE ids cpxName", - /* 23 */ "cmd ::= SHOW CREATE DATABASE ids", - /* 24 */ "cmd ::= SHOW dbPrefix TABLES", - /* 25 */ "cmd ::= SHOW dbPrefix TABLES LIKE ids", - /* 26 */ "cmd ::= SHOW dbPrefix STABLES", - /* 27 */ "cmd ::= SHOW dbPrefix STABLES LIKE ids", - /* 28 */ "cmd ::= SHOW dbPrefix VGROUPS", - /* 29 */ "cmd ::= SHOW dbPrefix VGROUPS ids", - /* 30 */ "cmd ::= DROP TABLE ifexists ids cpxName", - /* 31 */ "cmd ::= DROP STABLE ifexists ids cpxName", - /* 32 */ "cmd ::= DROP DATABASE ifexists ids", - /* 33 */ "cmd ::= DROP TOPIC ifexists ids", - /* 34 */ "cmd ::= DROP FUNCTION ids", - /* 35 */ "cmd ::= DROP DNODE ids", - /* 36 */ "cmd ::= DROP USER ids", - /* 37 */ "cmd ::= DROP ACCOUNT ids", - /* 38 */ "cmd ::= USE ids", - /* 39 */ "cmd ::= DESCRIBE ids cpxName", - /* 40 */ "cmd ::= DESC ids cpxName", - /* 41 */ "cmd ::= ALTER USER ids PASS ids", - /* 42 */ "cmd ::= ALTER USER ids PRIVILEGE ids", - /* 43 */ "cmd ::= ALTER DNODE ids ids", - /* 44 */ "cmd ::= ALTER DNODE ids ids ids", - /* 45 */ "cmd ::= ALTER LOCAL ids", - /* 46 */ "cmd ::= ALTER LOCAL ids ids", - /* 47 */ "cmd ::= ALTER DATABASE ids alter_db_optr", - /* 48 */ "cmd ::= ALTER ACCOUNT ids acct_optr", - /* 49 */ "cmd ::= ALTER ACCOUNT ids PASS ids acct_optr", - /* 50 */ "cmd ::= COMPACT VNODES IN LP exprlist RP", - /* 51 */ "ids ::= ID", - /* 52 */ "ifexists ::= IF EXISTS", - /* 53 */ "ifexists ::=", - /* 54 */ "ifnotexists ::= IF NOT EXISTS", - /* 55 */ "ifnotexists ::=", - /* 56 */ "cmd ::= CREATE DNODE ids PORT ids", - /* 57 */ "cmd ::= CREATE DNODE IPTOKEN PORT ids", - /* 58 */ "cmd ::= CREATE ACCOUNT ids PASS ids acct_optr", - /* 59 */ "cmd ::= CREATE DATABASE ifnotexists ids db_optr", - /* 60 */ "cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize", - /* 61 */ "cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize", - /* 62 */ "cmd ::= CREATE USER ids PASS ids", - /* 63 */ "bufsize ::=", - /* 64 */ "bufsize ::= BUFSIZE INTEGER", - /* 65 */ "pps ::=", - /* 66 */ "pps ::= PPS INTEGER", - /* 67 */ "tseries ::=", - /* 68 */ "tseries ::= TSERIES INTEGER", - /* 69 */ "dbs ::=", - /* 70 */ "dbs ::= DBS INTEGER", - /* 71 */ "streams ::=", - /* 72 */ "streams ::= STREAMS INTEGER", - /* 73 */ "storage ::=", - /* 74 */ "storage ::= STORAGE INTEGER", - /* 75 */ "qtime ::=", - /* 76 */ "qtime ::= QTIME INTEGER", - /* 77 */ "users ::=", - /* 78 */ "users ::= USERS INTEGER", - /* 79 */ "conns ::=", - /* 80 */ "conns ::= CONNS INTEGER", - /* 81 */ "state ::=", - /* 82 */ "state ::= STATE ids", - /* 83 */ "acct_optr ::= pps tseries storage streams qtime dbs users conns state", - /* 84 */ "intitemlist ::= intitemlist COMMA intitem", - /* 85 */ "intitemlist ::= intitem", - /* 86 */ "intitem ::= INTEGER", - /* 87 */ "keep ::= KEEP intitemlist", - /* 88 */ "cache ::= CACHE INTEGER", - /* 89 */ "replica ::= REPLICA INTEGER", - /* 90 */ "quorum ::= QUORUM INTEGER", - /* 91 */ "days ::= DAYS INTEGER", - /* 92 */ "minrows ::= MINROWS INTEGER", - /* 93 */ "maxrows ::= MAXROWS INTEGER", - /* 94 */ "blocks ::= BLOCKS INTEGER", - /* 95 */ "ctime ::= CTIME INTEGER", - /* 96 */ "wal ::= WAL INTEGER", - /* 97 */ "fsync ::= FSYNC INTEGER", - /* 98 */ "comp ::= COMP INTEGER", - /* 99 */ "prec ::= PRECISION STRING", - /* 100 */ "update ::= UPDATE INTEGER", - /* 101 */ "cachelast ::= CACHELAST INTEGER", - /* 102 */ "vgroups ::= VGROUPS INTEGER", - /* 103 */ "stream_mode ::= STREAM MODE INTEGER", - /* 104 */ "db_optr ::=", - /* 105 */ "db_optr ::= db_optr cache", - /* 106 */ "db_optr ::= db_optr replica", - /* 107 */ "db_optr ::= db_optr quorum", - /* 108 */ "db_optr ::= db_optr days", - /* 109 */ "db_optr ::= db_optr minrows", - /* 110 */ "db_optr ::= db_optr maxrows", - /* 111 */ "db_optr ::= db_optr blocks", - /* 112 */ "db_optr ::= db_optr ctime", - /* 113 */ "db_optr ::= db_optr wal", - /* 114 */ "db_optr ::= db_optr fsync", - /* 115 */ "db_optr ::= db_optr comp", - /* 116 */ "db_optr ::= db_optr prec", - /* 117 */ "db_optr ::= db_optr keep", - /* 118 */ "db_optr ::= db_optr update", - /* 119 */ "db_optr ::= db_optr cachelast", - /* 120 */ "db_optr ::= db_optr vgroups", - /* 121 */ "db_optr ::= db_optr stream_mode", - /* 122 */ "alter_db_optr ::=", - /* 123 */ "alter_db_optr ::= alter_db_optr replica", - /* 124 */ "alter_db_optr ::= alter_db_optr quorum", - /* 125 */ "alter_db_optr ::= alter_db_optr keep", - /* 126 */ "alter_db_optr ::= alter_db_optr blocks", - /* 127 */ "alter_db_optr ::= alter_db_optr comp", - /* 128 */ "alter_db_optr ::= alter_db_optr update", - /* 129 */ "alter_db_optr ::= alter_db_optr cachelast", - /* 130 */ "typename ::= ids", - /* 131 */ "typename ::= ids LP signed RP", - /* 132 */ "typename ::= ids UNSIGNED", - /* 133 */ "signed ::= INTEGER", - /* 134 */ "signed ::= PLUS INTEGER", - /* 135 */ "signed ::= MINUS INTEGER", - /* 136 */ "cmd ::= CREATE TABLE create_table_args", - /* 137 */ "cmd ::= CREATE TABLE create_stable_args", - /* 138 */ "cmd ::= CREATE STABLE create_stable_args", - /* 139 */ "cmd ::= CREATE TABLE create_table_list", - /* 140 */ "create_table_list ::= create_from_stable", - /* 141 */ "create_table_list ::= create_table_list create_from_stable", - /* 142 */ "create_table_args ::= ifnotexists ids cpxName LP columnlist RP", - /* 143 */ "create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP", - /* 144 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist1 RP", - /* 145 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist1 RP", - /* 146 */ "tagNamelist ::= tagNamelist COMMA ids", - /* 147 */ "tagNamelist ::= ids", - /* 148 */ "create_table_args ::= ifnotexists ids cpxName AS select", - /* 149 */ "columnlist ::= columnlist COMMA column", - /* 150 */ "columnlist ::= column", - /* 151 */ "column ::= ids typename", - /* 152 */ "tagitemlist1 ::= tagitemlist1 COMMA tagitem1", - /* 153 */ "tagitemlist1 ::= tagitem1", - /* 154 */ "tagitem1 ::= MINUS INTEGER", - /* 155 */ "tagitem1 ::= MINUS FLOAT", - /* 156 */ "tagitem1 ::= PLUS INTEGER", - /* 157 */ "tagitem1 ::= PLUS FLOAT", - /* 158 */ "tagitem1 ::= INTEGER", - /* 159 */ "tagitem1 ::= FLOAT", - /* 160 */ "tagitem1 ::= STRING", - /* 161 */ "tagitem1 ::= BOOL", - /* 162 */ "tagitem1 ::= NULL", - /* 163 */ "tagitem1 ::= NOW", - /* 164 */ "tagitemlist ::= tagitemlist COMMA tagitem", - /* 165 */ "tagitemlist ::= tagitem", - /* 166 */ "tagitem ::= INTEGER", - /* 167 */ "tagitem ::= FLOAT", - /* 168 */ "tagitem ::= STRING", - /* 169 */ "tagitem ::= BOOL", - /* 170 */ "tagitem ::= NULL", - /* 171 */ "tagitem ::= NOW", - /* 172 */ "tagitem ::= MINUS INTEGER", - /* 173 */ "tagitem ::= MINUS FLOAT", - /* 174 */ "tagitem ::= PLUS INTEGER", - /* 175 */ "tagitem ::= PLUS FLOAT", - /* 176 */ "select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt", - /* 177 */ "select ::= LP select RP", - /* 178 */ "union ::= select", - /* 179 */ "union ::= union UNION ALL select", - /* 180 */ "union ::= union UNION select", - /* 181 */ "cmd ::= union", - /* 182 */ "select ::= SELECT selcollist", - /* 183 */ "sclp ::= selcollist COMMA", - /* 184 */ "sclp ::=", - /* 185 */ "selcollist ::= sclp distinct expr as", - /* 186 */ "selcollist ::= sclp STAR", - /* 187 */ "as ::= AS ids", - /* 188 */ "as ::= ids", - /* 189 */ "as ::=", - /* 190 */ "distinct ::= DISTINCT", - /* 191 */ "distinct ::=", - /* 192 */ "from ::= FROM tablelist", - /* 193 */ "from ::= FROM sub", - /* 194 */ "sub ::= LP union RP", - /* 195 */ "sub ::= LP union RP ids", - /* 196 */ "sub ::= sub COMMA LP union RP ids", - /* 197 */ "tablelist ::= ids cpxName", - /* 198 */ "tablelist ::= ids cpxName ids", - /* 199 */ "tablelist ::= tablelist COMMA ids cpxName", - /* 200 */ "tablelist ::= tablelist COMMA ids cpxName ids", - /* 201 */ "tmvar ::= VARIABLE", - /* 202 */ "interval_option ::= intervalKey LP tmvar RP", - /* 203 */ "interval_option ::= intervalKey LP tmvar COMMA tmvar RP", - /* 204 */ "interval_option ::=", - /* 205 */ "intervalKey ::= INTERVAL", - /* 206 */ "intervalKey ::= EVERY", - /* 207 */ "session_option ::=", - /* 208 */ "session_option ::= SESSION LP ids cpxName COMMA tmvar RP", - /* 209 */ "windowstate_option ::=", - /* 210 */ "windowstate_option ::= STATE_WINDOW LP ids RP", - /* 211 */ "fill_opt ::=", - /* 212 */ "fill_opt ::= FILL LP ID COMMA tagitemlist RP", - /* 213 */ "fill_opt ::= FILL LP ID RP", - /* 214 */ "sliding_opt ::= SLIDING LP tmvar RP", - /* 215 */ "sliding_opt ::=", - /* 216 */ "orderby_opt ::=", - /* 217 */ "orderby_opt ::= ORDER BY sortlist", - /* 218 */ "sortlist ::= sortlist COMMA item sortorder", - /* 219 */ "sortlist ::= item sortorder", - /* 220 */ "item ::= ids cpxName", - /* 221 */ "sortorder ::= ASC", - /* 222 */ "sortorder ::= DESC", - /* 223 */ "sortorder ::=", - /* 224 */ "groupby_opt ::=", - /* 225 */ "groupby_opt ::= GROUP BY grouplist", - /* 226 */ "grouplist ::= grouplist COMMA item", - /* 227 */ "grouplist ::= item", - /* 228 */ "having_opt ::=", - /* 229 */ "having_opt ::= HAVING expr", - /* 230 */ "limit_opt ::=", - /* 231 */ "limit_opt ::= LIMIT signed", - /* 232 */ "limit_opt ::= LIMIT signed OFFSET signed", - /* 233 */ "limit_opt ::= LIMIT signed COMMA signed", - /* 234 */ "slimit_opt ::=", - /* 235 */ "slimit_opt ::= SLIMIT signed", - /* 236 */ "slimit_opt ::= SLIMIT signed SOFFSET signed", - /* 237 */ "slimit_opt ::= SLIMIT signed COMMA signed", - /* 238 */ "where_opt ::=", - /* 239 */ "where_opt ::= WHERE expr", - /* 240 */ "expr ::= LP expr RP", - /* 241 */ "expr ::= ID", - /* 242 */ "expr ::= ID DOT ID", - /* 243 */ "expr ::= ID DOT STAR", - /* 244 */ "expr ::= INTEGER", - /* 245 */ "expr ::= MINUS INTEGER", - /* 246 */ "expr ::= PLUS INTEGER", - /* 247 */ "expr ::= FLOAT", - /* 248 */ "expr ::= MINUS FLOAT", - /* 249 */ "expr ::= PLUS FLOAT", - /* 250 */ "expr ::= STRING", - /* 251 */ "expr ::= NOW", - /* 252 */ "expr ::= VARIABLE", - /* 253 */ "expr ::= PLUS VARIABLE", - /* 254 */ "expr ::= MINUS VARIABLE", - /* 255 */ "expr ::= BOOL", - /* 256 */ "expr ::= NULL", - /* 257 */ "expr ::= ID LP exprlist RP", - /* 258 */ "expr ::= ID LP STAR RP", - /* 259 */ "expr ::= expr IS NULL", - /* 260 */ "expr ::= expr IS NOT NULL", - /* 261 */ "expr ::= expr LT expr", - /* 262 */ "expr ::= expr GT expr", - /* 263 */ "expr ::= expr LE expr", - /* 264 */ "expr ::= expr GE expr", - /* 265 */ "expr ::= expr NE expr", - /* 266 */ "expr ::= expr EQ expr", - /* 267 */ "expr ::= expr BETWEEN expr AND expr", - /* 268 */ "expr ::= expr AND expr", - /* 269 */ "expr ::= expr OR expr", - /* 270 */ "expr ::= expr PLUS expr", - /* 271 */ "expr ::= expr MINUS expr", - /* 272 */ "expr ::= expr STAR expr", - /* 273 */ "expr ::= expr SLASH expr", - /* 274 */ "expr ::= expr REM expr", - /* 275 */ "expr ::= expr LIKE expr", - /* 276 */ "expr ::= expr MATCH expr", - /* 277 */ "expr ::= expr NMATCH expr", - /* 278 */ "expr ::= expr IN LP exprlist RP", - /* 279 */ "exprlist ::= exprlist COMMA expritem", - /* 280 */ "exprlist ::= expritem", - /* 281 */ "expritem ::= expr", - /* 282 */ "expritem ::=", - /* 283 */ "cmd ::= RESET QUERY CACHE", - /* 284 */ "cmd ::= SYNCDB ids REPLICA", - /* 285 */ "cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist", - /* 286 */ "cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids", - /* 287 */ "cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist", - /* 288 */ "cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist", - /* 289 */ "cmd ::= ALTER TABLE ids cpxName DROP TAG ids", - /* 290 */ "cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids", - /* 291 */ "cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem", - /* 292 */ "cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist", - /* 293 */ "cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist", - /* 294 */ "cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids", - /* 295 */ "cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist", - /* 296 */ "cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist", - /* 297 */ "cmd ::= ALTER STABLE ids cpxName DROP TAG ids", - /* 298 */ "cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids", - /* 299 */ "cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem", - /* 300 */ "cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist", - /* 301 */ "cmd ::= KILL CONNECTION INTEGER", - /* 302 */ "cmd ::= KILL STREAM INTEGER COLON INTEGER", - /* 303 */ "cmd ::= KILL QUERY INTEGER COLON INTEGER", + /* 0 */ "cmd ::= CREATE USER user_name PASS NK_STRING", + /* 1 */ "cmd ::= ALTER USER user_name PASS NK_STRING", + /* 2 */ "cmd ::= ALTER USER user_name PRIVILEGE NK_STRING", + /* 3 */ "cmd ::= DROP USER user_name", + /* 4 */ "cmd ::= SHOW USERS", + /* 5 */ "cmd ::= CREATE DNODE dnode_endpoint", + /* 6 */ "cmd ::= CREATE DNODE dnode_host_name PORT NK_INTEGER", + /* 7 */ "cmd ::= DROP DNODE NK_INTEGER", + /* 8 */ "cmd ::= DROP DNODE dnode_endpoint", + /* 9 */ "cmd ::= SHOW DNODES", + /* 10 */ "dnode_endpoint ::= NK_STRING", + /* 11 */ "dnode_host_name ::= NK_ID", + /* 12 */ "dnode_host_name ::= NK_IPTOKEN", + /* 13 */ "cmd ::= CREATE DATABASE not_exists_opt db_name db_options", + /* 14 */ "cmd ::= DROP DATABASE exists_opt db_name", + /* 15 */ "cmd ::= SHOW DATABASES", + /* 16 */ "cmd ::= USE db_name", + /* 17 */ "not_exists_opt ::= IF NOT EXISTS", + /* 18 */ "not_exists_opt ::=", + /* 19 */ "exists_opt ::= IF EXISTS", + /* 20 */ "exists_opt ::=", + /* 21 */ "db_options ::=", + /* 22 */ "db_options ::= db_options BLOCKS NK_INTEGER", + /* 23 */ "db_options ::= db_options CACHE NK_INTEGER", + /* 24 */ "db_options ::= db_options CACHELAST NK_INTEGER", + /* 25 */ "db_options ::= db_options COMP NK_INTEGER", + /* 26 */ "db_options ::= db_options DAYS NK_INTEGER", + /* 27 */ "db_options ::= db_options FSYNC NK_INTEGER", + /* 28 */ "db_options ::= db_options MAXROWS NK_INTEGER", + /* 29 */ "db_options ::= db_options MINROWS NK_INTEGER", + /* 30 */ "db_options ::= db_options KEEP NK_INTEGER", + /* 31 */ "db_options ::= db_options PRECISION NK_STRING", + /* 32 */ "db_options ::= db_options QUORUM NK_INTEGER", + /* 33 */ "db_options ::= db_options REPLICA NK_INTEGER", + /* 34 */ "db_options ::= db_options TTL NK_INTEGER", + /* 35 */ "db_options ::= db_options WAL NK_INTEGER", + /* 36 */ "db_options ::= db_options VGROUPS NK_INTEGER", + /* 37 */ "db_options ::= db_options SINGLE_STABLE NK_INTEGER", + /* 38 */ "db_options ::= db_options STREAM_MODE NK_INTEGER", + /* 39 */ "cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options", + /* 40 */ "cmd ::= CREATE TABLE multi_create_clause", + /* 41 */ "cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options", + /* 42 */ "cmd ::= DROP TABLE multi_drop_clause", + /* 43 */ "cmd ::= DROP STABLE exists_opt full_table_name", + /* 44 */ "cmd ::= SHOW TABLES", + /* 45 */ "cmd ::= SHOW STABLES", + /* 46 */ "multi_create_clause ::= create_subtable_clause", + /* 47 */ "multi_create_clause ::= multi_create_clause create_subtable_clause", + /* 48 */ "create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_tags_opt TAGS NK_LP literal_list NK_RP", + /* 49 */ "multi_drop_clause ::= drop_table_clause", + /* 50 */ "multi_drop_clause ::= multi_drop_clause drop_table_clause", + /* 51 */ "drop_table_clause ::= exists_opt full_table_name", + /* 52 */ "specific_tags_opt ::=", + /* 53 */ "specific_tags_opt ::= NK_LP col_name_list NK_RP", + /* 54 */ "full_table_name ::= table_name", + /* 55 */ "full_table_name ::= db_name NK_DOT table_name", + /* 56 */ "column_def_list ::= column_def", + /* 57 */ "column_def_list ::= column_def_list NK_COMMA column_def", + /* 58 */ "column_def ::= column_name type_name", + /* 59 */ "column_def ::= column_name type_name COMMENT NK_STRING", + /* 60 */ "type_name ::= BOOL", + /* 61 */ "type_name ::= TINYINT", + /* 62 */ "type_name ::= SMALLINT", + /* 63 */ "type_name ::= INT", + /* 64 */ "type_name ::= INTEGER", + /* 65 */ "type_name ::= BIGINT", + /* 66 */ "type_name ::= FLOAT", + /* 67 */ "type_name ::= DOUBLE", + /* 68 */ "type_name ::= BINARY NK_LP NK_INTEGER NK_RP", + /* 69 */ "type_name ::= TIMESTAMP", + /* 70 */ "type_name ::= NCHAR NK_LP NK_INTEGER NK_RP", + /* 71 */ "type_name ::= TINYINT UNSIGNED", + /* 72 */ "type_name ::= SMALLINT UNSIGNED", + /* 73 */ "type_name ::= INT UNSIGNED", + /* 74 */ "type_name ::= BIGINT UNSIGNED", + /* 75 */ "type_name ::= JSON", + /* 76 */ "type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP", + /* 77 */ "type_name ::= MEDIUMBLOB", + /* 78 */ "type_name ::= BLOB", + /* 79 */ "type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP", + /* 80 */ "type_name ::= DECIMAL", + /* 81 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP", + /* 82 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP", + /* 83 */ "tags_def_opt ::=", + /* 84 */ "tags_def_opt ::= tags_def", + /* 85 */ "tags_def ::= TAGS NK_LP column_def_list NK_RP", + /* 86 */ "table_options ::=", + /* 87 */ "table_options ::= table_options COMMENT NK_STRING", + /* 88 */ "table_options ::= table_options KEEP NK_INTEGER", + /* 89 */ "table_options ::= table_options TTL NK_INTEGER", + /* 90 */ "table_options ::= table_options SMA NK_LP col_name_list NK_RP", + /* 91 */ "col_name_list ::= col_name", + /* 92 */ "col_name_list ::= col_name_list NK_COMMA col_name", + /* 93 */ "col_name ::= column_name", + /* 94 */ "cmd ::= SHOW VGROUPS", + /* 95 */ "cmd ::= SHOW db_name NK_DOT VGROUPS", + /* 96 */ "cmd ::= SHOW MNODES", + /* 97 */ "cmd ::= query_expression", + /* 98 */ "literal ::= NK_INTEGER", + /* 99 */ "literal ::= NK_FLOAT", + /* 100 */ "literal ::= NK_STRING", + /* 101 */ "literal ::= NK_BOOL", + /* 102 */ "literal ::= TIMESTAMP NK_STRING", + /* 103 */ "literal ::= duration_literal", + /* 104 */ "duration_literal ::= NK_VARIABLE", + /* 105 */ "literal_list ::= literal", + /* 106 */ "literal_list ::= literal_list NK_COMMA literal", + /* 107 */ "db_name ::= NK_ID", + /* 108 */ "table_name ::= NK_ID", + /* 109 */ "column_name ::= NK_ID", + /* 110 */ "function_name ::= NK_ID", + /* 111 */ "table_alias ::= NK_ID", + /* 112 */ "column_alias ::= NK_ID", + /* 113 */ "user_name ::= NK_ID", + /* 114 */ "expression ::= literal", + /* 115 */ "expression ::= column_reference", + /* 116 */ "expression ::= function_name NK_LP expression_list NK_RP", + /* 117 */ "expression ::= function_name NK_LP NK_STAR NK_RP", + /* 118 */ "expression ::= subquery", + /* 119 */ "expression ::= NK_LP expression NK_RP", + /* 120 */ "expression ::= NK_PLUS expression", + /* 121 */ "expression ::= NK_MINUS expression", + /* 122 */ "expression ::= expression NK_PLUS expression", + /* 123 */ "expression ::= expression NK_MINUS expression", + /* 124 */ "expression ::= expression NK_STAR expression", + /* 125 */ "expression ::= expression NK_SLASH expression", + /* 126 */ "expression ::= expression NK_REM expression", + /* 127 */ "expression_list ::= expression", + /* 128 */ "expression_list ::= expression_list NK_COMMA expression", + /* 129 */ "column_reference ::= column_name", + /* 130 */ "column_reference ::= table_name NK_DOT column_name", + /* 131 */ "predicate ::= expression compare_op expression", + /* 132 */ "predicate ::= expression BETWEEN expression AND expression", + /* 133 */ "predicate ::= expression NOT BETWEEN expression AND expression", + /* 134 */ "predicate ::= expression IS NULL", + /* 135 */ "predicate ::= expression IS NOT NULL", + /* 136 */ "predicate ::= expression in_op in_predicate_value", + /* 137 */ "compare_op ::= NK_LT", + /* 138 */ "compare_op ::= NK_GT", + /* 139 */ "compare_op ::= NK_LE", + /* 140 */ "compare_op ::= NK_GE", + /* 141 */ "compare_op ::= NK_NE", + /* 142 */ "compare_op ::= NK_EQ", + /* 143 */ "compare_op ::= LIKE", + /* 144 */ "compare_op ::= NOT LIKE", + /* 145 */ "compare_op ::= MATCH", + /* 146 */ "compare_op ::= NMATCH", + /* 147 */ "in_op ::= IN", + /* 148 */ "in_op ::= NOT IN", + /* 149 */ "in_predicate_value ::= NK_LP expression_list NK_RP", + /* 150 */ "boolean_value_expression ::= boolean_primary", + /* 151 */ "boolean_value_expression ::= NOT boolean_primary", + /* 152 */ "boolean_value_expression ::= boolean_value_expression OR boolean_value_expression", + /* 153 */ "boolean_value_expression ::= boolean_value_expression AND boolean_value_expression", + /* 154 */ "boolean_primary ::= predicate", + /* 155 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP", + /* 156 */ "common_expression ::= expression", + /* 157 */ "common_expression ::= boolean_value_expression", + /* 158 */ "from_clause ::= FROM table_reference_list", + /* 159 */ "table_reference_list ::= table_reference", + /* 160 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference", + /* 161 */ "table_reference ::= table_primary", + /* 162 */ "table_reference ::= joined_table", + /* 163 */ "table_primary ::= table_name alias_opt", + /* 164 */ "table_primary ::= db_name NK_DOT table_name alias_opt", + /* 165 */ "table_primary ::= subquery alias_opt", + /* 166 */ "table_primary ::= parenthesized_joined_table", + /* 167 */ "alias_opt ::=", + /* 168 */ "alias_opt ::= table_alias", + /* 169 */ "alias_opt ::= AS table_alias", + /* 170 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP", + /* 171 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP", + /* 172 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition", + /* 173 */ "join_type ::=", + /* 174 */ "join_type ::= INNER", + /* 175 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt twindow_clause_opt group_by_clause_opt having_clause_opt", + /* 176 */ "set_quantifier_opt ::=", + /* 177 */ "set_quantifier_opt ::= DISTINCT", + /* 178 */ "set_quantifier_opt ::= ALL", + /* 179 */ "select_list ::= NK_STAR", + /* 180 */ "select_list ::= select_sublist", + /* 181 */ "select_sublist ::= select_item", + /* 182 */ "select_sublist ::= select_sublist NK_COMMA select_item", + /* 183 */ "select_item ::= common_expression", + /* 184 */ "select_item ::= common_expression column_alias", + /* 185 */ "select_item ::= common_expression AS column_alias", + /* 186 */ "select_item ::= table_name NK_DOT NK_STAR", + /* 187 */ "where_clause_opt ::=", + /* 188 */ "where_clause_opt ::= WHERE search_condition", + /* 189 */ "partition_by_clause_opt ::=", + /* 190 */ "partition_by_clause_opt ::= PARTITION BY expression_list", + /* 191 */ "twindow_clause_opt ::=", + /* 192 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA NK_INTEGER NK_RP", + /* 193 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP column_reference NK_RP", + /* 194 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt", + /* 195 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt", + /* 196 */ "sliding_opt ::=", + /* 197 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP", + /* 198 */ "fill_opt ::=", + /* 199 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP", + /* 200 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP", + /* 201 */ "fill_mode ::= NONE", + /* 202 */ "fill_mode ::= PREV", + /* 203 */ "fill_mode ::= NULL", + /* 204 */ "fill_mode ::= LINEAR", + /* 205 */ "fill_mode ::= NEXT", + /* 206 */ "group_by_clause_opt ::=", + /* 207 */ "group_by_clause_opt ::= GROUP BY group_by_list", + /* 208 */ "group_by_list ::= expression", + /* 209 */ "group_by_list ::= group_by_list NK_COMMA expression", + /* 210 */ "having_clause_opt ::=", + /* 211 */ "having_clause_opt ::= HAVING search_condition", + /* 212 */ "query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt", + /* 213 */ "query_expression_body ::= query_primary", + /* 214 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body", + /* 215 */ "query_primary ::= query_specification", + /* 216 */ "order_by_clause_opt ::=", + /* 217 */ "order_by_clause_opt ::= ORDER BY sort_specification_list", + /* 218 */ "slimit_clause_opt ::=", + /* 219 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER", + /* 220 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER", + /* 221 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER", + /* 222 */ "limit_clause_opt ::=", + /* 223 */ "limit_clause_opt ::= LIMIT NK_INTEGER", + /* 224 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER", + /* 225 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER", + /* 226 */ "subquery ::= NK_LP query_expression NK_RP", + /* 227 */ "search_condition ::= common_expression", + /* 228 */ "sort_specification_list ::= sort_specification", + /* 229 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification", + /* 230 */ "sort_specification ::= expression ordering_specification_opt null_ordering_opt", + /* 231 */ "ordering_specification_opt ::=", + /* 232 */ "ordering_specification_opt ::= ASC", + /* 233 */ "ordering_specification_opt ::= DESC", + /* 234 */ "null_ordering_opt ::=", + /* 235 */ "null_ordering_opt ::= NULLS FIRST", + /* 236 */ "null_ordering_opt ::= NULLS LAST", }; #endif /* NDEBUG */ @@ -1425,28 +1094,29 @@ static int yyGrowStack(yyParser *p){ /* Initialize a new parser that has already been allocated. */ -void ParseInit(void *yypParser){ - yyParser *pParser = (yyParser*)yypParser; +void ParseInit(void *yypRawParser ParseCTX_PDECL){ + yyParser *yypParser = (yyParser*)yypRawParser; + ParseCTX_STORE #ifdef YYTRACKMAXSTACKDEPTH - pParser->yyhwm = 0; + yypParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 - pParser->yytos = NULL; - pParser->yystack = NULL; - pParser->yystksz = 0; - if( yyGrowStack(pParser) ){ - pParser->yystack = &pParser->yystk0; - pParser->yystksz = 1; + yypParser->yytos = NULL; + yypParser->yystack = NULL; + yypParser->yystksz = 0; + if( yyGrowStack(yypParser) ){ + yypParser->yystack = &yypParser->yystk0; + yypParser->yystksz = 1; } #endif #ifndef YYNOERRORRECOVERY - pParser->yyerrcnt = -1; + yypParser->yyerrcnt = -1; #endif - pParser->yytos = pParser->yystack; - pParser->yystack[0].stateno = 0; - pParser->yystack[0].major = 0; + yypParser->yytos = yypParser->yystack; + yypParser->yystack[0].stateno = 0; + yypParser->yystack[0].major = 0; #if YYSTACKDEPTH>0 - pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; + yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; #endif } @@ -1463,11 +1133,14 @@ void ParseInit(void *yypParser){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ - yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( pParser ) ParseInit(pParser); - return pParser; +void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ + yyParser *yypParser; + yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + if( yypParser ){ + ParseCTX_STORE + ParseInit(yypParser ParseCTX_PARAM); + } + return (void*)yypParser; } #endif /* Parse_ENGINEALWAYSONSTACK */ @@ -1484,7 +1157,8 @@ static void yy_destructor( YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen @@ -1497,61 +1171,127 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 201: /* exprlist */ - case 247: /* selcollist */ - case 261: /* sclp */ + /* Default NON-TERMINAL Destructor */ + case 135: /* cmd */ + case 143: /* full_table_name */ + case 150: /* create_subtable_clause */ + case 153: /* drop_table_clause */ + case 156: /* column_def */ + case 159: /* col_name */ + case 160: /* query_expression */ + case 161: /* literal */ + case 162: /* duration_literal */ + case 166: /* expression */ + case 167: /* column_reference */ + case 169: /* subquery */ + case 170: /* predicate */ + case 173: /* in_predicate_value */ + case 174: /* boolean_value_expression */ + case 175: /* boolean_primary */ + case 176: /* common_expression */ + case 177: /* from_clause */ + case 178: /* table_reference_list */ + case 179: /* table_reference */ + case 180: /* table_primary */ + case 181: /* joined_table */ + case 183: /* parenthesized_joined_table */ + case 185: /* search_condition */ + case 186: /* query_specification */ + case 189: /* where_clause_opt */ + case 191: /* twindow_clause_opt */ + case 193: /* having_clause_opt */ + case 195: /* select_item */ + case 196: /* sliding_opt */ + case 197: /* fill_opt */ + case 200: /* query_expression_body */ + case 202: /* slimit_clause_opt */ + case 203: /* limit_clause_opt */ + case 204: /* query_primary */ + case 206: /* sort_specification */ +{ + nodesDestroyNode((yypminor->yy256)); +} + break; + case 136: /* user_name */ + case 137: /* dnode_endpoint */ + case 138: /* dnode_host_name */ + case 140: /* db_name */ + case 155: /* table_name */ + case 157: /* column_name */ + case 163: /* function_name */ + case 164: /* table_alias */ + case 165: /* column_alias */ + case 182: /* alias_opt */ { -tSqlExprListDestroy((yypminor->yy131)); + } break; - case 215: /* intitemlist */ - case 217: /* keep */ - case 239: /* columnlist */ - case 240: /* tagitemlist1 */ - case 241: /* tagNamelist */ - case 245: /* tagitemlist */ - case 254: /* fill_opt */ - case 255: /* groupby_opt */ - case 257: /* orderby_opt */ - case 269: /* sortlist */ - case 273: /* grouplist */ + case 139: /* not_exists_opt */ + case 142: /* exists_opt */ + case 187: /* set_quantifier_opt */ { -taosArrayDestroy((yypminor->yy131)); + } break; - case 237: /* create_table_list */ + case 141: /* db_options */ { -destroyCreateTableSql((yypminor->yy272)); + tfree((yypminor->yy391)); } break; - case 242: /* select */ + case 144: /* column_def_list */ + case 145: /* tags_def_opt */ + case 147: /* multi_create_clause */ + case 148: /* tags_def */ + case 149: /* multi_drop_clause */ + case 151: /* specific_tags_opt */ + case 152: /* literal_list */ + case 154: /* col_name_list */ + case 168: /* expression_list */ + case 188: /* select_list */ + case 190: /* partition_by_clause_opt */ + case 192: /* group_by_clause_opt */ + case 194: /* select_sublist */ + case 199: /* group_by_list */ + case 201: /* order_by_clause_opt */ + case 205: /* sort_specification_list */ +{ + nodesDestroyList((yypminor->yy46)); +} + break; + case 146: /* table_options */ { -destroySqlNode((yypminor->yy256)); + tfree((yypminor->yy340)); } break; - case 248: /* from */ - case 265: /* tablelist */ - case 266: /* sub */ + case 158: /* type_name */ { -destroyRelationInfo((yypminor->yy544)); + } break; - case 249: /* where_opt */ - case 256: /* having_opt */ - case 263: /* expr */ - case 274: /* expritem */ + case 171: /* compare_op */ + case 172: /* in_op */ { -tSqlExprDestroy((yypminor->yy46)); + } break; - case 260: /* union */ + case 184: /* join_type */ { -destroyAllSqlNode((yypminor->yy303)); + } break; - case 270: /* sortitem */ + case 198: /* fill_mode */ { -taosVariantDestroy(&(yypminor->yy43)); + +} + break; + case 207: /* ordering_specification_opt */ +{ + +} + break; + case 208: /* null_ordering_opt */ +{ + } break; /********* End destructor definitions *****************************************/ @@ -1663,13 +1403,12 @@ int ParseCoverage(FILE *out){ ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ -static unsigned int yy_find_shift_action( - yyParser *pParser, /* The parser */ - YYCODETYPE iLookAhead /* The look-ahead token */ +static YYACTIONTYPE yy_find_shift_action( + YYCODETYPE iLookAhead, /* The look-ahead token */ + YYACTIONTYPE stateno /* Current state number */ ){ int i; - int stateno = pParser->yytos->stateno; - + if( stateno>YY_MAX_SHIFT ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); #if defined(YYCOVERAGE) @@ -1677,11 +1416,12 @@ static unsigned int yy_find_shift_action( #endif do{ i = yy_shift_ofst[stateno]; - assert( i>=0 && i+YYNTOKEN<=sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); + assert( i>=0 ); + /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - if( yy_lookahead[i]!=iLookAhead ){ + if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ if( iLookAhead=YY_ACTTAB_COUNT j0 ){ #ifndef NDEBUG @@ -1731,8 +1472,8 @@ static unsigned int yy_find_shift_action( ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. */ -static int yy_find_reduce_action( - int stateno, /* Current state number */ +static YYACTIONTYPE yy_find_reduce_action( + YYACTIONTYPE stateno, /* Current state number */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; @@ -1761,7 +1502,8 @@ static int yy_find_reduce_action( ** The following routine is called if the stack overflows. */ static void yyStackOverflow(yyParser *yypParser){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); @@ -1772,7 +1514,8 @@ static void yyStackOverflow(yyParser *yypParser){ ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ /******** End %stack_overflow code ********************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ + ParseARG_STORE /* Suppress warning about unused %extra_argument var */ + ParseCTX_STORE } /* @@ -1801,8 +1544,8 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ - int yyNewState, /* The new state to shift in */ - int yyMajor, /* The major token to shift in */ + YYACTIONTYPE yyNewState, /* The new state to shift in */ + YYCODETYPE yyMajor, /* The major token to shift in */ ParseTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; @@ -1832,8 +1575,8 @@ static void yy_shift( yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; } yytos = yypParser->yytos; - yytos->stateno = (YYACTIONTYPE)yyNewState; - yytos->major = (YYCODETYPE)yyMajor; + yytos->stateno = yyNewState; + yytos->major = yyMajor; yytos->minor.yy0 = yyMinor; yyTraceShift(yypParser, yyNewState, "Shift"); } @@ -1845,310 +1588,243 @@ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ signed char nrhs; /* Negative of the number of RHS symbols in the rule */ } yyRuleInfo[] = { - { 193, -1 }, /* (0) program ::= cmd */ - { 194, -2 }, /* (1) cmd ::= SHOW DATABASES */ - { 194, -2 }, /* (2) cmd ::= SHOW TOPICS */ - { 194, -2 }, /* (3) cmd ::= SHOW FUNCTIONS */ - { 194, -2 }, /* (4) cmd ::= SHOW MNODES */ - { 194, -2 }, /* (5) cmd ::= SHOW DNODES */ - { 194, -2 }, /* (6) cmd ::= SHOW ACCOUNTS */ - { 194, -2 }, /* (7) cmd ::= SHOW USERS */ - { 194, -2 }, /* (8) cmd ::= SHOW MODULES */ - { 194, -2 }, /* (9) cmd ::= SHOW QUERIES */ - { 194, -2 }, /* (10) cmd ::= SHOW CONNECTIONS */ - { 194, -2 }, /* (11) cmd ::= SHOW STREAMS */ - { 194, -2 }, /* (12) cmd ::= SHOW VARIABLES */ - { 194, -2 }, /* (13) cmd ::= SHOW SCORES */ - { 194, -2 }, /* (14) cmd ::= SHOW GRANTS */ - { 194, -2 }, /* (15) cmd ::= SHOW VNODES */ - { 194, -3 }, /* (16) cmd ::= SHOW VNODES ids */ - { 196, 0 }, /* (17) dbPrefix ::= */ - { 196, -2 }, /* (18) dbPrefix ::= ids DOT */ - { 197, 0 }, /* (19) cpxName ::= */ - { 197, -2 }, /* (20) cpxName ::= DOT ids */ - { 194, -5 }, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ - { 194, -5 }, /* (22) cmd ::= SHOW CREATE STABLE ids cpxName */ - { 194, -4 }, /* (23) cmd ::= SHOW CREATE DATABASE ids */ - { 194, -3 }, /* (24) cmd ::= SHOW dbPrefix TABLES */ - { 194, -5 }, /* (25) cmd ::= SHOW dbPrefix TABLES LIKE ids */ - { 194, -3 }, /* (26) cmd ::= SHOW dbPrefix STABLES */ - { 194, -5 }, /* (27) cmd ::= SHOW dbPrefix STABLES LIKE ids */ - { 194, -3 }, /* (28) cmd ::= SHOW dbPrefix VGROUPS */ - { 194, -4 }, /* (29) cmd ::= SHOW dbPrefix VGROUPS ids */ - { 194, -5 }, /* (30) cmd ::= DROP TABLE ifexists ids cpxName */ - { 194, -5 }, /* (31) cmd ::= DROP STABLE ifexists ids cpxName */ - { 194, -4 }, /* (32) cmd ::= DROP DATABASE ifexists ids */ - { 194, -4 }, /* (33) cmd ::= DROP TOPIC ifexists ids */ - { 194, -3 }, /* (34) cmd ::= DROP FUNCTION ids */ - { 194, -3 }, /* (35) cmd ::= DROP DNODE ids */ - { 194, -3 }, /* (36) cmd ::= DROP USER ids */ - { 194, -3 }, /* (37) cmd ::= DROP ACCOUNT ids */ - { 194, -2 }, /* (38) cmd ::= USE ids */ - { 194, -3 }, /* (39) cmd ::= DESCRIBE ids cpxName */ - { 194, -3 }, /* (40) cmd ::= DESC ids cpxName */ - { 194, -5 }, /* (41) cmd ::= ALTER USER ids PASS ids */ - { 194, -5 }, /* (42) cmd ::= ALTER USER ids PRIVILEGE ids */ - { 194, -4 }, /* (43) cmd ::= ALTER DNODE ids ids */ - { 194, -5 }, /* (44) cmd ::= ALTER DNODE ids ids ids */ - { 194, -3 }, /* (45) cmd ::= ALTER LOCAL ids */ - { 194, -4 }, /* (46) cmd ::= ALTER LOCAL ids ids */ - { 194, -4 }, /* (47) cmd ::= ALTER DATABASE ids alter_db_optr */ - { 194, -4 }, /* (48) cmd ::= ALTER ACCOUNT ids acct_optr */ - { 194, -6 }, /* (49) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ - { 194, -6 }, /* (50) cmd ::= COMPACT VNODES IN LP exprlist RP */ - { 195, -1 }, /* (51) ids ::= ID */ - { 198, -2 }, /* (52) ifexists ::= IF EXISTS */ - { 198, 0 }, /* (53) ifexists ::= */ - { 202, -3 }, /* (54) ifnotexists ::= IF NOT EXISTS */ - { 202, 0 }, /* (55) ifnotexists ::= */ - { 194, -5 }, /* (56) cmd ::= CREATE DNODE ids PORT ids */ - { 194, -5 }, /* (57) cmd ::= CREATE DNODE IPTOKEN PORT ids */ - { 194, -6 }, /* (58) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ - { 194, -5 }, /* (59) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ - { 194, -8 }, /* (60) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ - { 194, -9 }, /* (61) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ - { 194, -5 }, /* (62) cmd ::= CREATE USER ids PASS ids */ - { 205, 0 }, /* (63) bufsize ::= */ - { 205, -2 }, /* (64) bufsize ::= BUFSIZE INTEGER */ - { 206, 0 }, /* (65) pps ::= */ - { 206, -2 }, /* (66) pps ::= PPS INTEGER */ - { 207, 0 }, /* (67) tseries ::= */ - { 207, -2 }, /* (68) tseries ::= TSERIES INTEGER */ - { 208, 0 }, /* (69) dbs ::= */ - { 208, -2 }, /* (70) dbs ::= DBS INTEGER */ - { 209, 0 }, /* (71) streams ::= */ - { 209, -2 }, /* (72) streams ::= STREAMS INTEGER */ - { 210, 0 }, /* (73) storage ::= */ - { 210, -2 }, /* (74) storage ::= STORAGE INTEGER */ - { 211, 0 }, /* (75) qtime ::= */ - { 211, -2 }, /* (76) qtime ::= QTIME INTEGER */ - { 212, 0 }, /* (77) users ::= */ - { 212, -2 }, /* (78) users ::= USERS INTEGER */ - { 213, 0 }, /* (79) conns ::= */ - { 213, -2 }, /* (80) conns ::= CONNS INTEGER */ - { 214, 0 }, /* (81) state ::= */ - { 214, -2 }, /* (82) state ::= STATE ids */ - { 200, -9 }, /* (83) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ - { 215, -3 }, /* (84) intitemlist ::= intitemlist COMMA intitem */ - { 215, -1 }, /* (85) intitemlist ::= intitem */ - { 216, -1 }, /* (86) intitem ::= INTEGER */ - { 217, -2 }, /* (87) keep ::= KEEP intitemlist */ - { 218, -2 }, /* (88) cache ::= CACHE INTEGER */ - { 219, -2 }, /* (89) replica ::= REPLICA INTEGER */ - { 220, -2 }, /* (90) quorum ::= QUORUM INTEGER */ - { 221, -2 }, /* (91) days ::= DAYS INTEGER */ - { 222, -2 }, /* (92) minrows ::= MINROWS INTEGER */ - { 223, -2 }, /* (93) maxrows ::= MAXROWS INTEGER */ - { 224, -2 }, /* (94) blocks ::= BLOCKS INTEGER */ - { 225, -2 }, /* (95) ctime ::= CTIME INTEGER */ - { 226, -2 }, /* (96) wal ::= WAL INTEGER */ - { 227, -2 }, /* (97) fsync ::= FSYNC INTEGER */ - { 228, -2 }, /* (98) comp ::= COMP INTEGER */ - { 229, -2 }, /* (99) prec ::= PRECISION STRING */ - { 230, -2 }, /* (100) update ::= UPDATE INTEGER */ - { 231, -2 }, /* (101) cachelast ::= CACHELAST INTEGER */ - { 232, -2 }, /* (102) vgroups ::= VGROUPS INTEGER */ - { 233, -3 }, /* (103) stream_mode ::= STREAM MODE INTEGER */ - { 203, 0 }, /* (104) db_optr ::= */ - { 203, -2 }, /* (105) db_optr ::= db_optr cache */ - { 203, -2 }, /* (106) db_optr ::= db_optr replica */ - { 203, -2 }, /* (107) db_optr ::= db_optr quorum */ - { 203, -2 }, /* (108) db_optr ::= db_optr days */ - { 203, -2 }, /* (109) db_optr ::= db_optr minrows */ - { 203, -2 }, /* (110) db_optr ::= db_optr maxrows */ - { 203, -2 }, /* (111) db_optr ::= db_optr blocks */ - { 203, -2 }, /* (112) db_optr ::= db_optr ctime */ - { 203, -2 }, /* (113) db_optr ::= db_optr wal */ - { 203, -2 }, /* (114) db_optr ::= db_optr fsync */ - { 203, -2 }, /* (115) db_optr ::= db_optr comp */ - { 203, -2 }, /* (116) db_optr ::= db_optr prec */ - { 203, -2 }, /* (117) db_optr ::= db_optr keep */ - { 203, -2 }, /* (118) db_optr ::= db_optr update */ - { 203, -2 }, /* (119) db_optr ::= db_optr cachelast */ - { 203, -2 }, /* (120) db_optr ::= db_optr vgroups */ - { 203, -2 }, /* (121) db_optr ::= db_optr stream_mode */ - { 199, 0 }, /* (122) alter_db_optr ::= */ - { 199, -2 }, /* (123) alter_db_optr ::= alter_db_optr replica */ - { 199, -2 }, /* (124) alter_db_optr ::= alter_db_optr quorum */ - { 199, -2 }, /* (125) alter_db_optr ::= alter_db_optr keep */ - { 199, -2 }, /* (126) alter_db_optr ::= alter_db_optr blocks */ - { 199, -2 }, /* (127) alter_db_optr ::= alter_db_optr comp */ - { 199, -2 }, /* (128) alter_db_optr ::= alter_db_optr update */ - { 199, -2 }, /* (129) alter_db_optr ::= alter_db_optr cachelast */ - { 204, -1 }, /* (130) typename ::= ids */ - { 204, -4 }, /* (131) typename ::= ids LP signed RP */ - { 204, -2 }, /* (132) typename ::= ids UNSIGNED */ - { 234, -1 }, /* (133) signed ::= INTEGER */ - { 234, -2 }, /* (134) signed ::= PLUS INTEGER */ - { 234, -2 }, /* (135) signed ::= MINUS INTEGER */ - { 194, -3 }, /* (136) cmd ::= CREATE TABLE create_table_args */ - { 194, -3 }, /* (137) cmd ::= CREATE TABLE create_stable_args */ - { 194, -3 }, /* (138) cmd ::= CREATE STABLE create_stable_args */ - { 194, -3 }, /* (139) cmd ::= CREATE TABLE create_table_list */ - { 237, -1 }, /* (140) create_table_list ::= create_from_stable */ - { 237, -2 }, /* (141) create_table_list ::= create_table_list create_from_stable */ - { 235, -6 }, /* (142) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ - { 236, -10 }, /* (143) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ - { 238, -10 }, /* (144) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist1 RP */ - { 238, -13 }, /* (145) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist1 RP */ - { 241, -3 }, /* (146) tagNamelist ::= tagNamelist COMMA ids */ - { 241, -1 }, /* (147) tagNamelist ::= ids */ - { 235, -5 }, /* (148) create_table_args ::= ifnotexists ids cpxName AS select */ - { 239, -3 }, /* (149) columnlist ::= columnlist COMMA column */ - { 239, -1 }, /* (150) columnlist ::= column */ - { 243, -2 }, /* (151) column ::= ids typename */ - { 240, -3 }, /* (152) tagitemlist1 ::= tagitemlist1 COMMA tagitem1 */ - { 240, -1 }, /* (153) tagitemlist1 ::= tagitem1 */ - { 244, -2 }, /* (154) tagitem1 ::= MINUS INTEGER */ - { 244, -2 }, /* (155) tagitem1 ::= MINUS FLOAT */ - { 244, -2 }, /* (156) tagitem1 ::= PLUS INTEGER */ - { 244, -2 }, /* (157) tagitem1 ::= PLUS FLOAT */ - { 244, -1 }, /* (158) tagitem1 ::= INTEGER */ - { 244, -1 }, /* (159) tagitem1 ::= FLOAT */ - { 244, -1 }, /* (160) tagitem1 ::= STRING */ - { 244, -1 }, /* (161) tagitem1 ::= BOOL */ - { 244, -1 }, /* (162) tagitem1 ::= NULL */ - { 244, -1 }, /* (163) tagitem1 ::= NOW */ - { 245, -3 }, /* (164) tagitemlist ::= tagitemlist COMMA tagitem */ - { 245, -1 }, /* (165) tagitemlist ::= tagitem */ - { 246, -1 }, /* (166) tagitem ::= INTEGER */ - { 246, -1 }, /* (167) tagitem ::= FLOAT */ - { 246, -1 }, /* (168) tagitem ::= STRING */ - { 246, -1 }, /* (169) tagitem ::= BOOL */ - { 246, -1 }, /* (170) tagitem ::= NULL */ - { 246, -1 }, /* (171) tagitem ::= NOW */ - { 246, -2 }, /* (172) tagitem ::= MINUS INTEGER */ - { 246, -2 }, /* (173) tagitem ::= MINUS FLOAT */ - { 246, -2 }, /* (174) tagitem ::= PLUS INTEGER */ - { 246, -2 }, /* (175) tagitem ::= PLUS FLOAT */ - { 242, -14 }, /* (176) select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ - { 242, -3 }, /* (177) select ::= LP select RP */ - { 260, -1 }, /* (178) union ::= select */ - { 260, -4 }, /* (179) union ::= union UNION ALL select */ - { 260, -3 }, /* (180) union ::= union UNION select */ - { 194, -1 }, /* (181) cmd ::= union */ - { 242, -2 }, /* (182) select ::= SELECT selcollist */ - { 261, -2 }, /* (183) sclp ::= selcollist COMMA */ - { 261, 0 }, /* (184) sclp ::= */ - { 247, -4 }, /* (185) selcollist ::= sclp distinct expr as */ - { 247, -2 }, /* (186) selcollist ::= sclp STAR */ - { 264, -2 }, /* (187) as ::= AS ids */ - { 264, -1 }, /* (188) as ::= ids */ - { 264, 0 }, /* (189) as ::= */ - { 262, -1 }, /* (190) distinct ::= DISTINCT */ - { 262, 0 }, /* (191) distinct ::= */ - { 248, -2 }, /* (192) from ::= FROM tablelist */ - { 248, -2 }, /* (193) from ::= FROM sub */ - { 266, -3 }, /* (194) sub ::= LP union RP */ - { 266, -4 }, /* (195) sub ::= LP union RP ids */ - { 266, -6 }, /* (196) sub ::= sub COMMA LP union RP ids */ - { 265, -2 }, /* (197) tablelist ::= ids cpxName */ - { 265, -3 }, /* (198) tablelist ::= ids cpxName ids */ - { 265, -4 }, /* (199) tablelist ::= tablelist COMMA ids cpxName */ - { 265, -5 }, /* (200) tablelist ::= tablelist COMMA ids cpxName ids */ - { 267, -1 }, /* (201) tmvar ::= VARIABLE */ - { 250, -4 }, /* (202) interval_option ::= intervalKey LP tmvar RP */ - { 250, -6 }, /* (203) interval_option ::= intervalKey LP tmvar COMMA tmvar RP */ - { 250, 0 }, /* (204) interval_option ::= */ - { 268, -1 }, /* (205) intervalKey ::= INTERVAL */ - { 268, -1 }, /* (206) intervalKey ::= EVERY */ - { 252, 0 }, /* (207) session_option ::= */ - { 252, -7 }, /* (208) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ - { 253, 0 }, /* (209) windowstate_option ::= */ - { 253, -4 }, /* (210) windowstate_option ::= STATE_WINDOW LP ids RP */ - { 254, 0 }, /* (211) fill_opt ::= */ - { 254, -6 }, /* (212) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ - { 254, -4 }, /* (213) fill_opt ::= FILL LP ID RP */ - { 251, -4 }, /* (214) sliding_opt ::= SLIDING LP tmvar RP */ - { 251, 0 }, /* (215) sliding_opt ::= */ - { 257, 0 }, /* (216) orderby_opt ::= */ - { 257, -3 }, /* (217) orderby_opt ::= ORDER BY sortlist */ - { 269, -4 }, /* (218) sortlist ::= sortlist COMMA item sortorder */ - { 269, -2 }, /* (219) sortlist ::= item sortorder */ - { 271, -2 }, /* (220) item ::= ids cpxName */ - { 272, -1 }, /* (221) sortorder ::= ASC */ - { 272, -1 }, /* (222) sortorder ::= DESC */ - { 272, 0 }, /* (223) sortorder ::= */ - { 255, 0 }, /* (224) groupby_opt ::= */ - { 255, -3 }, /* (225) groupby_opt ::= GROUP BY grouplist */ - { 273, -3 }, /* (226) grouplist ::= grouplist COMMA item */ - { 273, -1 }, /* (227) grouplist ::= item */ - { 256, 0 }, /* (228) having_opt ::= */ - { 256, -2 }, /* (229) having_opt ::= HAVING expr */ - { 259, 0 }, /* (230) limit_opt ::= */ - { 259, -2 }, /* (231) limit_opt ::= LIMIT signed */ - { 259, -4 }, /* (232) limit_opt ::= LIMIT signed OFFSET signed */ - { 259, -4 }, /* (233) limit_opt ::= LIMIT signed COMMA signed */ - { 258, 0 }, /* (234) slimit_opt ::= */ - { 258, -2 }, /* (235) slimit_opt ::= SLIMIT signed */ - { 258, -4 }, /* (236) slimit_opt ::= SLIMIT signed SOFFSET signed */ - { 258, -4 }, /* (237) slimit_opt ::= SLIMIT signed COMMA signed */ - { 249, 0 }, /* (238) where_opt ::= */ - { 249, -2 }, /* (239) where_opt ::= WHERE expr */ - { 263, -3 }, /* (240) expr ::= LP expr RP */ - { 263, -1 }, /* (241) expr ::= ID */ - { 263, -3 }, /* (242) expr ::= ID DOT ID */ - { 263, -3 }, /* (243) expr ::= ID DOT STAR */ - { 263, -1 }, /* (244) expr ::= INTEGER */ - { 263, -2 }, /* (245) expr ::= MINUS INTEGER */ - { 263, -2 }, /* (246) expr ::= PLUS INTEGER */ - { 263, -1 }, /* (247) expr ::= FLOAT */ - { 263, -2 }, /* (248) expr ::= MINUS FLOAT */ - { 263, -2 }, /* (249) expr ::= PLUS FLOAT */ - { 263, -1 }, /* (250) expr ::= STRING */ - { 263, -1 }, /* (251) expr ::= NOW */ - { 263, -1 }, /* (252) expr ::= VARIABLE */ - { 263, -2 }, /* (253) expr ::= PLUS VARIABLE */ - { 263, -2 }, /* (254) expr ::= MINUS VARIABLE */ - { 263, -1 }, /* (255) expr ::= BOOL */ - { 263, -1 }, /* (256) expr ::= NULL */ - { 263, -4 }, /* (257) expr ::= ID LP exprlist RP */ - { 263, -4 }, /* (258) expr ::= ID LP STAR RP */ - { 263, -3 }, /* (259) expr ::= expr IS NULL */ - { 263, -4 }, /* (260) expr ::= expr IS NOT NULL */ - { 263, -3 }, /* (261) expr ::= expr LT expr */ - { 263, -3 }, /* (262) expr ::= expr GT expr */ - { 263, -3 }, /* (263) expr ::= expr LE expr */ - { 263, -3 }, /* (264) expr ::= expr GE expr */ - { 263, -3 }, /* (265) expr ::= expr NE expr */ - { 263, -3 }, /* (266) expr ::= expr EQ expr */ - { 263, -5 }, /* (267) expr ::= expr BETWEEN expr AND expr */ - { 263, -3 }, /* (268) expr ::= expr AND expr */ - { 263, -3 }, /* (269) expr ::= expr OR expr */ - { 263, -3 }, /* (270) expr ::= expr PLUS expr */ - { 263, -3 }, /* (271) expr ::= expr MINUS expr */ - { 263, -3 }, /* (272) expr ::= expr STAR expr */ - { 263, -3 }, /* (273) expr ::= expr SLASH expr */ - { 263, -3 }, /* (274) expr ::= expr REM expr */ - { 263, -3 }, /* (275) expr ::= expr LIKE expr */ - { 263, -3 }, /* (276) expr ::= expr MATCH expr */ - { 263, -3 }, /* (277) expr ::= expr NMATCH expr */ - { 263, -5 }, /* (278) expr ::= expr IN LP exprlist RP */ - { 201, -3 }, /* (279) exprlist ::= exprlist COMMA expritem */ - { 201, -1 }, /* (280) exprlist ::= expritem */ - { 274, -1 }, /* (281) expritem ::= expr */ - { 274, 0 }, /* (282) expritem ::= */ - { 194, -3 }, /* (283) cmd ::= RESET QUERY CACHE */ - { 194, -3 }, /* (284) cmd ::= SYNCDB ids REPLICA */ - { 194, -7 }, /* (285) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ - { 194, -7 }, /* (286) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ - { 194, -7 }, /* (287) cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ - { 194, -7 }, /* (288) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ - { 194, -7 }, /* (289) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ - { 194, -8 }, /* (290) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ - { 194, -9 }, /* (291) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ - { 194, -7 }, /* (292) cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ - { 194, -7 }, /* (293) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ - { 194, -7 }, /* (294) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ - { 194, -7 }, /* (295) cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ - { 194, -7 }, /* (296) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ - { 194, -7 }, /* (297) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ - { 194, -8 }, /* (298) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ - { 194, -9 }, /* (299) cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ - { 194, -7 }, /* (300) cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ - { 194, -3 }, /* (301) cmd ::= KILL CONNECTION INTEGER */ - { 194, -5 }, /* (302) cmd ::= KILL STREAM INTEGER COLON INTEGER */ - { 194, -5 }, /* (303) cmd ::= KILL QUERY INTEGER COLON INTEGER */ + { 135, -5 }, /* (0) cmd ::= CREATE USER user_name PASS NK_STRING */ + { 135, -5 }, /* (1) cmd ::= ALTER USER user_name PASS NK_STRING */ + { 135, -5 }, /* (2) cmd ::= ALTER USER user_name PRIVILEGE NK_STRING */ + { 135, -3 }, /* (3) cmd ::= DROP USER user_name */ + { 135, -2 }, /* (4) cmd ::= SHOW USERS */ + { 135, -3 }, /* (5) cmd ::= CREATE DNODE dnode_endpoint */ + { 135, -5 }, /* (6) cmd ::= CREATE DNODE dnode_host_name PORT NK_INTEGER */ + { 135, -3 }, /* (7) cmd ::= DROP DNODE NK_INTEGER */ + { 135, -3 }, /* (8) cmd ::= DROP DNODE dnode_endpoint */ + { 135, -2 }, /* (9) cmd ::= SHOW DNODES */ + { 137, -1 }, /* (10) dnode_endpoint ::= NK_STRING */ + { 138, -1 }, /* (11) dnode_host_name ::= NK_ID */ + { 138, -1 }, /* (12) dnode_host_name ::= NK_IPTOKEN */ + { 135, -5 }, /* (13) cmd ::= CREATE DATABASE not_exists_opt db_name db_options */ + { 135, -4 }, /* (14) cmd ::= DROP DATABASE exists_opt db_name */ + { 135, -2 }, /* (15) cmd ::= SHOW DATABASES */ + { 135, -2 }, /* (16) cmd ::= USE db_name */ + { 139, -3 }, /* (17) not_exists_opt ::= IF NOT EXISTS */ + { 139, 0 }, /* (18) not_exists_opt ::= */ + { 142, -2 }, /* (19) exists_opt ::= IF EXISTS */ + { 142, 0 }, /* (20) exists_opt ::= */ + { 141, 0 }, /* (21) db_options ::= */ + { 141, -3 }, /* (22) db_options ::= db_options BLOCKS NK_INTEGER */ + { 141, -3 }, /* (23) db_options ::= db_options CACHE NK_INTEGER */ + { 141, -3 }, /* (24) db_options ::= db_options CACHELAST NK_INTEGER */ + { 141, -3 }, /* (25) db_options ::= db_options COMP NK_INTEGER */ + { 141, -3 }, /* (26) db_options ::= db_options DAYS NK_INTEGER */ + { 141, -3 }, /* (27) db_options ::= db_options FSYNC NK_INTEGER */ + { 141, -3 }, /* (28) db_options ::= db_options MAXROWS NK_INTEGER */ + { 141, -3 }, /* (29) db_options ::= db_options MINROWS NK_INTEGER */ + { 141, -3 }, /* (30) db_options ::= db_options KEEP NK_INTEGER */ + { 141, -3 }, /* (31) db_options ::= db_options PRECISION NK_STRING */ + { 141, -3 }, /* (32) db_options ::= db_options QUORUM NK_INTEGER */ + { 141, -3 }, /* (33) db_options ::= db_options REPLICA NK_INTEGER */ + { 141, -3 }, /* (34) db_options ::= db_options TTL NK_INTEGER */ + { 141, -3 }, /* (35) db_options ::= db_options WAL NK_INTEGER */ + { 141, -3 }, /* (36) db_options ::= db_options VGROUPS NK_INTEGER */ + { 141, -3 }, /* (37) db_options ::= db_options SINGLE_STABLE NK_INTEGER */ + { 141, -3 }, /* (38) db_options ::= db_options STREAM_MODE NK_INTEGER */ + { 135, -9 }, /* (39) cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */ + { 135, -3 }, /* (40) cmd ::= CREATE TABLE multi_create_clause */ + { 135, -9 }, /* (41) cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */ + { 135, -3 }, /* (42) cmd ::= DROP TABLE multi_drop_clause */ + { 135, -4 }, /* (43) cmd ::= DROP STABLE exists_opt full_table_name */ + { 135, -2 }, /* (44) cmd ::= SHOW TABLES */ + { 135, -2 }, /* (45) cmd ::= SHOW STABLES */ + { 147, -1 }, /* (46) multi_create_clause ::= create_subtable_clause */ + { 147, -2 }, /* (47) multi_create_clause ::= multi_create_clause create_subtable_clause */ + { 150, -9 }, /* (48) create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_tags_opt TAGS NK_LP literal_list NK_RP */ + { 149, -1 }, /* (49) multi_drop_clause ::= drop_table_clause */ + { 149, -2 }, /* (50) multi_drop_clause ::= multi_drop_clause drop_table_clause */ + { 153, -2 }, /* (51) drop_table_clause ::= exists_opt full_table_name */ + { 151, 0 }, /* (52) specific_tags_opt ::= */ + { 151, -3 }, /* (53) specific_tags_opt ::= NK_LP col_name_list NK_RP */ + { 143, -1 }, /* (54) full_table_name ::= table_name */ + { 143, -3 }, /* (55) full_table_name ::= db_name NK_DOT table_name */ + { 144, -1 }, /* (56) column_def_list ::= column_def */ + { 144, -3 }, /* (57) column_def_list ::= column_def_list NK_COMMA column_def */ + { 156, -2 }, /* (58) column_def ::= column_name type_name */ + { 156, -4 }, /* (59) column_def ::= column_name type_name COMMENT NK_STRING */ + { 158, -1 }, /* (60) type_name ::= BOOL */ + { 158, -1 }, /* (61) type_name ::= TINYINT */ + { 158, -1 }, /* (62) type_name ::= SMALLINT */ + { 158, -1 }, /* (63) type_name ::= INT */ + { 158, -1 }, /* (64) type_name ::= INTEGER */ + { 158, -1 }, /* (65) type_name ::= BIGINT */ + { 158, -1 }, /* (66) type_name ::= FLOAT */ + { 158, -1 }, /* (67) type_name ::= DOUBLE */ + { 158, -4 }, /* (68) type_name ::= BINARY NK_LP NK_INTEGER NK_RP */ + { 158, -1 }, /* (69) type_name ::= TIMESTAMP */ + { 158, -4 }, /* (70) type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */ + { 158, -2 }, /* (71) type_name ::= TINYINT UNSIGNED */ + { 158, -2 }, /* (72) type_name ::= SMALLINT UNSIGNED */ + { 158, -2 }, /* (73) type_name ::= INT UNSIGNED */ + { 158, -2 }, /* (74) type_name ::= BIGINT UNSIGNED */ + { 158, -1 }, /* (75) type_name ::= JSON */ + { 158, -4 }, /* (76) type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */ + { 158, -1 }, /* (77) type_name ::= MEDIUMBLOB */ + { 158, -1 }, /* (78) type_name ::= BLOB */ + { 158, -4 }, /* (79) type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */ + { 158, -1 }, /* (80) type_name ::= DECIMAL */ + { 158, -4 }, /* (81) type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */ + { 158, -6 }, /* (82) type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */ + { 145, 0 }, /* (83) tags_def_opt ::= */ + { 145, -1 }, /* (84) tags_def_opt ::= tags_def */ + { 148, -4 }, /* (85) tags_def ::= TAGS NK_LP column_def_list NK_RP */ + { 146, 0 }, /* (86) table_options ::= */ + { 146, -3 }, /* (87) table_options ::= table_options COMMENT NK_STRING */ + { 146, -3 }, /* (88) table_options ::= table_options KEEP NK_INTEGER */ + { 146, -3 }, /* (89) table_options ::= table_options TTL NK_INTEGER */ + { 146, -5 }, /* (90) table_options ::= table_options SMA NK_LP col_name_list NK_RP */ + { 154, -1 }, /* (91) col_name_list ::= col_name */ + { 154, -3 }, /* (92) col_name_list ::= col_name_list NK_COMMA col_name */ + { 159, -1 }, /* (93) col_name ::= column_name */ + { 135, -2 }, /* (94) cmd ::= SHOW VGROUPS */ + { 135, -4 }, /* (95) cmd ::= SHOW db_name NK_DOT VGROUPS */ + { 135, -2 }, /* (96) cmd ::= SHOW MNODES */ + { 135, -1 }, /* (97) cmd ::= query_expression */ + { 161, -1 }, /* (98) literal ::= NK_INTEGER */ + { 161, -1 }, /* (99) literal ::= NK_FLOAT */ + { 161, -1 }, /* (100) literal ::= NK_STRING */ + { 161, -1 }, /* (101) literal ::= NK_BOOL */ + { 161, -2 }, /* (102) literal ::= TIMESTAMP NK_STRING */ + { 161, -1 }, /* (103) literal ::= duration_literal */ + { 162, -1 }, /* (104) duration_literal ::= NK_VARIABLE */ + { 152, -1 }, /* (105) literal_list ::= literal */ + { 152, -3 }, /* (106) literal_list ::= literal_list NK_COMMA literal */ + { 140, -1 }, /* (107) db_name ::= NK_ID */ + { 155, -1 }, /* (108) table_name ::= NK_ID */ + { 157, -1 }, /* (109) column_name ::= NK_ID */ + { 163, -1 }, /* (110) function_name ::= NK_ID */ + { 164, -1 }, /* (111) table_alias ::= NK_ID */ + { 165, -1 }, /* (112) column_alias ::= NK_ID */ + { 136, -1 }, /* (113) user_name ::= NK_ID */ + { 166, -1 }, /* (114) expression ::= literal */ + { 166, -1 }, /* (115) expression ::= column_reference */ + { 166, -4 }, /* (116) expression ::= function_name NK_LP expression_list NK_RP */ + { 166, -4 }, /* (117) expression ::= function_name NK_LP NK_STAR NK_RP */ + { 166, -1 }, /* (118) expression ::= subquery */ + { 166, -3 }, /* (119) expression ::= NK_LP expression NK_RP */ + { 166, -2 }, /* (120) expression ::= NK_PLUS expression */ + { 166, -2 }, /* (121) expression ::= NK_MINUS expression */ + { 166, -3 }, /* (122) expression ::= expression NK_PLUS expression */ + { 166, -3 }, /* (123) expression ::= expression NK_MINUS expression */ + { 166, -3 }, /* (124) expression ::= expression NK_STAR expression */ + { 166, -3 }, /* (125) expression ::= expression NK_SLASH expression */ + { 166, -3 }, /* (126) expression ::= expression NK_REM expression */ + { 168, -1 }, /* (127) expression_list ::= expression */ + { 168, -3 }, /* (128) expression_list ::= expression_list NK_COMMA expression */ + { 167, -1 }, /* (129) column_reference ::= column_name */ + { 167, -3 }, /* (130) column_reference ::= table_name NK_DOT column_name */ + { 170, -3 }, /* (131) predicate ::= expression compare_op expression */ + { 170, -5 }, /* (132) predicate ::= expression BETWEEN expression AND expression */ + { 170, -6 }, /* (133) predicate ::= expression NOT BETWEEN expression AND expression */ + { 170, -3 }, /* (134) predicate ::= expression IS NULL */ + { 170, -4 }, /* (135) predicate ::= expression IS NOT NULL */ + { 170, -3 }, /* (136) predicate ::= expression in_op in_predicate_value */ + { 171, -1 }, /* (137) compare_op ::= NK_LT */ + { 171, -1 }, /* (138) compare_op ::= NK_GT */ + { 171, -1 }, /* (139) compare_op ::= NK_LE */ + { 171, -1 }, /* (140) compare_op ::= NK_GE */ + { 171, -1 }, /* (141) compare_op ::= NK_NE */ + { 171, -1 }, /* (142) compare_op ::= NK_EQ */ + { 171, -1 }, /* (143) compare_op ::= LIKE */ + { 171, -2 }, /* (144) compare_op ::= NOT LIKE */ + { 171, -1 }, /* (145) compare_op ::= MATCH */ + { 171, -1 }, /* (146) compare_op ::= NMATCH */ + { 172, -1 }, /* (147) in_op ::= IN */ + { 172, -2 }, /* (148) in_op ::= NOT IN */ + { 173, -3 }, /* (149) in_predicate_value ::= NK_LP expression_list NK_RP */ + { 174, -1 }, /* (150) boolean_value_expression ::= boolean_primary */ + { 174, -2 }, /* (151) boolean_value_expression ::= NOT boolean_primary */ + { 174, -3 }, /* (152) boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */ + { 174, -3 }, /* (153) boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */ + { 175, -1 }, /* (154) boolean_primary ::= predicate */ + { 175, -3 }, /* (155) boolean_primary ::= NK_LP boolean_value_expression NK_RP */ + { 176, -1 }, /* (156) common_expression ::= expression */ + { 176, -1 }, /* (157) common_expression ::= boolean_value_expression */ + { 177, -2 }, /* (158) from_clause ::= FROM table_reference_list */ + { 178, -1 }, /* (159) table_reference_list ::= table_reference */ + { 178, -3 }, /* (160) table_reference_list ::= table_reference_list NK_COMMA table_reference */ + { 179, -1 }, /* (161) table_reference ::= table_primary */ + { 179, -1 }, /* (162) table_reference ::= joined_table */ + { 180, -2 }, /* (163) table_primary ::= table_name alias_opt */ + { 180, -4 }, /* (164) table_primary ::= db_name NK_DOT table_name alias_opt */ + { 180, -2 }, /* (165) table_primary ::= subquery alias_opt */ + { 180, -1 }, /* (166) table_primary ::= parenthesized_joined_table */ + { 182, 0 }, /* (167) alias_opt ::= */ + { 182, -1 }, /* (168) alias_opt ::= table_alias */ + { 182, -2 }, /* (169) alias_opt ::= AS table_alias */ + { 183, -3 }, /* (170) parenthesized_joined_table ::= NK_LP joined_table NK_RP */ + { 183, -3 }, /* (171) parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ + { 181, -6 }, /* (172) joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ + { 184, 0 }, /* (173) join_type ::= */ + { 184, -1 }, /* (174) join_type ::= INNER */ + { 186, -9 }, /* (175) query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ + { 187, 0 }, /* (176) set_quantifier_opt ::= */ + { 187, -1 }, /* (177) set_quantifier_opt ::= DISTINCT */ + { 187, -1 }, /* (178) set_quantifier_opt ::= ALL */ + { 188, -1 }, /* (179) select_list ::= NK_STAR */ + { 188, -1 }, /* (180) select_list ::= select_sublist */ + { 194, -1 }, /* (181) select_sublist ::= select_item */ + { 194, -3 }, /* (182) select_sublist ::= select_sublist NK_COMMA select_item */ + { 195, -1 }, /* (183) select_item ::= common_expression */ + { 195, -2 }, /* (184) select_item ::= common_expression column_alias */ + { 195, -3 }, /* (185) select_item ::= common_expression AS column_alias */ + { 195, -3 }, /* (186) select_item ::= table_name NK_DOT NK_STAR */ + { 189, 0 }, /* (187) where_clause_opt ::= */ + { 189, -2 }, /* (188) where_clause_opt ::= WHERE search_condition */ + { 190, 0 }, /* (189) partition_by_clause_opt ::= */ + { 190, -3 }, /* (190) partition_by_clause_opt ::= PARTITION BY expression_list */ + { 191, 0 }, /* (191) twindow_clause_opt ::= */ + { 191, -6 }, /* (192) twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA NK_INTEGER NK_RP */ + { 191, -4 }, /* (193) twindow_clause_opt ::= STATE_WINDOW NK_LP column_reference NK_RP */ + { 191, -6 }, /* (194) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ + { 191, -8 }, /* (195) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ + { 196, 0 }, /* (196) sliding_opt ::= */ + { 196, -4 }, /* (197) sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ + { 197, 0 }, /* (198) fill_opt ::= */ + { 197, -4 }, /* (199) fill_opt ::= FILL NK_LP fill_mode NK_RP */ + { 197, -6 }, /* (200) fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ + { 198, -1 }, /* (201) fill_mode ::= NONE */ + { 198, -1 }, /* (202) fill_mode ::= PREV */ + { 198, -1 }, /* (203) fill_mode ::= NULL */ + { 198, -1 }, /* (204) fill_mode ::= LINEAR */ + { 198, -1 }, /* (205) fill_mode ::= NEXT */ + { 192, 0 }, /* (206) group_by_clause_opt ::= */ + { 192, -3 }, /* (207) group_by_clause_opt ::= GROUP BY group_by_list */ + { 199, -1 }, /* (208) group_by_list ::= expression */ + { 199, -3 }, /* (209) group_by_list ::= group_by_list NK_COMMA expression */ + { 193, 0 }, /* (210) having_clause_opt ::= */ + { 193, -2 }, /* (211) having_clause_opt ::= HAVING search_condition */ + { 160, -4 }, /* (212) query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ + { 200, -1 }, /* (213) query_expression_body ::= query_primary */ + { 200, -4 }, /* (214) query_expression_body ::= query_expression_body UNION ALL query_expression_body */ + { 204, -1 }, /* (215) query_primary ::= query_specification */ + { 201, 0 }, /* (216) order_by_clause_opt ::= */ + { 201, -3 }, /* (217) order_by_clause_opt ::= ORDER BY sort_specification_list */ + { 202, 0 }, /* (218) slimit_clause_opt ::= */ + { 202, -2 }, /* (219) slimit_clause_opt ::= SLIMIT NK_INTEGER */ + { 202, -4 }, /* (220) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ + { 202, -4 }, /* (221) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + { 203, 0 }, /* (222) limit_clause_opt ::= */ + { 203, -2 }, /* (223) limit_clause_opt ::= LIMIT NK_INTEGER */ + { 203, -4 }, /* (224) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ + { 203, -4 }, /* (225) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + { 169, -3 }, /* (226) subquery ::= NK_LP query_expression NK_RP */ + { 185, -1 }, /* (227) search_condition ::= common_expression */ + { 205, -1 }, /* (228) sort_specification_list ::= sort_specification */ + { 205, -3 }, /* (229) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ + { 206, -3 }, /* (230) sort_specification ::= expression ordering_specification_opt null_ordering_opt */ + { 207, 0 }, /* (231) ordering_specification_opt ::= */ + { 207, -1 }, /* (232) ordering_specification_opt ::= ASC */ + { 207, -1 }, /* (233) ordering_specification_opt ::= DESC */ + { 208, 0 }, /* (234) null_ordering_opt ::= */ + { 208, -2 }, /* (235) null_ordering_opt ::= NULLS FIRST */ + { 208, -2 }, /* (236) null_ordering_opt ::= NULLS LAST */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -2163,17 +1839,18 @@ static void yy_accept(yyParser*); /* Forward Declaration */ ** only called from one place, optimizing compilers will in-line it, which ** means that the extra parameters have no performance impact. */ -static void yy_reduce( +static YYACTIONTYPE yy_reduce( yyParser *yypParser, /* The parser */ unsigned int yyruleno, /* Number of the rule by which to reduce */ int yyLookahead, /* Lookahead token, or YYNOCODE if none */ ParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ + ParseCTX_PDECL /* %extra_context */ ){ int yygoto; /* The next state */ - int yyact; /* The next action */ + YYACTIONTYPE yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ - ParseARG_FETCH; + ParseARG_FETCH (void)yyLookahead; (void)yyLookaheadToken; yymsp = yypParser->yytos; @@ -2204,13 +1881,19 @@ static void yy_reduce( #if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); - return; + /* The call to yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } #else if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); - return; + /* The call to yyStackOverflow() above pops the stack until it is + ** empty, causing the main parser loop to exit. So the return value + ** is never used and does not matter. */ + return 0; } yymsp = yypParser->yytos; } @@ -2228,1132 +1911,749 @@ static void yy_reduce( */ /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; - case 0: /* program ::= cmd */ - case 136: /* cmd ::= CREATE TABLE create_table_args */ yytestcase(yyruleno==136); - case 137: /* cmd ::= CREATE TABLE create_stable_args */ yytestcase(yyruleno==137); - case 138: /* cmd ::= CREATE STABLE create_stable_args */ yytestcase(yyruleno==138); -{} + case 0: /* cmd ::= CREATE USER user_name PASS NK_STRING */ +{ pCxt->pRootNode = createCreateUserStmt(pCxt, &yymsp[-2].minor.yy129, &yymsp[0].minor.yy0);} break; - case 1: /* cmd ::= SHOW DATABASES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_DB, 0, 0);} + case 1: /* cmd ::= ALTER USER user_name PASS NK_STRING */ +{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy129, TSDB_ALTER_USER_PASSWD, &yymsp[0].minor.yy0);} break; - case 2: /* cmd ::= SHOW TOPICS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_TP, 0, 0);} + case 2: /* cmd ::= ALTER USER user_name PRIVILEGE NK_STRING */ +{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy129, TSDB_ALTER_USER_PRIVILEGES, &yymsp[0].minor.yy0);} break; - case 3: /* cmd ::= SHOW FUNCTIONS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_FUNC, 0, 0);} + case 3: /* cmd ::= DROP USER user_name */ +{ pCxt->pRootNode = createDropUserStmt(pCxt, &yymsp[0].minor.yy129); } break; - case 4: /* cmd ::= SHOW MNODES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_MNODE, 0, 0);} + case 4: /* cmd ::= SHOW USERS */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_USERS_STMT, NULL); } break; - case 5: /* cmd ::= SHOW DNODES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_DNODE, 0, 0);} + case 5: /* cmd ::= CREATE DNODE dnode_endpoint */ +{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[0].minor.yy129, NULL);} break; - case 6: /* cmd ::= SHOW ACCOUNTS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_ACCT, 0, 0);} + case 6: /* cmd ::= CREATE DNODE dnode_host_name PORT NK_INTEGER */ +{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[-2].minor.yy129, &yymsp[0].minor.yy0);} break; - case 7: /* cmd ::= SHOW USERS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_USER, 0, 0);} + case 7: /* cmd ::= DROP DNODE NK_INTEGER */ +{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[0].minor.yy0);} break; - case 8: /* cmd ::= SHOW MODULES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_MODULE, 0, 0); } + case 8: /* cmd ::= DROP DNODE dnode_endpoint */ +{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[0].minor.yy129);} break; - case 9: /* cmd ::= SHOW QUERIES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_QUERIES, 0, 0); } + case 9: /* cmd ::= SHOW DNODES */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DNODES_STMT, NULL); } break; - case 10: /* cmd ::= SHOW CONNECTIONS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_CONNS, 0, 0);} + case 10: /* dnode_endpoint ::= NK_STRING */ + case 11: /* dnode_host_name ::= NK_ID */ yytestcase(yyruleno==11); + case 12: /* dnode_host_name ::= NK_IPTOKEN */ yytestcase(yyruleno==12); + case 107: /* db_name ::= NK_ID */ yytestcase(yyruleno==107); + case 108: /* table_name ::= NK_ID */ yytestcase(yyruleno==108); + case 109: /* column_name ::= NK_ID */ yytestcase(yyruleno==109); + case 110: /* function_name ::= NK_ID */ yytestcase(yyruleno==110); + case 111: /* table_alias ::= NK_ID */ yytestcase(yyruleno==111); + case 112: /* column_alias ::= NK_ID */ yytestcase(yyruleno==112); + case 113: /* user_name ::= NK_ID */ yytestcase(yyruleno==113); +{ yylhsminor.yy129 = yymsp[0].minor.yy0; } + yymsp[0].minor.yy129 = yylhsminor.yy129; break; - case 11: /* cmd ::= SHOW STREAMS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_STREAMS, 0, 0); } + case 13: /* cmd ::= CREATE DATABASE not_exists_opt db_name db_options */ +{ pCxt->pRootNode = createCreateDatabaseStmt(pCxt, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy129, yymsp[0].minor.yy391);} break; - case 12: /* cmd ::= SHOW VARIABLES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_VARIABLES, 0, 0); } + case 14: /* cmd ::= DROP DATABASE exists_opt db_name */ +{ pCxt->pRootNode = createDropDatabaseStmt(pCxt, yymsp[-1].minor.yy185, &yymsp[0].minor.yy129); } break; - case 13: /* cmd ::= SHOW SCORES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_TRANS, 0, 0); } + case 15: /* cmd ::= SHOW DATABASES */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DATABASES_STMT, NULL); } break; - case 14: /* cmd ::= SHOW GRANTS */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_GRANTS, 0, 0); } + case 16: /* cmd ::= USE db_name */ +{ pCxt->pRootNode = createUseDatabaseStmt(pCxt, &yymsp[0].minor.yy129);} break; - case 15: /* cmd ::= SHOW VNODES */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, 0, 0); } + case 17: /* not_exists_opt ::= IF NOT EXISTS */ +{ yymsp[-2].minor.yy185 = true; } break; - case 16: /* cmd ::= SHOW VNODES ids */ -{ setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, &yymsp[0].minor.yy0, 0); } + case 18: /* not_exists_opt ::= */ + case 20: /* exists_opt ::= */ yytestcase(yyruleno==20); + case 176: /* set_quantifier_opt ::= */ yytestcase(yyruleno==176); +{ yymsp[1].minor.yy185 = false; } break; - case 17: /* dbPrefix ::= */ -{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.type = 0;} + case 19: /* exists_opt ::= IF EXISTS */ +{ yymsp[-1].minor.yy185 = true; } break; - case 18: /* dbPrefix ::= ids DOT */ -{yylhsminor.yy0 = yymsp[-1].minor.yy0; } - yymsp[-1].minor.yy0 = yylhsminor.yy0; + case 21: /* db_options ::= */ +{ yymsp[1].minor.yy391 = createDefaultDatabaseOptions(pCxt); } break; - case 19: /* cpxName ::= */ -{yymsp[1].minor.yy0.n = 0; } + case 22: /* db_options ::= db_options BLOCKS NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_BLOCKS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 20: /* cpxName ::= DOT ids */ -{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n += 1; } + case 23: /* db_options ::= db_options CACHE NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_CACHE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 21: /* cmd ::= SHOW CREATE TABLE ids cpxName */ -{ - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_TABLE, 1, &yymsp[-1].minor.yy0); -} + case 24: /* db_options ::= db_options CACHELAST NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_CACHELAST, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 22: /* cmd ::= SHOW CREATE STABLE ids cpxName */ -{ - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_STABLE, 1, &yymsp[-1].minor.yy0); -} + case 25: /* db_options ::= db_options COMP NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_COMP, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 23: /* cmd ::= SHOW CREATE DATABASE ids */ -{ - setDCLSqlElems(pInfo, TSDB_SQL_SHOW_CREATE_DATABASE, 1, &yymsp[0].minor.yy0); -} + case 26: /* db_options ::= db_options DAYS NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_DAYS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 24: /* cmd ::= SHOW dbPrefix TABLES */ -{ - setShowOptions(pInfo, TSDB_MGMT_TABLE_TABLE, &yymsp[-1].minor.yy0, 0); -} + case 27: /* db_options ::= db_options FSYNC NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_FSYNC, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 25: /* cmd ::= SHOW dbPrefix TABLES LIKE ids */ -{ - setShowOptions(pInfo, TSDB_MGMT_TABLE_TABLE, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); -} + case 28: /* db_options ::= db_options MAXROWS NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_MAXROWS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 26: /* cmd ::= SHOW dbPrefix STABLES */ -{ - setShowOptions(pInfo, TSDB_MGMT_TABLE_STB, &yymsp[-1].minor.yy0, 0); -} + case 29: /* db_options ::= db_options MINROWS NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_MINROWS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 27: /* cmd ::= SHOW dbPrefix STABLES LIKE ids */ -{ - SToken token; - tSetDbName(&token, &yymsp[-3].minor.yy0); - setShowOptions(pInfo, TSDB_MGMT_TABLE_STB, &token, &yymsp[0].minor.yy0); -} + case 30: /* db_options ::= db_options KEEP NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_KEEP, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 28: /* cmd ::= SHOW dbPrefix VGROUPS */ -{ - SToken token; - tSetDbName(&token, &yymsp[-1].minor.yy0); - setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, 0); -} + case 31: /* db_options ::= db_options PRECISION NK_STRING */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_PRECISION, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 29: /* cmd ::= SHOW dbPrefix VGROUPS ids */ -{ - SToken token; - tSetDbName(&token, &yymsp[-2].minor.yy0); - setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, &yymsp[0].minor.yy0); -} + case 32: /* db_options ::= db_options QUORUM NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_QUORUM, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 30: /* cmd ::= DROP TABLE ifexists ids cpxName */ -{ - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDropDbTableInfo(pInfo, TSDB_SQL_DROP_TABLE, &yymsp[-1].minor.yy0, &yymsp[-2].minor.yy0, -1, -1); -} + case 33: /* db_options ::= db_options REPLICA NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_REPLICA, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 31: /* cmd ::= DROP STABLE ifexists ids cpxName */ -{ - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDropDbTableInfo(pInfo, TSDB_SQL_DROP_TABLE, &yymsp[-1].minor.yy0, &yymsp[-2].minor.yy0, -1, TSDB_SUPER_TABLE); -} + case 34: /* db_options ::= db_options TTL NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_TTL, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 32: /* cmd ::= DROP DATABASE ifexists ids */ -{ setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &yymsp[0].minor.yy0, &yymsp[-1].minor.yy0, TSDB_DB_TYPE_DEFAULT, -1); } + case 35: /* db_options ::= db_options WAL NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_WAL, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 33: /* cmd ::= DROP TOPIC ifexists ids */ -{ setDropDbTableInfo(pInfo, TSDB_SQL_DROP_DB, &yymsp[0].minor.yy0, &yymsp[-1].minor.yy0, TSDB_DB_TYPE_TOPIC, -1); } + case 36: /* db_options ::= db_options VGROUPS NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_VGROUPS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 34: /* cmd ::= DROP FUNCTION ids */ -{ setDropFuncInfo(pInfo, TSDB_SQL_DROP_FUNCTION, &yymsp[0].minor.yy0); } + case 37: /* db_options ::= db_options SINGLE_STABLE NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_SINGLESTABLE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 35: /* cmd ::= DROP DNODE ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_DROP_DNODE, 1, &yymsp[0].minor.yy0); } + case 38: /* db_options ::= db_options STREAM_MODE NK_INTEGER */ +{ yylhsminor.yy391 = setDatabaseOption(pCxt, yymsp[-2].minor.yy391, DB_OPTION_STREAMMODE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 36: /* cmd ::= DROP USER ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_DROP_USER, 1, &yymsp[0].minor.yy0); } + case 39: /* cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */ + case 41: /* cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */ yytestcase(yyruleno==41); +{ pCxt->pRootNode = createCreateTableStmt(pCxt, yymsp[-6].minor.yy185, yymsp[-5].minor.yy256, yymsp[-3].minor.yy46, yymsp[-1].minor.yy46, yymsp[0].minor.yy340);} break; - case 37: /* cmd ::= DROP ACCOUNT ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_DROP_ACCT, 1, &yymsp[0].minor.yy0); } + case 40: /* cmd ::= CREATE TABLE multi_create_clause */ +{ pCxt->pRootNode = createCreateMultiTableStmt(pCxt, yymsp[0].minor.yy46);} break; - case 38: /* cmd ::= USE ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_USE_DB, 1, &yymsp[0].minor.yy0);} + case 42: /* cmd ::= DROP TABLE multi_drop_clause */ +{ pCxt->pRootNode = createDropTableStmt(pCxt, yymsp[0].minor.yy46); } break; - case 39: /* cmd ::= DESCRIBE ids cpxName */ - case 40: /* cmd ::= DESC ids cpxName */ yytestcase(yyruleno==40); -{ - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &yymsp[-1].minor.yy0); -} + case 43: /* cmd ::= DROP STABLE exists_opt full_table_name */ +{ pCxt->pRootNode = createDropSuperTableStmt(pCxt, yymsp[-1].minor.yy185, yymsp[0].minor.yy256); } break; - case 41: /* cmd ::= ALTER USER ids PASS ids */ -{ setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, NULL); } + case 44: /* cmd ::= SHOW TABLES */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TABLES_STMT, NULL); } break; - case 42: /* cmd ::= ALTER USER ids PRIVILEGE ids */ -{ setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &yymsp[-2].minor.yy0, NULL, &yymsp[0].minor.yy0);} + case 45: /* cmd ::= SHOW STABLES */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STABLES_STMT, NULL); } break; - case 43: /* cmd ::= ALTER DNODE ids ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } + case 46: /* multi_create_clause ::= create_subtable_clause */ + case 49: /* multi_drop_clause ::= drop_table_clause */ yytestcase(yyruleno==49); + case 56: /* column_def_list ::= column_def */ yytestcase(yyruleno==56); + case 91: /* col_name_list ::= col_name */ yytestcase(yyruleno==91); + case 181: /* select_sublist ::= select_item */ yytestcase(yyruleno==181); + case 228: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==228); +{ yylhsminor.yy46 = createNodeList(pCxt, yymsp[0].minor.yy256); } + yymsp[0].minor.yy46 = yylhsminor.yy46; break; - case 44: /* cmd ::= ALTER DNODE ids ids ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 3, &yymsp[-2].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } + case 47: /* multi_create_clause ::= multi_create_clause create_subtable_clause */ + case 50: /* multi_drop_clause ::= multi_drop_clause drop_table_clause */ yytestcase(yyruleno==50); +{ yylhsminor.yy46 = addNodeToList(pCxt, yymsp[-1].minor.yy46, yymsp[0].minor.yy256); } + yymsp[-1].minor.yy46 = yylhsminor.yy46; break; - case 45: /* cmd ::= ALTER LOCAL ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &yymsp[0].minor.yy0); } + case 48: /* create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_tags_opt TAGS NK_LP literal_list NK_RP */ +{ yylhsminor.yy256 = createCreateSubTableClause(pCxt, yymsp[-8].minor.yy185, yymsp[-7].minor.yy256, yymsp[-5].minor.yy256, yymsp[-4].minor.yy46, yymsp[-1].minor.yy46); } + yymsp[-8].minor.yy256 = yylhsminor.yy256; break; - case 46: /* cmd ::= ALTER LOCAL ids ids */ -{ setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } + case 51: /* drop_table_clause ::= exists_opt full_table_name */ +{ yylhsminor.yy256 = createDropTableClause(pCxt, yymsp[-1].minor.yy185, yymsp[0].minor.yy256); } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 47: /* cmd ::= ALTER DATABASE ids alter_db_optr */ -{ SToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy42, &t);} + case 52: /* specific_tags_opt ::= */ + case 83: /* tags_def_opt ::= */ yytestcase(yyruleno==83); + case 189: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==189); + case 206: /* group_by_clause_opt ::= */ yytestcase(yyruleno==206); + case 216: /* order_by_clause_opt ::= */ yytestcase(yyruleno==216); +{ yymsp[1].minor.yy46 = NULL; } + break; + case 53: /* specific_tags_opt ::= NK_LP col_name_list NK_RP */ +{ yymsp[-2].minor.yy46 = yymsp[-1].minor.yy46; } + break; + case 54: /* full_table_name ::= table_name */ +{ yylhsminor.yy256 = createRealTableNode(pCxt, NULL, &yymsp[0].minor.yy129, NULL); } + yymsp[0].minor.yy256 = yylhsminor.yy256; + break; + case 55: /* full_table_name ::= db_name NK_DOT table_name */ +{ yylhsminor.yy256 = createRealTableNode(pCxt, &yymsp[-2].minor.yy129, &yymsp[0].minor.yy129, NULL); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; + break; + case 57: /* column_def_list ::= column_def_list NK_COMMA column_def */ + case 92: /* col_name_list ::= col_name_list NK_COMMA col_name */ yytestcase(yyruleno==92); + case 182: /* select_sublist ::= select_sublist NK_COMMA select_item */ yytestcase(yyruleno==182); + case 229: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==229); +{ yylhsminor.yy46 = addNodeToList(pCxt, yymsp[-2].minor.yy46, yymsp[0].minor.yy256); } + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; - case 48: /* cmd ::= ALTER ACCOUNT ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy341);} + case 58: /* column_def ::= column_name type_name */ +{ yylhsminor.yy256 = createColumnDefNode(pCxt, &yymsp[-1].minor.yy129, yymsp[0].minor.yy70, NULL); } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 49: /* cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy341);} + case 59: /* column_def ::= column_name type_name COMMENT NK_STRING */ +{ yylhsminor.yy256 = createColumnDefNode(pCxt, &yymsp[-3].minor.yy129, yymsp[-2].minor.yy70, &yymsp[0].minor.yy0); } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 50: /* cmd ::= COMPACT VNODES IN LP exprlist RP */ -{ setCompactVnodeSql(pInfo, TSDB_SQL_COMPACT_VNODE, yymsp[-1].minor.yy131);} + case 60: /* type_name ::= BOOL */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_BOOL); } break; - case 51: /* ids ::= ID */ -{yylhsminor.yy0 = yymsp[0].minor.yy0; } - yymsp[0].minor.yy0 = yylhsminor.yy0; + case 61: /* type_name ::= TINYINT */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_TINYINT); } break; - case 52: /* ifexists ::= IF EXISTS */ -{ yymsp[-1].minor.yy0.n = 1;} + case 62: /* type_name ::= SMALLINT */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_SMALLINT); } break; - case 53: /* ifexists ::= */ - case 55: /* ifnotexists ::= */ yytestcase(yyruleno==55); - case 191: /* distinct ::= */ yytestcase(yyruleno==191); -{ yymsp[1].minor.yy0.n = 0;} + case 63: /* type_name ::= INT */ + case 64: /* type_name ::= INTEGER */ yytestcase(yyruleno==64); +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_INT); } break; - case 54: /* ifnotexists ::= IF NOT EXISTS */ -{ yymsp[-2].minor.yy0.n = 1;} + case 65: /* type_name ::= BIGINT */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_BIGINT); } break; - case 56: /* cmd ::= CREATE DNODE ids PORT ids */ - case 57: /* cmd ::= CREATE DNODE IPTOKEN PORT ids */ yytestcase(yyruleno==57); -{ setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 2, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);} + case 66: /* type_name ::= FLOAT */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_FLOAT); } break; - case 58: /* cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ -{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy341);} + case 67: /* type_name ::= DOUBLE */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_DOUBLE); } break; - case 59: /* cmd ::= CREATE DATABASE ifnotexists ids db_optr */ -{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy42, &yymsp[-2].minor.yy0);} + case 68: /* type_name ::= BINARY NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy70 = createVarLenDataType(TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy0); } break; - case 60: /* cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ -{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy290, &yymsp[0].minor.yy0, 1);} + case 69: /* type_name ::= TIMESTAMP */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_TIMESTAMP); } break; - case 61: /* cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ -{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy290, &yymsp[0].minor.yy0, 2);} + case 70: /* type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy70 = createVarLenDataType(TSDB_DATA_TYPE_NCHAR, &yymsp[-1].minor.yy0); } break; - case 62: /* cmd ::= CREATE USER ids PASS ids */ -{ setCreateUserSql(pInfo, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);} + case 71: /* type_name ::= TINYINT UNSIGNED */ +{ yymsp[-1].minor.yy70 = createDataType(TSDB_DATA_TYPE_UTINYINT); } break; - case 63: /* bufsize ::= */ - case 65: /* pps ::= */ yytestcase(yyruleno==65); - case 67: /* tseries ::= */ yytestcase(yyruleno==67); - case 69: /* dbs ::= */ yytestcase(yyruleno==69); - case 71: /* streams ::= */ yytestcase(yyruleno==71); - case 73: /* storage ::= */ yytestcase(yyruleno==73); - case 75: /* qtime ::= */ yytestcase(yyruleno==75); - case 77: /* users ::= */ yytestcase(yyruleno==77); - case 79: /* conns ::= */ yytestcase(yyruleno==79); - case 81: /* state ::= */ yytestcase(yyruleno==81); -{ yymsp[1].minor.yy0.n = 0; } + case 72: /* type_name ::= SMALLINT UNSIGNED */ +{ yymsp[-1].minor.yy70 = createDataType(TSDB_DATA_TYPE_USMALLINT); } break; - case 64: /* bufsize ::= BUFSIZE INTEGER */ - case 66: /* pps ::= PPS INTEGER */ yytestcase(yyruleno==66); - case 68: /* tseries ::= TSERIES INTEGER */ yytestcase(yyruleno==68); - case 70: /* dbs ::= DBS INTEGER */ yytestcase(yyruleno==70); - case 72: /* streams ::= STREAMS INTEGER */ yytestcase(yyruleno==72); - case 74: /* storage ::= STORAGE INTEGER */ yytestcase(yyruleno==74); - case 76: /* qtime ::= QTIME INTEGER */ yytestcase(yyruleno==76); - case 78: /* users ::= USERS INTEGER */ yytestcase(yyruleno==78); - case 80: /* conns ::= CONNS INTEGER */ yytestcase(yyruleno==80); - case 82: /* state ::= STATE ids */ yytestcase(yyruleno==82); -{ yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } + case 73: /* type_name ::= INT UNSIGNED */ +{ yymsp[-1].minor.yy70 = createDataType(TSDB_DATA_TYPE_UINT); } break; - case 83: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ -{ - yylhsminor.yy341.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; - yylhsminor.yy341.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; - yylhsminor.yy341.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; - yylhsminor.yy341.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; - yylhsminor.yy341.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; - yylhsminor.yy341.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy341.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; - yylhsminor.yy341.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; - yylhsminor.yy341.stat = yymsp[0].minor.yy0; -} - yymsp[-8].minor.yy341 = yylhsminor.yy341; - break; - case 84: /* intitemlist ::= intitemlist COMMA intitem */ - case 164: /* tagitemlist ::= tagitemlist COMMA tagitem */ yytestcase(yyruleno==164); -{ yylhsminor.yy131 = tListItemAppend(yymsp[-2].minor.yy131, &yymsp[0].minor.yy43, -1); } - yymsp[-2].minor.yy131 = yylhsminor.yy131; - break; - case 85: /* intitemlist ::= intitem */ - case 165: /* tagitemlist ::= tagitem */ yytestcase(yyruleno==165); -{ yylhsminor.yy131 = tListItemAppend(NULL, &yymsp[0].minor.yy43, -1); } - yymsp[0].minor.yy131 = yylhsminor.yy131; - break; - case 86: /* intitem ::= INTEGER */ - case 166: /* tagitem ::= INTEGER */ yytestcase(yyruleno==166); - case 167: /* tagitem ::= FLOAT */ yytestcase(yyruleno==167); - case 168: /* tagitem ::= STRING */ yytestcase(yyruleno==168); - case 169: /* tagitem ::= BOOL */ yytestcase(yyruleno==169); -{ toTSDBType(yymsp[0].minor.yy0.type); taosVariantCreate(&yylhsminor.yy43, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.type); } - yymsp[0].minor.yy43 = yylhsminor.yy43; - break; - case 87: /* keep ::= KEEP intitemlist */ -{ yymsp[-1].minor.yy131 = yymsp[0].minor.yy131; } - break; - case 88: /* cache ::= CACHE INTEGER */ - case 89: /* replica ::= REPLICA INTEGER */ yytestcase(yyruleno==89); - case 90: /* quorum ::= QUORUM INTEGER */ yytestcase(yyruleno==90); - case 91: /* days ::= DAYS INTEGER */ yytestcase(yyruleno==91); - case 92: /* minrows ::= MINROWS INTEGER */ yytestcase(yyruleno==92); - case 93: /* maxrows ::= MAXROWS INTEGER */ yytestcase(yyruleno==93); - case 94: /* blocks ::= BLOCKS INTEGER */ yytestcase(yyruleno==94); - case 95: /* ctime ::= CTIME INTEGER */ yytestcase(yyruleno==95); - case 96: /* wal ::= WAL INTEGER */ yytestcase(yyruleno==96); - case 97: /* fsync ::= FSYNC INTEGER */ yytestcase(yyruleno==97); - case 98: /* comp ::= COMP INTEGER */ yytestcase(yyruleno==98); - case 99: /* prec ::= PRECISION STRING */ yytestcase(yyruleno==99); - case 100: /* update ::= UPDATE INTEGER */ yytestcase(yyruleno==100); - case 101: /* cachelast ::= CACHELAST INTEGER */ yytestcase(yyruleno==101); - case 102: /* vgroups ::= VGROUPS INTEGER */ yytestcase(yyruleno==102); -{ yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } - break; - case 103: /* stream_mode ::= STREAM MODE INTEGER */ -{ yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; } - break; - case 104: /* db_optr ::= */ -{setDefaultCreateDbOption(&yymsp[1].minor.yy42);} - break; - case 105: /* db_optr ::= db_optr cache */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 106: /* db_optr ::= db_optr replica */ - case 123: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==123); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 107: /* db_optr ::= db_optr quorum */ - case 124: /* alter_db_optr ::= alter_db_optr quorum */ yytestcase(yyruleno==124); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 108: /* db_optr ::= db_optr days */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 109: /* db_optr ::= db_optr minrows */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 110: /* db_optr ::= db_optr maxrows */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 111: /* db_optr ::= db_optr blocks */ - case 126: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==126); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 112: /* db_optr ::= db_optr ctime */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 113: /* db_optr ::= db_optr wal */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 114: /* db_optr ::= db_optr fsync */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 115: /* db_optr ::= db_optr comp */ - case 127: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==127); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 116: /* db_optr ::= db_optr prec */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.precision = yymsp[0].minor.yy0; } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 117: /* db_optr ::= db_optr keep */ - case 125: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==125); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.keep = yymsp[0].minor.yy131; } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 118: /* db_optr ::= db_optr update */ - case 128: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==128); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 119: /* db_optr ::= db_optr cachelast */ - case 129: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==129); -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 120: /* db_optr ::= db_optr vgroups */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.numOfVgroups = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 121: /* db_optr ::= db_optr stream_mode */ -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.streamMode = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[-1].minor.yy42 = yylhsminor.yy42; - break; - case 122: /* alter_db_optr ::= */ -{ setDefaultCreateDbOption(&yymsp[1].minor.yy42);} - break; - case 130: /* typename ::= ids */ -{ - yymsp[0].minor.yy0.type = 0; - tSetColumnType (&yylhsminor.yy290, &yymsp[0].minor.yy0); -} - yymsp[0].minor.yy290 = yylhsminor.yy290; + case 74: /* type_name ::= BIGINT UNSIGNED */ +{ yymsp[-1].minor.yy70 = createDataType(TSDB_DATA_TYPE_UBIGINT); } break; - case 131: /* typename ::= ids LP signed RP */ -{ - if (yymsp[-1].minor.yy459 <= 0) { - yymsp[-3].minor.yy0.type = 0; - tSetColumnType(&yylhsminor.yy290, &yymsp[-3].minor.yy0); - } else { - yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy459; // negative value of name length - tSetColumnType(&yylhsminor.yy290, &yymsp[-3].minor.yy0); - } -} - yymsp[-3].minor.yy290 = yylhsminor.yy290; + case 75: /* type_name ::= JSON */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_JSON); } break; - case 132: /* typename ::= ids UNSIGNED */ -{ - yymsp[-1].minor.yy0.type = 0; - yymsp[-1].minor.yy0.n = ((yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z); - tSetColumnType (&yylhsminor.yy290, &yymsp[-1].minor.yy0); -} - yymsp[-1].minor.yy290 = yylhsminor.yy290; + case 76: /* type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy70 = createVarLenDataType(TSDB_DATA_TYPE_VARCHAR, &yymsp[-1].minor.yy0); } break; - case 133: /* signed ::= INTEGER */ -{ yylhsminor.yy459 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } - yymsp[0].minor.yy459 = yylhsminor.yy459; + case 77: /* type_name ::= MEDIUMBLOB */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); } break; - case 134: /* signed ::= PLUS INTEGER */ -{ yymsp[-1].minor.yy459 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } + case 78: /* type_name ::= BLOB */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_BLOB); } break; - case 135: /* signed ::= MINUS INTEGER */ -{ yymsp[-1].minor.yy459 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} + case 79: /* type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy70 = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &yymsp[-1].minor.yy0); } break; - case 139: /* cmd ::= CREATE TABLE create_table_list */ -{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy272;} + case 80: /* type_name ::= DECIMAL */ +{ yymsp[0].minor.yy70 = createDataType(TSDB_DATA_TYPE_DECIMAL); } break; - case 140: /* create_table_list ::= create_from_stable */ -{ - SCreateTableSql* pCreateTable = calloc(1, sizeof(SCreateTableSql)); - pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); - - taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy96); - pCreateTable->type = TSDB_SQL_CREATE_TABLE; - yylhsminor.yy272 = pCreateTable; -} - yymsp[0].minor.yy272 = yylhsminor.yy272; + case 81: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy70 = createDataType(TSDB_DATA_TYPE_DECIMAL); } break; - case 141: /* create_table_list ::= create_table_list create_from_stable */ -{ - taosArrayPush(yymsp[-1].minor.yy272->childTableInfo, &yymsp[0].minor.yy96); - yylhsminor.yy272 = yymsp[-1].minor.yy272; -} - yymsp[-1].minor.yy272 = yylhsminor.yy272; + case 82: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */ +{ yymsp[-5].minor.yy70 = createDataType(TSDB_DATA_TYPE_DECIMAL); } break; - case 142: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ -{ - yylhsminor.yy272 = tSetCreateTableInfo(yymsp[-1].minor.yy131, NULL, NULL, TSDB_SQL_CREATE_TABLE); - setSqlInfo(pInfo, yylhsminor.yy272, NULL, TSDB_SQL_CREATE_TABLE); - - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - setCreatedTableName(pInfo, &yymsp[-4].minor.yy0, &yymsp[-5].minor.yy0); -} - yymsp[-5].minor.yy272 = yylhsminor.yy272; + case 84: /* tags_def_opt ::= tags_def */ + case 180: /* select_list ::= select_sublist */ yytestcase(yyruleno==180); +{ yylhsminor.yy46 = yymsp[0].minor.yy46; } + yymsp[0].minor.yy46 = yylhsminor.yy46; break; - case 143: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ -{ - yylhsminor.yy272 = tSetCreateTableInfo(yymsp[-5].minor.yy131, yymsp[-1].minor.yy131, NULL, TSDB_SQL_CREATE_STABLE); - setSqlInfo(pInfo, yylhsminor.yy272, NULL, TSDB_SQL_CREATE_STABLE); - - yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - setCreatedTableName(pInfo, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); -} - yymsp[-9].minor.yy272 = yylhsminor.yy272; + case 85: /* tags_def ::= TAGS NK_LP column_def_list NK_RP */ +{ yymsp[-3].minor.yy46 = yymsp[-1].minor.yy46; } break; - case 144: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist1 RP */ -{ - yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; - yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - yylhsminor.yy96 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy131, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); -} - yymsp[-9].minor.yy96 = yylhsminor.yy96; + case 86: /* table_options ::= */ +{ yymsp[1].minor.yy340 = createDefaultTableOptions(pCxt);} break; - case 145: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist1 RP */ -{ - yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - yymsp[-11].minor.yy0.n += yymsp[-10].minor.yy0.n; - yylhsminor.yy96 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy131, yymsp[-1].minor.yy131, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); -} - yymsp[-12].minor.yy96 = yylhsminor.yy96; + case 87: /* table_options ::= table_options COMMENT NK_STRING */ +{ yylhsminor.yy340 = setTableOption(pCxt, yymsp[-2].minor.yy340, TABLE_OPTION_COMMENT, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy340 = yylhsminor.yy340; break; - case 146: /* tagNamelist ::= tagNamelist COMMA ids */ -{taosArrayPush(yymsp[-2].minor.yy131, &yymsp[0].minor.yy0); yylhsminor.yy131 = yymsp[-2].minor.yy131; } - yymsp[-2].minor.yy131 = yylhsminor.yy131; + case 88: /* table_options ::= table_options KEEP NK_INTEGER */ +{ yylhsminor.yy340 = setTableOption(pCxt, yymsp[-2].minor.yy340, TABLE_OPTION_KEEP, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy340 = yylhsminor.yy340; break; - case 147: /* tagNamelist ::= ids */ -{yylhsminor.yy131 = taosArrayInit(4, sizeof(SToken)); taosArrayPush(yylhsminor.yy131, &yymsp[0].minor.yy0);} - yymsp[0].minor.yy131 = yylhsminor.yy131; + case 89: /* table_options ::= table_options TTL NK_INTEGER */ +{ yylhsminor.yy340 = setTableOption(pCxt, yymsp[-2].minor.yy340, TABLE_OPTION_TTL, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy340 = yylhsminor.yy340; break; - case 148: /* create_table_args ::= ifnotexists ids cpxName AS select */ -{ -// yylhsminor.yy272 = tSetCreateTableInfo(NULL, NULL, yymsp[0].minor.yy256, TSQL_CREATE_STREAM); -// setSqlInfo(pInfo, yylhsminor.yy272, NULL, TSDB_SQL_CREATE_TABLE); -// -// yymsp[-3].minor.yy0.n += yymsp[-2].minor.yy0.n; -// setCreatedTableName(pInfo, &yymsp[-3].minor.yy0, &yymsp[-4].minor.yy0); -} - yymsp[-4].minor.yy272 = yylhsminor.yy272; + case 90: /* table_options ::= table_options SMA NK_LP col_name_list NK_RP */ +{ yylhsminor.yy340 = setTableSmaOption(pCxt, yymsp[-4].minor.yy340, yymsp[-1].minor.yy46); } + yymsp[-4].minor.yy340 = yylhsminor.yy340; break; - case 149: /* columnlist ::= columnlist COMMA column */ -{taosArrayPush(yymsp[-2].minor.yy131, &yymsp[0].minor.yy290); yylhsminor.yy131 = yymsp[-2].minor.yy131; } - yymsp[-2].minor.yy131 = yylhsminor.yy131; + case 93: /* col_name ::= column_name */ +{ yylhsminor.yy256 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy129); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 150: /* columnlist ::= column */ -{yylhsminor.yy131 = taosArrayInit(4, sizeof(SField)); taosArrayPush(yylhsminor.yy131, &yymsp[0].minor.yy290);} - yymsp[0].minor.yy131 = yylhsminor.yy131; + case 94: /* cmd ::= SHOW VGROUPS */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, NULL); } break; - case 151: /* column ::= ids typename */ -{ - tSetColumnInfo(&yylhsminor.yy290, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy290); -} - yymsp[-1].minor.yy290 = yylhsminor.yy290; - break; - case 152: /* tagitemlist1 ::= tagitemlist1 COMMA tagitem1 */ -{ taosArrayPush(yymsp[-2].minor.yy131, &yymsp[0].minor.yy0); yylhsminor.yy131 = yymsp[-2].minor.yy131;} - yymsp[-2].minor.yy131 = yylhsminor.yy131; - break; - case 153: /* tagitemlist1 ::= tagitem1 */ -{ yylhsminor.yy131 = taosArrayInit(4, sizeof(SToken)); taosArrayPush(yylhsminor.yy131, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy131 = yylhsminor.yy131; - break; - case 154: /* tagitem1 ::= MINUS INTEGER */ - case 155: /* tagitem1 ::= MINUS FLOAT */ yytestcase(yyruleno==155); - case 156: /* tagitem1 ::= PLUS INTEGER */ yytestcase(yyruleno==156); - case 157: /* tagitem1 ::= PLUS FLOAT */ yytestcase(yyruleno==157); -{ yylhsminor.yy0.n = yymsp[-1].minor.yy0.n + yymsp[0].minor.yy0.n; yylhsminor.yy0.type = yymsp[0].minor.yy0.type; yylhsminor.yy0.z = yymsp[-1].minor.yy0.z;} - yymsp[-1].minor.yy0 = yylhsminor.yy0; - break; - case 158: /* tagitem1 ::= INTEGER */ - case 159: /* tagitem1 ::= FLOAT */ yytestcase(yyruleno==159); - case 160: /* tagitem1 ::= STRING */ yytestcase(yyruleno==160); - case 161: /* tagitem1 ::= BOOL */ yytestcase(yyruleno==161); - case 162: /* tagitem1 ::= NULL */ yytestcase(yyruleno==162); - case 163: /* tagitem1 ::= NOW */ yytestcase(yyruleno==163); -{ yylhsminor.yy0 = yymsp[0].minor.yy0; } - yymsp[0].minor.yy0 = yylhsminor.yy0; - break; - case 170: /* tagitem ::= NULL */ -{ yymsp[0].minor.yy0.type = 0; taosVariantCreate(&yylhsminor.yy43, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.type); } - yymsp[0].minor.yy43 = yylhsminor.yy43; - break; - case 171: /* tagitem ::= NOW */ -{ yymsp[0].minor.yy0.type = TSDB_DATA_TYPE_TIMESTAMP; taosVariantCreate(&yylhsminor.yy43, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.type);} - yymsp[0].minor.yy43 = yylhsminor.yy43; - break; - case 172: /* tagitem ::= MINUS INTEGER */ - case 173: /* tagitem ::= MINUS FLOAT */ yytestcase(yyruleno==173); - case 174: /* tagitem ::= PLUS INTEGER */ yytestcase(yyruleno==174); - case 175: /* tagitem ::= PLUS FLOAT */ yytestcase(yyruleno==175); -{ - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yymsp[-1].minor.yy0.type = yymsp[0].minor.yy0.type; - toTSDBType(yymsp[-1].minor.yy0.type); - taosVariantCreate(&yylhsminor.yy43, yymsp[-1].minor.yy0.z, yymsp[-1].minor.yy0.n, yymsp[-1].minor.yy0.type); -} - yymsp[-1].minor.yy43 = yylhsminor.yy43; + case 95: /* cmd ::= SHOW db_name NK_DOT VGROUPS */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, &yymsp[-2].minor.yy129); } break; - case 176: /* select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ -{ - yylhsminor.yy256 = tSetQuerySqlNode(&yymsp[-13].minor.yy0, yymsp[-12].minor.yy131, yymsp[-11].minor.yy544, yymsp[-10].minor.yy46, yymsp[-4].minor.yy131, yymsp[-2].minor.yy131, &yymsp[-9].minor.yy530, &yymsp[-7].minor.yy39, &yymsp[-6].minor.yy538, &yymsp[-8].minor.yy0, yymsp[-5].minor.yy131, &yymsp[0].minor.yy55, &yymsp[-1].minor.yy55, yymsp[-3].minor.yy46); -} - yymsp[-13].minor.yy256 = yylhsminor.yy256; + case 96: /* cmd ::= SHOW MNODES */ +{ pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MNODES_STMT, NULL); } break; - case 177: /* select ::= LP select RP */ -{yymsp[-2].minor.yy256 = yymsp[-1].minor.yy256;} + case 97: /* cmd ::= query_expression */ +{ pCxt->pRootNode = yymsp[0].minor.yy256; } break; - case 178: /* union ::= select */ -{ yylhsminor.yy303 = setSubclause(NULL, yymsp[0].minor.yy256); } - yymsp[0].minor.yy303 = yylhsminor.yy303; + case 98: /* literal ::= NK_INTEGER */ +{ yylhsminor.yy256 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 179: /* union ::= union UNION ALL select */ -{ yylhsminor.yy303 = appendSelectClause(yymsp[-3].minor.yy303, SQL_TYPE_UNIONALL, yymsp[0].minor.yy256); } - yymsp[-3].minor.yy303 = yylhsminor.yy303; + case 99: /* literal ::= NK_FLOAT */ +{ yylhsminor.yy256 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 180: /* union ::= union UNION select */ -{ yylhsminor.yy303 = appendSelectClause(yymsp[-2].minor.yy303, SQL_TYPE_UNION, yymsp[0].minor.yy256); } - yymsp[-2].minor.yy303 = yylhsminor.yy303; + case 100: /* literal ::= NK_STRING */ +{ yylhsminor.yy256 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 181: /* cmd ::= union */ -{ setSqlInfo(pInfo, yymsp[0].minor.yy303, NULL, TSDB_SQL_SELECT); } + case 101: /* literal ::= NK_BOOL */ +{ yylhsminor.yy256 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 182: /* select ::= SELECT selcollist */ -{ - yylhsminor.yy256 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy131, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); -} + case 102: /* literal ::= TIMESTAMP NK_STRING */ +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0)); } yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 183: /* sclp ::= selcollist COMMA */ -{yylhsminor.yy131 = yymsp[-1].minor.yy131;} - yymsp[-1].minor.yy131 = yylhsminor.yy131; - break; - case 184: /* sclp ::= */ - case 216: /* orderby_opt ::= */ yytestcase(yyruleno==216); -{yymsp[1].minor.yy131 = 0;} - break; - case 185: /* selcollist ::= sclp distinct expr as */ -{ - yylhsminor.yy131 = tSqlExprListAppend(yymsp[-3].minor.yy131, yymsp[-1].minor.yy46, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); -} - yymsp[-3].minor.yy131 = yylhsminor.yy131; - break; - case 186: /* selcollist ::= sclp STAR */ -{ - tSqlExpr *pNode = tSqlExprCreateIdValue(NULL, TK_ALL); - yylhsminor.yy131 = tSqlExprListAppend(yymsp[-1].minor.yy131, pNode, 0, 0); -} - yymsp[-1].minor.yy131 = yylhsminor.yy131; - break; - case 187: /* as ::= AS ids */ -{ yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } - break; - case 188: /* as ::= ids */ -{ yylhsminor.yy0 = yymsp[0].minor.yy0; } - yymsp[0].minor.yy0 = yylhsminor.yy0; - break; - case 189: /* as ::= */ -{ yymsp[1].minor.yy0.n = 0; } - break; - case 190: /* distinct ::= DISTINCT */ -{ yylhsminor.yy0 = yymsp[0].minor.yy0; } - yymsp[0].minor.yy0 = yylhsminor.yy0; + case 103: /* literal ::= duration_literal */ + case 114: /* expression ::= literal */ yytestcase(yyruleno==114); + case 115: /* expression ::= column_reference */ yytestcase(yyruleno==115); + case 118: /* expression ::= subquery */ yytestcase(yyruleno==118); + case 150: /* boolean_value_expression ::= boolean_primary */ yytestcase(yyruleno==150); + case 154: /* boolean_primary ::= predicate */ yytestcase(yyruleno==154); + case 156: /* common_expression ::= expression */ yytestcase(yyruleno==156); + case 157: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==157); + case 159: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==159); + case 161: /* table_reference ::= table_primary */ yytestcase(yyruleno==161); + case 162: /* table_reference ::= joined_table */ yytestcase(yyruleno==162); + case 166: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==166); + case 213: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==213); + case 215: /* query_primary ::= query_specification */ yytestcase(yyruleno==215); +{ yylhsminor.yy256 = yymsp[0].minor.yy256; } + yymsp[0].minor.yy256 = yylhsminor.yy256; + break; + case 104: /* duration_literal ::= NK_VARIABLE */ +{ yylhsminor.yy256 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy256 = yylhsminor.yy256; + break; + case 105: /* literal_list ::= literal */ + case 127: /* expression_list ::= expression */ yytestcase(yyruleno==127); +{ yylhsminor.yy46 = createNodeList(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy256)); } + yymsp[0].minor.yy46 = yylhsminor.yy46; break; - case 192: /* from ::= FROM tablelist */ - case 193: /* from ::= FROM sub */ yytestcase(yyruleno==193); -{yymsp[-1].minor.yy544 = yymsp[0].minor.yy544;} + case 106: /* literal_list ::= literal_list NK_COMMA literal */ + case 128: /* expression_list ::= expression_list NK_COMMA expression */ yytestcase(yyruleno==128); +{ yylhsminor.yy46 = addNodeToList(pCxt, yymsp[-2].minor.yy46, releaseRawExprNode(pCxt, yymsp[0].minor.yy256)); } + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; - case 194: /* sub ::= LP union RP */ -{yymsp[-2].minor.yy544 = addSubquery(NULL, yymsp[-1].minor.yy303, NULL);} + case 116: /* expression ::= function_name NK_LP expression_list NK_RP */ +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy129, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy129, yymsp[-1].minor.yy46)); } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 195: /* sub ::= LP union RP ids */ -{yymsp[-3].minor.yy544 = addSubquery(NULL, yymsp[-2].minor.yy303, &yymsp[0].minor.yy0);} + case 117: /* expression ::= function_name NK_LP NK_STAR NK_RP */ +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy129, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy129, createNodeList(pCxt, createColumnNode(pCxt, NULL, &yymsp[-1].minor.yy0)))); } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 196: /* sub ::= sub COMMA LP union RP ids */ -{yylhsminor.yy544 = addSubquery(yymsp[-5].minor.yy544, yymsp[-2].minor.yy303, &yymsp[0].minor.yy0);} - yymsp[-5].minor.yy544 = yylhsminor.yy544; + case 119: /* expression ::= NK_LP expression NK_RP */ + case 155: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==155); +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, releaseRawExprNode(pCxt, yymsp[-1].minor.yy256)); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 197: /* tablelist ::= ids cpxName */ + case 120: /* expression ::= NK_PLUS expression */ { - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(NULL, &yymsp[-1].minor.yy0, NULL); -} - yymsp[-1].minor.yy544 = yylhsminor.yy544; + SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, releaseRawExprNode(pCxt, yymsp[0].minor.yy256)); + } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 198: /* tablelist ::= ids cpxName ids */ + case 121: /* expression ::= NK_MINUS expression */ { - yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(NULL, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); -} - yymsp[-2].minor.yy544 = yylhsminor.yy544; + SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[0].minor.yy256), NULL)); + } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 199: /* tablelist ::= tablelist COMMA ids cpxName */ + case 122: /* expression ::= expression NK_PLUS expression */ { - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(yymsp[-3].minor.yy544, &yymsp[-1].minor.yy0, NULL); -} - yymsp[-3].minor.yy544 = yylhsminor.yy544; + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 200: /* tablelist ::= tablelist COMMA ids cpxName ids */ + case 123: /* expression ::= expression NK_MINUS expression */ { - yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(yymsp[-4].minor.yy544, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); -} - yymsp[-4].minor.yy544 = yylhsminor.yy544; - break; - case 201: /* tmvar ::= VARIABLE */ -{yylhsminor.yy0 = yymsp[0].minor.yy0;} - yymsp[0].minor.yy0 = yylhsminor.yy0; - break; - case 202: /* interval_option ::= intervalKey LP tmvar RP */ -{yylhsminor.yy530.interval = yymsp[-1].minor.yy0; yylhsminor.yy530.offset.n = 0; yylhsminor.yy530.token = yymsp[-3].minor.yy310;} - yymsp[-3].minor.yy530 = yylhsminor.yy530; - break; - case 203: /* interval_option ::= intervalKey LP tmvar COMMA tmvar RP */ -{yylhsminor.yy530.interval = yymsp[-3].minor.yy0; yylhsminor.yy530.offset = yymsp[-1].minor.yy0; yylhsminor.yy530.token = yymsp[-5].minor.yy310;} - yymsp[-5].minor.yy530 = yylhsminor.yy530; - break; - case 204: /* interval_option ::= */ -{memset(&yymsp[1].minor.yy530, 0, sizeof(yymsp[1].minor.yy530));} - break; - case 205: /* intervalKey ::= INTERVAL */ -{yymsp[0].minor.yy310 = TK_INTERVAL;} - break; - case 206: /* intervalKey ::= EVERY */ -{yymsp[0].minor.yy310 = TK_EVERY; } - break; - case 207: /* session_option ::= */ -{yymsp[1].minor.yy39.col.n = 0; yymsp[1].minor.yy39.gap.n = 0;} + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 208: /* session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + case 124: /* expression ::= expression NK_STAR expression */ { - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - yymsp[-6].minor.yy39.col = yymsp[-4].minor.yy0; - yymsp[-6].minor.yy39.gap = yymsp[-1].minor.yy0; -} - break; - case 209: /* windowstate_option ::= */ -{ yymsp[1].minor.yy538.col.n = 0; yymsp[1].minor.yy538.col.z = NULL;} - break; - case 210: /* windowstate_option ::= STATE_WINDOW LP ids RP */ -{ yymsp[-3].minor.yy538.col = yymsp[-1].minor.yy0; } - break; - case 211: /* fill_opt ::= */ -{ yymsp[1].minor.yy131 = 0; } + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 212: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + case 125: /* expression ::= expression NK_SLASH expression */ { - SVariant A = {0}; - toTSDBType(yymsp[-3].minor.yy0.type); - taosVariantCreate(&A, yymsp[-3].minor.yy0.z, yymsp[-3].minor.yy0.n, yymsp[-3].minor.yy0.type); - - tListItemInsert(yymsp[-1].minor.yy131, &A, -1, 0); - yymsp[-5].minor.yy131 = yymsp[-1].minor.yy131; -} + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 213: /* fill_opt ::= FILL LP ID RP */ + case 126: /* expression ::= expression NK_REM expression */ { - toTSDBType(yymsp[-1].minor.yy0.type); - yymsp[-3].minor.yy131 = tListItemAppendToken(NULL, &yymsp[-1].minor.yy0, -1); -} + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MOD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 214: /* sliding_opt ::= SLIDING LP tmvar RP */ -{yymsp[-3].minor.yy0 = yymsp[-1].minor.yy0; } + case 129: /* column_reference ::= column_name */ +{ yylhsminor.yy256 = createRawExprNode(pCxt, &yymsp[0].minor.yy129, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy129)); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 215: /* sliding_opt ::= */ -{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = NULL; yymsp[1].minor.yy0.type = 0; } + case 130: /* column_reference ::= table_name NK_DOT column_name */ +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy129, &yymsp[0].minor.yy129, createColumnNode(pCxt, &yymsp[-2].minor.yy129, &yymsp[0].minor.yy129)); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 217: /* orderby_opt ::= ORDER BY sortlist */ -{yymsp[-2].minor.yy131 = yymsp[0].minor.yy131;} - break; - case 218: /* sortlist ::= sortlist COMMA item sortorder */ + case 131: /* predicate ::= expression compare_op expression */ + case 136: /* predicate ::= expression in_op in_predicate_value */ yytestcase(yyruleno==136); { - yylhsminor.yy131 = tListItemAppend(yymsp[-3].minor.yy131, &yymsp[-1].minor.yy43, yymsp[0].minor.yy44); -} - yymsp[-3].minor.yy131 = yylhsminor.yy131; + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, yymsp[-1].minor.yy326, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 219: /* sortlist ::= item sortorder */ + case 132: /* predicate ::= expression BETWEEN expression AND expression */ { - yylhsminor.yy131 = tListItemAppend(NULL, &yymsp[-1].minor.yy43, yymsp[0].minor.yy44); -} - yymsp[-1].minor.yy131 = yylhsminor.yy131; + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-4].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-4].minor.yy256), releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-4].minor.yy256 = yylhsminor.yy256; break; - case 220: /* item ::= ids cpxName */ + case 133: /* predicate ::= expression NOT BETWEEN expression AND expression */ { - toTSDBType(yymsp[-1].minor.yy0.type); - yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - - taosVariantCreate(&yylhsminor.yy43, yymsp[-1].minor.yy0.z, yymsp[-1].minor.yy0.n, yymsp[-1].minor.yy0.type); -} - yymsp[-1].minor.yy43 = yylhsminor.yy43; - break; - case 221: /* sortorder ::= ASC */ -{ yymsp[0].minor.yy44 = TSDB_ORDER_ASC; } - break; - case 222: /* sortorder ::= DESC */ -{ yymsp[0].minor.yy44 = TSDB_ORDER_DESC;} - break; - case 223: /* sortorder ::= */ -{ yymsp[1].minor.yy44 = TSDB_ORDER_ASC; } + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-5].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[-5].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-5].minor.yy256 = yylhsminor.yy256; break; - case 224: /* groupby_opt ::= */ -{ yymsp[1].minor.yy131 = 0;} - break; - case 225: /* groupby_opt ::= GROUP BY grouplist */ -{ yymsp[-2].minor.yy131 = yymsp[0].minor.yy131;} - break; - case 226: /* grouplist ::= grouplist COMMA item */ + case 134: /* predicate ::= expression IS NULL */ { - yylhsminor.yy131 = tListItemAppend(yymsp[-2].minor.yy131, &yymsp[0].minor.yy43, -1); -} - yymsp[-2].minor.yy131 = yylhsminor.yy131; + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), NULL)); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 227: /* grouplist ::= item */ + case 135: /* predicate ::= expression IS NOT NULL */ { - yylhsminor.yy131 = tListItemAppend(NULL, &yymsp[0].minor.yy43, -1); -} - yymsp[0].minor.yy131 = yylhsminor.yy131; + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy256), NULL)); + } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 228: /* having_opt ::= */ - case 238: /* where_opt ::= */ yytestcase(yyruleno==238); - case 282: /* expritem ::= */ yytestcase(yyruleno==282); -{yymsp[1].minor.yy46 = 0;} + case 137: /* compare_op ::= NK_LT */ +{ yymsp[0].minor.yy326 = OP_TYPE_LOWER_THAN; } break; - case 229: /* having_opt ::= HAVING expr */ - case 239: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==239); -{yymsp[-1].minor.yy46 = yymsp[0].minor.yy46;} + case 138: /* compare_op ::= NK_GT */ +{ yymsp[0].minor.yy326 = OP_TYPE_GREATER_THAN; } break; - case 230: /* limit_opt ::= */ - case 234: /* slimit_opt ::= */ yytestcase(yyruleno==234); -{yymsp[1].minor.yy55.limit = -1; yymsp[1].minor.yy55.offset = 0;} + case 139: /* compare_op ::= NK_LE */ +{ yymsp[0].minor.yy326 = OP_TYPE_LOWER_EQUAL; } break; - case 231: /* limit_opt ::= LIMIT signed */ - case 235: /* slimit_opt ::= SLIMIT signed */ yytestcase(yyruleno==235); -{yymsp[-1].minor.yy55.limit = yymsp[0].minor.yy459; yymsp[-1].minor.yy55.offset = 0;} + case 140: /* compare_op ::= NK_GE */ +{ yymsp[0].minor.yy326 = OP_TYPE_GREATER_EQUAL; } break; - case 232: /* limit_opt ::= LIMIT signed OFFSET signed */ -{ yymsp[-3].minor.yy55.limit = yymsp[-2].minor.yy459; yymsp[-3].minor.yy55.offset = yymsp[0].minor.yy459;} + case 141: /* compare_op ::= NK_NE */ +{ yymsp[0].minor.yy326 = OP_TYPE_NOT_EQUAL; } break; - case 233: /* limit_opt ::= LIMIT signed COMMA signed */ -{ yymsp[-3].minor.yy55.limit = yymsp[0].minor.yy459; yymsp[-3].minor.yy55.offset = yymsp[-2].minor.yy459;} + case 142: /* compare_op ::= NK_EQ */ +{ yymsp[0].minor.yy326 = OP_TYPE_EQUAL; } break; - case 236: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ -{yymsp[-3].minor.yy55.limit = yymsp[-2].minor.yy459; yymsp[-3].minor.yy55.offset = yymsp[0].minor.yy459;} + case 143: /* compare_op ::= LIKE */ +{ yymsp[0].minor.yy326 = OP_TYPE_LIKE; } break; - case 237: /* slimit_opt ::= SLIMIT signed COMMA signed */ -{yymsp[-3].minor.yy55.limit = yymsp[0].minor.yy459; yymsp[-3].minor.yy55.offset = yymsp[-2].minor.yy459;} + case 144: /* compare_op ::= NOT LIKE */ +{ yymsp[-1].minor.yy326 = OP_TYPE_NOT_LIKE; } break; - case 240: /* expr ::= LP expr RP */ -{yylhsminor.yy46 = yymsp[-1].minor.yy46; yylhsminor.yy46->exprToken.z = yymsp[-2].minor.yy0.z; yylhsminor.yy46->exprToken.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 145: /* compare_op ::= MATCH */ +{ yymsp[0].minor.yy326 = OP_TYPE_MATCH; } break; - case 241: /* expr ::= ID */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_ID);} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 146: /* compare_op ::= NMATCH */ +{ yymsp[0].minor.yy326 = OP_TYPE_NMATCH; } break; - case 242: /* expr ::= ID DOT ID */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ID);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 147: /* in_op ::= IN */ +{ yymsp[0].minor.yy326 = OP_TYPE_IN; } break; - case 243: /* expr ::= ID DOT STAR */ -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ALL);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 148: /* in_op ::= NOT IN */ +{ yymsp[-1].minor.yy326 = OP_TYPE_NOT_IN; } break; - case 244: /* expr ::= INTEGER */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_INTEGER);} - yymsp[0].minor.yy46 = yylhsminor.yy46; - break; - case 245: /* expr ::= MINUS INTEGER */ - case 246: /* expr ::= PLUS INTEGER */ yytestcase(yyruleno==246); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_INTEGER);} - yymsp[-1].minor.yy46 = yylhsminor.yy46; - break; - case 247: /* expr ::= FLOAT */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_FLOAT);} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 149: /* in_predicate_value ::= NK_LP expression_list NK_RP */ +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, createNodeListNode(pCxt, yymsp[-1].minor.yy46)); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 248: /* expr ::= MINUS FLOAT */ - case 249: /* expr ::= PLUS FLOAT */ yytestcase(yyruleno==249); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_FLOAT);} - yymsp[-1].minor.yy46 = yylhsminor.yy46; + case 151: /* boolean_value_expression ::= NOT boolean_primary */ +{ + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, yymsp[0].minor.yy256), NULL)); + } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 250: /* expr ::= STRING */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_STRING);} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 152: /* boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */ +{ + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 251: /* expr ::= NOW */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NOW); } - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 153: /* boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */ +{ + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy256); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); + } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 252: /* expr ::= VARIABLE */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_VARIABLE);} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 158: /* from_clause ::= FROM table_reference_list */ + case 188: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==188); + case 211: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==211); +{ yymsp[-1].minor.yy256 = yymsp[0].minor.yy256; } break; - case 253: /* expr ::= PLUS VARIABLE */ - case 254: /* expr ::= MINUS VARIABLE */ yytestcase(yyruleno==254); -{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_VARIABLE; yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_VARIABLE);} - yymsp[-1].minor.yy46 = yylhsminor.yy46; + case 160: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */ +{ yylhsminor.yy256 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy256, yymsp[0].minor.yy256, NULL); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 255: /* expr ::= BOOL */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_BOOL);} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 163: /* table_primary ::= table_name alias_opt */ +{ yylhsminor.yy256 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy129, &yymsp[0].minor.yy129); } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 256: /* expr ::= NULL */ -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NULL);} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 164: /* table_primary ::= db_name NK_DOT table_name alias_opt */ +{ yylhsminor.yy256 = createRealTableNode(pCxt, &yymsp[-3].minor.yy129, &yymsp[-1].minor.yy129, &yymsp[0].minor.yy129); } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 257: /* expr ::= ID LP exprlist RP */ -{ tRecordFuncName(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy46 = tSqlExprCreateFunction(yymsp[-1].minor.yy131, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy46 = yylhsminor.yy46; + case 165: /* table_primary ::= subquery alias_opt */ +{ yylhsminor.yy256 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy256), &yymsp[0].minor.yy129); } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 258: /* expr ::= ID LP STAR RP */ -{ tRecordFuncName(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy46 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } - yymsp[-3].minor.yy46 = yylhsminor.yy46; + case 167: /* alias_opt ::= */ +{ yymsp[1].minor.yy129 = nil_token; } break; - case 259: /* expr ::= expr IS NULL */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, NULL, TK_ISNULL);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 168: /* alias_opt ::= table_alias */ +{ yylhsminor.yy129 = yymsp[0].minor.yy129; } + yymsp[0].minor.yy129 = yylhsminor.yy129; break; - case 260: /* expr ::= expr IS NOT NULL */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-3].minor.yy46, NULL, TK_NOTNULL);} - yymsp[-3].minor.yy46 = yylhsminor.yy46; + case 169: /* alias_opt ::= AS table_alias */ +{ yymsp[-1].minor.yy129 = yymsp[0].minor.yy129; } break; - case 261: /* expr ::= expr LT expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_LT);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 170: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */ + case 171: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==171); +{ yymsp[-2].minor.yy256 = yymsp[-1].minor.yy256; } break; - case 262: /* expr ::= expr GT expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_GT);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 172: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ +{ yylhsminor.yy256 = createJoinTableNode(pCxt, yymsp[-4].minor.yy266, yymsp[-5].minor.yy256, yymsp[-2].minor.yy256, yymsp[0].minor.yy256); } + yymsp[-5].minor.yy256 = yylhsminor.yy256; break; - case 263: /* expr ::= expr LE expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_LE);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 173: /* join_type ::= */ +{ yymsp[1].minor.yy266 = JOIN_TYPE_INNER; } break; - case 264: /* expr ::= expr GE expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_GE);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 174: /* join_type ::= INNER */ +{ yymsp[0].minor.yy266 = JOIN_TYPE_INNER; } break; - case 265: /* expr ::= expr NE expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_NE);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 175: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ +{ + yymsp[-8].minor.yy256 = createSelectStmt(pCxt, yymsp[-7].minor.yy185, yymsp[-6].minor.yy46, yymsp[-5].minor.yy256); + yymsp[-8].minor.yy256 = addWhereClause(pCxt, yymsp[-8].minor.yy256, yymsp[-4].minor.yy256); + yymsp[-8].minor.yy256 = addPartitionByClause(pCxt, yymsp[-8].minor.yy256, yymsp[-3].minor.yy46); + yymsp[-8].minor.yy256 = addWindowClauseClause(pCxt, yymsp[-8].minor.yy256, yymsp[-2].minor.yy256); + yymsp[-8].minor.yy256 = addGroupByClause(pCxt, yymsp[-8].minor.yy256, yymsp[-1].minor.yy46); + yymsp[-8].minor.yy256 = addHavingClause(pCxt, yymsp[-8].minor.yy256, yymsp[0].minor.yy256); + } break; - case 266: /* expr ::= expr EQ expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_EQ);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 177: /* set_quantifier_opt ::= DISTINCT */ +{ yymsp[0].minor.yy185 = true; } break; - case 267: /* expr ::= expr BETWEEN expr AND expr */ -{ tSqlExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy46); yylhsminor.yy46 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy46, yymsp[-2].minor.yy46, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy46, TK_LE), TK_AND);} - yymsp[-4].minor.yy46 = yylhsminor.yy46; + case 178: /* set_quantifier_opt ::= ALL */ +{ yymsp[0].minor.yy185 = false; } break; - case 268: /* expr ::= expr AND expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_AND);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 179: /* select_list ::= NK_STAR */ +{ yymsp[0].minor.yy46 = NULL; } break; - case 269: /* expr ::= expr OR expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_OR); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 183: /* select_item ::= common_expression */ +{ + SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy256); + yylhsminor.yy256 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy256), &t); + } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 270: /* expr ::= expr PLUS expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_PLUS); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 184: /* select_item ::= common_expression column_alias */ +{ yylhsminor.yy256 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy256), &yymsp[0].minor.yy129); } + yymsp[-1].minor.yy256 = yylhsminor.yy256; break; - case 271: /* expr ::= expr MINUS expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_MINUS); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 185: /* select_item ::= common_expression AS column_alias */ +{ yylhsminor.yy256 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), &yymsp[0].minor.yy129); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 272: /* expr ::= expr STAR expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_STAR); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 186: /* select_item ::= table_name NK_DOT NK_STAR */ +{ yylhsminor.yy256 = createColumnNode(pCxt, &yymsp[-2].minor.yy129, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 273: /* expr ::= expr SLASH expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_DIVIDE);} - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 187: /* where_clause_opt ::= */ + case 191: /* twindow_clause_opt ::= */ yytestcase(yyruleno==191); + case 196: /* sliding_opt ::= */ yytestcase(yyruleno==196); + case 198: /* fill_opt ::= */ yytestcase(yyruleno==198); + case 210: /* having_clause_opt ::= */ yytestcase(yyruleno==210); + case 218: /* slimit_clause_opt ::= */ yytestcase(yyruleno==218); + case 222: /* limit_clause_opt ::= */ yytestcase(yyruleno==222); +{ yymsp[1].minor.yy256 = NULL; } break; - case 274: /* expr ::= expr REM expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_REM); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 190: /* partition_by_clause_opt ::= PARTITION BY expression_list */ + case 207: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==207); + case 217: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==217); +{ yymsp[-2].minor.yy46 = yymsp[0].minor.yy46; } break; - case 275: /* expr ::= expr LIKE expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_LIKE); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 192: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA NK_INTEGER NK_RP */ +{ yymsp[-5].minor.yy256 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy256), &yymsp[-1].minor.yy0); } break; - case 276: /* expr ::= expr MATCH expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_MATCH); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 193: /* twindow_clause_opt ::= STATE_WINDOW NK_LP column_reference NK_RP */ +{ yymsp[-3].minor.yy256 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy256)); } break; - case 277: /* expr ::= expr NMATCH expr */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-2].minor.yy46, yymsp[0].minor.yy46, TK_NMATCH); } - yymsp[-2].minor.yy46 = yylhsminor.yy46; + case 194: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ +{ yymsp[-5].minor.yy256 = createIntervalWindowNode(pCxt, yymsp[-3].minor.yy256, NULL, yymsp[-1].minor.yy256, yymsp[0].minor.yy256); } break; - case 278: /* expr ::= expr IN LP exprlist RP */ -{yylhsminor.yy46 = tSqlExprCreate(yymsp[-4].minor.yy46, (tSqlExpr*)yymsp[-1].minor.yy131, TK_IN); } - yymsp[-4].minor.yy46 = yylhsminor.yy46; + case 195: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ +{ yymsp[-7].minor.yy256 = createIntervalWindowNode(pCxt, yymsp[-5].minor.yy256, yymsp[-3].minor.yy256, yymsp[-1].minor.yy256, yymsp[0].minor.yy256); } break; - case 279: /* exprlist ::= exprlist COMMA expritem */ -{yylhsminor.yy131 = tSqlExprListAppend(yymsp[-2].minor.yy131,yymsp[0].minor.yy46,0, 0);} - yymsp[-2].minor.yy131 = yylhsminor.yy131; + case 197: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ +{ yymsp[-3].minor.yy256 = yymsp[-1].minor.yy256; } break; - case 280: /* exprlist ::= expritem */ -{yylhsminor.yy131 = tSqlExprListAppend(0,yymsp[0].minor.yy46,0, 0);} - yymsp[0].minor.yy131 = yylhsminor.yy131; + case 199: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */ +{ yymsp[-3].minor.yy256 = createFillNode(pCxt, yymsp[-1].minor.yy360, NULL); } break; - case 281: /* expritem ::= expr */ -{yylhsminor.yy46 = yymsp[0].minor.yy46;} - yymsp[0].minor.yy46 = yylhsminor.yy46; + case 200: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ +{ yymsp[-5].minor.yy256 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy46)); } break; - case 283: /* cmd ::= RESET QUERY CACHE */ -{ setDCLSqlElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} + case 201: /* fill_mode ::= NONE */ +{ yymsp[0].minor.yy360 = FILL_MODE_NONE; } break; - case 284: /* cmd ::= SYNCDB ids REPLICA */ -{ setDCLSqlElems(pInfo, TSDB_SQL_SYNC_DB_REPLICA, 1, &yymsp[-1].minor.yy0);} + case 202: /* fill_mode ::= PREV */ +{ yymsp[0].minor.yy360 = FILL_MODE_PREV; } break; - case 285: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 203: /* fill_mode ::= NULL */ +{ yymsp[0].minor.yy360 = FILL_MODE_NULL; } break; - case 286: /* cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - toTSDBType(yymsp[0].minor.yy0.type); - SArray* K = tListItemAppendToken(NULL, &yymsp[0].minor.yy0, -1); - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 204: /* fill_mode ::= LINEAR */ +{ yymsp[0].minor.yy360 = FILL_MODE_LINEAR; } break; - case 287: /* cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 205: /* fill_mode ::= NEXT */ +{ yymsp[0].minor.yy360 = FILL_MODE_NEXT; } break; - case 288: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_TAG, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 208: /* group_by_list ::= expression */ +{ yylhsminor.yy46 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); } + yymsp[0].minor.yy46 = yylhsminor.yy46; break; - case 289: /* cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - - toTSDBType(yymsp[0].minor.yy0.type); - SArray* A = tListItemAppendToken(NULL, &yymsp[0].minor.yy0, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 209: /* group_by_list ::= group_by_list NK_COMMA expression */ +{ yylhsminor.yy46 = addNodeToList(pCxt, yymsp[-2].minor.yy46, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy256))); } + yymsp[-2].minor.yy46 = yylhsminor.yy46; break; - case 290: /* cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ -{ - yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; - - toTSDBType(yymsp[-1].minor.yy0.type); - SArray* A = tListItemAppendToken(NULL, &yymsp[-1].minor.yy0, -1); - - toTSDBType(yymsp[0].minor.yy0.type); - A = tListItemAppendToken(A, &yymsp[0].minor.yy0, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 212: /* query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ +{ + yylhsminor.yy256 = addOrderByClause(pCxt, yymsp[-3].minor.yy256, yymsp[-2].minor.yy46); + yylhsminor.yy256 = addSlimitClause(pCxt, yylhsminor.yy256, yymsp[-1].minor.yy256); + yylhsminor.yy256 = addLimitClause(pCxt, yylhsminor.yy256, yymsp[0].minor.yy256); + } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 291: /* cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ -{ - yymsp[-6].minor.yy0.n += yymsp[-5].minor.yy0.n; - - toTSDBType(yymsp[-2].minor.yy0.type); - SArray* A = tListItemAppendToken(NULL, &yymsp[-2].minor.yy0, -1); - A = tListItemAppend(A, &yymsp[0].minor.yy43, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-6].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 214: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */ +{ yylhsminor.yy256 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy256, yymsp[0].minor.yy256); } + yymsp[-3].minor.yy256 = yylhsminor.yy256; break; - case 292: /* cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, -1); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 219: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */ + case 223: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==223); +{ yymsp[-1].minor.yy256 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); } break; - case 293: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 220: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ + case 224: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==224); +{ yymsp[-3].minor.yy256 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 294: /* cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - - toTSDBType(yymsp[0].minor.yy0.type); - SArray* K = tListItemAppendToken(NULL, &yymsp[0].minor.yy0, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, K, TSDB_ALTER_TABLE_DROP_COLUMN, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 221: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + case 225: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==225); +{ yymsp[-3].minor.yy256 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); } break; - case 295: /* cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 226: /* subquery ::= NK_LP query_expression NK_RP */ +{ yylhsminor.yy256 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy256); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 296: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_TAG, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 227: /* search_condition ::= common_expression */ +{ yylhsminor.yy256 = releaseRawExprNode(pCxt, yymsp[0].minor.yy256); } + yymsp[0].minor.yy256 = yylhsminor.yy256; break; - case 297: /* cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - - toTSDBType(yymsp[0].minor.yy0.type); - SArray* A = tListItemAppendToken(NULL, &yymsp[0].minor.yy0, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, NULL, A, TSDB_ALTER_TABLE_DROP_TAG, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 230: /* sort_specification ::= expression ordering_specification_opt null_ordering_opt */ +{ yylhsminor.yy256 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy256), yymsp[-1].minor.yy202, yymsp[0].minor.yy147); } + yymsp[-2].minor.yy256 = yylhsminor.yy256; break; - case 298: /* cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ -{ - yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; - - toTSDBType(yymsp[-1].minor.yy0.type); - SArray* A = tListItemAppendToken(NULL, &yymsp[-1].minor.yy0, -1); - - toTSDBType(yymsp[0].minor.yy0.type); - A = tListItemAppendToken(A, &yymsp[0].minor.yy0, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-5].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 231: /* ordering_specification_opt ::= */ +{ yymsp[1].minor.yy202 = ORDER_ASC; } break; - case 299: /* cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ -{ - yymsp[-6].minor.yy0.n += yymsp[-5].minor.yy0.n; - - toTSDBType(yymsp[-2].minor.yy0.type); - SArray* A = tListItemAppendToken(NULL, &yymsp[-2].minor.yy0, -1); - A = tListItemAppend(A, &yymsp[0].minor.yy43, -1); - - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-6].minor.yy0, NULL, A, TSDB_ALTER_TABLE_UPDATE_TAG_VAL, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 232: /* ordering_specification_opt ::= ASC */ +{ yymsp[0].minor.yy202 = ORDER_ASC; } break; - case 300: /* cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ -{ - yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, TSDB_SUPER_TABLE); - setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); -} + case 233: /* ordering_specification_opt ::= DESC */ +{ yymsp[0].minor.yy202 = ORDER_DESC; } break; - case 301: /* cmd ::= KILL CONNECTION INTEGER */ -{setKillSql(pInfo, TSDB_SQL_KILL_CONNECTION, &yymsp[0].minor.yy0);} + case 234: /* null_ordering_opt ::= */ +{ yymsp[1].minor.yy147 = NULL_ORDER_DEFAULT; } break; - case 302: /* cmd ::= KILL STREAM INTEGER COLON INTEGER */ -{yymsp[-2].minor.yy0.n += (yymsp[-1].minor.yy0.n + yymsp[0].minor.yy0.n); setKillSql(pInfo, TSDB_SQL_KILL_STREAM, &yymsp[-2].minor.yy0);} + case 235: /* null_ordering_opt ::= NULLS FIRST */ +{ yymsp[-1].minor.yy147 = NULL_ORDER_FIRST; } break; - case 303: /* cmd ::= KILL QUERY INTEGER COLON INTEGER */ -{yymsp[-2].minor.yy0.n += (yymsp[-1].minor.yy0.n + yymsp[0].minor.yy0.n); setKillSql(pInfo, TSDB_SQL_KILL_QUERY, &yymsp[-2].minor.yy0);} + case 236: /* null_ordering_opt ::= NULLS LAST */ +{ yymsp[-1].minor.yy147 = NULL_ORDER_LAST; } break; default: break; @@ -3376,6 +2676,7 @@ static void yy_reduce( yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact, "... then shift"); + return yyact; } /* @@ -3385,7 +2686,8 @@ static void yy_reduce( static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); @@ -3396,7 +2698,8 @@ static void yy_parse_failed( ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ + ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ + ParseCTX_STORE } #endif /* YYNOERRORRECOVERY */ @@ -3408,33 +2711,20 @@ static void yy_syntax_error( int yymajor, /* The major type of the error token */ ParseTOKENTYPE yyminor /* The minor type of the error token */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ - - pInfo->valid = false; - int32_t outputBufLen = tListLen(pInfo->msg); - int32_t len = 0; - + if(TOKEN.z) { - char msg[] = "syntax error near \"%s\""; - int32_t sqlLen = strlen(&TOKEN.z[0]); - - if (sqlLen + sizeof(msg)/sizeof(msg[0]) + 1 > outputBufLen) { - char tmpstr[128] = {0}; - memcpy(tmpstr, &TOKEN.z[0], sizeof(tmpstr)/sizeof(tmpstr[0]) - 1); - len = sprintf(pInfo->msg, msg, tmpstr); - } else { - len = sprintf(pInfo->msg, msg, &TOKEN.z[0]); - } - + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, TOKEN.z); } else { - len = sprintf(pInfo->msg, "Incomplete SQL statement"); + generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCOMPLETE_SQL); } - - assert(len <= outputBufLen); + pCxt->valid = false; /************ End %syntax_error code ******************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ + ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ + ParseCTX_STORE } /* @@ -3443,7 +2733,8 @@ static void yy_syntax_error( static void yy_accept( yyParser *yypParser /* The parser */ ){ - ParseARG_FETCH; + ParseARG_FETCH + ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); @@ -3456,9 +2747,9 @@ static void yy_accept( /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ - /*********** End %parse_accept code *******************************************/ - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ + ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ + ParseCTX_STORE } /* The main parser program. @@ -3487,45 +2778,47 @@ void Parse( ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; - unsigned int yyact; /* The parser action. */ + YYACTIONTYPE yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif - yyParser *yypParser; /* The parser */ + yyParser *yypParser = (yyParser*)yyp; /* The parser */ + ParseCTX_FETCH + ParseARG_STORE - yypParser = (yyParser*)yyp; assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif - ParseARG_STORE; + yyact = yypParser->yytos->stateno; #ifndef NDEBUG if( yyTraceFILE ){ - int stateno = yypParser->yytos->stateno; - if( stateno < YY_MIN_REDUCE ){ + if( yyact < YY_MIN_REDUCE ){ fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", - yyTracePrompt,yyTokenName[yymajor],stateno); + yyTracePrompt,yyTokenName[yymajor],yyact); }else{ fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - yyTracePrompt,yyTokenName[yymajor],stateno-YY_MIN_REDUCE); + yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); } } #endif do{ - yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); + assert( yyact==yypParser->yytos->stateno ); + yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); if( yyact >= YY_MIN_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor); + yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, + yyminor ParseCTX_PARAM); }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,yymajor,yyminor); + yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif - yymajor = YYNOCODE; + break; }else if( yyact==YY_ACCEPT_ACTION ){ yypParser->yytos--; yy_accept(yypParser); @@ -3576,10 +2869,9 @@ void Parse( yymajor = YYNOCODE; }else{ while( yypParser->yytos >= yypParser->yystack - && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE ){ yy_pop_parser_stack(yypParser); } @@ -3596,6 +2888,8 @@ void Parse( } yypParser->yyerrcnt = 3; yyerrorhit = 1; + if( yymajor==YYNOCODE ) break; + yyact = yypParser->yytos->stateno; #elif defined(YYNOERRORRECOVERY) /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax @@ -3606,8 +2900,7 @@ void Parse( */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - + break; #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** @@ -3629,10 +2922,10 @@ void Parse( yypParser->yyerrcnt = -1; #endif } - yymajor = YYNOCODE; + break; #endif } - }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); + }while( yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ yyStackEntry *i; @@ -3647,3 +2940,18 @@ void Parse( #endif return; } + +/* +** Return the fallback token corresponding to canonical token iToken, or +** 0 if iToken has no fallback. +*/ +int ParseFallback(int iToken){ +#ifdef YYFALLBACK + if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ + return yyFallback[iToken]; + } +#else + (void)iToken; +#endif + return 0; +} diff --git a/source/libs/parser/test/mockCatalog.cpp b/source/libs/parser/test/mockCatalog.cpp index e626fc68aeb93b70fa6ad8443e1ffd48634f2f4a..3236ad165c3aef025505e8802a26efab27ed63e7 100644 --- a/source/libs/parser/test/mockCatalog.cpp +++ b/source/libs/parser/test/mockCatalog.cpp @@ -37,8 +37,8 @@ void generateTestT1(MockCatalogService* mcs) { void generateTestST1(MockCatalogService* mcs) { ITableBuilder& builder = mcs->createTableBuilder("test", "st1", TSDB_SUPER_TABLE, 3, 2) .setPrecision(TSDB_TIME_PRECISION_MILLI).addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP) - .addTag("tag1", TSDB_DATA_TYPE_INT).addTag("tag2", TSDB_DATA_TYPE_BINARY, 20) - .addColumn("c1", TSDB_DATA_TYPE_INT).addColumn("c2", TSDB_DATA_TYPE_BINARY, 20); + .addColumn("c1", TSDB_DATA_TYPE_INT).addColumn("c2", TSDB_DATA_TYPE_BINARY, 20) + .addTag("tag1", TSDB_DATA_TYPE_INT).addTag("tag2", TSDB_DATA_TYPE_BINARY, 20); builder.done(); mcs->createSubTable("test", "st1", "st1s1", 1); mcs->createSubTable("test", "st1", "st1s2", 2); @@ -58,6 +58,14 @@ int32_t __catalogGetTableHashVgroup(struct SCatalog* pCatalog, void *pRpc, const return mockCatalogService->catalogGetTableHashVgroup(pTableName, vgInfo); } +int32_t __catalogGetTableDistVgInfo(SCatalog* pCtg, void *pRpc, const SEpSet* pMgmtEps, const SName* pTableName, SArray** pVgList) { + return mockCatalogService->catalogGetTableDistVgInfo(pTableName, pVgList); +} + +int32_t __catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId, int32_t *tableNum) { + return 0; +} + void initMetaDataEnv() { mockCatalogService.reset(new MockCatalogService()); @@ -65,30 +73,47 @@ void initMetaDataEnv() { stub.set(catalogGetHandle, __catalogGetHandle); stub.set(catalogGetTableMeta, __catalogGetTableMeta); stub.set(catalogGetTableHashVgroup, __catalogGetTableHashVgroup); - { - AddrAny any("libcatalog.so"); - std::map result; - any.get_global_func_addr_dynsym("^catalogGetHandle$", result); - for (const auto& f : result) { - stub.set(f.second, __catalogGetHandle); - } - } - { - AddrAny any("libcatalog.so"); - std::map result; - any.get_global_func_addr_dynsym("^catalogGetTableMeta$", result); - for (const auto& f : result) { - stub.set(f.second, __catalogGetTableMeta); - } - } - { - AddrAny any("libcatalog.so"); - std::map result; - any.get_global_func_addr_dynsym("^catalogGetTableHashVgroup$", result); - for (const auto& f : result) { - stub.set(f.second, __catalogGetTableHashVgroup); - } - } + stub.set(catalogGetTableDistVgInfo, __catalogGetTableDistVgInfo); + // { + // AddrAny any("libcatalog.so"); + // std::map result; + // any.get_global_func_addr_dynsym("^catalogGetHandle$", result); + // for (const auto& f : result) { + // stub.set(f.second, __catalogGetHandle); + // } + // } + // { + // AddrAny any("libcatalog.so"); + // std::map result; + // any.get_global_func_addr_dynsym("^catalogGetTableMeta$", result); + // for (const auto& f : result) { + // stub.set(f.second, __catalogGetTableMeta); + // } + // } + // { + // AddrAny any("libcatalog.so"); + // std::map result; + // any.get_global_func_addr_dynsym("^catalogGetTableHashVgroup$", result); + // for (const auto& f : result) { + // stub.set(f.second, __catalogGetTableHashVgroup); + // } + // } + // { + // AddrAny any("libcatalog.so"); + // std::map result; + // any.get_global_func_addr_dynsym("^catalogGetTableDistVgInfo$", result); + // for (const auto& f : result) { + // stub.set(f.second, __catalogGetTableDistVgInfo); + // } + // } + // { + // AddrAny any("libcatalog.so"); + // std::map result; + // any.get_global_func_addr_dynsym("^catalogGetDBVgVersion$", result); + // for (const auto& f : result) { + // stub.set(f.second, __catalogGetDBVgVersion); + // } + // } } void generateMetaData() { diff --git a/source/libs/parser/test/mockCatalogService.cpp b/source/libs/parser/test/mockCatalogService.cpp index cd3ffcdce963cbaa978d3b887d35af5dd3cd3345..65d3f51dde3e1aaf7cba570f60b9f3f10bf5641c 100644 --- a/source/libs/parser/test/mockCatalogService.cpp +++ b/source/libs/parser/test/mockCatalogService.cpp @@ -77,10 +77,10 @@ private: } TableBuilder(STableMeta* schemaMeta) : colId_(1), rowsize_(0), meta_(new MockTableMeta()) { - meta_->schema.reset(schemaMeta); + meta_->schema = schemaMeta; } - std::shared_ptr schema() { + STableMeta* schema() { return meta_->schema; } @@ -113,6 +113,7 @@ public: const char* tname = tNameGetTableName(pTableName); int32_t code = copyTableSchemaMeta(db, tname, &table); if (TSDB_CODE_SUCCESS != code) { + std::cout << "db : " << db << ", table :" << tname << std::endl; return code; } *pTableMeta = table.release(); @@ -126,6 +127,19 @@ public: return 0; } + int32_t catalogGetTableDistVgInfo(const SName* pTableName, SArray** pVgList) const { + SVgroupInfo info = {0}; + info.vgId = 1; + addEpIntoEpSet(&info.epSet, "node1", 6030); + + info.hashBegin = 0; + info.hashEnd = 1; + *pVgList = taosArrayInit(4, sizeof(SVgroupInfo)); + + taosArrayPush(*pVgList, &info); + return 0; + } + TableBuilder& createTableBuilder(const std::string& db, const std::string& tbname, int8_t tableType, int32_t numOfColumns, int32_t numOfTags) { builder_ = TableBuilder::createTableBuilder(tableType, numOfColumns, numOfTags); meta_[db][tbname] = builder_->table(); @@ -139,7 +153,7 @@ public: throw std::runtime_error("copyTableSchemaMeta failed"); } meta_[db][tbname].reset(new MockTableMeta()); - meta_[db][tbname]->schema.reset(table.release()); + meta_[db][tbname]->schema = table.release(); meta_[db][tbname]->schema->uid = id_++; SVgroupInfo vgroup = {.vgId = vgid, .hashBegin = 0, .hashEnd = 0,}; @@ -261,14 +275,14 @@ private: return (0 == colid ? "column" : (colid <= numOfTags ? "tag" : "column")); } - std::shared_ptr getTableSchemaMeta(const std::string& db, const std::string& tbname) const { + STableMeta* getTableSchemaMeta(const std::string& db, const std::string& tbname) const { std::shared_ptr table = getTableMeta(db, tbname); - return table ? table->schema : std::shared_ptr(); + return table ? table->schema : nullptr; } int32_t copyTableSchemaMeta(const std::string& db, const std::string& tbname, std::unique_ptr* dst) const { - std::shared_ptr src = getTableSchemaMeta(db, tbname); - if (!src) { + STableMeta* src = getTableSchemaMeta(db, tbname); + if (nullptr == src) { return TSDB_CODE_TSC_INVALID_TABLE_NAME; } int32_t len = sizeof(STableMeta) + sizeof(SSchema) * (src->tableInfo.numOfTags + src->tableInfo.numOfColumns); @@ -276,7 +290,7 @@ private: if (!dst) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } - memcpy(dst->get(), src.get(), len); + memcpy(dst->get(), src, len); return TSDB_CODE_SUCCESS; } @@ -314,3 +328,7 @@ int32_t MockCatalogService::catalogGetTableMeta(const SName* pTableName, STableM int32_t MockCatalogService::catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const { return impl_->catalogGetTableHashVgroup(pTableName, vgInfo); } + +int32_t MockCatalogService::catalogGetTableDistVgInfo(const SName* pTableName, SArray** pVgList) const { + return impl_->catalogGetTableDistVgInfo(pTableName, pVgList); +} diff --git a/source/libs/parser/test/mockCatalogService.h b/source/libs/parser/test/mockCatalogService.h index b9713316351d458cbf6631480b0881a5fd901858..a722f0b821255d9564f298842aa6d92afd37f0ae 100644 --- a/source/libs/parser/test/mockCatalogService.h +++ b/source/libs/parser/test/mockCatalogService.h @@ -43,7 +43,11 @@ public: }; struct MockTableMeta { - std::shared_ptr schema; + ~MockTableMeta() { + free(schema); + } + + STableMeta* schema; std::vector vgs; }; @@ -59,6 +63,7 @@ public: int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta) const; int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const; + int32_t catalogGetTableDistVgInfo(const SName* pTableName, SArray** pVgList) const; private: std::unique_ptr impl_; diff --git a/source/libs/parser/test/newParserTest.cpp b/source/libs/parser/test/newParserTest.cpp deleted file mode 100644 index 996e94184853861708bd0e53eed30753ec9d22ca..0000000000000000000000000000000000000000 --- a/source/libs/parser/test/newParserTest.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include -#include - -#include - -#include "parserImpl.h" - -using namespace std; -using namespace testing; - -class NewParserTest : public Test { -protected: - void setDatabase(const string& acctId, const string& db) { - acctId_ = acctId; - db_ = db; - } - - void bind(const char* sql) { - reset(); - cxt_.acctId = atoi(acctId_.c_str()); - cxt_.db = db_.c_str(); - sqlBuf_ = string(sql); - transform(sqlBuf_.begin(), sqlBuf_.end(), sqlBuf_.begin(), ::tolower); - cxt_.sqlLen = strlen(sql); - cxt_.pSql = sqlBuf_.c_str(); - } - - bool run(int32_t parseCode = TSDB_CODE_SUCCESS, int32_t translateCode = TSDB_CODE_SUCCESS) { - int32_t code = doParse(&cxt_, &query_); - // cout << "doParse return " << code << endl; - if (code != TSDB_CODE_SUCCESS) { - cout << "sql:[" << cxt_.pSql << "] code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl; - return (TSDB_CODE_SUCCESS != parseCode); - } - if (TSDB_CODE_SUCCESS != parseCode) { - return false; - } - code = doTranslate(&cxt_, &query_); - // cout << "doTranslate return " << code << endl; - if (code != TSDB_CODE_SUCCESS) { - cout << "sql:[" << cxt_.pSql << "] code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl; - return (code == translateCode); - } - if (NULL != query_.pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_.pRoot)) { - cout << "input sql : [" << cxt_.pSql << "]" << endl; - // string sql; - // selectToSql(query_.pRoot, sql); - // cout << "output sql : [" << sql << "]" << endl; - string str; - selectToStr(query_.pRoot, str); - cout << "translate str : \n" << str << endl; - } - return (TSDB_CODE_SUCCESS == translateCode); - } - -private: - static const int max_err_len = 1024; - - void exprNodeToStr(const SNode* node, string& str, bool isProject) { - switch (nodeType(node)) { - case QUERY_NODE_COLUMN: - case QUERY_NODE_VALUE: - case QUERY_NODE_OPERATOR: - case QUERY_NODE_FUNCTION: - case QUERY_NODE_LOGIC_CONDITION: { - SExprNode* pExpr = (SExprNode*)node; - str.append(" [" + dataTypeToStr(pExpr->resType) + "]"); - if (isProject) { - str.append(" AS " + string(pExpr->aliasName)); - } - break; - } - default: - break; - } - } - - string dataTypeToStr(const SDataType& dt) { - switch (dt.type) { - case TSDB_DATA_TYPE_NULL: - return "NULL"; - case TSDB_DATA_TYPE_BOOL: - return "BOOL"; - case TSDB_DATA_TYPE_TINYINT: - return "TINYINT"; - case TSDB_DATA_TYPE_SMALLINT: - return "SMALLINT"; - case TSDB_DATA_TYPE_INT: - return "INT"; - case TSDB_DATA_TYPE_BIGINT: - return "BIGINT"; - case TSDB_DATA_TYPE_FLOAT: - return "FLOAT"; - case TSDB_DATA_TYPE_DOUBLE: - return "DOUBLE"; - case TSDB_DATA_TYPE_BINARY: - return "BINART(" + to_string(dt.bytes) + ")"; - case TSDB_DATA_TYPE_TIMESTAMP: - return "TIMESTAMP"; - case TSDB_DATA_TYPE_NCHAR: - return "NCHAR(" + to_string(dt.bytes) + ")"; - case TSDB_DATA_TYPE_UTINYINT: - return "UTINYINT"; - case TSDB_DATA_TYPE_USMALLINT: - return "USMALLINT"; - case TSDB_DATA_TYPE_UINT: - return "UINT"; - case TSDB_DATA_TYPE_UBIGINT: - return "UBIGINT"; - case TSDB_DATA_TYPE_VARCHAR: - return "VARCHAR(" + to_string(dt.bytes) + ")"; - case TSDB_DATA_TYPE_VARBINARY: - return "VARBINARY(" + to_string(dt.bytes) + ")"; - case TSDB_DATA_TYPE_JSON: - return "JSON"; - case TSDB_DATA_TYPE_DECIMAL: - return "DECIMAL(" + to_string(dt.precision) + ", " + to_string(dt.scale) + ")"; - case TSDB_DATA_TYPE_BLOB: - return "BLOB"; - default: - break; - } - return "Unknown Data Type " + to_string(dt.type); - } - - void valueNodeToStr(const SValueNode* pVal, string& str) { - switch (pVal->node.resType.type) { - case TSDB_DATA_TYPE_NULL: - str.append("null"); - break; - case TSDB_DATA_TYPE_BOOL: - str.append(pVal->datum.b ? "true" : "false"); - break; - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_BIGINT: - str.append(to_string(pVal->datum.i)); - break; - case TSDB_DATA_TYPE_FLOAT: - case TSDB_DATA_TYPE_DOUBLE: - str.append(to_string(pVal->datum.d)); - break; - case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_NCHAR: - case TSDB_DATA_TYPE_VARCHAR: - case TSDB_DATA_TYPE_VARBINARY: - str.append(pVal->datum.p); - break; - case TSDB_DATA_TYPE_TIMESTAMP: - str.append(to_string(pVal->datum.u)); - break; - case TSDB_DATA_TYPE_UTINYINT: - case TSDB_DATA_TYPE_USMALLINT: - case TSDB_DATA_TYPE_UINT: - case TSDB_DATA_TYPE_UBIGINT: - str.append(to_string(pVal->datum.u)); - break; - case TSDB_DATA_TYPE_JSON: - case TSDB_DATA_TYPE_DECIMAL: - case TSDB_DATA_TYPE_BLOB: - str.append("JSON or DECIMAL or BLOB"); - break; - default: - break; - } - } - - void columnNodeToStr(const SColumnNode* pCol, string& str) { - if ('\0' != pCol->dbName[0]) { - str.append(pCol->dbName); - str.append("."); - } - if ('\0' != pCol->tableAlias[0]) { - str.append(pCol->tableAlias); - str.append("."); - } - str.append(pCol->colName); - } - - void operatorToStr(const SOperatorNode* pOp, string& str) { - nodeToStr(pOp->pLeft, str, false); - str.append(opTypeToStr(pOp->opType)); - nodeToStr(pOp->pRight, str, false); - } - - void functionToStr(const SFunctionNode* pFunc, string& str) { - str.append(pFunc->functionName); - str.append("("); - nodeListToStr(pFunc->pParameterList, "", str, false, ", "); - str.append(")"); - } - - void groupingSetToStr(SGroupingSetNode* pGroup, string& str) { - nodeToStr(nodesListGetNode(pGroup->pParameterList, 0), str, false); - } - - void orderByExprToStr(SOrderByExprNode* pOrderBy, string& str) { - nodeToStr(pOrderBy->pExpr, str, false); - str.append((ORDER_ASC == pOrderBy->order ? " ASC" : " DESC")); - str.append((NULL_ORDER_FIRST == pOrderBy->nullOrder ? " NULLS FIRST" : " NULLS LAST")); - } - - string logicConditionTypeToStr(ELogicConditionType type) { - switch (type) { - case LOGIC_COND_TYPE_AND: - return "AND"; - case LOGIC_COND_TYPE_OR: - return "OR"; - case LOGIC_COND_TYPE_NOT: - return "NOT"; - default: - break; - } - return "Unknown logic cond type"; - } - - void logicCondToStr(SLogicConditionNode* pCond, string& str) { - SNode* node = nullptr; - bool first = true; - FOREACH(node, pCond->pParameterList) { - if (first && LOGIC_COND_TYPE_NOT == pCond->condType) { - str.append(logicConditionTypeToStr(pCond->condType) + " "); - } else if (!first && LOGIC_COND_TYPE_NOT != pCond->condType) { - str.append(" " + logicConditionTypeToStr(pCond->condType) + " "); - } - first = false; - nodeToStr(node, str, false); - } - } - - void nodeToStr(const SNode* node, string& str, bool isProject) { - if (nullptr == node) { - return; - } - - switch (nodeType(node)) { - case QUERY_NODE_COLUMN: { - columnNodeToStr((SColumnNode*)node, str); - break; - } - case QUERY_NODE_VALUE: { - valueNodeToStr((SValueNode*)node, str); - break; - } - case QUERY_NODE_OPERATOR: { - operatorToStr((SOperatorNode*)node, str); - break; - } - case QUERY_NODE_FUNCTION: { - functionToStr((SFunctionNode*)node, str); - break; - } - case QUERY_NODE_LOGIC_CONDITION: { - logicCondToStr((SLogicConditionNode*)node, str); - break; - } - case QUERY_NODE_GROUPING_SET: { - groupingSetToStr((SGroupingSetNode*)node, str); - break; - } - case QUERY_NODE_ORDER_BY_EXPR: { - orderByExprToStr((SOrderByExprNode*)node, str); - break; - } - default: - break; - } - exprNodeToStr(node, str, isProject); - } - - void nodeListToStr(const SNodeList* nodelist, const string& prefix, string& str, bool isProject = false, const string& sep = string("\n")) { - SNode* node = nullptr; - FOREACH(node, nodelist) { - str.append(prefix); - nodeToStr(node, str, isProject); - str.append(sep); - } - } - - void tableToStr(const SNode* node, const string& prefix, string& str) { - const STableNode* table = (const STableNode*)node; - switch (nodeType(node)) { - case QUERY_NODE_REAL_TABLE: { - SRealTableNode* realTable = (SRealTableNode*)table; - str.append(prefix); - if ('\0' != realTable->table.dbName[0]) { - str.append(realTable->table.dbName); - str.append("."); - } - str.append(realTable->table.tableName); - str.append(string(" ") + realTable->table.tableAlias); - break; - } - case QUERY_NODE_TEMP_TABLE: { - STempTableNode* tempTable = (STempTableNode*)table; - str.append(prefix + "(\n"); - selectToStr(tempTable->pSubquery, str, prefix + "\t"); - str.append("\n"); - str.append(prefix + ") "); - str.append(tempTable->table.tableAlias); - break; - } - case QUERY_NODE_JOIN_TABLE: { - SJoinTableNode* joinTable = (SJoinTableNode*)table; - tableToStr(joinTable->pLeft, prefix, str); - str.append("\n" + prefix + "JOIN\n"); - tableToStr(joinTable->pRight, prefix, str); - if (nullptr != joinTable->pOnCond) { - str.append("\n" + prefix + "\tON "); - nodeToStr(joinTable->pOnCond, str, false); - } - break; - } - default: - break; - } - } - - void selectToStr(const SNode* node, string& str, const string& prefix = "") { - SSelectStmt* select = (SSelectStmt*)node; - str.append(prefix + "SELECT "); - if (select->isDistinct) { - str.append("DISTINCT"); - } - str.append("\n"); - nodeListToStr(select->pProjectionList, prefix + "\t", str, true); - str.append(prefix + "FROM\n"); - tableToStr(select->pFromTable, prefix + "\t", str); - if (nullptr != select->pWhere) { - str.append("\n" + prefix + "WHERE\n\t"); - nodeToStr(select->pWhere, str, false); - } - if (nullptr != select->pGroupByList) { - str.append("\n" + prefix + "GROUP BY\n"); - nodeListToStr(select->pGroupByList, prefix + "\t", str, true); - } - if (nullptr != select->pOrderByList) { - str.append(prefix + "ORDER BY\n"); - nodeListToStr(select->pOrderByList, prefix + "\t", str, true); - } - } - - void selectToSql(const SNode* node, string& sql) { - SSelectStmt* select = (SSelectStmt*)node; - sql.append("SELECT "); - if (select->isDistinct) { - sql.append("DISTINCT "); - } - if (nullptr == select->pProjectionList) { - sql.append("* "); - } else { - nodeListToSql(select->pProjectionList, sql); - sql.append(" "); - } - sql.append("FROM "); - tableToSql(select->pFromTable, sql); - if (nullptr != select->pWhere) { - sql.append(" WHERE "); - nodeToSql(select->pWhere, sql); - } - } - - void tableToSql(const SNode* node, string& sql) { - const STableNode* table = (const STableNode*)node; - switch (nodeType(node)) { - case QUERY_NODE_REAL_TABLE: { - SRealTableNode* realTable = (SRealTableNode*)table; - if ('\0' != realTable->table.dbName[0]) { - sql.append(realTable->table.dbName); - sql.append("."); - } - sql.append(realTable->table.tableName); - break; - } - case QUERY_NODE_TEMP_TABLE: { - STempTableNode* tempTable = (STempTableNode*)table; - sql.append("("); - selectToSql(tempTable->pSubquery, sql); - sql.append(") "); - sql.append(tempTable->table.tableAlias); - break; - } - case QUERY_NODE_JOIN_TABLE: { - SJoinTableNode* joinTable = (SJoinTableNode*)table; - tableToSql(joinTable->pLeft, sql); - sql.append(" JOIN "); - tableToSql(joinTable->pRight, sql); - if (nullptr != joinTable->pOnCond) { - sql.append(" ON "); - nodeToSql(joinTable->pOnCond, sql); - } - break; - } - default: - break; - } - } - - string opTypeToStr(EOperatorType type) { - switch (type) { - case OP_TYPE_ADD: - return " + "; - case OP_TYPE_SUB: - return " - "; - case OP_TYPE_MULTI: - return " * "; - case OP_TYPE_DIV: - return " / "; - case OP_TYPE_MOD: - return " % "; - case OP_TYPE_GREATER_THAN: - return " > "; - case OP_TYPE_GREATER_EQUAL: - return " >= "; - case OP_TYPE_LOWER_THAN: - return " < "; - case OP_TYPE_LOWER_EQUAL: - return " <= "; - case OP_TYPE_EQUAL: - return " = "; - case OP_TYPE_NOT_EQUAL: - return " != "; - case OP_TYPE_IN: - case OP_TYPE_NOT_IN: - case OP_TYPE_LIKE: - case OP_TYPE_NOT_LIKE: - case OP_TYPE_MATCH: - case OP_TYPE_NMATCH: - case OP_TYPE_JSON_GET_VALUE: - case OP_TYPE_JSON_CONTAINS: - default: - break; - } - return " unknown operator "; - } - - void nodeToSql(const SNode* node, string& sql) { - if (nullptr == node) { - return; - } - - switch (nodeType(node)) { - case QUERY_NODE_COLUMN: { - SColumnNode* pCol = (SColumnNode*)node; - if ('\0' != pCol->dbName[0]) { - sql.append(pCol->dbName); - sql.append("."); - } - if ('\0' != pCol->tableAlias[0]) { - sql.append(pCol->tableAlias); - sql.append("."); - } - sql.append(pCol->colName); - break; - } - case QUERY_NODE_VALUE: - break; - case QUERY_NODE_OPERATOR: { - SOperatorNode* pOp = (SOperatorNode*)node; - nodeToSql(pOp->pLeft, sql); - sql.append(opTypeToStr(pOp->opType)); - nodeToSql(pOp->pRight, sql); - break; - } - default: - break; - } - } - - void nodeListToSql(const SNodeList* nodelist, string& sql, const string& seq = ",") { - SNode* node = nullptr; - bool firstNode = true; - FOREACH(node, nodelist) { - if (!firstNode) { - sql.append(", "); - } - firstNode = false; - nodeToSql(node, sql); - } - } - - void reset() { - memset(&cxt_, 0, sizeof(cxt_)); - memset(errMagBuf_, 0, max_err_len); - cxt_.pMsg = errMagBuf_; - cxt_.msgLen = max_err_len; - } - - string acctId_; - string db_; - char errMagBuf_[max_err_len]; - string sqlBuf_; - SParseContext cxt_; - SQuery query_; -}; - -TEST_F(NewParserTest, selectSimple) { - setDatabase("root", "test"); - - bind("SELECT * FROM t1"); - ASSERT_TRUE(run()); - - bind("SELECT * FROM test.t1"); - ASSERT_TRUE(run()); - - bind("SELECT ts, c1 FROM t1"); - ASSERT_TRUE(run()); - - bind("SELECT ts, t.c1 FROM (SELECT * FROM t1) t"); - ASSERT_TRUE(run()); - - bind("SELECT * FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1"); - ASSERT_TRUE(run()); -} - -TEST_F(NewParserTest, selectConstant) { - setDatabase("root", "test"); - - bind("SELECT 123, 20.4, 'abc', \"wxy\", TIMESTAMP '2022-02-09 17:30:20', true, false, 10s FROM t1"); - ASSERT_TRUE(run()); - - bind("SELECT 1234567890123456789012345678901234567890, 20.1234567890123456789012345678901234567890, 'abc', \"wxy\", TIMESTAMP '2022-02-09 17:30:20', true, false, 15s FROM t1"); - ASSERT_TRUE(run()); -} - -TEST_F(NewParserTest, selectExpression) { - setDatabase("root", "test"); - - bind("SELECT ts + 10s, c1 + 10, concat(c2, 'abc') FROM t1"); - ASSERT_TRUE(run()); - - bind("SELECT ts > 0, c1 < 20 AND c2 = 'qaz' FROM t1"); - ASSERT_TRUE(run()); - - bind("SELECT ts > 0, c1 BETWEEN 10 AND 20 AND c2 = 'qaz' FROM t1"); - ASSERT_TRUE(run()); -} - -TEST_F(NewParserTest, selectClause) { - setDatabase("root", "test"); - - // GROUP BY clause - bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0"); - ASSERT_TRUE(run()); - - bind("SELECT count(*), c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2"); - ASSERT_TRUE(run()); - - bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 HAVING count(c1) > 10"); - ASSERT_TRUE(run()); - - bind("SELECT count(*), c1, c2 + 10, c1 + c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2, c1"); - ASSERT_TRUE(run()); - - bind("SELECT count(*), c1 + 10, c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c1 + 10, c2"); - ASSERT_TRUE(run()); - - // ORDER BY clause - bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 ORDER BY cnt"); - ASSERT_TRUE(run()); - - bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 ORDER BY 1"); - ASSERT_TRUE(run()); - - // DISTINCT clause - bind("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 0 ORDER BY c1"); - ASSERT_TRUE(run()); - - bind("SELECT DISTINCT c1 + 10, c2 FROM t1 WHERE c1 > 0 ORDER BY c1 + 10, c2"); - ASSERT_TRUE(run()); - - bind("SELECT DISTINCT c1 + 10 cc1, c2 cc2 FROM t1 WHERE c1 > 0 ORDER BY cc1, c2"); - ASSERT_TRUE(run()); - - bind("SELECT DISTINCT count(c2) FROM t1 WHERE c1 > 0 GROUP BY c1 ORDER BY count(c2)"); - ASSERT_TRUE(run()); -} - -TEST_F(NewParserTest, selectSyntaxError) { - setDatabase("root", "test"); - - bind("SELECTT * FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_FAILED)); - - bind("SELECT *"); - ASSERT_TRUE(run(TSDB_CODE_FAILED)); - - bind("SELECT *, * FROM test.t1"); - ASSERT_TRUE(run(TSDB_CODE_FAILED)); - - bind("SELECT * FROM test.t1 t WHER"); - ASSERT_TRUE(run(TSDB_CODE_FAILED)); -} - -TEST_F(NewParserTest, selectSemanticError) { - setDatabase("root", "test"); - - // TSDB_CODE_PAR_INVALID_COLUMN - bind("SELECT c1, c3 FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_COLUMN)); - - bind("SELECT t1.c1, t1.c3 FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_COLUMN)); - - // TSDB_CODE_PAR_TABLE_NOT_EXIST - bind("SELECT * FROM t10"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST)); - - bind("SELECT * FROM test.t10"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST)); - - bind("SELECT t2.c1 FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST)); - - // TSDB_CODE_PAR_AMBIGUOUS_COLUMN - bind("SELECT c2 FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_AMBIGUOUS_COLUMN)); - - // TSDB_CODE_PAR_WRONG_VALUE_TYPE - bind("SELECT 10n FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_VALUE_TYPE)); - - bind("SELECT TIMESTAMP '2010' FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_VALUE_TYPE)); - - // TSDB_CODE_PAR_INVALID_FUNTION - bind("SELECT cnt(*) FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_FUNTION)); - - // TSDB_CODE_PAR_FUNTION_PARA_NUM - // TSDB_CODE_PAR_FUNTION_PARA_TYPE - - // TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION - bind("SELECT c2 FROM t1 tt1 JOIN t1 tt2 ON count(*) > 0"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION)); - - bind("SELECT c2 FROM t1 where count(*) > 0"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION)); - - bind("SELECT c2 FROM t1 GROUP BY count(*)"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION)); - - // TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT - bind("SELECT c2 FROM t1 ORDER BY 0"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT)); - - bind("SELECT c2 FROM t1 ORDER BY 2"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT)); - - // TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION - bind("SELECT count(*) cnt FROM t1 HAVING c1 > 0"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); - - bind("SELECT count(*) cnt FROM t1 GROUP BY c2 HAVING c1 > 0"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); - - bind("SELECT count(*), c1 cnt FROM t1 GROUP BY c2 HAVING c2 > 0"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); - - bind("SELECT count(*) cnt FROM t1 GROUP BY c2 HAVING c2 > 0 ORDER BY c1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); - - // TSDB_CODE_PAR_NOT_SINGLE_GROUP - bind("SELECT count(*), c1 FROM t1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP)); - - bind("SELECT count(*) FROM t1 ORDER BY c1"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP)); - - bind("SELECT c1 FROM t1 ORDER BY count(*)"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP)); - - // TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION - bind("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 0 ORDER BY ts"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION)); - - bind("SELECT DISTINCT c1 FROM t1 WHERE c1 > 0 ORDER BY count(c2)"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION)); - - bind("SELECT DISTINCT c2 FROM t1 WHERE c1 > 0 ORDER BY count(c2)"); - ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION)); -} diff --git a/source/libs/parser/test/parserAstTest.cpp b/source/libs/parser/test/parserAstTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d30c21cc2113355e3671d8e53ad0b1aece63454e --- /dev/null +++ b/source/libs/parser/test/parserAstTest.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include +#include + +#include + +#include "parInt.h" + +using namespace std; +using namespace testing; + +class ParserTest : public Test { +protected: + void setDatabase(const string& acctId, const string& db) { + acctId_ = acctId; + db_ = db; + } + + void bind(const char* sql) { + reset(); + cxt_.acctId = atoi(acctId_.c_str()); + cxt_.db = db_.c_str(); + sqlBuf_ = string(sql); + transform(sqlBuf_.begin(), sqlBuf_.end(), sqlBuf_.begin(), ::tolower); + cxt_.sqlLen = strlen(sql); + cxt_.pSql = sqlBuf_.c_str(); + } + + bool run(int32_t parseCode = TSDB_CODE_SUCCESS, int32_t translateCode = TSDB_CODE_SUCCESS) { + query_ = nullptr; + bool res = runImpl(parseCode, translateCode); + qDestroyQuery(query_); + return res; + } + +private: + static const int max_err_len = 1024; + + bool runImpl(int32_t parseCode, int32_t translateCode) { + int32_t code = doParse(&cxt_, &query_); + if (code != TSDB_CODE_SUCCESS) { + cout << "sql:[" << cxt_.pSql << "] parser code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl; + return (TSDB_CODE_SUCCESS != parseCode); + } + if (TSDB_CODE_SUCCESS != parseCode) { + return false; + } + string parserStr = toString(query_->pRoot); + code = doTranslate(&cxt_, query_); + if (code != TSDB_CODE_SUCCESS) { + cout << "sql:[" << cxt_.pSql << "] translate code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl; + return (code == translateCode); + } + cout << "input sql : [" << cxt_.pSql << "]" << endl; + cout << "parser output: " << endl; + cout << parserStr << endl; + cout << "translate output: " << endl; + cout << toString(query_->pRoot) << endl; + return (TSDB_CODE_SUCCESS == translateCode); + } + + string toString(const SNode* pRoot, bool format = false) { + char* pStr = NULL; + int32_t len = 0; + int32_t code = nodesNodeToString(pRoot, format, &pStr, &len); + if (code != TSDB_CODE_SUCCESS) { + cout << "sql:[" << cxt_.pSql << "] toString code:" << code << ", strerror:" << tstrerror(code) << endl; + throw "nodesNodeToString failed!"; + } + string str(pStr); + tfree(pStr); + return str; + } + + void reset() { + memset(&cxt_, 0, sizeof(cxt_)); + memset(errMagBuf_, 0, max_err_len); + cxt_.pMsg = errMagBuf_; + cxt_.msgLen = max_err_len; + } + + string acctId_; + string db_; + char errMagBuf_[max_err_len]; + string sqlBuf_; + SParseContext cxt_; + SQuery* query_; +}; + +TEST_F(ParserTest, selectSimple) { + setDatabase("root", "test"); + + bind("SELECT * FROM t1"); + ASSERT_TRUE(run()); + + bind("SELECT * FROM test.t1"); + ASSERT_TRUE(run()); + + bind("SELECT ts, c1 FROM t1"); + ASSERT_TRUE(run()); + + bind("SELECT ts, t.c1 FROM (SELECT * FROM t1) t"); + ASSERT_TRUE(run()); + + bind("SELECT * FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, selectConstant) { + setDatabase("root", "test"); + + bind("SELECT 123, 20.4, 'abc', \"wxy\", TIMESTAMP '2022-02-09 17:30:20', true, false, 10s FROM t1"); + ASSERT_TRUE(run()); + + bind("SELECT 1234567890123456789012345678901234567890, 20.1234567890123456789012345678901234567890, 'abc', \"wxy\", TIMESTAMP '2022-02-09 17:30:20', true, false, 15s FROM t1"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, selectExpression) { + setDatabase("root", "test"); + + bind("SELECT ts + 10s, c1 + 10, concat(c2, 'abc') FROM t1"); + ASSERT_TRUE(run()); + + bind("SELECT ts > 0, c1 < 20 AND c2 = 'qaz' FROM t1"); + ASSERT_TRUE(run()); + + bind("SELECT ts > 0, c1 BETWEEN 10 AND 20 AND c2 = 'qaz' FROM t1"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, selectClause) { + setDatabase("root", "test"); + + // GROUP BY clause + bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0"); + ASSERT_TRUE(run()); + + bind("SELECT count(*), c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2"); + ASSERT_TRUE(run()); + + bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 HAVING count(c1) > 10"); + ASSERT_TRUE(run()); + + bind("SELECT count(*), c1, c2 + 10, c1 + c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2, c1"); + ASSERT_TRUE(run()); + + bind("SELECT count(*), c1 + 10, c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c1 + 10, c2"); + ASSERT_TRUE(run()); + + // ORDER BY clause + bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 ORDER BY cnt"); + ASSERT_TRUE(run()); + + bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 ORDER BY 1"); + ASSERT_TRUE(run()); + + // DISTINCT clause + bind("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 0 ORDER BY c1"); + ASSERT_TRUE(run()); + + bind("SELECT DISTINCT c1 + 10, c2 FROM t1 WHERE c1 > 0 ORDER BY c1 + 10, c2"); + ASSERT_TRUE(run()); + + bind("SELECT DISTINCT c1 + 10 cc1, c2 cc2 FROM t1 WHERE c1 > 0 ORDER BY cc1, c2"); + ASSERT_TRUE(run()); + + bind("SELECT DISTINCT count(c2) FROM t1 WHERE c1 > 0 GROUP BY c1 ORDER BY count(c2)"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, selectWindow) { + setDatabase("root", "test"); + + bind("SELECT count(*) FROM t1 interval(10s)"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, selectSyntaxError) { + setDatabase("root", "test"); + + bind("SELECTT * FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_FAILED)); + + bind("SELECT *"); + ASSERT_TRUE(run(TSDB_CODE_FAILED)); + + bind("SELECT *, * FROM test.t1"); + ASSERT_TRUE(run(TSDB_CODE_FAILED)); + + bind("SELECT * FROM test.t1 t WHER"); + ASSERT_TRUE(run(TSDB_CODE_FAILED)); +} + +TEST_F(ParserTest, selectSemanticError) { + setDatabase("root", "test"); + + // TSDB_CODE_PAR_INVALID_COLUMN + bind("SELECT c1, cc1 FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_COLUMN)); + + bind("SELECT t1.c1, t1.cc1 FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_COLUMN)); + + // TSDB_CODE_PAR_TABLE_NOT_EXIST + bind("SELECT * FROM t10"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST)); + + bind("SELECT * FROM test.t10"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST)); + + bind("SELECT t2.c1 FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST)); + + // TSDB_CODE_PAR_AMBIGUOUS_COLUMN + bind("SELECT c2 FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_AMBIGUOUS_COLUMN)); + + // TSDB_CODE_PAR_WRONG_VALUE_TYPE + bind("SELECT 10n FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_VALUE_TYPE)); + + bind("SELECT TIMESTAMP '2010' FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_VALUE_TYPE)); + + // TSDB_CODE_PAR_INVALID_FUNTION + bind("SELECT cnt(*) FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_FUNTION)); + + // TSDB_CODE_PAR_FUNTION_PARA_NUM + // TSDB_CODE_PAR_FUNTION_PARA_TYPE + + // TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION + bind("SELECT c2 FROM t1 tt1 JOIN t1 tt2 ON count(*) > 0"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION)); + + bind("SELECT c2 FROM t1 where count(*) > 0"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION)); + + bind("SELECT c2 FROM t1 GROUP BY count(*)"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION)); + + // TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT + bind("SELECT c2 FROM t1 ORDER BY 0"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT)); + + bind("SELECT c2 FROM t1 ORDER BY 2"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT)); + + // TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION + bind("SELECT count(*) cnt FROM t1 HAVING c1 > 0"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); + + bind("SELECT count(*) cnt FROM t1 GROUP BY c2 HAVING c1 > 0"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); + + bind("SELECT count(*), c1 cnt FROM t1 GROUP BY c2 HAVING c2 > 0"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); + + bind("SELECT count(*) cnt FROM t1 GROUP BY c2 HAVING c2 > 0 ORDER BY c1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION)); + + // TSDB_CODE_PAR_NOT_SINGLE_GROUP + bind("SELECT count(*), c1 FROM t1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP)); + + bind("SELECT count(*) FROM t1 ORDER BY c1"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP)); + + bind("SELECT c1 FROM t1 ORDER BY count(*)"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP)); + + // TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION + bind("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 0 ORDER BY ts"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION)); + + bind("SELECT DISTINCT c1 FROM t1 WHERE c1 > 0 ORDER BY count(c2)"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION)); + + bind("SELECT DISTINCT c2 FROM t1 WHERE c1 > 0 ORDER BY count(c2)"); + ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION)); +} + +TEST_F(ParserTest, createUser) { + setDatabase("root", "test"); + + bind("create user wxy pass '123456'"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, createDnode) { + setDatabase("root", "test"); + + bind("create dnode abc1 port 7000"); + ASSERT_TRUE(run()); + + bind("create dnode 1.1.1.1 port 9000"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, createDatabase) { + setDatabase("root", "test"); + + bind("create database wxy_db"); + ASSERT_TRUE(run()); + + bind("create database if not exists wxy_db " + "BLOCKS 100 " + "CACHE 100 " + "CACHELAST 2 " + "COMP 1 " + "DAYS 100 " + "FSYNC 100 " + "MAXROWS 1000 " + "MINROWS 100 " + "KEEP 100 " + "PRECISION 'ms' " + "QUORUM 1 " + "REPLICA 3 " + "TTL 100 " + "WAL 2 " + "VGROUPS 100 " + "SINGLE_STABLE 0 " + "STREAM_MODE 1 " + ); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, showDatabase) { + setDatabase("root", "test"); + + bind("show databases"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, useDatabase) { + setDatabase("root", "test"); + + bind("use wxy_db"); + ASSERT_TRUE(run()); +} + +TEST_F(ParserTest, createTable) { + setDatabase("root", "test"); + + bind("create table t1(ts timestamp, c1 int)"); + ASSERT_TRUE(run()); + + bind("create table if not exists test.t1(" + "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 SMALLINT, " + "c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), c14 JSON, c15 VARCHAR(50)) " + "KEEP 100 TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)" + ); + ASSERT_TRUE(run()); + + bind("create table if not exists test.t1(" + "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 SMALLINT, " + "c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), c14 JSON, c15 VARCHAR(50)) " + "TAGS (tsa TIMESTAMP, a1 INT, a2 INT UNSIGNED, a3 BIGINT, a4 BIGINT UNSIGNED, a5 FLOAT, a6 DOUBLE, a7 BINARY(20), a8 SMALLINT, " + "a9 SMALLINT UNSIGNED COMMENT 'test column comment', a10 TINYINT, a11 TINYINT UNSIGNED, a12 BOOL, a13 NCHAR(30), a14 JSON, a15 VARCHAR(50)) " + "KEEP 100 TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)" + ); + ASSERT_TRUE(run()); + + bind("create table if not exists t1 using st1 tags(1, 'wxy')"); + ASSERT_TRUE(run()); + + bind("create table " + "if not exists test.t1 using test.st1 (tag1, tag2) tags(1, 'abc') " + "if not exists test.t2 using test.st1 (tag1, tag2) tags(2, 'abc') " + "if not exists test.t3 using test.st1 (tag1, tag2) tags(3, 'abc')" + ); + ASSERT_TRUE(run()); + + bind("create stable t1(ts timestamp, c1 int) TAGS(id int)"); + ASSERT_TRUE(run()); + + bind("create stable if not exists test.t1(" + "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 SMALLINT, " + "c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), c14 JSON, c15 VARCHAR(50)) " + "TAGS (tsa TIMESTAMP, a1 INT, a2 INT UNSIGNED, a3 BIGINT, a4 BIGINT UNSIGNED, a5 FLOAT, a6 DOUBLE, a7 BINARY(20), a8 SMALLINT, " + "a9 SMALLINT UNSIGNED COMMENT 'test column comment', a10 TINYINT, a11 TINYINT UNSIGNED, a12 BOOL, a13 NCHAR(30), a14 JSON, a15 VARCHAR(50)) " + "KEEP 100 TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)" + ); + ASSERT_TRUE(run()); +} diff --git a/source/libs/parser/test/insertParserTest.cpp b/source/libs/parser/test/parserInsertTest.cpp similarity index 85% rename from source/libs/parser/test/insertParserTest.cpp rename to source/libs/parser/test/parserInsertTest.cpp index b6992e51571f9fb31469cf320502288dcf48f305..3d4a6e0eb86b0901b555aae3e21e668ccfcd30ce 100644 --- a/source/libs/parser/test/insertParserTest.cpp +++ b/source/libs/parser/test/parserInsertTest.cpp @@ -15,8 +15,7 @@ #include -#include "insertParser.h" -// #include "mockCatalog.h" +#include "parInt.h" using namespace std; using namespace testing; @@ -60,15 +59,12 @@ protected: return code_; } - SVnodeModifOpStmtInfo* reslut() { - return res_; - } - void dumpReslut() { - size_t num = taosArrayGetSize(res_->pDataBlocks); - cout << "schemaAttache:" << (int32_t)res_->schemaAttache << ", payloadType:" << (int32_t)res_->payloadType << ", insertType:" << res_->insertType << ", numOfVgs:" << num << endl; + SVnodeModifOpStmt* pStmt = getVnodeModifStmt(res_); + size_t num = taosArrayGetSize(pStmt->pDataBlocks); + cout << "schemaAttache:" << (int32_t)pStmt->schemaAttache << ", payloadType:" << (int32_t)pStmt->payloadType << ", insertType:" << pStmt->insertType << ", numOfVgs:" << num << endl; for (size_t i = 0; i < num; ++i) { - SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(res_->pDataBlocks, i); + SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, i); cout << "vgId:" << vg->vg.vgId << ", numOfTables:" << vg->numOfTables << ", dataSize:" << vg->size << endl; SSubmitReq* submit = (SSubmitReq*)vg->pData; cout << "length:" << ntohl(submit->length) << ", numOfBlocks:" << ntohl(submit->numOfBlocks) << endl; @@ -84,13 +80,14 @@ protected: } void checkReslut(int32_t numOfTables, int16_t numOfRows1, int16_t numOfRows2 = -1) { - ASSERT_EQ(res_->schemaAttache, 0); - ASSERT_EQ(res_->payloadType, PAYLOAD_TYPE_KV); - ASSERT_EQ(res_->insertType, TSDB_QUERY_TYPE_INSERT); - size_t num = taosArrayGetSize(res_->pDataBlocks); + SVnodeModifOpStmt* pStmt = getVnodeModifStmt(res_); + ASSERT_EQ(pStmt->schemaAttache, 0); + ASSERT_EQ(pStmt->payloadType, PAYLOAD_TYPE_KV); + ASSERT_EQ(pStmt->insertType, TSDB_QUERY_TYPE_INSERT); + size_t num = taosArrayGetSize(pStmt->pDataBlocks); ASSERT_GE(num, 0); for (size_t i = 0; i < num; ++i) { - SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(res_->pDataBlocks, i); + SVgDataBlocks* vg = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, i); ASSERT_EQ(vg->numOfTables, numOfTables); ASSERT_GE(vg->size, 0); SSubmitReq* submit = (SSubmitReq*)vg->pData; @@ -115,7 +112,10 @@ private: cxt_.pMsg = errMagBuf_; cxt_.msgLen = max_err_len; code_ = TSDB_CODE_SUCCESS; - res_ = nullptr; + } + + SVnodeModifOpStmt* getVnodeModifStmt(SQuery* pQuery) { + return (SVnodeModifOpStmt*)pQuery->pRoot; } string acctId_; @@ -124,7 +124,7 @@ private: char sqlBuf_[max_sql_len]; SParseContext cxt_; int32_t code_; - SVnodeModifOpStmtInfo* res_; + SQuery* res_; }; // INSERT INTO tb_name VALUES (field1_value, ...) diff --git a/source/libs/parser/test/parserTestMain.cpp b/source/libs/parser/test/parserTestMain.cpp index 7de2cb66c202324d1bef2bf3cd47d00eae8feefa..9a9711ca9678a84ff66c50acdb257a7b8c06bf39 100644 --- a/source/libs/parser/test/parserTestMain.cpp +++ b/source/libs/parser/test/parserTestMain.cpp @@ -18,6 +18,8 @@ #include #include "mockCatalog.h" +#include "parToken.h" +#include "functionMgt.h" class ParserEnv : public testing::Environment { public: @@ -28,6 +30,8 @@ public: virtual void TearDown() { destroyMetaDataEnv(); + taosCleanupKeywordsTable(); + fmFuncMgtDestroy(); } ParserEnv() {} diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp deleted file mode 100644 index b80efe09edaf55af42d69ab874d768005b2a8fa3..0000000000000000000000000000000000000000 --- a/source/libs/parser/test/parserTests.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wwrite-strings" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wsign-compare" -#include "os.h" - -#include "function.h" -#include "tglobal.h" -#include "astGenerator.h" -#include "parserInt.h" -#include "taos.h" -#include "tdef.h" -#include "tvariant.h" -#include "parserUtil.h" - -namespace { -void setSchema(SSchema* p, int32_t type, int32_t bytes, const char* name, int32_t colId) { - p->colId = colId; - p->bytes = bytes; - p->type = type; - strcpy(p->name, name); -} - -void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SCatalogReq* req) { - pQueryInfo->numOfTables = 1; - - pQueryInfo->pTableMetaInfo = (STableMetaInfo**)calloc(1, POINTER_BYTES); - STableMetaInfo* pTableMetaInfo = (STableMetaInfo*)calloc(1, sizeof(STableMetaInfo)); - pQueryInfo->pTableMetaInfo[0] = pTableMetaInfo; - - SName* name = (SName*)taosArrayGet(req->pTableName, 0); - - memcpy(&pTableMetaInfo->name, taosArrayGet(req->pTableName, 0), sizeof(SName)); - pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 6 * sizeof(SSchema)); - strcpy(pTableMetaInfo->aliasName, name->tname); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - pTableMeta->tableType = TSDB_NORMAL_TABLE; - pTableMeta->tableInfo.numOfColumns = 6; - pTableMeta->tableInfo.rowSize = 28; - pTableMeta->uid = 110; - - pTableMetaInfo->tagColList = (SArray*)taosArrayInit(4, POINTER_BYTES); - - SSchema* pSchema = pTableMetaInfo->pTableMeta->schema; - setSchema(&pSchema[0], TSDB_DATA_TYPE_TIMESTAMP, 8, "ts", 0); - setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1); - setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2); - setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3); - setSchema(&pSchema[4], TSDB_DATA_TYPE_BINARY, 12, "c", 4); - setSchema(&pSchema[5], TSDB_DATA_TYPE_BINARY, 44, "d", 5); -} - -void sqlCheck(const char* sql, bool valid) { - SSqlInfo info1 = doGenerateAST(sql); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - - if (valid) { - ASSERT_EQ(ret, 0); - } else { - ASSERT_NE(ret, 0); - } - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -} // namespace - -TEST(testCase, validateAST_test) { - SSqlInfo info1 = doGenerateAST("select a a1111, a+b + 22, tbname from `t.1abc` where tsexprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 3); - - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_INT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1111"); - ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a"); - ASSERT_EQ(p1->base.pColumns->info.colId, 1); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "a1111"); - - ASSERT_EQ(taosArrayGetSize(pExprList), 3); - - SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, 1); - ASSERT_EQ(p2->base.pColumns->uid, 110); - ASSERT_EQ(p2->base.numOfParams, 1); // it is the serialized binary string of expression. - ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p2->base.resSchema.name, "a+b + 22"); - - // ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a"); - // ASSERT_EQ(p1->base.colInfo.colId, 1); - // ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p2->base.token, "a+b + 22"); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 3); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test) { - SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a)"); - ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a"); - ASSERT_EQ(p1->base.pColumns->info.colId, 1); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "count(a)"); - ASSERT_EQ(p1->base.interBytes, 8); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test2) { - SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "abc"); - ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a"); - ASSERT_EQ(p1->base.pColumns->info.colId, 1); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "count(a)"); - ASSERT_EQ(p1->base.interBytes, 8); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test3) { - SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 6); - - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_TIMESTAMP); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)"); - ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.ts"); - ASSERT_EQ(p1->base.pColumns->info.colId, 0); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "first(ts)"); - ASSERT_EQ(p1->base.interBytes, 24); - - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 6); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test4) { - SSqlInfo info1 = doGenerateAST("select block_dist() as a1 from `t.1abc`"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); - // ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts"); - // ASSERT_EQ(p1->base.colInfo.colId, 0); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_UDC); - ASSERT_STRCASEEQ(p1->base.token, "block_dist()"); - ASSERT_EQ(p1->base.interBytes, 0); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test5) { - // todo select concat(concat(a, b), concat(b, a)) from `t.1abc`; - - SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.numOfCols, 2); - ASSERT_EQ(p1->base.pColumns->uid, 110); - - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); - - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP); - ASSERT_STREQ(p1->base.pColumns->name, "sum(a)"); - ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)"); - ASSERT_EQ(p1->base.interBytes, 0); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test10) { - sqlCheck("select c from `t.1abc`", true); - sqlCheck("select length(c) from `t.1abc`", true); - sqlCheck("select length(sum(col)) from `t.1abc`", true); - sqlCheck("select sum(length(a+b)) from `t.1abc`", true); - sqlCheck("select sum(sum(a+b)) from `t.1abc`", false); - sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true); - sqlCheck("select length(sum(a) + sum(b)) + length(sum(a) + sum(b)) from `t.1abc`", true); - sqlCheck("select sum(length(sum(a))) from `t.1abc`", true); - sqlCheck("select cov(a, b) from `t.1abc`", true); - sqlCheck("select sum(length(a) + count(b)) from `t.1abc`", false); - - sqlCheck("select concat(sum(a), count(b)) from `t.1abc`", true); - - sqlCheck("select concat(concat(a,b), concat(a,b)) from `t.1abc`", true); - sqlCheck("select length(length(length(a))) from `t.1abc`", true); - sqlCheck("select count() from `t.1abc`", false); - sqlCheck("select block_dist() from `t.1abc`", true); - sqlCheck("select block_dist(a) from `t.1abc`", false); - sqlCheck("select count(*) from `t.1abc` interval(1s) group by a", false); - - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// - sqlCheck("select length119(a,b) from `t.1abc`", false); - sqlCheck("select length(a, b) from `t.1abc`", false); - sqlCheck("select block_dist() + 20 from `t.1abc`", true); - sqlCheck("select count(b), c from `t.1abc`", false); - sqlCheck("select top(a, 20), count(b) from `t.1abc`", false); - sqlCheck("select top(a, 20), b from `t.1abc`", false); - sqlCheck("select top(a, 20), a+20 from `t.1abc`", true); -// sqlCheck("select top(a, 20), bottom(a, 10) from `t.1abc`", false); -// sqlCheck("select last_row(*), count(b) from `t.1abc`", false); -// sqlCheck("select last_row(a, b) + 20 from `t.1abc`", false); -// sqlCheck("select last_row(count(*)) from `t.1abc`", false); -} - -TEST(testCase, function_Test6) { - SSqlInfo info1 = doGenerateAST( - "select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList[0]; - if (tsCompatibleModel) { - ASSERT_EQ(taosArrayGetSize(pExprList), 6); - } else { - ASSERT_EQ(taosArrayGetSize(pExprList), 5); - } - - int32_t index = tsCompatibleModel? 1:0; - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, index); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP); - ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)"); - ASSERT_EQ(p1->base.interBytes, 16); - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE); - ASSERT_STRCASEEQ(p1->pExpr->_function.functionName, "sum"); - ASSERT_EQ(p1->pExpr->_function.num, 1); - - tExprNode* pParam = p1->pExpr->_function.pChild[0]; - - ASSERT_EQ(pParam->nodeType, TEXPR_COL_NODE); - ASSERT_STREQ(pParam->pSchema->name, "t.1abc.a+b"); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - - int32_t numOfResCol = tsCompatibleModel? 6:5; - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfResCol); - - index = tsCompatibleModel? 2:1; - SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, index); - ASSERT_EQ(p2->base.pColumns->uid, 110); - ASSERT_EQ(p2->base.numOfParams, 0); - ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)"); - - ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_TMP); - ASSERT_STREQ(p2->base.pColumns->name, "t.1abc.b*a"); - - ASSERT_STRCASEEQ(p2->base.token, "first(b*a)"); - ASSERT_EQ(p2->base.interBytes, 24); - ASSERT_EQ(p2->pExpr->nodeType, TEXPR_FUNCTION_NODE); - ASSERT_STRCASEEQ(p2->pExpr->_function.functionName, "first"); - ASSERT_EQ(p2->pExpr->_function.num, 1); - ASSERT_EQ(p2->pExpr->_function.pChild[0]->nodeType, TEXPR_COL_NODE); - ASSERT_STREQ(p2->pExpr->_function.pChild[0]->pSchema->name, "t.1abc.b*a"); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - - TEST(testCase, function_Test7) { - SSqlInfo info1 = doGenerateAST("select count(a+b),count(1) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 3); - - int32_t index = tsCompatibleModel? 1:0; - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, index); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a+b)"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP); - ASSERT_STRCASEEQ(p1->base.token, "count(a+b)"); - ASSERT_EQ(p1->base.interBytes, 8); - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE); - ASSERT_STREQ(p1->pExpr->_function.functionName, "count"); - - tExprNode* pParam = p1->pExpr->_function.pChild[0]; - ASSERT_EQ(pParam->nodeType, TEXPR_COL_NODE); - - SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pQueryInfo->exprList[1], 0); - ASSERT_EQ(p2->pExpr->nodeType, TEXPR_BINARYEXPR_NODE); - - ASSERT_EQ(p2->pExpr->_node.optr, OP_TYPE_ADD); - ASSERT_EQ(p2->pExpr->_node.pLeft->nodeType, TEXPR_COL_NODE); - ASSERT_EQ(p2->pExpr->_node.pRight->nodeType, TEXPR_COL_NODE); - - ASSERT_EQ(pParam->pSchema->colId, p2->base.resSchema.colId); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - - int32_t numOfCols = tsCompatibleModel? 3:2; - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfCols); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - - TEST(testCase, function_Test8) { - SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 2); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP); - ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.interBytes, 16); - - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE); - ASSERT_STRCASEEQ(p1->pExpr->_function.functionName, "top"); - ASSERT_TRUE(p1->pExpr->_function.num == 1); - - tExprNode* pParam = p1->pExpr->_function.pChild[0]; - - ASSERT_EQ(pParam->nodeType, TSDB_COL_TMP); -// ASSERT_EQ(pParam->.optr, TSDB_BINARY_OP_DIVIDE); -// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE); -// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - info1 = doGenerateAST("select sum(length(a)+length(b)) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - - TEST(testCase, invalid_sql_Test) { - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlInfo info1 = doGenerateAST("select count(k) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - ctx.db = "db1"; - ctx.acctId = 1; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_NE(ret, 0); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -//=============================================================================================================== - info1 = doGenerateAST("select top(a*b, ABC) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_NE(ret, 0); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, show_user_Test) { - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - char sql1[] = "show users"; - SSqlInfo info1 = doGenerateAST(sql1); - ASSERT_EQ(info1.valid, true); - - SParseContext ct= {.requestId = 1, .acctId = 1, .db = "abc", .pTransporter = NULL}; - SDclStmtInfo* output = qParserValidateDclSqlNode(&info1, &ct, msg, buf.len); - ASSERT_NE(output, nullptr); - - // convert the show command to be the select query - // select name, privilege, create_time, account from information_schema.users; -} - -TEST(testCase, create_user_Test) { - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - char sql[] = {"create user abc pass 'abc'"}; - - SSqlInfo info1 = doGenerateAST(sql); - ASSERT_EQ(info1.valid, true); - ASSERT_EQ(isDclSqlStatement(&info1), true); - - SParseContext ct= {.requestId = 1, .acctId = 1, .db = "abc"}; - SDclStmtInfo* output = qParserValidateDclSqlNode(&info1, &ct, msg, buf.len); - ASSERT_NE(output, nullptr); - - destroySqlInfo(&info1); -} - -#pragma GCC diagnostic pop \ No newline at end of file diff --git a/source/libs/parser/test/plannerTest.cpp b/source/libs/parser/test/plannerTest.cpp deleted file mode 100644 index 095e2f4f973c7c45b71541bcbbdc0ad4f4f9029d..0000000000000000000000000000000000000000 --- a/source/libs/parser/test/plannerTest.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wwrite-strings" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wsign-compare" -#include "os.h" - -#include "function.h" -#include "astGenerator.h" -#include "parserInt.h" -#include "taos.h" -#include "tdef.h" -#include "tvariant.h" -#include "planner.h" -#include "../../planner/inc/plannerInt.h" - -namespace { -void setSchema(SSchema* p, int32_t type, int32_t bytes, const char* name, int32_t colId) { - p->colId = colId; - p->bytes = bytes; - p->type = type; - strcpy(p->name, name); -} - -void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SCatalogReq *req) { - pQueryInfo->numOfTables = 1; - - pQueryInfo->pTableMetaInfo = (STableMetaInfo**)calloc(1, POINTER_BYTES); - STableMetaInfo* pTableMetaInfo = (STableMetaInfo*)calloc(1, sizeof(STableMetaInfo)); - pQueryInfo->pTableMetaInfo[0] = pTableMetaInfo; - - SName* name = (SName*)taosArrayGet(req->pTableName, 0); - - memcpy(&pTableMetaInfo->name, taosArrayGet(req->pTableName, 0), sizeof(SName)); - pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 4 * sizeof(SSchema)); - strcpy(pTableMetaInfo->aliasName, name->tname); - STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; - pTableMeta->tableType = TSDB_NORMAL_TABLE; - pTableMeta->tableInfo.numOfColumns = 4; - pTableMeta->tableInfo.rowSize = 28; - pTableMeta->uid = 110; - - pTableMetaInfo->tagColList = (SArray*) taosArrayInit(4, POINTER_BYTES); - - SSchema* pSchema = pTableMetaInfo->pTableMeta->schema; - setSchema(&pSchema[0], TSDB_DATA_TYPE_TIMESTAMP, 8, "ts", 0); - setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1); - setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2); - setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3); -} - -void generateLogicplan(const char* sql) { - SSqlInfo info1 = doGenerateAST(sql); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - struct SQueryPlanNode* n = nullptr; - code = createQueryPlan((const SQueryNode*)pQueryInfo, &n); - - char* str = NULL; - queryPlanToString(n, &str); - - printf("--------SQL:%s\n", sql); - printf("%s\n", str); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} -} - -TEST(testCase, planner_test) { - SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.sub.node), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SCatalogReq req = {0}; - SParseContext ctx = {0}; - - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, &ctx, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.sub.node, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList[0]; - - int32_t num = tsCompatibleModel? 2:1; - ASSERT_EQ(taosArrayGetSize(pExprList), num); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_TMP); - ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.interBytes, 16); - - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE); - ASSERT_STREQ(p1->pExpr->_function.functionName, "top"); - - tExprNode* pParam = p1->pExpr->_function.pChild[0]; - - ASSERT_EQ(pParam->nodeType, TEXPR_COL_NODE); - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); - - struct SQueryPlanNode* n = nullptr; - code = createQueryPlan((const SQueryNode*)pQueryInfo, &n); - - char* str = NULL; - queryPlanToString(n, &str); - printf("%s\n", str); - - destroyQueryInfo(pQueryInfo); - qParserCleanupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, displayPlan) { - generateLogicplan("select count(*) from `t.1abc`"); - generateLogicplan("select count(*)+ 22 from `t.1abc`"); - generateLogicplan("select count(*)+ 22 from `t.1abc` interval(1h, 20s) sliding(10m) limit 20,30"); - generateLogicplan("select count(*) from `t.1abc` group by a"); - generateLogicplan("select count(A+B) from `t.1abc` group by a"); - generateLogicplan("select count(length(a)+b) from `t.1abc` group by a"); - generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s)"); - generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s) order by 1 desc "); - generateLogicplan("select count(*),sum(a),avg(b),min(a+b)+99 from `t.1abc`"); - generateLogicplan("select count(*), min(a) + 99 from `t.1abc`"); - generateLogicplan("select count(length(count(*) + 22)) from `t.1abc`"); - generateLogicplan("select concat(concat(a,b), concat(a,b)) from `t.1abc` limit 20"); - generateLogicplan("select count(*), first(a), last(b) from `t.1abc` state_window(a)"); - generateLogicplan("select count(*), first(a), last(b) from `t.1abc` session(ts, 20s)"); - - // order by + group by column + limit offset - generateLogicplan("select top(a, 20) k from `t.1abc` order by k asc limit 3 offset 1"); - - // fill - generateLogicplan("select min(a) from `t.1abc` where ts>now and ts -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wwrite-strings" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wsign-compare" -#include "os.h" - -#include "taos.h" -#include "tvariant.h" -#include "tdef.h" -#include "ttoken.h" -#include "astGenerator.h" -#include "parserUtil.h" -#include "parserInt.h" - -namespace { -int32_t testValidateName(char* name) { - SToken token = {0}; - token.z = name; - token.n = strlen(name); - token.type = 0; - - tGetToken(name, &token.type); - return parserValidateIdToken(&token); -} - -SToken createToken(char* s) { - SToken t = {0}; - - t.type = TK_STRING; - t.z = s; - t.n = strlen(s); - return t; -} -} // namespace - -static void _init_tvariant_bool(SVariant* t) { - t->i = TSDB_FALSE; - t->nType = TSDB_DATA_TYPE_BOOL; -} - -static void _init_tvariant_tinyint(SVariant* t) { - t->i = -27; - t->nType = TSDB_DATA_TYPE_TINYINT; -} - -static void _init_tvariant_int(SVariant* t) { - t->i = -23997659; - t->nType = TSDB_DATA_TYPE_INT; -} - -static void _init_tvariant_bigint(SVariant* t) { - t->i = -3333333333333; - t->nType = TSDB_DATA_TYPE_BIGINT; -} - -static void _init_tvariant_float(SVariant* t) { - t->d = -8991212199.8987878776; - t->nType = TSDB_DATA_TYPE_FLOAT; -} - -static void _init_tvariant_binary(SVariant* t) { - taosVariantDestroy(t); - - t->pz = (char*)calloc(1, 20); //"2e3"); - t->nType = TSDB_DATA_TYPE_BINARY; - strcpy(t->pz, "2e5"); - t->nLen = strlen(t->pz); -} - -static void _init_tvariant_nchar(SVariant* t) { - taosVariantDestroy(t); - - t->wpz = (wchar_t*)calloc(1, 20 * TSDB_NCHAR_SIZE); - t->nType = TSDB_DATA_TYPE_NCHAR; - wcscpy(t->wpz, L"-2000000.8765"); - t->nLen = twcslen(t->wpz); -} - -TEST(testCase, validateToken_test) { - char t01[] = "abc"; - EXPECT_EQ(testValidateName(t01), TSDB_CODE_SUCCESS); - - char t110[] = "`1233abc.911`"; - EXPECT_EQ(testValidateName(t110), TSDB_CODE_SUCCESS); - - char t02[] = "'abc'"; - EXPECT_EQ(testValidateName(t02), TSDB_CODE_TSC_INVALID_OPERATION); - - char t1[] = "abc.def"; - EXPECT_EQ(testValidateName(t1), TSDB_CODE_SUCCESS); - printf("%s\n", t1); - - char t98[] = "abc.DeF"; - EXPECT_EQ(testValidateName(t98), TSDB_CODE_SUCCESS); - EXPECT_STREQ(t98, "abc.def"); - printf("%s\n", t98); - - char t97[] = "257.abc"; - EXPECT_EQ(testValidateName(t97), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t97); - - char t96[] = "_257.aBc"; - EXPECT_EQ(testValidateName(t96), TSDB_CODE_SUCCESS); - EXPECT_STREQ(t96, "_257.abc"); - printf("%s\n", t96); - - char t99[] = "abc . def"; - EXPECT_EQ(testValidateName(t99), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t99); - - char t2[] = "'abc.def'"; - EXPECT_EQ(testValidateName(t2), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t2); - - char t3[] = "'abc'.def"; - EXPECT_EQ(testValidateName(t3), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t3); - - char t4[] = "'abc'.'def'"; - EXPECT_EQ(testValidateName(t4), TSDB_CODE_TSC_INVALID_OPERATION); - - char t5[] = "table.'def'"; - EXPECT_EQ(testValidateName(t5), TSDB_CODE_TSC_INVALID_OPERATION); - - char t6[] = "'table'.'def'"; - EXPECT_EQ(testValidateName(t6), TSDB_CODE_TSC_INVALID_OPERATION); - - char t7[] = "'_ab1234'.'def'"; - EXPECT_EQ(testValidateName(t7), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t7); - - char t8[] = "'_ab&^%1234'.'def'"; - EXPECT_EQ(testValidateName(t8), TSDB_CODE_TSC_INVALID_OPERATION); - - char t9[] = "'_123'.'gtest中文'"; - EXPECT_EQ(testValidateName(t9), TSDB_CODE_TSC_INVALID_OPERATION); - - char t10[] = "abc.'gtest中文'"; - EXPECT_EQ(testValidateName(t10), TSDB_CODE_TSC_INVALID_OPERATION); - - char t10_1[] = "abc.'中文gtest'"; - EXPECT_EQ(testValidateName(t10_1), TSDB_CODE_TSC_INVALID_OPERATION); - - char t11[] = "'192.168.0.1'.abc"; - EXPECT_EQ(testValidateName(t11), TSDB_CODE_TSC_INVALID_OPERATION); - - char t12[] = "192.168.0.1.abc"; - EXPECT_EQ(testValidateName(t12), TSDB_CODE_TSC_INVALID_OPERATION); - - char t13[] = "abc."; - EXPECT_EQ(testValidateName(t13), TSDB_CODE_TSC_INVALID_OPERATION); - - char t14[] = ".abc"; - EXPECT_EQ(testValidateName(t14), TSDB_CODE_TSC_INVALID_OPERATION); - - char t15[] = ".'abc'"; - EXPECT_EQ(testValidateName(t15), TSDB_CODE_TSC_INVALID_OPERATION); - - char t16[] = ".abc'"; - EXPECT_EQ(testValidateName(t16), TSDB_CODE_TSC_INVALID_OPERATION); - - char t17[] = "123a.\"abc\""; - EXPECT_EQ(testValidateName(t17), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t17); - - char t18[] = "a.\"abc\""; - EXPECT_EQ(testValidateName(t18), TSDB_CODE_TSC_INVALID_OPERATION); - printf("%s\n", t18); - - char t19[] = "'_ab1234'.'def'.'ab123'"; - EXPECT_EQ(testValidateName(t19), TSDB_CODE_TSC_INVALID_OPERATION); - - char t20[] = "'_ab1234*&^'"; - EXPECT_EQ(testValidateName(t20), TSDB_CODE_TSC_INVALID_OPERATION); - - char t21[] = "'1234_abc'"; - EXPECT_EQ(testValidateName(t21), TSDB_CODE_TSC_INVALID_OPERATION); - - // =======Containing capital letters================= - char t30[] = "ABC"; - EXPECT_EQ(testValidateName(t30), TSDB_CODE_SUCCESS); - - char t31[] = "'ABC'"; - EXPECT_EQ(testValidateName(t31), TSDB_CODE_TSC_INVALID_OPERATION); - - char t32[] = "ABC.def"; - EXPECT_EQ(testValidateName(t32), TSDB_CODE_SUCCESS); - - char t33[] = "'ABC.def"; - EXPECT_EQ(testValidateName(t33), TSDB_CODE_TSC_INVALID_OPERATION); - - char t33_0[] = "abc.DEF'"; - EXPECT_EQ(testValidateName(t33_0), TSDB_CODE_TSC_INVALID_OPERATION); - - char t34[] = "'ABC.def'"; - // int32_t tmp0 = testValidateName(t34); - EXPECT_EQ(testValidateName(t34), TSDB_CODE_TSC_INVALID_OPERATION); - - char t35[] = "'ABC'.def"; - EXPECT_EQ(testValidateName(t35), TSDB_CODE_TSC_INVALID_OPERATION); - - char t36[] = "ABC.DEF"; - EXPECT_EQ(testValidateName(t36), TSDB_CODE_SUCCESS); - - char t37[] = "abc.DEF"; - EXPECT_EQ(testValidateName(t37), TSDB_CODE_SUCCESS); - - char t37_1[] = "abc._123DEF"; - EXPECT_EQ(testValidateName(t37_1), TSDB_CODE_SUCCESS); - - char t38[] = "'abc'.\"DEF\""; - EXPECT_EQ(testValidateName(t38), TSDB_CODE_TSC_INVALID_OPERATION); - - // do not use key words - char t39[] = "table.'DEF'"; - EXPECT_EQ(testValidateName(t39), TSDB_CODE_TSC_INVALID_OPERATION); - - char t40[] = "'table'.'DEF'"; - EXPECT_EQ(testValidateName(t40), TSDB_CODE_TSC_INVALID_OPERATION); - - char t41[] = "'_abXYZ1234'.'deFF'"; - EXPECT_EQ(testValidateName(t41), TSDB_CODE_TSC_INVALID_OPERATION); - - char t42[] = "'_abDEF&^%1234'.'DIef'"; - EXPECT_EQ(testValidateName(t42), TSDB_CODE_TSC_INVALID_OPERATION); - - char t43[] = "'_123'.'Gtest中文'"; - EXPECT_EQ(testValidateName(t43), TSDB_CODE_TSC_INVALID_OPERATION); - - char t44[] = "'aABC'.'Gtest中文'"; - EXPECT_EQ(testValidateName(t44), TSDB_CODE_TSC_INVALID_OPERATION); - - char t45[] = "'ABC'."; - EXPECT_EQ(testValidateName(t45), TSDB_CODE_TSC_INVALID_OPERATION); - - char t46[] = ".'ABC'"; - EXPECT_EQ(testValidateName(t46), TSDB_CODE_TSC_INVALID_OPERATION); - - char t47[] = "a.\"aTWc\""; - EXPECT_EQ(testValidateName(t47), TSDB_CODE_TSC_INVALID_OPERATION); - - // ================has space ================= - char t60[] = " ABC "; - EXPECT_EQ(testValidateName(t60), TSDB_CODE_TSC_INVALID_OPERATION); - - char t60_1[] = " ABC "; - EXPECT_EQ(testValidateName(t60_1), TSDB_CODE_TSC_INVALID_OPERATION); - - char t61[] = "' ABC '"; - EXPECT_EQ(testValidateName(t61), TSDB_CODE_TSC_INVALID_OPERATION); - - char t61_1[] = "' ABC '"; - EXPECT_EQ(testValidateName(t61_1), TSDB_CODE_TSC_INVALID_OPERATION); - - char t62[] = " ABC . def "; - EXPECT_EQ(testValidateName(t62), TSDB_CODE_TSC_INVALID_OPERATION); - - char t63[] = "' ABC . def "; - EXPECT_EQ(testValidateName(t63), TSDB_CODE_TSC_INVALID_OPERATION); - - char t63_0[] = " abc . DEF ' "; - EXPECT_EQ(testValidateName(t63_0), TSDB_CODE_TSC_INVALID_OPERATION); - - char t64[] = " ' ABC . def ' "; - // int32_t tmp1 = testValidateName(t64); - EXPECT_EQ(testValidateName(t64), TSDB_CODE_TSC_INVALID_OPERATION); - - char t65[] = " ' ABC '. def "; - EXPECT_EQ(testValidateName(t65), TSDB_CODE_TSC_INVALID_OPERATION); - - char t66[] = "' ABC '.' DEF '"; - EXPECT_EQ(testValidateName(t66), TSDB_CODE_TSC_INVALID_OPERATION); - - char t67[] = "abc . ' DEF '"; - EXPECT_EQ(testValidateName(t67), TSDB_CODE_TSC_INVALID_OPERATION); - - char t68[] = "' abc '.' DEF '"; - EXPECT_EQ(testValidateName(t68), TSDB_CODE_TSC_INVALID_OPERATION); - - // do not use key words - char t69[] = "table.'DEF'"; - EXPECT_EQ(testValidateName(t69), TSDB_CODE_TSC_INVALID_OPERATION); - - char t70[] = "'table'.'DEF'"; - EXPECT_EQ(testValidateName(t70), TSDB_CODE_TSC_INVALID_OPERATION); - - char t71[] = "'_abXYZ1234 '.' deFF '"; - EXPECT_EQ(testValidateName(t71), TSDB_CODE_TSC_INVALID_OPERATION); - - char t72[] = "'_abDEF&^%1234'.' DIef'"; - EXPECT_EQ(testValidateName(t72), TSDB_CODE_TSC_INVALID_OPERATION); - - char t73[] = "'_123'.' Gtest中文'"; - EXPECT_EQ(testValidateName(t73), TSDB_CODE_TSC_INVALID_OPERATION); - - char t74[] = "' aABC'.'Gtest中文'"; - EXPECT_EQ(testValidateName(t74), TSDB_CODE_TSC_INVALID_OPERATION); - - char t75[] = "' ABC '."; - EXPECT_EQ(testValidateName(t75), TSDB_CODE_TSC_INVALID_OPERATION); - - char t76[] = ".' ABC'"; - EXPECT_EQ(testValidateName(t76), TSDB_CODE_TSC_INVALID_OPERATION); - - char t77[] = " a . \"aTWc\" "; - EXPECT_EQ(testValidateName(t77), TSDB_CODE_TSC_INVALID_OPERATION); - - char t78[] = " a.\"aTWc \""; - EXPECT_EQ(testValidateName(t78), TSDB_CODE_TSC_INVALID_OPERATION); - - // ===============muti string by space =================== - // There's no such case. - // char t160[] = "A BC"; - // EXPECT_EQ(testValidateName(t160), TSDB_CODE_TSC_INVALID_OPERATION); - // printf("end:%s\n", t160); - - // There's no such case. - // char t161[] = "' A BC '"; - // EXPECT_EQ(testValidateName(t161), TSDB_CODE_TSC_INVALID_OPERATION); - - char t162[] = " AB C . de f "; - EXPECT_EQ(testValidateName(t162), TSDB_CODE_TSC_INVALID_OPERATION); - - char t163[] = "' AB C . de f "; - EXPECT_EQ(testValidateName(t163), TSDB_CODE_TSC_INVALID_OPERATION); - - char t163_0[] = " ab c . DE F ' "; - EXPECT_EQ(testValidateName(t163_0), TSDB_CODE_TSC_INVALID_OPERATION); - - char t164[] = " ' AB C . de f ' "; - // int32_t tmp2 = testValidateName(t164); - EXPECT_EQ(testValidateName(t164), TSDB_CODE_TSC_INVALID_OPERATION); - - char t165[] = " ' A BC '. de f "; - EXPECT_EQ(testValidateName(t165), TSDB_CODE_TSC_INVALID_OPERATION); - - char t166[] = "' AB C '.' DE F '"; - EXPECT_EQ(testValidateName(t166), TSDB_CODE_TSC_INVALID_OPERATION); - - char t167[] = "ab c . ' D EF '"; - EXPECT_EQ(testValidateName(t167), TSDB_CODE_TSC_INVALID_OPERATION); - - char t168[] = "' a bc '.' DE F '"; - EXPECT_EQ(testValidateName(t168), TSDB_CODE_TSC_INVALID_OPERATION); -} - -#if 0 -TEST(testCase, tvariant_convert) { - // 1. bool data to all other data types - SVariant t = {0}; - _init_tvariant_bool(&t); - - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 0); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0); - EXPECT_EQ(t.i, 0); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_SMALLINT), 0); - EXPECT_EQ(t.i, 0); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, 0); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_EQ(t.d, 0); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_EQ(t.d, 0); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "FALSE"); - taosVariantDestroy(&t); - - _init_tvariant_bool(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"FALSE"); - taosVariantDestroy(&t); - - // 2. tinyint to other data types - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 1); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0); - EXPECT_EQ(t.i, -27); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_SMALLINT), 0); - EXPECT_EQ(t.i, -27); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_INT), 0); - EXPECT_EQ(t.i, -27); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, -27); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_EQ(t.d, -27); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_EQ(t.d, -27); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "-27"); - taosVariantDestroy(&t); - - _init_tvariant_tinyint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"-27"); - taosVariantDestroy(&t); - - // 3. int to other data - // types////////////////////////////////////////////////////////////////// - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 1); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_SMALLINT), 0); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_INT), 0); - EXPECT_EQ(t.i, -23997659); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, -23997659); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_EQ(t.d, -23997659); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_EQ(t.d, -23997659); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "-23997659"); - taosVariantDestroy(&t); - - _init_tvariant_int(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"-23997659"); - taosVariantDestroy(&t); - - // 4. bigint to other data - // type////////////////////////////////////////////////////////////////////////////// - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 1); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_SMALLINT), 0); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_INT), 0); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, -3333333333333); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_EQ(t.d, -3333333333333); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_EQ(t.d, -3333333333333); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "-3333333333333"); - taosVariantDestroy(&t); - - _init_tvariant_bigint(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"-3333333333333"); - taosVariantDestroy(&t); - - // 5. float to other data - // types//////////////////////////////////////////////////////////////////////// - _init_tvariant_float(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 1); - - _init_tvariant_float(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, -8991212199); - - _init_tvariant_float(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_DOUBLE_EQ(t.d, -8991212199.8987885); - - _init_tvariant_float(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_DOUBLE_EQ(t.d, -8991212199.8987885); - - _init_tvariant_float(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "-8991212199.898788"); - taosVariantDestroy(&t); - - _init_tvariant_float(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"-8991212199.898788"); - taosVariantDestroy(&t); - - // 6. binary to other data types - // ////////////////////////////////////////////////////////////////// - t.pz = "true"; - t.nLen = strlen(t.pz); - t.nType = TSDB_DATA_TYPE_BINARY; - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 1); - - _init_tvariant_binary(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), -1); - - _init_tvariant_binary(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, 200000); - - _init_tvariant_binary(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_DOUBLE_EQ(t.d, 200000); - - _init_tvariant_binary(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_DOUBLE_EQ(t.d, 200000); - - _init_tvariant_binary(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "2e5"); - taosVariantDestroy(&t); - - _init_tvariant_binary(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"2e5"); - taosVariantDestroy(&t); - - // 7. nchar to other data types - // ////////////////////////////////////////////////////////////////// - t.wpz = L"FALSE"; - t.nLen = wcslen(t.wpz); - t.nType = TSDB_DATA_TYPE_NCHAR; - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - EXPECT_EQ(t.i, 0); - - _init_tvariant_nchar(&t); - EXPECT_LE(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0); - - _init_tvariant_nchar(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0); - EXPECT_EQ(t.i, -2000000); - - _init_tvariant_nchar(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0); - EXPECT_DOUBLE_EQ(t.d, -2000000.8765); - - _init_tvariant_nchar(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_DOUBLE), 0); - EXPECT_DOUBLE_EQ(t.d, -2000000.8765); - - _init_tvariant_nchar(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BINARY), 0); - EXPECT_STREQ(t.pz, "-2000000.8765"); - taosVariantDestroy(&t); - - _init_tvariant_nchar(&t); - EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_NCHAR), 0); - EXPECT_STREQ(t.wpz, L"-2000000.8765"); - taosVariantDestroy(&t); -} -#endif - -TEST(testCase, tGetToken_Test) { - char* s = ".123 "; - uint32_t type = 0; - - int32_t len = tGetToken(s, &type); - EXPECT_EQ(type, TK_FLOAT); - EXPECT_EQ(len, strlen(s) - 1); - - char s1[] = "1.123e10 "; - len = tGetToken(s1, &type); - EXPECT_EQ(type, TK_FLOAT); - EXPECT_EQ(len, strlen(s1) - 1); - - char s4[] = "0xff "; - len = tGetToken(s4, &type); - EXPECT_EQ(type, TK_HEX); - EXPECT_EQ(len, strlen(s4) - 1); - - // invalid data type - char s2[] = "e10 "; - len = tGetToken(s2, &type); - EXPECT_FALSE(type == TK_FLOAT); - - char s3[] = "1.1.1.1"; - len = tGetToken(s3, &type); - EXPECT_EQ(type, TK_IPTOKEN); - EXPECT_EQ(len, strlen(s3)); - - char s5[] = "0x "; - len = tGetToken(s5, &type); - EXPECT_FALSE(type == TK_HEX); -} - -TEST(testCase, isValidNumber_test) { - SToken t1 = createToken("123abc"); - - EXPECT_EQ(tGetNumericStringType(&t1), TK_ILLEGAL); - - t1 = createToken("0xabc"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_HEX); - - t1 = createToken("0b11101"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_BIN); - - t1 = createToken(".134abc"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_ILLEGAL); - - t1 = createToken("1e1 "); - EXPECT_EQ(tGetNumericStringType(&t1), TK_ILLEGAL); - - t1 = createToken("1+2"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_ILLEGAL); - - t1 = createToken("-0x123"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_HEX); - - t1 = createToken("-1"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_INTEGER); - - t1 = createToken("-0b1110"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_BIN); - - t1 = createToken("-.234"); - EXPECT_EQ(tGetNumericStringType(&t1), TK_FLOAT); -} - -TEST(testCase, generateAST_test) { - SSqlInfo info = doGenerateAST("select * from t1 where ts < now"); - ASSERT_EQ(info.valid, true); - - SSqlInfo info1 = doGenerateAST("select * from `t.1abc` where ts + * + * 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 . + */ + +#ifndef _TD_PLANNER_IMPL_H_ +#define _TD_PLANNER_IMPL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "planner.h" + +#define CHECK_ALLOC(p, res) \ + do { \ + if (NULL == (p)) { \ + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \ + return (res); \ + } \ + } while (0) + +#define CHECK_CODE(exec, res) \ + do { \ + int32_t code = (exec); \ + if (TSDB_CODE_SUCCESS != code) { \ + pCxt->errCode = code; \ + return (res); \ + } \ + } while (0) + +#define CHECK_CODE_EXT(exec) \ + do { \ + int32_t code = (exec); \ + if (TSDB_CODE_SUCCESS != code) { \ + pCxt->errCode = code; \ + return code; \ + } \ + } while (0) + +#define planFatal(param, ...) qFatal("PLAN: " param, __VA_ARGS__) +#define planError(param, ...) qError("PLAN: " param, __VA_ARGS__) +#define planWarn(param, ...) qWarn("PLAN: " param, __VA_ARGS__) +#define planInfo(param, ...) qInfo("PLAN: " param, __VA_ARGS__) +#define planDebug(param, ...) qDebug("PLAN: " param, __VA_ARGS__) +#define planTrace(param, ...) qTrace("PLAN: " param, __VA_ARGS__) + +int32_t createLogicPlan(SPlanContext* pCxt, SLogicNode** pLogicNode); +int32_t optimize(SPlanContext* pCxt, SLogicNode* pLogicNode); +int32_t applySplitRule(SSubLogicPlan* pSubplan); +int32_t createPhysiPlan(SPlanContext* pCxt, SLogicNode* pLogicNode, SQueryPlan** pPlan, SArray* pExecNodeList); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_PLANNER_IMPL_H_*/ diff --git a/source/libs/planner/inc/plannerImpl.h b/source/libs/planner/inc/plannerImpl.h deleted file mode 100644 index 559d614829291a00de665d45e67f81f4736f459d..0000000000000000000000000000000000000000 --- a/source/libs/planner/inc/plannerImpl.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef _TD_PLANNER_IMPL_H_ -#define _TD_PLANNER_IMPL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "plannodes.h" -#include "planner.h" - -int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode); -int32_t createPhysiPlan(SLogicNode* pLogicNode, SPhysiNode** pPhyNode); - -#ifdef __cplusplus -} -#endif - -#endif /*_TD_PLANNER_IMPL_H_*/ diff --git a/source/libs/planner/inc/plannerInt.h b/source/libs/planner/inc/plannerInt.h deleted file mode 100644 index 248a24f51e9ffd90019f176bf62a4dc7f86ac1c1..0000000000000000000000000000000000000000 --- a/source/libs/planner/inc/plannerInt.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef _TD_PLANNER_INT_H_ -#define _TD_PLANNER_INT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "tcommon.h" -#include "tarray.h" -#include "planner.h" -#include "parser.h" -#include "tmsg.h" - -#define QNODE_TAGSCAN 1 -#define QNODE_TABLESCAN 2 -#define QNODE_STREAMSCAN 3 -#define QNODE_PROJECT 4 -#define QNODE_AGGREGATE 5 -#define QNODE_GROUPBY 6 -#define QNODE_LIMIT 7 -#define QNODE_JOIN 8 -#define QNODE_DISTINCT 9 -#define QNODE_SORT 10 -#define QNODE_UNION 11 -#define QNODE_TIMEWINDOW 12 -#define QNODE_SESSIONWINDOW 13 -#define QNODE_STATEWINDOW 14 -#define QNODE_FILL 15 -#define QNODE_MODIFY 16 - -typedef struct SQueryDistPlanNodeInfo { - bool stableQuery; // super table query or not - int32_t phase; // merge|partial - int32_t type; // operator type - char *name; // operator name - SEpSet *sourceEp; // data source epset -} SQueryDistPlanNodeInfo; - -typedef struct SQueryTableInfo { - char *tableName; // to be deleted - uint64_t uid; // to be deleted - STableMetaInfo *pMeta; - STimeWindow window; -} SQueryTableInfo; - -typedef struct SQueryPlanNode { - SQueryNodeBasicInfo info; - SSchema *pSchema; // the schema of the input SSDatablock - int32_t numOfCols; // number of input columns - SArray *pExpr; // the query functions or sql aggregations - int32_t numOfExpr; // number of result columns, which is also the number of pExprs - void *pExtInfo; // additional information - // children operator to generated result for current node to process - // in case of join, multiple prev nodes exist. - SArray *pChildren; // upstream nodes - struct SQueryPlanNode *pParent; -} SQueryPlanNode; - -typedef struct SDataPayloadInfo { - int32_t msgType; - SArray *payload; -} SDataPayloadInfo; - -/** - * Optimize the query execution plan, currently not implement yet. - * @param pQueryNode - * @return - */ -int32_t optimizeQueryPlan(struct SQueryPlanNode* pQueryNode); - -/** - * Create the query plan according to the bound AST, which is in the form of pQueryInfo - * @param pQueryInfo - * @param pQueryNode - * @return - */ -int32_t createQueryPlan(const SQueryNode* pNode, struct SQueryPlanNode** pQueryPlan); - -/** - * Convert the query plan to string, in order to display it in the shell. - * @param pQueryNode - * @return - */ -int32_t queryPlanToString(struct SQueryPlanNode* pQueryNode, char** str); - -/** - * Restore the SQL statement according to the logic query plan. - * @param pQueryNode - * @param sql - * @return - */ -int32_t queryPlanToSql(struct SQueryPlanNode* pQueryNode, char** sql); - -int32_t createDag(SQueryPlanNode* pQueryNode, struct SCatalog* pCatalog, SQueryDag** pDag, SArray* pNodeList, uint64_t requestId); -void setSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource); -int32_t subPlanToString(const SSubplan *pPhyNode, char** str, int32_t* len); -int32_t stringToSubplan(const char* str, SSubplan** subplan); - -/** - * Destroy the query plan object. - * @return - */ -void destroyQueryPlan(struct SQueryPlanNode* pQueryNode); - -/** - * Destroy the physical plan. - * @param pQueryPhyNode - * @return - */ -void* destroyQueryPhyPlan(struct SPhyNode* pQueryPhyNode); - -const char* opTypeToOpName(int32_t type); -int32_t opNameToOpType(const char* name); - -const char* dsinkTypeToDsinkName(int32_t type); -int32_t dsinkNameToDsinkType(const char* name); - -#ifdef __cplusplus -} -#endif - -#endif /*_TD_PLANNER_INT_H_*/ \ No newline at end of file diff --git a/source/libs/planner/inc/plannerUtil.h b/source/libs/planner/inc/plannerUtil.h deleted file mode 100644 index 198c883c5a09e11c085240a31f01c5ceb8f7ab39..0000000000000000000000000000000000000000 --- a/source/libs/planner/inc/plannerUtil.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef TDENGINE_PLANNERUTIL_H -#define TDENGINE_PLANNERUTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "parser.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#endif // TDENGINE_PLANNERUTIL_H diff --git a/source/libs/planner/src/logicPlan.c b/source/libs/planner/src/logicPlan.c deleted file mode 100644 index a5b1fd6f6b1a49590043fc00996285bf958ac416..0000000000000000000000000000000000000000 --- a/source/libs/planner/src/logicPlan.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include -#include "function.h" -#include "os.h" -#include "parser.h" -#include "plannerInt.h" - -typedef struct SFillEssInfo { - int32_t fillType; // fill type - int64_t *val; // fill value -} SFillEssInfo; - -typedef struct SJoinCond { - bool tagExists; // denote if tag condition exists or not - SColumn *tagCond[2]; - SColumn *colCond[2]; -} SJoinCond; - -static SArray* createQueryPlanImpl(const SQueryStmtInfo* pQueryInfo); -static void doDestroyQueryNode(SQueryPlanNode* pQueryNode); - -int32_t printExprInfo(char* buf, const SQueryPlanNode* pQueryNode, int32_t len); -int32_t optimizeQueryPlan(struct SQueryPlanNode* pQueryNode) { - return 0; -} - -static int32_t createModificationOpPlan(const SQueryNode* pNode, SQueryPlanNode** pQueryPlan) { - SVnodeModifOpStmtInfo* pModifStmtInfo = (SVnodeModifOpStmtInfo*)pNode; - - *pQueryPlan = calloc(1, sizeof(SQueryPlanNode)); - SArray* blocks = taosArrayInit(taosArrayGetSize(pModifStmtInfo->pDataBlocks), POINTER_BYTES); - - SDataPayloadInfo* pPayload = calloc(1, sizeof(SDataPayloadInfo)); - if (NULL == *pQueryPlan || NULL == blocks || NULL == pPayload) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - - (*pQueryPlan)->info.type = QNODE_MODIFY; - taosArrayAddAll(blocks, pModifStmtInfo->pDataBlocks); - - if (pNode->type == TSDB_SQL_INSERT) { - pPayload->msgType = TDMT_VND_SUBMIT; - } else if (pNode->type == TSDB_SQL_CREATE_TABLE) { - pPayload->msgType = TDMT_VND_CREATE_TABLE; - } - - pPayload->payload = blocks; - (*pQueryPlan)->pExtInfo = pPayload; - - return TSDB_CODE_SUCCESS; -} - -int32_t createSelectPlan(const SQueryStmtInfo* pSelect, SQueryPlanNode** pQueryPlan) { - SArray* pDownstream = createQueryPlanImpl(pSelect); - assert(taosArrayGetSize(pDownstream) == 1); - - *pQueryPlan = taosArrayGetP(pDownstream, 0); - taosArrayDestroy(pDownstream); - return TSDB_CODE_SUCCESS; -} - -int32_t createQueryPlan(const SQueryNode* pNode, SQueryPlanNode** pQueryPlan) { - switch (queryNodeType(pNode)) { - case TSDB_SQL_SELECT: { - return createSelectPlan((const SQueryStmtInfo*)pNode, pQueryPlan); - } - - case TSDB_SQL_INSERT: - case TSDB_SQL_CREATE_TABLE: - return createModificationOpPlan(pNode, pQueryPlan); - - default: - return TSDB_CODE_FAILED; - } -} - -int32_t queryPlanToSql(struct SQueryPlanNode* pQueryNode, char** sql) { - return 0; -} - -void destroyQueryPlan(SQueryPlanNode* pQueryNode) { - if (pQueryNode == NULL) { - return; - } - - doDestroyQueryNode(pQueryNode); -} - -//====================================================================================================================== - -static SQueryPlanNode* createQueryNode(int32_t type, const char* name, SQueryPlanNode** pChildrenNode, int32_t numOfChildren, - SExprInfo** pExpr, int32_t numOfOutput, const void* pExtInfo) { - SQueryPlanNode* pNode = calloc(1, sizeof(SQueryPlanNode)); - - pNode->info.type = type; - pNode->info.name = strdup(name); - pNode->numOfExpr = numOfOutput; - - pNode->pExpr = taosArrayInit(numOfOutput, POINTER_BYTES); - taosArrayAddBatch(pNode->pExpr, pExpr, numOfOutput); - assert(pNode->numOfExpr == numOfOutput); - - pNode->pChildren = taosArrayInit(4, POINTER_BYTES); - for(int32_t i = 0; i < numOfChildren; ++i) { - taosArrayPush(pNode->pChildren, &pChildrenNode[i]); - } - - switch(type) { - case QNODE_TAGSCAN: - case QNODE_STREAMSCAN: - case QNODE_TABLESCAN: { - SQueryTableInfo* info = calloc(1, sizeof(SQueryTableInfo)); - memcpy(info, pExtInfo, sizeof(SQueryTableInfo)); - info->tableName = strdup(((SQueryTableInfo*) pExtInfo)->tableName); - pNode->pExtInfo = info; - break; - } - - case QNODE_TIMEWINDOW: { - SInterval* pInterval = calloc(1, sizeof(SInterval)); - pNode->pExtInfo = pInterval; - memcpy(pInterval, pExtInfo, sizeof(SInterval)); - break; - } - - case QNODE_STATEWINDOW: { - SColumn* psw = calloc(1, sizeof(SColumn)); - pNode->pExtInfo = psw; - memcpy(psw, pExtInfo, sizeof(SColumn)); - break; - } - - case QNODE_SESSIONWINDOW: { - SSessionWindow *pSessionWindow = calloc(1, sizeof(SSessionWindow)); - pNode->pExtInfo = pSessionWindow; - memcpy(pSessionWindow, pExtInfo, sizeof(struct SSessionWindow)); - break; - } - - case QNODE_GROUPBY: { - SGroupbyExpr* p = (SGroupbyExpr*) pExtInfo; - - SGroupbyExpr* pGroupbyExpr = calloc(1, sizeof(SGroupbyExpr)); - pGroupbyExpr->groupbyTag = p->groupbyTag; - pGroupbyExpr->columnInfo = taosArrayDup(p->columnInfo); - - pNode->pExtInfo = pGroupbyExpr; - break; - } - - case QNODE_FILL: { // todo !! - pNode->pExtInfo = (void*)pExtInfo; - break; - } - - case QNODE_LIMIT: { - pNode->pExtInfo = calloc(1, sizeof(SLimit)); - memcpy(pNode->pExtInfo, pExtInfo, sizeof(SLimit)); - break; - } - - case QNODE_SORT: { - pNode->pExtInfo = taosArrayDup(pExtInfo); - break; - } - - default: - break; - } - - return pNode; -} - -static SQueryPlanNode* doAddTableColumnNode(const SQueryStmtInfo* pQueryInfo, SQueryTableInfo* info, SArray* pExprs, SArray* tableCols) { - if (pQueryInfo->info.onlyTagQuery) { - int32_t num = (int32_t) taosArrayGetSize(pExprs); - SQueryPlanNode* pNode = createQueryNode(QNODE_TAGSCAN, "TableTagScan", NULL, 0, pExprs->pData, num, info); - - if (pQueryInfo->info.distinct) { - pNode = createQueryNode(QNODE_DISTINCT, "Distinct", &pNode, 1, pExprs->pData, num, NULL); - } - return pNode; - } - - SQueryPlanNode* pNode = NULL; - if (pQueryInfo->info.continueQuery) { - pNode = createQueryNode(QNODE_STREAMSCAN, "StreamScan", NULL, 0, NULL, 0, info); - } else { - pNode = createQueryNode(QNODE_TABLESCAN, "TableScan", NULL, 0, NULL, 0, info); - } - - if (!pQueryInfo->info.projectionQuery) { - SArray* p = pQueryInfo->exprList[0]; - - // table source column projection, generate the projection expr - int32_t numOfCols = (int32_t) taosArrayGetSize(tableCols); - - pNode->numOfExpr = numOfCols; - pNode->pExpr = taosArrayInit(numOfCols, POINTER_BYTES); - for(int32_t i = 0; i < numOfCols; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(p, i); - SColumn* pCol = pExprInfo->base.pColumns; - - SSchema schema = createSchema(pCol->info.type, pCol->info.bytes, pCol->info.colId, pCol->name); - - tExprNode* pExprNode = pExprInfo->pExpr->_function.pChild[0]; - SExprInfo* px = createBinaryExprInfo(pExprNode, &schema); - taosArrayPush(pNode->pExpr, &px); - } - } - - return pNode; -} - -static SQueryPlanNode* doCreateQueryPlanForSingleTableImpl(const SQueryStmtInfo* pQueryInfo, SQueryPlanNode* pNode, SQueryTableInfo* info) { - // group by column not by tag - size_t numOfGroupCols = taosArrayGetSize(pQueryInfo->groupbyExpr.columnInfo); - - // check for aggregation - int32_t level = getExprFunctionLevel(pQueryInfo); - - for(int32_t i = level - 1; i >= 0; --i) { - SArray* p = pQueryInfo->exprList[i]; - size_t num = taosArrayGetSize(p); - - bool aggregateFunc = false; - for(int32_t j = 0; j < num; ++j) { - SExprInfo* pExpr = (SExprInfo*)taosArrayGetP(p, 0); - if (pExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE) { - continue; - } - - aggregateFunc = qIsAggregateFunction(pExpr->pExpr->_function.functionName); - if (aggregateFunc) { - break; - } - } - - if (aggregateFunc) { - if (pQueryInfo->interval.interval > 0) { - pNode = createQueryNode(QNODE_TIMEWINDOW, "TimeWindowAgg", &pNode, 1, p->pData, num, &pQueryInfo->interval); - } else if (pQueryInfo->sessionWindow.gap > 0) { - pNode = createQueryNode(QNODE_SESSIONWINDOW, "SessionWindowAgg", &pNode, 1, p->pData, num, &pQueryInfo->sessionWindow); - } else if (pQueryInfo->stateWindow.col.info.colId > 0) { - pNode = createQueryNode(QNODE_STATEWINDOW, "StateWindowAgg", &pNode, 1, p->pData, num, &pQueryInfo->stateWindow); - } else if (numOfGroupCols != 0 && !pQueryInfo->groupbyExpr.groupbyTag) { - pNode = createQueryNode(QNODE_GROUPBY, "Groupby", &pNode, 1, p->pData, num, &pQueryInfo->groupbyExpr); - } else { - pNode = createQueryNode(QNODE_AGGREGATE, "Aggregate", &pNode, 1, p->pData, num, NULL); - } - } else { - // here we can push down the projection to tablescan operator. - pNode->numOfExpr = num; - taosArrayAddAll(pNode->pExpr, p); - } - } - - if (pQueryInfo->havingFieldNum > 0) { -// int32_t numOfExpr = (int32_t)taosArrayGetSize(pQueryInfo->exprList1); -// pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, NULL); - } - - if (pQueryInfo->fillType != TSDB_FILL_NONE) { - SFillEssInfo* pInfo = calloc(1, sizeof(SFillEssInfo)); - pInfo->fillType = pQueryInfo->fillType; - pInfo->val = calloc(pNode->numOfExpr, sizeof(int64_t)); - memcpy(pInfo->val, pQueryInfo->fillVal, pNode->numOfExpr); - - SArray* p = pQueryInfo->exprList[0]; // top expression in select clause - pNode = createQueryNode(QNODE_FILL, "Fill", &pNode, 1, p->pData, taosArrayGetSize(p), pInfo); - } - - if (pQueryInfo->order != NULL) { - SArray* pList = pQueryInfo->exprList[0]; - pNode = createQueryNode(QNODE_SORT, "Sort", &pNode, 1, pList->pData, taosArrayGetSize(pList), pQueryInfo->order); - } - - if (pQueryInfo->limit.limit != -1 || pQueryInfo->limit.offset != 0) { - pNode = createQueryNode(QNODE_LIMIT, "Limit", &pNode, 1, NULL, 0, &pQueryInfo->limit); - } - - return pNode; -} - -static SQueryPlanNode* doCreateQueryPlanForSingleTable(const SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, SArray* pExprs, - SArray* tableCols) { - char name[TSDB_TABLE_FNAME_LEN] = {0}; - tstrncpy(name, pTableMetaInfo->name.tname, TSDB_TABLE_FNAME_LEN); - - SQueryTableInfo info = {.tableName = strdup(name), .uid = pTableMetaInfo->pTableMeta->uid,}; - info.window = pQueryInfo->window; - info.pMeta = pTableMetaInfo; - - // handle the only tag query - SQueryPlanNode* pNode = doAddTableColumnNode(pQueryInfo, &info, pExprs, tableCols); - if (pQueryInfo->info.onlyTagQuery) { - tfree(info.tableName); - return pNode; - } - - SQueryPlanNode* pNode1 = doCreateQueryPlanForSingleTableImpl(pQueryInfo, pNode, &info); - tfree(info.tableName); - return pNode1; -} - -static bool isAllAggExpr(SArray* pList) { - assert(pList != NULL); - - for (int32_t k = 0; k < taosArrayGetSize(pList); ++k) { - SExprInfo* p = taosArrayGetP(pList, k); - if (p->pExpr->nodeType != TEXPR_FUNCTION_NODE || !qIsAggregateFunction(p->pExpr->_function.functionName)) { - return false; - } - } - - return true; -} - -SArray* createQueryPlanImpl(const SQueryStmtInfo* pQueryInfo) { - SArray* pDownstream = NULL; - - if (pQueryInfo->pDownstream != NULL && taosArrayGetSize(pQueryInfo->pDownstream) > 0) { // subquery in the from clause - pDownstream = taosArrayInit(4, POINTER_BYTES); - - size_t size = taosArrayGetSize(pQueryInfo->pDownstream); - for(int32_t i = 0; i < size; ++i) { - SQueryStmtInfo* pq = taosArrayGet(pQueryInfo->pDownstream, i); - SArray* p = createQueryPlanImpl(pq); - taosArrayAddBatch(pDownstream, p->pData, (int32_t) taosArrayGetSize(p)); - } - } - - if (pQueryInfo->numOfTables > 1) { // it is a join query - // 1. separate the select clause according to table - taosArrayDestroy(pDownstream); - pDownstream = taosArrayInit(5, POINTER_BYTES); - - for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { - STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[i]; - uint64_t uid = pTableMetaInfo->pTableMeta->uid; - - SArray* exprList = taosArrayInit(4, POINTER_BYTES); - if (copyExprInfoList(exprList, pQueryInfo->exprList[0], uid, true) != 0) { - terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; - exit(-1); - } - - // 2. create the query execution node - char name[TSDB_TABLE_FNAME_LEN] = {0}; - tNameExtractFullName(&pTableMetaInfo->name, name); - SQueryTableInfo info = {.tableName = strdup(name), .uid = pTableMetaInfo->pTableMeta->uid,}; - - // 3. get the required table column list - SArray* tableColumnList = taosArrayInit(4, sizeof(SColumn)); - columnListCopy(tableColumnList, pQueryInfo->colList, uid); - - // 4. add the projection query node - SQueryPlanNode* pNode = doAddTableColumnNode(pQueryInfo, &info, exprList, tableColumnList); - columnListDestroy(tableColumnList); - taosArrayPush(pDownstream, &pNode); - } - - // 3. add the join node here - SQueryTableInfo info = {0}; - int32_t num = (int32_t) taosArrayGetSize(pQueryInfo->exprList[0]); - SQueryPlanNode* pNode = createQueryNode(QNODE_JOIN, "Join", pDownstream->pData, pQueryInfo->numOfTables, - pQueryInfo->exprList[0]->pData, num, NULL); - - // 4. add the aggregation or projection execution node - pNode = doCreateQueryPlanForSingleTableImpl(pQueryInfo, pNode, &info); - pDownstream = taosArrayInit(5, POINTER_BYTES); - taosArrayPush(pDownstream, &pNode); - } else { // only one table, normal query process - STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[0]; - SQueryPlanNode* pNode = doCreateQueryPlanForSingleTable(pQueryInfo, pTableMetaInfo, pQueryInfo->exprList[0], pQueryInfo->colList); - pDownstream = taosArrayInit(5, POINTER_BYTES); - taosArrayPush(pDownstream, &pNode); - } - - return pDownstream; -} - -static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) { - int32_t type = queryNodeType(pQueryNode); - if (type == QNODE_MODIFY) { - SDataPayloadInfo* pInfo = pQueryNode->pExtInfo; - - size_t size = taosArrayGetSize(pInfo->payload); - for (int32_t i = 0; i < size; ++i) { - SVgDataBlocks* pBlock = taosArrayGetP(pInfo->payload, i); - tfree(pBlock); - } - - taosArrayDestroy(pInfo->payload); - } - - if (type == QNODE_STREAMSCAN || type == QNODE_TABLESCAN) { - SQueryTableInfo* pQueryTableInfo = pQueryNode->pExtInfo; - tfree(pQueryTableInfo->tableName); - } - - taosArrayDestroy(pQueryNode->pExpr); - - tfree(pQueryNode->pExtInfo); - tfree(pQueryNode->pSchema); - tfree(pQueryNode->info.name); - - if (pQueryNode->pChildren != NULL) { - int32_t size = (int32_t) taosArrayGetSize(pQueryNode->pChildren); - for(int32_t i = 0; i < size; ++i) { - SQueryPlanNode* p = taosArrayGetP(pQueryNode->pChildren, i); - doDestroyQueryNode(p); - } - - taosArrayDestroy(pQueryNode->pChildren); - } - - tfree(pQueryNode); -} - -static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level, int32_t totalLen) { - if (level > 0) { - sprintf(buf + totalLen, "%*c", level, ' '); - totalLen += level; - } - - int32_t len1 = sprintf(buf + totalLen, "%s(", pQueryNode->info.name); - int32_t len = len1 + totalLen; - - switch(pQueryNode->info.type) { - case QNODE_STREAMSCAN: - case QNODE_TABLESCAN: { - SQueryTableInfo* pInfo = (SQueryTableInfo*)pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "%s #%" PRIu64, pInfo->tableName, pInfo->uid); - assert(len1 > 0); - len += len1; - - len1 = sprintf(buf + len, " , cols:"); - assert(len1 > 0); - len += len1; - - len = printExprInfo(buf, pQueryNode, len); - len1 = sprintf(buf + len, ")"); - assert(len1 > 0); - - // todo print filter info - len1 = sprintf(buf + len, ") filters:(nil)"); - len += len1; - - len1 = sprintf(buf + len, " time_range: %" PRId64 " - %" PRId64"\n", pInfo->window.skey, pInfo->window.ekey); - len += len1; - break; - } - - case QNODE_PROJECT: { - len1 = sprintf(buf + len, "cols:"); - assert(len1 > 0); - len += len1; - - len = printExprInfo(buf, pQueryNode, len); - len1 = sprintf(buf + len, ")"); - len += len1; - - // todo print filter info - len1 = sprintf(buf + len, " filters:(nil)\n"); - len += len1; - break; - } - - case QNODE_AGGREGATE: { - len = printExprInfo(buf, pQueryNode, len); - len1 = sprintf(buf + len, ")\n"); - len += len1; - - break; - } - - case QNODE_TIMEWINDOW: { - len = printExprInfo(buf, pQueryNode, len); - len1 = sprintf(buf + len, ") "); - len += len1; - - SInterval* pInterval = pQueryNode->pExtInfo; - - // todo dynamic return the time precision - len1 = sprintf(buf + len, "interval:%" PRId64 "(%s), sliding:%" PRId64 "(%s), offset:%" PRId64 "(%s)\n", - pInterval->interval, TSDB_TIME_PRECISION_MILLI_STR, pInterval->sliding, - TSDB_TIME_PRECISION_MILLI_STR, pInterval->offset, TSDB_TIME_PRECISION_MILLI_STR); - len += len1; - - break; - } - - case QNODE_STATEWINDOW: { - len = printExprInfo(buf, pQueryNode, len); - len1 = sprintf(buf + len, ") "); - len += len1; - - SColumn* pCol = pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "col:%s #%d\n", pCol->name, pCol->info.colId); - len += len1; - break; - } - - case QNODE_SESSIONWINDOW: { - len = printExprInfo(buf, pQueryNode, len); - - len1 = sprintf(buf + len, ") "); - len += len1; - - struct SSessionWindow* ps = pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "col:[%s #%d], gap:%" PRId64 " (ms) \n", ps->col.name, ps->col.info.colId, ps->gap); - len += len1; - break; - } - - case QNODE_GROUPBY: { - len = printExprInfo(buf, pQueryNode, len); - - SGroupbyExpr* pGroupbyExpr = pQueryNode->pExtInfo; - len1 = sprintf(buf + len, ") groupby_col: "); - len += len1; - - for (int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) { - SColumn* pCol = taosArrayGet(pGroupbyExpr->columnInfo, i); - len1 = sprintf(buf + len, "[%s #%d] ", pCol->name, pCol->info.colId); - len += len1; - } - - len += sprintf(buf + len, "\n"); - break; - } - - case QNODE_FILL: { - SFillEssInfo* pEssInfo = pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "%d", pEssInfo->fillType); - len += len1; - - if (pEssInfo->fillType == TSDB_FILL_SET_VALUE) { - len1 = sprintf(buf + len, ", val:"); - len += len1; - - // todo get the correct fill data type - for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - len1 = sprintf(buf + len, "%" PRId64, pEssInfo->val[i]); - len += len1; - - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len, ", "); - len += len1; - } - } - } - - len1 = sprintf(buf + len, ")\n"); - len += len1; - break; - } - - case QNODE_LIMIT: { - SLimit* pVal = pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "limit: %" PRId64 ", offset: %" PRId64 ")\n", pVal->limit, pVal->offset); - len += len1; - break; - } - - case QNODE_DISTINCT: - case QNODE_TAGSCAN: { - len1 = sprintf(buf + len, "cols: "); - len += len1; - - len = printExprInfo(buf, pQueryNode, len); - - len1 = sprintf(buf + len, ")\n"); - len += len1; - - break; - } - - case QNODE_SORT: { - len1 = sprintf(buf + len, "cols:"); - len += len1; - - SArray* pSort = pQueryNode->pExtInfo; - for (int32_t i = 0; i < taosArrayGetSize(pSort); ++i) { - SOrder* p = taosArrayGet(pSort, i); - len1 = sprintf(buf + len, " [%s #%d %s]", p->col.name, p->col.info.colId, p->order == TSDB_ORDER_ASC? "ASC":"DESC"); - - len += len1; - } - - len1 = sprintf(buf + len, ")\n"); - len += len1; - break; - } - - case QNODE_JOIN: { - // print join condition - len1 = sprintf(buf + len, ")\n"); - len += len1; - break; - } - } - - return len; -} - -int32_t printExprInfo(char* buf, const SQueryPlanNode* pQueryNode, int32_t len) { - int32_t len1 = 0; - - for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - - SSqlExpr* pExpr = &pExprInfo->base; - len1 = sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); - assert(len1 > 0); - - len += len1; - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len, ", "); - len += len1; - } - } - - return len; -} - -int32_t queryPlanToStringImpl(char* buf, SQueryPlanNode* pQueryNode, int32_t level, int32_t totalLen) { - int32_t len = doPrintPlan(buf, pQueryNode, level, totalLen); - - for(int32_t i = 0; i < taosArrayGetSize(pQueryNode->pChildren); ++i) { - SQueryPlanNode* p1 = taosArrayGetP(pQueryNode->pChildren, i); - int32_t len1 = queryPlanToStringImpl(buf, p1, level + 1, len); - len = len1; - } - - return len; -} - -int32_t queryPlanToString(struct SQueryPlanNode* pQueryNode, char** str) { - assert(pQueryNode); - *str = calloc(1, 4096); - - int32_t len = sprintf(*str, "===== logic plan =====\n"); - queryPlanToStringImpl(*str, pQueryNode, 0, len); - - return TSDB_CODE_SUCCESS; -} - -SQueryPlanNode* queryPlanFromString() { - return NULL; -} diff --git a/source/libs/planner/src/physicalPlan.c b/source/libs/planner/src/physicalPlan.c deleted file mode 100644 index dbc0340b348f09e2143ea26dcd9331e0622e6f43..0000000000000000000000000000000000000000 --- a/source/libs/planner/src/physicalPlan.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "plannerInt.h" -#include "texception.h" -#include "parser.h" - -#define STORE_CURRENT_SUBPLAN(cxt) SSubplan* _ = cxt->pCurrentSubplan -#define RECOVERY_CURRENT_SUBPLAN(cxt) cxt->pCurrentSubplan = _ - -typedef struct SPlanContext { - struct SCatalog* pCatalog; - struct SQueryDag* pDag; - SSubplan* pCurrentSubplan; - SSubplanId nextId; -} SPlanContext; - -static const char* gOpName[] = { - "Unknown", -#define INCLUDE_AS_NAME -#include "plannerOp.h" -#undef INCLUDE_AS_NAME -}; - -static void* validPointer(void* p) { - if (NULL == p) { - THROW(TSDB_CODE_TSC_OUT_OF_MEMORY); - } - return p; -} - -const char* opTypeToOpName(int32_t type) { - return gOpName[type]; -} - -int32_t opNameToOpType(const char* name) { - for (int32_t i = 1; i < sizeof(gOpName) / sizeof(gOpName[0]); ++i) { - if (0 == strcmp(name, gOpName[i])) { - return i; - } - } - return OP_Unknown; -} - -const char* dsinkTypeToDsinkName(int32_t type) { - switch (type) { - case DSINK_Dispatch: - return "Dispatch"; - case DSINK_Insert: - return "Insert"; - default: - break; - } - return "Unknown"; -} - -int32_t dsinkNameToDsinkType(const char* name) { - if (0 == strcmp(name, "Dispatch")) { - return DSINK_Dispatch; - } else if (0 == strcmp(name, "Insert")) { - return DSINK_Insert; - } - return DSINK_Unknown; -} - -static bool copySchema(SDataBlockSchema* dst, const SDataBlockSchema* src) { - dst->pSchema = malloc(sizeof(SSlotSchema) * src->numOfCols); - if (NULL == dst->pSchema) { - return false; - } - memcpy(dst->pSchema, src->pSchema, sizeof(SSlotSchema) * src->numOfCols); - dst->numOfCols = src->numOfCols; - dst->resultRowSize = src->resultRowSize; - dst->precision = src->precision; - return true; -} - -static bool toDataBlockSchema(SQueryPlanNode* pPlanNode, SDataBlockSchema* dataBlockSchema) { - dataBlockSchema->numOfCols = pPlanNode->numOfExpr; - dataBlockSchema->pSchema = malloc(sizeof(SSlotSchema) * pPlanNode->numOfExpr); - if (NULL == dataBlockSchema->pSchema) { - return false; - } - - dataBlockSchema->resultRowSize = 0; - for (int32_t i = 0; i < pPlanNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pPlanNode->pExpr, i); - memcpy(&dataBlockSchema->pSchema[i], &pExprInfo->base.resSchema, sizeof(SSlotSchema)); - - dataBlockSchema->resultRowSize += dataBlockSchema->pSchema[i].bytes; - } - - return true; -} - -static bool cloneExprArray(SArray** dst, SArray* src) { - if (NULL == src) { - return true; - } - size_t size = taosArrayGetSize(src); - if (0 == size) { - return true; - } - *dst = taosArrayInit(size, POINTER_BYTES); - if (NULL == *dst) { - return false; - } - return (TSDB_CODE_SUCCESS == copyAllExprInfo(*dst, src, true) ? true : false); -} - -static SDataSink* initDataSink(int32_t type, int32_t size, const SPhyNode* pRoot) { - SDataSink* sink = (SDataSink*)validPointer(calloc(1, size)); - sink->info.type = type; - sink->info.name = dsinkTypeToDsinkName(type); - if (NULL !=pRoot && !copySchema(&sink->schema, &pRoot->targetSchema)) { - tfree(sink); - THROW(TSDB_CODE_TSC_OUT_OF_MEMORY); - } - return sink; -} - -static SDataSink* createDataInserter(SPlanContext* pCxt, SVgDataBlocks* pBlocks, const SPhyNode* pRoot) { - SDataInserter* inserter = (SDataInserter*)initDataSink(DSINK_Insert, sizeof(SDataInserter), pRoot); - inserter->numOfTables = pBlocks->numOfTables; - inserter->size = pBlocks->size; - TSWAP(inserter->pData, pBlocks->pData, char*); - return (SDataSink*)inserter; -} - -static SDataSink* createDataDispatcher(SPlanContext* pCxt, SQueryPlanNode* pPlanNode, const SPhyNode* pRoot) { - SDataDispatcher* dispatcher = (SDataDispatcher*)initDataSink(DSINK_Dispatch, sizeof(SDataDispatcher), pRoot); - return (SDataSink*)dispatcher; -} - -static SPhyNode* initPhyNode(SQueryPlanNode* pPlanNode, int32_t type, int32_t size) { - SPhyNode* node = (SPhyNode*)validPointer(calloc(1, size)); - node->info.type = type; - node->info.name = opTypeToOpName(type); - if (!cloneExprArray(&node->pTargets, pPlanNode->pExpr) || !toDataBlockSchema(pPlanNode, &(node->targetSchema))) { - free(node); - THROW(TSDB_CODE_TSC_OUT_OF_MEMORY); - } - return node; -} - -static void cleanupPhyNode(SPhyNode* pPhyNode) { - if (pPhyNode == NULL) { - return; - } - - dropOneLevelExprInfo(pPhyNode->pTargets); - tfree(pPhyNode->targetSchema.pSchema); - tfree(pPhyNode); -} - -static SPhyNode* initScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable, int32_t type, int32_t size) { - SScanPhyNode* node = (SScanPhyNode*) initPhyNode(pPlanNode, type, size); - - STableMeta *pTableMeta = pTable->pMeta->pTableMeta; - node->uid = pTableMeta->uid; - node->count = 1; - node->order = TSDB_ORDER_ASC; - node->tableType = pTableMeta->tableType; - - return (SPhyNode*)node; -} - -static SPhyNode* createPseudoScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable, int32_t op) { - return initScanNode(pPlanNode, pTable, op, sizeof(SScanPhyNode)); -} - -static SPhyNode* createTagScanNode(SQueryPlanNode* pPlanNode) { - SQueryTableInfo* pTable = (SQueryTableInfo*)pPlanNode->pExtInfo; - return createPseudoScanNode(pPlanNode, pTable, OP_TagScan); -} - -static uint8_t getScanFlag(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable) { - // todo - return MAIN_SCAN; -} - -static SPhyNode* createUserTableScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pQueryTableInfo, int32_t op) { - STableScanPhyNode* node = (STableScanPhyNode*)initScanNode(pPlanNode, pQueryTableInfo, op, sizeof(STableScanPhyNode)); - node->scanFlag = getScanFlag(pPlanNode, pQueryTableInfo); - node->window = pQueryTableInfo->window; - // todo tag cond - return (SPhyNode*)node; -} - - -static bool isSystemTable(SQueryTableInfo* pTable) { - // todo - return false; -} - -static bool needSeqScan(SQueryPlanNode* pPlanNode) { - // todo - return false; -} - -static SPhyNode* createMultiTableScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable) { - if (isSystemTable(pTable)) { - return createPseudoScanNode(pPlanNode, pTable, OP_SystemTableScan); - } else if (needSeqScan(pPlanNode)) { - return createUserTableScanNode(pPlanNode, pTable, OP_TableSeqScan); - } - int32_t type = (pPlanNode->info.type == QNODE_TABLESCAN)? OP_TableScan:OP_StreamScan; - return createUserTableScanNode(pPlanNode, pTable, type); -} - -static SSubplan* initSubplan(SPlanContext* pCxt, int32_t type) { - SSubplan* subplan = validPointer(calloc(1, sizeof(SSubplan))); - subplan->id = pCxt->nextId; - ++(pCxt->nextId.subplanId); - - subplan->type = type; - subplan->level = 0; - if (NULL != pCxt->pCurrentSubplan) { - subplan->level = pCxt->pCurrentSubplan->level + 1; - if (NULL == pCxt->pCurrentSubplan->pChildren) { - pCxt->pCurrentSubplan->pChildren = validPointer(taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES)); - } - - taosArrayPush(pCxt->pCurrentSubplan->pChildren, &subplan); - subplan->pParents = validPointer(taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES)); - taosArrayPush(subplan->pParents, &pCxt->pCurrentSubplan); - } - - SArray* currentLevel; - if (subplan->level >= taosArrayGetSize(pCxt->pDag->pSubplans)) { - currentLevel = validPointer(taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES)); - taosArrayPush(pCxt->pDag->pSubplans, ¤tLevel); - } else { - currentLevel = taosArrayGetP(pCxt->pDag->pSubplans, subplan->level); - } - - taosArrayPush(currentLevel, &subplan); - pCxt->pCurrentSubplan = subplan; - ++(pCxt->pDag->numOfSubplans); - return subplan; -} - -static void vgroupInfoToNodeAddr(const SVgroupInfo* vg, SQueryNodeAddr* pNodeAddr) { - pNodeAddr->nodeId = vg->vgId; - pNodeAddr->epSet = vg->epSet; -} - -static uint64_t splitSubplanByTable(SPlanContext* pCxt, SQueryPlanNode* pPlanNode, SQueryTableInfo* pTableInfo) { - SVgroupsInfo* pVgroupList = pTableInfo->pMeta->vgroupList; - for (int32_t i = 0; i < pVgroupList->numOfVgroups; ++i) { - STORE_CURRENT_SUBPLAN(pCxt); - SSubplan* subplan = initSubplan(pCxt, QUERY_TYPE_SCAN); - subplan->msgType = TDMT_VND_QUERY; - - vgroupInfoToNodeAddr(&(pTableInfo->pMeta->vgroupList->vgroups[i]), &subplan->execNode); - subplan->pNode = createMultiTableScanNode(pPlanNode, pTableInfo); - subplan->pDataSink = createDataDispatcher(pCxt, pPlanNode, subplan->pNode); - RECOVERY_CURRENT_SUBPLAN(pCxt); - } - return pCxt->nextId.templateId++; -} - -static SPhyNode* createExchangeNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode, uint64_t srcTemplateId) { - SExchangePhyNode* node = (SExchangePhyNode*)initPhyNode(pPlanNode, OP_Exchange, sizeof(SExchangePhyNode)); - node->srcTemplateId = srcTemplateId; - node->pSrcEndPoints = validPointer(taosArrayInit(TARRAY_MIN_SIZE, sizeof(SDownstreamSource))); - return (SPhyNode*)node; -} - -static bool needMultiNodeScan(SQueryTableInfo* pTable) { - // todo system table, for instance, user_tables - return (TSDB_SUPER_TABLE == pTable->pMeta->pTableMeta->tableType); -} - -// TODO: the SVgroupInfo index -static SPhyNode* createSingleTableScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTableInfo, SSubplan* subplan) { - SVgroupsInfo* pVgroupsInfo = pTableInfo->pMeta->vgroupList; - vgroupInfoToNodeAddr(&(pVgroupsInfo->vgroups[0]), &subplan->execNode); - int32_t type = (pPlanNode->info.type == QNODE_TABLESCAN)? OP_TableScan:OP_StreamScan; - return createUserTableScanNode(pPlanNode, pTableInfo, type); -} - -static SPhyNode* createTableScanNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) { - SQueryTableInfo* pTable = (SQueryTableInfo*)pPlanNode->pExtInfo; - if (needMultiNodeScan(pTable)) { - return createExchangeNode(pCxt, pPlanNode, splitSubplanByTable(pCxt, pPlanNode, pTable)); - } - - return createSingleTableScanNode(pPlanNode, pTable, pCxt->pCurrentSubplan); -} - -static SPhyNode* createSingleTableAgg(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) { - SAggPhyNode* node = (SAggPhyNode*)initPhyNode(pPlanNode, OP_Aggregate, sizeof(SAggPhyNode)); - SGroupbyExpr* pGroupBy = (SGroupbyExpr*)pPlanNode->pExtInfo; - node->aggAlgo = AGG_ALGO_PLAIN; - node->aggSplit = AGG_SPLIT_FINAL; - if (NULL != pGroupBy) { - node->aggAlgo = AGG_ALGO_HASHED; - node->pGroupByList = validPointer(taosArrayDup(pGroupBy->columnInfo)); - } - return (SPhyNode*)node; -} - -static SPhyNode* createAggNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) { - // if (needMultiNodeAgg(pPlanNode)) { - - // } - return createSingleTableAgg(pCxt, pPlanNode); -} - -static SPhyNode* createPhyNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) { - SPhyNode* node = NULL; - switch (pPlanNode->info.type) { - case QNODE_TAGSCAN: - node = createTagScanNode(pPlanNode); - break; - case QNODE_STREAMSCAN: - case QNODE_TABLESCAN: - node = createTableScanNode(pCxt, pPlanNode); - break; - case QNODE_AGGREGATE: - case QNODE_GROUPBY: - node = createAggNode(pCxt, pPlanNode); - break; - case QNODE_MODIFY: - // Insert is not an operator in a physical plan. - break; - default: - assert(false); - } - - if (pPlanNode->pChildren != NULL && taosArrayGetSize(pPlanNode->pChildren) > 0) { - node->pChildren = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); - size_t size = taosArrayGetSize(pPlanNode->pChildren); - for(int32_t i = 0; i < size; ++i) { - SPhyNode* child = createPhyNode(pCxt, taosArrayGetP(pPlanNode->pChildren, i)); - child->pParent = node; - taosArrayPush(node->pChildren, &child); - } - } - - return node; -} - -static void splitModificationOpSubPlan(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) { - SDataPayloadInfo* pPayload = (SDataPayloadInfo*) pPlanNode->pExtInfo; - - size_t numOfVgroups = taosArrayGetSize(pPayload->payload); - for (int32_t i = 0; i < numOfVgroups; ++i) { - STORE_CURRENT_SUBPLAN(pCxt); - SSubplan* subplan = initSubplan(pCxt, QUERY_TYPE_MODIFY); - SVgDataBlocks* blocks = (SVgDataBlocks*)taosArrayGetP(pPayload->payload, i); - - subplan->execNode.epSet = blocks->vg.epSet; - subplan->pDataSink = createDataInserter(pCxt, blocks, NULL); - subplan->pNode = NULL; - subplan->type = QUERY_TYPE_MODIFY; - subplan->msgType = pPayload->msgType; - subplan->id.queryId = pCxt->pDag->queryId; - - RECOVERY_CURRENT_SUBPLAN(pCxt); - } -} - -static void createSubplanByLevel(SPlanContext* pCxt, SQueryPlanNode* pRoot) { - if (QNODE_MODIFY == pRoot->info.type) { - splitModificationOpSubPlan(pCxt, pRoot); - } else { - SSubplan* subplan = initSubplan(pCxt, QUERY_TYPE_SCAN); - ++(pCxt->nextId.templateId); - - subplan->msgType = TDMT_VND_QUERY; - subplan->pNode = createPhyNode(pCxt, pRoot); - subplan->pDataSink = createDataDispatcher(pCxt, pRoot, subplan->pNode); - } - // todo deal subquery -} - -static void postCreateDag(SQueryPlanNode* pQueryNode, SQueryDag* pDag, SArray* pNodeList) { - // The exchange operator is not necessary, in case of the stream scan. - // Here we need to remove it from the DAG. - if (pQueryNode->info.type == QNODE_STREAMSCAN) { - SArray* pRootLevel = taosArrayGetP(pDag->pSubplans, 0); - SSubplan *pSubplan = taosArrayGetP(pRootLevel, 0); - - if (pSubplan->pNode->info.type == OP_Exchange) { - ASSERT(taosArrayGetSize(pRootLevel) == 1); - - taosArrayRemove(pDag->pSubplans, 0); - // And then update the number of the subplans. - pDag->numOfSubplans -= 1; - } - } else { - // Traverse the dag again to acquire the execution node. - if (pNodeList != NULL) { - SArray** pSubLevel = taosArrayGetLast(pDag->pSubplans); - size_t num = taosArrayGetSize(*pSubLevel); - for (int32_t j = 0; j < num; ++j) { - SSubplan* pPlan = taosArrayGetP(*pSubLevel, j); - taosArrayPush(pNodeList, &pPlan->execNode); - } - } - } -} - -int32_t createDag(SQueryPlanNode* pQueryNode, struct SCatalog* pCatalog, SQueryDag** pDag, SArray* pNodeList, uint64_t requestId) { - TRY(TSDB_MAX_TAG_CONDITIONS) { - SPlanContext context = { - .pCatalog = pCatalog, - .pDag = validPointer(calloc(1, sizeof(SQueryDag))), - .pCurrentSubplan = NULL, - //The unsigned Id starting from 1 would be better - .nextId = {.queryId = requestId, .subplanId = 1, .templateId = 1}, - }; - - *pDag = context.pDag; - context.pDag->queryId = requestId; - - context.pDag->pSubplans = validPointer(taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES)); - createSubplanByLevel(&context, pQueryNode); - } CATCH(code) { - CLEANUP_EXECUTE(); - terrno = code; - return TSDB_CODE_FAILED; - } END_TRY - - postCreateDag(pQueryNode, *pDag, pNodeList); - return TSDB_CODE_SUCCESS; -} - -void setExchangSourceNode(uint64_t templateId, SDownstreamSource *pSource, SPhyNode* pNode) { - if (NULL == pNode) { - return; - } - if (OP_Exchange == pNode->info.type) { - SExchangePhyNode* pExchange = (SExchangePhyNode*)pNode; - if (templateId == pExchange->srcTemplateId) { - taosArrayPush(pExchange->pSrcEndPoints, pSource); - } - } - - if (pNode->pChildren != NULL) { - size_t size = taosArrayGetSize(pNode->pChildren); - for(int32_t i = 0; i < size; ++i) { - setExchangSourceNode(templateId, pSource, taosArrayGetP(pNode->pChildren, i)); - } - } -} - -void setSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource) { - setExchangSourceNode(templateId, pSource, subplan->pNode); -} - -static void destroyDataSinkNode(SDataSink* pSinkNode) { - if (pSinkNode == NULL) { - return; - } - - if (queryNodeType(pSinkNode) == DSINK_Dispatch) { - SDataDispatcher* pDdSink = (SDataDispatcher*)pSinkNode; - tfree(pDdSink->sink.schema.pSchema); - } - - tfree(pSinkNode); -} - -void qDestroySubplan(SSubplan* pSubplan) { - if (pSubplan == NULL) { - return; - } - - taosArrayDestroy(pSubplan->pChildren); - taosArrayDestroy(pSubplan->pParents); - destroyDataSinkNode(pSubplan->pDataSink); - cleanupPhyNode(pSubplan->pNode); - - tfree(pSubplan); -} diff --git a/source/libs/planner/src/physicalPlanJson.c b/source/libs/planner/src/physicalPlanJson.c deleted file mode 100644 index 40187410916724f8689928ecd8610677d209b84d..0000000000000000000000000000000000000000 --- a/source/libs/planner/src/physicalPlanJson.c +++ /dev/null @@ -1,1240 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "cJSON.h" -#include "parser.h" -#include "plannerInt.h" - -typedef bool (*FToJson)(const void* obj, cJSON* json); -typedef bool (*FFromJson)(const cJSON* json, void* obj); - -static char* getString(const cJSON* json, const char* name) { - char* p = cJSON_GetStringValue(cJSON_GetObjectItem(json, name)); - return strdup(p); -} - -static void copyString(const cJSON* json, const char* name, char* dst) { - strcpy(dst, cJSON_GetStringValue(cJSON_GetObjectItem(json, name))); -} - -static uint64_t getBigintFromString(const cJSON* json, const char* name) { - char* val = getString(json, name); - uint64_t intVal = strtoul(val, NULL, 10); - tfree(val); - - return intVal; -} - -static int64_t getNumber(const cJSON* json, const char* name) { - double d = cJSON_GetNumberValue(cJSON_GetObjectItem(json, name)); - return (int64_t)d; -} - -static bool addObject(cJSON* json, const char* name, FToJson func, const void* obj) { - if (NULL == obj) { - return true; - } - - cJSON* jObj = cJSON_CreateObject(); - if (NULL == jObj || !func(obj, jObj)) { - cJSON_Delete(jObj); - return false; - } - return cJSON_AddItemToObject(json, name, jObj); -} - -static bool addItem(cJSON* json, FToJson func, const void* obj) { - cJSON* jObj = cJSON_CreateObject(); - if (NULL == jObj || !func(obj, jObj)) { - cJSON_Delete(jObj); - return false; - } - return cJSON_AddItemToArray(json, jObj); -} - -static bool fromObject(const cJSON* json, const char* name, FFromJson func, void* obj, bool required) { - cJSON* jObj = cJSON_GetObjectItem(json, name); - if (NULL == jObj) { - return !required; - } - return func(jObj, obj); -} - -static bool fromObjectWithAlloc(const cJSON* json, const char* name, FFromJson func, void** obj, int32_t size, - bool required) { - cJSON* jObj = cJSON_GetObjectItem(json, name); - if (NULL == jObj) { - return !required; - } - *obj = calloc(1, size); - if (NULL == *obj) { - return false; - } - return func(jObj, *obj); -} - -static const char* jkPnodeType = "Type"; -static int32_t getPnodeTypeSize(cJSON* json) { - switch (getNumber(json, jkPnodeType)) { - case OP_StreamScan: - case OP_TableScan: - case OP_TableSeqScan: - return sizeof(STableScanPhyNode); - case OP_TagScan: - return sizeof(STagScanPhyNode); - case OP_SystemTableScan: - return sizeof(SSystemTableScanPhyNode); - case OP_Aggregate: - return sizeof(SAggPhyNode); - case OP_Exchange: - return sizeof(SExchangePhyNode); - default: - break; - }; - return -1; -} - -static bool fromPnode(const cJSON* json, const char* name, FFromJson func, void** obj) { - cJSON* jObj = cJSON_GetObjectItem(json, name); - if (NULL == jObj) { - return true; - } - *obj = calloc(1, getPnodeTypeSize(jObj)); - if (NULL == *obj) { - return false; - } - return func(jObj, *obj); -} - -static bool fromPnodeArray(const cJSON* json, const char* name, FFromJson func, SArray** array) { - const cJSON* jArray = cJSON_GetObjectItem(json, name); - int32_t size = (NULL == jArray ? 0 : cJSON_GetArraySize(jArray)); - if (size > 0) { - *array = taosArrayInit(size, POINTER_BYTES); - if (NULL == *array) { - return false; - } - } - for (int32_t i = 0; i < size; ++i) { - cJSON* jItem = cJSON_GetArrayItem(jArray, i); - void* item = calloc(1, getPnodeTypeSize(jItem)); - if (NULL == item || !func(jItem, item)) { - return false; - } - taosArrayPush(*array, &item); - } - return true; -} - -static bool addTarray(cJSON* json, const char* name, FToJson func, const SArray* array, bool isPoint) { - size_t size = (NULL == array) ? 0 : taosArrayGetSize(array); - if (size > 0) { - cJSON* jArray = cJSON_AddArrayToObject(json, name); - if (NULL == jArray) { - return false; - } - for (size_t i = 0; i < size; ++i) { - if (!addItem(jArray, func, isPoint ? taosArrayGetP(array, i) : taosArrayGet(array, i))) { - return false; - } - } - } - return true; -} - -static bool addInlineArray(cJSON* json, const char* name, FToJson func, const SArray* array) { - return addTarray(json, name, func, array, false); -} - -static bool addArray(cJSON* json, const char* name, FToJson func, const SArray* array) { - return addTarray(json, name, func, array, true); -} - -static bool fromTarray(const cJSON* json, const char* name, FFromJson func, SArray** array, int32_t itemSize, - bool isPoint) { - const cJSON* jArray = cJSON_GetObjectItem(json, name); - int32_t size = (NULL == jArray ? 0 : cJSON_GetArraySize(jArray)); - if (size > 0) { - *array = taosArrayInit(size, isPoint ? POINTER_BYTES : itemSize); - if (NULL == *array) { - return false; - } - } - for (int32_t i = 0; i < size; ++i) { - void* item = calloc(1, itemSize); - if (NULL == item || !func(cJSON_GetArrayItem(jArray, i), item)) { - return false; - } - taosArrayPush(*array, isPoint ? &item : item); - } - return true; -} - -static bool fromInlineArray(const cJSON* json, const char* name, FFromJson func, SArray** array, int32_t itemSize) { - return fromTarray(json, name, func, array, itemSize, false); -} - -static bool fromArray(const cJSON* json, const char* name, FFromJson func, SArray** array, int32_t itemSize) { - return fromTarray(json, name, func, array, itemSize, true); -} - -static bool addRawArray(cJSON* json, const char* name, FToJson func, const void* array, int32_t itemSize, - int32_t size) { - if (size > 0) { - cJSON* jArray = cJSON_AddArrayToObject(json, name); - if (NULL == jArray) { - return false; - } - for (size_t i = 0; i < size; ++i) { - if (!addItem(jArray, func, (const char*)array + itemSize * i)) { - return false; - } - } - } - return true; -} - -static const cJSON* getArray(const cJSON* json, const char* name, int32_t* size) { - const cJSON* jArray = cJSON_GetObjectItem(json, name); - *size = (NULL == jArray ? 0 : cJSON_GetArraySize(jArray)); - return jArray; -} - -static bool fromItem(const cJSON* jArray, FFromJson func, void* array, int32_t itemSize, int32_t size) { - for (int32_t i = 0; i < size; ++i) { - if (!func(cJSON_GetArrayItem(jArray, i), (char*)array + itemSize * i)) { - return false; - } - } - return true; -} - -static bool fromRawArrayWithAlloc(const cJSON* json, const char* name, FFromJson func, void** array, int32_t itemSize, - int32_t* size) { - const cJSON* jArray = getArray(json, name, size); - if (*size > 0) { - *array = calloc(1, itemSize * (*size)); - if (NULL == *array) { - return false; - } - } - return fromItem(jArray, func, *array, itemSize, *size); -} - -static bool fromRawArray(const cJSON* json, const char* name, FFromJson func, void* array, int32_t itemSize, - int32_t* size) { - const cJSON* jArray = getArray(json, name, size); - return fromItem(jArray, func, array, itemSize, *size); -} - -static const char* jkSchemaType = "Type"; -static const char* jkSchemaColId = "ColId"; -static const char* jkSchemaBytes = "Bytes"; -// The 'name' field do not need to be serialized. -static bool schemaToJson(const void* obj, cJSON* jSchema) { - const SSlotSchema* schema = (const SSlotSchema*)obj; - bool res = cJSON_AddNumberToObject(jSchema, jkSchemaType, schema->type); - if (res) { - res = cJSON_AddNumberToObject(jSchema, jkSchemaColId, schema->colId); - } - if (res) { - res = cJSON_AddNumberToObject(jSchema, jkSchemaBytes, schema->bytes); - } - return res; -} - -static bool schemaFromJson(const cJSON* json, void* obj) { - SSlotSchema* schema = (SSlotSchema*)obj; - schema->type = getNumber(json, jkSchemaType); - schema->colId = getNumber(json, jkSchemaColId); - schema->bytes = getNumber(json, jkSchemaBytes); - return true; -} - -static const char* jkDataBlockSchemaSlotSchema = "SlotSchema"; -static const char* jkDataBlockSchemaResultRowSize = "resultRowSize"; -static const char* jkDataBlockSchemaPrecision = "Precision"; - -static bool dataBlockSchemaToJson(const void* obj, cJSON* json) { - const SDataBlockSchema* schema = (const SDataBlockSchema*)obj; - bool res = addRawArray(json, jkDataBlockSchemaSlotSchema, schemaToJson, schema->pSchema, sizeof(SSlotSchema), - schema->numOfCols); - if (res) { - res = cJSON_AddNumberToObject(json, jkDataBlockSchemaResultRowSize, schema->resultRowSize); - } - if (res) { - res = cJSON_AddNumberToObject(json, jkDataBlockSchemaPrecision, schema->precision); - } - return res; -} - -static bool dataBlockSchemaFromJson(const cJSON* json, void* obj) { - SDataBlockSchema* schema = (SDataBlockSchema*)obj; - schema->resultRowSize = getNumber(json, jkDataBlockSchemaResultRowSize); - schema->precision = getNumber(json, jkDataBlockSchemaPrecision); - - return fromRawArrayWithAlloc(json, jkDataBlockSchemaSlotSchema, schemaFromJson, (void**)&(schema->pSchema), - sizeof(SSlotSchema), &schema->numOfCols); -} - -static const char* jkColumnFilterInfoLowerRelOptr = "LowerRelOptr"; -static const char* jkColumnFilterInfoUpperRelOptr = "UpperRelOptr"; -static const char* jkColumnFilterInfoFilterstr = "Filterstr"; -static const char* jkColumnFilterInfoLowerBnd = "LowerBnd"; -static const char* jkColumnFilterInfoUpperBnd = "UpperBnd"; - -static bool columnFilterInfoToJson(const void* obj, cJSON* jFilter) { - const SColumnFilterInfo* filter = (const SColumnFilterInfo*)obj; - bool res = cJSON_AddNumberToObject(jFilter, jkColumnFilterInfoLowerRelOptr, filter->lowerRelOptr); - if (res) { - res = cJSON_AddNumberToObject(jFilter, jkColumnFilterInfoUpperRelOptr, filter->upperRelOptr); - } - if (res) { - res = cJSON_AddNumberToObject(jFilter, jkColumnFilterInfoFilterstr, filter->filterstr); - } - if (res) { - res = cJSON_AddNumberToObject(jFilter, jkColumnFilterInfoLowerBnd, filter->lowerBndd); - } - if (res) { - res = cJSON_AddNumberToObject(jFilter, jkColumnFilterInfoUpperBnd, filter->upperBndd); - } - return res; -} - -static bool columnFilterInfoFromJson(const cJSON* json, void* obj) { - SColumnFilterInfo* filter = (SColumnFilterInfo*)obj; - filter->lowerRelOptr = getNumber(json, jkColumnFilterInfoLowerRelOptr); - filter->upperRelOptr = getNumber(json, jkColumnFilterInfoUpperRelOptr); - filter->filterstr = getNumber(json, jkColumnFilterInfoFilterstr); - filter->lowerBndd = getNumber(json, jkColumnFilterInfoLowerBnd); - filter->upperBndd = getNumber(json, jkColumnFilterInfoUpperBnd); - return true; -} - -static const char* jkColumnInfoColId = "ColId"; -static const char* jkColumnInfoType = "Type"; -static const char* jkColumnInfoBytes = "Bytes"; -static const char* jkColumnInfoFilterList = "FilterList"; - -static bool columnInfoToJson(const void* obj, cJSON* jCol) { - const SColumnInfo* col = (const SColumnInfo*)obj; - bool res = cJSON_AddNumberToObject(jCol, jkColumnInfoColId, col->colId); - if (res) { - res = cJSON_AddNumberToObject(jCol, jkColumnInfoType, col->type); - } - if (res) { - res = cJSON_AddNumberToObject(jCol, jkColumnInfoBytes, col->bytes); - } - - if (res) { // TODO: temporarily disable it - // res = addRawArray(jCol, jkColumnInfoFilterList, columnFilterInfoToJson, col->flist.filterInfo, - // sizeof(SColumnFilterInfo), col->flist.numOfFilters); - } - - return res; -} - -static bool columnInfoFromJson(const cJSON* json, void* obj) { - SColumnInfo* col = (SColumnInfo*)obj; - col->colId = getNumber(json, jkColumnInfoColId); - col->type = getNumber(json, jkColumnInfoType); - col->bytes = getNumber(json, jkColumnInfoBytes); - int32_t size = 0; - bool res = fromRawArrayWithAlloc(json, jkColumnInfoFilterList, columnFilterInfoFromJson, - (void**)&col->flist.filterInfo, sizeof(SColumnFilterInfo), &size); - col->flist.numOfFilters = size; - return res; -} - -static const char* jkColumnTableId = "TableId"; -static const char* jkColumnFlag = "Flag"; -static const char* jkColumnInfo = "Info"; - -static bool columnToJson(const void* obj, cJSON* jCol) { - const SColumn* col = (const SColumn*)obj; - bool res = cJSON_AddNumberToObject(jCol, jkColumnTableId, col->uid); - if (res) { - res = cJSON_AddNumberToObject(jCol, jkColumnFlag, col->flag); - } - if (res) { - res = addObject(jCol, jkColumnInfo, columnInfoToJson, &col->info); - } - return res; -} - -static bool columnFromJson(const cJSON* json, void* obj) { - SColumn* col = (SColumn*)obj; - col->uid = getNumber(json, jkColumnTableId); - col->flag = getNumber(json, jkColumnFlag); - return fromObject(json, jkColumnInfo, columnInfoFromJson, &col->info, true); -} - -static bool exprNodeToJson(const void* obj, cJSON* jExprInfo); -static bool exprNodeFromJson(const cJSON* json, void* obj); - -static const char* jkExprNodeOper = "Oper"; -static const char* jkExprNodeLeft = "Left"; -static const char* jkExprNodeRight = "Right"; - -static bool operatorToJson(const void* obj, cJSON* jOper) { - const tExprNode* exprInfo = (const tExprNode*)obj; - bool res = cJSON_AddNumberToObject(jOper, jkExprNodeOper, exprInfo->_node.optr); - if (res) { - res = addObject(jOper, jkExprNodeLeft, exprNodeToJson, exprInfo->_node.pLeft); - } - if (res) { - res = addObject(jOper, jkExprNodeRight, exprNodeToJson, exprInfo->_node.pRight); - } - return res; -} - -static bool operatorFromJson(const cJSON* json, void* obj) { - tExprNode* exprInfo = (tExprNode*)obj; - exprInfo->_node.optr = getNumber(json, jkExprNodeOper); - bool res = fromObject(json, jkExprNodeLeft, exprNodeFromJson, exprInfo->_node.pLeft, false); - if (res) { - res = fromObject(json, jkExprNodeRight, exprNodeFromJson, exprInfo->_node.pRight, false); - } - return res; -} - -static const char* jkFunctionName = "Name"; -static const char* jkFunctionChild = "Child"; - -static bool functionToJson(const void* obj, cJSON* jFunc) { - const tExprNode* exprInfo = (const tExprNode*)obj; - bool res = cJSON_AddStringToObject(jFunc, jkFunctionName, exprInfo->_function.functionName); - if (res && NULL != exprInfo->_function.pChild) { - res = addRawArray(jFunc, jkFunctionChild, exprNodeToJson, exprInfo->_function.pChild, sizeof(tExprNode*), - exprInfo->_function.num); - } - return res; -} - -static bool functionFromJson(const cJSON* json, void* obj) { - tExprNode* exprInfo = (tExprNode*)obj; - copyString(json, jkFunctionName, exprInfo->_function.functionName); - exprInfo->_function.pChild = calloc(1, sizeof(tExprNode*)); - if (NULL == exprInfo->_function.pChild) { - return false; - } - return fromRawArrayWithAlloc(json, jkFunctionChild, exprNodeFromJson, (void**)exprInfo->_function.pChild, - sizeof(tExprNode*), &exprInfo->_function.num); -} - -static const char* jkVariantType = "Type"; -static const char* jkVariantLen = "Len"; -static const char* jkVariantvalues = "values"; -static const char* jkVariantValue = "Value"; - -static bool variantToJson(const void* obj, cJSON* jVar) { - const SVariant* var = (const SVariant*)obj; - bool res = cJSON_AddNumberToObject(jVar, jkVariantType, var->nType); - if (res) { - res = cJSON_AddNumberToObject(jVar, jkVariantLen, var->nLen); - } - if (res) { - if (0 /* in */) { - res = addArray(jVar, jkVariantvalues, variantToJson, var->arr); - } else if (IS_NUMERIC_TYPE(var->nType)) { - res = cJSON_AddNumberToObject(jVar, jkVariantValue, var->d); - } else { - res = cJSON_AddStringToObject(jVar, jkVariantValue, var->pz); - } - } - return res; -} - -static bool variantFromJson(const cJSON* json, void* obj) { - SVariant* var = (SVariant*)obj; - var->nType = getNumber(json, jkVariantType); - var->nLen = getNumber(json, jkVariantLen); - if (0 /* in */) { - return fromArray(json, jkVariantvalues, variantFromJson, &var->arr, sizeof(SVariant)); - } else if (IS_NUMERIC_TYPE(var->nType)) { - var->d = getNumber(json, jkVariantValue); - } else { - var->pz = getString(json, jkVariantValue); - } - return true; -} - -static const char* jkExprNodeType = "Type"; -static const char* jkExprNodeOperator = "Operator"; -static const char* jkExprNodeFunction = "Function"; -static const char* jkExprNodeColumn = "Column"; -static const char* jkExprNodeValue = "Value"; - -static bool exprNodeToJson(const void* obj, cJSON* jExprInfo) { - const tExprNode* exprInfo = *(const tExprNode**)obj; - bool res = cJSON_AddNumberToObject(jExprInfo, jkExprNodeType, exprInfo->nodeType); - if (res) { - switch (exprInfo->nodeType) { - case TEXPR_BINARYEXPR_NODE: - case TEXPR_UNARYEXPR_NODE: - res = addObject(jExprInfo, jkExprNodeOperator, operatorToJson, exprInfo); - break; - case TEXPR_FUNCTION_NODE: - res = addObject(jExprInfo, jkExprNodeFunction, functionToJson, exprInfo); - break; - case TEXPR_COL_NODE: - res = addObject(jExprInfo, jkExprNodeColumn, schemaToJson, exprInfo->pSchema); - break; - case TEXPR_VALUE_NODE: - res = addObject(jExprInfo, jkExprNodeValue, variantToJson, exprInfo->pVal); - break; - default: - res = false; - break; - } - } - return res; -} - -static bool exprNodeFromJson(const cJSON* json, void* obj) { - tExprNode* exprInfo = (tExprNode*)obj; - exprInfo->nodeType = getNumber(json, jkExprNodeType); - switch (exprInfo->nodeType) { - case TEXPR_BINARYEXPR_NODE: - case TEXPR_UNARYEXPR_NODE: - return fromObject(json, jkExprNodeOperator, operatorFromJson, exprInfo, false); - case TEXPR_FUNCTION_NODE: - return fromObject(json, jkExprNodeFunction, functionFromJson, exprInfo, false); - case TEXPR_COL_NODE: - return fromObjectWithAlloc(json, jkExprNodeColumn, schemaFromJson, (void**)&exprInfo->pSchema, sizeof(SSchema), - false); - case TEXPR_VALUE_NODE: - return fromObject(json, jkExprNodeValue, variantFromJson, exprInfo->pVal, false); - default: - break; - } - return false; -} - -static const char* jkSqlExprSchema = "Schema"; -static const char* jkSqlExprColumns = "Columns"; -static const char* jkSqlExprInterBytes = "InterBytes"; -static const char* jkSqlExprParams = "Params"; -// token does not need to be serialized. -static bool sqlExprToJson(const void* obj, cJSON* jExpr) { - const SSqlExpr* expr = (const SSqlExpr*)obj; - bool res = addObject(jExpr, jkSqlExprSchema, schemaToJson, &expr->resSchema); - if (res) { - res = addRawArray(jExpr, jkSqlExprColumns, columnToJson, expr->pColumns, sizeof(SColumn), expr->numOfCols); - } - if (res) { - res = cJSON_AddNumberToObject(jExpr, jkSqlExprInterBytes, expr->interBytes); - } - if (res) { - res = addRawArray(jExpr, jkSqlExprParams, variantToJson, expr->param, sizeof(SVariant), expr->numOfParams); - } - return res; -} - -static bool sqlExprFromJson(const cJSON* json, void* obj) { - SSqlExpr* expr = (SSqlExpr*)obj; - bool res = fromObject(json, jkSqlExprSchema, schemaFromJson, &expr->resSchema, false); - if (res) { - res = fromRawArrayWithAlloc(json, jkSqlExprColumns, columnFromJson, (void**)&expr->pColumns, sizeof(SColumn), - &expr->numOfCols); - } - if (res) { - expr->interBytes = getNumber(json, jkSqlExprInterBytes); - } - if (res) { - int32_t size = 0; - res = fromRawArray(json, jkSqlExprParams, variantFromJson, expr->param, sizeof(SVariant), &size); - expr->numOfParams = size; - } - return res; -} - -static const char* jkExprInfoBase = "Base"; -static const char* jkExprInfoExpr = "Expr"; - -static bool exprInfoToJson(const void* obj, cJSON* jExprInfo) { - const SExprInfo* exprInfo = (const SExprInfo*)obj; - bool res = addObject(jExprInfo, jkExprInfoBase, sqlExprToJson, &exprInfo->base); - if (res) { - res = addObject(jExprInfo, jkExprInfoExpr, exprNodeToJson, &exprInfo->pExpr); - } - return res; -} - -static bool exprInfoFromJson(const cJSON* json, void* obj) { - SExprInfo* exprInfo = (SExprInfo*)obj; - bool res = fromObject(json, jkExprInfoBase, sqlExprFromJson, &exprInfo->base, true); - if (res) { - res = - fromObjectWithAlloc(json, jkExprInfoExpr, exprNodeFromJson, (void**)&exprInfo->pExpr, sizeof(tExprNode), true); - } - return res; -} - -static const char* jkTimeWindowStartKey = "StartKey"; -static const char* jkTimeWindowEndKey = "EndKey"; - -static bool timeWindowToJson(const void* obj, cJSON* json) { - const STimeWindow* win = (const STimeWindow*)obj; - - char tmp[40] = {0}; - snprintf(tmp, tListLen(tmp), "%" PRId64, win->skey); - - bool res = cJSON_AddStringToObject(json, jkTimeWindowStartKey, tmp); - if (res) { - memset(tmp, 0, tListLen(tmp)); - snprintf(tmp, tListLen(tmp), "%" PRId64, win->ekey); - res = cJSON_AddStringToObject(json, jkTimeWindowEndKey, tmp); - } - return res; -} - -static bool timeWindowFromJson(const cJSON* json, void* obj) { - STimeWindow* win = (STimeWindow*)obj; - win->skey = getBigintFromString(json, jkTimeWindowStartKey); - win->ekey = getBigintFromString(json, jkTimeWindowEndKey); - return true; -} - -static const char* jkScanNodeTableId = "TableId"; -static const char* jkScanNodeTableType = "TableType"; -static const char* jkScanNodeTableOrder = "Order"; -static const char* jkScanNodeTableCount = "Count"; -static const char* jkScanNodeTableRevCount = "Reverse"; - -static bool scanNodeToJson(const void* obj, cJSON* json) { - const SScanPhyNode* pNode = (const SScanPhyNode*)obj; - - char uid[40] = {0}; - snprintf(uid, tListLen(uid), "%" PRIu64, pNode->uid); - bool res = cJSON_AddStringToObject(json, jkScanNodeTableId, uid); - - if (res) { - res = cJSON_AddNumberToObject(json, jkScanNodeTableType, pNode->tableType); - } - - if (res) { - res = cJSON_AddNumberToObject(json, jkScanNodeTableOrder, pNode->order); - } - - if (res) { - res = cJSON_AddNumberToObject(json, jkScanNodeTableCount, pNode->count); - } - - if (res) { - res = cJSON_AddNumberToObject(json, jkScanNodeTableRevCount, pNode->reverse); - } - - return res; -} - -static bool scanNodeFromJson(const cJSON* json, void* obj) { - SScanPhyNode* pNode = (SScanPhyNode*)obj; - - pNode->uid = getBigintFromString(json, jkScanNodeTableId); - pNode->tableType = getNumber(json, jkScanNodeTableType); - pNode->count = getNumber(json, jkScanNodeTableCount); - pNode->order = getNumber(json, jkScanNodeTableOrder); - pNode->reverse = getNumber(json, jkScanNodeTableRevCount); - return true; -} - -static const char* jkColIndexColId = "ColId"; -static const char* jkColIndexColIndex = "ColIndex"; -static const char* jkColIndexFlag = "Flag"; -static const char* jkColIndexName = "Name"; - -static bool colIndexToJson(const void* obj, cJSON* json) { - const SColIndex* col = (const SColIndex*)obj; - bool res = cJSON_AddNumberToObject(json, jkColIndexColId, col->colId); - if (res) { - res = cJSON_AddNumberToObject(json, jkColIndexColIndex, col->colIndex); - } - if (res) { - res = cJSON_AddNumberToObject(json, jkColIndexFlag, col->flag); - } - if (res) { - res = cJSON_AddStringToObject(json, jkColIndexName, col->name); - } - return res; -} - -static bool colIndexFromJson(const cJSON* json, void* obj) { - SColIndex* col = (SColIndex*)obj; - col->colId = getNumber(json, jkColIndexColId); - col->colIndex = getNumber(json, jkColIndexColIndex); - col->flag = getNumber(json, jkColIndexFlag); - copyString(json, jkColIndexName, col->name); - return true; -} - -static const char* jkAggNodeAggAlgo = "AggAlgo"; -static const char* jkAggNodeAggSplit = "AggSplit"; -static const char* jkAggNodeExprs = "Exprs"; -static const char* jkAggNodeGroupByList = "GroupByList"; - -static bool aggNodeToJson(const void* obj, cJSON* json) { - const SAggPhyNode* agg = (const SAggPhyNode*)obj; - bool res = cJSON_AddNumberToObject(json, jkAggNodeAggAlgo, agg->aggAlgo); - if (res) { - res = cJSON_AddNumberToObject(json, jkAggNodeAggSplit, agg->aggSplit); - } - if (res) { - res = addArray(json, jkAggNodeExprs, exprInfoToJson, agg->pExprs); - } - if (res) { - res = addArray(json, jkAggNodeGroupByList, colIndexToJson, agg->pGroupByList); - } - return res; -} - -static bool aggNodeFromJson(const cJSON* json, void* obj) { - SAggPhyNode* agg = (SAggPhyNode*)obj; - agg->aggAlgo = getNumber(json, jkAggNodeAggAlgo); - agg->aggSplit = getNumber(json, jkAggNodeAggSplit); - bool res = fromArray(json, jkAggNodeExprs, exprInfoFromJson, &agg->pExprs, sizeof(SExprInfo)); - if (res) { - res = fromArray(json, jkAggNodeGroupByList, colIndexFromJson, &agg->pGroupByList, sizeof(SExprInfo)); - } - return res; -} - -static const char* jkTableScanNodeFlag = "Flag"; -static const char* jkTableScanNodeWindow = "Window"; -static const char* jkTableScanNodeTagsConditions = "TagsConditions"; - -static bool tableScanNodeToJson(const void* obj, cJSON* json) { - const STableScanPhyNode* scan = (const STableScanPhyNode*)obj; - bool res = scanNodeToJson(obj, json); - if (res) { - res = cJSON_AddNumberToObject(json, jkTableScanNodeFlag, scan->scanFlag); - } - if (res) { - res = addObject(json, jkTableScanNodeWindow, timeWindowToJson, &scan->window); - } - if (res) { - res = addArray(json, jkTableScanNodeTagsConditions, exprInfoToJson, scan->pTagsConditions); - } - return res; -} - -static bool tableScanNodeFromJson(const cJSON* json, void* obj) { - STableScanPhyNode* scan = (STableScanPhyNode*)obj; - bool res = scanNodeFromJson(json, obj); - if (res) { - scan->scanFlag = getNumber(json, jkTableScanNodeFlag); - } - if (res) { - res = fromObject(json, jkTableScanNodeWindow, timeWindowFromJson, &scan->window, true); - } - if (res) { - res = fromArray(json, jkTableScanNodeTagsConditions, exprInfoFromJson, &scan->pTagsConditions, sizeof(SExprInfo)); - } - return res; -} - -static const char* jkEpAddrFqdn = "Fqdn"; -static const char* jkEpAddrPort = "Port"; - -static bool epAddrToJson(const void* obj, cJSON* json) { - const SEp* ep = (const SEp*)obj; - bool res = cJSON_AddStringToObject(json, jkEpAddrFqdn, ep->fqdn); - if (res) { - res = cJSON_AddNumberToObject(json, jkEpAddrPort, ep->port); - } - return res; -} - -static bool epAddrFromJson(const cJSON* json, void* obj) { - SEp* ep = (SEp*)obj; - copyString(json, jkEpAddrFqdn, ep->fqdn); - ep->port = getNumber(json, jkEpAddrPort); - return true; -} - -static const char* jkNodeAddrId = "NodeId"; -static const char* jkNodeAddrInUse = "InUse"; -static const char* jkNodeAddrEpAddrs = "Ep"; -static const char* jkNodeAddr = "NodeAddr"; -static const char* jkNodeTaskId = "TaskId"; -static const char* jkNodeTaskSchedId = "SchedId"; - -static bool queryNodeAddrToJson(const void* obj, cJSON* json) { - const SQueryNodeAddr* pAddr = (const SQueryNodeAddr*)obj; - bool res = cJSON_AddNumberToObject(json, jkNodeAddrId, pAddr->nodeId); - - if (res) { - res = cJSON_AddNumberToObject(json, jkNodeAddrInUse, pAddr->epSet.inUse); - } - - if (res) { - res = addRawArray(json, jkNodeAddrEpAddrs, epAddrToJson, pAddr->epSet.eps, sizeof(SEp), pAddr->epSet.numOfEps); - } - return res; -} - -static bool queryNodeAddrFromJson(const cJSON* json, void* obj) { - SQueryNodeAddr* pAddr = (SQueryNodeAddr*)obj; - - pAddr->nodeId = getNumber(json, jkNodeAddrId); - pAddr->epSet.inUse = getNumber(json, jkNodeAddrInUse); - - int32_t numOfEps = 0; - bool res = fromRawArray(json, jkNodeAddrEpAddrs, epAddrFromJson, pAddr->epSet.eps, sizeof(SEp), &numOfEps); - pAddr->epSet.numOfEps = numOfEps; - return res; -} - -static bool nodeAddrToJson(const void* obj, cJSON* json) { - const SDownstreamSource* pSource = (const SDownstreamSource*)obj; - bool res = cJSON_AddNumberToObject(json, jkNodeTaskId, pSource->taskId); - - if (res) { - char t[30] = {0}; - snprintf(t, tListLen(t), "%" PRIu64, pSource->schedId); - res = cJSON_AddStringToObject(json, jkNodeTaskSchedId, t); - } - - if (res) { - res = addObject(json, jkNodeAddr, queryNodeAddrToJson, &pSource->addr); - } - return res; -} - -static bool nodeAddrFromJson(const cJSON* json, void* obj) { - SDownstreamSource* pSource = (SDownstreamSource*)obj; - pSource->taskId = getNumber(json, jkNodeTaskId); - - pSource->schedId = getBigintFromString(json, jkNodeTaskSchedId); - bool res = fromObject(json, jkNodeAddr, queryNodeAddrFromJson, &pSource->addr, true); - return res; -} - -static const char* jkExchangeNodeSrcTemplateId = "SrcTemplateId"; -static const char* jkExchangeNodeSrcEndPoints = "SrcAddrs"; - -static bool exchangeNodeToJson(const void* obj, cJSON* json) { - const SExchangePhyNode* exchange = (const SExchangePhyNode*)obj; - bool res = cJSON_AddNumberToObject(json, jkExchangeNodeSrcTemplateId, exchange->srcTemplateId); - if (res) { - res = addRawArray(json, jkExchangeNodeSrcEndPoints, nodeAddrToJson, exchange->pSrcEndPoints->pData, - sizeof(SDownstreamSource), taosArrayGetSize(exchange->pSrcEndPoints)); - } - return res; -} - -static bool exchangeNodeFromJson(const cJSON* json, void* obj) { - SExchangePhyNode* exchange = (SExchangePhyNode*)obj; - exchange->srcTemplateId = getNumber(json, jkExchangeNodeSrcTemplateId); - return fromInlineArray(json, jkExchangeNodeSrcEndPoints, nodeAddrFromJson, &exchange->pSrcEndPoints, - sizeof(SDownstreamSource)); -} - -static bool specificPhyNodeToJson(const void* obj, cJSON* json) { - const SPhyNode* phyNode = (const SPhyNode*)obj; - switch (phyNode->info.type) { - case OP_StreamScan: - case OP_TableScan: - case OP_TableSeqScan: - return tableScanNodeToJson(obj, json); - case OP_TagScan: - case OP_SystemTableScan: - return scanNodeToJson(obj, json); - case OP_Aggregate: - return aggNodeToJson(obj, json); - case OP_Project: - return true; - // case OP_Groupby: - case OP_Limit: - case OP_SLimit: - case OP_TimeWindow: - case OP_SessionWindow: - case OP_StateWindow: - case OP_Fill: - case OP_MultiTableAggregate: - case OP_MultiTableTimeInterval: - case OP_Filter: - case OP_Distinct: - case OP_Join: - case OP_AllTimeWindow: - case OP_AllMultiTableTimeInterval: - case OP_Order: - break; // todo - case OP_Exchange: - return exchangeNodeToJson(obj, json); - default: - break; - } - return false; -} - -static bool specificPhyNodeFromJson(const cJSON* json, void* obj) { - SPhyNode* phyNode = (SPhyNode*)obj; - switch (phyNode->info.type) { - case OP_StreamScan: - case OP_TableScan: - case OP_TableSeqScan: - return tableScanNodeFromJson(json, obj); - case OP_TagScan: - case OP_SystemTableScan: - return scanNodeFromJson(json, obj); - case OP_Aggregate: - return aggNodeFromJson(json, obj); - case OP_Project: - return true; - // case OP_Groupby: - case OP_Limit: - case OP_SLimit: - case OP_TimeWindow: - case OP_SessionWindow: - case OP_StateWindow: - case OP_Fill: - case OP_MultiTableAggregate: - case OP_MultiTableTimeInterval: - case OP_Filter: - case OP_Distinct: - case OP_Join: - case OP_AllTimeWindow: - case OP_AllMultiTableTimeInterval: - case OP_Order: - break; // todo - case OP_Exchange: - return exchangeNodeFromJson(json, obj); - default: - break; - } - return false; -} - -static const char* jkPnodeName = "Name"; -static const char* jkPnodeTargets = "Targets"; -static const char* jkPnodeConditions = "Conditions"; -static const char* jkPnodeSchema = "TargetSchema"; -static const char* jkPnodeChildren = "Children"; -// The 'pParent' field do not need to be serialized. -static bool phyNodeToJson(const void* obj, cJSON* jNode) { - const SPhyNode* phyNode = (const SPhyNode*)obj; - bool res = cJSON_AddNumberToObject(jNode, jkPnodeType, phyNode->info.type); - if (res) { - res = cJSON_AddStringToObject(jNode, jkPnodeName, phyNode->info.name); - } - if (res) { - res = addArray(jNode, jkPnodeTargets, exprInfoToJson, phyNode->pTargets); - } - if (res) { - res = addArray(jNode, jkPnodeConditions, exprInfoToJson, phyNode->pConditions); - } - if (res) { - res = addObject(jNode, jkPnodeSchema, dataBlockSchemaToJson, &phyNode->targetSchema); - } - if (res) { - res = addArray(jNode, jkPnodeChildren, phyNodeToJson, phyNode->pChildren); - } - if (res) { - res = addObject(jNode, phyNode->info.name, specificPhyNodeToJson, phyNode); - } - return res; -} - -static bool phyNodeFromJson(const cJSON* json, void* obj) { - SPhyNode* node = (SPhyNode*)obj; - - node->info.type = getNumber(json, jkPnodeType); - node->info.name = opTypeToOpName(node->info.type); - - bool res = fromArray(json, jkPnodeTargets, exprInfoFromJson, &node->pTargets, sizeof(SExprInfo)); - if (res) { - res = fromArray(json, jkPnodeConditions, exprInfoFromJson, &node->pConditions, sizeof(SExprInfo)); - } - if (res) { - res = fromObject(json, jkPnodeSchema, dataBlockSchemaFromJson, &node->targetSchema, true); - } - if (res) { - res = fromPnodeArray(json, jkPnodeChildren, phyNodeFromJson, &node->pChildren); - } - if (res) { - res = fromObject(json, node->info.name, specificPhyNodeFromJson, node, true); - } - return res; -} - -static const char* jkInserterNumOfTables = "NumOfTables"; -static const char* jkInserterDataSize = "DataSize"; - -static bool inserterToJson(const void* obj, cJSON* json) { - const SDataInserter* inserter = (const SDataInserter*)obj; - bool res = cJSON_AddNumberToObject(json, jkInserterNumOfTables, inserter->numOfTables); - if (res) { - res = cJSON_AddNumberToObject(json, jkInserterDataSize, inserter->size); - } - // todo pData - return res; -} - -static bool inserterFromJson(const cJSON* json, void* obj) { - SDataInserter* inserter = (SDataInserter*)obj; - inserter->numOfTables = getNumber(json, jkInserterNumOfTables); - inserter->size = getNumber(json, jkInserterDataSize); - // todo pData -} - -static bool specificDataSinkToJson(const void* obj, cJSON* json) { - const SDataSink* dsink = (const SDataSink*)obj; - switch (dsink->info.type) { - case DSINK_Dispatch: - return true; - case DSINK_Insert: - return inserterToJson(obj, json); - default: - break; - } - return false; -} - -static bool specificDataSinkFromJson(const cJSON* json, void* obj) { - SDataSink* dsink = (SDataSink*)obj; - switch (dsink->info.type) { - case DSINK_Dispatch: - return true; - case DSINK_Insert: - return inserterFromJson(json, obj); - default: - break; - } - return false; -} - -static const char* jkDataSinkName = "Name"; -static const char* jkDataSinkSchema = "Schema"; - -static bool dataSinkToJson(const void* obj, cJSON* json) { - const SDataSink* dsink = (const SDataSink*)obj; - bool res = cJSON_AddStringToObject(json, jkDataSinkName, dsink->info.name); - if (res) { - res = addObject(json, dsink->info.name, specificDataSinkToJson, dsink); - } - if (res) { - res = addObject(json, jkDataSinkSchema, dataBlockSchemaToJson, &dsink->schema); - } - return res; -} - -static bool dataSinkFromJson(const cJSON* json, void* obj) { - SDataSink* dsink = (SDataSink*)obj; - dsink->info.name = getString(json, jkDataSinkName); - dsink->info.type = dsinkNameToDsinkType(dsink->info.name); - bool res = fromObject(json, jkDataSinkSchema, dataBlockSchemaFromJson, &dsink->schema, true); - if (res) { - res = fromObject(json, dsink->info.name, specificDataSinkFromJson, dsink, true); - } - return res; -} - -static const char* jkIdQueryId = "QueryId"; -static const char* jkIdTemplateId = "TemplateId"; -static const char* jkIdSubplanId = "SubplanId"; - -static bool subplanIdToJson(const void* obj, cJSON* jId) { - const SSubplanId* id = (const SSubplanId*)obj; - - char ids[40] = {0}; - snprintf(ids, tListLen(ids), "%" PRIu64, id->queryId); - - bool res = cJSON_AddStringToObject(jId, jkIdQueryId, ids); - if (res) { - res = cJSON_AddNumberToObject(jId, jkIdTemplateId, id->templateId); - } - if (res) { - res = cJSON_AddNumberToObject(jId, jkIdSubplanId, id->subplanId); - } - return res; -} - -static bool subplanIdFromJson(const cJSON* json, void* obj) { - SSubplanId* id = (SSubplanId*)obj; - - id->queryId = getBigintFromString(json, jkIdQueryId); - id->templateId = getNumber(json, jkIdTemplateId); - id->subplanId = getNumber(json, jkIdSubplanId); - return true; -} - -static const char* jkSubplanId = "Id"; -static const char* jkSubplanNode = "Node"; -static const char* jkSubplanDataSink = "DataSink"; - -static cJSON* subplanToJson(const SSubplan* subplan) { - cJSON* jSubplan = cJSON_CreateObject(); - if (NULL == jSubplan) { - return NULL; - } - - // The 'type', 'level', 'execEpSet', 'pChildren' and 'pParents' fields do not need to be serialized. - bool res = addObject(jSubplan, jkSubplanId, subplanIdToJson, &subplan->id); - if (res) { - res = addObject(jSubplan, jkSubplanNode, phyNodeToJson, subplan->pNode); - } - if (res) { - res = addObject(jSubplan, jkSubplanDataSink, dataSinkToJson, subplan->pDataSink); - } - if (!res) { - cJSON_Delete(jSubplan); - return NULL; - } - - return jSubplan; -} - -static SSubplan* subplanFromJson(const cJSON* json) { - SSubplan* subplan = calloc(1, sizeof(SSubplan)); - if (NULL == subplan) { - return NULL; - } - - bool res = fromObject(json, jkSubplanId, subplanIdFromJson, &subplan->id, true); - - if (res) { - res = fromPnode(json, jkSubplanNode, phyNodeFromJson, (void**)&subplan->pNode); - } - - if (res) { - res = fromObjectWithAlloc(json, jkSubplanDataSink, dataSinkFromJson, (void**)&subplan->pDataSink, sizeof(SDataSink), - false); - } - - if (!res) { - qDestroySubplan(subplan); - return NULL; - } - return subplan; -} - -int32_t subPlanToString(const SSubplan* subplan, char** str, int32_t* len) { - if (QUERY_TYPE_MODIFY == subplan->type) { - SDataInserter* insert = (SDataInserter*)(subplan->pDataSink); - *len = insert->size; - *str = insert->pData; - insert->pData = NULL; - return TSDB_CODE_SUCCESS; - } - - cJSON* json = subplanToJson(subplan); - if (NULL == json) { - terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; - } - - *str = cJSON_Print(json); - cJSON_Delete(json); - - *len = strlen(*str) + 1; - return TSDB_CODE_SUCCESS; -} - -int32_t stringToSubplan(const char* str, SSubplan** subplan) { - cJSON* json = cJSON_Parse(str); - if (NULL == json) { - return TSDB_CODE_FAILED; - } - *subplan = subplanFromJson(json); - return (NULL == *subplan ? TSDB_CODE_FAILED : TSDB_CODE_SUCCESS); -} - -cJSON* qDagToJson(const SQueryDag* pDag) { - cJSON* pRoot = cJSON_CreateObject(); - if (pRoot == NULL) { - return NULL; - } - - cJSON_AddNumberToObject(pRoot, "Number", pDag->numOfSubplans); - cJSON_AddNumberToObject(pRoot, "QueryId", pDag->queryId); - - cJSON* pLevels = cJSON_CreateArray(); - if (pLevels == NULL) { - cJSON_Delete(pRoot); - return NULL; - } - - cJSON_AddItemToObject(pRoot, "Subplans", pLevels); - - size_t level = taosArrayGetSize(pDag->pSubplans); - for (size_t i = 0; i < level; i++) { - const SArray* pSubplans = (const SArray*)taosArrayGetP(pDag->pSubplans, i); - size_t num = taosArrayGetSize(pSubplans); - cJSON* plansOneLevel = cJSON_CreateArray(); - if (plansOneLevel == NULL) { - cJSON_Delete(pRoot); - return NULL; - } - - cJSON_AddItemToArray(pLevels, plansOneLevel); - for (size_t j = 0; j < num; j++) { - cJSON* pSubplan = subplanToJson((const SSubplan*)taosArrayGetP(pSubplans, j)); - if (pSubplan == NULL) { - cJSON_Delete(pRoot); - return NULL; - } - - cJSON_AddItemToArray(plansOneLevel, pSubplan); - } - } - return pRoot; -} - -char* qDagToString(const SQueryDag* pDag) { - cJSON* pRoot = qDagToJson(pDag); - return cJSON_Print(pRoot); -} - -SQueryDag* qJsonToDag(const cJSON* pRoot) { - SQueryDag* pDag = malloc(sizeof(SQueryDag)); - if (pDag == NULL) { - return NULL; - } - pDag->numOfSubplans = cJSON_GetNumberValue(cJSON_GetObjectItem(pRoot, "Number")); - pDag->queryId = cJSON_GetNumberValue(cJSON_GetObjectItem(pRoot, "QueryId")); - pDag->pSubplans = taosArrayInit(0, sizeof(void*)); - if (pDag->pSubplans == NULL) { - free(pDag); - return NULL; - } - cJSON* pLevels = cJSON_GetObjectItem(pRoot, "Subplans"); - int level = cJSON_GetArraySize(pLevels); - for (int i = 0; i < level; i++) { - SArray* plansOneLevel = taosArrayInit(0, sizeof(void*)); - if (plansOneLevel == NULL) { - for (int j = 0; j < i; j++) { - taosArrayDestroy(taosArrayGetP(pDag->pSubplans, j)); - } - taosArrayDestroy(pDag->pSubplans); - free(pDag); - return NULL; - } - cJSON* pItem = cJSON_GetArrayItem(pLevels, i); - int sz = cJSON_GetArraySize(pItem); - for (int j = 0; j < sz; j++) { - cJSON* pSubplanJson = cJSON_GetArrayItem(pItem, j); - SSubplan* pSubplan = subplanFromJson(pSubplanJson); - taosArrayPush(plansOneLevel, &pSubplan); - } - taosArrayPush(pDag->pSubplans, &plansOneLevel); - } - return pDag; -} - -SQueryDag* qStringToDag(const char* pStr) { - cJSON* pRoot = cJSON_Parse(pStr); - return qJsonToDag(pRoot); -} diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c new file mode 100644 index 0000000000000000000000000000000000000000..7520ea3c9e3c36d503d1358845d44bb42bf105a9 --- /dev/null +++ b/source/libs/planner/src/planLogicCreater.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "planInt.h" + +#include "functionMgt.h" + +typedef struct SLogicPlanContext { + int32_t errCode; + int32_t planNodeId; + int32_t acctId; +} SLogicPlanContext; + +static SLogicNode* createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt); +static SLogicNode* createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable); + +typedef struct SRewriteExprCxt { + int32_t errCode; + SNodeList* pExprs; +} SRewriteExprCxt; + +static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { + switch (nodeType(*pNode)) { + case QUERY_NODE_OPERATOR: + case QUERY_NODE_LOGIC_CONDITION: + case QUERY_NODE_FUNCTION: { + SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext; + SNode* pExpr; + int32_t index = 0; + FOREACH(pExpr, pCxt->pExprs) { + if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) { + pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0); + } + if (nodesEqualNode(pExpr, *pNode)) { + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + CHECK_ALLOC(pCol, DEAL_RES_ERROR); + SExprNode* pToBeRewrittenExpr = (SExprNode*)(*pNode); + pCol->node.resType = pToBeRewrittenExpr->resType; + strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName); + strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName); + nodesDestroyNode(*pNode); + *pNode = (SNode*)pCol; + return DEAL_RES_IGNORE_CHILD; + } + ++index; + } + break; + } + default: + break; + } + + return DEAL_RES_CONTINUE; +} + +typedef struct SNameExprCxt { + int32_t planNodeId; + int32_t rewriteId; +} SNameExprCxt; + +static EDealRes doNameExpr(SNode* pNode, void* pContext) { + switch (nodeType(pNode)) { + case QUERY_NODE_OPERATOR: + case QUERY_NODE_LOGIC_CONDITION: + case QUERY_NODE_FUNCTION: { + SNameExprCxt* pCxt = (SNameExprCxt*)pContext; + sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId++); + return DEAL_RES_IGNORE_CHILD; + } + default: + break; + } + + return DEAL_RES_CONTINUE; +} + +static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) { + SNameExprCxt nameCxt = { .planNodeId = planNodeId, .rewriteId = rewriteId }; + nodesWalkList(pExprs, doNameExpr, &nameCxt); + SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs }; + nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt); + return cxt.errCode; +} + +static SLogicNode* pushLogicNode(SLogicPlanContext* pCxt, SLogicNode* pRoot, SLogicNode* pNode) { + if (TSDB_CODE_SUCCESS != pCxt->errCode) { + goto error; + } + + if (NULL == pRoot) { + return pNode; + } + + if (NULL == pNode) { + return pRoot; + } + + if (NULL == pNode->pChildren) { + pNode->pChildren = nodesMakeList(); + if (NULL == pNode->pChildren) { + goto error; + } + } + if (TSDB_CODE_SUCCESS != nodesListAppend(pNode->pChildren, (SNode*)pRoot)) { + goto error; + } + pRoot->pParent = pNode; + return pNode; +error: + nodesDestroyNode((SNode*)pNode); + return pRoot; +} + +static SLogicNode* createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) { + SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN); + CHECK_ALLOC(pScan, NULL); + pScan->node.id = pCxt->planNodeId++; + + TSWAP(pScan->pMeta, pRealTable->pMeta, STableMeta*); + TSWAP(pScan->pVgroupList, pRealTable->pVgroupList, SVgroupsInfo*); + + // set columns to scan + SNodeList* pCols = NULL; + CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan); + if (NULL != pCols) { + pScan->pScanCols = nodesCloneList(pCols); + CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan); + } + + // set output + if (NULL != pCols) { + pScan->node.pTargets = nodesCloneList(pCols); + CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan); + } + + pScan->scanType = SCAN_TYPE_TABLE; + pScan->scanFlag = MAIN_SCAN; + pScan->scanRange = TSWINDOW_INITIALIZER; + pScan->tableName.type = TSDB_TABLE_NAME_T; + pScan->tableName.acctId = pCxt->acctId; + strcpy(pScan->tableName.dbname, pRealTable->table.dbName); + strcpy(pScan->tableName.tname, pRealTable->table.tableName); + + return (SLogicNode*)pScan; +} + +static SLogicNode* createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) { + SLogicNode* pRoot = createQueryLogicNode(pCxt, pTable->pSubquery); + CHECK_ALLOC(pRoot, NULL); + SNode* pNode; + FOREACH(pNode, pRoot->pTargets) { + strcpy(((SColumnNode*)pNode)->tableAlias, pTable->table.tableAlias); + } + return pRoot; +} + +static SLogicNode* createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) { + SJoinLogicNode* pJoin = (SJoinLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN); + CHECK_ALLOC(pJoin, NULL); + pJoin->node.id = pCxt->planNodeId++; + + pJoin->joinType = pJoinTable->joinType; + + // set left and right node + pJoin->node.pChildren = nodesMakeList(); + CHECK_ALLOC(pJoin->node.pChildren, (SLogicNode*)pJoin); + SLogicNode* pLeft = createLogicNodeByTable(pCxt, pSelect, pJoinTable->pLeft); + CHECK_ALLOC(pLeft, (SLogicNode*)pJoin); + CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pLeft), (SLogicNode*)pJoin); + SLogicNode* pRight = createLogicNodeByTable(pCxt, pSelect, pJoinTable->pRight); + CHECK_ALLOC(pRight, (SLogicNode*)pJoin); + CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin); + + // set on conditions + if (NULL != pJoinTable->pOnCond) { + pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond); + CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin); + } + + // set the output + pJoin->node.pTargets = nodesCloneList(pLeft->pTargets); + CHECK_ALLOC(pJoin->node.pTargets, (SLogicNode*)pJoin); + SNodeList* pTargets = nodesCloneList(pRight->pTargets); + CHECK_ALLOC(pTargets, (SLogicNode*)pJoin); + nodesListAppendList(pJoin->node.pTargets, pTargets); + + return (SLogicNode*)pJoin; +} + +static SLogicNode* createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable) { + switch (nodeType(pTable)) { + case QUERY_NODE_REAL_TABLE: + return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable); + case QUERY_NODE_TEMP_TABLE: + return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable); + case QUERY_NODE_JOIN_TABLE: + return createJoinLogicNode(pCxt, pSelect, (SJoinTableNode*)pTable); + default: + break; + } + return NULL; +} + +typedef struct SCreateColumnCxt { + int32_t errCode; + SNodeList* pList; +} SCreateColumnCxt; + +static EDealRes doCreateColumn(SNode* pNode, void* pContext) { + SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext; + switch (nodeType(pNode)) { + case QUERY_NODE_COLUMN: { + SNode* pCol = nodesCloneNode(pNode); + CHECK_ALLOC(pCol, DEAL_RES_ERROR); + CHECK_CODE(nodesListAppend(pCxt->pList, pCol), DEAL_RES_ERROR); + return DEAL_RES_IGNORE_CHILD; + } + case QUERY_NODE_OPERATOR: + case QUERY_NODE_LOGIC_CONDITION: + case QUERY_NODE_FUNCTION: { + SExprNode* pExpr = (SExprNode*)pNode; + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + CHECK_ALLOC(pCol, DEAL_RES_ERROR); + pCol->node.resType = pExpr->resType; + strcpy(pCol->colName, pExpr->aliasName); + CHECK_CODE(nodesListAppend(pCxt->pList, (SNode*)pCol), DEAL_RES_ERROR); + return DEAL_RES_IGNORE_CHILD; + } + default: + break; + } + + return DEAL_RES_CONTINUE; +} + +static SNodeList* createColumnByRewriteExps(SLogicPlanContext* pCxt, SNodeList* pExprs) { + SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() }; + CHECK_ALLOC(cxt.pList, NULL); + + nodesWalkList(pExprs, doCreateColumn, &cxt); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyList(cxt.pList); + return NULL; + } + return cxt.pList; +} + +static SLogicNode* createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) { + SNodeList* pAggFuncs = NULL; + CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL); + if (NULL == pAggFuncs && NULL == pSelect->pGroupByList) { + return NULL; + } + + SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG); + CHECK_ALLOC(pAgg, NULL); + pAgg->node.id = pCxt->planNodeId++; + + // set grouyp keys, agg funcs and having conditions + if (NULL != pSelect->pGroupByList) { + pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList); + CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg); + } + if (NULL != pAggFuncs) { + pAgg->pAggFuncs = nodesCloneList(pAggFuncs); + CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg); + } + + // rewrite the expression in subsequent clauses + CHECK_CODE(rewriteExpr(pAgg->node.id, 1, pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg); + CHECK_CODE(rewriteExpr(pAgg->node.id, 1 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg); + + if (NULL != pSelect->pHaving) { + pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving); + CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg); + } + + // set the output + pAgg->node.pTargets = nodesMakeList(); + CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg); + if (NULL != pAgg->pGroupKeys) { + SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys); + CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg); + nodesListAppendList(pAgg->node.pTargets, pTargets); + } + if (NULL != pAgg->pAggFuncs) { + SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs); + CHECK_ALLOC(pTargets, (SLogicNode*)pAgg); + nodesListAppendList(pAgg->node.pTargets, pTargets); + } + + return (SLogicNode*)pAgg; +} + +static SLogicNode* createWindowLogicNodeByInterval(SLogicPlanContext* pCxt, SIntervalWindowNode* pInterval, SSelectStmt* pSelect) { + SWindowLogicNode* pWindow = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW); + CHECK_ALLOC(pWindow, NULL); + pWindow->node.id = pCxt->planNodeId++; + + pWindow->winType = WINDOW_TYPE_INTERVAL; + pWindow->interval = ((SValueNode*)pInterval->pInterval)->datum.i; + pWindow->offset = (NULL != pInterval->pOffset ? ((SValueNode*)pInterval->pOffset)->datum.i : 0); + pWindow->sliding = (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->datum.i : 0); + if (NULL != pInterval->pFill) { + pWindow->pFill = nodesCloneNode(pInterval->pFill); + CHECK_ALLOC(pWindow->pFill, (SLogicNode*)pWindow); + } + + SNodeList* pFuncs = NULL; + CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pFuncs), NULL); + if (NULL != pFuncs) { + pWindow->pFuncs = nodesCloneList(pFuncs); + CHECK_ALLOC(pWindow->pFuncs, (SLogicNode*)pWindow); + } + + CHECK_CODE(rewriteExpr(pWindow->node.id, 1, pWindow->pFuncs, pSelect, SQL_CLAUSE_WINDOW), (SLogicNode*)pWindow); + + pWindow->node.pTargets = createColumnByRewriteExps(pCxt, pWindow->pFuncs); + CHECK_ALLOC(pWindow->node.pTargets, (SLogicNode*)pWindow); + + return (SLogicNode*)pWindow; +} + +static SLogicNode* createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) { + if (NULL == pSelect->pWindow) { + return NULL; + } + + switch (nodeType(pSelect->pWindow)) { + case QUERY_NODE_INTERVAL_WINDOW: + return createWindowLogicNodeByInterval(pCxt, (SIntervalWindowNode*)pSelect->pWindow, pSelect); + default: + break; + } + + return NULL; +} + +static SNodeList* createColumnByProjections(SLogicPlanContext* pCxt, SNodeList* pExprs) { + SNodeList* pList = nodesMakeList(); + CHECK_ALLOC(pList, NULL); + SNode* pNode; + FOREACH(pNode, pExprs) { + SExprNode* pExpr = (SExprNode*)pNode; + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + goto error; + } + pCol->node.resType = pExpr->resType; + strcpy(pCol->colName, pExpr->aliasName); + if (TSDB_CODE_SUCCESS != nodesListAppend(pList, (SNode*)pCol)) { + goto error; + } + } + return pList; +error: + nodesDestroyList(pList); + return NULL; +} + +static SLogicNode* createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) { + SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT); + CHECK_ALLOC(pProject, NULL); + pProject->node.id = pCxt->planNodeId++; + + pProject->pProjections = nodesCloneList(pSelect->pProjectionList); + + pProject->node.pTargets = createColumnByProjections(pCxt,pSelect->pProjectionList); + CHECK_ALLOC(pProject->node.pTargets, (SLogicNode*)pProject); + + return (SLogicNode*)pProject; +} + +static SLogicNode* createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) { + SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable); + if (TSDB_CODE_SUCCESS == pCxt->errCode && NULL != pSelect->pWhere) { + pRoot->pConditions = nodesCloneNode(pSelect->pWhere); + CHECK_ALLOC(pRoot->pConditions, pRoot); + } + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pRoot = pushLogicNode(pCxt, pRoot, createWindowLogicNode(pCxt, pSelect)); + } + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pRoot = pushLogicNode(pCxt, pRoot, createAggLogicNode(pCxt, pSelect)); + } + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pRoot = pushLogicNode(pCxt, pRoot, createProjectLogicNode(pCxt, pSelect)); + } + return pRoot; +} + +static int32_t getMsgType(ENodeType sqlType) { + return (QUERY_NODE_CREATE_TABLE_STMT == sqlType || QUERY_NODE_CREATE_MULTI_TABLE_STMT == sqlType) ? TDMT_VND_CREATE_TABLE : TDMT_VND_SUBMIT; +} + +static SLogicNode* createVnodeModifLogicNode(SLogicPlanContext* pCxt, SVnodeModifOpStmt* pStmt) { + SVnodeModifLogicNode* pModif = (SVnodeModifLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIF); + CHECK_ALLOC(pModif, NULL); + pModif->pDataBlocks = pStmt->pDataBlocks; + pModif->msgType = getMsgType(pStmt->sqlNodeType); + return (SLogicNode*)pModif; +} + +static SLogicNode* createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt) { + switch (nodeType(pStmt)) { + case QUERY_NODE_SELECT_STMT: + return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt); + case QUERY_NODE_VNODE_MODIF_STMT: + return createVnodeModifLogicNode(pCxt, (SVnodeModifOpStmt*)pStmt); + default: + break; + } +} + +int32_t createLogicPlan(SPlanContext* pCxt, SLogicNode** pLogicNode) { + SLogicPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1, .acctId = pCxt->acctId }; + SLogicNode* pRoot = createQueryLogicNode(&cxt, pCxt->pAstRoot); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyNode((SNode*)pRoot); + return cxt.errCode; + } + *pLogicNode = pRoot; + return TSDB_CODE_SUCCESS; +} diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c new file mode 100644 index 0000000000000000000000000000000000000000..7b7dd26df1a985463f915408f8984d00f245653f --- /dev/null +++ b/source/libs/planner/src/planPhysiCreater.c @@ -0,0 +1,867 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "planInt.h" + +#include "functionMgt.h" + +typedef struct SSlotIndex { + int16_t dataBlockId; + int16_t slotId; +} SSlotIndex; + +typedef struct SPhysiPlanContext { + SPlanContext* pPlanCxt; + int32_t errCode; + int16_t nextDataBlockId; + SArray* pLocationHelper; + SArray* pExecNodeList; + int32_t subplanId; +} SPhysiPlanContext; + +static int32_t getSlotKey(SNode* pNode, char* pKey) { + if (QUERY_NODE_COLUMN == nodeType(pNode)) { + SColumnNode* pCol = (SColumnNode*)pNode; + if ('\0' == pCol->tableAlias[0]) { + return sprintf(pKey, "%s", pCol->colName); + } + return sprintf(pKey, "%s.%s", pCol->tableAlias, pCol->colName); + } + return sprintf(pKey, "%s", ((SExprNode*)pNode)->aliasName); +} + +static SNode* createSlotDesc(SPhysiPlanContext* pCxt, const SNode* pNode, int16_t slotId) { + SSlotDescNode* pSlot = (SSlotDescNode*)nodesMakeNode(QUERY_NODE_SLOT_DESC); + CHECK_ALLOC(pSlot, NULL); + pSlot->slotId = slotId; + pSlot->dataType = ((SExprNode*)pNode)->resType; + pSlot->reserve = false; + pSlot->output = true; + return (SNode*)pSlot; +} + +static SNode* createTarget(SNode* pNode, int16_t dataBlockId, int16_t slotId) { + STargetNode* pTarget = (STargetNode*)nodesMakeNode(QUERY_NODE_TARGET); + if (NULL == pTarget) { + return NULL; + } + pTarget->dataBlockId = dataBlockId; + pTarget->slotId = slotId; + pTarget->pExpr = pNode; + return (SNode*)pTarget; +} + +static int32_t addDataBlockDesc(SPhysiPlanContext* pCxt, SNodeList* pList, SDataBlockDescNode* pDataBlockDesc) { + SHashObj* pHash = NULL; + if (NULL == pDataBlockDesc->pSlots) { + pDataBlockDesc->pSlots = nodesMakeList(); + CHECK_ALLOC(pDataBlockDesc->pSlots, TSDB_CODE_OUT_OF_MEMORY); + + pHash = taosHashInit(LIST_LENGTH(pList), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + CHECK_ALLOC(pHash, TSDB_CODE_OUT_OF_MEMORY); + if (NULL == taosArrayInsert(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId, &pHash)) { + taosHashCleanup(pHash); + return TSDB_CODE_OUT_OF_MEMORY; + } + } else { + pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId); + } + + SNode* pNode = NULL; + int16_t slotId = taosHashGetSize(pHash); + FOREACH(pNode, pList) { + CHECK_CODE_EXT(nodesListStrictAppend(pDataBlockDesc->pSlots, createSlotDesc(pCxt, pNode, slotId))); + + SSlotIndex index = { .dataBlockId = pDataBlockDesc->dataBlockId, .slotId = slotId }; + char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; + int32_t len = getSlotKey(pNode, name); + CHECK_CODE(taosHashPut(pHash, name, len, &index, sizeof(SSlotIndex)), TSDB_CODE_OUT_OF_MEMORY); + + SNode* pTarget = createTarget(pNode, pDataBlockDesc->dataBlockId, slotId); + CHECK_ALLOC(pTarget, TSDB_CODE_OUT_OF_MEMORY); + REPLACE_NODE(pTarget); + + pDataBlockDesc->resultRowSize += ((SExprNode*)pNode)->resType.bytes; + ++slotId; + } + return TSDB_CODE_SUCCESS; +} + +typedef struct SSetSlotIdCxt { + int32_t errCode; + SHashObj* pLeftHash; + SHashObj* pRightHash; +} SSetSlotIdCxt; + +static EDealRes doSetSlotId(SNode* pNode, void* pContext) { + if (QUERY_NODE_COLUMN == nodeType(pNode) && 0 != strcmp(((SColumnNode*)pNode)->colName, "*")) { + SSetSlotIdCxt* pCxt = (SSetSlotIdCxt*)pContext; + char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; + int32_t len = getSlotKey(pNode, name); + SSlotIndex* pIndex = taosHashGet(pCxt->pLeftHash, name, len); + if (NULL == pIndex) { + pIndex = taosHashGet(pCxt->pRightHash, name, len); + } + // pIndex is definitely not NULL, otherwise it is a bug + CHECK_ALLOC(pIndex, DEAL_RES_ERROR); + ((SColumnNode*)pNode)->dataBlockId = pIndex->dataBlockId; + ((SColumnNode*)pNode)->slotId = pIndex->slotId; + CHECK_ALLOC(pNode, DEAL_RES_ERROR); + return DEAL_RES_IGNORE_CHILD; + } + return DEAL_RES_CONTINUE; +} + +static SNode* setNodeSlotId(SPhysiPlanContext* pCxt, int16_t leftDataBlockId, int16_t rightDataBlockId, SNode* pNode) { + SNode* pRes = nodesCloneNode(pNode); + CHECK_ALLOC(pRes, NULL); + SSetSlotIdCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pLeftHash = taosArrayGetP(pCxt->pLocationHelper, leftDataBlockId), + .pRightHash = (rightDataBlockId < 0 ? NULL : taosArrayGetP(pCxt->pLocationHelper, rightDataBlockId)) }; + nodesWalkNode(pRes, doSetSlotId, &cxt); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyNode(pRes); + return NULL; + } + return pRes; +} + +static SNodeList* setListSlotId(SPhysiPlanContext* pCxt, int16_t leftDataBlockId, int16_t rightDataBlockId, SNodeList* pList) { + SNodeList* pRes = nodesCloneList(pList); + CHECK_ALLOC(pRes, NULL); + SSetSlotIdCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pLeftHash = taosArrayGetP(pCxt->pLocationHelper, leftDataBlockId), + .pRightHash = (rightDataBlockId < 0 ? NULL : taosArrayGetP(pCxt->pLocationHelper, rightDataBlockId)) }; + nodesWalkList(pRes, doSetSlotId, &cxt); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyList(pRes); + return NULL; + } + return pRes; +} + +static SPhysiNode* makePhysiNode(SPhysiPlanContext* pCxt, ENodeType type) { + SPhysiNode* pPhysiNode = (SPhysiNode*)nodesMakeNode(type); + CHECK_ALLOC(pPhysiNode, NULL); + pPhysiNode->pOutputDataBlockDesc = nodesMakeNode(QUERY_NODE_DATABLOCK_DESC); + if (NULL == pPhysiNode->pOutputDataBlockDesc) { + nodesDestroyNode(pPhysiNode); + return NULL; + } + pPhysiNode->pOutputDataBlockDesc->dataBlockId = pCxt->nextDataBlockId++; + pPhysiNode->pOutputDataBlockDesc->type = QUERY_NODE_DATABLOCK_DESC; + return pPhysiNode; +} + +static int32_t setConditionsSlotId(SPhysiPlanContext* pCxt, const SLogicNode* pLogicNode, SPhysiNode* pPhysiNode) { + if (NULL != pLogicNode->pConditions) { + pPhysiNode->pConditions = setNodeSlotId(pCxt, pPhysiNode->pOutputDataBlockDesc->dataBlockId, -1, pLogicNode->pConditions); + CHECK_ALLOC(pPhysiNode->pConditions, TSDB_CODE_OUT_OF_MEMORY); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t setSlotOutput(SPhysiPlanContext* pCxt, SNodeList* pTargets, SDataBlockDescNode* pDataBlockDesc) { + SHashObj* pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId); + char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; + SNode* pNode; + FOREACH(pNode, pTargets) { + int32_t len = getSlotKey(pNode, name); + SSlotIndex* pIndex = taosHashGet(pHash, name, len); + // pIndex is definitely not NULL, otherwise it is a bug + CHECK_ALLOC(pIndex, TSDB_CODE_FAILED); + ((SSlotDescNode*)nodesListGetNode(pDataBlockDesc->pSlots, pIndex->slotId))->output = true; + } + + return TSDB_CODE_SUCCESS; +} + +static SNodeptr createPrimaryKeyCol(SPhysiPlanContext* pCxt, uint64_t tableId) { + SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN); + CHECK_ALLOC(pCol, NULL); + pCol->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; + pCol->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; + pCol->tableId = tableId; + pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID; + pCol->colType = COLUMN_TYPE_COLUMN; + strcpy(pCol->colName, "#primarykey"); + return pCol; +} + +static int32_t createScanCols(SPhysiPlanContext* pCxt, SScanPhysiNode* pScanPhysiNode, SNodeList* pScanCols) { + pScanPhysiNode->pScanCols = nodesMakeList(); + CHECK_ALLOC(pScanPhysiNode->pScanCols, TSDB_CODE_OUT_OF_MEMORY); + CHECK_CODE_EXT(nodesListStrictAppend(pScanPhysiNode->pScanCols, createPrimaryKeyCol(pCxt, pScanPhysiNode->uid))); + + SNode* pNode; + FOREACH(pNode, pScanCols) { + if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pNode)->colId) { + SColumnNode* pCol = nodesListGetNode(pScanPhysiNode->pScanCols, 0); + strcpy(pCol->tableAlias, ((SColumnNode*)pNode)->tableAlias); + strcpy(pCol->colName, ((SColumnNode*)pNode)->colName); + continue; + } + CHECK_CODE_EXT(nodesListStrictAppend(pScanPhysiNode->pScanCols, nodesCloneNode(pNode))); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t initScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode, SScanPhysiNode* pScanPhysiNode) { + CHECK_CODE(createScanCols(pCxt, pScanPhysiNode, pScanLogicNode->pScanCols), TSDB_CODE_OUT_OF_MEMORY); + + // Data block describe also needs to be set without scanning column, such as SELECT COUNT(*) FROM t + CHECK_CODE(addDataBlockDesc(pCxt, pScanPhysiNode->pScanCols, pScanPhysiNode->node.pOutputDataBlockDesc), TSDB_CODE_OUT_OF_MEMORY); + + CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pScanLogicNode, (SPhysiNode*)pScanPhysiNode), TSDB_CODE_OUT_OF_MEMORY); + + CHECK_CODE(setSlotOutput(pCxt, pScanLogicNode->node.pTargets, pScanPhysiNode->node.pOutputDataBlockDesc), TSDB_CODE_OUT_OF_MEMORY); + + pScanPhysiNode->uid = pScanLogicNode->pMeta->uid; + pScanPhysiNode->tableType = pScanLogicNode->pMeta->tableType; + pScanPhysiNode->order = TSDB_ORDER_ASC; + pScanPhysiNode->count = 1; + pScanPhysiNode->reverse = 0; + memcpy(&pScanPhysiNode->tableName, &pScanLogicNode->tableName, sizeof(SName)); + + return TSDB_CODE_SUCCESS; +} + +static void vgroupInfoToNodeAddr(const SVgroupInfo* vg, SQueryNodeAddr* pNodeAddr) { + pNodeAddr->nodeId = vg->vgId; + pNodeAddr->epSet = vg->epSet; +} + +static SPhysiNode* createTagScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) { + STagScanPhysiNode* pTagScan = (STagScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN); + CHECK_ALLOC(pTagScan, NULL); + CHECK_CODE(initScanPhysiNode(pCxt, pScanLogicNode, (SScanPhysiNode*)pTagScan), (SPhysiNode*)pTagScan); + return (SPhysiNode*)pTagScan; +} + +static SPhysiNode* createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SScanLogicNode* pScanLogicNode) { + STableScanPhysiNode* pTableScan = (STableScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN); + CHECK_ALLOC(pTableScan, NULL); + CHECK_CODE(initScanPhysiNode(pCxt, pScanLogicNode, (SScanPhysiNode*)pTableScan), (SPhysiNode*)pTableScan); + pTableScan->scanFlag = pScanLogicNode->scanFlag; + pTableScan->scanRange = pScanLogicNode->scanRange; + vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode); + taosArrayPush(pCxt->pExecNodeList, &pSubplan->execNode); + return (SPhysiNode*)pTableScan; +} + +static SPhysiNode* createScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SScanLogicNode* pScanLogicNode) { + switch (pScanLogicNode->scanType) { + case SCAN_TYPE_TAG: + return createTagScanPhysiNode(pCxt, pScanLogicNode); + case SCAN_TYPE_TABLE: + return createTableScanPhysiNode(pCxt, pSubplan, pScanLogicNode); + case SCAN_TYPE_STABLE: + case SCAN_TYPE_STREAM: + break; + default: + break; + } + return NULL; +} + +static SNodeList* createJoinOutputCols(SPhysiPlanContext* pCxt, SDataBlockDescNode* pLeftDesc, SDataBlockDescNode* pRightDesc) { + SNodeList* pCols = nodesMakeList(); + CHECK_ALLOC(pCols, NULL); + SNode* pNode; + FOREACH(pNode, pLeftDesc->pSlots) { + SSlotDescNode* pSlot = (SSlotDescNode*)pNode; + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + goto error; + } + pCol->node.resType = pSlot->dataType; + pCol->dataBlockId = pLeftDesc->dataBlockId; + pCol->slotId = pSlot->slotId; + pCol->colId = -1; + if (TSDB_CODE_SUCCESS != nodesListAppend(pCols, (SNode*)pCol)) { + goto error; + } + } + FOREACH(pNode, pRightDesc->pSlots) { + SSlotDescNode* pSlot = (SSlotDescNode*)pNode; + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + goto error; + } + pCol->node.resType = pSlot->dataType; + pCol->dataBlockId = pRightDesc->dataBlockId; + pCol->slotId = pSlot->slotId; + pCol->colId = -1; + if (TSDB_CODE_SUCCESS != nodesListAppend(pCols, (SNode*)pCol)) { + goto error; + } + } + return pCols; +error: + nodesDestroyList(pCols); + return NULL; +} + +static SPhysiNode* createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SJoinLogicNode* pJoinLogicNode) { + SJoinPhysiNode* pJoin = (SJoinPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_JOIN); + CHECK_ALLOC(pJoin, NULL); + + SDataBlockDescNode* pLeftDesc = ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc; + SDataBlockDescNode* pRightDesc = ((SPhysiNode*)nodesListGetNode(pChildren, 1))->pOutputDataBlockDesc; + pJoin->pOnConditions = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pOnConditions); + CHECK_ALLOC(pJoin->pOnConditions, (SPhysiNode*)pJoin); + + pJoin->pTargets = createJoinOutputCols(pCxt, pLeftDesc, pRightDesc); + CHECK_ALLOC(pJoin->pTargets, (SPhysiNode*)pJoin); + CHECK_CODE(addDataBlockDesc(pCxt, pJoin->pTargets, pJoin->node.pOutputDataBlockDesc), (SPhysiNode*)pJoin); + + CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pJoinLogicNode, (SPhysiNode*)pJoin), (SPhysiNode*)pJoin); + + CHECK_CODE(setSlotOutput(pCxt, pJoinLogicNode->node.pTargets, pJoin->node.pOutputDataBlockDesc), (SPhysiNode*)pJoin); + + return (SPhysiNode*)pJoin; +} + +typedef struct SRewritePrecalcExprsCxt { + int32_t errCode; + int32_t planNodeId; + int32_t rewriteId; + SNodeList* pPrecalcExprs; +} SRewritePrecalcExprsCxt; + +static EDealRes collectAndRewrite(SRewritePrecalcExprsCxt* pCxt, SNode** pNode) { + SNode* pExpr = nodesCloneNode(*pNode); + CHECK_ALLOC(pExpr, DEAL_RES_ERROR); + if (nodesListAppend(pCxt->pPrecalcExprs, pExpr)) { + nodesDestroyNode(pExpr); + return DEAL_RES_ERROR; + } + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + nodesDestroyNode(pExpr); + return DEAL_RES_ERROR; + } + SExprNode* pRewrittenExpr = (SExprNode*)pExpr; + pCol->node.resType = pRewrittenExpr->resType; + if ('\0' != pRewrittenExpr->aliasName[0]) { + strcpy(pCol->colName, pRewrittenExpr->aliasName); + } else { + snprintf(pRewrittenExpr->aliasName, sizeof(pRewrittenExpr->aliasName), "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId); + strcpy(pCol->colName, pRewrittenExpr->aliasName); + } + nodesDestroyNode(*pNode); + *pNode = (SNode*)pCol; + return DEAL_RES_IGNORE_CHILD; +} + +static EDealRes doRewritePrecalcExprs(SNode** pNode, void* pContext) { + SRewritePrecalcExprsCxt* pCxt = (SRewritePrecalcExprsCxt*)pContext; + switch (nodeType(*pNode)) { + case QUERY_NODE_OPERATOR: + case QUERY_NODE_LOGIC_CONDITION: { + return collectAndRewrite(pContext, pNode); + } + case QUERY_NODE_FUNCTION: { + if (!fmIsAggFunc(((SFunctionNode*)(*pNode))->funcId)) { + return collectAndRewrite(pContext, pNode); + } + } + default: + break; + } + return DEAL_RES_CONTINUE; +} + +static int32_t rewritePrecalcExprs(SPhysiPlanContext* pCxt, SNodeList* pList, SNodeList** pPrecalcExprs, SNodeList** pRewrittenList) { + if (NULL == pList) { + return TSDB_CODE_SUCCESS; + } + + if (NULL == *pPrecalcExprs) { + *pPrecalcExprs = nodesMakeList(); + CHECK_ALLOC(*pPrecalcExprs, TSDB_CODE_OUT_OF_MEMORY); + } + if (NULL == *pRewrittenList) { + *pRewrittenList = nodesMakeList(); + CHECK_ALLOC(*pRewrittenList, TSDB_CODE_OUT_OF_MEMORY); + } + SNode* pNode = NULL; + FOREACH(pNode, pList) { + SNode* pNew = NULL; + if (QUERY_NODE_GROUPING_SET == nodeType(pNode)) { + pNew = nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pNode)->pParameterList, 0)); + } else { + pNew = nodesCloneNode(pNode); + } + CHECK_ALLOC(pNew, TSDB_CODE_OUT_OF_MEMORY); + CHECK_CODE(nodesListAppend(*pRewrittenList, pNew), TSDB_CODE_OUT_OF_MEMORY); + } + SRewritePrecalcExprsCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pPrecalcExprs = *pPrecalcExprs }; + nodesRewriteList(*pRewrittenList, doRewritePrecalcExprs, &cxt); + if (0 == LIST_LENGTH(cxt.pPrecalcExprs)) { + nodesDestroyList(cxt.pPrecalcExprs); + *pPrecalcExprs = NULL; + } + return cxt.errCode; +} + +static SPhysiNode* createAggPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SAggLogicNode* pAggLogicNode) { + SAggPhysiNode* pAgg = (SAggPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_AGG); + CHECK_ALLOC(pAgg, NULL); + + SNodeList* pPrecalcExprs = NULL; + SNodeList* pGroupKeys = NULL; + SNodeList* pAggFuncs = NULL; + CHECK_CODE(rewritePrecalcExprs(pCxt, pAggLogicNode->pGroupKeys, &pPrecalcExprs, &pGroupKeys), (SPhysiNode*)pAgg); + CHECK_CODE(rewritePrecalcExprs(pCxt, pAggLogicNode->pAggFuncs, &pPrecalcExprs, &pAggFuncs), (SPhysiNode*)pAgg); + + SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc); + // push down expression to pOutputDataBlockDesc of child node + if (NULL != pPrecalcExprs) { + pAgg->pExprs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs); + CHECK_ALLOC(pAgg->pExprs, (SPhysiNode*)pAgg); + CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pExprs, pChildTupe), (SPhysiNode*)pAgg); + } + + if (NULL != pGroupKeys) { + pAgg->pGroupKeys = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pGroupKeys); + CHECK_ALLOC(pAgg->pGroupKeys, (SPhysiNode*)pAgg); + CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pGroupKeys, pAgg->node.pOutputDataBlockDesc), (SPhysiNode*)pAgg); + } + + if (NULL != pAggFuncs) { + pAgg->pAggFuncs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pAggFuncs); + CHECK_ALLOC(pAgg->pAggFuncs, (SPhysiNode*)pAgg); + CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pAggFuncs, pAgg->node.pOutputDataBlockDesc), (SPhysiNode*)pAgg); + } + + CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pAggLogicNode, (SPhysiNode*)pAgg), (SPhysiNode*)pAgg); + + CHECK_CODE(setSlotOutput(pCxt, pAggLogicNode->node.pTargets, pAgg->node.pOutputDataBlockDesc), (SPhysiNode*)pAgg); + + return (SPhysiNode*)pAgg; +} + +static SPhysiNode* createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SProjectLogicNode* pProjectLogicNode) { + SProjectPhysiNode* pProject = (SProjectPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_PROJECT); + CHECK_ALLOC(pProject, NULL); + + pProject->pProjections = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc->dataBlockId, -1, pProjectLogicNode->pProjections); + CHECK_ALLOC(pProject->pProjections, (SPhysiNode*)pProject); + CHECK_CODE(addDataBlockDesc(pCxt, pProject->pProjections, pProject->node.pOutputDataBlockDesc), (SPhysiNode*)pProject); + + CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pProjectLogicNode, (SPhysiNode*)pProject), (SPhysiNode*)pProject); + + return (SPhysiNode*)pProject; +} + +static SPhysiNode* createExchangePhysiNode(SPhysiPlanContext* pCxt, SExchangeLogicNode* pExchangeLogicNode) { + SExchangePhysiNode* pExchange = (SExchangePhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_EXCHANGE); + CHECK_ALLOC(pExchange, NULL); + CHECK_CODE(addDataBlockDesc(pCxt, pExchangeLogicNode->node.pTargets, pExchange->node.pOutputDataBlockDesc), (SPhysiNode*)pExchange); + pExchange->srcGroupId = pExchangeLogicNode->srcGroupId; + return (SPhysiNode*)pExchange; +} + +static SPhysiNode* createIntervalPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SWindowLogicNode* pWindowLogicNode) { + SIntervalPhysiNode* pInterval = (SIntervalPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_INTERVAL); + CHECK_ALLOC(pInterval, NULL); + + pInterval->interval = pWindowLogicNode->interval; + pInterval->offset = pWindowLogicNode->offset; + pInterval->sliding = pWindowLogicNode->sliding; + pInterval->pFill = nodesCloneNode(pWindowLogicNode->pFill); + + SNodeList* pPrecalcExprs = NULL; + SNodeList* pFuncs = NULL; + CHECK_CODE(rewritePrecalcExprs(pCxt, pWindowLogicNode->pFuncs, &pPrecalcExprs, &pFuncs), (SPhysiNode*)pInterval); + + SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc); + // push down expression to pOutputDataBlockDesc of child node + if (NULL != pPrecalcExprs) { + pInterval->pExprs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs); + CHECK_ALLOC(pInterval->pExprs, (SPhysiNode*)pInterval); + CHECK_CODE(addDataBlockDesc(pCxt, pInterval->pExprs, pChildTupe), (SPhysiNode*)pInterval); + } + + if (NULL != pFuncs) { + pInterval->pFuncs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pFuncs); + CHECK_ALLOC(pInterval->pFuncs, (SPhysiNode*)pInterval); + CHECK_CODE(addDataBlockDesc(pCxt, pInterval->pFuncs, pInterval->node.pOutputDataBlockDesc), (SPhysiNode*)pInterval); + } + + CHECK_CODE(setSlotOutput(pCxt, pWindowLogicNode->node.pTargets, pInterval->node.pOutputDataBlockDesc), (SPhysiNode*)pInterval); + + return (SPhysiNode*)pInterval; +} + +static SPhysiNode* createWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SWindowLogicNode* pWindowLogicNode) { + switch (pWindowLogicNode->winType) { + case WINDOW_TYPE_INTERVAL: + return createIntervalPhysiNode(pCxt, pChildren, pWindowLogicNode); + case WINDOW_TYPE_SESSION: + case WINDOW_TYPE_STATE: + break; + default: + break; + } + return NULL; +} + +static SPhysiNode* createPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SLogicNode* pLogicPlan) { + SNodeList* pChildren = nodesMakeList(); + CHECK_ALLOC(pChildren, NULL); + + SNode* pLogicChild; + FOREACH(pLogicChild, pLogicPlan->pChildren) { + if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pChildren, createPhysiNode(pCxt, pSubplan, (SLogicNode*)pLogicChild))) { + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; + nodesDestroyList(pChildren); + return NULL; + } + } + + SPhysiNode* pPhyNode = NULL; + switch (nodeType(pLogicPlan)) { + case QUERY_NODE_LOGIC_PLAN_SCAN: + pPhyNode = createScanPhysiNode(pCxt, pSubplan, (SScanLogicNode*)pLogicPlan); + break; + case QUERY_NODE_LOGIC_PLAN_JOIN: + pPhyNode = createJoinPhysiNode(pCxt, pChildren, (SJoinLogicNode*)pLogicPlan); + break; + case QUERY_NODE_LOGIC_PLAN_AGG: + pPhyNode = createAggPhysiNode(pCxt, pChildren, (SAggLogicNode*)pLogicPlan); + break; + case QUERY_NODE_LOGIC_PLAN_PROJECT: + pPhyNode = createProjectPhysiNode(pCxt, pChildren, (SProjectLogicNode*)pLogicPlan); + break; + case QUERY_NODE_LOGIC_PLAN_EXCHANGE: + pPhyNode = createExchangePhysiNode(pCxt, (SExchangeLogicNode*)pLogicPlan); + break; + case QUERY_NODE_LOGIC_PLAN_WINDOW: + pPhyNode = createWindowPhysiNode(pCxt, pChildren, (SWindowLogicNode*)pLogicPlan); + break; + default: + break; + } + if (TSDB_CODE_SUCCESS != pCxt->errCode) { + nodesDestroyNode(pPhyNode); + return NULL; + } + + pPhyNode->pChildren = pChildren; + SNode* pChild; + FOREACH(pChild, pPhyNode->pChildren) { + ((SPhysiNode*)pChild)->pParent = pPhyNode; + } + + return pPhyNode; +} + +static SDataSinkNode* createDataInserter(SPhysiPlanContext* pCxt, SVgDataBlocks* pBlocks) { + SDataInserterNode* pInserter = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_INSERT); + CHECK_ALLOC(pInserter, NULL); + pInserter->numOfTables = pBlocks->numOfTables; + pInserter->size = pBlocks->size; + TSWAP(pInserter->pData, pBlocks->pData, char*); + return (SDataSinkNode*)pInserter; +} + +static SDataSinkNode* createDataDispatcher(SPhysiPlanContext* pCxt, const SPhysiNode* pRoot) { + SDataDispatcherNode* pDispatcher = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_DISPATCH); + CHECK_ALLOC(pDispatcher, NULL); + pDispatcher->sink.pInputDataBlockDesc = nodesCloneNode(pRoot->pOutputDataBlockDesc); + CHECK_ALLOC(pDispatcher->sink.pInputDataBlockDesc, (SDataSinkNode*)pDispatcher); + return (SDataSinkNode*)pDispatcher; +} + +static SSubplan* makeSubplan(SPhysiPlanContext* pCxt, SSubLogicPlan* pLogicSubplan) { + SSubplan* pSubplan = nodesMakeNode(QUERY_NODE_PHYSICAL_SUBPLAN); + CHECK_ALLOC(pSubplan, NULL); + pSubplan->id = pLogicSubplan->id; + pSubplan->subplanType = pLogicSubplan->subplanType; + pSubplan->level = pLogicSubplan->level; + return pSubplan; +} + +static SSubplan* createPhysiSubplan(SPhysiPlanContext* pCxt, SSubLogicPlan* pLogicSubplan) { + SSubplan* pSubplan = makeSubplan(pCxt, pLogicSubplan); + CHECK_ALLOC(pSubplan, NULL); + if (SUBPLAN_TYPE_MODIFY == pLogicSubplan->subplanType) { + SVnodeModifLogicNode* pModif = (SVnodeModifLogicNode*)pLogicSubplan->pNode; + pSubplan->pDataSink = createDataInserter(pCxt, pModif->pVgDataBlocks); + pSubplan->msgType = pModif->msgType; + pSubplan->execNode.epSet = pModif->pVgDataBlocks->vg.epSet; + taosArrayPush(pCxt->pExecNodeList, &pSubplan->execNode); + } else { + pSubplan->pNode = createPhysiNode(pCxt, pSubplan, pLogicSubplan->pNode); + pSubplan->pDataSink = createDataDispatcher(pCxt, pSubplan->pNode); + pSubplan->msgType = TDMT_VND_QUERY; + } + return pSubplan; +} + +static void doSetLogicNodeParent(SLogicNode* pNode, SLogicNode* pParent) { + pNode->pParent = pParent; + SNode* pChild; + FOREACH(pChild, pNode->pChildren) { + doSetLogicNodeParent((SLogicNode*)pChild, pNode); + } +} + +static void setLogicNodeParent(SLogicNode* pNode) { + doSetLogicNodeParent(pNode, NULL); +} + +static int32_t splitLogicPlan(SPhysiPlanContext* pCxt, SLogicNode* pLogicNode, SSubLogicPlan** pSubLogicPlan) { + *pSubLogicPlan = (SSubLogicPlan*)nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN); + CHECK_ALLOC(*pSubLogicPlan, TSDB_CODE_OUT_OF_MEMORY); + (*pSubLogicPlan)->pNode = nodesCloneNode(pLogicNode); + if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIF == nodeType(pLogicNode)) { + (*pSubLogicPlan)->subplanType = SUBPLAN_TYPE_MODIFY; + TSWAP(((SVnodeModifLogicNode*)pLogicNode)->pDataBlocks, ((SVnodeModifLogicNode*)(*pSubLogicPlan)->pNode)->pDataBlocks, SArray*); + } else { + (*pSubLogicPlan)->subplanType = SUBPLAN_TYPE_SCAN; + } + (*pSubLogicPlan)->id.queryId = pCxt->pPlanCxt->queryId; + setLogicNodeParent((*pSubLogicPlan)->pNode); + return applySplitRule(*pSubLogicPlan); +} + +static int32_t pushSubplan(SPhysiPlanContext* pCxt, SNodeptr pSubplan, int32_t level, SNodeList* pSubplans) { + SNodeListNode* pGroup; + if (level >= LIST_LENGTH(pSubplans)) { + pGroup = nodesMakeNode(QUERY_NODE_NODE_LIST); + CHECK_ALLOC(pGroup, TSDB_CODE_OUT_OF_MEMORY); + CHECK_CODE(nodesListStrictAppend(pSubplans, pGroup), TSDB_CODE_OUT_OF_MEMORY); + } else { + pGroup = nodesListGetNode(pSubplans, level); + } + if (NULL == pGroup->pNodeList) { + pGroup->pNodeList = nodesMakeList(); + CHECK_ALLOC(pGroup->pNodeList, TSDB_CODE_OUT_OF_MEMORY); + } + CHECK_CODE(nodesListStrictAppend(pGroup->pNodeList, pSubplan), TSDB_CODE_OUT_OF_MEMORY); + return TSDB_CODE_SUCCESS; +} + +static SSubLogicPlan* singleCloneSubLogicPlan(SPhysiPlanContext* pCxt, SSubLogicPlan* pSrc, int32_t level) { + SSubLogicPlan* pDst = nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN); + CHECK_ALLOC(pDst, NULL); + pDst->pNode = nodesCloneNode(pSrc->pNode); + if (NULL == pDst->pNode) { + nodesDestroyNode(pDst); + return NULL; + } + pDst->subplanType = pSrc->subplanType; + pDst->level = level; + pDst->id.queryId = pSrc->id.queryId; + pDst->id.groupId = pSrc->id.groupId; + pDst->id.subplanId = pCxt->subplanId++; + return pDst; +} + +static int32_t scaleOutForModify(SPhysiPlanContext* pCxt, SSubLogicPlan* pSubplan, int32_t level, SNodeList* pGroup) { + SVnodeModifLogicNode* pNode = (SVnodeModifLogicNode*)pSubplan->pNode; + size_t numOfVgroups = taosArrayGetSize(pNode->pDataBlocks); + for (int32_t i = 0; i < numOfVgroups; ++i) { + SSubLogicPlan* pNewSubplan = singleCloneSubLogicPlan(pCxt, pSubplan, level); + CHECK_ALLOC(pNewSubplan, TSDB_CODE_OUT_OF_MEMORY); + SVgDataBlocks* blocks = (SVgDataBlocks*)taosArrayGetP(pNode->pDataBlocks, i); + ((SVnodeModifLogicNode*)pNewSubplan->pNode)->pVgDataBlocks = blocks; + CHECK_CODE_EXT(nodesListAppend(pGroup, pNewSubplan)); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t scaleOutForMerge(SPhysiPlanContext* pCxt, SSubLogicPlan* pSubplan, int32_t level, SNodeList* pGroup) { + return nodesListStrictAppend(pGroup, singleCloneSubLogicPlan(pCxt, pSubplan, level)); +} + +static int32_t doSetScanVgroup(SPhysiPlanContext* pCxt, SLogicNode* pNode, const SVgroupInfo* pVgroup, bool* pFound) { + if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) { + SScanLogicNode* pScan = (SScanLogicNode*)pNode; + pScan->pVgroupList = calloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo)); + CHECK_ALLOC(pScan->pVgroupList, TSDB_CODE_OUT_OF_MEMORY); + memcpy(pScan->pVgroupList->vgroups, pVgroup, sizeof(SVgroupInfo)); + *pFound = true; + return TSDB_CODE_SUCCESS; + } + SNode* pChild = NULL; + FOREACH(pChild, pNode->pChildren) { + int32_t code = doSetScanVgroup(pCxt, (SLogicNode*)pChild, pVgroup, pFound); + if (TSDB_CODE_SUCCESS != code || *pFound) { + return code; + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t setScanVgroup(SPhysiPlanContext* pCxt, SLogicNode* pNode, const SVgroupInfo* pVgroup) { + bool found = false; + return doSetScanVgroup(pCxt, pNode, pVgroup, &found); +} + +static int32_t scaleOutForScan(SPhysiPlanContext* pCxt, SSubLogicPlan* pSubplan, int32_t level, SNodeList* pGroup) { + if (pSubplan->pVgroupList) { + for (int32_t i = 0; i < pSubplan->pVgroupList->numOfVgroups; ++i) { + SSubLogicPlan* pNewSubplan = singleCloneSubLogicPlan(pCxt, pSubplan, level); + CHECK_ALLOC(pNewSubplan, TSDB_CODE_OUT_OF_MEMORY); + CHECK_CODE_EXT(setScanVgroup(pCxt, pNewSubplan->pNode, pSubplan->pVgroupList->vgroups + i)); + CHECK_CODE_EXT(nodesListAppend(pGroup, pNewSubplan)); + } + return TSDB_CODE_SUCCESS; + } else { + return scaleOutForMerge(pCxt, pSubplan, level, pGroup); + } +} + +static int32_t appendWithMakeList(SNodeList** pList, SNodeptr pNode) { + if (NULL == *pList) { + *pList = nodesMakeList(); + if (NULL == *pList) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + return nodesListAppend(*pList, pNode); +} + +static int32_t pushHierarchicalPlan(SPhysiPlanContext* pCxt, SNodeList* pParentsGroup, SNodeList* pCurrentGroup) { + bool topLevel = (0 == LIST_LENGTH(pParentsGroup)); + SNode* pChild = NULL; + FOREACH(pChild, pCurrentGroup) { + if (topLevel) { + CHECK_CODE_EXT(nodesListAppend(pParentsGroup, pChild)); + } else { + SNode* pParent = NULL; + FOREACH(pParent, pParentsGroup) { + CHECK_CODE_EXT(appendWithMakeList(&(((SSubLogicPlan*)pParent)->pChildren), pChild)); + CHECK_CODE_EXT(appendWithMakeList(&(((SSubLogicPlan*)pChild)->pParents), pParent)); + } + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t doScaleOut(SPhysiPlanContext* pCxt, SSubLogicPlan* pSubplan, int32_t* pLevel, SNodeList* pParentsGroup) { + SNodeList* pCurrentGroup = nodesMakeList(); + CHECK_ALLOC(pCurrentGroup, TSDB_CODE_OUT_OF_MEMORY); + int32_t code = TSDB_CODE_SUCCESS; + switch (pSubplan->subplanType) { + case SUBPLAN_TYPE_MERGE: + code = scaleOutForMerge(pCxt, pSubplan, *pLevel, pCurrentGroup); + break; + case SUBPLAN_TYPE_SCAN: + code = scaleOutForScan(pCxt, pSubplan, *pLevel, pCurrentGroup); + break; + case SUBPLAN_TYPE_MODIFY: + code = scaleOutForModify(pCxt, pSubplan, *pLevel, pCurrentGroup); + break; + default: + break; + } + if (TSDB_CODE_SUCCESS != code) { + return code; + } + + CHECK_CODE_EXT(pushHierarchicalPlan(pCxt, pParentsGroup, pCurrentGroup)); + ++(*pLevel); + SNode* pChild; + FOREACH(pChild, pSubplan->pChildren) { + CHECK_CODE_EXT(doScaleOut(pCxt, (SSubLogicPlan*)pChild, pLevel, pCurrentGroup)); + } + + return TSDB_CODE_SUCCESS; +} + +static SQueryLogicPlan* makeQueryLogicPlan(SPhysiPlanContext* pCxt) { + SQueryLogicPlan* pLogicPlan = (SQueryLogicPlan*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN); + CHECK_ALLOC(pLogicPlan, NULL); + pLogicPlan->pTopSubplans = nodesMakeList(); + if (NULL == pLogicPlan->pTopSubplans) { + nodesDestroyNode(pLogicPlan); + return NULL; + } + return pLogicPlan; +} + +static int32_t scaleOutLogicPlan(SPhysiPlanContext* pCxt, SSubLogicPlan* pRootSubLogicPlan, SQueryLogicPlan** pLogicPlan) { + *pLogicPlan = makeQueryLogicPlan(pCxt); + CHECK_ALLOC(*pLogicPlan, TSDB_CODE_OUT_OF_MEMORY); + return doScaleOut(pCxt, pRootSubLogicPlan, &((*pLogicPlan)->totalLevel), (*pLogicPlan)->pTopSubplans); +} + +static SQueryPlan* makeQueryPhysiPlan(SPhysiPlanContext* pCxt) { + SQueryPlan* pPlan = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN); + CHECK_ALLOC(pPlan, NULL); + pPlan->pSubplans = nodesMakeList(); + if (NULL == pPlan->pSubplans) { + nodesDestroyNode(pPlan); + return NULL; + } + pPlan->queryId = pCxt->pPlanCxt->queryId; + return pPlan; +} + +static int32_t doBuildPhysiPlan(SPhysiPlanContext* pCxt, SSubLogicPlan* pLogicSubplan, SSubplan* pParent, SQueryPlan* pQueryPlan) { + SSubplan* pSubplan = createPhysiSubplan(pCxt, pLogicSubplan); + CHECK_ALLOC(pSubplan, DEAL_RES_ERROR); + CHECK_CODE_EXT(pushSubplan(pCxt, pSubplan, pLogicSubplan->level, pQueryPlan->pSubplans)); + ++(pQueryPlan->numOfSubplans); + if (NULL != pParent) { + CHECK_CODE_EXT(appendWithMakeList(&pParent->pChildren, pSubplan)); + CHECK_CODE_EXT(appendWithMakeList(&pSubplan->pParents, pParent)); + } + + SNode* pChild = NULL; + FOREACH(pChild, pLogicSubplan->pChildren) { + CHECK_CODE_EXT(doBuildPhysiPlan(pCxt, (SSubLogicPlan*)pChild, pSubplan, pQueryPlan)); + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t buildPhysiPlan(SPhysiPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryPlan** pPlan) { + *pPlan = makeQueryPhysiPlan(pCxt); + CHECK_ALLOC(*pPlan, TSDB_CODE_OUT_OF_MEMORY); + SNode* pSubplan = NULL; + FOREACH(pSubplan, pLogicPlan->pTopSubplans) { + CHECK_CODE_EXT(doBuildPhysiPlan(pCxt, (SSubLogicPlan*)pSubplan, NULL, *pPlan)); + } + return TSDB_CODE_SUCCESS; +} + +int32_t createPhysiPlan(SPlanContext* pCxt, SLogicNode* pLogicNode, SQueryPlan** pPlan, SArray* pExecNodeList) { + SPhysiPlanContext cxt = { + .pPlanCxt = pCxt, + .errCode = TSDB_CODE_SUCCESS, + .nextDataBlockId = 0, + .pLocationHelper = taosArrayInit(32, POINTER_BYTES), + .pExecNodeList = pExecNodeList + }; + if (NULL == cxt.pLocationHelper) { + return TSDB_CODE_OUT_OF_MEMORY; + } + SQueryLogicPlan* pLogicPlan = NULL; + SSubLogicPlan* pSubLogicPlan = NULL; + int32_t code = splitLogicPlan(&cxt, pLogicNode, &pSubLogicPlan); + if (TSDB_CODE_SUCCESS == code) { + code = scaleOutLogicPlan(&cxt, pSubLogicPlan, &pLogicPlan); + } + if (TSDB_CODE_SUCCESS == code) { + code = buildPhysiPlan(&cxt, pLogicPlan, pPlan); + } + nodesDestroyNode(pSubLogicPlan); + nodesDestroyNode(pLogicPlan); + return code; +} diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c new file mode 100644 index 0000000000000000000000000000000000000000..5a5e1d46c622ec9d854614b9ddb4724bd047e710 --- /dev/null +++ b/source/libs/planner/src/planSpliter.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "planInt.h" + +#define SPLIT_FLAG_MASK(n) (1 << n) + +#define SPLIT_FLAG_STS SPLIT_FLAG_MASK(0) + +#define SPLIT_FLAG_SET_MASK(val, mask) (val) |= (mask) +#define SPLIT_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0) + +typedef struct SSplitContext { + int32_t errCode; + int32_t groupId; + bool match; + void* pInfo; +} SSplitContext; + +typedef int32_t (*FMatch)(SSplitContext* pCxt, SSubLogicPlan* pSubplan); +typedef int32_t (*FSplit)(SSplitContext* pCxt); + +typedef struct SSplitRule { + char* pName; + FMatch matchFunc; + FSplit splitFunc; +} SSplitRule; + +typedef struct SStsInfo { + SScanLogicNode* pScan; + SSubLogicPlan* pSubplan; +} SStsInfo; + +static SLogicNode* stsMatchByNode(SLogicNode* pNode) { + if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode) && TSDB_SUPER_TABLE == ((SScanLogicNode*)pNode)->pMeta->tableType) { + return pNode; + } + SNode* pChild; + FOREACH(pChild, pNode->pChildren) { + SLogicNode* pSplitNode = stsMatchByNode((SLogicNode*)pChild); + if (NULL != pSplitNode) { + return pSplitNode; + } + } + return NULL; +} + +static int32_t stsMatch(SSplitContext* pCxt, SSubLogicPlan* pSubplan) { + if (SPLIT_FLAG_TEST_MASK(pSubplan->splitFlag, SPLIT_FLAG_STS)) { + return TSDB_CODE_SUCCESS; + } + SLogicNode* pSplitNode = stsMatchByNode(pSubplan->pNode); + if (NULL != pSplitNode) { + SStsInfo* pInfo = calloc(1, sizeof(SStsInfo)); + CHECK_ALLOC(pInfo, TSDB_CODE_OUT_OF_MEMORY); + pInfo->pScan = (SScanLogicNode*)pSplitNode; + pInfo->pSubplan = pSubplan; + pCxt->pInfo = pInfo; + pCxt->match = true; + return TSDB_CODE_SUCCESS; + } + SNode* pChild; + FOREACH(pChild, pSubplan->pChildren) { + int32_t code = stsMatch(pCxt, (SSubLogicPlan*)pChild); + if (TSDB_CODE_SUCCESS != code || pCxt->match) { + return code; + } + } + return TSDB_CODE_SUCCESS; +} + +static SSubLogicPlan* stsCreateScanSubplan(SSplitContext* pCxt, SScanLogicNode* pScan) { + SSubLogicPlan* pSubplan = nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN); + if (NULL == pSubplan) { + return NULL; + } + pSubplan->id.groupId = pCxt->groupId; + pSubplan->subplanType = SUBPLAN_TYPE_SCAN; + pSubplan->pNode = (SLogicNode*)nodesCloneNode(pScan); + TSWAP(pSubplan->pVgroupList, ((SScanLogicNode*)pSubplan->pNode)->pVgroupList, SVgroupsInfo); + SPLIT_FLAG_SET_MASK(pSubplan->splitFlag, SPLIT_FLAG_STS); + return pSubplan; +} + +static int32_t stsCreateExchangeNode(SSplitContext* pCxt, SSubLogicPlan* pSubplan, SScanLogicNode* pScan) { + SExchangeLogicNode* pExchange = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_EXCHANGE); + if (NULL == pExchange) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pExchange->srcGroupId = pCxt->groupId; + pExchange->node.pTargets = nodesCloneList(pScan->node.pTargets); + if (NULL == pExchange->node.pTargets) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + if (NULL == pScan->node.pParent) { + pSubplan->pNode = (SLogicNode*)pExchange; + return TSDB_CODE_SUCCESS; + } + + SNode* pNode; + FOREACH(pNode, pScan->node.pParent->pChildren) { + if (nodesEqualNode(pNode, pScan)) { + REPLACE_NODE(pExchange); + nodesDestroyNode(pNode); + return TSDB_CODE_SUCCESS; + } + } + nodesDestroyNode(pExchange); + return TSDB_CODE_FAILED; +} + +static int32_t stsSplit(SSplitContext* pCxt) { + SStsInfo* pInfo = pCxt->pInfo; + if (NULL == pInfo->pSubplan->pChildren) { + pInfo->pSubplan->pChildren = nodesMakeList(); + if (NULL == pInfo->pSubplan->pChildren) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + int32_t code = nodesListStrictAppend(pInfo->pSubplan->pChildren, stsCreateScanSubplan(pCxt, pInfo->pScan)); + if (TSDB_CODE_SUCCESS == code) { + code = stsCreateExchangeNode(pCxt, pInfo->pSubplan, pInfo->pScan); + } + ++(pCxt->groupId); + return code; +} + +static const SSplitRule splitRuleSet[] = { + { .pName = "SuperTableScan", .matchFunc = stsMatch, .splitFunc = stsSplit } +}; + +static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule)); + +int32_t applySplitRule(SSubLogicPlan* pSubplan) { + SSplitContext cxt = { .errCode = TSDB_CODE_SUCCESS, .groupId = pSubplan->id.groupId + 1, .match = false, .pInfo = NULL }; + bool split = false; + do { + split = false; + for (int32_t i = 0; i < splitRuleNum; ++i) { + cxt.match = false; + int32_t code = splitRuleSet[i].matchFunc(&cxt, pSubplan); + if (TSDB_CODE_SUCCESS == code && cxt.match) { + code = splitRuleSet[i].splitFunc(&cxt); + split = true; + } + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + } while (split); + return TSDB_CODE_SUCCESS; +} diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index e6b7eaca7f36eaed5b05e2d781fc659f5ad6cbbf..fa0dc549c8a0d3ea1dcaa4120a9c9e0d020cb3b5 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -13,90 +13,89 @@ * along with this program. If not, see . */ -#include "parser.h" -#include "plannerInt.h" +#include "planner.h" -static void extractResSchema(struct SQueryDag* const* pDag, SSchema** pResSchema, int32_t* numOfCols); +#include "planInt.h" -void qDestroyQueryDag(struct SQueryDag* pDag) { - if (pDag == NULL) { - return; - } - - size_t size = taosArrayGetSize(pDag->pSubplans); - for(size_t i = 0; i < size; ++i) { - SArray* pa = taosArrayGetP(pDag->pSubplans, i); - - size_t t = taosArrayGetSize(pa); - for(int32_t j = 0; j < t; ++j) { - SSubplan* pSubplan = taosArrayGetP(pa, j); - qDestroySubplan(pSubplan); - } - - taosArrayDestroy(pa); - } - - taosArrayDestroy(pDag->pSubplans); - tfree(pDag); +int32_t optimize(SPlanContext* pCxt, SLogicNode* pLogicNode) { + return TSDB_CODE_SUCCESS; } -int32_t qCreateQueryDag(const struct SQueryNode* pNode, struct SQueryDag** pDag, SSchema** pResSchema, int32_t* numOfCols, SArray* pNodeList, - uint64_t requestId) { - SQueryPlanNode* pLogicPlan; - int32_t code = createQueryPlan(pNode, &pLogicPlan); - if (TSDB_CODE_SUCCESS != code) { - destroyQueryPlan(pLogicPlan); - return code; +int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNodeList) { + SLogicNode* pLogicNode = NULL; + int32_t code = createLogicPlan(pCxt, &pLogicNode); + if (TSDB_CODE_SUCCESS == code) { + code = optimize(pCxt, pLogicNode); } - - if (pLogicPlan->info.type != QNODE_MODIFY) { - char* str = NULL; - queryPlanToString(pLogicPlan, &str); - qDebug("reqId:0x%"PRIx64": %s", requestId, str); - tfree(str); + if (TSDB_CODE_SUCCESS == code) { + code = createPhysiPlan(pCxt, pLogicNode, pPlan, pExecNodeList); } + nodesDestroyNode(pLogicNode); + return code; +} - code = optimizeQueryPlan(pLogicPlan); - if (TSDB_CODE_SUCCESS != code) { - destroyQueryPlan(pLogicPlan); - return code; +static int32_t setSubplanExecutionNode(SPhysiNode* pNode, int32_t groupId, SDownstreamSourceNode* pSource) { + if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == nodeType(pNode)) { + SExchangePhysiNode* pExchange = (SExchangePhysiNode*)pNode; + if (pExchange->srcGroupId == groupId) { + if (NULL == pExchange->pSrcEndPoints) { + pExchange->pSrcEndPoints = nodesMakeList(); + if (NULL == pExchange->pSrcEndPoints) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pExchange->pSrcEndPoints, nodesCloneNode(pSource))) { + return TSDB_CODE_OUT_OF_MEMORY; + } + return TSDB_CODE_SUCCESS; + } } - code = createDag(pLogicPlan, NULL, pDag, pNodeList, requestId); - if (TSDB_CODE_SUCCESS != code) { - destroyQueryPlan(pLogicPlan); - qDestroyQueryDag(*pDag); - return code; + SNode* pChild = NULL; + FOREACH(pChild, pNode->pChildren) { + if (TSDB_CODE_SUCCESS != setSubplanExecutionNode((SPhysiNode*)pChild, groupId, pSource)) { + return TSDB_CODE_OUT_OF_MEMORY; + } } - - extractResSchema(pDag, pResSchema, numOfCols); - - destroyQueryPlan(pLogicPlan); return TSDB_CODE_SUCCESS; } -// extract the final result schema -void extractResSchema(struct SQueryDag* const* pDag, SSchema** pResSchema, int32_t* numOfCols) { - SArray* pTopSubplan = taosArrayGetP((*pDag)->pSubplans, 0); - - SSubplan* pPlan = taosArrayGetP(pTopSubplan, 0); - SDataBlockSchema* pDataBlockSchema = &(pPlan->pDataSink->schema); +int32_t qSetSubplanExecutionNode(SSubplan* subplan, int32_t groupId, SDownstreamSourceNode* pSource) { + return setSubplanExecutionNode(subplan->pNode, groupId, pSource); +} - *numOfCols = pDataBlockSchema->numOfCols; - if (*numOfCols > 0) { - *pResSchema = calloc(pDataBlockSchema->numOfCols, sizeof(SSchema)); - memcpy((*pResSchema), pDataBlockSchema->pSchema, pDataBlockSchema->numOfCols * sizeof(SSchema)); +int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen) { + if (SUBPLAN_TYPE_MODIFY == pSubplan->subplanType) { + SDataInserterNode* insert = (SDataInserterNode*)pSubplan->pDataSink; + *pLen = insert->size; + *pStr = insert->pData; + insert->pData = NULL; + return TSDB_CODE_SUCCESS; } + return nodesNodeToString((const SNode*)pSubplan, false, pStr, pLen); } -void qSetSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SDownstreamSource* pSource) { - setSubplanExecutionNode(subplan, templateId, pSource); +int32_t qStringToSubplan(const char* pStr, SSubplan** pSubplan) { + return nodesStringToNode(pStr, (SNode**)pSubplan); } -int32_t qSubPlanToString(const SSubplan *subplan, char** str, int32_t* len) { - return subPlanToString(subplan, str, len); +char* qQueryPlanToString(const SQueryPlan* pPlan) { + char* pStr = NULL; + int32_t len = 0; + if (TSDB_CODE_SUCCESS != nodesNodeToString(pPlan, false, &pStr, &len)) { + return NULL; + } + return pStr; +} + +SQueryPlan* qStringToQueryPlan(const char* pStr) { + SQueryPlan* pPlan = NULL; + if (TSDB_CODE_SUCCESS != nodesStringToNode(pStr, (SNode**)&pPlan)) { + return NULL; + } + return pPlan; } -int32_t qStringToSubplan(const char* str, SSubplan** subplan) { - return stringToSubplan(str, subplan); +void qDestroyQueryPlan(SQueryPlan* pPlan) { + nodesDestroyNode(pPlan); } diff --git a/source/libs/planner/src/plannerImpl.c b/source/libs/planner/src/plannerImpl.c deleted file mode 100644 index b7e28d70db2110672401861e42125f48e00497e6..0000000000000000000000000000000000000000 --- a/source/libs/planner/src/plannerImpl.c +++ /dev/null @@ -1,866 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "plannerImpl.h" -#include "functionMgt.h" - -#define CHECK_ALLOC(p, res) \ - do { \ - if (NULL == (p)) { \ - pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \ - return (res); \ - } \ - } while (0) - -#define CHECK_CODE(exec, res) \ - do { \ - int32_t code = (exec); \ - if (TSDB_CODE_SUCCESS != code) { \ - pCxt->errCode = code; \ - return (res); \ - } \ - } while (0) - -typedef struct SPlanContext { - int32_t errCode; - int32_t planNodeId; -} SPlanContext; - -static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt); -static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable); - -typedef struct SRewriteExprCxt { - int32_t errCode; - SNodeList* pExprs; -} SRewriteExprCxt; - -static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { - switch (nodeType(*pNode)) { - case QUERY_NODE_OPERATOR: - case QUERY_NODE_LOGIC_CONDITION: - case QUERY_NODE_FUNCTION: { - SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext; - SNode* pExpr; - int32_t index = 0; - FOREACH(pExpr, pCxt->pExprs) { - if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) { - pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0); - } - if (nodesEqualNode(pExpr, *pNode)) { - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - CHECK_ALLOC(pCol, DEAL_RES_ERROR); - SExprNode* pToBeRewrittenExpr = (SExprNode*)(*pNode); - pCol->node.resType = pToBeRewrittenExpr->resType; - strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName); - strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName); - nodesDestroyNode(*pNode); - *pNode = (SNode*)pCol; - return DEAL_RES_IGNORE_CHILD; - } - ++index; - } - break; - } - default: - break; - } - - return DEAL_RES_CONTINUE; -} - -typedef struct SNameExprCxt { - int32_t planNodeId; - int32_t rewriteId; -} SNameExprCxt; - -static EDealRes doNameExpr(SNode* pNode, void* pContext) { - switch (nodeType(pNode)) { - case QUERY_NODE_OPERATOR: - case QUERY_NODE_LOGIC_CONDITION: - case QUERY_NODE_FUNCTION: { - SNameExprCxt* pCxt = (SNameExprCxt*)pContext; - sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId++); - return DEAL_RES_IGNORE_CHILD; - } - default: - break; - } - - return DEAL_RES_CONTINUE; -} - -static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) { - SNameExprCxt nameCxt = { .planNodeId = planNodeId, .rewriteId = rewriteId }; - nodesWalkList(pExprs, doNameExpr, &nameCxt); - SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs }; - nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt); - return cxt.errCode; -} - -static SLogicNode* pushLogicNode(SPlanContext* pCxt, SLogicNode* pRoot, SLogicNode* pNode) { - if (TSDB_CODE_SUCCESS != pCxt->errCode) { - goto error; - } - - if (NULL == pRoot) { - return pNode; - } - - if (NULL == pNode) { - return pRoot; - } - - if (NULL == pNode->pChildren) { - pNode->pChildren = nodesMakeList(); - if (NULL == pNode->pChildren) { - goto error; - } - } - if (TSDB_CODE_SUCCESS != nodesListAppend(pNode->pChildren, (SNode*)pRoot)) { - goto error; - } - pRoot->pParent = pNode; - return pNode; -error: - nodesDestroyNode((SNode*)pNode); - return pRoot; -} - -static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) { - SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN); - CHECK_ALLOC(pScan, NULL); - pScan->node.id = pCxt->planNodeId++; - - pScan->pMeta = pRealTable->pMeta; - - // set columns to scan - SNodeList* pCols = NULL; - CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan); - if (NULL != pCols) { - pScan->pScanCols = nodesCloneList(pCols); - CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan); - } - - // set output - if (NULL != pCols) { - pScan->node.pTargets = nodesCloneList(pCols); - CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan); - } - - pScan->scanType = SCAN_TYPE_TABLE; - pScan->scanFlag = MAIN_SCAN; - pScan->scanRange = TSWINDOW_INITIALIZER; - - return (SLogicNode*)pScan; -} - -static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) { - SLogicNode* pRoot = createQueryLogicNode(pCxt, pTable->pSubquery); - CHECK_ALLOC(pRoot, NULL); - SNode* pNode; - FOREACH(pNode, pRoot->pTargets) { - strcpy(((SColumnNode*)pNode)->tableAlias, pTable->table.tableAlias); - } - return pRoot; -} - -static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) { - SJoinLogicNode* pJoin = (SJoinLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN); - CHECK_ALLOC(pJoin, NULL); - pJoin->node.id = pCxt->planNodeId++; - - pJoin->joinType = pJoinTable->joinType; - - // set left and right node - pJoin->node.pChildren = nodesMakeList(); - CHECK_ALLOC(pJoin->node.pChildren, (SLogicNode*)pJoin); - SLogicNode* pLeft = createLogicNodeByTable(pCxt, pSelect, pJoinTable->pLeft); - CHECK_ALLOC(pLeft, (SLogicNode*)pJoin); - CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pLeft), (SLogicNode*)pJoin); - SLogicNode* pRight = createLogicNodeByTable(pCxt, pSelect, pJoinTable->pRight); - CHECK_ALLOC(pRight, (SLogicNode*)pJoin); - CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin); - - // set on conditions - if (NULL != pJoinTable->pOnCond) { - pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond); - CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin); - } - - // set the output - pJoin->node.pTargets = nodesCloneList(pLeft->pTargets); - CHECK_ALLOC(pJoin->node.pTargets, (SLogicNode*)pJoin); - SNodeList* pTargets = nodesCloneList(pRight->pTargets); - CHECK_ALLOC(pTargets, (SLogicNode*)pJoin); - nodesListAppendList(pJoin->node.pTargets, pTargets); - - return (SLogicNode*)pJoin; -} - -static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable) { - switch (nodeType(pTable)) { - case QUERY_NODE_REAL_TABLE: - return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable); - case QUERY_NODE_TEMP_TABLE: - return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable); - case QUERY_NODE_JOIN_TABLE: - return createJoinLogicNode(pCxt, pSelect, (SJoinTableNode*)pTable); - default: - break; - } - return NULL; -} - -typedef struct SCreateColumnCxt { - int32_t errCode; - SNodeList* pList; -} SCreateColumnCxt; - -static EDealRes doCreateColumn(SNode* pNode, void* pContext) { - SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext; - switch (nodeType(pNode)) { - case QUERY_NODE_COLUMN: { - SNode* pCol = nodesCloneNode(pNode); - CHECK_ALLOC(pCol, DEAL_RES_ERROR); - CHECK_CODE(nodesListAppend(pCxt->pList, pCol), DEAL_RES_ERROR); - return DEAL_RES_IGNORE_CHILD; - } - case QUERY_NODE_OPERATOR: - case QUERY_NODE_LOGIC_CONDITION: - case QUERY_NODE_FUNCTION: { - SExprNode* pExpr = (SExprNode*)pNode; - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - CHECK_ALLOC(pCol, DEAL_RES_ERROR); - pCol->node.resType = pExpr->resType; - strcpy(pCol->colName, pExpr->aliasName); - CHECK_CODE(nodesListAppend(pCxt->pList, (SNode*)pCol), DEAL_RES_ERROR); - return DEAL_RES_IGNORE_CHILD; - } - default: - break; - } - - return DEAL_RES_CONTINUE; -} - -static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) { - SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() }; - CHECK_ALLOC(cxt.pList, NULL); - - nodesWalkList(pExprs, doCreateColumn, &cxt); - if (TSDB_CODE_SUCCESS != cxt.errCode) { - nodesDestroyList(cxt.pList); - return NULL; - } - return cxt.pList; -} - -static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { - SNodeList* pAggFuncs = NULL; - CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL); - if (NULL == pAggFuncs && NULL == pSelect->pGroupByList) { - return NULL; - } - - SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG); - CHECK_ALLOC(pAgg, NULL); - pAgg->node.id = pCxt->planNodeId++; - - // set grouyp keys, agg funcs and having conditions - if (NULL != pSelect->pGroupByList) { - pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList); - CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg); - } - if (NULL != pAggFuncs) { - pAgg->pAggFuncs = nodesCloneList(pAggFuncs); - CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg); - } - - // rewrite the expression in subsequent clauses - CHECK_CODE(rewriteExpr(pAgg->node.id, 1, pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg); - CHECK_CODE(rewriteExpr(pAgg->node.id, 1 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg); - - if (NULL != pSelect->pHaving) { - pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving); - CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg); - } - - // set the output - pAgg->node.pTargets = nodesMakeList(); - CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg); - if (NULL != pAgg->pGroupKeys) { - SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys); - CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg); - nodesListAppendList(pAgg->node.pTargets, pTargets); - } - if (NULL != pAgg->pAggFuncs) { - SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs); - CHECK_ALLOC(pTargets, (SLogicNode*)pAgg); - nodesListAppendList(pAgg->node.pTargets, pTargets); - } - - return (SLogicNode*)pAgg; -} - -static SNodeList* createColumnByProjections(SPlanContext* pCxt, SNodeList* pExprs) { - SNodeList* pList = nodesMakeList(); - CHECK_ALLOC(pList, NULL); - SNode* pNode; - FOREACH(pNode, pExprs) { - SExprNode* pExpr = (SExprNode*)pNode; - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - goto error; - } - pCol->node.resType = pExpr->resType; - strcpy(pCol->colName, pExpr->aliasName); - if (TSDB_CODE_SUCCESS != nodesListAppend(pList, (SNode*)pCol)) { - goto error; - } - } - return pList; -error: - nodesDestroyList(pList); - return NULL; -} - -static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { - SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT); - CHECK_ALLOC(pProject, NULL); - pProject->node.id = pCxt->planNodeId++; - - pProject->pProjections = nodesCloneList(pSelect->pProjectionList); - - pProject->node.pTargets = createColumnByProjections(pCxt,pSelect->pProjectionList); - CHECK_ALLOC(pProject->node.pTargets, (SLogicNode*)pProject); - - return (SLogicNode*)pProject; -} - -static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { - SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable); - if (TSDB_CODE_SUCCESS == pCxt->errCode && NULL != pSelect->pWhere) { - pRoot->pConditions = nodesCloneNode(pSelect->pWhere); - CHECK_ALLOC(pRoot->pConditions, pRoot); - } - if (TSDB_CODE_SUCCESS == pCxt->errCode) { - pRoot = pushLogicNode(pCxt, pRoot, createAggLogicNode(pCxt, pSelect)); - } - if (TSDB_CODE_SUCCESS == pCxt->errCode) { - pRoot = pushLogicNode(pCxt, pRoot, createProjectLogicNode(pCxt, pSelect)); - } - return pRoot; -} - -static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) { - switch (nodeType(pStmt)) { - case QUERY_NODE_SELECT_STMT: - return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt); - default: - break; - } -} - -int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) { - SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1 }; - SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode); - if (TSDB_CODE_SUCCESS != cxt.errCode) { - nodesDestroyNode((SNode*)pRoot); - return cxt.errCode; - } - *pLogicNode = pRoot; - return TSDB_CODE_SUCCESS; -} - -int32_t optimize(SLogicNode* pLogicNode) { - // todo - return TSDB_CODE_SUCCESS; -} - -typedef struct SSubLogicPlan { - SNode* pRoot; // SLogicNode - bool haveSuperTable; - bool haveSystemTable; -} SSubLogicPlan; - -int32_t splitLogicPlan(SSubLogicPlan* pLogicPlan) { - // todo - return TSDB_CODE_SUCCESS; -} - -typedef struct SSlotIndex { - int16_t dataBlockId; - int16_t slotId; -} SSlotIndex; - -typedef struct SPhysiPlanContext { - int32_t errCode; - int16_t nextDataBlockId; - SArray* pLocationHelper; -} SPhysiPlanContext; - -static int32_t getSlotKey(SNode* pNode, char* pKey) { - if (QUERY_NODE_COLUMN == nodeType(pNode)) { - SColumnNode* pCol = (SColumnNode*)pNode; - if ('\0' == pCol->tableAlias[0]) { - return sprintf(pKey, "%s", pCol->colName); - } - return sprintf(pKey, "%s.%s", pCol->tableAlias, pCol->colName); - } - return sprintf(pKey, "%s", ((SExprNode*)pNode)->aliasName); -} - -static SNode* createSlotDesc(SPhysiPlanContext* pCxt, const SNode* pNode, int16_t slotId) { - SSlotDescNode* pSlot = (SSlotDescNode*)nodesMakeNode(QUERY_NODE_SLOT_DESC); - CHECK_ALLOC(pSlot, NULL); - pSlot->slotId = slotId; - pSlot->dataType = ((SExprNode*)pNode)->resType; - pSlot->reserve = false; - pSlot->output = false; - return (SNode*)pSlot; -} - -static SNode* createTarget(SNode* pNode, int16_t dataBlockId, int16_t slotId) { - STargetNode* pTarget = (STargetNode*)nodesMakeNode(QUERY_NODE_TARGET); - if (NULL == pTarget) { - return NULL; - } - pTarget->dataBlockId = dataBlockId; - pTarget->slotId = slotId; - pTarget->pExpr = pNode; - return (SNode*)pTarget; -} - -static int32_t addDataBlockDesc(SPhysiPlanContext* pCxt, SNodeList* pList, SDataBlockDescNode* pDataBlockDesc) { - SHashObj* pHash = NULL; - if (NULL == pDataBlockDesc->pSlots) { - pDataBlockDesc->pSlots = nodesMakeList(); - CHECK_ALLOC(pDataBlockDesc->pSlots, TSDB_CODE_OUT_OF_MEMORY); - - pHash = taosHashInit(LIST_LENGTH(pList), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); - CHECK_ALLOC(pHash, TSDB_CODE_OUT_OF_MEMORY); - if (NULL == taosArrayInsert(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId, &pHash)) { - taosHashCleanup(pHash); - return TSDB_CODE_OUT_OF_MEMORY; - } - } else { - pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId); - } - - SNode* pNode = NULL; - int16_t slotId = taosHashGetSize(pHash); - FOREACH(pNode, pList) { - SNode* pSlot = createSlotDesc(pCxt, pNode, slotId); - CHECK_ALLOC(pSlot, TSDB_CODE_OUT_OF_MEMORY); - if (TSDB_CODE_SUCCESS != nodesListAppend(pDataBlockDesc->pSlots, (SNode*)pSlot)) { - nodesDestroyNode(pSlot); - return TSDB_CODE_OUT_OF_MEMORY; - } - - SSlotIndex index = { .dataBlockId = pDataBlockDesc->dataBlockId, .slotId = slotId }; - char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; - int32_t len = getSlotKey(pNode, name); - CHECK_CODE(taosHashPut(pHash, name, len, &index, sizeof(SSlotIndex)), TSDB_CODE_OUT_OF_MEMORY); - - SNode* pTarget = createTarget(pNode, pDataBlockDesc->dataBlockId, slotId); - CHECK_ALLOC(pTarget, TSDB_CODE_OUT_OF_MEMORY); - REPLACE_NODE(pTarget); - - ++slotId; - } - return TSDB_CODE_SUCCESS; -} - -typedef struct SSetSlotIdCxt { - int32_t errCode; - SHashObj* pLeftHash; - SHashObj* pRightHash; -} SSetSlotIdCxt; - -static EDealRes doSetSlotId(SNode* pNode, void* pContext) { - if (QUERY_NODE_COLUMN == nodeType(pNode) && 0 != strcmp(((SColumnNode*)pNode)->colName, "*")) { - SSetSlotIdCxt* pCxt = (SSetSlotIdCxt*)pContext; - char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; - int32_t len = getSlotKey(pNode, name); - SSlotIndex* pIndex = taosHashGet(pCxt->pLeftHash, name, len); - if (NULL == pIndex) { - pIndex = taosHashGet(pCxt->pRightHash, name, len); - } - // pIndex is definitely not NULL, otherwise it is a bug - ((SColumnNode*)pNode)->dataBlockId = pIndex->dataBlockId; - ((SColumnNode*)pNode)->slotId = pIndex->slotId; - CHECK_ALLOC(pNode, DEAL_RES_ERROR); - return DEAL_RES_IGNORE_CHILD; - } - return DEAL_RES_CONTINUE; -} - -static SNode* setNodeSlotId(SPhysiPlanContext* pCxt, int16_t leftDataBlockId, int16_t rightDataBlockId, SNode* pNode) { - SNode* pRes = nodesCloneNode(pNode); - CHECK_ALLOC(pRes, NULL); - SSetSlotIdCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pLeftHash = taosArrayGetP(pCxt->pLocationHelper, leftDataBlockId), - .pRightHash = (rightDataBlockId < 0 ? NULL : taosArrayGetP(pCxt->pLocationHelper, rightDataBlockId)) }; - nodesWalkNode(pRes, doSetSlotId, &cxt); - if (TSDB_CODE_SUCCESS != cxt.errCode) { - nodesDestroyNode(pRes); - return NULL; - } - return pRes; -} - -static SNodeList* setListSlotId(SPhysiPlanContext* pCxt, int16_t leftDataBlockId, int16_t rightDataBlockId, SNodeList* pList) { - SNodeList* pRes = nodesCloneList(pList); - CHECK_ALLOC(pRes, NULL); - SSetSlotIdCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pLeftHash = taosArrayGetP(pCxt->pLocationHelper, leftDataBlockId), - .pRightHash = (rightDataBlockId < 0 ? NULL : taosArrayGetP(pCxt->pLocationHelper, rightDataBlockId)) }; - nodesWalkList(pRes, doSetSlotId, &cxt); - if (TSDB_CODE_SUCCESS != cxt.errCode) { - nodesDestroyList(pRes); - return NULL; - } - return pRes; -} - -static SPhysiNode* makePhysiNode(SPhysiPlanContext* pCxt, ENodeType type) { - SPhysiNode* pPhysiNode = (SPhysiNode*)nodesMakeNode(type); - if (NULL == pPhysiNode) { - return NULL; - } - pPhysiNode->outputDataBlockDesc.dataBlockId = pCxt->nextDataBlockId++; - pPhysiNode->outputDataBlockDesc.type = QUERY_NODE_DATABLOCK_DESC; - return pPhysiNode; -} - -static int32_t setConditionsSlotId(SPhysiPlanContext* pCxt, const SLogicNode* pLogicNode, SPhysiNode* pPhysiNode) { - if (NULL != pLogicNode->pConditions) { - pPhysiNode->pConditions = setNodeSlotId(pCxt, pPhysiNode->outputDataBlockDesc.dataBlockId, -1, pLogicNode->pConditions); - CHECK_ALLOC(pPhysiNode->pConditions, TSDB_CODE_OUT_OF_MEMORY); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t setSlotOutput(SPhysiPlanContext* pCxt, SNodeList* pTargets, SDataBlockDescNode* pDataBlockDesc) { - SHashObj* pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId); - char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; - SNode* pNode; - FOREACH(pNode, pTargets) { - int32_t len = getSlotKey(pNode, name); - SSlotIndex* pIndex = taosHashGet(pHash, name, len); - ((SSlotDescNode*)nodesListGetNode(pDataBlockDesc->pSlots, pIndex->slotId))->output = true; - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t initScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode, SScanPhysiNode* pScanPhysiNode) { - if (NULL != pScanLogicNode->pScanCols) { - pScanPhysiNode->pScanCols = nodesCloneList(pScanLogicNode->pScanCols); - CHECK_ALLOC(pScanPhysiNode->pScanCols, TSDB_CODE_OUT_OF_MEMORY); - } - // Data block describe also needs to be set without scanning column, such as SELECT COUNT(*) FROM t - CHECK_CODE(addDataBlockDesc(pCxt, pScanPhysiNode->pScanCols, &pScanPhysiNode->node.outputDataBlockDesc), TSDB_CODE_OUT_OF_MEMORY); - - CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pScanLogicNode, (SPhysiNode*)pScanPhysiNode), TSDB_CODE_OUT_OF_MEMORY); - - CHECK_CODE(setSlotOutput(pCxt, pScanLogicNode->node.pTargets, &pScanPhysiNode->node.outputDataBlockDesc), TSDB_CODE_OUT_OF_MEMORY); - - pScanPhysiNode->uid = pScanLogicNode->pMeta->uid; - pScanPhysiNode->tableType = pScanLogicNode->pMeta->tableType; - pScanPhysiNode->order = TSDB_ORDER_ASC; - pScanPhysiNode->count = 1; - pScanPhysiNode->reverse = 0; - - return TSDB_CODE_SUCCESS; -} - -static SPhysiNode* createTagScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) { - STagScanPhysiNode* pTagScan = (STagScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN); - CHECK_ALLOC(pTagScan, NULL); - CHECK_CODE(initScanPhysiNode(pCxt, pScanLogicNode, (SScanPhysiNode*)pTagScan), (SPhysiNode*)pTagScan); - return (SPhysiNode*)pTagScan; -} - -static SPhysiNode* createTableScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) { - STableScanPhysiNode* pTableScan = (STableScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN); - CHECK_ALLOC(pTableScan, NULL); - CHECK_CODE(initScanPhysiNode(pCxt, pScanLogicNode, (SScanPhysiNode*)pTableScan), (SPhysiNode*)pTableScan); - pTableScan->scanFlag = pScanLogicNode->scanFlag; - pTableScan->scanRange = pScanLogicNode->scanRange; - return (SPhysiNode*)pTableScan; -} - -static SPhysiNode* createScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) { - switch (pScanLogicNode->scanType) { - case SCAN_TYPE_TAG: - return createTagScanPhysiNode(pCxt, pScanLogicNode); - case SCAN_TYPE_TABLE: - return createTableScanPhysiNode(pCxt, pScanLogicNode); - case SCAN_TYPE_STABLE: - case SCAN_TYPE_STREAM: - break; - default: - break; - } - return NULL; -} - -static SNodeList* createJoinOutputCols(SPhysiPlanContext* pCxt, SDataBlockDescNode* pLeftDesc, SDataBlockDescNode* pRightDesc) { - SNodeList* pCols = nodesMakeList(); - CHECK_ALLOC(pCols, NULL); - SNode* pNode; - FOREACH(pNode, pLeftDesc->pSlots) { - SSlotDescNode* pSlot = (SSlotDescNode*)pNode; - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - goto error; - } - pCol->node.resType = pSlot->dataType; - pCol->dataBlockId = pLeftDesc->dataBlockId; - pCol->slotId = pSlot->slotId; - pCol->colId = -1; - if (TSDB_CODE_SUCCESS != nodesListAppend(pCols, (SNode*)pCol)) { - goto error; - } - } - FOREACH(pNode, pRightDesc->pSlots) { - SSlotDescNode* pSlot = (SSlotDescNode*)pNode; - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - goto error; - } - pCol->node.resType = pSlot->dataType; - pCol->dataBlockId = pRightDesc->dataBlockId; - pCol->slotId = pSlot->slotId; - pCol->colId = -1; - if (TSDB_CODE_SUCCESS != nodesListAppend(pCols, (SNode*)pCol)) { - goto error; - } - } - return pCols; -error: - nodesDestroyList(pCols); - return NULL; -} - -static SPhysiNode* createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SJoinLogicNode* pJoinLogicNode) { - SJoinPhysiNode* pJoin = (SJoinPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_JOIN); - CHECK_ALLOC(pJoin, NULL); - - SDataBlockDescNode* pLeftDesc = &((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc; - SDataBlockDescNode* pRightDesc = &((SPhysiNode*)nodesListGetNode(pChildren, 1))->outputDataBlockDesc; - pJoin->pOnConditions = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pOnConditions); - CHECK_ALLOC(pJoin->pOnConditions, (SPhysiNode*)pJoin); - - pJoin->pTargets = createJoinOutputCols(pCxt, pLeftDesc, pRightDesc); - CHECK_ALLOC(pJoin->pTargets, (SPhysiNode*)pJoin); - CHECK_CODE(addDataBlockDesc(pCxt, pJoin->pTargets, &pJoin->node.outputDataBlockDesc), (SPhysiNode*)pJoin); - - CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pJoinLogicNode, (SPhysiNode*)pJoin), (SPhysiNode*)pJoin); - - CHECK_CODE(setSlotOutput(pCxt, pJoinLogicNode->node.pTargets, &pJoin->node.outputDataBlockDesc), (SPhysiNode*)pJoin); - - return (SPhysiNode*)pJoin; -} - -typedef struct SRewritePrecalcExprsCxt { - int32_t errCode; - int32_t planNodeId; - int32_t rewriteId; - SNodeList* pPrecalcExprs; -} SRewritePrecalcExprsCxt; - -static EDealRes collectAndRewrite(SRewritePrecalcExprsCxt* pCxt, SNode** pNode) { - SNode* pExpr = nodesCloneNode(*pNode); - CHECK_ALLOC(pExpr, DEAL_RES_ERROR); - if (nodesListAppend(pCxt->pPrecalcExprs, pExpr)) { - nodesDestroyNode(pExpr); - return DEAL_RES_ERROR; - } - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - nodesDestroyNode(pExpr); - return DEAL_RES_ERROR; - } - SExprNode* pRewrittenExpr = (SExprNode*)pExpr; - pCol->node.resType = pRewrittenExpr->resType; - if ('\0' != pRewrittenExpr->aliasName[0]) { - strcpy(pCol->colName, pRewrittenExpr->aliasName); - } else { - snprintf(pRewrittenExpr->aliasName, sizeof(pRewrittenExpr->aliasName), "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId); - strcpy(pCol->colName, pRewrittenExpr->aliasName); - } - nodesDestroyNode(*pNode); - *pNode = (SNode*)pCol; - return DEAL_RES_IGNORE_CHILD; -} - -static EDealRes doRewritePrecalcExprs(SNode** pNode, void* pContext) { - SRewritePrecalcExprsCxt* pCxt = (SRewritePrecalcExprsCxt*)pContext; - switch (nodeType(*pNode)) { - case QUERY_NODE_OPERATOR: - case QUERY_NODE_LOGIC_CONDITION: { - return collectAndRewrite(pContext, pNode); - } - case QUERY_NODE_FUNCTION: { - if (!fmIsAggFunc(((SFunctionNode*)(*pNode))->funcId)) { - return collectAndRewrite(pContext, pNode); - } - } - default: - break; - } - return DEAL_RES_CONTINUE; -} - -static int32_t rewritePrecalcExprs(SPhysiPlanContext* pCxt, SNodeList* pList, SNodeList** pPrecalcExprs, SNodeList** pRewrittenList) { - if (NULL == pList) { - return TSDB_CODE_SUCCESS; - } - - if (NULL == *pPrecalcExprs) { - *pPrecalcExprs = nodesMakeList(); - CHECK_ALLOC(*pPrecalcExprs, TSDB_CODE_OUT_OF_MEMORY); - } - if (NULL == *pRewrittenList) { - *pRewrittenList = nodesMakeList(); - CHECK_ALLOC(*pRewrittenList, TSDB_CODE_OUT_OF_MEMORY); - } - SNode* pNode = NULL; - FOREACH(pNode, pList) { - SNode* pNew = NULL; - if (QUERY_NODE_GROUPING_SET == nodeType(pNode)) { - pNew = nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pNode)->pParameterList, 0)); - } else { - pNew = nodesCloneNode(pNode); - } - CHECK_ALLOC(pNew, TSDB_CODE_OUT_OF_MEMORY); - CHECK_CODE(nodesListAppend(*pRewrittenList, pNew), TSDB_CODE_OUT_OF_MEMORY); - } - SRewritePrecalcExprsCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pPrecalcExprs = *pPrecalcExprs }; - nodesRewriteList(*pRewrittenList, doRewritePrecalcExprs, &cxt); - if (0 == LIST_LENGTH(cxt.pPrecalcExprs)) { - nodesDestroyList(cxt.pPrecalcExprs); - *pPrecalcExprs = NULL; - } - return cxt.errCode; -} - -static SPhysiNode* createAggPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SAggLogicNode* pAggLogicNode) { - SAggPhysiNode* pAgg = (SAggPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_AGG); - CHECK_ALLOC(pAgg, NULL); - - SNodeList* pPrecalcExprs = NULL; - SNodeList* pGroupKeys = NULL; - SNodeList* pAggFuncs = NULL; - CHECK_CODE(rewritePrecalcExprs(pCxt, pAggLogicNode->pGroupKeys, &pPrecalcExprs, &pGroupKeys), (SPhysiNode*)pAgg); - CHECK_CODE(rewritePrecalcExprs(pCxt, pAggLogicNode->pAggFuncs, &pPrecalcExprs, &pAggFuncs), (SPhysiNode*)pAgg); - - SDataBlockDescNode* pChildTupe = &(((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc); - // push down expression to outputDataBlockDesc of child node - if (NULL != pPrecalcExprs) { - pAgg->pExprs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs); - CHECK_ALLOC(pAgg->pExprs, (SPhysiNode*)pAgg); - CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pExprs, pChildTupe), (SPhysiNode*)pAgg); - } - - if (NULL != pGroupKeys) { - pAgg->pGroupKeys = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pGroupKeys); - CHECK_ALLOC(pAgg->pGroupKeys, (SPhysiNode*)pAgg); - CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pGroupKeys, &pAgg->node.outputDataBlockDesc), (SPhysiNode*)pAgg); - } - - if (NULL != pAggFuncs) { - pAgg->pAggFuncs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pAggFuncs); - CHECK_ALLOC(pAgg->pAggFuncs, (SPhysiNode*)pAgg); - CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pAggFuncs, &pAgg->node.outputDataBlockDesc), (SPhysiNode*)pAgg); - } - - CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pAggLogicNode, (SPhysiNode*)pAgg), (SPhysiNode*)pAgg); - - CHECK_CODE(setSlotOutput(pCxt, pAggLogicNode->node.pTargets, &pAgg->node.outputDataBlockDesc), (SPhysiNode*)pAgg); - - return (SPhysiNode*)pAgg; -} - -static SPhysiNode* createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SProjectLogicNode* pProjectLogicNode) { - SProjectPhysiNode* pProject = (SProjectPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_PROJECT); - CHECK_ALLOC(pProject, NULL); - - pProject->pProjections = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc.dataBlockId, -1, pProjectLogicNode->pProjections); - CHECK_ALLOC(pProject->pProjections, (SPhysiNode*)pProject); - CHECK_CODE(addDataBlockDesc(pCxt, pProject->pProjections, &pProject->node.outputDataBlockDesc), (SPhysiNode*)pProject); - - CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pProjectLogicNode, (SPhysiNode*)pProject), (SPhysiNode*)pProject); - - return (SPhysiNode*)pProject; -} - -static SPhysiNode* createPhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicPlan) { - SNodeList* pChildren = nodesMakeList(); - CHECK_ALLOC(pChildren, NULL); - - SNode* pLogicChild; - FOREACH(pLogicChild, pLogicPlan->pChildren) { - SNode* pChildPhyNode = (SNode*)createPhysiNode(pCxt, (SLogicNode*)pLogicChild); - if (TSDB_CODE_SUCCESS != nodesListAppend(pChildren, pChildPhyNode)) { - pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; - nodesDestroyList(pChildren); - return NULL; - } - } - - SPhysiNode* pPhyNode = NULL; - switch (nodeType(pLogicPlan)) { - case QUERY_NODE_LOGIC_PLAN_SCAN: - pPhyNode = createScanPhysiNode(pCxt, (SScanLogicNode*)pLogicPlan); - break; - case QUERY_NODE_LOGIC_PLAN_JOIN: - pPhyNode = createJoinPhysiNode(pCxt, pChildren, (SJoinLogicNode*)pLogicPlan); - break; - case QUERY_NODE_LOGIC_PLAN_AGG: - pPhyNode = createAggPhysiNode(pCxt, pChildren, (SAggLogicNode*)pLogicPlan); - break; - case QUERY_NODE_LOGIC_PLAN_PROJECT: - pPhyNode = createProjectPhysiNode(pCxt, pChildren, (SProjectLogicNode*)pLogicPlan); - break; - default: - break; - } - - pPhyNode->pChildren = pChildren; - SNode* pChild; - FOREACH(pChild, pPhyNode->pChildren) { - ((SPhysiNode*)pChild)->pParent = pPhyNode; - } - - return pPhyNode; -} - -int32_t createPhysiPlan(SLogicNode* pLogicNode, SPhysiNode** pPhyNode) { - SPhysiPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .nextDataBlockId = 0, .pLocationHelper = taosArrayInit(32, POINTER_BYTES) }; - if (NULL == cxt.pLocationHelper) { - return TSDB_CODE_OUT_OF_MEMORY; - } - *pPhyNode = createPhysiNode(&cxt, pLogicNode); - return cxt.errCode; -} - -int32_t buildPhysiPlan(SLogicNode* pLogicNode, SPhysiNode** pPhyNode) { - // split - // scale out - // maping - // create - return TSDB_CODE_SUCCESS; -} diff --git a/source/libs/planner/src/plannerUtil.c b/source/libs/planner/src/plannerUtil.c deleted file mode 100644 index b692fc67c2e04e5eaac600eca8c3fc8168593a39..0000000000000000000000000000000000000000 --- a/source/libs/planner/src/plannerUtil.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "tvariant.h" -#include "plannerUtil.h" - - - - diff --git a/source/libs/planner/test/phyPlanTests.cpp b/source/libs/planner/test/phyPlanTests.cpp deleted file mode 100644 index f4bdf57572cbd97403d66146fb064b3a35179257..0000000000000000000000000000000000000000 --- a/source/libs/planner/test/phyPlanTests.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include - -#include "plannerInt.h" -#include "mockCatalogService.h" - -using namespace std; -using namespace testing; - -void* myCalloc(size_t nmemb, size_t size) { - if (void* p = calloc(nmemb, size)) { - return p; - } - throw bad_alloc(); -} - -class PhyPlanTest : public Test { -protected: - void pushAgg(int32_t aggOp) { - unique_ptr agg((SQueryPlanNode*)myCalloc(1, sizeof(SQueryPlanNode))); - agg->info.type = aggOp; - agg->pExpr = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); - unique_ptr expr((SExprInfo*)myCalloc(1, sizeof(SExprInfo))); - expr->base.resSchema.type = TSDB_DATA_TYPE_INT; - expr->base.resSchema.bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes; - expr->pExpr = (tExprNode*)myCalloc(1, sizeof(tExprNode)); - expr->pExpr->nodeType = TEXPR_FUNCTION_NODE; - strcpy(expr->pExpr->_function.functionName, "Count"); - SExprInfo* item = expr.release(); - taosArrayPush(agg->pExpr, &item); - pushNode(agg.release()); - } - - void pushScan(const string& db, const string& table, int32_t scanOp) { - shared_ptr meta = mockCatalogService->getTableMeta(db, table); - EXPECT_TRUE(meta); - unique_ptr scan((SQueryPlanNode*)myCalloc(1, sizeof(SQueryPlanNode))); - scan->info.type = scanOp; - scan->numOfCols = meta->schema->tableInfo.numOfColumns; - scan->pSchema = (SSchema*)myCalloc(1, sizeof(SSchema) * scan->numOfCols); - memcpy(scan->pSchema, meta->schema->schema, sizeof(SSchema) * scan->numOfCols); - //todo 'pExpr' 'numOfExpr' - scan->pExtInfo = createScanExtInfo(meta); - pushNode(scan.release()); - } - - int32_t run() { - SQueryDag* dag = nullptr; - uint64_t requestId = 20; - int32_t code = createDag(logicPlan_.get(), nullptr, &dag, NULL, requestId); - dag_.reset(dag); - return code; - } - - int32_t run(const string& db, const string& sql) { - SParseContext cxt; - buildParseContext(db, sql, &cxt); - SQueryNode* query; - int32_t code = qParseQuerySql(&cxt, &query); - if (TSDB_CODE_SUCCESS != code) { - cout << "error no:" << code << ", msg:" << cxt.pMsg << endl; - return code; - } - SQueryDag* dag = nullptr; - uint64_t requestId = 20; - SSchema *schema = NULL; - int32_t numOfOutput = 0; - - code = qCreateQueryDag(query, &dag, &schema, &numOfOutput, nullptr, requestId); - dag_.reset(dag); - return code; - } - - void explain() { - size_t level = taosArrayGetSize(dag_->pSubplans); - for (size_t i = 0; i < level; ++i) { - std::cout << "level " << i << ":" << std::endl; - const SArray* subplans = (const SArray*)taosArrayGetP(dag_->pSubplans, i); - size_t num = taosArrayGetSize(subplans); - for (size_t j = 0; j < num; ++j) { - std::cout << "no " << j << ":" << std::endl; - int32_t len = 0; - char* str = nullptr; - ASSERT_EQ(TSDB_CODE_SUCCESS, qSubPlanToString((const SSubplan*)taosArrayGetP(subplans, j), &str, &len)); - std::cout << "len:" << len << std::endl; - std::cout << str << std::endl; - free(str); - } - } - } - - SQueryDag* result() { - return dag_.get(); - } - -private: - void pushNode(SQueryPlanNode* node) { - if (logicPlan_) { - node->pChildren = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); - SQueryPlanNode* child = logicPlan_.release(); - taosArrayPush(node->pChildren, &child); - } - logicPlan_.reset(node); - } - - void copySchemaMeta(STableMeta** dst, const STableMeta* src) { - int32_t size = sizeof(STableMeta) + sizeof(SSchema) * (src->tableInfo.numOfTags + src->tableInfo.numOfColumns); - *dst = (STableMeta*)myCalloc(1, size); - memcpy(*dst, src, size); - } - - void copyStorageMeta(SVgroupsInfo** dst, const std::vector& src) { - *dst = (SVgroupsInfo*)myCalloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo) * src.size()); - (*dst)->numOfVgroups = src.size(); - for (int32_t i = 0; i < src.size(); ++i) { - (*dst)->vgroups[i] = src[i]; - } - } - - SQueryTableInfo* createScanExtInfo(shared_ptr& meta) { - SQueryTableInfo* info = (SQueryTableInfo*)myCalloc(1, sizeof(SQueryTableInfo)); - info->pMeta = (STableMetaInfo*)myCalloc(1, sizeof(STableMetaInfo)); - copySchemaMeta(&info->pMeta->pTableMeta, meta->schema.get()); - copyStorageMeta(&info->pMeta->vgroupList, meta->vgs); - return info; - } - - void buildParseContext(const string& db, const string& sql, SParseContext* pCxt) { - static string _db; - static string _sql; - static const int32_t _msgMaxLen = 4096; - static char _msg[_msgMaxLen]; - - _db = db; - _sql = sql; - memset(_msg, 0, _msgMaxLen); - - pCxt->acctId = 1; - pCxt->db = _db.c_str(); - pCxt->requestId = 1; - pCxt->pSql = _sql.c_str(); - pCxt->sqlLen = _sql.length(); - pCxt->pMsg = _msg; - pCxt->msgLen = _msgMaxLen; - } - - shared_ptr meta_; - unique_ptr logicPlan_; - unique_ptr dag_; -}; - -// select * from table -TEST_F(PhyPlanTest, tableScanTest) { - pushScan("test", "t1", QNODE_TABLESCAN); - ASSERT_EQ(run(), TSDB_CODE_SUCCESS); - explain(); - SQueryDag* dag = result(); - // todo check -} - -TEST_F(PhyPlanTest, serializeTest) { - pushScan("test", "t1", QNODE_TABLESCAN); - ASSERT_EQ(run(), TSDB_CODE_SUCCESS); - SQueryDag* dag = result(); - cout << qDagToString(dag) << endl; -} - -// select * from supertable -TEST_F(PhyPlanTest, superTableScanTest) { - pushScan("test", "st1", QNODE_TABLESCAN); - ASSERT_EQ(run(), TSDB_CODE_SUCCESS); - explain(); - SQueryDag* dag = result(); - // todo check -} - -// select count(*) from table -TEST_F(PhyPlanTest, simpleAggTest) { - pushScan("test", "t1", QNODE_TABLESCAN); - pushAgg(QNODE_AGGREGATE); - ASSERT_EQ(run(), TSDB_CODE_SUCCESS); - explain(); - SQueryDag* dag = result(); - // todo check -} - -// insert into t values(...) -TEST_F(PhyPlanTest, insertTest) { - ASSERT_EQ(run("test", "insert into t1 values (now, 1, \"beijing\")"), TSDB_CODE_SUCCESS); - explain(); - SQueryDag* dag = result(); - // todo check -} diff --git a/source/libs/planner/test/newPlannerTest.cpp b/source/libs/planner/test/plannerTest.cpp similarity index 71% rename from source/libs/planner/test/newPlannerTest.cpp rename to source/libs/planner/test/plannerTest.cpp index e7c0c2483005c0fb8485526c4ad9621841b1f6c9..8baa64d8fb78b92bbee314442ccf2f0b30cc2213 100644 --- a/source/libs/planner/test/newPlannerTest.cpp +++ b/source/libs/planner/test/plannerTest.cpp @@ -17,13 +17,13 @@ #include -#include "plannerImpl.h" -#include "newParser.h" +#include "parser.h" +#include "planInt.h" using namespace std; using namespace testing; -class NewPlannerTest : public Test { +class PlannerTest : public Test { protected: enum TestTarget { TEST_LOGIC_PLAN, @@ -46,17 +46,18 @@ protected: } bool run(TestTarget target = TEST_PHYSICAL_PLAN) { - int32_t code = parser(&cxt_, &query_); + int32_t code = qParseQuerySql(&cxt_, &query_); if (code != TSDB_CODE_SUCCESS) { cout << "sql:[" << cxt_.pSql << "] parser code:" << code << ", strerror:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl; return false; } - const string syntaxTreeStr = toString(query_.pRoot, false); + const string syntaxTreeStr = toString(query_->pRoot, false); SLogicNode* pLogicPlan = nullptr; - code = createLogicPlan(query_.pRoot, &pLogicPlan); + SPlanContext cxt = { .queryId = 1, .acctId = 0, .pAstRoot = query_->pRoot }; + code = createLogicPlan(&cxt, &pLogicPlan); if (code != TSDB_CODE_SUCCESS) { cout << "sql:[" << cxt_.pSql << "] logic plan code:" << code << ", strerror:" << tstrerror(code) << endl; return false; @@ -69,14 +70,22 @@ protected: cout << toString((const SNode*)pLogicPlan, false) << endl; if (TEST_PHYSICAL_PLAN == target) { - SPhysiNode* pPhyPlan = nullptr; - code = createPhysiPlan(pLogicPlan, &pPhyPlan); + SQueryPlan* pPlan = nullptr; + code = createPhysiPlan(&cxt, pLogicPlan, &pPlan, NULL); if (code != TSDB_CODE_SUCCESS) { cout << "sql:[" << cxt_.pSql << "] physical plan code:" << code << ", strerror:" << tstrerror(code) << endl; return false; } cout << "unformatted physical plan : " << endl; - cout << toString((const SNode*)pPhyPlan, false) << endl; + cout << toString((const SNode*)pPlan, false) << endl; + SNode* pNode; + FOREACH(pNode, pPlan->pSubplans) { + SNode* pSubplan; + FOREACH(pSubplan, ((SNodeListNode*)pNode)->pNodeList) { + cout << "unformatted physical subplan : " << endl; + cout << toString(pSubplan, false) << endl; + } + } } return true; @@ -100,6 +109,14 @@ private: cout << "sql:[" << cxt_.pSql << "] toString code:" << code << ", strerror:" << tstrerror(code) << endl; return string(); } + SNode* pNode; + code = nodesStringToNode(pStr, &pNode); + if (code != TSDB_CODE_SUCCESS) { + tfree(pStr); + cout << "sql:[" << cxt_.pSql << "] toObject code:" << code << ", strerror:" << tstrerror(code) << endl; + return string(); + } + nodesDestroyNode(pNode); string str(pStr); tfree(pStr); return str; @@ -110,17 +127,24 @@ private: char errMagBuf_[max_err_len]; string sqlBuf_; SParseContext cxt_; - SQuery query_; + SQuery* query_; }; -TEST_F(NewPlannerTest, simple) { +TEST_F(PlannerTest, simple) { setDatabase("root", "test"); bind("SELECT * FROM t1"); ASSERT_TRUE(run()); } -TEST_F(NewPlannerTest, groupBy) { +TEST_F(PlannerTest, stSimple) { + setDatabase("root", "test"); + + bind("SELECT * FROM st1"); + ASSERT_TRUE(run()); +} + +TEST_F(PlannerTest, groupBy) { setDatabase("root", "test"); bind("SELECT count(*) FROM t1"); @@ -136,9 +160,16 @@ TEST_F(NewPlannerTest, groupBy) { ASSERT_TRUE(run()); } -TEST_F(NewPlannerTest, subquery) { +TEST_F(PlannerTest, subquery) { setDatabase("root", "test"); bind("SELECT count(*) FROM (SELECT c1 + c3 a, c1 + count(*) b FROM t1 where c2 = 'abc' GROUP BY c1, c3) where a > 100 group by b"); ASSERT_TRUE(run()); } + +TEST_F(PlannerTest, interval) { + setDatabase("root", "test"); + + bind("SELECT count(*) FROM t1 interval(10s)"); + ASSERT_TRUE(run()); +} diff --git a/include/libs/parser/newParser.h b/source/libs/planner/test/plannerTestMain.cpp similarity index 58% rename from include/libs/parser/newParser.h rename to source/libs/planner/test/plannerTestMain.cpp index fd631087db0029599d1c4f3a500170ffc038cfab..36a46ab99eb1734320dae1e4d04b3ec8056725b5 100644 --- a/include/libs/parser/newParser.h +++ b/source/libs/planner/test/plannerTestMain.cpp @@ -13,31 +13,29 @@ * along with this program. If not, see . */ -#ifndef _TD_NEW_PARSER_H_ -#define _TD_NEW_PARSER_H_ +#include -#ifdef __cplusplus -extern "C" { -#endif +#include -#include "parser.h" +#include "mockCatalog.h" -typedef enum EStmtType { - STMT_TYPE_CMD = 1, - STMT_TYPE_QUERY -} EStmtType; +class PlannerEnv : public testing::Environment { +public: + virtual void SetUp() { + initMetaDataEnv(); + generateMetaData(); + } -typedef struct SQuery { - EStmtType stmtType; - SNode* pRoot; - int32_t numOfResCols; - SSchema* pResSchema; -} SQuery; + virtual void TearDown() { + destroyMetaDataEnv(); + } -int32_t parser(SParseContext* pParseCxt, SQuery* pQuery); + PlannerEnv() {} + virtual ~PlannerEnv() {} +}; -#ifdef __cplusplus +int main(int argc, char* argv[]) { + testing::AddGlobalTestEnvironment(new PlannerEnv()); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } -#endif - -#endif /*_TD_NEW_PARSER_H_*/ diff --git a/source/libs/planner/test/plannerTests.cpp b/source/libs/planner/test/plannerTests.cpp deleted file mode 100644 index 765651a31abc9c9fff80e1251c34769394cd1d47..0000000000000000000000000000000000000000 --- a/source/libs/planner/test/plannerTests.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include -#include - -#include "os.h" - -#include "taos.h" -#include "parser.h" -#include "mockCatalog.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wwrite-strings" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wsign-compare" - -class PlannerEnv : public testing::Environment { -public: - virtual void SetUp() { - initMetaDataEnv(); - generateMetaData(); - } - - virtual void TearDown() { - destroyMetaDataEnv(); - } - - PlannerEnv() {} - virtual ~PlannerEnv() {} -}; - -int main(int argc, char* argv[]) { - testing::AddGlobalTestEnvironment(new PlannerEnv()); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - -TEST(testCase, planner_test) { - char msg[128] = {0}; - const char* sql = "select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"; - - SQueryStmtInfo* pQueryInfo = nullptr; -// int32_t code = qParseQuerySql(sql, strlen(sql), &pQueryInfo, 0, msg, sizeof(msg)); -// ASSERT_EQ(code, 0); - -// SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.list), 0); -// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); -// ASSERT_EQ(code, 0); -// -// SMetaReq req = {0}; -// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); -// ASSERT_EQ(ret, 0); -// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); -// -// SQueryStmtInfo* pQueryInfo = createQueryInfo(); -// setTableMetaInfo(pQueryInfo, &req); -// -// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); -// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); -// ASSERT_EQ(ret, 0); -// -// SArray* pExprList = pQueryInfo->exprList; -// ASSERT_EQ(taosArrayGetSize(pExprList), 2); -// -// SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 1); -// ASSERT_EQ(p1->base.uid, 110); -// ASSERT_EQ(p1->base.numOfParams, 1); -// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); -// ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); -// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); -// ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); -// ASSERT_EQ(p1->base.interBytes, 16); -// -// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); -// ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_TOP); -// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); -// -// tExprNode* pParam = p1->pExpr->_node.pLeft; -// -// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); -// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE); -// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE); -// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE); -// -// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); -// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); -// -// destroyQueryInfo(pQueryInfo); -// qParserCleanupMetaRequestInfo(&req); -// destroySqlInfo(&info1); -} - -#pragma GCC diagnostic pop \ No newline at end of file diff --git a/source/libs/qcom/src/querymsg.c b/source/libs/qcom/src/querymsg.c index 2a52e01dc17d7a92b513834831eff6c72f055e0a..37e8b7302eb16de21a0813250ad68a559d1e8420 100644 --- a/source/libs/qcom/src/querymsg.c +++ b/source/libs/qcom/src/querymsg.c @@ -42,6 +42,7 @@ int32_t queryBuildUseDbOutput(SUseDbOutput *pOut, SUseDbRsp *usedbRsp) { for (int32_t i = 0; i < usedbRsp->vgNum; ++i) { SVgroupInfo *pVgInfo = taosArrayGet(usedbRsp->pVgroupInfos, i); + pOut->dbVgroup->numOfTable += pVgInfo->numOfTable; if (0 != taosHashPut(pOut->dbVgroup->vgHash, &pVgInfo->vgId, sizeof(int32_t), pVgInfo, sizeof(SVgroupInfo))) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } @@ -84,6 +85,7 @@ int32_t queryBuildUseDbMsg(void *input, char **msg, int32_t msgSize, int32_t *ms usedbReq.db[sizeof(usedbReq.db) - 1] = 0; usedbReq.vgVersion = pInput->vgVersion; usedbReq.dbId = pInput->dbId; + usedbReq.numOfTable = pInput->numOfTable; int32_t bufLen = tSerializeSUseDbReq(NULL, 0, &usedbReq); void *pBuf = rpcMallocCont(bufLen); @@ -95,6 +97,25 @@ int32_t queryBuildUseDbMsg(void *input, char **msg, int32_t msgSize, int32_t *ms return TSDB_CODE_SUCCESS; } +int32_t queryBuildQnodeListMsg(void *input, char **msg, int32_t msgSize, int32_t *msgLen) { + if (NULL == msg || NULL == msgLen) { + return TSDB_CODE_TSC_INVALID_INPUT; + } + + SQnodeListReq qnodeListReq = {0}; + qnodeListReq.rowNum = -1; + + int32_t bufLen = tSerializeSQnodeListReq(NULL, 0, &qnodeListReq); + void *pBuf = rpcMallocCont(bufLen); + tSerializeSQnodeListReq(pBuf, bufLen, &qnodeListReq); + + *msg = pBuf; + *msgLen = bufLen; + + return TSDB_CODE_SUCCESS; +} + + int32_t queryProcessUseDBRsp(void *output, char *msg, int32_t msgSize) { SUseDbOutput *pOut = output; SUseDbRsp usedbRsp = {0}; @@ -247,21 +268,52 @@ int32_t queryProcessTableMetaRsp(void *output, char *msg, int32_t msgSize) { PROCESS_META_OVER: if (code != 0) { - qError("failed to process table meta rsp since %s", terrstr()); + qError("failed to process table meta rsp since %s", tstrerror(code)); } tFreeSTableMetaRsp(&metaRsp); return code; } + +int32_t queryProcessQnodeListRsp(void *output, char *msg, int32_t msgSize) { + SQnodeListRsp out = {0}; + int32_t code = -1; + + if (NULL == output || NULL == msg || msgSize <= 0) { + code = TSDB_CODE_TSC_INVALID_INPUT; + goto PROCESS_QLIST_OVER; + } + + if (tDeserializeSQnodeListRsp(msg, msgSize, &out) != 0) { + qError("invalid qnode list rsp msg, msgSize:%d", msgSize); + code = TSDB_CODE_INVALID_MSG; + goto PROCESS_QLIST_OVER; + } + +PROCESS_QLIST_OVER: + + if (code != 0) { + tFreeSQnodeListRsp(&out); + out.epSetList = NULL; + } + + *(SArray **)output = out.epSetList; + + return code; +} + + void initQueryModuleMsgHandle() { queryBuildMsg[TMSG_INDEX(TDMT_VND_TABLE_META)] = queryBuildTableMetaReqMsg; queryBuildMsg[TMSG_INDEX(TDMT_MND_TABLE_META)] = queryBuildTableMetaReqMsg; queryBuildMsg[TMSG_INDEX(TDMT_MND_USE_DB)] = queryBuildUseDbMsg; + queryBuildMsg[TMSG_INDEX(TDMT_MND_QNODE_LIST)] = queryBuildQnodeListMsg; queryProcessMsgRsp[TMSG_INDEX(TDMT_VND_TABLE_META)] = queryProcessTableMetaRsp; queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_TABLE_META)] = queryProcessTableMetaRsp; queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_USE_DB)] = queryProcessUseDBRsp; + queryProcessMsgRsp[TMSG_INDEX(TDMT_MND_QNODE_LIST)] = queryProcessQnodeListRsp; } #pragma GCC diagnostic pop diff --git a/source/libs/qcom/test/queryTest.cpp b/source/libs/qcom/test/queryTest.cpp index 9ca7442d55fd35d3db8ef084f237a49f4b90c82b..72ce0f7c37f814e0457699ad2c1e7b1d883bab6b 100644 --- a/source/libs/qcom/test/queryTest.cpp +++ b/source/libs/qcom/test/queryTest.cpp @@ -63,7 +63,7 @@ int main(int argc, char** argv) { TEST(testCase, async_task_test) { SParam* p = (SParam*)calloc(1, sizeof(SParam)); taosAsyncExec(testPrint, p, NULL); - usleep(5000); + taosMsleep(5); } TEST(testCase, many_async_task_test) { @@ -73,14 +73,14 @@ TEST(testCase, many_async_task_test) { taosAsyncExec(testPrint, p, NULL); } - usleep(10000); + taosMsleep(10); } TEST(testCase, error_in_async_test) { int32_t code = 0; SParam* p = (SParam*) calloc(1, sizeof(SParam)); taosAsyncExec(testPrintError, p, &code); - usleep(1000); + taosMsleep(1); printf("Error code:%d after asynchronously exec function\n", code); } diff --git a/source/libs/qworker/CMakeLists.txt b/source/libs/qworker/CMakeLists.txt index 9ada451c61be1cf2bbb8a48b624695cc1a0930ea..89700e89399221836496666083ea79447af88657 100644 --- a/source/libs/qworker/CMakeLists.txt +++ b/source/libs/qworker/CMakeLists.txt @@ -8,7 +8,7 @@ target_include_directories( ) target_link_libraries(qworker - PRIVATE os util transport planner qcom executor + PRIVATE os util transport nodes planner qcom executor ) if(${BUILD_TEST}) diff --git a/source/libs/qworker/inc/qworkerInt.h b/source/libs/qworker/inc/qworkerInt.h index de2940846c9e7c4efdcfaf7df3d9539a5fd44716..b5b8726a4c9115541c666ad0c66531700ae885d5 100644 --- a/source/libs/qworker/inc/qworkerInt.h +++ b/source/libs/qworker/inc/qworkerInt.h @@ -21,11 +21,14 @@ extern "C" { #endif #include "tlockfree.h" +#include "ttimer.h" #define QW_DEFAULT_SCHEDULER_NUMBER 10000 #define QW_DEFAULT_TASK_NUMBER 10000 #define QW_DEFAULT_SCH_TASK_NUMBER 10000 #define QW_DEFAULT_SHORT_RUN_TIMES 2 +#define QW_DEFAULT_HEARTBEAT_MSEC 3000 + enum { QW_PHASE_PRE_QUERY = 1, QW_PHASE_POST_QUERY, @@ -82,6 +85,11 @@ typedef struct SQWMsg { void *connection; } SQWMsg; +typedef struct SQWHbInfo { + SSchedulerHbRsp rsp; + void *connection; +} SQWHbInfo; + typedef struct SQWPhaseInput { int8_t taskStatus; int8_t taskType; @@ -95,6 +103,7 @@ typedef struct SQWPhaseOutput { typedef struct SQWTaskStatus { + int64_t refId; // job's refId int32_t code; int8_t status; } SQWTaskStatus; @@ -122,6 +131,8 @@ typedef struct SQWTaskCtx { typedef struct SQWSchStatus { int32_t lastAccessTs; // timestamp in second + uint64_t hbSeqId; + void *hbConnection; SRWLatch tasksLock; SHashObj *tasksHash; // key:queryId+taskId, value: SQWTaskStatus } SQWSchStatus; @@ -131,6 +142,8 @@ typedef struct SQWorkerMgmt { SQWorkerCfg cfg; int8_t nodeType; int32_t nodeId; + void *timer; + tmr_h hbTimer; SRWLatch schLock; //SRWLatch ctxLock; SHashObj *schHash; //key: schedulerId, value: SQWSchStatus @@ -140,8 +153,8 @@ typedef struct SQWorkerMgmt { sendReqToDnodeFp sendReqFp; } SQWorkerMgmt; -#define QW_FPARAMS_DEF SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId -#define QW_IDS() sId, qId, tId +#define QW_FPARAMS_DEF SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int64_t rId +#define QW_IDS() sId, qId, tId, rId #define QW_FPARAMS() mgmt, QW_IDS() #define QW_GET_EVENT_VALUE(ctx, event) atomic_load_8(&(ctx)->events[event]) diff --git a/source/libs/qworker/inc/qworkerMsg.h b/source/libs/qworker/inc/qworkerMsg.h index 51f55d238f33f3c109ec51e3df6f845f5f5aabac..ecb5dbd654d24292f818ee221105a1e9d79dd798 100644 --- a/source/libs/qworker/inc/qworkerMsg.h +++ b/source/libs/qworker/inc/qworkerMsg.h @@ -23,22 +23,24 @@ extern "C" { #include "qworkerInt.h" #include "dataSinkMgt.h" -int32_t qwProcessQuery(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg, int8_t taskType); -int32_t qwProcessCQuery(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg); -int32_t qwProcessReady(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg); -int32_t qwProcessFetch(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg); -int32_t qwProcessDrop(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg); +int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType); +int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg); +int32_t qwProcessReady(QW_FPARAMS_DEF, SQWMsg *qwMsg); +int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg); +int32_t qwProcessDrop(QW_FPARAMS_DEF, SQWMsg *qwMsg); +int32_t qwProcessHb(SQWorkerMgmt *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req); int32_t qwBuildAndSendDropRsp(void *connection, int32_t code); int32_t qwBuildAndSendCancelRsp(SRpcMsg *pMsg, int32_t code); int32_t qwBuildAndSendFetchRsp(void *connection, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code); void qwBuildFetchRsp(void *msg, SOutputData *input, int32_t len, bool qComplete); -int32_t qwBuildAndSendCQueryMsg(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, void *connection); -int32_t qwBuildAndSendSchSinkMsg(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, void *connection); +int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, void *connection); int32_t qwBuildAndSendReadyRsp(void *connection, int32_t code); int32_t qwBuildAndSendQueryRsp(void *connection, int32_t code); void qwFreeFetchRsp(void *msg); int32_t qwMallocFetchRsp(int32_t length, SRetrieveTableRsp **rsp); +int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, SSchedulerStatusRsp **rsp); +int32_t qwBuildAndSendHbRsp(SRpcMsg *pMsg, SSchedulerHbRsp *rsp, int32_t code); diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index 7a6fa4cfd78f1c9278931cfc300a85fc7f4a05f8..42890ab38a09753ae1607d2cc58cfdf9ec080f1f 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -106,7 +106,7 @@ int32_t qwSetTaskStatus(QW_FPARAMS_DEF, SQWTaskStatus *task, int8_t status) { } -int32_t qwAddSchedulerImpl(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sch) { +int32_t qwAddSchedulerImpl(SQWorkerMgmt *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch) { SQWSchStatus newSch = {0}; newSch.tasksHash = taosHashInit(mgmt->cfg.maxSchTaskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); if (NULL == newSch.tasksHash) { @@ -132,7 +132,7 @@ int32_t qwAddSchedulerImpl(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sch) { return TSDB_CODE_SUCCESS; } -int32_t qwAcquireSchedulerImpl(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sch, int32_t nOpt) { +int32_t qwAcquireSchedulerImpl(SQWorkerMgmt *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch, int32_t nOpt) { while (true) { QW_LOCK(rwType, &mgmt->schLock); *sch = taosHashGet(mgmt->schHash, &sId, sizeof(sId)); @@ -140,7 +140,7 @@ int32_t qwAcquireSchedulerImpl(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sc QW_UNLOCK(rwType, &mgmt->schLock); if (QW_NOT_EXIST_ADD == nOpt) { - QW_ERR_RET(qwAddSchedulerImpl(QW_FPARAMS(), rwType, sch)); + QW_ERR_RET(qwAddSchedulerImpl(mgmt, sId, rwType, sch)); nOpt = QW_NOT_EXIST_RET_ERR; @@ -148,7 +148,7 @@ int32_t qwAcquireSchedulerImpl(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sc } else if (QW_NOT_EXIST_RET_ERR == nOpt) { QW_RET(TSDB_CODE_QRY_SCH_NOT_EXIST); } else { - QW_TASK_ELOG("unknown notExistOpt:%d", nOpt); + QW_SCH_ELOG("unknown notExistOpt:%d", nOpt); QW_ERR_RET(TSDB_CODE_QRY_APP_ERROR); } } @@ -159,12 +159,12 @@ int32_t qwAcquireSchedulerImpl(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sc return TSDB_CODE_SUCCESS; } -int32_t qwAcquireAddScheduler(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sch) { - return qwAcquireSchedulerImpl(QW_FPARAMS(), rwType, sch, QW_NOT_EXIST_ADD); +int32_t qwAcquireAddScheduler(SQWorkerMgmt *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch) { + return qwAcquireSchedulerImpl(mgmt, sId, rwType, sch, QW_NOT_EXIST_ADD); } -int32_t qwAcquireScheduler(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus **sch) { - return qwAcquireSchedulerImpl(QW_FPARAMS(), rwType, sch, QW_NOT_EXIST_RET_ERR); +int32_t qwAcquireScheduler(SQWorkerMgmt *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch) { + return qwAcquireSchedulerImpl(mgmt, sId, rwType, sch, QW_NOT_EXIST_RET_ERR); } void qwReleaseScheduler(int32_t rwType, SQWorkerMgmt *mgmt) { @@ -196,6 +196,7 @@ int32_t qwAddTaskStatusImpl(QW_FPARAMS_DEF, SQWSchStatus *sch, int32_t rwType, i SQWTaskStatus ntask = {0}; ntask.status = status; + ntask.refId = rId; QW_LOCK(QW_WRITE, &sch->tasksLock); code = taosHashPut(sch->tasksHash, id, sizeof(id), &ntask, sizeof(ntask)); @@ -225,7 +226,7 @@ int32_t qwAddTaskStatusImpl(QW_FPARAMS_DEF, SQWSchStatus *sch, int32_t rwType, i int32_t qwAddTaskStatus(QW_FPARAMS_DEF, int32_t status) { SQWSchStatus *tsch = NULL; int32_t code = 0; - QW_ERR_RET(qwAcquireAddScheduler(QW_FPARAMS(), QW_READ, &tsch)); + QW_ERR_RET(qwAcquireAddScheduler(mgmt, sId, QW_READ, &tsch)); QW_ERR_JRET(qwAddTaskStatusImpl(QW_FPARAMS(), tsch, 0, status, NULL)); @@ -411,7 +412,7 @@ int32_t qwDropTaskStatus(QW_FPARAMS_DEF) { char id[sizeof(qId) + sizeof(tId)] = {0}; QW_SET_QTID(id, qId, tId); - if (qwAcquireScheduler(QW_FPARAMS(), QW_WRITE, &sch)) { + if (qwAcquireScheduler(mgmt, sId, QW_WRITE, &sch)) { QW_TASK_WLOG_E("scheduler does not exist"); return TSDB_CODE_SUCCESS; } @@ -443,7 +444,7 @@ int32_t qwUpdateTaskStatus(QW_FPARAMS_DEF, int8_t status) { SQWTaskStatus *task = NULL; int32_t code = 0; - QW_ERR_RET(qwAcquireScheduler(QW_FPARAMS(), QW_READ, &sch)); + QW_ERR_RET(qwAcquireScheduler(mgmt, sId, QW_READ, &sch)); QW_ERR_JRET(qwAcquireTaskStatus(QW_FPARAMS(), QW_READ, sch, &task)); QW_ERR_JRET(qwSetTaskStatus(QW_FPARAMS(), task, status)); @@ -494,7 +495,7 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryEnd) { ASSERT(pRes->info.rows > 0); - SInputData inputData = {.pData = pRes, .pTableRetrieveTsMap = NULL}; + SInputData inputData = {.pData = pRes}; code = dsPutDataBlock(sinkHandle, &inputData, &qcontinue); if (code) { QW_TASK_ELOG("dsPutDataBlock failed, code:%s", tstrerror(code)); @@ -521,6 +522,50 @@ _return: QW_RET(code); } +int32_t qwGenerateSchHbRsp(SQWorkerMgmt *mgmt, SQWSchStatus *sch, SQWHbInfo *hbInfo) { + int32_t taskNum = 0; + + QW_LOCK(QW_READ, &sch->tasksLock); + + taskNum = taosHashGetSize(sch->tasksHash); + + hbInfo->rsp.taskStatus = taosArrayInit(taskNum, sizeof(STaskStatus)); + if (NULL == hbInfo->rsp.taskStatus) { + QW_UNLOCK(QW_READ, &sch->tasksLock); + QW_ELOG("taosArrayInit taskStatus failed, num:%d", taskNum); + return TSDB_CODE_QRY_OUT_OF_MEMORY; + } + + hbInfo->connection = sch->hbConnection; + hbInfo->rsp.seqId = -1; + + void *key = NULL; + size_t keyLen = 0; + int32_t i = 0; + STaskStatus status = {0}; + + void *pIter = taosHashIterate(sch->tasksHash, NULL); + while (pIter) { + SQWTaskStatus *taskStatus = (SQWTaskStatus *)pIter; + key = taosHashGetKey(pIter, &keyLen); + + //TODO GET EXECUTOR API TO GET MORE INFO + + QW_GET_QTID(key, status.queryId, status.taskId); + status.status = taskStatus->status; + status.refId = taskStatus->refId; + + taosArrayPush(hbInfo->rsp.taskStatus, &status); + + ++i; + pIter = taosHashIterate(sch->tasksHash, pIter); + } + + QW_UNLOCK(QW_READ, &sch->tasksLock); + + return TSDB_CODE_SUCCESS; +} + int32_t qwGetResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, void **rspMsg, SOutputData *pOutput) { int32_t len = 0; @@ -1312,6 +1357,91 @@ _return: QW_RET(code); } +int32_t qwProcessHb(SQWorkerMgmt *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req) { + int32_t code = 0; + SSchedulerHbRsp rsp = {0}; + SQWSchStatus *sch = NULL; + uint64_t seqId = 0; + + memcpy(&rsp.epId, &req->epId, sizeof(req->epId)); + + QW_ERR_JRET(qwAcquireAddScheduler(mgmt, req->sId, QW_READ, &sch)); + + atomic_store_ptr(&sch->hbConnection, qwMsg->connection); + ++sch->hbSeqId; + + rsp.seqId = sch->hbSeqId; + + QW_DLOG("hb connection updated, seqId:%" PRIx64 ", sId:%" PRIx64 ", nodeId:%d, fqdn:%s, port:%d, connection:%p", + sch->hbSeqId, req->sId, req->epId.nodeId, req->epId.ep.fqdn, req->epId.ep.port, qwMsg->connection); + + qwReleaseScheduler(QW_READ, mgmt); + +_return: + + qwBuildAndSendHbRsp(qwMsg->connection, &rsp, code); + + QW_RET(code); +} + + +void qwProcessHbTimerEvent(void *param, void *tmrId) { + return; + + SQWorkerMgmt *mgmt = (SQWorkerMgmt *)param; + SQWSchStatus *sch = NULL; + int32_t taskNum = 0; + SQWHbInfo *rspList = NULL; + int32_t code = 0; + + QW_LOCK(QW_READ, &mgmt->schLock); + + int32_t schNum = taosHashGetSize(mgmt->schHash); + if (schNum <= 0) { + QW_UNLOCK(QW_READ, &mgmt->schLock); + taosTmrReset(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, param, mgmt->timer, &mgmt->hbTimer); + return; + } + + rspList = calloc(schNum, sizeof(SQWHbInfo)); + if (NULL == rspList) { + QW_UNLOCK(QW_READ, &mgmt->schLock); + QW_ELOG("calloc %d SQWHbInfo failed", schNum); + taosTmrReset(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, param, mgmt->timer, &mgmt->hbTimer); + return; + } + + void *key = NULL; + size_t keyLen = 0; + int32_t i = 0; + + void *pIter = taosHashIterate(mgmt->schHash, NULL); + while (pIter) { + code = qwGenerateSchHbRsp(mgmt, (SQWSchStatus *)pIter, &rspList[i]); + if (code) { + taosHashCancelIterate(mgmt->schHash, pIter); + QW_ERR_JRET(code); + } + + ++i; + pIter = taosHashIterate(mgmt->schHash, pIter); + } + +_return: + + QW_UNLOCK(QW_READ, &mgmt->schLock); + + for (int32_t j = 0; j < i; ++j) { + QW_DLOG("hb on connection %p, taskNum:%d", rspList[j].connection, (rspList[j].rsp.taskStatus ? (int32_t)taosArrayGetSize(rspList[j].rsp.taskStatus) : 0)); + qwBuildAndSendHbRsp(rspList[j].connection, &rspList[j].rsp, code); + tFreeSSchedulerHbRsp(&rspList[j].rsp); + } + + tfree(rspList); + + taosTmrReset(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, param, mgmt->timer, &mgmt->hbTimer); +} + int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qWorkerMgmt, void *nodeObj, putReqToQueryQFp fp1, sendReqToDnodeFp fp2) { if (NULL == qWorkerMgmt || NULL == nodeObj || NULL == fp1 || NULL == fp2) { @@ -1319,6 +1449,7 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qW QW_RET(TSDB_CODE_QRY_INVALID_INPUT); } + int32_t code = 0; SQWorkerMgmt *mgmt = calloc(1, sizeof(SQWorkerMgmt)); if (NULL == mgmt) { qError("calloc %d failed", (int32_t)sizeof(SQWorkerMgmt)); @@ -1346,16 +1477,25 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qW if (NULL == mgmt->schHash) { tfree(mgmt); qError("init %d scheduler hash failed", mgmt->cfg.maxSchedulerNum); - QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + QW_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); } mgmt->ctxHash = taosHashInit(mgmt->cfg.maxTaskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); if (NULL == mgmt->ctxHash) { qError("init %d task ctx hash failed", mgmt->cfg.maxTaskNum); - taosHashCleanup(mgmt->schHash); - mgmt->schHash = NULL; - tfree(mgmt); - QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + QW_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + mgmt->timer = taosTmrInit(0, 0, 0, "qworker"); + if (NULL == mgmt->timer) { + qError("init timer failed, error:%s", tstrerror(terrno)); + QW_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + mgmt->hbTimer = taosTmrStart(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, mgmt, mgmt->timer); + if (NULL == mgmt->hbTimer) { + qError("start hb timer failed"); + QW_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); } mgmt->nodeType = nodeType; @@ -1369,6 +1509,17 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qW qDebug("qworker initialized for node, type:%d, id:%d, handle:%p", mgmt->nodeType, mgmt->nodeId, mgmt); return TSDB_CODE_SUCCESS; + +_return: + + taosHashCleanup(mgmt->schHash); + taosHashCleanup(mgmt->ctxHash); + + taosTmrCleanUp(mgmt->timer); + + tfree(mgmt); + + QW_RET(code); } void qWorkerDestroy(void **qWorkerMgmt) { @@ -1377,6 +1528,9 @@ void qWorkerDestroy(void **qWorkerMgmt) { } SQWorkerMgmt *mgmt = *qWorkerMgmt; + + taosTmrStopA(&mgmt->hbTimer); + taosTmrCleanUp(mgmt->timer); //TODO STOP ALL QUERY @@ -1385,12 +1539,12 @@ void qWorkerDestroy(void **qWorkerMgmt) { tfree(*qWorkerMgmt); } -int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SSchedulerStatusRsp **rsp) { +int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, SSchedulerStatusRsp **rsp) { +/* SQWSchStatus *sch = NULL; int32_t taskNum = 0; -/* - QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + QW_ERR_RET(qwAcquireScheduler(mgmt, sId, QW_READ, &sch)); sch->lastAccessTs = taosGetTimestampSec(); @@ -1401,7 +1555,7 @@ int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint int32_t size = sizeof(SSchedulerStatusRsp) + sizeof((*rsp)->status[0]) * taskNum; *rsp = calloc(1, size); if (NULL == *rsp) { - qError("calloc %d failed", size); + QW_SCH_ELOG("calloc %d failed", size); QW_UNLOCK(QW_READ, &sch->tasksLock); qwReleaseScheduler(QW_READ, mgmt); @@ -1420,6 +1574,7 @@ int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint QW_GET_QTID(key, (*rsp)->status[i].queryId, (*rsp)->status[i].taskId); (*rsp)->status[i].status = taskStatus->status; + ++i; pIter = taosHashIterate(sch->tasksHash, pIter); } @@ -1428,7 +1583,6 @@ int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint (*rsp)->num = taskNum; */ - return TSDB_CODE_SUCCESS; } diff --git a/source/libs/qworker/src/qworkerMsg.c b/source/libs/qworker/src/qworkerMsg.c index bdb9617d0dc9ae8f44ad2d3d34aa8022307aeea4..7d633d1c731480122e3b737ea1c18d336723de2e 100644 --- a/source/libs/qworker/src/qworkerMsg.c +++ b/source/libs/qworker/src/qworkerMsg.c @@ -82,30 +82,18 @@ int32_t qwBuildAndSendReadyRsp(void *connection, int32_t code) { return TSDB_CODE_SUCCESS; } -int32_t qwBuildAndSendStatusRsp(SRpcMsg *pMsg, SSchedulerStatusRsp *sStatus) { - int32_t size = 0; - - if (sStatus) { - size = sizeof(SSchedulerStatusRsp) + sizeof(sStatus->status[0]) * sStatus->num; - } else { - size = sizeof(SSchedulerStatusRsp); - } - - SSchedulerStatusRsp *pRsp = (SSchedulerStatusRsp *)rpcMallocCont(size); - - if (sStatus) { - memcpy(pRsp, sStatus, size); - } else { - pRsp->num = 0; - } +int32_t qwBuildAndSendHbRsp(SRpcMsg *pMsg, SSchedulerHbRsp *pStatus, int32_t code) { + int32_t contLen = tSerializeSSchedulerHbRsp(NULL, 0, pStatus); + void *pRsp = rpcMallocCont(contLen); + tSerializeSSchedulerHbRsp(pRsp, contLen, pStatus); SRpcMsg rpcRsp = { - .msgType = TDMT_VND_TASKS_STATUS_RSP, + .msgType = TDMT_VND_QUERY_HEARTBEAT_RSP, .handle = pMsg->handle, .ahandle = pMsg->ahandle, .pCont = pRsp, - .contLen = size, - .code = 0, + .contLen = contLen, + .code = code, }; rpcSendResponse(&rpcRsp); @@ -243,7 +231,7 @@ int32_t qwBuildAndSendShowFetchRsp(SRpcMsg *pMsg, SVShowTablesFetchReq* pFetchRe return TSDB_CODE_SUCCESS; } -int32_t qwBuildAndSendCQueryMsg(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, void *connection) { +int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, void *connection) { SRpcMsg *pMsg = (SRpcMsg *)connection; SQueryContinueReq * req = (SQueryContinueReq *)rpcMallocCont(sizeof(SQueryContinueReq)); if (NULL == req) { @@ -294,12 +282,14 @@ int32_t qWorkerProcessQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { msg->sId = be64toh(msg->sId); msg->queryId = be64toh(msg->queryId); msg->taskId = be64toh(msg->taskId); + msg->refId = be64toh(msg->refId); msg->phyLen = ntohl(msg->phyLen); msg->sqlLen = ntohl(msg->sqlLen); uint64_t sId = msg->sId; uint64_t qId = msg->queryId; uint64_t tId = msg->taskId; + int64_t rId = msg->refId; SQWMsg qwMsg = {.node = node, .msg = msg->msg + msg->sqlLen, .msgLen = msg->phyLen, .connection = pMsg}; @@ -331,6 +321,7 @@ int32_t qWorkerProcessCQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { uint64_t sId = msg->sId; uint64_t qId = msg->queryId; uint64_t tId = msg->taskId; + int64_t rId = 0; SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; @@ -362,12 +353,13 @@ int32_t qWorkerProcessReadyMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg){ uint64_t sId = msg->sId; uint64_t qId = msg->queryId; uint64_t tId = msg->taskId; + int64_t rId = 0; SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; QW_SCH_TASK_DLOG("processReady start, node:%p", node); - QW_ERR_RET(qwProcessReady(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, &qwMsg)); + QW_ERR_RET(qwProcessReady(QW_FPARAMS(), &qwMsg)); QW_SCH_TASK_DLOG("processReady end, node:%p", node); @@ -396,7 +388,7 @@ int32_t qWorkerProcessStatusMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { _return: - QW_ERR_RET(qwBuildAndSendStatusRsp(pMsg, sStatus)); + //QW_ERR_RET(qwBuildAndSendStatusRsp(pMsg, sStatus)); return TSDB_CODE_SUCCESS; } @@ -421,6 +413,7 @@ int32_t qWorkerProcessFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { uint64_t sId = msg->sId; uint64_t qId = msg->queryId; uint64_t tId = msg->taskId; + int64_t rId = 0; SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; @@ -450,9 +443,10 @@ int32_t qWorkerProcessCancelMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - msg->sId = htobe64(msg->sId); - msg->queryId = htobe64(msg->queryId); - msg->taskId = htobe64(msg->taskId); + msg->sId = be64toh(msg->sId); + msg->queryId = be64toh(msg->queryId); + msg->taskId = be64toh(msg->taskId); + msg->refId = be64toh(msg->refId); //QW_ERR_JRET(qwCancelTask(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId)); @@ -480,10 +474,12 @@ int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { msg->sId = be64toh(msg->sId); msg->queryId = be64toh(msg->queryId); msg->taskId = be64toh(msg->taskId); + msg->refId = be64toh(msg->refId); uint64_t sId = msg->sId; uint64_t qId = msg->queryId; uint64_t tId = msg->taskId; + int64_t rId = msg->refId; SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; @@ -496,6 +492,39 @@ int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { return TSDB_CODE_SUCCESS; } +int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + int32_t code = 0; + SSchedulerHbReq req = {0}; + SQWorkerMgmt *mgmt = (SQWorkerMgmt *)qWorkerMgmt; + + if (NULL == pMsg->pCont) { + QW_ELOG("invalid hb msg, msg:%p, msgLen:%d", pMsg->pCont, pMsg->contLen); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (tDeserializeSSchedulerHbReq(pMsg->pCont, pMsg->contLen, &req)) { + QW_ELOG("invalid hb msg, msg:%p, msgLen:%d", pMsg->pCont, pMsg->contLen); + tFreeSSchedulerHbReq(&req); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + uint64_t sId = req.sId; + SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; + + QW_SCH_DLOG("processHb start, node:%p", node); + + QW_ERR_RET(qwProcessHb(mgmt, &qwMsg, &req)); + + QW_SCH_DLOG("processHb end, node:%p", node); + + return TSDB_CODE_SUCCESS; +} + + int32_t qWorkerProcessShowMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { return TSDB_CODE_QRY_INVALID_INPUT; diff --git a/source/libs/qworker/test/CMakeLists.txt b/source/libs/qworker/test/CMakeLists.txt index a464486546c6028ec409acef305050d573f07fa2..6de71a4530a4afbb36bf79cbaa854476cd3f3c0b 100644 --- a/source/libs/qworker/test/CMakeLists.txt +++ b/source/libs/qworker/test/CMakeLists.txt @@ -8,7 +8,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) ADD_EXECUTABLE(qworkerTest ${SOURCE_LIST}) TARGET_LINK_LIBRARIES( qworkerTest - PUBLIC os util common transport gtest qcom planner qworker executor + PUBLIC os util common transport gtest qcom nodes planner qworker executor ) TARGET_INCLUDE_DIRECTORIES( diff --git a/source/libs/qworker/test/qworkerTests.cpp b/source/libs/qworker/test/qworkerTests.cpp index 231f0c7fffdf989e361e63b6a4f5a5a8a39b4759..d7814a5dfbaadabc0b5e1b7bc05e91c3084e7192 100644 --- a/source/libs/qworker/test/qworkerTests.cpp +++ b/source/libs/qworker/test/qworkerTests.cpp @@ -266,7 +266,7 @@ int32_t qwtCreateExecTask(void* tsdb, int32_t vgId, struct SSubplan* pPlan, qTas int32_t idx = abs((++qwtTestCaseIdx) % qwtTestCaseNum); qwtTestSinkBlockNum = 0; - qwtTestSinkMaxBlockNum = rand() % 100 + 1; + qwtTestSinkMaxBlockNum = taosRand() % 100 + 1; qwtTestSinkQueryEnd = false; if (0 == idx) { @@ -295,29 +295,29 @@ int32_t qwtExecTask(qTaskInfo_t tinfo, SSDataBlock** pRes, uint64_t *useconds) { } else { if (qwtTestSinkQueryEnd) { *pRes = NULL; - *useconds = rand() % 10; + *useconds = taosRand() % 10; return 0; } - endExec = rand() % 5; + endExec = taosRand() % 5; int32_t runTime = 0; if (qwtTestEnableSleep && qwtTestMaxExecTaskUsec > 0) { - runTime = rand() % qwtTestMaxExecTaskUsec; + runTime = taosRand() % qwtTestMaxExecTaskUsec; } if (qwtTestEnableSleep) { if (runTime) { - usleep(runTime); + taosUsleep(runTime); } } if (endExec) { *pRes = (SSDataBlock*)calloc(1, sizeof(SSDataBlock)); - (*pRes)->info.rows = rand() % 1000; + (*pRes)->info.rows = taosRand() % 1000; } else { *pRes = NULL; - *useconds = rand() % 10; + *useconds = taosRand() % 10; } } @@ -376,7 +376,7 @@ void qwtGetDataLength(DataSinkHandle handle, int32_t* pLen, bool* pQueryEnd) { taosWLockLatch(&qwtTestSinkLock); if (qwtTestSinkBlockNum > 0) { - *pLen = rand() % 100 + 1; + *pLen = taosRand() % 100 + 1; qwtTestSinkBlockNum--; } else { *pLen = 0; @@ -392,7 +392,7 @@ void qwtGetDataLength(DataSinkHandle handle, int32_t* pLen, bool* pQueryEnd) { int32_t qwtGetDataBlock(DataSinkHandle handle, SOutputData* pOutput) { taosWLockLatch(&qwtTestSinkLock); if (qwtTestSinkLastLen > 0) { - pOutput->numOfRows = rand() % 10 + 1; + pOutput->numOfRows = taosRand() % 10 + 1; pOutput->compressed = 1; pOutput->queryEnd = qwtTestSinkQueryEnd; if (qwtTestSinkBlockNum == 0) { @@ -402,7 +402,7 @@ int32_t qwtGetDataBlock(DataSinkHandle handle, SOutputData* pOutput) { } else { pOutput->bufStatus = DS_BUF_FULL; } - pOutput->useconds = rand() % 10 + 1; + pOutput->useconds = taosRand() % 10 + 1; pOutput->precision = 1; } else if (qwtTestSinkLastLen == 0) { pOutput->numOfRows = 0; @@ -416,7 +416,7 @@ int32_t qwtGetDataBlock(DataSinkHandle handle, SOutputData* pOutput) { } else { pOutput->bufStatus = DS_BUF_FULL; } - pOutput->useconds = rand() % 10 + 1; + pOutput->useconds = taosRand() % 10 + 1; pOutput->precision = 1; } else { assert(0); @@ -590,7 +590,7 @@ void *queryThread(void *param) { qwtBuildQueryReqMsg(&queryRpc); qWorkerProcessQueryMsg(mockPointer, mgmt, &queryRpc); if (qwtTestEnableSleep) { - usleep(rand()%5); + taosUsleep(taosRand()%5); } if (++n % qwtTestPrintNum == 0) { printf("query:%d\n", n); @@ -612,7 +612,7 @@ void *readyThread(void *param) { qwtBuildReadyReqMsg(&readyMsg, &readyRpc); code = qWorkerProcessReadyMsg(mockPointer, mgmt, &readyRpc); if (qwtTestEnableSleep) { - usleep(rand()%5); + taosUsleep(taosRand()%5); } if (++n % qwtTestPrintNum == 0) { printf("ready:%d\n", n); @@ -634,7 +634,7 @@ void *fetchThread(void *param) { qwtBuildFetchReqMsg(&fetchMsg, &fetchRpc); code = qWorkerProcessFetchMsg(mockPointer, mgmt, &fetchRpc); if (qwtTestEnableSleep) { - usleep(rand()%5); + taosUsleep(taosRand()%5); } if (++n % qwtTestPrintNum == 0) { printf("fetch:%d\n", n); @@ -656,7 +656,7 @@ void *dropThread(void *param) { qwtBuildDropReqMsg(&dropMsg, &dropRpc); code = qWorkerProcessDropMsg(mockPointer, mgmt, &dropRpc); if (qwtTestEnableSleep) { - usleep(rand()%5); + taosUsleep(taosRand()%5); } if (++n % qwtTestPrintNum == 0) { printf("drop:%d\n", n); @@ -678,7 +678,7 @@ void *statusThread(void *param) { qwtBuildStatusReqMsg(&statusMsg, &statusRpc); code = qWorkerProcessStatusMsg(mockPointer, mgmt, &statusRpc); if (qwtTestEnableSleep) { - usleep(rand()%5); + taosUsleep(taosRand()%5); } if (++n % qwtTestPrintNum == 0) { printf("status:%d\n", n); @@ -696,7 +696,7 @@ void *qwtclientThread(void *param) { void *mockPointer = (void *)0x1; SRpcMsg queryRpc = {0}; - sleep(1); + taosSsleep(1); while (!qwtTestStop) { qwtTestCaseFinished = false; @@ -705,7 +705,7 @@ void *qwtclientThread(void *param) { qwtPutReqToQueue((void *)0x1, &queryRpc); while (!qwtTestCaseFinished) { - usleep(1); + taosUsleep(1); } @@ -748,10 +748,10 @@ void *queryQueueThread(void *param) { if (qwtTestEnableSleep && qwtTestReqMaxDelayUsec > 0) { - int32_t delay = rand() % qwtTestReqMaxDelayUsec; + int32_t delay = taosRand() % qwtTestReqMaxDelayUsec; if (delay) { - usleep(delay); + taosUsleep(delay); } } @@ -804,10 +804,10 @@ void *fetchQueueThread(void *param) { taosWUnLockLatch(&qwtTestFetchQueueLock); if (qwtTestEnableSleep && qwtTestReqMaxDelayUsec > 0) { - int32_t delay = rand() % qwtTestReqMaxDelayUsec; + int32_t delay = taosRand() % qwtTestReqMaxDelayUsec; if (delay) { - usleep(delay); + taosUsleep(delay); } } @@ -963,7 +963,7 @@ TEST(seqTest, randCase) { stubSetRpcSendResponse(); stubSetCreateExecTask(); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); code = qWorkerInit(NODE_TYPE_VNODE, 1, NULL, &mgmt, mockPointer, qwtPutReqToQueue); ASSERT_EQ(code, 0); @@ -971,7 +971,7 @@ TEST(seqTest, randCase) { int32_t t = 0; int32_t maxr = 10001; while (true) { - int32_t r = rand() % maxr; + int32_t r = taosRand() % maxr; if (r >= 0 && r < maxr/5) { printf("Query,%d\n", t++); @@ -982,21 +982,21 @@ TEST(seqTest, randCase) { qwtBuildReadyReqMsg(&readyMsg, &readyRpc); code = qWorkerProcessReadyMsg(mockPointer, mgmt, &readyRpc); if (qwtTestEnableSleep) { - usleep(1); + taosUsleep(1); } } else if (r >= maxr * 2/5 && r < maxr* 3/5) { printf("Fetch,%d\n", t++); qwtBuildFetchReqMsg(&fetchMsg, &fetchRpc); code = qWorkerProcessFetchMsg(mockPointer, mgmt, &fetchRpc); if (qwtTestEnableSleep) { - usleep(1); + taosUsleep(1); } } else if (r >= maxr * 3/5 && r < maxr * 4/5) { printf("Drop,%d\n", t++); qwtBuildDropReqMsg(&dropMsg, &dropRpc); code = qWorkerProcessDropMsg(mockPointer, mgmt, &dropRpc); if (qwtTestEnableSleep) { - usleep(1); + taosUsleep(1); } } else if (r >= maxr * 4/5 && r < maxr-1) { printf("Status,%d\n", t++); @@ -1004,7 +1004,7 @@ TEST(seqTest, randCase) { code = qWorkerProcessStatusMsg(mockPointer, mgmt, &statusRpc); ASSERT_EQ(code, 0); if (qwtTestEnableSleep) { - usleep(1); + taosUsleep(1); } } else { printf("QUIT RAND NOW"); @@ -1025,7 +1025,7 @@ TEST(seqTest, multithreadRand) { stubSetStringToPlan(); stubSetRpcSendResponse(); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); code = qWorkerInit(NODE_TYPE_VNODE, 1, NULL, &mgmt, mockPointer, qwtPutReqToQueue); ASSERT_EQ(code, 0); @@ -1042,15 +1042,15 @@ TEST(seqTest, multithreadRand) { while (true) { if (qwtTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(qwtTestMTRunSec); + taosSsleep(qwtTestMTRunSec); break; } } qwtTestStop = true; - sleep(3); + taosSsleep(3); qWorkerDestroy(&mgmt); } @@ -1076,7 +1076,7 @@ TEST(rcTest, shortExecshortDelay) { stubSetPutDataBlock(); stubSetGetDataBlock(); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); qwtTestStop = false; qwtTestQuitThreadNum = 0; @@ -1099,9 +1099,9 @@ TEST(rcTest, shortExecshortDelay) { while (true) { if (qwtTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(qwtTestMTRunSec); + taosSsleep(qwtTestMTRunSec); break; } } @@ -1113,14 +1113,14 @@ TEST(rcTest, shortExecshortDelay) { break; } - sleep(1); + taosSsleep(1); if (qwtTestCaseFinished) { if (qwtTestQuitThreadNum < 3) { tsem_post(&qwtTestQuerySem); tsem_post(&qwtTestFetchSem); - usleep(10); + taosUsleep(10); } } @@ -1157,7 +1157,7 @@ TEST(rcTest, longExecshortDelay) { stubSetPutDataBlock(); stubSetGetDataBlock(); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); qwtTestStop = false; qwtTestQuitThreadNum = 0; @@ -1180,9 +1180,9 @@ TEST(rcTest, longExecshortDelay) { while (true) { if (qwtTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(qwtTestMTRunSec); + taosSsleep(qwtTestMTRunSec); break; } } @@ -1195,14 +1195,14 @@ TEST(rcTest, longExecshortDelay) { break; } - sleep(1); + taosSsleep(1); if (qwtTestCaseFinished) { if (qwtTestQuitThreadNum < 3) { tsem_post(&qwtTestQuerySem); tsem_post(&qwtTestFetchSem); - usleep(10); + taosUsleep(10); } } @@ -1240,7 +1240,7 @@ TEST(rcTest, shortExeclongDelay) { stubSetPutDataBlock(); stubSetGetDataBlock(); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); qwtTestStop = false; qwtTestQuitThreadNum = 0; @@ -1263,9 +1263,9 @@ TEST(rcTest, shortExeclongDelay) { while (true) { if (qwtTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(qwtTestMTRunSec); + taosSsleep(qwtTestMTRunSec); break; } } @@ -1278,14 +1278,14 @@ TEST(rcTest, shortExeclongDelay) { break; } - sleep(1); + taosSsleep(1); if (qwtTestCaseFinished) { if (qwtTestQuitThreadNum < 3) { tsem_post(&qwtTestQuerySem); tsem_post(&qwtTestFetchSem); - usleep(10); + taosUsleep(10); } } @@ -1324,7 +1324,7 @@ TEST(rcTest, dropTest) { stubSetPutDataBlock(); stubSetGetDataBlock(); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); code = qWorkerInit(NODE_TYPE_VNODE, 1, NULL, &mgmt, mockPointer, qwtPutReqToQueue); ASSERT_EQ(code, 0); @@ -1342,15 +1342,15 @@ TEST(rcTest, dropTest) { while (true) { if (qwtTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(qwtTestMTRunSec); + taosSsleep(qwtTestMTRunSec); break; } } qwtTestStop = true; - sleep(3); + taosSsleep(3); qWorkerDestroy(&mgmt); } @@ -1358,7 +1358,7 @@ TEST(rcTest, dropTest) { int main(int argc, char** argv) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index b066dd2e77806609b817cde98f03d601b0e3cfc6..0fe7bf6e369fc3c9e9b2d8658ccb45c513b255f3 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -411,27 +411,26 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } int8_t gConvertTypes[TSDB_DATA_TYPE_BLOB+1][TSDB_DATA_TYPE_BLOB+1] = { -/* NULL BOOL TINY SMAL INT BIG FLOA DOUB BINA TIME NCHA UTIN USMA UINT UBIG VARC VARB JSON DECI BLOB */ -/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*BOOL*/ 0, 0, 0, 3, 4, 5, 6, 7, 7, 9, 7, 0, 12, 13, 14, 7, 7, 0, 0, 0, -/*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 7, 9, 7, 3, 4, 5, 7, 7, 7, 0, 0, 0, -/*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 7, 9, 7, 3, 4, 5, 7, 7, 7, 0, 0, 0, -/*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 7, 9, 7, 4, 4, 5, 7, 7, 7, 0, 0, 0, -/*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 5, 5, 5, 7, 7, 7, 0, 0, 0, -/*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 7, 6, 6, 6, 6, 7, 7, 0, 0, 0, -/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, -/*BINA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, -/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 9, 7, 7, 7, 0, 0, 0, -/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, -/*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 7, 7, 0, 0, 0, -/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 7, 7, 0, 0, 0, -/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 7, 7, 0, 0, 0, -/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, -/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +/* NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG VARB JSON DECI BLOB */ +/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*BOOL*/ 0, 0, 0, 3, 4, 5, 6, 7, 7, 9, 7, 0, 12, 13, 14, 7, 0, 0, 0, +/*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 7, 9, 7, 3, 4, 5, 7, 7, 0, 0, 0, +/*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 7, 9, 7, 3, 4, 5, 7, 7, 0, 0, 0, +/*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 7, 9, 7, 4, 4, 5, 7, 7, 0, 0, 0, +/*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 5, 5, 5, 7, 7, 0, 0, 0, +/*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 7, 6, 6, 6, 6, 7, 0, 0, 0, +/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, +/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7, 7, 7, 0, 0, 0, 0, +/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 9, 7, 7, 0, 0, 0, +/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, +/*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 7, 0, 0, 0, +/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 7, 0, 0, 0, +/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 7, 0, 0, 0, +/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, +/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int32_t vectorGetConvertType(int32_t type1, int32_t type2) { diff --git a/source/libs/scalar/test/filter/filterTests.cpp b/source/libs/scalar/test/filter/filterTests.cpp index 08210aa2f0d479d007f4b989f46a350aa2b3db49..328028a1d4675e408e77a16cad9fff36d4282d90 100644 --- a/source/libs/scalar/test/filter/filterTests.cpp +++ b/source/libs/scalar/test/filter/filterTests.cpp @@ -66,7 +66,7 @@ void flttInitLogFile() { void flttMakeValueNode(SNode **pNode, int32_t dataType, void *value) { - SNode *node = nodesMakeNode(QUERY_NODE_VALUE); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); SValueNode *vnode = (SValueNode *)node; vnode->node.resType.type = dataType; @@ -85,7 +85,7 @@ void flttMakeValueNode(SNode **pNode, int32_t dataType, void *value) { void flttMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, int32_t dataBytes, int32_t rowNum, void *value) { static uint64_t dbidx = 0; - SNode *node = nodesMakeNode(QUERY_NODE_COLUMN); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_COLUMN); SColumnNode *rnode = (SColumnNode *)node; rnode->node.resType.type = dataType; rnode->node.resType.bytes = dataBytes; @@ -174,7 +174,7 @@ void flttMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in } void flttMakeOpNode(SNode **pNode, EOperatorType opType, int32_t resType, SNode *pLeft, SNode *pRight) { - SNode *node = nodesMakeNode(QUERY_NODE_OPERATOR); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_OPERATOR); SOperatorNode *onode = (SOperatorNode *)node; onode->node.resType.type = resType; onode->node.resType.bytes = tDataTypes[resType].bytes; @@ -187,7 +187,7 @@ void flttMakeOpNode(SNode **pNode, EOperatorType opType, int32_t resType, SNode } void flttMakeLogicNode(SNode **pNode, ELogicConditionType opType, SNode **nodeList, int32_t nodeNum) { - SNode *node = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); SLogicConditionNode *onode = (SLogicConditionNode *)node; onode->condType = opType; onode->node.resType.type = TSDB_DATA_TYPE_BOOL; @@ -202,7 +202,7 @@ void flttMakeLogicNode(SNode **pNode, ELogicConditionType opType, SNode **nodeLi } void flttMakeLogicNodeFromList(SNode **pNode, ELogicConditionType opType, SNodeList *nodeList) { - SNode *node = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); SLogicConditionNode *onode = (SLogicConditionNode *)node; onode->condType = opType; onode->node.resType.type = TSDB_DATA_TYPE_BOOL; @@ -214,7 +214,7 @@ void flttMakeLogicNodeFromList(SNode **pNode, ELogicConditionType opType, SNodeL } void flttMakeListNode(SNode **pNode, SNodeList *list, int32_t resType) { - SNode *node = nodesMakeNode(QUERY_NODE_NODE_LIST); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); SNodeListNode *lnode = (SNodeListNode *)node; lnode->dataType.type = resType; lnode->pNodeList = list; @@ -1286,7 +1286,7 @@ TEST(scalarModelogicTest, diff_columns_or_and_or) { int main(int argc, char** argv) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/source/libs/scalar/test/scalar/scalarTests.cpp b/source/libs/scalar/test/scalar/scalarTests.cpp index faf13f0a82cfa30327f26fb0809ec0420f870a88..d6a73d99bb1e0b46af55605ed1af14625a653304 100644 --- a/source/libs/scalar/test/scalar/scalarTests.cpp +++ b/source/libs/scalar/test/scalar/scalarTests.cpp @@ -41,6 +41,14 @@ namespace { +SColumnInfo createColumnInfo(int32_t colId, int32_t type, int32_t bytes) { + SColumnInfo info = {0}; + info.colId = colId; + info.type = type; + info.bytes = bytes; + return info; +} + int64_t scltLeftV = 21, scltRightV = 10; double scltLeftVd = 21.0, scltRightVd = 10.0; @@ -93,7 +101,7 @@ void scltAppendReservedSlot(SArray *pBlockList, int16_t *dataBlockId, int16_t *s } void scltMakeValueNode(SNode **pNode, int32_t dataType, void *value) { - SNode *node = nodesMakeNode(QUERY_NODE_VALUE); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); SValueNode *vnode = (SValueNode *)node; vnode->node.resType.type = dataType; @@ -110,7 +118,7 @@ void scltMakeValueNode(SNode **pNode, int32_t dataType, void *value) { } void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, int32_t dataBytes, int32_t rowNum, void *value) { - SNode *node = nodesMakeNode(QUERY_NODE_COLUMN); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_COLUMN); SColumnNode *rnode = (SColumnNode *)node; rnode->node.resType.type = dataType; rnode->node.resType.bytes = dataBytes; @@ -189,7 +197,7 @@ void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in } void scltMakeOpNode(SNode **pNode, EOperatorType opType, int32_t resType, SNode *pLeft, SNode *pRight) { - SNode *node = nodesMakeNode(QUERY_NODE_OPERATOR); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_OPERATOR); SOperatorNode *onode = (SOperatorNode *)node; onode->node.resType.type = resType; onode->node.resType.bytes = tDataTypes[resType].bytes; @@ -203,7 +211,7 @@ void scltMakeOpNode(SNode **pNode, EOperatorType opType, int32_t resType, SNode void scltMakeListNode(SNode **pNode, SNodeList *list, int32_t resType) { - SNode *node = nodesMakeNode(QUERY_NODE_NODE_LIST); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); SNodeListNode *lnode = (SNodeListNode *)node; lnode->dataType.type = resType; lnode->pNodeList = list; @@ -213,7 +221,7 @@ void scltMakeListNode(SNode **pNode, SNodeList *list, int32_t resType) { void scltMakeLogicNode(SNode **pNode, ELogicConditionType opType, SNode **nodeList, int32_t nodeNum) { - SNode *node = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); SLogicConditionNode *onode = (SLogicConditionNode *)node; onode->condType = opType; onode->node.resType.type = TSDB_DATA_TYPE_BOOL; @@ -228,7 +236,7 @@ void scltMakeLogicNode(SNode **pNode, ELogicConditionType opType, SNode **nodeLi } void scltMakeTargetNode(SNode **pNode, int16_t dataBlockId, int16_t slotId, SNode *snode) { - SNode *node = nodesMakeNode(QUERY_NODE_TARGET); + SNode *node = (SNode*)nodesMakeNode(QUERY_NODE_TARGET); STargetNode *onode = (STargetNode *)node; onode->pExpr = snode; onode->dataBlockId = dataBlockId; @@ -914,7 +922,7 @@ TEST(columnTest, smallint_value_add_int_column) { SArray *blockList = taosArrayInit(2, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_DOUBLE, .bytes = sizeof(double)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_DOUBLE, sizeof(double)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, true, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -954,7 +962,7 @@ TEST(columnTest, bigint_column_multi_binary_column) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_DOUBLE, .bytes = sizeof(double)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_DOUBLE, sizeof(double)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -992,7 +1000,7 @@ TEST(columnTest, smallint_column_and_binary_column) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BIGINT, .bytes = sizeof(int64_t)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1025,7 +1033,7 @@ TEST(columnTest, smallint_column_or_float_column) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BIGINT, .bytes = sizeof(int64_t)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, true, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1058,7 +1066,7 @@ TEST(columnTest, smallint_column_or_double_value) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BIGINT, .bytes = sizeof(int64_t)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, true, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1091,7 +1099,7 @@ TEST(columnTest, smallint_column_greater_double_value) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, true, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1131,7 +1139,7 @@ TEST(columnTest, int_column_in_double_list) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, true, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1190,7 +1198,7 @@ TEST(columnTest, binary_column_in_binary_list) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1234,7 +1242,7 @@ TEST(columnTest, binary_column_like_binary) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1276,7 +1284,7 @@ TEST(columnTest, binary_column_is_true) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1320,7 +1328,7 @@ TEST(columnTest, binary_column_is_null) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1363,7 +1371,7 @@ TEST(columnTest, binary_column_is_not_null) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&opNode, dataBlockId, slotId, opNode); @@ -1405,7 +1413,7 @@ TEST(columnTest, greater_and_lower) { SArray *blockList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(blockList, &src); - SColumnInfo colInfo = {.colId = 1, .type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; + SColumnInfo colInfo = createColumnInfo(1, TSDB_DATA_TYPE_BOOL, sizeof(bool)); int16_t dataBlockId = 0, slotId = 0; scltAppendReservedSlot(blockList, &dataBlockId, &slotId, false, rowNum, &colInfo); scltMakeTargetNode(&logicNode, dataBlockId, slotId, logicNode); @@ -1427,7 +1435,7 @@ TEST(columnTest, greater_and_lower) { int main(int argc, char** argv) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/source/libs/scheduler/CMakeLists.txt b/source/libs/scheduler/CMakeLists.txt index 862ae7ccae82f40812145b8f0261d23f09b19402..a4a299317cbf5ccc875fe5c0b41f3e33d63e2fa0 100644 --- a/source/libs/scheduler/CMakeLists.txt +++ b/source/libs/scheduler/CMakeLists.txt @@ -9,7 +9,7 @@ target_include_directories( target_link_libraries( scheduler - PUBLIC os util planner qcom common catalog transport + PUBLIC os util nodes planner qcom common catalog transport ) if(${BUILD_TEST}) diff --git a/source/libs/scheduler/inc/schedulerInt.h b/source/libs/scheduler/inc/schedulerInt.h index 50c274ad483cfe80be135628d389985622ee3d4d..2776059f66673696a001b66a5edd86065959f0f1 100644 --- a/source/libs/scheduler/inc/schedulerInt.h +++ b/source/libs/scheduler/inc/schedulerInt.h @@ -26,8 +26,10 @@ extern "C" { #include "scheduler.h" #include "thash.h" -#define SCHEDULE_DEFAULT_JOB_NUMBER 1000 -#define SCHEDULE_DEFAULT_TASK_NUMBER 1000 +#define SCHEDULE_DEFAULT_MAX_JOB_NUM 1000 +#define SCHEDULE_DEFAULT_MAX_TASK_NUM 1000 +#define SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM 20 // unit is TSDB_TABLE_NUM_UNIT + #define SCH_MAX_CANDIDATE_EP_NUM TSDB_MAX_REPLICA @@ -41,6 +43,12 @@ typedef struct SSchTrans { void *transHandle; } SSchTrans; +typedef struct SSchHbTrans { + SRWLatch lock; + uint64_t seqId; + SSchTrans trans; +} SSchHbTrans; + typedef struct SSchApiStat { } SSchApiStat; @@ -61,28 +69,39 @@ typedef struct SSchedulerStat { typedef struct SSchedulerMgmt { - uint64_t taskId; // sequential taksId - uint64_t sId; // schedulerId - SSchedulerCfg cfg; - int32_t jobRef; - SSchedulerStat stat; + uint64_t taskId; // sequential taksId + uint64_t sId; // schedulerId + SSchedulerCfg cfg; + int32_t jobRef; + SSchedulerStat stat; + SHashObj *hbConnections; } SSchedulerMgmt; typedef struct SSchCallbackParam { uint64_t queryId; int64_t refId; uint64_t taskId; + void *transport; } SSchCallbackParam; +typedef struct SSchFlowControl { + SRWLatch lock; + bool sorted; + int32_t tableNumSum; + uint32_t execTaskNum; + SArray *taskList; // Element is SSchTask* +} SSchFlowControl; + typedef struct SSchLevel { - int32_t level; - int8_t status; - SRWLatch lock; - int32_t taskFailed; - int32_t taskSucceed; - int32_t taskNum; - int32_t taskLaunchIdx; // launch startup index - SArray *subTasks; // Element is SQueryTask + int32_t level; + int8_t status; + SRWLatch lock; + int32_t taskFailed; + int32_t taskSucceed; + int32_t taskNum; + int32_t taskLaunchedNum; + SHashObj *flowCtrl; // key is ep, element is SSchFlowControl + SArray *subTasks; // Element is SQueryTask } SSchLevel; typedef struct SSchTask { @@ -102,13 +121,14 @@ typedef struct SSchTask { int32_t childReady; // child task ready number SArray *children; // the datasource tasks,from which to fetch the result, element is SQueryTask* SArray *parents; // the data destination tasks, get data from current task, element is SQueryTask* - void* handle; // task send handle + void* handle; // task send handle } SSchTask; typedef struct SSchJobAttr { bool needFetch; bool syncSchedule; bool queryJob; + bool needFlowCtrl; } SSchJobAttr; typedef struct SSchJob { @@ -119,7 +139,7 @@ typedef struct SSchJob { void *transport; SArray *nodeList; // qnode/vnode list, element is SQueryNodeAddr SArray *levels; // Element is SQueryLevel, starting from 0. SArray - SArray *subPlans; // subplan pointer copied from DAG, no need to free it in scheduler + SNodeList *subPlans; // subplan pointer copied from DAG, no need to free it in scheduler int32_t levelIdx; SEpSet dataSrcEps; @@ -140,11 +160,17 @@ typedef struct SSchJob { SQueryProfileSummary summary; } SSchJob; +extern SSchedulerMgmt schMgmt; + #define SCH_TASK_READY_TO_LUNCH(readyNum, task) ((readyNum) >= taosArrayGetSize((task)->children)) -#define SCH_IS_DATA_SRC_TASK(task) ((task)->plan->type == QUERY_TYPE_SCAN) -#define SCH_TASK_NEED_WAIT_ALL(task) ((task)->plan->type == QUERY_TYPE_MODIFY) -#define SCH_TASK_NO_NEED_DROP(task) ((task)->plan->type == QUERY_TYPE_MODIFY) +#define SCH_TASK_ID(_task) ((_task) ? (_task)->taskId : -1) +#define SCH_SET_TASK_LASTMSG_TYPE(_task, _type) do { if(_task) { atomic_store_32(&(_task)->lastMsgType, _type); } } while (0) +#define SCH_GET_TASK_LASTMSG_TYPE(_task) ((_task) ? atomic_load_32(&(_task)->lastMsgType) : -1) + +#define SCH_IS_DATA_SRC_TASK(task) ((task)->plan->subplanType == SUBPLAN_TYPE_SCAN) +#define SCH_TASK_NEED_WAIT_ALL(task) ((task)->plan->subplanType == SUBPLAN_TYPE_MODIFY) +#define SCH_TASK_NO_NEED_DROP(task) ((task)->plan->subplanType == SUBPLAN_TYPE_MODIFY) #define SCH_SET_TASK_STATUS(task, st) atomic_store_8(&(task)->status, st) #define SCH_GET_TASK_STATUS(task) atomic_load_8(&(task)->status) @@ -152,18 +178,27 @@ typedef struct SSchJob { #define SCH_SET_JOB_STATUS(job, st) atomic_store_8(&(job)->status, st) #define SCH_GET_JOB_STATUS(job) atomic_load_8(&(job)->status) -#define SCH_SET_JOB_TYPE(pAttr, type) (pAttr)->queryJob = ((type) != QUERY_TYPE_MODIFY) -#define SCH_JOB_NEED_FETCH(pAttr) ((pAttr)->queryJob) +#define SCH_SET_JOB_NEED_FLOW_CTRL(_job) (_job)->attr.needFlowCtrl = true +#define SCH_JOB_NEED_FLOW_CTRL(_job) ((_job)->attr.needFlowCtrl) +#define SCH_TASK_NEED_FLOW_CTRL(_job, _task) (SCH_IS_DATA_SRC_TASK(_task) && SCH_JOB_NEED_FLOW_CTRL(_job) && SCH_IS_LEAF_TASK(_job, _task) && SCH_IS_LEVEL_UNFINISHED((_task)->level)) + +#define SCH_SET_JOB_TYPE(_job, type) (_job)->attr.queryJob = ((type) != SUBPLAN_TYPE_MODIFY) +#define SCH_IS_QUERY_JOB(_job) ((_job)->attr.queryJob) +#define SCH_JOB_NEED_FETCH(_job) SCH_IS_QUERY_JOB(_job) +#define SCH_IS_LEAF_TASK(_job, _task) (((_task)->level->level + 1) == (_job)->levelNum) +#define SCH_IS_LEVEL_UNFINISHED(_level) ((_level)->taskLaunchedNum < (_level)->taskNum) +#define SCH_GET_CUR_EP(_addr) (&(_addr)->epSet.eps[(_addr)->epSet.inUse]) +#define SCH_SWITCH_EPSET(_addr) ((_addr)->epSet.inUse = ((_addr)->epSet.inUse + 1) % (_addr)->epSet.numOfEps) #define SCH_JOB_ELOG(param, ...) qError("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__) #define SCH_JOB_DLOG(param, ...) qDebug("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__) #define SCH_TASK_ELOG(param, ...) \ - qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, pTask->taskId, __VA_ARGS__) + qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__) #define SCH_TASK_DLOG(param, ...) \ - qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, pTask->taskId, __VA_ARGS__) + qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__) #define SCH_TASK_WLOG(param, ...) \ - qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, pTask->taskId, __VA_ARGS__) + qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 " " param, pJob->queryId, SCH_TASK_ID(pTask), __VA_ARGS__) #define SCH_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0) #define SCH_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0) @@ -173,10 +208,19 @@ typedef struct SSchJob { #define SCH_UNLOCK(type, _lock) (SCH_READ == (type) ? taosRUnLockLatch(_lock) : taosWUnLockLatch(_lock)) -static int32_t schLaunchTask(SSchJob *job, SSchTask *task); -static int32_t schBuildAndSendMsg(SSchJob *job, SSchTask *task, SQueryNodeAddr *addr, int32_t msgType); +int32_t schLaunchTask(SSchJob *job, SSchTask *task); +int32_t schBuildAndSendMsg(SSchJob *job, SSchTask *task, SQueryNodeAddr *addr, int32_t msgType); SSchJob *schAcquireJob(int64_t refId); int32_t schReleaseJob(int64_t refId); +void schFreeFlowCtrl(SSchLevel *pLevel); +int32_t schCheckJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel); +int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask); +int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough); +int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask); +int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask); +int32_t schFetchFromRemote(SSchJob *pJob); +int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode); + #ifdef __cplusplus } diff --git a/source/libs/scheduler/src/schFlowCtrl.c b/source/libs/scheduler/src/schFlowCtrl.c new file mode 100644 index 0000000000000000000000000000000000000000..9fba6523b6bbfcb165d5e6acff3b53fc73620fd8 --- /dev/null +++ b/source/libs/scheduler/src/schFlowCtrl.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "schedulerInt.h" +#include "tmsg.h" +#include "query.h" +#include "catalog.h" +#include "tref.h" + +void schFreeFlowCtrl(SSchLevel *pLevel) { + if (NULL == pLevel->flowCtrl) { + return; + } + + SSchFlowControl *ctrl = NULL; + void *pIter = taosHashIterate(pLevel->flowCtrl, NULL); + while (pIter) { + ctrl = (SSchFlowControl *)pIter; + + if (ctrl->taskList) { + taosArrayDestroy(ctrl->taskList); + } + + pIter = taosHashIterate(pLevel->flowCtrl, pIter); + } + + taosHashCleanup(pLevel->flowCtrl); + pLevel->flowCtrl = NULL; +} + +int32_t schCheckJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel) { + if (!SCH_IS_QUERY_JOB(pJob)) { + SCH_JOB_DLOG("job no need flow ctrl, queryJob:%d", SCH_IS_QUERY_JOB(pJob)); + return TSDB_CODE_SUCCESS; + } + + int32_t sum = 0; + + for (int32_t i = 0; i < pLevel->taskNum; ++i) { + SSchTask *pTask = taosArrayGet(pLevel->subTasks, i); + + sum += pTask->plan->execNodeStat.tableNum; + } + + if (sum < schMgmt.cfg.maxNodeTableNum) { + SCH_JOB_DLOG("job no need flow ctrl, totalTableNum:%d", sum); + return TSDB_CODE_SUCCESS; + } + + pLevel->flowCtrl = taosHashInit(pLevel->taskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pLevel->flowCtrl) { + SCH_JOB_ELOG("taosHashInit %d flowCtrl failed", pLevel->taskNum); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_SET_JOB_NEED_FLOW_CTRL(pJob); + + SCH_JOB_DLOG("job NEED flow ctrl, totalTableNum:%d", sum); + + return TSDB_CODE_SUCCESS; +} + +int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask) { + SSchLevel *pLevel = pTask->level; + SSchFlowControl *ctrl = NULL; + int32_t code = 0; + SEp *ep = SCH_GET_CUR_EP(&pTask->plan->execNode); + + ctrl = (SSchFlowControl *)taosHashGet(pLevel->flowCtrl, ep, sizeof(SEp)); + if (NULL == ctrl) { + SCH_TASK_ELOG("taosHashGet node from flowCtrl failed, fqdn:%s, port:%d", ep->fqdn, ep->port); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + SCH_LOCK(SCH_WRITE, &ctrl->lock); + if (ctrl->execTaskNum <= 0) { + SCH_TASK_ELOG("taosHashGet node from flowCtrl failed, fqdn:%s, port:%d", ep->fqdn, ep->port); + SCH_ERR_JRET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + --ctrl->execTaskNum; + ctrl->tableNumSum -= pTask->plan->execNodeStat.tableNum; + + SCH_TASK_DLOG("task quota removed, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", + ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); + +_return: + + SCH_UNLOCK(SCH_WRITE, &ctrl->lock); + + SCH_RET(code); +} + +int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough) { + SSchLevel *pLevel = pTask->level; + int32_t code = 0; + SSchFlowControl *ctrl = NULL; + SEp *ep = SCH_GET_CUR_EP(&pTask->plan->execNode); + + do { + ctrl = (SSchFlowControl *)taosHashGet(pLevel->flowCtrl, ep, sizeof(SEp)); + if (NULL == ctrl) { + SSchFlowControl nctrl = {.tableNumSum = pTask->plan->execNodeStat.tableNum, .execTaskNum = 1}; + + code = taosHashPut(pLevel->flowCtrl, ep, sizeof(SEp), &nctrl, sizeof(nctrl)); + if (code) { + if (HASH_NODE_EXIST(code)) { + continue; + } + + SCH_TASK_ELOG("taosHashPut flowCtrl failed, size:%d", (int32_t)sizeof(nctrl)); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_TASK_DLOG("task quota added, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", + ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, nctrl.tableNumSum, nctrl.execTaskNum); + + *enough = true; + return TSDB_CODE_SUCCESS; + } + + SCH_LOCK(SCH_WRITE, &ctrl->lock); + + if (0 == ctrl->execTaskNum) { + ctrl->tableNumSum = pTask->plan->execNodeStat.tableNum; + ++ctrl->execTaskNum; + + *enough = true; + break; + } + + int32_t sum = pTask->plan->execNodeStat.tableNum + ctrl->tableNumSum; + + if (sum <= schMgmt.cfg.maxNodeTableNum) { + ctrl->tableNumSum = sum; + ++ctrl->execTaskNum; + + *enough = true; + break; + } + + if (NULL == ctrl->taskList) { + ctrl->taskList = taosArrayInit(pLevel->taskNum, POINTER_BYTES); + if (NULL == ctrl->taskList) { + SCH_TASK_ELOG("taosArrayInit taskList failed, size:%d", (int32_t)pLevel->taskNum); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + } + + if (NULL == taosArrayPush(ctrl->taskList, &pTask)) { + SCH_TASK_ELOG("taosArrayPush to taskList failed, size:%d", (int32_t)taosArrayGetSize(ctrl->taskList)); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + *enough = false; + ctrl->sorted = false; + + break; + } while (true); + +_return: + + SCH_TASK_DLOG("task quota %s added, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", + ((*enough)?"":"NOT"), ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); + + SCH_UNLOCK(SCH_WRITE, &ctrl->lock); + + SCH_RET(code); +} + +int32_t schTaskTableNumCompare(const void* key1, const void* key2) { + SSchTask *pTask1 = *(SSchTask **)key1; + SSchTask *pTask2 = *(SSchTask **)key2; + + if (pTask1->plan->execNodeStat.tableNum < pTask2->plan->execNodeStat.tableNum) { + return 1; + } else if (pTask1->plan->execNodeStat.tableNum > pTask2->plan->execNodeStat.tableNum) { + return -1; + } else { + return 0; + } +} + + +int32_t schLaunchTasksInFlowCtrlListImpl(SSchJob *pJob, SSchFlowControl *ctrl) { + SCH_LOCK(SCH_WRITE, &ctrl->lock); + + if (NULL == ctrl->taskList || taosArrayGetSize(ctrl->taskList) <= 0) { + SCH_UNLOCK(SCH_WRITE, &ctrl->lock); + return TSDB_CODE_SUCCESS; + } + + int32_t remainNum = schMgmt.cfg.maxNodeTableNum - ctrl->tableNumSum; + int32_t taskNum = taosArrayGetSize(ctrl->taskList); + int32_t code = 0; + SSchTask *pTask = NULL; + + if (taskNum > 1 && !ctrl->sorted) { + taosArraySort(ctrl->taskList, schTaskTableNumCompare); // desc order + } + + for (int32_t i = 0; i < taskNum; ++i) { + pTask = *(SSchTask **)taosArrayGet(ctrl->taskList, i); + SEp *ep = SCH_GET_CUR_EP(&pTask->plan->execNode); + + if (pTask->plan->execNodeStat.tableNum > remainNum && ctrl->execTaskNum > 0) { + SCH_TASK_DLOG("task NOT to launch, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", + ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); + + continue; + } + + ctrl->tableNumSum += pTask->plan->execNodeStat.tableNum; + ++ctrl->execTaskNum; + + taosArrayRemove(ctrl->taskList, i); + + SCH_TASK_DLOG("task to launch, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", + ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); + + SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); + + remainNum -= pTask->plan->execNodeStat.tableNum; + if (remainNum <= 0) { + SCH_TASK_DLOG("no more task to launch, fqdn:%s, port:%d, remainNum:%d, remainExecTaskNum:%d", + ep->fqdn, ep->port, ctrl->tableNumSum, ctrl->execTaskNum); + + break; + } + + if (i < (taskNum - 1)) { + SSchTask *pLastTask = *(SSchTask **)taosArrayGetLast(ctrl->taskList); + if (remainNum < pLastTask->plan->execNodeStat.tableNum) { + SCH_TASK_DLOG("no more task to launch, fqdn:%s, port:%d, remainNum:%d, remainExecTaskNum:%d, smallestInList:%d", + ep->fqdn, ep->port, ctrl->tableNumSum, ctrl->execTaskNum, pLastTask->plan->execNodeStat.tableNum); + + break; + } + } + + --i; + --taskNum; + } + +_return: + + SCH_UNLOCK(SCH_WRITE, &ctrl->lock); + + if (code) { + code = schProcessOnTaskFailure(pJob, pTask, code); + } + + SCH_RET(code); +} + + +int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask) { + if (!SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { + return TSDB_CODE_SUCCESS; + } + + SCH_ERR_RET(schDecTaskFlowQuota(pJob, pTask)); + + SSchLevel *pLevel = pTask->level; + SEp *ep = SCH_GET_CUR_EP(&pTask->plan->execNode); + + SSchFlowControl *ctrl = (SSchFlowControl *)taosHashGet(pLevel->flowCtrl, ep, sizeof(SEp)); + if (NULL == ctrl) { + SCH_TASK_ELOG("taosHashGet node from flowCtrl failed, fqdn:%s, port:%d", ep->fqdn, ep->port); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + SCH_ERR_RET(schLaunchTasksInFlowCtrlListImpl(pJob, ctrl)); + +} + + diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index 8ed39eb0b782fa495a6305228b9f50c13bdb5a91..ebe70ca401e725a0ba7f448223dde13dabc405c8 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -91,8 +91,20 @@ void schFreeTask(SSchTask* pTask) { } +static FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) { + int8_t status = SCH_GET_JOB_STATUS(pJob); + if (pStatus) { + *pStatus = status; + } + + return (status == JOB_TASK_STATUS_FAILED || status == JOB_TASK_STATUS_CANCELLED + || status == JOB_TASK_STATUS_CANCELLING || status == JOB_TASK_STATUS_DROPPING + || status == JOB_TASK_STATUS_SUCCEED); +} + + int32_t schValidateTaskReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgType) { - int32_t lastMsgType = atomic_load_32(&pTask->lastMsgType); + int32_t lastMsgType = SCH_GET_TASK_LASTMSG_TYPE(pTask); switch (msgType) { case TDMT_VND_CREATE_TABLE_RSP: @@ -102,22 +114,24 @@ int32_t schValidateTaskReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t m case TDMT_VND_FETCH_RSP: case TDMT_VND_DROP_TASK: if (lastMsgType != (msgType - 1)) { - SCH_TASK_ELOG("rsp msg type mis-match, last sent msgType:%d, rspType:%d", lastMsgType, msgType); + SCH_TASK_ELOG("rsp msg type mis-match, last sent msgType:%s, rspType:%s", TMSG_INFO(lastMsgType), TMSG_INFO(msgType)); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXECUTING && SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_PARTIAL_SUCCEED) { - SCH_TASK_ELOG("rsp msg conflicted with task status, status:%d, rspType:%d", SCH_GET_TASK_STATUS(pTask), msgType); + SCH_TASK_ELOG("rsp msg conflicted with task status, status:%d, rspType:%s", SCH_GET_TASK_STATUS(pTask), TMSG_INFO(msgType)); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } break; default: - SCH_TASK_ELOG("unknown rsp msg, type:%d, status:%d", msgType, SCH_GET_TASK_STATUS(pTask)); + SCH_TASK_ELOG("unknown rsp msg, type:%s, status:%d", TMSG_INFO(msgType), SCH_GET_TASK_STATUS(pTask)); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } + SCH_SET_TASK_LASTMSG_TYPE(pTask, -1); + return TSDB_CODE_SUCCESS; } @@ -197,6 +211,7 @@ int32_t schCheckAndUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { _return: SCH_JOB_ELOG("invalid job status update, from %d to %d", oriStatus, newStatus); + SCH_ERR_RET(code); } @@ -208,8 +223,8 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { for (int32_t m = 0; m < pLevel->taskNum; ++m) { SSchTask *pTask = taosArrayGet(pLevel->subTasks, m); SSubplan *pPlan = pTask->plan; - int32_t childNum = pPlan->pChildren ? (int32_t)taosArrayGetSize(pPlan->pChildren) : 0; - int32_t parentNum = pPlan->pParents ? (int32_t)taosArrayGetSize(pPlan->pParents) : 0; + int32_t childNum = pPlan->pChildren ? (int32_t)LIST_LENGTH(pPlan->pChildren) : 0; + int32_t parentNum = pPlan->pParents ? (int32_t)LIST_LENGTH(pPlan->pParents) : 0; if (childNum > 0) { if (pJob->levelIdx == pLevel->level) { @@ -225,8 +240,8 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { } for (int32_t n = 0; n < childNum; ++n) { - SSubplan **child = taosArrayGet(pPlan->pChildren, n); - SSchTask **childTask = taosHashGet(planToTask, child, POINTER_BYTES); + SSubplan *child = (SSubplan*)nodesListGetNode(pPlan->pChildren, n); + SSchTask **childTask = taosHashGet(planToTask, &child, POINTER_BYTES); if (NULL == childTask || NULL == *childTask) { SCH_TASK_ELOG("subplan children relationship error, level:%d, taskIdx:%d, childIdx:%d", i, m, n); SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); @@ -257,8 +272,8 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { } for (int32_t n = 0; n < parentNum; ++n) { - SSubplan **parent = taosArrayGet(pPlan->pParents, n); - SSchTask **parentTask = taosHashGet(planToTask, parent, POINTER_BYTES); + SSubplan *parent = (SSubplan*)nodesListGetNode(pPlan->pParents, n); + SSchTask **parentTask = taosHashGet(planToTask, &parent, POINTER_BYTES); if (NULL == parentTask || NULL == *parentTask) { SCH_TASK_ELOG("subplan parent relationship error, level:%d, taskIdx:%d, childIdx:%d", i, m, n); SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); @@ -275,7 +290,7 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { } SSchLevel *pLevel = taosArrayGet(pJob->levels, 0); - if (pJob->attr.queryJob && pLevel->taskNum > 1) { + if (SCH_IS_QUERY_JOB(pJob) && pLevel->taskNum > 1) { SCH_JOB_ELOG("invalid query plan, level:0, taskNum:%d", pLevel->taskNum); SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); } @@ -285,10 +300,9 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { int32_t schRecordTaskSucceedNode(SSchJob *pJob, SSchTask *pTask) { - int32_t idx = atomic_load_8(&pTask->candidateIdx); - SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, idx); + SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); if (NULL == addr) { - SCH_TASK_ELOG("taosArrayGet candidate addr failed, idx:%d, size:%d", idx, (int32_t)taosArrayGetSize(pTask->candidateAddrs)); + SCH_TASK_ELOG("taosArrayGet candidate addr failed, idx:%d, size:%d", pTask->candidateIdx, (int32_t)taosArrayGetSize(pTask->candidateAddrs)); SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); } @@ -308,7 +322,7 @@ int32_t schRecordTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *ad } -int32_t schValidateAndBuildJob(SQueryDag *pDag, SSchJob *pJob) { +int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { int32_t code = 0; pJob->queryId = pDag->queryId; @@ -317,15 +331,15 @@ int32_t schValidateAndBuildJob(SQueryDag *pDag, SSchJob *pJob) { SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - int32_t levelNum = (int32_t)taosArrayGetSize(pDag->pSubplans); + int32_t levelNum = (int32_t)LIST_LENGTH(pDag->pSubplans); if (levelNum <= 0) { SCH_JOB_ELOG("invalid level num:%d", levelNum); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - SHashObj *planToTask = taosHashInit(SCHEDULE_DEFAULT_TASK_NUMBER, taosGetDefaultHashFunction(POINTER_BYTES == sizeof(int64_t) ? TSDB_DATA_TYPE_BIGINT : TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); + SHashObj *planToTask = taosHashInit(SCHEDULE_DEFAULT_MAX_TASK_NUM, taosGetDefaultHashFunction(POINTER_BYTES == sizeof(int64_t) ? TSDB_DATA_TYPE_BIGINT : TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); if (NULL == planToTask) { - SCH_JOB_ELOG("taosHashInit %d failed", SCHEDULE_DEFAULT_TASK_NUMBER); + SCH_JOB_ELOG("taosHashInit %d failed", SCHEDULE_DEFAULT_MAX_TASK_NUM); SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); } @@ -341,7 +355,7 @@ int32_t schValidateAndBuildJob(SQueryDag *pDag, SSchJob *pJob) { pJob->subPlans = pDag->pSubplans; SSchLevel level = {0}; - SArray *plans = NULL; + SNodeListNode *plans = NULL; int32_t taskNum = 0; SSchLevel *pLevel = NULL; @@ -356,13 +370,13 @@ int32_t schValidateAndBuildJob(SQueryDag *pDag, SSchJob *pJob) { pLevel = taosArrayGet(pJob->levels, i); pLevel->level = i; - plans = taosArrayGetP(pDag->pSubplans, i); + plans = (SNodeListNode*)nodesListGetNode(pDag->pSubplans, i); if (NULL == plans) { SCH_JOB_ELOG("empty level plan, level:%d", i); SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } - taskNum = (int32_t)taosArrayGetSize(plans); + taskNum = (int32_t)LIST_LENGTH(plans->pNodeList); if (taskNum <= 0) { SCH_JOB_ELOG("invalid level plan number:%d, level:%d", taskNum, i); SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); @@ -377,9 +391,9 @@ int32_t schValidateAndBuildJob(SQueryDag *pDag, SSchJob *pJob) { } for (int32_t n = 0; n < taskNum; ++n) { - SSubplan *plan = taosArrayGetP(plans, n); + SSubplan *plan = (SSubplan*)nodesListGetNode(plans->pNodeList, n); - SCH_SET_JOB_TYPE(&pJob->attr, plan->type); + SCH_SET_JOB_TYPE(pJob, plan->subplanType); SSchTask task = {0}; SSchTask *pTask = &task; @@ -488,6 +502,8 @@ int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) { int32_t schMoveTaskToSuccList(SSchJob *pJob, SSchTask *pTask, bool *moved) { if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) { SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%d", SCH_GET_TASK_STATUS(pTask)); + } else { + SCH_TASK_DLOG("task removed from execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); } int32_t code = taosHashPut(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); @@ -564,15 +580,93 @@ int32_t schMoveTaskToExecList(SSchJob *pJob, SSchTask *pTask, bool *moved) { } -int32_t schTaskCheckAndSetRetry(SSchJob *job, SSchTask *task, int32_t errCode, bool *needRetry) { +int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry) { // TODO set retry or not based on task type/errCode/retry times/job status/available eps... - // TODO if needRetry, set task retry info - // TODO set condidateIdx - // TODO record failed but tried task *needRetry = false; return TSDB_CODE_SUCCESS; + + //TODO CHECK epList/condidateList + if (SCH_IS_DATA_SRC_TASK(pTask)) { + + } else { + int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs); + + if ((pTask->candidateIdx + 1) >= candidateNum) { + return TSDB_CODE_SUCCESS; + } + + ++pTask->candidateIdx; + } + + +} + +int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) { + atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); + + if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { + SCH_ERR_RET(schDecTaskFlowQuota(pJob, pTask)); + SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask)); + } + + if (SCH_IS_DATA_SRC_TASK(pTask)) { + SCH_SWITCH_EPSET(&pTask->plan->execNode); + } else { + ++pTask->candidateIdx; + } + + SCH_ERR_RET(schLaunchTask(pJob, pTask)); + + return TSDB_CODE_SUCCESS; +} + +int32_t schUpdateHbConnection(SQueryNodeEpId *epId, SSchHbTrans *trans) { + int32_t code = 0; + SSchHbTrans *hb = NULL; + + while (true) { + hb = taosHashGet(schMgmt.hbConnections, epId, sizeof(SQueryNodeEpId)); + if (NULL == hb) { + code = taosHashPut(schMgmt.hbConnections, epId, sizeof(SQueryNodeEpId), trans, sizeof(SSchHbTrans)); + if (code) { + if (HASH_NODE_EXIST(code)) { + continue; + } + + qError("taosHashPut hb trans failed, nodeId:%d, fqdn:%s, port:%d", epId->nodeId, epId->ep.fqdn, epId->ep.port); + SCH_ERR_RET(code); + } + + qDebug("hb connection updated, seqId:%" PRIx64 ", sId:%" PRIx64 ", nodeId:%d, fqdn:%s, port:%d, instance:%p, connection:%p", + trans->seqId, schMgmt.sId, epId->nodeId, epId->ep.fqdn, epId->ep.port, trans->trans.transInst, trans->trans.transHandle); + + return TSDB_CODE_SUCCESS; + } + + break; + } + + SCH_LOCK(SCH_WRITE, &hb->lock); + + if (hb->seqId >= trans->seqId) { + qDebug("hb trans seqId is old, seqId:%" PRId64 ", currentId:%" PRId64 ", nodeId:%d, fqdn:%s, port:%d", + trans->seqId, hb->seqId, epId->nodeId, epId->ep.fqdn, epId->ep.port); + + SCH_UNLOCK(SCH_WRITE, &hb->lock); + return TSDB_CODE_SUCCESS; + } + + hb->seqId = trans->seqId; + memcpy(&hb->trans, &trans->trans, sizeof(trans->trans)); + + SCH_UNLOCK(SCH_WRITE, &hb->lock); + + qDebug("hb connection updated, seqId:%" PRIx64 ", sId:%" PRIx64 ", nodeId:%d, fqdn:%s, port:%d, instance:%p, connection:%p", + trans->seqId, schMgmt.sId, epId->nodeId, epId->ep.fqdn, epId->ep.port, trans->trans.transInst, trans->trans.transHandle); + + return TSDB_CODE_SUCCESS; } int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCode) { @@ -588,14 +682,14 @@ int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCod } int32_t code = atomic_load_32(&pJob->errCode); - SCH_ERR_RET(code); - SCH_JOB_ELOG("job errCode is invalid, errCode:%d", code); + SCH_JOB_DLOG("job failed with error: %s", tstrerror(code)); + + SCH_RET(code); } - -// Note: no more error processing, handled in function internal +// Note: no more task error processing, handled in function internal int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode) { SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAILED, errCode)); } @@ -606,38 +700,8 @@ int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode) { } -// Note: no more error processing, handled in function internal -int32_t schFetchFromRemote(SSchJob *pJob) { - int32_t code = 0; - - if (atomic_val_compare_exchange_32(&pJob->remoteFetch, 0, 1) != 0) { - SCH_JOB_ELOG("prior fetching not finished, remoteFetch:%d", atomic_load_32(&pJob->remoteFetch)); - return TSDB_CODE_SUCCESS; - } - - void *res = atomic_load_ptr(&pJob->res); - if (res) { - atomic_val_compare_exchange_32(&pJob->remoteFetch, 1, 0); - - SCH_JOB_DLOG("res already fetched, res:%p", res); - return TSDB_CODE_SUCCESS; - } - - SCH_ERR_JRET(schBuildAndSendMsg(pJob, pJob->fetchTask, &pJob->resNode, TDMT_VND_FETCH)); - - return TSDB_CODE_SUCCESS; - -_return: - atomic_val_compare_exchange_32(&pJob->remoteFetch, 1, 0); - - schProcessOnJobFailure(pJob, code); - - return code; -} - - -// Note: no more error processing, handled in function internal +// Note: no more task error processing, handled in function internal int32_t schProcessOnJobPartialSuccess(SSchJob *pJob) { int32_t code = 0; @@ -655,9 +719,7 @@ int32_t schProcessOnJobPartialSuccess(SSchJob *pJob) { _return: - SCH_ERR_RET(schProcessOnJobFailure(pJob, code)); - - SCH_RET(code); + SCH_RET(schProcessOnJobFailure(pJob, code)); } int32_t schProcessOnDataFetched(SSchJob *job) { @@ -665,8 +727,16 @@ int32_t schProcessOnDataFetched(SSchJob *job) { tsem_post(&job->rspSem); } -// Note: no more error processing, handled in function internal +// Note: no more task error processing, handled in function internal int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) { + int8_t status = 0; + + if (schJobNeedToStop(pJob, &status)) { + SCH_TASK_DLOG("task failed not processed cause of job status, job status:%d", status); + + SCH_RET(atomic_load_32(&pJob->errCode)); + } + bool needRetry = false; bool moved = false; int32_t taskDone = 0; @@ -674,16 +744,16 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode)); - SCH_ERR_JRET(schTaskCheckAndSetRetry(pJob, pTask, errCode, &needRetry)); + SCH_ERR_JRET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry)); if (!needRetry) { SCH_TASK_ELOG("task failed and no more retry, code:%s", tstrerror(errCode)); if (SCH_GET_TASK_STATUS(pTask) == JOB_TASK_STATUS_EXECUTING) { - code = schMoveTaskToFailList(pJob, pTask, &moved); - if (code && moved) { - SCH_ERR_RET(errCode); - } + SCH_ERR_JRET(schMoveTaskToFailList(pJob, pTask, &moved)); + } else { + SCH_TASK_DLOG("task already done, no more failure process, status:%d", SCH_GET_TASK_STATUS(pTask)); + return TSDB_CODE_SUCCESS; } SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAILED); @@ -702,35 +772,31 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) } } } else { - // Note: no more error processing, already handled - SCH_ERR_RET(schLaunchTask(pJob, pTask)); + SCH_ERR_JRET(schHandleTaskRetry(pJob, pTask)); return TSDB_CODE_SUCCESS; } _return: - SCH_ERR_RET(schProcessOnJobFailure(pJob, errCode)); - - SCH_ERR_RET(errCode); + SCH_RET(schProcessOnJobFailure(pJob, errCode)); } - -// Note: no more error processing, handled in function internal +// Note: no more task error processing, handled in function internal int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { bool moved = false; int32_t code = 0; - SSchTask *pErrTask = pTask; - code = schMoveTaskToSuccList(pJob, pTask, &moved); - if (code && moved) { - SCH_ERR_RET(code); - } + SCH_TASK_DLOG("taskOnSuccess, status:%d", SCH_GET_TASK_STATUS(pTask)); + + SCH_ERR_JRET(schMoveTaskToSuccList(pJob, pTask, &moved)); SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_PARTIAL_SUCCEED); SCH_ERR_JRET(schRecordTaskSucceedNode(pJob, pTask)); - + + SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); + int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0; if (parentNum == 0) { int32_t taskDone = 0; @@ -759,14 +825,9 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { pJob->fetchTask = pTask; - code = schMoveTaskToExecList(pJob, pTask, &moved); - if (code && moved) { - SCH_ERR_RET(code); - } + SCH_ERR_JRET(schMoveTaskToExecList(pJob, pTask, &moved)); - SCH_ERR_RET(schProcessOnJobPartialSuccess(pJob)); - - return TSDB_CODE_SUCCESS; + SCH_RET(schProcessOnJobPartialSuccess(pJob)); } /* @@ -780,17 +841,15 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { for (int32_t i = 0; i < parentNum; ++i) { SSchTask *par = *(SSchTask **)taosArrayGet(pTask->parents, i); - pErrTask = par; - int32_t readyNum = atomic_add_fetch_32(&par->childReady, 1); SCH_LOCK(SCH_WRITE, &par->lock); - SDownstreamSource source = {.taskId = pTask->taskId, .schedId = schMgmt.sId, .addr = pTask->succeedAddr}; - qSetSubplanExecutionNode(par->plan, pTask->plan->id.templateId, &source); + SDownstreamSourceNode source = {.type = QUERY_NODE_DOWNSTREAM_SOURCE, .taskId = pTask->taskId, .schedId = schMgmt.sId, .addr = pTask->succeedAddr}; + qSetSubplanExecutionNode(par->plan, pTask->plan->id.groupId, &source); SCH_UNLOCK(SCH_WRITE, &par->lock); if (SCH_TASK_READY_TO_LUNCH(readyNum, par)) { - SCH_ERR_RET(schLaunchTask(pJob, par)); + SCH_ERR_RET(schLaunchTaskImpl(pJob, par)); } } @@ -798,22 +857,55 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { _return: - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pErrTask, code)); + SCH_RET(schProcessOnJobFailure(pJob, code)); +} + - SCH_ERR_RET(code); +// Note: no more error processing, handled in function internal +int32_t schFetchFromRemote(SSchJob *pJob) { + int32_t code = 0; + + if (atomic_val_compare_exchange_32(&pJob->remoteFetch, 0, 1) != 0) { + SCH_JOB_ELOG("prior fetching not finished, remoteFetch:%d", atomic_load_32(&pJob->remoteFetch)); + return TSDB_CODE_SUCCESS; + } + + void *res = atomic_load_ptr(&pJob->res); + if (res) { + atomic_val_compare_exchange_32(&pJob->remoteFetch, 1, 0); + + SCH_JOB_DLOG("res already fetched, res:%p", res); + return TSDB_CODE_SUCCESS; + } + + SCH_ERR_JRET(schBuildAndSendMsg(pJob, pJob->fetchTask, &pJob->resNode, TDMT_VND_FETCH)); + + return TSDB_CODE_SUCCESS; + +_return: + + atomic_val_compare_exchange_32(&pJob->remoteFetch, 1, 0); + + SCH_RET(schProcessOnTaskFailure(pJob, pJob->fetchTask, code)); } + +// Note: no more task error processing, handled in function internal int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, char *msg, int32_t msgSize, int32_t rspCode) { int32_t code = 0; + int8_t status = 0; + + if (schJobNeedToStop(pJob, &status)) { + SCH_TASK_ELOG("rsp not processed cause of job status, job status:%d", status); + + SCH_RET(atomic_load_32(&pJob->errCode)); + } SCH_ERR_JRET(schValidateTaskReceivedMsgType(pJob, pTask, msgType)); switch (msgType) { case TDMT_VND_CREATE_TABLE_RSP: { - if (rspCode != TSDB_CODE_SUCCESS) { - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, rspCode)); - } - + SCH_ERR_JRET(rspCode); SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask)); break; @@ -828,9 +920,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch pJob->resNumOfRows += rsp->affectedRows; #else - if (rspCode != TSDB_CODE_SUCCESS) { - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, rspCode)); - } + SCH_ERR_JRET(rspCode); SSubmitRsp *rsp = (SSubmitRsp *)msg; if (rsp) { @@ -845,9 +935,11 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch case TDMT_VND_QUERY_RSP: { SQueryTableRsp *rsp = (SQueryTableRsp *)msg; - if (rspCode != TSDB_CODE_SUCCESS || NULL == msg || rsp->code != TSDB_CODE_SUCCESS) { - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, rspCode)); + SCH_ERR_JRET(rspCode); + if (NULL == msg) { + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } + SCH_ERR_JRET(rsp->code); SCH_ERR_JRET(schBuildAndSendMsg(pJob, pTask, NULL, TDMT_VND_RES_READY)); @@ -856,9 +948,11 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch case TDMT_VND_RES_READY_RSP: { SResReadyRsp *rsp = (SResReadyRsp *)msg; - if (rspCode != TSDB_CODE_SUCCESS || NULL == msg || rsp->code != TSDB_CODE_SUCCESS) { - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, rspCode)); + SCH_ERR_JRET(rspCode); + if (NULL == msg) { + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } + SCH_ERR_JRET(rsp->code); SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask)); @@ -867,14 +961,15 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch case TDMT_VND_FETCH_RSP: { SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)msg; - if (rspCode != TSDB_CODE_SUCCESS || NULL == msg) { - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, rspCode)); + SCH_ERR_JRET(rspCode); + if (NULL == msg) { + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } - + if (pJob->res) { SCH_TASK_ELOG("got fetch rsp while res already exists, res:%p", pJob->res); tfree(rsp); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); } atomic_store_ptr(&pJob->res, rsp); @@ -886,7 +981,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch SCH_TASK_DLOG("got fetch rsp, rows:%d, complete:%d", htonl(rsp->numOfRows), rsp->completed); - SCH_ERR_JRET(schProcessOnDataFetched(pJob)); + schProcessOnDataFetched(pJob); break; } case TDMT_VND_DROP_TASK_RSP: { @@ -904,9 +999,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch _return: - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, code)); - - SCH_RET(code); + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); } @@ -915,7 +1008,7 @@ int32_t schHandleCallback(void* param, const SDataBuf* pMsg, int32_t msgType, in SSchCallbackParam *pParam = (SSchCallbackParam *)param; SSchTask *pTask = NULL; - SSchJob *pJob = taosAcquireRef(schMgmt.jobRef, pParam->refId); + SSchJob *pJob = schAcquireJob(pParam->refId); if (NULL == pJob) { qError("QID:0x%" PRIx64 ",TID:0x%" PRIx64 "taosAcquireRef job failed, may be dropped, refId:%" PRIx64, pParam->queryId, pParam->taskId, pParam->refId); SCH_ERR_JRET(TSDB_CODE_QRY_JOB_FREED); @@ -942,7 +1035,7 @@ int32_t schHandleCallback(void* param, const SDataBuf* pMsg, int32_t msgType, in _return: if (pJob) { - taosReleaseRef(schMgmt.jobRef, pParam->refId); + schReleaseJob(pParam->refId); } tfree(param); @@ -974,6 +1067,55 @@ int32_t schHandleDropCallback(void* param, const SDataBuf* pMsg, int32_t code) { qDebug("QID:%"PRIx64",TID:%"PRIx64" drop task rsp received, code:%x", pParam->queryId, pParam->taskId, code); } + +int32_t schHandleHbCallback(void* param, const SDataBuf* pMsg, int32_t code) { + if (code) { + qError("hb rsp error:%s", tstrerror(code)); + SCH_ERR_RET(code); + } + + SSchedulerHbRsp rsp = {0}; + + SSchCallbackParam *pParam = (SSchCallbackParam *)param; + + if (tDeserializeSSchedulerHbRsp(pMsg->pData, pMsg->len, &rsp)) { + qError("invalid hb rsp msg, size:%d", pMsg->len); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (rsp.seqId != (uint64_t)-1) { + SSchHbTrans trans = {0}; + trans.seqId = rsp.seqId; + trans.trans.transInst = pParam->transport; + trans.trans.transHandle = pMsg->handle; + + SCH_RET(schUpdateHbConnection(&rsp.epId, &trans)); + } + + int32_t taskNum = (int32_t)taosArrayGetSize(rsp.taskStatus); + for (int32_t i = 0; i < taskNum; ++i) { + STaskStatus *taskStatus = taosArrayGet(rsp.taskStatus, i); + + SSchJob *pJob = schAcquireJob(taskStatus->refId); + if (NULL == pJob) { + qWarn("job not found, refId:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64, taskStatus->refId, taskStatus->queryId, taskStatus->taskId); + //TODO DROP TASK FROM SERVER!!!! + continue; + } + + // TODO + + schReleaseJob(taskStatus->refId); + } + +_return: + + tFreeSSchedulerHbRsp(&rsp); + + SCH_RET(code); +} + + int32_t schGetCallbackFp(int32_t msgType, __async_send_cb_fn_t *fp) { switch (msgType) { case TDMT_VND_CREATE_TABLE: @@ -994,6 +1136,9 @@ int32_t schGetCallbackFp(int32_t msgType, __async_send_cb_fn_t *fp) { case TDMT_VND_DROP_TASK: *fp = schHandleDropCallback; break; + case TDMT_VND_QUERY_HEARTBEAT: + *fp = schHandleHbCallback; + break; default: qError("unknown msg type for callback, msgType:%d", msgType); SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR); @@ -1025,7 +1170,8 @@ int32_t schAsyncSendMsg(SSchJob *pJob, SSchTask *pTask, void *transport, SEpSet* param->queryId = pJob->queryId; param->refId = pJob->refId; - param->taskId = pTask->taskId; + param->taskId = SCH_TASK_ID(pTask); + param->transport = trans->transInst; pMsgSendInfo->param = param; @@ -1057,7 +1203,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t code = 0; bool isCandidateAddr = false; if (NULL == addr) { - addr = taosArrayGet(pTask->candidateAddrs, atomic_load_8(&pTask->candidateIdx)); + addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); isCandidateAddr = true; } @@ -1092,6 +1238,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, pMsg->sId = htobe64(schMgmt.sId); pMsg->queryId = htobe64(pJob->queryId); pMsg->taskId = htobe64(pTask->taskId); + pMsg->refId = htobe64(pJob->refId); pMsg->taskType = TASK_TYPE_TEMP; pMsg->phyLen = htonl(pTask->msgLen); pMsg->sqlLen = htonl(len); @@ -1150,6 +1297,30 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, pMsg->sId = htobe64(schMgmt.sId); pMsg->queryId = htobe64(pJob->queryId); pMsg->taskId = htobe64(pTask->taskId); + pMsg->refId = htobe64(pJob->refId); + break; + } + case TDMT_VND_QUERY_HEARTBEAT: { + SSchedulerHbReq req = {0}; + req.sId = schMgmt.sId; + req.header.vgId = addr->nodeId; + req.epId.nodeId = addr->nodeId; + memcpy(&req.epId.ep, SCH_GET_CUR_EP(addr), sizeof(SEp)); + + msgSize = tSerializeSSchedulerHbReq(NULL, 0, &req); + if (msgSize < 0) { + SCH_JOB_ELOG("tSerializeSSchedulerHbReq hbReq failed, size:%d", msgSize); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + msg = calloc(1, msgSize); + if (NULL == msg) { + SCH_JOB_ELOG("calloc %d failed", msgSize); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + if (tSerializeSSchedulerHbReq(msg, msgSize, &req) < 0) { + SCH_JOB_ELOG("tSerializeSSchedulerHbReq hbReq failed, size:%d", msgSize); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } break; } default: @@ -1158,9 +1329,9 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, break; } - atomic_store_32(&pTask->lastMsgType, msgType); + SCH_SET_TASK_LASTMSG_TYPE(pTask, msgType); - SSchTrans trans = {.transInst = pJob->transport, .transHandle = pTask->handle}; + SSchTrans trans = {.transInst = pJob->transport, .transHandle = pTask ? pTask->handle : NULL}; SCH_ERR_JRET(schAsyncSendMsg(pJob, pTask, &trans, &epSet, msgType, msg, msgSize)); if (isCandidateAddr) { @@ -1171,74 +1342,111 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, _return: - atomic_store_32(&pTask->lastMsgType, -1); - + SCH_SET_TASK_LASTMSG_TYPE(pTask, -1); + tfree(msg); SCH_RET(code); } -static FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) { - int8_t status = SCH_GET_JOB_STATUS(pJob); - if (pStatus) { - *pStatus = status; +int32_t schEnsureHbConnection(SSchJob *pJob, SSchTask *pTask) { + SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); + SQueryNodeEpId epId = {0}; + + epId.nodeId = addr->nodeId; + memcpy(&epId.ep, SCH_GET_CUR_EP(addr), sizeof(SEp)); + + SSchHbTrans *hb = taosHashGet(schMgmt.hbConnections, &epId, sizeof(SQueryNodeEpId)); + if (NULL == hb) { + SCH_ERR_RET(schBuildAndSendMsg(pJob, NULL, addr, TDMT_VND_QUERY_HEARTBEAT)); } - return (status == JOB_TASK_STATUS_FAILED || status == JOB_TASK_STATUS_CANCELLED - || status == JOB_TASK_STATUS_CANCELLING || status == JOB_TASK_STATUS_DROPPING); + return TSDB_CODE_SUCCESS; } - -// Note: no more error processing, handled in function internal -int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) { +int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) { int8_t status = 0; int32_t code = 0; + + atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1); if (schJobNeedToStop(pJob, &status)) { - SCH_TASK_ELOG("no need to launch task cause of job status, job status:%d", status); + SCH_TASK_DLOG("no need to launch task cause of job status, job status:%d", status); - code = atomic_load_32(&pJob->errCode); - SCH_ERR_RET(code); - SCH_RET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_RET(atomic_load_32(&pJob->errCode)); } SSubplan *plan = pTask->plan; if (NULL == pTask->msg) { // TODO add more detailed reason for failure code = qSubPlanToString(plan, &pTask->msg, &pTask->msgLen); - if (TSDB_CODE_SUCCESS != code || NULL == pTask->msg || pTask->msgLen <= 0) { + if (TSDB_CODE_SUCCESS != code) { SCH_TASK_ELOG("failed to create physical plan, code:%s, msg:%p, len:%d", tstrerror(code), pTask->msg, pTask->msgLen); - SCH_ERR_JRET(code); + SCH_ERR_RET(code); } else { SCH_TASK_DLOG("physical plan len:%d, %s", pTask->msgLen, pTask->msg); } } - SCH_ERR_JRET(schSetTaskCandidateAddrs(pJob, pTask)); + SCH_ERR_RET(schSetTaskCandidateAddrs(pJob, pTask)); // NOTE: race condition: the task should be put into the hash table before send msg to server if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXECUTING) { - SCH_ERR_JRET(schPushTaskToExecList(pJob, pTask)); + SCH_ERR_RET(schPushTaskToExecList(pJob, pTask)); SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXECUTING); } - SCH_ERR_JRET(schBuildAndSendMsg(pJob, pTask, NULL, plan->msgType)); + if (SCH_IS_QUERY_JOB(pJob)) { + SCH_ERR_RET(schEnsureHbConnection(pJob, pTask)); + } + + SCH_ERR_RET(schBuildAndSendMsg(pJob, pTask, NULL, plan->msgType)); + + return TSDB_CODE_SUCCESS; +} + +// Note: no more error processing, handled in function internal +int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) { + bool enough = false; + int32_t code = 0; + + if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { + SCH_ERR_JRET(schCheckIncTaskFlowQuota(pJob, pTask, &enough)); + + if (enough) { + SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); + } + } else { + SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); + } + return TSDB_CODE_SUCCESS; _return: - SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, code)); - SCH_RET(code); -} -int32_t schLaunchJob(SSchJob *pJob) { - SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx); + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); +} - SCH_ERR_RET(schCheckAndUpdateJobStatus(pJob, JOB_TASK_STATUS_EXECUTING)); - +int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) { for (int32_t i = 0; i < level->taskNum; ++i) { SSchTask *pTask = taosArrayGet(level->subTasks, i); + SCH_ERR_RET(schLaunchTask(pJob, pTask)); } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t schLaunchJob(SSchJob *pJob) { + SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx); + SCH_ERR_RET(schCheckAndUpdateJobStatus(pJob, JOB_TASK_STATUS_EXECUTING)); + + SCH_ERR_RET(schCheckJobNeedFlowCtrl(pJob, level)); + + SCH_ERR_RET(schLaunchLevelTasks(pJob, level)); + return TSDB_CODE_SUCCESS; } @@ -1284,7 +1492,6 @@ void schDropJobAllTasks(SSchJob *pJob) { schDropTaskInHashList(pJob, pJob->failTasks); } - int32_t schCancelJob(SSchJob *pJob) { //TODO @@ -1313,6 +1520,8 @@ void schFreeJobImpl(void *job) { for(int32_t i = 0; i < numOfLevels; ++i) { SSchLevel *pLevel = taosArrayGet(pJob->levels, i); + schFreeFlowCtrl(pLevel); + int32_t numOfTasks = taosArrayGetSize(pLevel->subTasks); for(int32_t j = 0; j < numOfTasks; ++j) { SSchTask* pTask = taosArrayGet(pLevel->subTasks, j); @@ -1337,7 +1546,7 @@ void schFreeJobImpl(void *job) { } -static int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryDag* pDag, int64_t *job, const char* sql, bool syncSchedule) { +static int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryPlan* pDag, int64_t *job, const char* sql, bool syncSchedule) { qDebug("QID:0x%"PRIx64" job started", pDag->queryId); if (pNodeList == NULL || (pNodeList && taosArrayGetSize(pNodeList) <= 0)) { @@ -1392,7 +1601,7 @@ static int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryDag* pDa pJob->status = JOB_TASK_STATUS_NOT_START; SCH_ERR_JRET(schLaunchJob(pJob)); - taosAcquireRef(schMgmt.jobRef, pJob->refId); + schAcquireJob(pJob->refId); *job = pJob->refId; @@ -1403,7 +1612,7 @@ static int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryDag* pDa SCH_JOB_DLOG("job exec done, job status:%d", SCH_GET_JOB_STATUS(pJob)); - taosReleaseRef(schMgmt.jobRef, pJob->refId); + schReleaseJob(pJob->refId); return TSDB_CODE_SUCCESS; @@ -1424,15 +1633,25 @@ int32_t schedulerInit(SSchedulerCfg *cfg) { schMgmt.cfg = *cfg; if (schMgmt.cfg.maxJobNum == 0) { - schMgmt.cfg.maxJobNum = SCHEDULE_DEFAULT_JOB_NUMBER; + schMgmt.cfg.maxJobNum = SCHEDULE_DEFAULT_MAX_JOB_NUM; + } + if (schMgmt.cfg.maxNodeTableNum <= 0) { + schMgmt.cfg.maxNodeTableNum = SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM; } } else { - schMgmt.cfg.maxJobNum = SCHEDULE_DEFAULT_JOB_NUMBER; + schMgmt.cfg.maxJobNum = SCHEDULE_DEFAULT_MAX_JOB_NUM; + schMgmt.cfg.maxNodeTableNum = SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM; } schMgmt.jobRef = taosOpenRef(schMgmt.cfg.maxJobNum, schFreeJobImpl); if (schMgmt.jobRef < 0) { - qError("init schduler jobs failed, num:%u", schMgmt.cfg.maxJobNum); + qError("init schduler jobRef failed, num:%u", schMgmt.cfg.maxJobNum); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + schMgmt.hbConnections = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == schMgmt.hbConnections) { + qError("taosHashInit hb connections failed"); SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); } @@ -1446,22 +1665,22 @@ int32_t schedulerInit(SSchedulerCfg *cfg) { return TSDB_CODE_SUCCESS; } -int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryDag* pDag, int64_t *pJob, const char* sql, SQueryResult *pRes) { +int32_t schedulerExecJob(void *transport, SArray *nodeList, SQueryPlan* pDag, int64_t *pJob, const char* sql, SQueryResult *pRes) { if (NULL == transport || NULL == pDag || NULL == pDag->pSubplans || NULL == pJob || NULL == pRes) { SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } SCH_ERR_RET(schExecJobImpl(transport, nodeList, pDag, pJob, sql, true)); - SSchJob *job = taosAcquireRef(schMgmt.jobRef, *pJob); + SSchJob *job = schAcquireJob(*pJob); pRes->code = atomic_load_32(&job->errCode); pRes->numOfRows = job->resNumOfRows; - taosReleaseRef(schMgmt.jobRef, *pJob); + schReleaseJob(*pJob); return TSDB_CODE_SUCCESS; } -int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryDag* pDag, const char* sql, int64_t *pJob) { +int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryPlan* pDag, const char* sql, int64_t *pJob) { if (NULL == transport || NULL == pDag || NULL == pDag->pSubplans || NULL == pJob) { SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } @@ -1471,19 +1690,19 @@ int32_t schedulerAsyncExecJob(void *transport, SArray *pNodeList, SQueryDag* pDa return TSDB_CODE_SUCCESS; } -int32_t schedulerConvertDagToTaskList(SQueryDag* pDag, SArray **pTasks) { - if (NULL == pDag || pDag->numOfSubplans <= 0 || taosArrayGetSize(pDag->pSubplans) == 0) { +int32_t schedulerConvertDagToTaskList(SQueryPlan* pDag, SArray **pTasks) { + if (NULL == pDag || pDag->numOfSubplans <= 0 || LIST_LENGTH(pDag->pSubplans) == 0) { SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - int32_t levelNum = taosArrayGetSize(pDag->pSubplans); + int32_t levelNum = LIST_LENGTH(pDag->pSubplans); if (1 != levelNum) { qError("invalid level num: %d", levelNum); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - SArray *plans = taosArrayGet(pDag->pSubplans, 0); - int32_t taskNum = taosArrayGetSize(plans); + SNodeListNode *plans = (SNodeListNode*)nodesListGetNode(pDag->pSubplans, 0); + int32_t taskNum = LIST_LENGTH(plans->pNodeList); if (taskNum <= 0) { qError("invalid task num: %d", taskNum); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); @@ -1501,11 +1720,11 @@ int32_t schedulerConvertDagToTaskList(SQueryDag* pDag, SArray **pTasks) { int32_t code = 0; for (int32_t i = 0; i < taskNum; ++i) { - SSubplan *plan = taosArrayGetP(plans, i); + SSubplan *plan = (SSubplan*)nodesListGetNode(plans->pNodeList, i); tInfo.addr = plan->execNode; code = qSubPlanToString(plan, &msg, &msgLen); - if (TSDB_CODE_SUCCESS != code || NULL == msg || msgLen <= 0) { + if (TSDB_CODE_SUCCESS != code) { qError("subplanToString error, code:%x, msg:%p, len:%d", code, msg, msgLen); SCH_ERR_JRET(code); } @@ -1599,7 +1818,7 @@ int32_t schedulerFetchRows(int64_t job, void** pData) { } int32_t code = 0; - SSchJob *pJob = taosAcquireRef(schMgmt.jobRef, job); + SSchJob *pJob = schAcquireJob(job); if (NULL == pJob) { qError("acquire job from jobRef list failed, may be dropped, refId:%" PRIx64, job); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); @@ -1608,19 +1827,19 @@ int32_t schedulerFetchRows(int64_t job, void** pData) { int8_t status = SCH_GET_JOB_STATUS(pJob); if (status == JOB_TASK_STATUS_DROPPING) { SCH_JOB_ELOG("job is dropping, status:%d", status); - taosReleaseRef(schMgmt.jobRef, job); + schReleaseJob(job); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } - if (!SCH_JOB_NEED_FETCH(&pJob->attr)) { + if (!SCH_JOB_NEED_FETCH(pJob)) { SCH_JOB_ELOG("no need to fetch data, status:%d", SCH_GET_JOB_STATUS(pJob)); - taosReleaseRef(schMgmt.jobRef, job); + schReleaseJob(job); SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR); } if (atomic_val_compare_exchange_8(&pJob->userFetch, 0, 1) != 0) { SCH_JOB_ELOG("prior fetching not finished, userFetch:%d", atomic_load_8(&pJob->userFetch)); - taosReleaseRef(schMgmt.jobRef, job); + schReleaseJob(job); SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR); } @@ -1628,7 +1847,7 @@ int32_t schedulerFetchRows(int64_t job, void** pData) { SCH_JOB_ELOG("job failed or dropping, status:%d", status); SCH_ERR_JRET(atomic_load_32(&pJob->errCode)); } else if (status == JOB_TASK_STATUS_SUCCEED) { - SCH_JOB_ELOG("job already succeed, status:%d", status); + SCH_JOB_DLOG("job already succeed, status:%d", status); goto _return; } else if (status == JOB_TASK_STATUS_PARTIAL_SUCCEED) { SCH_ERR_JRET(schFetchFromRemote(pJob)); @@ -1673,13 +1892,13 @@ _return: atomic_val_compare_exchange_8(&pJob->userFetch, 1, 0); - taosReleaseRef(schMgmt.jobRef, job); + schReleaseJob(job); SCH_RET(code); } int32_t scheduleCancelJob(int64_t job) { - SSchJob *pJob = taosAcquireRef(schMgmt.jobRef, job); + SSchJob *pJob = schAcquireJob(job); if (NULL == pJob) { qError("acquire job from jobRef list failed, may be dropped, refId:%" PRIx64, job); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); @@ -1687,13 +1906,13 @@ int32_t scheduleCancelJob(int64_t job) { int32_t code = schCancelJob(pJob); - taosReleaseRef(schMgmt.jobRef, job); + schReleaseJob(job); SCH_RET(code); } void schedulerFreeJob(int64_t job) { - SSchJob *pJob = taosAcquireRef(schMgmt.jobRef, job); + SSchJob *pJob = schAcquireJob(job); if (NULL == pJob) { qError("acquire job from jobRef list failed, may be dropped, refId:%" PRIx64, job); return; @@ -1708,6 +1927,8 @@ void schedulerFreeJob(int64_t job) { if (taosRemoveRef(schMgmt.jobRef, job)) { SCH_JOB_ELOG("remove job from job list failed, refId:%" PRIx64, job); } + + schReleaseJob(job); } void schedulerFreeTaskList(SArray *taskList) { diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp index 8ed963d875700353fc805b84d60c3e5530e058f7..376ed1e2bc1f5015bd5c8c2466ac77877cf53ce1 100644 --- a/source/libs/scheduler/test/schedulerTests.cpp +++ b/source/libs/scheduler/test/schedulerTests.cpp @@ -86,22 +86,22 @@ void schtInitLogFile() { } -void schtBuildQueryDag(SQueryDag *dag) { +void schtBuildQueryDag(SQueryPlan *dag) { uint64_t qId = schtQueryId; dag->queryId = qId; dag->numOfSubplans = 2; - dag->pSubplans = taosArrayInit(dag->numOfSubplans, POINTER_BYTES); - SArray *scan = taosArrayInit(1, POINTER_BYTES); - SArray *merge = taosArrayInit(1, POINTER_BYTES); + dag->pSubplans = nodesMakeList(); + SNodeListNode *scan = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); + SNodeListNode *merge = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); SSubplan *scanPlan = (SSubplan *)calloc(1, sizeof(SSubplan)); SSubplan *mergePlan = (SSubplan *)calloc(1, sizeof(SSubplan)); scanPlan->id.queryId = qId; - scanPlan->id.templateId = 0x0000000000000002; + scanPlan->id.groupId = 0x0000000000000002; scanPlan->id.subplanId = 0x0000000000000003; - scanPlan->type = QUERY_TYPE_SCAN; + scanPlan->subplanType = SUBPLAN_TYPE_SCAN; scanPlan->execNode.nodeId = 1; scanPlan->execNode.epSet.inUse = 0; @@ -109,51 +109,116 @@ void schtBuildQueryDag(SQueryDag *dag) { scanPlan->pChildren = NULL; scanPlan->level = 1; - scanPlan->pParents = taosArrayInit(1, POINTER_BYTES); - scanPlan->pNode = (SPhyNode*)calloc(1, sizeof(SPhyNode)); + scanPlan->pParents = nodesMakeList(); + scanPlan->pNode = (SPhysiNode*)calloc(1, sizeof(SPhysiNode)); scanPlan->msgType = TDMT_VND_QUERY; mergePlan->id.queryId = qId; - mergePlan->id.templateId = schtMergeTemplateId; - mergePlan->id.subplanId = 0x5555555555; - mergePlan->type = QUERY_TYPE_MERGE; + mergePlan->id.groupId = schtMergeTemplateId; + mergePlan->id.subplanId = 0x5555; + mergePlan->subplanType = SUBPLAN_TYPE_MERGE; mergePlan->level = 0; mergePlan->execNode.epSet.numOfEps = 0; - mergePlan->pChildren = taosArrayInit(1, POINTER_BYTES); + mergePlan->pChildren = nodesMakeList(); mergePlan->pParents = NULL; - mergePlan->pNode = (SPhyNode*)calloc(1, sizeof(SPhyNode)); + mergePlan->pNode = (SPhysiNode*)calloc(1, sizeof(SPhysiNode)); mergePlan->msgType = TDMT_VND_QUERY; - SSubplan *mergePointer = (SSubplan *)taosArrayPush(merge, &mergePlan); - SSubplan *scanPointer = (SSubplan *)taosArrayPush(scan, &scanPlan); + merge->pNodeList = nodesMakeList(); + scan->pNodeList = nodesMakeList(); - taosArrayPush(mergePlan->pChildren, &scanPlan); - taosArrayPush(scanPlan->pParents, &mergePlan); + nodesListAppend(merge->pNodeList, (SNode*)mergePlan); + nodesListAppend(scan->pNodeList, (SNode*)scanPlan); - taosArrayPush(dag->pSubplans, &merge); - taosArrayPush(dag->pSubplans, &scan); + nodesListAppend(mergePlan->pChildren, (SNode*)scanPlan); + nodesListAppend(scanPlan->pParents, (SNode*)mergePlan); + + nodesListAppend(dag->pSubplans, (SNode*)merge); + nodesListAppend(dag->pSubplans, (SNode*)scan); +} + +void schtBuildQueryFlowCtrlDag(SQueryPlan *dag) { + uint64_t qId = schtQueryId; + int32_t scanPlanNum = 20; + + dag->queryId = qId; + dag->numOfSubplans = 2; + dag->pSubplans = nodesMakeList(); + SNodeListNode *scan = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); + SNodeListNode *merge = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); + + SSubplan *scanPlan = (SSubplan *)calloc(scanPlanNum, sizeof(SSubplan)); + SSubplan *mergePlan = (SSubplan *)calloc(1, sizeof(SSubplan)); + + merge->pNodeList = nodesMakeList(); + scan->pNodeList = nodesMakeList(); + + mergePlan->pChildren = nodesMakeList(); + + for (int32_t i = 0; i < scanPlanNum; ++i) { + scanPlan[i].id.queryId = qId; + scanPlan[i].id.groupId = 0x0000000000000002; + scanPlan[i].id.subplanId = 0x0000000000000003 + i; + scanPlan[i].subplanType = SUBPLAN_TYPE_SCAN; + + scanPlan[i].execNode.nodeId = 1 + i; + scanPlan[i].execNode.epSet.inUse = 0; + scanPlan[i].execNodeStat.tableNum = taosRand() % 30; + addEpIntoEpSet(&scanPlan[i].execNode.epSet, "ep0", 6030); + addEpIntoEpSet(&scanPlan[i].execNode.epSet, "ep1", 6030); + addEpIntoEpSet(&scanPlan[i].execNode.epSet, "ep2", 6030); + scanPlan[i].execNode.epSet.inUse = taosRand() % 3; + + scanPlan[i].pChildren = NULL; + scanPlan[i].level = 1; + scanPlan[i].pParents = nodesMakeList(); + scanPlan[i].pNode = (SPhysiNode*)calloc(1, sizeof(SPhysiNode)); + scanPlan[i].msgType = TDMT_VND_QUERY; + + nodesListAppend(scanPlan[i].pParents, (SNode*)mergePlan); + nodesListAppend(mergePlan->pChildren, (SNode*)(scanPlan + i)); + + nodesListAppend(scan->pNodeList, (SNode*)(scanPlan + i)); + } + + mergePlan->id.queryId = qId; + mergePlan->id.groupId = schtMergeTemplateId; + mergePlan->id.subplanId = 0x5555; + mergePlan->subplanType = SUBPLAN_TYPE_MERGE; + mergePlan->level = 0; + mergePlan->execNode.epSet.numOfEps = 0; + + mergePlan->pParents = NULL; + mergePlan->pNode = (SPhysiNode*)calloc(1, sizeof(SPhysiNode)); + mergePlan->msgType = TDMT_VND_QUERY; + + nodesListAppend(merge->pNodeList, (SNode*)mergePlan); + + nodesListAppend(dag->pSubplans, (SNode*)merge); + nodesListAppend(dag->pSubplans, (SNode*)scan); } -void schtFreeQueryDag(SQueryDag *dag) { + +void schtFreeQueryDag(SQueryPlan *dag) { } -void schtBuildInsertDag(SQueryDag *dag) { +void schtBuildInsertDag(SQueryPlan *dag) { uint64_t qId = 0x0000000000000002; dag->queryId = qId; dag->numOfSubplans = 2; - dag->pSubplans = taosArrayInit(1, POINTER_BYTES); - SArray *inserta = taosArrayInit(dag->numOfSubplans, POINTER_BYTES); + dag->pSubplans = nodesMakeList(); + SNodeListNode *inserta = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); SSubplan *insertPlan = (SSubplan *)calloc(2, sizeof(SSubplan)); insertPlan[0].id.queryId = qId; - insertPlan[0].id.templateId = 0x0000000000000003; + insertPlan[0].id.groupId = 0x0000000000000003; insertPlan[0].id.subplanId = 0x0000000000000004; - insertPlan[0].type = QUERY_TYPE_MODIFY; + insertPlan[0].subplanType = SUBPLAN_TYPE_MODIFY; insertPlan[0].level = 0; insertPlan[0].execNode.nodeId = 1; @@ -163,13 +228,13 @@ void schtBuildInsertDag(SQueryDag *dag) { insertPlan[0].pChildren = NULL; insertPlan[0].pParents = NULL; insertPlan[0].pNode = NULL; - insertPlan[0].pDataSink = (SDataSink*)calloc(1, sizeof(SDataSink)); + insertPlan[0].pDataSink = (SDataSinkNode*)calloc(1, sizeof(SDataSinkNode)); insertPlan[0].msgType = TDMT_VND_SUBMIT; insertPlan[1].id.queryId = qId; - insertPlan[1].id.templateId = 0x0000000000000003; + insertPlan[1].id.groupId = 0x0000000000000003; insertPlan[1].id.subplanId = 0x0000000000000005; - insertPlan[1].type = QUERY_TYPE_MODIFY; + insertPlan[1].subplanType = SUBPLAN_TYPE_MODIFY; insertPlan[1].level = 0; insertPlan[1].execNode.nodeId = 1; @@ -179,14 +244,16 @@ void schtBuildInsertDag(SQueryDag *dag) { insertPlan[1].pChildren = NULL; insertPlan[1].pParents = NULL; insertPlan[1].pNode = NULL; - insertPlan[1].pDataSink = (SDataSink*)calloc(1, sizeof(SDataSink)); + insertPlan[1].pDataSink = (SDataSinkNode*)calloc(1, sizeof(SDataSinkNode)); insertPlan[1].msgType = TDMT_VND_SUBMIT; - taosArrayPush(inserta, &insertPlan); + inserta->pNodeList = nodesMakeList(); + + nodesListAppend(inserta->pNodeList, (SNode*)insertPlan); insertPlan += 1; - taosArrayPush(inserta, &insertPlan); + nodesListAppend(inserta->pNodeList, (SNode*)insertPlan); - taosArrayPush(dag->pSubplans, &inserta); + nodesListAppend(dag->pSubplans, (SNode*)inserta); } @@ -196,7 +263,7 @@ int32_t schtPlanToString(const SSubplan *subplan, char** str, int32_t* len) { return 0; } -void schtExecNode(SSubplan* subplan, uint64_t templateId, SQueryNodeAddr* ep) { +void schtExecNode(SSubplan* subplan, uint64_t groupId, SQueryNodeAddr* ep) { } @@ -278,7 +345,7 @@ void *schtSendRsp(void *param) { break; } - usleep(1000); + taosMsleep(1); } pJob = schAcquireJob(job); @@ -303,7 +370,7 @@ void *schtCreateFetchRspThread(void *param) { int64_t job = *(int64_t *)param; SSchJob* pJob = schAcquireJob(job); - sleep(1); + taosSsleep(1); int32_t code = 0; SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)calloc(1, sizeof(SRetrieveTableRsp)); @@ -327,7 +394,7 @@ void *schtFetchRspThread(void *aa) { continue; } - usleep(1); + taosUsleep(1); param = (SSchCallbackParam *)calloc(1, sizeof(*param)); @@ -368,7 +435,7 @@ void* schtRunJobThread(void *aa) { char *dbname = "1.db1"; char *tablename = "table1"; SVgroupInfo vgInfo = {0}; - SQueryDag dag = {0}; + SQueryPlan dag; schtInitLogFile(); @@ -532,7 +599,7 @@ void* schtRunJobThread(void *aa) { void* schtFreeJobThread(void *aa) { while (!schtTestStop) { - usleep(rand() % 100); + taosUsleep(taosRand() % 100); schtFreeQueryJob(1); } } @@ -547,9 +614,9 @@ TEST(queryTest, normalCase) { char *tablename = "table1"; SVgroupInfo vgInfo = {0}; int64_t job = 0; - SQueryDag dag = {0}; + SQueryPlan dag; - schtInitLogFile(); + memset(&dag, 0, sizeof(dag)); SArray *qnodeList = taosArrayInit(1, sizeof(SEp)); @@ -646,6 +713,101 @@ TEST(queryTest, normalCase) { schedulerDestroy(); } +TEST(queryTest, flowCtrlCase) { + void *mockPointer = (void *)0x1; + char *clusterId = "cluster1"; + char *dbname = "1.db1"; + char *tablename = "table1"; + SVgroupInfo vgInfo = {0}; + int64_t job = 0; + SQueryPlan dag; + + schtInitLogFile(); + + taosSeedRand(taosGetTimestampSec()); + + SArray *qnodeList = taosArrayInit(1, sizeof(SEp)); + + SEp qnodeAddr = {0}; + strcpy(qnodeAddr.fqdn, "qnode0.ep"); + qnodeAddr.port = 6031; + taosArrayPush(qnodeList, &qnodeAddr); + + int32_t code = schedulerInit(NULL); + ASSERT_EQ(code, 0); + + schtBuildQueryFlowCtrlDag(&dag); + + schtSetPlanToString(); + schtSetExecNode(); + schtSetAsyncSendMsgToServer(); + + code = schedulerAsyncExecJob(mockPointer, qnodeList, &dag, "select * from tb", &job); + ASSERT_EQ(code, 0); + + + SSchJob *pJob = schAcquireJob(job); + + bool queryDone = false; + + while (!queryDone) { + void *pIter = taosHashIterate(pJob->execTasks, NULL); + if (NULL == pIter) { + break; + } + + while (pIter) { + SSchTask *task = *(SSchTask **)pIter; + + taosHashCancelIterate(pJob->execTasks, pIter); + + if (task->lastMsgType == TDMT_VND_QUERY) { + SQueryTableRsp rsp = {0}; + code = schHandleResponseMsg(pJob, task, TDMT_VND_QUERY_RSP, (char *)&rsp, sizeof(rsp), 0); + + ASSERT_EQ(code, 0); + } else if (task->lastMsgType == TDMT_VND_RES_READY) { + SResReadyRsp rsp = {0}; + code = schHandleResponseMsg(pJob, task, TDMT_VND_RES_READY_RSP, (char *)&rsp, sizeof(rsp), 0); + ASSERT_EQ(code, 0); + } else { + queryDone = true; + break; + } + + pIter = NULL; + } + } + + + pthread_attr_t thattr; + pthread_attr_init(&thattr); + + pthread_t thread1; + pthread_create(&(thread1), &thattr, schtCreateFetchRspThread, &job); + + void *data = NULL; + code = schedulerFetchRows(job, &data); + ASSERT_EQ(code, 0); + + SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data; + ASSERT_EQ(pRsp->completed, 1); + ASSERT_EQ(pRsp->numOfRows, 10); + tfree(data); + + data = NULL; + code = schedulerFetchRows(job, &data); + ASSERT_EQ(code, 0); + ASSERT_TRUE(data == NULL); + + schReleaseJob(job); + + schedulerFreeJob(job); + + schtFreeQueryDag(&dag); + + schedulerDestroy(); +} TEST(insertTest, normalCase) { @@ -654,11 +816,9 @@ TEST(insertTest, normalCase) { char *dbname = "1.db1"; char *tablename = "table1"; SVgroupInfo vgInfo = {0}; - SQueryDag dag = {0}; + SQueryPlan dag; uint64_t numOfRows = 0; - schtInitLogFile(); - SArray *qnodeList = taosArrayInit(1, sizeof(SEp)); SEp qnodeAddr = {0}; @@ -701,19 +861,19 @@ TEST(multiThread, forceFree) { while (true) { if (schtTestDeadLoop) { - sleep(1); + taosSsleep(1); } else { - sleep(schtTestMTRunSec); + taosSsleep(schtTestMTRunSec); break; } } schtTestStop = true; - sleep(3); + taosSsleep(3); } int main(int argc, char** argv) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/source/libs/sync/inc/syncAppendEntries.h b/source/libs/sync/inc/syncAppendEntries.h index 35d3046d66e5557785d1179757733a764d323086..5999ef8300c5ac4440a4e94ab69d164d01f6d1d9 100644 --- a/source/libs/sync/inc/syncAppendEntries.h +++ b/source/libs/sync/inc/syncAppendEntries.h @@ -25,7 +25,6 @@ extern "C" { #include #include "syncInt.h" #include "syncMessage.h" -#include "syncRaft.h" #include "taosdef.h" // TLA+ Spec diff --git a/source/libs/sync/inc/syncAppendEntriesReply.h b/source/libs/sync/inc/syncAppendEntriesReply.h index 75b82aa5316fb0e744066ada9d1a3a4c9aba8b9b..c0c1f767075f3703c1ee2f8db409488af9968379 100644 --- a/source/libs/sync/inc/syncAppendEntriesReply.h +++ b/source/libs/sync/inc/syncAppendEntriesReply.h @@ -25,7 +25,6 @@ extern "C" { #include #include "syncInt.h" #include "syncMessage.h" -#include "syncRaft.h" #include "taosdef.h" // TLA+ Spec diff --git a/source/libs/sync/inc/syncEnv.h b/source/libs/sync/inc/syncEnv.h index 9fbea0326511e665d76f4c85dec78ab7d97b6836..40ff79287b34367d242764fce5794a32b34f8806 100644 --- a/source/libs/sync/inc/syncEnv.h +++ b/source/libs/sync/inc/syncEnv.h @@ -29,6 +29,7 @@ extern "C" { #include "ttimer.h" #define TIMER_MAX_MS 0x7FFFFFFF +#define ENV_TICK_TIMER_MS 1000 #define PING_TIMER_MS 1000 #define ELECT_TIMER_MS_MIN 150 #define ELECT_TIMER_MS_MAX 300 @@ -38,17 +39,28 @@ extern "C" { #define EMPTY_RAFT_ID ((SRaftId){.addr = 0, .vgId = 0}) typedef struct SSyncEnv { - tmr_h pEnvTickTimer; + // tick timer + tmr_h pEnvTickTimer; + int32_t envTickTimerMS; + uint64_t envTickTimerLogicClock; // if use queue, should pass logic clock into queue item + uint64_t envTickTimerLogicClockUser; + TAOS_TMR_CALLBACK FpEnvTickTimer; // Timer Fp + uint64_t envTickTimerCounter; + + // timer manager tmr_h pTimerManager; - char name[128]; + + // other resources shared by SyncNodes + // ... + } SSyncEnv; extern SSyncEnv* gSyncEnv; int32_t syncEnvStart(); int32_t syncEnvStop(); -tmr_h syncEnvStartTimer(TAOS_TMR_CALLBACK fp, int mseconds, void* param); -void syncEnvStopTimer(tmr_h* pTimer); +int32_t syncEnvStartTimer(); +int32_t syncEnvStopTimer(); #ifdef __cplusplus } diff --git a/source/libs/sync/inc/syncIO.h b/source/libs/sync/inc/syncIO.h index 160fefd086cc7e4a0334e2156883da1ba5034046..352d30c8d72b131b934f430971942fa718d54fd4 100644 --- a/source/libs/sync/inc/syncIO.h +++ b/source/libs/sync/inc/syncIO.h @@ -29,6 +29,9 @@ extern "C" { #include "tqueue.h" #include "trpc.h" +#define TICK_Q_TIMER_MS 1000 +#define TICK_Ping_TIMER_MS 1000 + typedef struct SSyncIO { STaosQueue *pMsgQ; STaosQset * pQset; @@ -38,9 +41,11 @@ typedef struct SSyncIO { void * clientRpc; SEpSet myAddr; - void *ioTimerTickQ; - void *ioTimerTickPing; - void *ioTimerManager; + tmr_h qTimer; + int32_t qTimerMS; + tmr_h pingTimer; + int32_t pingTimerMS; + tmr_h timerMgr; void *pSyncNode; int32_t (*FpOnSyncPing)(SSyncNode *pSyncNode, SyncPing *pMsg); @@ -59,11 +64,14 @@ extern SSyncIO *gSyncIO; int32_t syncIOStart(char *host, uint16_t port); int32_t syncIOStop(); -int32_t syncIOTickQ(); -int32_t syncIOTickPing(); int32_t syncIOSendMsg(void *clientRpc, const SEpSet *pEpSet, SRpcMsg *pMsg); int32_t syncIOEqMsg(void *queue, SRpcMsg *pMsg); +int32_t syncIOQTimerStart(); +int32_t syncIOQTimerStop(); +int32_t syncIOPingTimerStart(); +int32_t syncIOPingTimerStop(); + #ifdef __cplusplus } #endif diff --git a/source/libs/sync/inc/syncIndexMgr.h b/source/libs/sync/inc/syncIndexMgr.h new file mode 100644 index 0000000000000000000000000000000000000000..63f24b104fe47615750e6363207d93d19e9400b7 --- /dev/null +++ b/source/libs/sync/inc/syncIndexMgr.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#ifndef _TD_LIBS_SYNC_INDEX_MGR_H +#define _TD_LIBS_SYNC_INDEX_MGR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "syncInt.h" +#include "taosdef.h" + +// SIndexMgr ----------------------------- +typedef struct SSyncIndexMgr { + SRaftId (*replicas)[TSDB_MAX_REPLICA]; + SyncIndex index[TSDB_MAX_REPLICA]; + int32_t replicaNum; + SSyncNode *pSyncNode; +} SSyncIndexMgr; + +SSyncIndexMgr *syncIndexMgrCreate(SSyncNode *pSyncNode); +void syncIndexMgrDestroy(SSyncIndexMgr *pSyncIndexMgr); +void syncIndexMgrClear(SSyncIndexMgr *pSyncIndexMgr); +void syncIndexMgrSetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId, SyncIndex index); +SyncIndex syncIndexMgrGetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId); +cJSON * syncIndexMgr2Json(SSyncIndexMgr *pSyncIndexMgr); +char * syncIndexMgr2Str(SSyncIndexMgr *pSyncIndexMgr); + +// for debug ------------------- +void syncIndexMgrPrint(SSyncIndexMgr *pObj); +void syncIndexMgrPrint2(char *s, SSyncIndexMgr *pObj); +void syncIndexMgrLog(SSyncIndexMgr *pObj); +void syncIndexMgrLog2(char *s, SSyncIndexMgr *pObj); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_LIBS_SYNC_INDEX_MGR_H*/ diff --git a/source/libs/sync/inc/syncInt.h b/source/libs/sync/inc/syncInt.h index b8c7eb60e732d2b678e80dce2b0e67f5dbe5f5ff..15c719b76e08d27dda223275811f96433550ba84 100644 --- a/source/libs/sync/inc/syncInt.h +++ b/source/libs/sync/inc/syncInt.h @@ -23,6 +23,7 @@ extern "C" { #include #include #include +#include "cJSON.h" #include "sync.h" #include "taosdef.h" #include "tglobal.h" @@ -66,9 +67,6 @@ extern "C" { } \ } -struct SRaft; -typedef struct SRaft SRaft; - struct SyncTimeout; typedef struct SyncTimeout SyncTimeout; @@ -99,8 +97,11 @@ typedef struct SRaftStore SRaftStore; struct SVotesGranted; typedef struct SVotesGranted SVotesGranted; -struct SVotesResponded; -typedef struct SVotesResponded SVotesResponded; +struct SVotesRespond; +typedef struct SVotesRespond SVotesRespond; + +struct SSyncIndexMgr; +typedef struct SSyncIndexMgr SSyncIndexMgr; typedef struct SRaftId { SyncNodeId addr; // typedef uint64_t SyncNodeId; @@ -112,17 +113,21 @@ typedef struct SSyncNode { SyncGroupId vgId; SSyncCfg syncCfg; char path[TSDB_FILENAME_LEN]; - void* rpcClient; + char raftStorePath[TSDB_FILENAME_LEN * 2]; + + // sync io + SWal* pWal; + void* rpcClient; int32_t (*FpSendMsg)(void* rpcClient, const SEpSet* pEpSet, SRpcMsg* pMsg); void* queue; int32_t (*FpEqMsg)(void* queue, SRpcMsg* pMsg); // init internal - SNodeInfo me; - SRaftId raftId; + SNodeInfo myNodeInfo; + SRaftId myRaftId; int32_t peersNum; - SNodeInfo peers[TSDB_MAX_REPLICA]; + SNodeInfo peersNodeInfo[TSDB_MAX_REPLICA]; SRaftId peersId[TSDB_MAX_REPLICA]; int32_t replicaNum; @@ -142,37 +147,39 @@ typedef struct SSyncNode { SRaftStore* pRaftStore; // tla+ candidate vars - SVotesGranted* pVotesGranted; - SVotesResponded* pVotesResponded; + SVotesGranted* pVotesGranted; + SVotesRespond* pVotesRespond; // tla+ leader vars - SHashObj* pNextIndex; - SHashObj* pMatchIndex; + SSyncIndexMgr* pNextIndex; + SSyncIndexMgr* pMatchIndex; // tla+ log vars SSyncLogStore* pLogStore; SyncIndex commitIndex; - // timer + // ping timer tmr_h pPingTimer; int32_t pingTimerMS; uint64_t pingTimerLogicClock; uint64_t pingTimerLogicClockUser; - TAOS_TMR_CALLBACK FpPingTimer; // Timer Fp + TAOS_TMR_CALLBACK FpPingTimerCB; // Timer Fp uint64_t pingTimerCounter; + // elect timer tmr_h pElectTimer; int32_t electTimerMS; uint64_t electTimerLogicClock; uint64_t electTimerLogicClockUser; - TAOS_TMR_CALLBACK FpElectTimer; // Timer Fp + TAOS_TMR_CALLBACK FpElectTimerCB; // Timer Fp uint64_t electTimerCounter; + // heartbeat timer tmr_h pHeartbeatTimer; int32_t heartbeatTimerMS; uint64_t heartbeatTimerLogicClock; uint64_t heartbeatTimerLogicClockUser; - TAOS_TMR_CALLBACK FpHeartbeatTimer; // Timer Fp + TAOS_TMR_CALLBACK FpHeartbeatTimerCB; // Timer Fp uint64_t heartbeatTimerCounter; // callback @@ -186,24 +193,53 @@ typedef struct SSyncNode { } SSyncNode; +// open/close -------------- SSyncNode* syncNodeOpen(const SSyncInfo* pSyncInfo); void syncNodeClose(SSyncNode* pSyncNode); -int32_t syncNodeSendMsgById(const SRaftId* destRaftId, SSyncNode* pSyncNode, SRpcMsg* pMsg); -int32_t syncNodeSendMsgByInfo(const SNodeInfo* nodeInfo, SSyncNode* pSyncNode, SRpcMsg* pMsg); +// ping -------------- int32_t syncNodePing(SSyncNode* pSyncNode, const SRaftId* destRaftId, SyncPing* pMsg); -int32_t syncNodePingAll(SSyncNode* pSyncNode); -int32_t syncNodePingPeers(SSyncNode* pSyncNode); int32_t syncNodePingSelf(SSyncNode* pSyncNode); +int32_t syncNodePingPeers(SSyncNode* pSyncNode); +int32_t syncNodePingAll(SSyncNode* pSyncNode); +// timer control -------------- int32_t syncNodeStartPingTimer(SSyncNode* pSyncNode); int32_t syncNodeStopPingTimer(SSyncNode* pSyncNode); int32_t syncNodeStartElectTimer(SSyncNode* pSyncNode, int32_t ms); int32_t syncNodeStopElectTimer(SSyncNode* pSyncNode); int32_t syncNodeRestartElectTimer(SSyncNode* pSyncNode, int32_t ms); +int32_t syncNodeResetElectTimer(SSyncNode* pSyncNode); int32_t syncNodeStartHeartbeatTimer(SSyncNode* pSyncNode); int32_t syncNodeStopHeartbeatTimer(SSyncNode* pSyncNode); +// utils -------------- +int32_t syncNodeSendMsgById(const SRaftId* destRaftId, SSyncNode* pSyncNode, SRpcMsg* pMsg); +int32_t syncNodeSendMsgByInfo(const SNodeInfo* nodeInfo, SSyncNode* pSyncNode, SRpcMsg* pMsg); +cJSON* syncNode2Json(const SSyncNode* pSyncNode); +char* syncNode2Str(const SSyncNode* pSyncNode); + +// raft state change -------------- +void syncNodeUpdateTerm(SSyncNode* pSyncNode, SyncTerm term); +void syncNodeBecomeFollower(SSyncNode* pSyncNode); +void syncNodeBecomeLeader(SSyncNode* pSyncNode); + +void syncNodeCandidate2Leader(SSyncNode* pSyncNode); +void syncNodeFollower2Candidate(SSyncNode* pSyncNode); +void syncNodeLeader2Follower(SSyncNode* pSyncNode); +void syncNodeCandidate2Follower(SSyncNode* pSyncNode); + +// raft vote -------------- +void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId); +void syncNodeVoteForSelf(SSyncNode* pSyncNode); +void syncNodeMaybeAdvanceCommitIndex(SSyncNode* pSyncNode); + +// for debug -------------- +void syncNodePrint(SSyncNode* pObj); +void syncNodePrint2(char* s, SSyncNode* pObj); +void syncNodeLog(SSyncNode* pObj); +void syncNodeLog2(char* s, SSyncNode* pObj); + #ifdef __cplusplus } #endif diff --git a/source/libs/sync/inc/syncMessage.h b/source/libs/sync/inc/syncMessage.h index 3405f0f6cc14d810be052ed052f821e0fab2a27f..5785089a20beb96df31dcb7eb6a003d607f68d8e 100644 --- a/source/libs/sync/inc/syncMessage.h +++ b/source/libs/sync/inc/syncMessage.h @@ -24,8 +24,7 @@ extern "C" { #include #include #include "cJSON.h" -#include "sync.h" -#include "syncRaftEntry.h" +#include "syncInt.h" #include "taosdef.h" // encode as uint32 @@ -40,12 +39,20 @@ typedef enum ESyncMessageType { SYNC_REQUEST_VOTE_REPLY = 111, SYNC_APPEND_ENTRIES = 113, SYNC_APPEND_ENTRIES_REPLY = 115, + SYNC_RESPONSE = 119, } ESyncMessageType; // --------------------------------------------- cJSON* syncRpcMsg2Json(SRpcMsg* pRpcMsg); cJSON* syncRpcUnknownMsg2Json(); +char* syncRpcMsg2Str(SRpcMsg* pRpcMsg); + +// for debug ---------------------- +void syncRpcMsgPrint(SRpcMsg* pMsg); +void syncRpcMsgPrint2(char* s, SRpcMsg* pMsg); +void syncRpcMsgLog(SRpcMsg* pMsg); +void syncRpcMsgLog2(char* s, SRpcMsg* pMsg); // --------------------------------------------- typedef enum ESyncTimeoutType { @@ -60,17 +67,27 @@ typedef struct SyncTimeout { ESyncTimeoutType timeoutType; uint64_t logicClock; int32_t timerMS; - void* data; + void* data; // need optimized } SyncTimeout; SyncTimeout* syncTimeoutBuild(); +SyncTimeout* syncTimeoutBuild2(ESyncTimeoutType timeoutType, uint64_t logicClock, int32_t timerMS, void* data); void syncTimeoutDestroy(SyncTimeout* pMsg); void syncTimeoutSerialize(const SyncTimeout* pMsg, char* buf, uint32_t bufLen); void syncTimeoutDeserialize(const char* buf, uint32_t len, SyncTimeout* pMsg); +char* syncTimeoutSerialize2(const SyncTimeout* pMsg, uint32_t* len); // +SyncTimeout* syncTimeoutDeserialize2(const char* buf, uint32_t len); // void syncTimeout2RpcMsg(const SyncTimeout* pMsg, SRpcMsg* pRpcMsg); void syncTimeoutFromRpcMsg(const SRpcMsg* pRpcMsg, SyncTimeout* pMsg); +SyncTimeout* syncTimeoutFromRpcMsg2(const SRpcMsg* pRpcMsg); // cJSON* syncTimeout2Json(const SyncTimeout* pMsg); -SyncTimeout* syncTimeoutBuild2(ESyncTimeoutType timeoutType, uint64_t logicClock, int32_t timerMS, void* data); +char* syncTimeout2Str(const SyncTimeout* pMsg); // + +// for debug ---------------------- +void syncTimeoutPrint(const SyncTimeout* pMsg); +void syncTimeoutPrint2(char* s, const SyncTimeout* pMsg); +void syncTimeoutLog(const SyncTimeout* pMsg); +void syncTimeoutLog2(char* s, const SyncTimeout* pMsg); // --------------------------------------------- typedef struct SyncPing { @@ -83,17 +100,25 @@ typedef struct SyncPing { char data[]; } SyncPing; -#define SYNC_PING_FIX_LEN (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(SRaftId) + sizeof(SRaftId) + sizeof(uint32_t)) - SyncPing* syncPingBuild(uint32_t dataLen); +SyncPing* syncPingBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str); +SyncPing* syncPingBuild3(const SRaftId* srcId, const SRaftId* destId); void syncPingDestroy(SyncPing* pMsg); void syncPingSerialize(const SyncPing* pMsg, char* buf, uint32_t bufLen); void syncPingDeserialize(const char* buf, uint32_t len, SyncPing* pMsg); +char* syncPingSerialize2(const SyncPing* pMsg, uint32_t* len); +SyncPing* syncPingDeserialize2(const char* buf, uint32_t len); void syncPing2RpcMsg(const SyncPing* pMsg, SRpcMsg* pRpcMsg); void syncPingFromRpcMsg(const SRpcMsg* pRpcMsg, SyncPing* pMsg); +SyncPing* syncPingFromRpcMsg2(const SRpcMsg* pRpcMsg); cJSON* syncPing2Json(const SyncPing* pMsg); -SyncPing* syncPingBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str); -SyncPing* syncPingBuild3(const SRaftId* srcId, const SRaftId* destId); +char* syncPing2Str(const SyncPing* pMsg); + +// for debug ---------------------- +void syncPingPrint(const SyncPing* pMsg); +void syncPingPrint2(char* s, const SyncPing* pMsg); +void syncPingLog(const SyncPing* pMsg); +void syncPingLog2(char* s, const SyncPing* pMsg); // --------------------------------------------- typedef struct SyncPingReply { @@ -106,29 +131,56 @@ typedef struct SyncPingReply { char data[]; } SyncPingReply; -#define SYNC_PING_REPLY_FIX_LEN \ - (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(SRaftId) + sizeof(SRaftId) + sizeof(uint32_t)) - SyncPingReply* syncPingReplyBuild(uint32_t dataLen); +SyncPingReply* syncPingReplyBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str); +SyncPingReply* syncPingReplyBuild3(const SRaftId* srcId, const SRaftId* destId); void syncPingReplyDestroy(SyncPingReply* pMsg); void syncPingReplySerialize(const SyncPingReply* pMsg, char* buf, uint32_t bufLen); void syncPingReplyDeserialize(const char* buf, uint32_t len, SyncPingReply* pMsg); +char* syncPingReplySerialize2(const SyncPingReply* pMsg, uint32_t* len); // +SyncPingReply* syncPingReplyDeserialize2(const char* buf, uint32_t len); // void syncPingReply2RpcMsg(const SyncPingReply* pMsg, SRpcMsg* pRpcMsg); void syncPingReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncPingReply* pMsg); +SyncPingReply* syncPingReplyFromRpcMsg2(const SRpcMsg* pRpcMsg); // cJSON* syncPingReply2Json(const SyncPingReply* pMsg); -SyncPingReply* syncPingReplyBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str); -SyncPingReply* syncPingReplyBuild3(const SRaftId* srcId, const SRaftId* destId); +char* syncPingReply2Str(const SyncPingReply* pMsg); // + +// for debug ---------------------- +void syncPingReplyPrint(const SyncPingReply* pMsg); +void syncPingReplyPrint2(char* s, const SyncPingReply* pMsg); +void syncPingReplyLog(const SyncPingReply* pMsg); +void syncPingReplyLog2(char* s, const SyncPingReply* pMsg); // --------------------------------------------- typedef struct SyncClientRequest { uint32_t bytes; uint32_t msgType; - int64_t seqNum; + uint32_t originalRpcType; + uint64_t seqNum; bool isWeak; uint32_t dataLen; char data[]; } SyncClientRequest; +SyncClientRequest* syncClientRequestBuild(uint32_t dataLen); +SyncClientRequest* syncClientRequestBuild2(const SRpcMsg* pOriginalRpcMsg, uint64_t seqNum, bool isWeak); +void syncClientRequestDestroy(SyncClientRequest* pMsg); +void syncClientRequestSerialize(const SyncClientRequest* pMsg, char* buf, uint32_t bufLen); +void syncClientRequestDeserialize(const char* buf, uint32_t len, SyncClientRequest* pMsg); +char* syncClientRequestSerialize2(const SyncClientRequest* pMsg, uint32_t* len); +SyncClientRequest* syncClientRequestDeserialize2(const char* buf, uint32_t len); +void syncClientRequest2RpcMsg(const SyncClientRequest* pMsg, SRpcMsg* pRpcMsg); +void syncClientRequestFromRpcMsg(const SRpcMsg* pRpcMsg, SyncClientRequest* pMsg); +SyncClientRequest* syncClientRequestFromRpcMsg2(const SRpcMsg* pRpcMsg); +cJSON* syncClientRequest2Json(const SyncClientRequest* pMsg); +char* syncClientRequest2Str(const SyncClientRequest* pMsg); + +// for debug ---------------------- +void syncClientRequestPrint(const SyncClientRequest* pMsg); +void syncClientRequestPrint2(char* s, const SyncClientRequest* pMsg); +void syncClientRequestLog(const SyncClientRequest* pMsg); +void syncClientRequestLog2(char* s, const SyncClientRequest* pMsg); + // --------------------------------------------- typedef struct SyncClientRequestReply { uint32_t bytes; @@ -144,7 +196,7 @@ typedef struct SyncRequestVote { SRaftId srcId; SRaftId destId; // private data - SyncTerm currentTerm; + SyncTerm term; SyncIndex lastLogIndex; SyncTerm lastLogTerm; } SyncRequestVote; @@ -153,9 +205,19 @@ SyncRequestVote* syncRequestVoteBuild(); void syncRequestVoteDestroy(SyncRequestVote* pMsg); void syncRequestVoteSerialize(const SyncRequestVote* pMsg, char* buf, uint32_t bufLen); void syncRequestVoteDeserialize(const char* buf, uint32_t len, SyncRequestVote* pMsg); +char* syncRequestVoteSerialize2(const SyncRequestVote* pMsg, uint32_t* len); +SyncRequestVote* syncRequestVoteDeserialize2(const char* buf, uint32_t len); void syncRequestVote2RpcMsg(const SyncRequestVote* pMsg, SRpcMsg* pRpcMsg); void syncRequestVoteFromRpcMsg(const SRpcMsg* pRpcMsg, SyncRequestVote* pMsg); +SyncRequestVote* syncRequestVoteFromRpcMsg2(const SRpcMsg* pRpcMsg); cJSON* syncRequestVote2Json(const SyncRequestVote* pMsg); +char* syncRequestVote2Str(const SyncRequestVote* pMsg); + +// for debug ---------------------- +void syncRequestVotePrint(const SyncRequestVote* pMsg); +void syncRequestVotePrint2(char* s, const SyncRequestVote* pMsg); +void syncRequestVoteLog(const SyncRequestVote* pMsg); +void syncRequestVoteLog2(char* s, const SyncRequestVote* pMsg); // --------------------------------------------- typedef struct SyncRequestVoteReply { @@ -168,13 +230,23 @@ typedef struct SyncRequestVoteReply { bool voteGranted; } SyncRequestVoteReply; -SyncRequestVoteReply* SyncRequestVoteReplyBuild(); +SyncRequestVoteReply* syncRequestVoteReplyBuild(); void syncRequestVoteReplyDestroy(SyncRequestVoteReply* pMsg); void syncRequestVoteReplySerialize(const SyncRequestVoteReply* pMsg, char* buf, uint32_t bufLen); void syncRequestVoteReplyDeserialize(const char* buf, uint32_t len, SyncRequestVoteReply* pMsg); +char* syncRequestVoteReplySerialize2(const SyncRequestVoteReply* pMsg, uint32_t* len); +SyncRequestVoteReply* syncRequestVoteReplyDeserialize2(const char* buf, uint32_t len); void syncRequestVoteReply2RpcMsg(const SyncRequestVoteReply* pMsg, SRpcMsg* pRpcMsg); void syncRequestVoteReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncRequestVoteReply* pMsg); +SyncRequestVoteReply* syncRequestVoteReplyFromRpcMsg2(const SRpcMsg* pRpcMsg); cJSON* syncRequestVoteReply2Json(const SyncRequestVoteReply* pMsg); +char* syncRequestVoteReply2Str(const SyncRequestVoteReply* pMsg); + +// for debug ---------------------- +void syncRequestVoteReplyPrint(const SyncRequestVoteReply* pMsg); +void syncRequestVoteReplyPrint2(char* s, const SyncRequestVoteReply* pMsg); +void syncRequestVoteReplyLog(const SyncRequestVoteReply* pMsg); +void syncRequestVoteReplyLog2(char* s, const SyncRequestVoteReply* pMsg); // --------------------------------------------- typedef struct SyncAppendEntries { @@ -183,6 +255,7 @@ typedef struct SyncAppendEntries { SRaftId srcId; SRaftId destId; // private data + SyncTerm term; SyncIndex prevLogIndex; SyncTerm prevLogTerm; SyncIndex commitIndex; @@ -190,17 +263,23 @@ typedef struct SyncAppendEntries { char data[]; } SyncAppendEntries; -#define SYNC_APPEND_ENTRIES_FIX_LEN \ - (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(SRaftId) + sizeof(SRaftId) + sizeof(SyncIndex) + sizeof(SyncTerm) + \ - sizeof(SyncIndex) + sizeof(uint32_t)) - SyncAppendEntries* syncAppendEntriesBuild(uint32_t dataLen); void syncAppendEntriesDestroy(SyncAppendEntries* pMsg); void syncAppendEntriesSerialize(const SyncAppendEntries* pMsg, char* buf, uint32_t bufLen); void syncAppendEntriesDeserialize(const char* buf, uint32_t len, SyncAppendEntries* pMsg); +char* syncAppendEntriesSerialize2(const SyncAppendEntries* pMsg, uint32_t* len); +SyncAppendEntries* syncAppendEntriesDeserialize2(const char* buf, uint32_t len); void syncAppendEntries2RpcMsg(const SyncAppendEntries* pMsg, SRpcMsg* pRpcMsg); void syncAppendEntriesFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntries* pMsg); +SyncAppendEntries* syncAppendEntriesFromRpcMsg2(const SRpcMsg* pRpcMsg); cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg); +char* syncAppendEntries2Str(const SyncAppendEntries* pMsg); + +// for debug ---------------------- +void syncAppendEntriesPrint(const SyncAppendEntries* pMsg); +void syncAppendEntriesPrint2(char* s, const SyncAppendEntries* pMsg); +void syncAppendEntriesLog(const SyncAppendEntries* pMsg); +void syncAppendEntriesLog2(char* s, const SyncAppendEntries* pMsg); // --------------------------------------------- typedef struct SyncAppendEntriesReply { @@ -209,6 +288,7 @@ typedef struct SyncAppendEntriesReply { SRaftId srcId; SRaftId destId; // private data + SyncTerm term; bool success; SyncIndex matchIndex; } SyncAppendEntriesReply; @@ -217,9 +297,19 @@ SyncAppendEntriesReply* syncAppendEntriesReplyBuild(); void syncAppendEntriesReplyDestroy(SyncAppendEntriesReply* pMsg); void syncAppendEntriesReplySerialize(const SyncAppendEntriesReply* pMsg, char* buf, uint32_t bufLen); void syncAppendEntriesReplyDeserialize(const char* buf, uint32_t len, SyncAppendEntriesReply* pMsg); +char* syncAppendEntriesReplySerialize2(const SyncAppendEntriesReply* pMsg, uint32_t* len); +SyncAppendEntriesReply* syncAppendEntriesReplyDeserialize2(const char* buf, uint32_t len); void syncAppendEntriesReply2RpcMsg(const SyncAppendEntriesReply* pMsg, SRpcMsg* pRpcMsg); void syncAppendEntriesReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntriesReply* pMsg); +SyncAppendEntriesReply* syncAppendEntriesReplyFromRpcMsg2(const SRpcMsg* pRpcMsg); cJSON* syncAppendEntriesReply2Json(const SyncAppendEntriesReply* pMsg); +char* syncAppendEntriesReply2Str(const SyncAppendEntriesReply* pMsg); + +// for debug ---------------------- +void syncAppendEntriesReplyPrint(const SyncAppendEntriesReply* pMsg); +void syncAppendEntriesReplyPrint2(char* s, const SyncAppendEntriesReply* pMsg); +void syncAppendEntriesReplyLog(const SyncAppendEntriesReply* pMsg); +void syncAppendEntriesReplyLog2(char* s, const SyncAppendEntriesReply* pMsg); #ifdef __cplusplus } diff --git a/source/libs/sync/inc/syncOnMessage.h b/source/libs/sync/inc/syncOnMessage.h index 8eae4fed4d9169bca9c271ab448a801119963a70..7cb186a8121800134fad6d1896870e85cbe503b1 100644 --- a/source/libs/sync/inc/syncOnMessage.h +++ b/source/libs/sync/inc/syncOnMessage.h @@ -23,7 +23,6 @@ extern "C" { #include #include #include -#include "syncRaft.h" #include "taosdef.h" #ifdef __cplusplus diff --git a/source/libs/sync/inc/syncRaft.h b/source/libs/sync/inc/syncRaft.h deleted file mode 100644 index bc5cf26a4c94009e9a40ce17c22f0a8f68f3aa28..0000000000000000000000000000000000000000 --- a/source/libs/sync/inc/syncRaft.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#ifndef _TD_LIBS_SYNC_RAFT_H -#define _TD_LIBS_SYNC_RAFT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "sync.h" -#include "syncMessage.h" -#include "taosdef.h" - -#if 0 - -typedef struct SRaftId { - SyncNodeId addr; - SyncGroupId vgId; -} SRaftId; - -typedef struct SRaft { - SRaftId id; - SSyncFSM* pFsm; - - int32_t (*FpPing)(struct SRaft* ths, const RaftPing* pMsg); - - int32_t (*FpOnPing)(struct SRaft* ths, RaftPing* pMsg); - - int32_t (*FpOnPingReply)(struct SRaft* ths, RaftPingReply* pMsg); - - int32_t (*FpRequestVote)(struct SRaft* ths, const RaftRequestVote* pMsg); - - int32_t (*FpOnRequestVote)(struct SRaft* ths, RaftRequestVote* pMsg); - - int32_t (*FpOnRequestVoteReply)(struct SRaft* ths, RaftRequestVoteReply* pMsg); - - int32_t (*FpAppendEntries)(struct SRaft* ths, const RaftAppendEntries* pMsg); - - int32_t (*FpOnAppendEntries)(struct SRaft* ths, RaftAppendEntries* pMsg); - - int32_t (*FpOnAppendEntriesReply)(struct SRaft* ths, RaftAppendEntriesReply* pMsg); - -} SRaft; - -SRaft* raftOpen(SRaftId raftId, SSyncFSM* pFsm); - -void raftClose(SRaft* pRaft); - -static int32_t doRaftPing(struct SRaft* ths, const RaftPing* pMsg); - -static int32_t onRaftPing(struct SRaft* ths, RaftPing* pMsg); - -static int32_t onRaftPingReply(struct SRaft* ths, RaftPingReply* pMsg); - -static int32_t doRaftRequestVote(struct SRaft* ths, const RaftRequestVote* pMsg); - -static int32_t onRaftRequestVote(struct SRaft* ths, RaftRequestVote* pMsg); - -static int32_t onRaftRequestVoteReply(struct SRaft* ths, RaftRequestVoteReply* pMsg); - -static int32_t doRaftAppendEntries(struct SRaft* ths, const RaftAppendEntries* pMsg); - -static int32_t onRaftAppendEntries(struct SRaft* ths, RaftAppendEntries* pMsg); - -static int32_t onRaftAppendEntriesReply(struct SRaft* ths, RaftAppendEntriesReply* pMsg); - -int32_t raftPropose(SRaft* pRaft, const SSyncBuffer* pBuf, bool isWeak); - -static int raftSendMsg(SRaftId destRaftId, const void* pMsg, const SRaft* pRaft); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /*_TD_LIBS_SYNC_RAFT_H*/ diff --git a/source/libs/sync/inc/syncRaftEntry.h b/source/libs/sync/inc/syncRaftEntry.h index 516bef4d48c4f9b26d202f6999c1eec78644b056..6ba27b0d8a3812e97d151bbcf10a47a0ce19ed4c 100644 --- a/source/libs/sync/inc/syncRaftEntry.h +++ b/source/libs/sync/inc/syncRaftEntry.h @@ -24,15 +24,35 @@ extern "C" { #include #include #include "syncInt.h" +#include "syncMessage.h" #include "taosdef.h" typedef struct SSyncRaftEntry { - SyncTerm term; - SyncIndex index; - SSyncBuffer data; - int8_t flag; + uint32_t bytes; + uint32_t msgType; + uint32_t originalRpcType; + uint64_t seqNum; + bool isWeak; + SyncTerm term; + SyncIndex index; + uint32_t dataLen; + char data[]; } SSyncRaftEntry; +SSyncRaftEntry* syncEntryBuild(uint32_t dataLen); +SSyncRaftEntry* syncEntryBuild2(SyncClientRequest* pMsg, SyncTerm term, SyncIndex index); +void syncEntryDestory(SSyncRaftEntry* pEntry); +char* syncEntrySerialize(const SSyncRaftEntry* pEntry, uint32_t* len); +SSyncRaftEntry* syncEntryDeserialize(const char* buf, uint32_t len); +cJSON* syncEntry2Json(const SSyncRaftEntry* pEntry); +char* syncEntry2Str(const SSyncRaftEntry* pEntry); + +// for debug ---------------------- +void syncEntryPrint(const SSyncRaftEntry* pObj); +void syncEntryPrint2(char* s, const SSyncRaftEntry* pObj); +void syncEntryLog(const SSyncRaftEntry* pObj); +void syncEntryLog2(char* s, const SSyncRaftEntry* pObj); + #ifdef __cplusplus } #endif diff --git a/source/libs/sync/inc/syncRaftLog.h b/source/libs/sync/inc/syncRaftLog.h index ee971062cf7ed5140856f0c5d4483adf157d9d0a..d979e0df150f48ec403012d13eafb5431c5b42e6 100644 --- a/source/libs/sync/inc/syncRaftLog.h +++ b/source/libs/sync/inc/syncRaftLog.h @@ -24,27 +24,35 @@ extern "C" { #include #include #include "syncInt.h" +#include "syncRaftEntry.h" #include "taosdef.h" -int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncBuffer* pBuf); - -// get one log entry, user need to free pBuf->data -int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncBuffer* pBuf); - -// update log store commit index with "index" -int32_t raftLogUpdateCommitIndex(struct SSyncLogStore* pLogStore, SyncIndex index); - -// truncate log with index, entries after the given index (>index) will be deleted -int32_t raftLogTruncate(struct SSyncLogStore* pLogStore, SyncIndex index); - -// return commit index of log -SyncIndex raftLogGetCommitIndex(struct SSyncLogStore* pLogStore); - -// return index of last entry -SyncIndex raftLogGetLastIndex(struct SSyncLogStore* pLogStore); - -// return term of last entry -SyncTerm raftLogGetLastTerm(struct SSyncLogStore* pLogStore); +#define SYNC_INDEX_BEGIN 0 +#define SYNC_INDEX_INVALID -1 + +typedef struct SSyncLogStoreData { + SSyncNode* pSyncNode; + SWal* pWal; +} SSyncLogStoreData; + +SSyncLogStore* logStoreCreate(SSyncNode* pSyncNode); +void logStoreDestory(SSyncLogStore* pLogStore); +int32_t logStoreAppendEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry); +SSyncRaftEntry* logStoreGetEntry(SSyncLogStore* pLogStore, SyncIndex index); +int32_t logStoreTruncate(SSyncLogStore* pLogStore, SyncIndex fromIndex); +SyncIndex logStoreLastIndex(SSyncLogStore* pLogStore); +SyncTerm logStoreLastTerm(SSyncLogStore* pLogStore); +int32_t logStoreUpdateCommitIndex(SSyncLogStore* pLogStore, SyncIndex index); +SyncIndex logStoreGetCommitIndex(SSyncLogStore* pLogStore); +SSyncRaftEntry* logStoreGetLastEntry(SSyncLogStore* pLogStore); +cJSON* logStore2Json(SSyncLogStore* pLogStore); +char* logStore2Str(SSyncLogStore* pLogStore); + +// for debug +void logStorePrint(SSyncLogStore* pLogStore); +void logStorePrint2(char* s, SSyncLogStore* pLogStore); +void logStoreLog(SSyncLogStore* pLogStore); +void logStoreLog2(char* s, SSyncLogStore* pLogStore); #ifdef __cplusplus } diff --git a/source/libs/sync/inc/syncRaftStore.h b/source/libs/sync/inc/syncRaftStore.h index 591a5b996390a3cc9ad656cd26fe5286332f9f5a..30f7c5d9f7d66b37fec79ab370961ea7b0dc8998 100644 --- a/source/libs/sync/inc/syncRaftStore.h +++ b/source/libs/sync/inc/syncRaftStore.h @@ -25,7 +25,6 @@ extern "C" { #include #include "cJSON.h" #include "syncInt.h" -#include "syncRaft.h" #include "taosdef.h" #define RAFT_STORE_BLOCK_SIZE 512 @@ -43,7 +42,18 @@ int32_t raftStoreClose(SRaftStore *pRaftStore); int32_t raftStorePersist(SRaftStore *pRaftStore); int32_t raftStoreSerialize(SRaftStore *pRaftStore, char *buf, size_t len); int32_t raftStoreDeserialize(SRaftStore *pRaftStore, char *buf, size_t len); -void raftStorePrint(SRaftStore *pRaftStore); + +bool raftStoreHasVoted(SRaftStore *pRaftStore); +void raftStoreVote(SRaftStore *pRaftStore, SRaftId *pRaftId); +void raftStoreClearVote(SRaftStore *pRaftStore); +void raftStoreNextTerm(SRaftStore *pRaftStore); +void raftStoreSetTerm(SRaftStore *pRaftStore, SyncTerm term); + +// for debug ------------------- +void raftStorePrint(SRaftStore *pObj); +void raftStorePrint2(char *s, SRaftStore *pObj); +void raftStoreLog(SRaftStore *pObj); +void raftStoreLog2(char *s, SRaftStore *pObj); #ifdef __cplusplus } diff --git a/source/libs/sync/inc/syncReplication.h b/source/libs/sync/inc/syncReplication.h index 467cfdde5cfe6384ec910cefc3217cf88c2f5b09..aca6205b9dfd75d044ceb8156fb3683af45f097b 100644 --- a/source/libs/sync/inc/syncReplication.h +++ b/source/libs/sync/inc/syncReplication.h @@ -53,6 +53,7 @@ extern "C" { // int32_t syncNodeAppendEntriesPeers(SSyncNode* pSyncNode); +int32_t syncNodeReplicate(SSyncNode* pSyncNode); int32_t syncNodeAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftId, const SyncAppendEntries* pMsg); #ifdef __cplusplus diff --git a/source/libs/sync/inc/syncRequestVote.h b/source/libs/sync/inc/syncRequestVote.h index 8bb4976de25b252c455fea5ddc95d8f2ae73f1b8..fd4ccd5371be77c31dc74f29ef10ba28583c5674 100644 --- a/source/libs/sync/inc/syncRequestVote.h +++ b/source/libs/sync/inc/syncRequestVote.h @@ -25,7 +25,6 @@ extern "C" { #include #include "syncInt.h" #include "syncMessage.h" -#include "syncRaft.h" #include "taosdef.h" // TLA+ Spec diff --git a/source/libs/sync/inc/syncRequestVoteReply.h b/source/libs/sync/inc/syncRequestVoteReply.h index ab9430b857f1cc0a40ffa92651bb1bc955fe624e..bcaf71a54137ebed8b5dab3366eb3ba9ea971e4f 100644 --- a/source/libs/sync/inc/syncRequestVoteReply.h +++ b/source/libs/sync/inc/syncRequestVoteReply.h @@ -25,7 +25,6 @@ extern "C" { #include #include "syncInt.h" #include "syncMessage.h" -#include "syncRaft.h" #include "taosdef.h" // TLA+ Spec diff --git a/source/libs/sync/inc/syncSnapshot.h b/source/libs/sync/inc/syncSnapshot.h index 89fcb230fbe06f83a44cdd178bece09f80c5b587..611f33a0f21732e707e2d19eb460a2e7dee6397a 100644 --- a/source/libs/sync/inc/syncSnapshot.h +++ b/source/libs/sync/inc/syncSnapshot.h @@ -24,7 +24,6 @@ extern "C" { #include #include #include "syncInt.h" -#include "syncRaft.h" #include "taosdef.h" int32_t takeSnapshot(SSyncFSM *pFsm, SSnapshot *pSnapshot); diff --git a/source/libs/sync/inc/syncTimeout.h b/source/libs/sync/inc/syncTimeout.h index efd5aae48e0ba04719de7ec6e4b160e41eed1430..25c26c909da2c5616d2a56a6dd0689530f8e49a7 100644 --- a/source/libs/sync/inc/syncTimeout.h +++ b/source/libs/sync/inc/syncTimeout.h @@ -25,7 +25,6 @@ extern "C" { #include #include "syncInt.h" #include "syncMessage.h" -#include "syncRaft.h" #include "taosdef.h" // TLA+ Spec diff --git a/source/libs/sync/inc/syncUtil.h b/source/libs/sync/inc/syncUtil.h index 9b481e82d9a162df5e8c1a7e66735546b5927bc6..1b702c252867dc8a909048d2bea2c960989f40b4 100644 --- a/source/libs/sync/inc/syncUtil.h +++ b/source/libs/sync/inc/syncUtil.h @@ -34,6 +34,7 @@ void syncUtilnodeInfo2EpSet(const SNodeInfo* pNodeInfo, SEpSet* pEpSet); void syncUtilraftId2EpSet(const SRaftId* raftId, SEpSet* pEpSet); void syncUtilnodeInfo2raftId(const SNodeInfo* pNodeInfo, SyncGroupId vgId, SRaftId* raftId); bool syncUtilSameId(const SRaftId* pId1, const SRaftId* pId2); +bool syncUtilEmptyId(const SRaftId* pId); // ---- SSyncBuffer ---- void syncUtilbufBuild(SSyncBuffer* syncBuf, size_t len); @@ -42,8 +43,18 @@ void syncUtilbufCopy(const SSyncBuffer* src, SSyncBuffer* dest); void syncUtilbufCopyDeep(const SSyncBuffer* src, SSyncBuffer* dest); // ---- misc ---- -int32_t syncUtilRand(int32_t max); -int32_t syncUtilElectRandomMS(); +int32_t syncUtilRand(int32_t max); +int32_t syncUtilElectRandomMS(); +int32_t syncUtilQuorum(int32_t replicaNum); +cJSON* syncUtilNodeInfo2Json(const SNodeInfo* p); +cJSON* syncUtilRaftId2Json(const SRaftId* p); +char* syncUtilRaftId2Str(const SRaftId* p); +const char* syncUtilState2String(ESyncState state); +bool syncUtilCanPrint(char c); +char* syncUtilprintBin(char* ptr, uint32_t len); +char* syncUtilprintBin2(char* ptr, uint32_t len); +SyncIndex syncUtilMinIndex(SyncIndex a, SyncIndex b); +SyncIndex syncUtilMaxIndex(SyncIndex a, SyncIndex b); #ifdef __cplusplus } diff --git a/source/libs/sync/inc/syncVoteMgr.h b/source/libs/sync/inc/syncVoteMgr.h index e2307e9e665a7525369d96027dc98a2d8014128f..5bc240e9219a8bd1402683e1025ee15f32048e6b 100644 --- a/source/libs/sync/inc/syncVoteMgr.h +++ b/source/libs/sync/inc/syncVoteMgr.h @@ -28,10 +28,14 @@ extern "C" { #include "syncUtil.h" #include "taosdef.h" +// SVotesGranted ----------------------------- typedef struct SVotesGranted { + SRaftId (*replicas)[TSDB_MAX_REPLICA]; + bool isGranted[TSDB_MAX_REPLICA]; + int32_t replicaNum; + int32_t votes; SyncTerm term; int32_t quorum; - int32_t votes; bool toLeader; SSyncNode *pSyncNode; } SVotesGranted; @@ -41,7 +45,16 @@ void voteGrantedDestroy(SVotesGranted *pVotesGranted); bool voteGrantedMajority(SVotesGranted *pVotesGranted); void voteGrantedVote(SVotesGranted *pVotesGranted, SyncRequestVoteReply *pMsg); void voteGrantedReset(SVotesGranted *pVotesGranted, SyncTerm term); +cJSON * voteGranted2Json(SVotesGranted *pVotesGranted); +char * voteGranted2Str(SVotesGranted *pVotesGranted); + +// for debug ------------------- +void voteGrantedPrint(SVotesGranted *pObj); +void voteGrantedPrint2(char *s, SVotesGranted *pObj); +void voteGrantedLog(SVotesGranted *pObj); +void voteGrantedLog2(char *s, SVotesGranted *pObj); +// SVotesRespond ----------------------------- typedef struct SVotesRespond { SRaftId (*replicas)[TSDB_MAX_REPLICA]; bool isRespond[TSDB_MAX_REPLICA]; @@ -51,9 +64,18 @@ typedef struct SVotesRespond { } SVotesRespond; SVotesRespond *votesRespondCreate(SSyncNode *pSyncNode); +void votesRespondDestory(SVotesRespond *pVotesRespond); bool votesResponded(SVotesRespond *pVotesRespond, const SRaftId *pRaftId); void votesRespondAdd(SVotesRespond *pVotesRespond, const SyncRequestVoteReply *pMsg); -void Reset(SVotesRespond *pVotesRespond, SyncTerm term); +void votesRespondReset(SVotesRespond *pVotesRespond, SyncTerm term); +cJSON * votesRespond2Json(SVotesRespond *pVotesRespond); +char * votesRespond2Str(SVotesRespond *pVotesRespond); + +// for debug ------------------- +void votesRespondPrint(SVotesRespond *pObj); +void votesRespondPrint2(char *s, SVotesRespond *pObj); +void votesRespondLog(SVotesRespond *pObj); +void votesRespondLog2(char *s, SVotesRespond *pObj); #ifdef __cplusplus } diff --git a/source/libs/sync/src/syncAppendEntries.c b/source/libs/sync/src/syncAppendEntries.c index ba10234a1d25da702810bd2f31c2d64f67200899..87d6669f59c33a482af03aee58e793a7c30a4f38 100644 --- a/source/libs/sync/src/syncAppendEntries.c +++ b/source/libs/sync/src/syncAppendEntries.c @@ -14,6 +14,11 @@ */ #include "syncAppendEntries.h" +#include "syncInt.h" +#include "syncRaftLog.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" // TLA+ Spec // HandleAppendEntriesRequest(i, j, m) == @@ -80,4 +85,121 @@ // /\ UNCHANGED <> // /\ UNCHANGED <> // -int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) {} +int32_t syncNodeOnAppendEntriesCb(SSyncNode* ths, SyncAppendEntries* pMsg) { + int32_t ret = 0; + syncAppendEntriesLog2("==syncNodeOnAppendEntriesCb==", pMsg); + + if (pMsg->term > ths->pRaftStore->currentTerm) { + syncNodeUpdateTerm(ths, pMsg->term); + } + assert(pMsg->term <= ths->pRaftStore->currentTerm); + + if (pMsg->term == ths->pRaftStore->currentTerm) { + ths->leaderCache = pMsg->srcId; + syncNodeResetElectTimer(ths); + } + assert(pMsg->dataLen >= 0); + + SyncTerm localPreLogTerm = 0; + if (pMsg->prevLogTerm >= SYNC_INDEX_BEGIN && pMsg->prevLogTerm <= ths->pLogStore->getLastIndex(ths->pLogStore)) { + SSyncRaftEntry* pEntry = logStoreGetEntry(ths->pLogStore, pMsg->prevLogTerm); + assert(pEntry != NULL); + localPreLogTerm = pEntry->term; + syncEntryDestory(pEntry); + } + + bool logOK = + (pMsg->prevLogIndex == SYNC_INDEX_INVALID) || + ((pMsg->prevLogIndex >= SYNC_INDEX_BEGIN) && + (pMsg->prevLogIndex <= ths->pLogStore->getLastIndex(ths->pLogStore)) && (pMsg->prevLogIndex == localPreLogTerm)); + + // reject + if ((pMsg->term < ths->pRaftStore->currentTerm) || + ((pMsg->term == ths->pRaftStore->currentTerm) && (ths->state == TAOS_SYNC_STATE_FOLLOWER) && !logOK)) { + SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(); + pReply->srcId = ths->myRaftId; + pReply->destId = pMsg->srcId; + pReply->term = ths->pRaftStore->currentTerm; + pReply->success = false; + pReply->matchIndex = SYNC_INDEX_INVALID; + + SRpcMsg rpcMsg; + syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg); + syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg); + syncAppendEntriesReplyDestroy(pReply); + + return ret; + } + + // return to follower state + if (pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_CANDIDATE) { + syncNodeBecomeFollower(ths); + } + + // accept request + if (pMsg->term == ths->pRaftStore->currentTerm && ths->state == TAOS_SYNC_STATE_FOLLOWER && logOK) { + bool matchSuccess = false; + if (pMsg->prevLogIndex == SYNC_INDEX_INVALID && + ths->pLogStore->getLastIndex(ths->pLogStore) == SYNC_INDEX_INVALID) { + matchSuccess = true; + } + if (pMsg->prevLogIndex >= SYNC_INDEX_BEGIN && pMsg->prevLogIndex <= ths->pLogStore->getLastIndex(ths->pLogStore)) { + SSyncRaftEntry* pEntry = logStoreGetEntry(ths->pLogStore, pMsg->prevLogTerm); + assert(pEntry != NULL); + if (pMsg->prevLogTerm == pEntry->term) { + matchSuccess = true; + } + syncEntryDestory(pEntry); + } + + if (matchSuccess) { + // delete conflict entries + if (ths->pLogStore->getLastIndex(ths->pLogStore) > pMsg->prevLogIndex) { + SyncIndex fromIndex = pMsg->prevLogIndex + 1; + ths->pLogStore->truncate(ths->pLogStore, fromIndex); + } + + // append one entry + if (pMsg->dataLen > 0) { + SSyncRaftEntry* pEntry = syncEntryDeserialize(pMsg->data, pMsg->dataLen); + ths->pLogStore->appendEntry(ths->pLogStore, pEntry); + syncEntryDestory(pEntry); + } + + SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(); + pReply->srcId = ths->myRaftId; + pReply->destId = pMsg->srcId; + pReply->term = ths->pRaftStore->currentTerm; + pReply->success = true; + pReply->matchIndex = pMsg->prevLogIndex + 1; + + SRpcMsg rpcMsg; + syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg); + syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg); + + syncAppendEntriesReplyDestroy(pReply); + } else { + SyncAppendEntriesReply* pReply = syncAppendEntriesReplyBuild(); + pReply->srcId = ths->myRaftId; + pReply->destId = pMsg->srcId; + pReply->term = ths->pRaftStore->currentTerm; + pReply->success = false; + pReply->matchIndex = SYNC_INDEX_INVALID; + + SRpcMsg rpcMsg; + syncAppendEntriesReply2RpcMsg(pReply, &rpcMsg); + syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg); + syncAppendEntriesReplyDestroy(pReply); + } + + if (pMsg->commitIndex > ths->commitIndex) { + if (pMsg->commitIndex <= ths->pLogStore->getLastIndex(ths->pLogStore)) { + // commit + ths->commitIndex = pMsg->commitIndex; + ths->pLogStore->updateCommitIndex(ths->pLogStore, ths->commitIndex); + } + } + } + + return ret; +} diff --git a/source/libs/sync/src/syncAppendEntriesReply.c b/source/libs/sync/src/syncAppendEntriesReply.c index 0a5120c8dc4b87f36adb63eb82c1ba6362744bf2..61eb4884e2b8e5013adcc6012dec72257d98eac9 100644 --- a/source/libs/sync/src/syncAppendEntriesReply.c +++ b/source/libs/sync/src/syncAppendEntriesReply.c @@ -14,6 +14,12 @@ */ #include "syncAppendEntriesReply.h" +#include "syncIndexMgr.h" +#include "syncInt.h" +#include "syncRaftLog.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" // TLA+ Spec // HandleAppendEntriesResponse(i, j, m) == @@ -28,4 +34,41 @@ // /\ Discard(m) // /\ UNCHANGED <> // -int32_t syncNodeOnAppendEntriesReplyCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg) {} +int32_t syncNodeOnAppendEntriesReplyCb(SSyncNode* ths, SyncAppendEntriesReply* pMsg) { + int32_t ret = 0; + syncAppendEntriesReplyLog2("==syncNodeOnAppendEntriesReplyCb==", pMsg); + + if (pMsg->term < ths->pRaftStore->currentTerm) { + sTrace("DropStaleResponse, receive term:%lu, current term:%lu", pMsg->term, ths->pRaftStore->currentTerm); + return ret; + } + + // no need this code, because if I receive reply.term, then I must have sent for that term. + // if (pMsg->term > ths->pRaftStore->currentTerm) { + // syncNodeUpdateTerm(ths, pMsg->term); + // } + + assert(pMsg->term == ths->pRaftStore->currentTerm); + + if (pMsg->success) { + // nextIndex = reply.matchIndex + 1 + syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), pMsg->matchIndex + 1); + + // matchIndex = reply.matchIndex + syncIndexMgrSetIndex(ths->pMatchIndex, &(pMsg->srcId), pMsg->matchIndex); + + // maybe commit + syncNodeMaybeAdvanceCommitIndex(ths); + + } else { + SyncIndex nextIndex = syncIndexMgrGetIndex(ths->pNextIndex, &(pMsg->srcId)); + if (nextIndex > SYNC_INDEX_BEGIN) { + --nextIndex; + } else { + nextIndex = SYNC_INDEX_BEGIN; + } + syncIndexMgrSetIndex(ths->pNextIndex, &(pMsg->srcId), nextIndex); + } + + return ret; +} diff --git a/source/libs/sync/src/syncElection.c b/source/libs/sync/src/syncElection.c index 87017b718d56b62ec6ace7046a33f86da55fa88f..77c3d076988762713a2ffe354c1e91ca54b2e8bd 100644 --- a/source/libs/sync/src/syncElection.c +++ b/source/libs/sync/src/syncElection.c @@ -15,6 +15,8 @@ #include "syncElection.h" #include "syncMessage.h" +#include "syncRaftStore.h" +#include "syncVoteMgr.h" // TLA+ Spec // RequestVote(i, j) == @@ -28,11 +30,43 @@ // mdest |-> j]) // /\ UNCHANGED <> // -int32_t syncNodeRequestVotePeers(SSyncNode* pSyncNode) {} +int32_t syncNodeRequestVotePeers(SSyncNode* pSyncNode) { + assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE); + + int32_t ret = 0; + for (int i = 0; i < pSyncNode->peersNum; ++i) { + SyncRequestVote* pMsg = syncRequestVoteBuild(); + pMsg->srcId = pSyncNode->myRaftId; + pMsg->destId = pSyncNode->peersId[i]; + pMsg->term = pSyncNode->pRaftStore->currentTerm; + pMsg->lastLogIndex = pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore); + pMsg->lastLogTerm = pSyncNode->pLogStore->getLastTerm(pSyncNode->pLogStore); + + ret = syncNodeRequestVote(pSyncNode, &pSyncNode->peersId[i], pMsg); + assert(ret == 0); + syncRequestVoteDestroy(pMsg); + } + return ret; +} int32_t syncNodeElect(SSyncNode* pSyncNode) { + if (pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER) { + syncNodeFollower2Candidate(pSyncNode); + } + assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE); + // start election - syncNodeRequestVotePeers(pSyncNode); + raftStoreNextTerm(pSyncNode->pRaftStore); + raftStoreClearVote(pSyncNode->pRaftStore); + voteGrantedReset(pSyncNode->pVotesGranted, pSyncNode->pRaftStore->currentTerm); + votesRespondReset(pSyncNode->pVotesRespond, pSyncNode->pRaftStore->currentTerm); + + syncNodeVoteForSelf(pSyncNode); + int32_t ret = syncNodeRequestVotePeers(pSyncNode); + assert(ret == 0); + syncNodeResetElectTimer(pSyncNode); + + return ret; } int32_t syncNodeRequestVote(SSyncNode* pSyncNode, const SRaftId* destRaftId, const SyncRequestVote* pMsg) { diff --git a/source/libs/sync/src/syncEnv.c b/source/libs/sync/src/syncEnv.c index 6917df1597a68f29d2436ce0da39ce17dc7e7bc7..dd7161800dfe1d3f780383dc9bd3787b2e2c2623 100644 --- a/source/libs/sync/src/syncEnv.c +++ b/source/libs/sync/src/syncEnv.c @@ -19,19 +19,18 @@ SSyncEnv *gSyncEnv = NULL; // local function ----------------- -static void syncEnvTick(void *param, void *tmrId); -static int32_t doSyncEnvStart(SSyncEnv *pSyncEnv); -static int32_t doSyncEnvStop(SSyncEnv *pSyncEnv); -static tmr_h doSyncEnvStartTimer(SSyncEnv *pSyncEnv, TAOS_TMR_CALLBACK fp, int mseconds, void *param); -static void doSyncEnvStopTimer(SSyncEnv *pSyncEnv, tmr_h *pTimer); +static SSyncEnv *doSyncEnvStart(); +static int32_t doSyncEnvStop(SSyncEnv *pSyncEnv); +static int32_t doSyncEnvStartTimer(SSyncEnv *pSyncEnv); +static int32_t doSyncEnvStopTimer(SSyncEnv *pSyncEnv); +static void syncEnvTick(void *param, void *tmrId); // -------------------------------- int32_t syncEnvStart() { - int32_t ret; - srand(time(NULL)); - gSyncEnv = (SSyncEnv *)malloc(sizeof(SSyncEnv)); + int32_t ret = 0; + taosSeedRand(taosGetTimestampSec()); + gSyncEnv = doSyncEnvStart(gSyncEnv); assert(gSyncEnv != NULL); - ret = doSyncEnvStart(gSyncEnv); return ret; } @@ -40,31 +39,52 @@ int32_t syncEnvStop() { return ret; } -tmr_h syncEnvStartTimer(TAOS_TMR_CALLBACK fp, int mseconds, void *param) { - return doSyncEnvStartTimer(gSyncEnv, fp, mseconds, param); +int32_t syncEnvStartTimer() { + int32_t ret = doSyncEnvStartTimer(gSyncEnv); + return ret; } -void syncEnvStopTimer(tmr_h *pTimer) { doSyncEnvStopTimer(gSyncEnv, pTimer); } +int32_t syncEnvStopTimer() { + int32_t ret = doSyncEnvStopTimer(gSyncEnv); + return ret; +} // local function ----------------- static void syncEnvTick(void *param, void *tmrId) { SSyncEnv *pSyncEnv = (SSyncEnv *)param; - sTrace("syncEnvTick ... name:%s ", pSyncEnv->name); - - pSyncEnv->pEnvTickTimer = taosTmrStart(syncEnvTick, 1000, pSyncEnv, pSyncEnv->pTimerManager); + if (atomic_load_64(&pSyncEnv->envTickTimerLogicClockUser) <= atomic_load_64(&pSyncEnv->envTickTimerLogicClock)) { + ++(pSyncEnv->envTickTimerCounter); + sTrace( + "syncEnvTick do ... envTickTimerLogicClockUser:%lu, envTickTimerLogicClock:%lu, envTickTimerCounter:%lu, " + "envTickTimerMS:%d, tmrId:%p", + pSyncEnv->envTickTimerLogicClockUser, pSyncEnv->envTickTimerLogicClock, pSyncEnv->envTickTimerCounter, + pSyncEnv->envTickTimerMS, tmrId); + + // do something, tick ... + taosTmrReset(syncEnvTick, pSyncEnv->envTickTimerMS, pSyncEnv, pSyncEnv->pTimerManager, &pSyncEnv->pEnvTickTimer); + } else { + sTrace( + "syncEnvTick pass ... envTickTimerLogicClockUser:%lu, envTickTimerLogicClock:%lu, envTickTimerCounter:%lu, " + "envTickTimerMS:%d, tmrId:%p", + pSyncEnv->envTickTimerLogicClockUser, pSyncEnv->envTickTimerLogicClock, pSyncEnv->envTickTimerCounter, + pSyncEnv->envTickTimerMS, tmrId); + } } -static int32_t doSyncEnvStart(SSyncEnv *pSyncEnv) { - snprintf(pSyncEnv->name, sizeof(pSyncEnv->name), "SyncEnv_%p", pSyncEnv); +static SSyncEnv *doSyncEnvStart() { + SSyncEnv *pSyncEnv = (SSyncEnv *)malloc(sizeof(SSyncEnv)); + assert(pSyncEnv != NULL); + memset(pSyncEnv, 0, sizeof(pSyncEnv)); + + pSyncEnv->envTickTimerCounter = 0; + pSyncEnv->envTickTimerMS = ENV_TICK_TIMER_MS; + pSyncEnv->FpEnvTickTimer = syncEnvTick; + atomic_store_64(&pSyncEnv->envTickTimerLogicClock, 0); + atomic_store_64(&pSyncEnv->envTickTimerLogicClockUser, 0); // start tmr thread pSyncEnv->pTimerManager = taosTmrInit(1000, 50, 10000, "SYNC-ENV"); - - // pSyncEnv->pEnvTickTimer = taosTmrStart(syncEnvTick, 1000, pSyncEnv, pSyncEnv->pTimerManager); - - sTrace("SyncEnv start ok, name:%s", pSyncEnv->name); - - return 0; + return pSyncEnv; } static int32_t doSyncEnvStop(SSyncEnv *pSyncEnv) { @@ -72,8 +92,18 @@ static int32_t doSyncEnvStop(SSyncEnv *pSyncEnv) { return 0; } -static tmr_h doSyncEnvStartTimer(SSyncEnv *pSyncEnv, TAOS_TMR_CALLBACK fp, int mseconds, void *param) { - return taosTmrStart(fp, mseconds, pSyncEnv, pSyncEnv->pTimerManager); +static int32_t doSyncEnvStartTimer(SSyncEnv *pSyncEnv) { + int32_t ret = 0; + taosTmrReset(pSyncEnv->FpEnvTickTimer, pSyncEnv->envTickTimerMS, pSyncEnv, pSyncEnv->pTimerManager, + &pSyncEnv->pEnvTickTimer); + atomic_store_64(&pSyncEnv->envTickTimerLogicClock, pSyncEnv->envTickTimerLogicClockUser); + return ret; } -static void doSyncEnvStopTimer(SSyncEnv *pSyncEnv, tmr_h *pTimer) {} +static int32_t doSyncEnvStopTimer(SSyncEnv *pSyncEnv) { + int32_t ret = 0; + atomic_add_fetch_64(&pSyncEnv->envTickTimerLogicClockUser, 1); + taosTmrStop(pSyncEnv->pEnvTickTimer); + pSyncEnv->pEnvTickTimer = NULL; + return ret; +} diff --git a/source/libs/sync/src/syncIO.c b/source/libs/sync/src/syncIO.c index d37c821a2475790ee5e2ba7c2e127de8f8d49617..c307ec5068f5cd3a74fdba70a4a1f80b5a55980f 100644 --- a/source/libs/sync/src/syncIO.c +++ b/source/libs/sync/src/syncIO.c @@ -15,7 +15,8 @@ #include "syncIO.h" #include -#include "syncOnMessage.h" +#include "syncMessage.h" +#include "syncUtil.h" #include "tglobal.h" #include "ttimer.h" #include "tutil.h" @@ -23,33 +24,36 @@ SSyncIO *gSyncIO = NULL; // local function ------------ -static int32_t syncIOStartInternal(SSyncIO *io); -static int32_t syncIOStopInternal(SSyncIO *io); static SSyncIO *syncIOCreate(char *host, uint16_t port); static int32_t syncIODestroy(SSyncIO *io); +static int32_t syncIOStartInternal(SSyncIO *io); +static int32_t syncIOStopInternal(SSyncIO *io); -static void *syncIOConsumerFunc(void *param); -static int syncIOAuth(void *parent, char *meterId, char *spi, char *encrypt, char *secret, char *ckey); -static void syncIOProcessRequest(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet); -static void syncIOProcessReply(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet); - -static int32_t syncIOTickQInternal(SSyncIO *io); -static void syncIOTickQFunc(void *param, void *tmrId); -static int32_t syncIOTickPingInternal(SSyncIO *io); -static void syncIOTickPingFunc(void *param, void *tmrId); +static void * syncIOConsumerFunc(void *param); +static void syncIOProcessRequest(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet); +static void syncIOProcessReply(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet); +static int32_t syncIOAuth(void *parent, char *meterId, char *spi, char *encrypt, char *secret, char *ckey); + +static int32_t syncIOStartQ(SSyncIO *io); +static int32_t syncIOStopQ(SSyncIO *io); +static int32_t syncIOStartPing(SSyncIO *io); +static int32_t syncIOStopPing(SSyncIO *io); +static void syncIOTickQ(void *param, void *tmrId); +static void syncIOTickPing(void *param, void *tmrId); // ---------------------------- // public function ------------ int32_t syncIOStart(char *host, uint16_t port) { + int32_t ret = 0; gSyncIO = syncIOCreate(host, port); assert(gSyncIO != NULL); - srand(time(NULL)); - int32_t ret = syncIOStartInternal(gSyncIO); + taosSeedRand(taosGetTimestampSec()); + ret = syncIOStartInternal(gSyncIO); assert(ret == 0); - sTrace("syncIOStart ok, gSyncIO:%p gSyncIO->clientRpc:%p", gSyncIO, gSyncIO->clientRpc); - return 0; + sTrace("syncIOStart ok, gSyncIO:%p", gSyncIO); + return ret; } int32_t syncIOStop() { @@ -61,37 +65,25 @@ int32_t syncIOStop() { return ret; } -int32_t syncIOTickQ() { - int32_t ret = syncIOTickQInternal(gSyncIO); - assert(ret == 0); - return ret; -} +int32_t syncIOSendMsg(void *clientRpc, const SEpSet *pEpSet, SRpcMsg *pMsg) { + assert(pEpSet->inUse == 0); + assert(pEpSet->numOfEps == 1); -int32_t syncIOTickPing() { - int32_t ret = syncIOTickPingInternal(gSyncIO); - assert(ret == 0); - return ret; -} + int32_t ret = 0; + char logBuf[256]; + snprintf(logBuf, sizeof(logBuf), "==syncIOSendMsg== %s:%d", pEpSet->eps[0].fqdn, pEpSet->eps[0].port); + syncRpcMsgPrint2(logBuf, pMsg); -int32_t syncIOSendMsg(void *clientRpc, const SEpSet *pEpSet, SRpcMsg *pMsg) { - sTrace( - "<--- syncIOSendMsg ---> clientRpc:%p, numOfEps:%d, inUse:%d, destAddr:%s-%u, pMsg->ahandle:%p, pMsg->handle:%p, " - "pMsg->msgType:%d, pMsg->contLen:%d", - clientRpc, pEpSet->numOfEps, pEpSet->inUse, pEpSet->eps[0].fqdn, pEpSet->eps[0].port, pMsg->ahandle, pMsg->handle, - pMsg->msgType, pMsg->contLen); - { - cJSON *pJson = syncRpcMsg2Json(pMsg); - char * serialized = cJSON_Print(pJson); - sTrace("process syncMessage send: pMsg:%s ", serialized); - free(serialized); - cJSON_Delete(pJson); - } pMsg->handle = NULL; rpcSendRequest(clientRpc, pEpSet, pMsg, NULL); - return 0; + return ret; } int32_t syncIOEqMsg(void *queue, SRpcMsg *pMsg) { + int32_t ret = 0; + char logBuf[128]; + syncRpcMsgPrint2((char *)"==syncIOEqMsg==", pMsg); + SRpcMsg *pTemp; pTemp = taosAllocateQitem(sizeof(SRpcMsg)); memcpy(pTemp, pMsg, sizeof(SRpcMsg)); @@ -99,11 +91,75 @@ int32_t syncIOEqMsg(void *queue, SRpcMsg *pMsg) { STaosQueue *pMsgQ = queue; taosWriteQitem(pMsgQ, pTemp); - return 0; + return ret; +} + +int32_t syncIOQTimerStart() { + int32_t ret = syncIOStartQ(gSyncIO); + assert(ret == 0); + return ret; +} + +int32_t syncIOQTimerStop() { + int32_t ret = syncIOStopQ(gSyncIO); + assert(ret == 0); + return ret; +} + +int32_t syncIOPingTimerStart() { + int32_t ret = syncIOStartPing(gSyncIO); + assert(ret == 0); + return ret; +} + +int32_t syncIOPingTimerStop() { + int32_t ret = syncIOStopPing(gSyncIO); + assert(ret == 0); + return ret; } // local function ------------ +static SSyncIO *syncIOCreate(char *host, uint16_t port) { + SSyncIO *io = (SSyncIO *)malloc(sizeof(SSyncIO)); + memset(io, 0, sizeof(*io)); + + io->pMsgQ = taosOpenQueue(); + io->pQset = taosOpenQset(); + taosAddIntoQset(io->pQset, io->pMsgQ, NULL); + + io->myAddr.inUse = 0; + io->myAddr.numOfEps = 0; + addEpIntoEpSet(&io->myAddr, host, port); + + io->qTimerMS = TICK_Q_TIMER_MS; + io->pingTimerMS = TICK_Ping_TIMER_MS; + + return io; +} + +static int32_t syncIODestroy(SSyncIO *io) { + int32_t ret = 0; + int8_t start = atomic_load_8(&io->isStart); + assert(start == 0); + + if (io->serverRpc != NULL) { + rpcClose(io->serverRpc); + io->serverRpc = NULL; + } + + if (io->clientRpc != NULL) { + rpcClose(io->clientRpc); + io->clientRpc = NULL; + } + + taosCloseQueue(io->pMsgQ); + taosCloseQset(io->pQset); + + return ret; +} + static int32_t syncIOStartInternal(SSyncIO *io) { + int32_t ret = 0; taosBlockSIGPIPE(); rpcInit(); @@ -163,135 +219,96 @@ static int32_t syncIOStartInternal(SSyncIO *io) { } // start tmr thread - io->ioTimerManager = taosTmrInit(1000, 50, 10000, "SYNC"); + io->timerMgr = taosTmrInit(1000, 50, 10000, "SYNC-IO"); - return 0; + atomic_store_8(&io->isStart, 1); + return ret; } static int32_t syncIOStopInternal(SSyncIO *io) { + int32_t ret = 0; atomic_store_8(&io->isStart, 0); pthread_join(io->consumerTid, NULL); - return 0; -} - -static SSyncIO *syncIOCreate(char *host, uint16_t port) { - SSyncIO *io = (SSyncIO *)malloc(sizeof(SSyncIO)); - memset(io, 0, sizeof(*io)); - - io->pMsgQ = taosOpenQueue(); - io->pQset = taosOpenQset(); - taosAddIntoQset(io->pQset, io->pMsgQ, NULL); - - io->myAddr.inUse = 0; - addEpIntoEpSet(&io->myAddr, host, port); - - return io; -} - -static int32_t syncIODestroy(SSyncIO *io) { - int8_t start = atomic_load_8(&io->isStart); - assert(start == 0); - - if (io->serverRpc != NULL) { - free(io->serverRpc); - io->serverRpc = NULL; - } - - if (io->clientRpc != NULL) { - free(io->clientRpc); - io->clientRpc = NULL; - } - - taosCloseQueue(io->pMsgQ); - taosCloseQset(io->pQset); - - return 0; + taosTmrCleanUp(io->timerMgr); + return ret; } static void *syncIOConsumerFunc(void *param) { - SSyncIO *io = param; - + SSyncIO * io = param; STaosQall *qall; SRpcMsg * pRpcMsg, rpcMsg; - int type; - qall = taosAllocateQall(); while (1) { int numOfMsgs = taosReadAllQitemsFromQset(io->pQset, qall, NULL, NULL); sTrace("syncIOConsumerFunc %d msgs are received", numOfMsgs); - if (numOfMsgs <= 0) break; + if (numOfMsgs <= 0) { + break; + } for (int i = 0; i < numOfMsgs; ++i) { taosGetQitem(qall, (void **)&pRpcMsg); - sTrace("syncIOConsumerFunc get item from queue: msgType:%d contLen:%d msg:%s", pRpcMsg->msgType, pRpcMsg->contLen, - (char *)(pRpcMsg->pCont)); + syncRpcMsgLog2((char *)"==syncIOConsumerFunc==", pRpcMsg); + // use switch case instead of if else if (pRpcMsg->msgType == SYNC_PING) { if (io->FpOnSyncPing != NULL) { - SyncPing *pSyncMsg; + SyncPing *pSyncMsg = syncPingFromRpcMsg2(pRpcMsg); + assert(pSyncMsg != NULL); + io->FpOnSyncPing(io->pSyncNode, pSyncMsg); + syncPingDestroy(pSyncMsg); + /* pSyncMsg = syncPingBuild(pRpcMsg->contLen); syncPingFromRpcMsg(pRpcMsg, pSyncMsg); // memcpy(pSyncMsg, tmpRpcMsg.pCont, tmpRpcMsg.contLen); io->FpOnSyncPing(io->pSyncNode, pSyncMsg); syncPingDestroy(pSyncMsg); + */ } } else if (pRpcMsg->msgType == SYNC_PING_REPLY) { if (io->FpOnSyncPingReply != NULL) { - SyncPingReply *pSyncMsg; - pSyncMsg = syncPingReplyBuild(pRpcMsg->contLen); - syncPingReplyFromRpcMsg(pRpcMsg, pSyncMsg); + SyncPingReply *pSyncMsg = syncPingReplyFromRpcMsg2(pRpcMsg); io->FpOnSyncPingReply(io->pSyncNode, pSyncMsg); syncPingReplyDestroy(pSyncMsg); } } else if (pRpcMsg->msgType == SYNC_REQUEST_VOTE) { - if (io->FpOnSyncRequestVote) { - SyncRequestVote *pSyncMsg; - pSyncMsg = syncRequestVoteBuild(pRpcMsg->contLen); - syncRequestVoteFromRpcMsg(pRpcMsg, pSyncMsg); + if (io->FpOnSyncRequestVote != NULL) { + SyncRequestVote *pSyncMsg = syncRequestVoteFromRpcMsg2(pRpcMsg); io->FpOnSyncRequestVote(io->pSyncNode, pSyncMsg); syncRequestVoteDestroy(pSyncMsg); } } else if (pRpcMsg->msgType == SYNC_REQUEST_VOTE_REPLY) { - if (io->FpOnSyncRequestVoteReply) { - SyncRequestVoteReply *pSyncMsg; - pSyncMsg = SyncRequestVoteReplyBuild(); - syncRequestVoteReplyFromRpcMsg(pRpcMsg, pSyncMsg); + if (io->FpOnSyncRequestVoteReply != NULL) { + SyncRequestVoteReply *pSyncMsg = syncRequestVoteReplyFromRpcMsg2(pRpcMsg); io->FpOnSyncRequestVoteReply(io->pSyncNode, pSyncMsg); syncRequestVoteReplyDestroy(pSyncMsg); } } else if (pRpcMsg->msgType == SYNC_APPEND_ENTRIES) { - if (io->FpOnSyncAppendEntries) { - SyncAppendEntries *pSyncMsg; - pSyncMsg = syncAppendEntriesBuild(pRpcMsg->contLen); - syncAppendEntriesFromRpcMsg(pRpcMsg, pSyncMsg); + if (io->FpOnSyncAppendEntries != NULL) { + SyncAppendEntries *pSyncMsg = syncAppendEntriesFromRpcMsg2(pRpcMsg); io->FpOnSyncAppendEntries(io->pSyncNode, pSyncMsg); syncAppendEntriesDestroy(pSyncMsg); } } else if (pRpcMsg->msgType == SYNC_APPEND_ENTRIES_REPLY) { - if (io->FpOnSyncAppendEntriesReply) { - SyncAppendEntriesReply *pSyncMsg; - pSyncMsg = syncAppendEntriesReplyBuild(); - syncAppendEntriesReplyFromRpcMsg(pRpcMsg, pSyncMsg); + if (io->FpOnSyncAppendEntriesReply != NULL) { + SyncAppendEntriesReply *pSyncMsg = syncAppendEntriesReplyFromRpcMsg2(pRpcMsg); io->FpOnSyncAppendEntriesReply(io->pSyncNode, pSyncMsg); syncAppendEntriesReplyDestroy(pSyncMsg); } } else if (pRpcMsg->msgType == SYNC_TIMEOUT) { if (io->FpOnSyncTimeout != NULL) { - SyncTimeout *pSyncMsg; - pSyncMsg = syncTimeoutBuild(); - syncTimeoutFromRpcMsg(pRpcMsg, pSyncMsg); + SyncTimeout *pSyncMsg = syncTimeoutFromRpcMsg2(pRpcMsg); io->FpOnSyncTimeout(io->pSyncNode, pSyncMsg); syncTimeoutDestroy(pSyncMsg); } } else { - ; + sTrace("unknown msgType:%d, no operator", pRpcMsg->msgType); } } @@ -301,15 +318,16 @@ static void *syncIOConsumerFunc(void *param) { rpcFreeCont(pRpcMsg->pCont); if (pRpcMsg->handle != NULL) { - int msgSize = 128; + int msgSize = 32; memset(&rpcMsg, 0, sizeof(rpcMsg)); + rpcMsg.msgType = SYNC_RESPONSE; rpcMsg.pCont = rpcMallocCont(msgSize); rpcMsg.contLen = msgSize; snprintf(rpcMsg.pCont, rpcMsg.contLen, "%s", "give a reply"); rpcMsg.handle = pRpcMsg->handle; rpcMsg.code = 0; - sTrace("syncIOConsumerFunc rpcSendResponse ... msgType:%d contLen:%d", pRpcMsg->msgType, rpcMsg.contLen); + syncRpcMsgPrint2((char *)"syncIOConsumerFunc rpcSendResponse --> ", &rpcMsg); rpcSendResponse(&rpcMsg); } @@ -321,71 +339,95 @@ static void *syncIOConsumerFunc(void *param) { return NULL; } -static int syncIOAuth(void *parent, char *meterId, char *spi, char *encrypt, char *secret, char *ckey) { - // app shall retrieve the auth info based on meterID from DB or a data file - // demo code here only for simple demo - int ret = 0; - return ret; -} - static void syncIOProcessRequest(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet) { - sTrace("<-- syncIOProcessRequest --> type:%d, contLen:%d, cont:%s", pMsg->msgType, pMsg->contLen, - (char *)pMsg->pCont); - + syncRpcMsgPrint2((char *)"==syncIOProcessRequest==", pMsg); SSyncIO *io = pParent; SRpcMsg *pTemp; - pTemp = taosAllocateQitem(sizeof(SRpcMsg)); memcpy(pTemp, pMsg, sizeof(SRpcMsg)); - taosWriteQitem(io->pMsgQ, pTemp); } static void syncIOProcessReply(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet) { - sTrace("syncIOProcessReply: type:%d, contLen:%d msg:%s", pMsg->msgType, pMsg->contLen, (char *)pMsg->pCont); + if (pMsg->msgType == SYNC_RESPONSE) { + sTrace("==syncIOProcessReply=="); + } else { + syncRpcMsgPrint2((char *)"==syncIOProcessReply==", pMsg); + } rpcFreeCont(pMsg->pCont); } -static int32_t syncIOTickQInternal(SSyncIO *io) { - io->ioTimerTickQ = taosTmrStart(syncIOTickQFunc, 1000, io, io->ioTimerManager); - return 0; +static int32_t syncIOAuth(void *parent, char *meterId, char *spi, char *encrypt, char *secret, char *ckey) { + // app shall retrieve the auth info based on meterID from DB or a data file + // demo code here only for simple demo + int32_t ret = 0; + return ret; +} + +static int32_t syncIOStartQ(SSyncIO *io) { + int32_t ret = 0; + taosTmrReset(syncIOTickQ, io->qTimerMS, io, io->timerMgr, &io->qTimer); + return ret; } -static void syncIOTickQFunc(void *param, void *tmrId) { +static int32_t syncIOStopQ(SSyncIO *io) { + int32_t ret = 0; + taosTmrStop(io->qTimer); + io->qTimer = NULL; + return ret; +} + +static int32_t syncIOStartPing(SSyncIO *io) { + int32_t ret = 0; + taosTmrReset(syncIOTickPing, io->pingTimerMS, io, io->timerMgr, &io->pingTimer); + return ret; +} + +static int32_t syncIOStopPing(SSyncIO *io) { + int32_t ret = 0; + taosTmrStop(io->pingTimer); + io->pingTimer = NULL; + return ret; +} + +static void syncIOTickQ(void *param, void *tmrId) { SSyncIO *io = (SSyncIO *)param; - sTrace("<-- syncIOTickQFunc -->"); - SRpcMsg rpcMsg; - rpcMsg.contLen = 64; - rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen); - snprintf(rpcMsg.pCont, rpcMsg.contLen, "%s", "syncIOTickQ"); - rpcMsg.handle = NULL; - rpcMsg.msgType = 55; + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64(io->myAddr.eps[0].fqdn, io->myAddr.eps[0].port); + srcId.vgId = -1; + destId.addr = syncUtilAddr2U64(io->myAddr.eps[0].fqdn, io->myAddr.eps[0].port); + destId.vgId = -1; + SyncPingReply *pMsg = syncPingReplyBuild2(&srcId, &destId, "syncIOTickQ"); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pMsg, &rpcMsg); SRpcMsg *pTemp; pTemp = taosAllocateQitem(sizeof(SRpcMsg)); memcpy(pTemp, &rpcMsg, sizeof(SRpcMsg)); - + syncRpcMsgPrint2((char *)"==syncIOTickQ==", &rpcMsg); taosWriteQitem(io->pMsgQ, pTemp); - taosTmrReset(syncIOTickQFunc, 1000, io, io->ioTimerManager, &io->ioTimerTickQ); -} + syncPingReplyDestroy(pMsg); -static int32_t syncIOTickPingInternal(SSyncIO *io) { - io->ioTimerTickPing = taosTmrStart(syncIOTickPingFunc, 1000, io, io->ioTimerManager); - return 0; + taosTmrReset(syncIOTickQ, io->qTimerMS, io, io->timerMgr, &io->qTimer); } -static void syncIOTickPingFunc(void *param, void *tmrId) { +static void syncIOTickPing(void *param, void *tmrId) { SSyncIO *io = (SSyncIO *)param; - sTrace("<-- syncIOTickPingFunc -->"); - SRpcMsg rpcMsg; - rpcMsg.contLen = 64; - rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen); - snprintf(rpcMsg.pCont, rpcMsg.contLen, "%s", "syncIOTickPing"); - rpcMsg.handle = NULL; - rpcMsg.msgType = 77; + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64(io->myAddr.eps[0].fqdn, io->myAddr.eps[0].port); + srcId.vgId = -1; + destId.addr = syncUtilAddr2U64(io->myAddr.eps[0].fqdn, io->myAddr.eps[0].port); + destId.vgId = -1; + SyncPing *pMsg = syncPingBuild2(&srcId, &destId, "syncIOTickPing"); + // SyncPing *pMsg = syncPingBuild3(&srcId, &destId); + SRpcMsg rpcMsg; + syncPing2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"==syncIOTickPing==", &rpcMsg); rpcSendRequest(io->clientRpc, &io->myAddr, &rpcMsg, NULL); - taosTmrReset(syncIOTickPingFunc, 1000, io, io->ioTimerManager, &io->ioTimerTickPing); + syncPingDestroy(pMsg); + + taosTmrReset(syncIOTickPing, io->pingTimerMS, io, io->timerMgr, &io->pingTimer); } \ No newline at end of file diff --git a/source/libs/sync/src/syncIndexMgr.c b/source/libs/sync/src/syncIndexMgr.c new file mode 100644 index 0000000000000000000000000000000000000000..95679381978e8c7e574858e87f7e0cf5f93895e4 --- /dev/null +++ b/source/libs/sync/src/syncIndexMgr.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "syncIndexMgr.h" +#include "syncUtil.h" + +// SMatchIndex ----------------------------- + +SSyncIndexMgr *syncIndexMgrCreate(SSyncNode *pSyncNode) { + SSyncIndexMgr *pSyncIndexMgr = malloc(sizeof(SSyncIndexMgr)); + assert(pSyncIndexMgr != NULL); + memset(pSyncIndexMgr, 0, sizeof(SSyncIndexMgr)); + + pSyncIndexMgr->replicas = &(pSyncNode->replicasId); + pSyncIndexMgr->replicaNum = pSyncNode->replicaNum; + pSyncIndexMgr->pSyncNode = pSyncNode; + syncIndexMgrClear(pSyncIndexMgr); + + return pSyncIndexMgr; +} + +void syncIndexMgrDestroy(SSyncIndexMgr *pSyncIndexMgr) { + if (pSyncIndexMgr != NULL) { + free(pSyncIndexMgr); + } +} + +void syncIndexMgrClear(SSyncIndexMgr *pSyncIndexMgr) { + memset(pSyncIndexMgr->index, 0, sizeof(pSyncIndexMgr->index)); + /* + for (int i = 0; i < pSyncIndexMgr->replicaNum; ++i) { + pSyncIndexMgr->index[i] = 0; + } + */ +} + +void syncIndexMgrSetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId, SyncIndex index) { + for (int i = 0; i < pSyncIndexMgr->replicaNum; ++i) { + if (syncUtilSameId(&((*(pSyncIndexMgr->replicas))[i]), pRaftId)) { + (pSyncIndexMgr->index)[i] = index; + return; + } + } + assert(0); +} + +SyncIndex syncIndexMgrGetIndex(SSyncIndexMgr *pSyncIndexMgr, const SRaftId *pRaftId) { + for (int i = 0; i < pSyncIndexMgr->replicaNum; ++i) { + if (syncUtilSameId(&((*(pSyncIndexMgr->replicas))[i]), pRaftId)) { + SyncIndex idx = (pSyncIndexMgr->index)[i]; + return idx; + } + } + assert(0); +} + +cJSON *syncIndexMgr2Json(SSyncIndexMgr *pSyncIndexMgr) { + char u64buf[128]; + cJSON *pRoot = cJSON_CreateObject(); + + cJSON_AddNumberToObject(pRoot, "replicaNum", pSyncIndexMgr->replicaNum); + cJSON *pReplicas = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "replicas", pReplicas); + for (int i = 0; i < pSyncIndexMgr->replicaNum; ++i) { + cJSON_AddItemToArray(pReplicas, syncUtilRaftId2Json(&(*(pSyncIndexMgr->replicas))[i])); + } + int respondNum = 0; + int *arr = (int *)malloc(sizeof(int) * pSyncIndexMgr->replicaNum); + for (int i = 0; i < pSyncIndexMgr->replicaNum; ++i) { + arr[i] = pSyncIndexMgr->index[i]; + } + cJSON *pIndex = cJSON_CreateIntArray(arr, pSyncIndexMgr->replicaNum); + free(arr); + cJSON_AddItemToObject(pRoot, "index", pIndex); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncIndexMgr->pSyncNode); + cJSON_AddStringToObject(pRoot, "pSyncNode", u64buf); + + cJSON *pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "pSyncIndexMgr", pRoot); + return pJson; +} + +char *syncIndexMgr2Str(SSyncIndexMgr *pSyncIndexMgr) { + cJSON *pJson = syncIndexMgr2Json(pSyncIndexMgr); + char * serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ------------------- +void syncIndexMgrPrint(SSyncIndexMgr *pObj) { + char *serialized = syncIndexMgr2Str(pObj); + printf("syncIndexMgrPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncIndexMgrPrint2(char *s, SSyncIndexMgr *pObj) { + char *serialized = syncIndexMgr2Str(pObj); + printf("syncIndexMgrPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncIndexMgrLog(SSyncIndexMgr *pObj) { + char *serialized = syncIndexMgr2Str(pObj); + sTrace("syncIndexMgrLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncIndexMgrLog2(char *s, SSyncIndexMgr *pObj) { + char *serialized = syncIndexMgr2Str(pObj); + sTrace("syncIndexMgrLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} \ No newline at end of file diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index db34d16690e1acc2e7f5bd3ed88bb168b0e0e32a..aaf6535f402fd1757433ca9253a5b04b28f9da0b 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -17,90 +17,160 @@ #include "sync.h" #include "syncAppendEntries.h" #include "syncAppendEntriesReply.h" +#include "syncElection.h" #include "syncEnv.h" +#include "syncIndexMgr.h" #include "syncInt.h" -#include "syncRaft.h" +#include "syncMessage.h" +#include "syncRaftLog.h" +#include "syncRaftStore.h" +#include "syncReplication.h" #include "syncRequestVote.h" #include "syncRequestVoteReply.h" #include "syncTimeout.h" #include "syncUtil.h" +#include "syncVoteMgr.h" static int32_t tsNodeRefId = -1; // ------ local funciton --------- +// enqueue message ---- static void syncNodeEqPingTimer(void* param, void* tmrId); static void syncNodeEqElectTimer(void* param, void* tmrId); static void syncNodeEqHeartbeatTimer(void* param, void* tmrId); +// on message ---- static int32_t syncNodeOnPingCb(SSyncNode* ths, SyncPing* pMsg); static int32_t syncNodeOnPingReplyCb(SSyncNode* ths, SyncPingReply* pMsg); - -static void syncNodeBecomeFollower(SSyncNode* pSyncNode); -static void syncNodeBecomeLeader(SSyncNode* pSyncNode); -static void syncNodeFollower2Candidate(SSyncNode* pSyncNode); -static void syncNodeCandidate2Leader(SSyncNode* pSyncNode); -static void syncNodeLeader2Follower(SSyncNode* pSyncNode); -static void syncNodeCandidate2Follower(SSyncNode* pSyncNode); // --------------------------------- int32_t syncInit() { - sTrace("syncInit ok"); - return 0; + int32_t ret = syncEnvStart(); + return ret; } -void syncCleanUp() { sTrace("syncCleanUp ok"); } +void syncCleanUp() { + int32_t ret = syncEnvStop(); + assert(ret == 0); +} int64_t syncStart(const SSyncInfo* pSyncInfo) { + int32_t ret = 0; SSyncNode* pSyncNode = syncNodeOpen(pSyncInfo); assert(pSyncNode != NULL); - return 0; + return ret; } -void syncStop(int64_t rid) {} +void syncStop(int64_t rid) { + SSyncNode* pSyncNode = NULL; // get pointer from rid + syncNodeClose(pSyncNode); +} -int32_t syncReconfig(int64_t rid, const SSyncCfg* pSyncCfg) { return 0; } +int32_t syncReconfig(int64_t rid, const SSyncCfg* pSyncCfg) { + int32_t ret = 0; + return ret; +} -int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pBuf, bool isWeak) { return 0; } +int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pMsg, bool isWeak) { + int32_t ret = 0; + SSyncNode* pSyncNode = NULL; // get pointer from rid + if (pSyncNode->state == TAOS_SYNC_STATE_LEADER) { + SyncClientRequest* pSyncMsg = syncClientRequestBuild2(pMsg, 0, isWeak); + SRpcMsg rpcMsg; + syncClientRequest2RpcMsg(pSyncMsg, &rpcMsg); + pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); + syncClientRequestDestroy(pSyncMsg); + ret = 0; -ESyncState syncGetMyRole(int64_t rid) { return TAOS_SYNC_STATE_LEADER; } + } else { + sTrace("syncForwardToPeer not leader, %s", syncUtilState2String(pSyncNode->state)); + ret = -1; // need define err code !! + } + return ret; +} + +ESyncState syncGetMyRole(int64_t rid) { + SSyncNode* pSyncNode = NULL; // get pointer from rid + return pSyncNode->state; +} void syncGetNodesRole(int64_t rid, SNodesRole* pNodeRole) {} +// open/close -------------- SSyncNode* syncNodeOpen(const SSyncInfo* pSyncInfo) { SSyncNode* pSyncNode = (SSyncNode*)malloc(sizeof(SSyncNode)); assert(pSyncNode != NULL); memset(pSyncNode, 0, sizeof(SSyncNode)); + // init by SSyncInfo pSyncNode->vgId = pSyncInfo->vgId; pSyncNode->syncCfg = pSyncInfo->syncCfg; memcpy(pSyncNode->path, pSyncInfo->path, sizeof(pSyncNode->path)); - pSyncNode->pFsm = pSyncInfo->pFsm; - + snprintf(pSyncNode->raftStorePath, sizeof(pSyncNode->raftStorePath), "%s/raft_store.json", pSyncInfo->path); + pSyncNode->pWal = pSyncInfo->pWal; pSyncNode->rpcClient = pSyncInfo->rpcClient; pSyncNode->FpSendMsg = pSyncInfo->FpSendMsg; pSyncNode->queue = pSyncInfo->queue; pSyncNode->FpEqMsg = pSyncInfo->FpEqMsg; - pSyncNode->me = pSyncInfo->syncCfg.nodeInfo[pSyncInfo->syncCfg.myIndex]; - pSyncNode->peersNum = pSyncInfo->syncCfg.replicaNum - 1; + // init internal + pSyncNode->myNodeInfo = pSyncInfo->syncCfg.nodeInfo[pSyncInfo->syncCfg.myIndex]; + syncUtilnodeInfo2raftId(&pSyncNode->myNodeInfo, pSyncInfo->vgId, &pSyncNode->myRaftId); + // init peersNum, peers, peersId + pSyncNode->peersNum = pSyncInfo->syncCfg.replicaNum - 1; int j = 0; for (int i = 0; i < pSyncInfo->syncCfg.replicaNum; ++i) { if (i != pSyncInfo->syncCfg.myIndex) { - pSyncNode->peers[j] = pSyncInfo->syncCfg.nodeInfo[i]; + pSyncNode->peersNodeInfo[j] = pSyncInfo->syncCfg.nodeInfo[i]; j++; } } + for (int i = 0; i < pSyncNode->peersNum; ++i) { + syncUtilnodeInfo2raftId(&pSyncNode->peersNodeInfo[i], pSyncInfo->vgId, &pSyncNode->peersId[i]); + } + // init replicaNum, replicasId + pSyncNode->replicaNum = pSyncInfo->syncCfg.replicaNum; + for (int i = 0; i < pSyncInfo->syncCfg.replicaNum; ++i) { + syncUtilnodeInfo2raftId(&pSyncInfo->syncCfg.nodeInfo[i], pSyncInfo->vgId, &pSyncNode->replicasId[i]); + } + + // init raft algorithm + pSyncNode->pFsm = pSyncInfo->pFsm; + pSyncNode->quorum = syncUtilQuorum(pSyncInfo->syncCfg.replicaNum); + pSyncNode->leaderCache = EMPTY_RAFT_ID; + + // init life cycle + + // init TLA+ server vars pSyncNode->state = TAOS_SYNC_STATE_FOLLOWER; - syncUtilnodeInfo2raftId(&pSyncNode->me, pSyncNode->vgId, &pSyncNode->raftId); + pSyncNode->pRaftStore = raftStoreOpen(pSyncNode->raftStorePath); + assert(pSyncNode->pRaftStore != NULL); + + // init TLA+ candidate vars + pSyncNode->pVotesGranted = voteGrantedCreate(pSyncNode); + assert(pSyncNode->pVotesGranted != NULL); + pSyncNode->pVotesRespond = votesRespondCreate(pSyncNode); + assert(pSyncNode->pVotesRespond != NULL); + + // init TLA+ leader vars + pSyncNode->pNextIndex = syncIndexMgrCreate(pSyncNode); + assert(pSyncNode->pNextIndex != NULL); + pSyncNode->pMatchIndex = syncIndexMgrCreate(pSyncNode); + assert(pSyncNode->pMatchIndex != NULL); + + // init TLA+ log vars + pSyncNode->pLogStore = logStoreCreate(pSyncNode); + assert(pSyncNode->pLogStore != NULL); + pSyncNode->commitIndex = 0; // init ping timer pSyncNode->pPingTimer = NULL; pSyncNode->pingTimerMS = PING_TIMER_MS; atomic_store_64(&pSyncNode->pingTimerLogicClock, 0); atomic_store_64(&pSyncNode->pingTimerLogicClockUser, 0); - pSyncNode->FpPingTimer = syncNodeEqPingTimer; + pSyncNode->FpPingTimerCB = syncNodeEqPingTimer; pSyncNode->pingTimerCounter = 0; // init elect timer @@ -108,7 +178,7 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pSyncInfo) { pSyncNode->electTimerMS = syncUtilElectRandomMS(); atomic_store_64(&pSyncNode->electTimerLogicClock, 0); atomic_store_64(&pSyncNode->electTimerLogicClockUser, 0); - pSyncNode->FpElectTimer = syncNodeEqElectTimer; + pSyncNode->FpElectTimerCB = syncNodeEqElectTimer; pSyncNode->electTimerCounter = 0; // init heartbeat timer @@ -116,9 +186,10 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pSyncInfo) { pSyncNode->heartbeatTimerMS = HEARTBEAT_TIMER_MS; atomic_store_64(&pSyncNode->heartbeatTimerLogicClock, 0); atomic_store_64(&pSyncNode->heartbeatTimerLogicClockUser, 0); - pSyncNode->FpHeartbeatTimer = syncNodeEqHeartbeatTimer; + pSyncNode->FpHeartbeatTimerCB = syncNodeEqHeartbeatTimer; pSyncNode->heartbeatTimerCounter = 0; + // init callback pSyncNode->FpOnPing = syncNodeOnPingCb; pSyncNode->FpOnPingReply = syncNodeOnPingReplyCb; pSyncNode->FpOnRequestVote = syncNodeOnRequestVoteCb; @@ -131,236 +202,311 @@ SSyncNode* syncNodeOpen(const SSyncInfo* pSyncInfo) { } void syncNodeClose(SSyncNode* pSyncNode) { + int32_t ret; assert(pSyncNode != NULL); - free(pSyncNode); -} -int32_t syncNodeSendMsgById(const SRaftId* destRaftId, SSyncNode* pSyncNode, SRpcMsg* pMsg) { - SEpSet epSet; - syncUtilraftId2EpSet(destRaftId, &epSet); - pSyncNode->FpSendMsg(pSyncNode->rpcClient, &epSet, pMsg); - return 0; -} + ret = raftStoreClose(pSyncNode->pRaftStore); + assert(ret == 0); -int32_t syncNodeSendMsgByInfo(const SNodeInfo* nodeInfo, SSyncNode* pSyncNode, SRpcMsg* pMsg) { - SEpSet epSet; - syncUtilnodeInfo2EpSet(nodeInfo, &epSet); - pSyncNode->FpSendMsg(pSyncNode->rpcClient, &epSet, pMsg); - return 0; + voteGrantedDestroy(pSyncNode->pVotesGranted); + votesRespondDestory(pSyncNode->pVotesRespond); + syncIndexMgrDestroy(pSyncNode->pNextIndex); + syncIndexMgrDestroy(pSyncNode->pMatchIndex); + logStoreDestory(pSyncNode->pLogStore); + + syncNodeStopPingTimer(pSyncNode); + syncNodeStopElectTimer(pSyncNode); + syncNodeStopHeartbeatTimer(pSyncNode); + + free(pSyncNode); } +// ping -------------- int32_t syncNodePing(SSyncNode* pSyncNode, const SRaftId* destRaftId, SyncPing* pMsg) { - sTrace("syncNodePing pSyncNode:%p ", pSyncNode); + syncPingLog2((char*)"==syncNodePing==", pMsg); int32_t ret = 0; SRpcMsg rpcMsg; syncPing2RpcMsg(pMsg, &rpcMsg); - syncNodeSendMsgById(destRaftId, pSyncNode, &rpcMsg); - - { - cJSON* pJson = syncPing2Json(pMsg); - char* serialized = cJSON_Print(pJson); - sTrace("syncNodePing pMsg:%s ", serialized); - free(serialized); - cJSON_Delete(pJson); - } + syncRpcMsgLog2((char*)"==syncNodePing==", &rpcMsg); - { - SyncPing* pMsg2 = rpcMsg.pCont; - cJSON* pJson = syncPing2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - sTrace("syncNodePing rpcMsg.pCont:%s ", serialized); - free(serialized); - cJSON_Delete(pJson); - } + ret = syncNodeSendMsgById(destRaftId, pSyncNode, &rpcMsg); + return ret; +} + +int32_t syncNodePingSelf(SSyncNode* pSyncNode) { + int32_t ret = 0; + SyncPing* pMsg = syncPingBuild3(&pSyncNode->myRaftId, &pSyncNode->myRaftId); + ret = syncNodePing(pSyncNode, &pMsg->destId, pMsg); + assert(ret == 0); + syncPingDestroy(pMsg); return ret; } -int32_t syncNodePingAll(SSyncNode* pSyncNode) { - sTrace("syncNodePingAll pSyncNode:%p ", pSyncNode); +int32_t syncNodePingPeers(SSyncNode* pSyncNode) { int32_t ret = 0; - for (int i = 0; i < pSyncNode->syncCfg.replicaNum; ++i) { + for (int i = 0; i < pSyncNode->peersNum; ++i) { SRaftId destId; - syncUtilnodeInfo2raftId(&pSyncNode->syncCfg.nodeInfo[i], pSyncNode->vgId, &destId); - SyncPing* pMsg = syncPingBuild3(&pSyncNode->raftId, &destId); + syncUtilnodeInfo2raftId(&pSyncNode->peersNodeInfo[i], pSyncNode->vgId, &destId); + SyncPing* pMsg = syncPingBuild3(&pSyncNode->myRaftId, &destId); ret = syncNodePing(pSyncNode, &destId, pMsg); assert(ret == 0); syncPingDestroy(pMsg); } + return ret; } -int32_t syncNodePingPeers(SSyncNode* pSyncNode) { +int32_t syncNodePingAll(SSyncNode* pSyncNode) { int32_t ret = 0; - for (int i = 0; i < pSyncNode->peersNum; ++i) { + for (int i = 0; i < pSyncNode->syncCfg.replicaNum; ++i) { SRaftId destId; - syncUtilnodeInfo2raftId(&pSyncNode->peers[i], pSyncNode->vgId, &destId); - SyncPing* pMsg = syncPingBuild3(&pSyncNode->raftId, &destId); + syncUtilnodeInfo2raftId(&pSyncNode->syncCfg.nodeInfo[i], pSyncNode->vgId, &destId); + SyncPing* pMsg = syncPingBuild3(&pSyncNode->myRaftId, &destId); ret = syncNodePing(pSyncNode, &destId, pMsg); assert(ret == 0); syncPingDestroy(pMsg); } + return ret; } -int32_t syncNodePingSelf(SSyncNode* pSyncNode) { - int32_t ret; - SyncPing* pMsg = syncPingBuild3(&pSyncNode->raftId, &pSyncNode->raftId); - ret = syncNodePing(pSyncNode, &pMsg->destId, pMsg); - assert(ret == 0); - syncPingDestroy(pMsg); -} - +// timer control -------------- int32_t syncNodeStartPingTimer(SSyncNode* pSyncNode) { + int32_t ret = 0; + taosTmrReset(pSyncNode->FpPingTimerCB, pSyncNode->pingTimerMS, pSyncNode, gSyncEnv->pTimerManager, + &pSyncNode->pPingTimer); atomic_store_64(&pSyncNode->pingTimerLogicClock, pSyncNode->pingTimerLogicClockUser); - pSyncNode->pingTimerMS = PING_TIMER_MS; - if (pSyncNode->pPingTimer == NULL) { - pSyncNode->pPingTimer = - taosTmrStart(pSyncNode->FpPingTimer, pSyncNode->pingTimerMS, pSyncNode, gSyncEnv->pTimerManager); - } else { - taosTmrReset(pSyncNode->FpPingTimer, pSyncNode->pingTimerMS, pSyncNode, gSyncEnv->pTimerManager, - &pSyncNode->pPingTimer); - } - return 0; + return ret; } int32_t syncNodeStopPingTimer(SSyncNode* pSyncNode) { + int32_t ret = 0; atomic_add_fetch_64(&pSyncNode->pingTimerLogicClockUser, 1); - pSyncNode->pingTimerMS = TIMER_MAX_MS; - return 0; + taosTmrStop(pSyncNode->pPingTimer); + pSyncNode->pPingTimer = NULL; + return ret; } int32_t syncNodeStartElectTimer(SSyncNode* pSyncNode, int32_t ms) { + int32_t ret = 0; pSyncNode->electTimerMS = ms; + taosTmrReset(pSyncNode->FpElectTimerCB, pSyncNode->electTimerMS, pSyncNode, gSyncEnv->pTimerManager, + &pSyncNode->pElectTimer); atomic_store_64(&pSyncNode->electTimerLogicClock, pSyncNode->electTimerLogicClockUser); - if (pSyncNode->pElectTimer == NULL) { - pSyncNode->pElectTimer = - taosTmrStart(pSyncNode->FpElectTimer, pSyncNode->electTimerMS, pSyncNode, gSyncEnv->pTimerManager); - } else { - taosTmrReset(pSyncNode->FpElectTimer, pSyncNode->electTimerMS, pSyncNode, gSyncEnv->pTimerManager, - &pSyncNode->pElectTimer); - } - return 0; + return ret; } int32_t syncNodeStopElectTimer(SSyncNode* pSyncNode) { + int32_t ret = 0; atomic_add_fetch_64(&pSyncNode->electTimerLogicClockUser, 1); - pSyncNode->electTimerMS = TIMER_MAX_MS; - return 0; + taosTmrStop(pSyncNode->pElectTimer); + pSyncNode->pElectTimer = NULL; + return ret; } int32_t syncNodeRestartElectTimer(SSyncNode* pSyncNode, int32_t ms) { + int32_t ret = 0; syncNodeStopElectTimer(pSyncNode); syncNodeStartElectTimer(pSyncNode, ms); - return 0; -} - -int32_t syncNodeStartHeartbeatTimer(SSyncNode* pSyncNode) { - atomic_store_64(&pSyncNode->heartbeatTimerLogicClock, pSyncNode->heartbeatTimerLogicClockUser); - if (pSyncNode->pHeartbeatTimer == NULL) { - pSyncNode->pHeartbeatTimer = - taosTmrStart(pSyncNode->FpHeartbeatTimer, pSyncNode->heartbeatTimerMS, pSyncNode, gSyncEnv->pTimerManager); - } else { - taosTmrReset(pSyncNode->FpHeartbeatTimer, pSyncNode->heartbeatTimerMS, pSyncNode, gSyncEnv->pTimerManager, - &pSyncNode->pHeartbeatTimer); - } - return 0; + return ret; } -int32_t syncNodeStopHeartbeatTimer(SSyncNode* pSyncNode) { - atomic_add_fetch_64(&pSyncNode->heartbeatTimerLogicClockUser, 1); - pSyncNode->heartbeatTimerMS = TIMER_MAX_MS; - return 0; +int32_t syncNodeResetElectTimer(SSyncNode* pSyncNode) { + int32_t ret = 0; + int32_t electMS = syncUtilElectRandomMS(); + ret = syncNodeRestartElectTimer(pSyncNode, electMS); + return ret; } -// ------ local funciton --------- -static int32_t syncNodeOnPingCb(SSyncNode* ths, SyncPing* pMsg) { +int32_t syncNodeStartHeartbeatTimer(SSyncNode* pSyncNode) { int32_t ret = 0; - sTrace("<-- syncNodeOnPingCb -->"); - - { - cJSON* pJson = syncPing2Json(pMsg); - char* serialized = cJSON_Print(pJson); - sTrace("process syncMessage recv: syncNodeOnPingCb pMsg:%s ", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SyncPingReply* pMsgReply = syncPingReplyBuild3(&ths->raftId, &pMsg->srcId); - SRpcMsg rpcMsg; - syncPingReply2RpcMsg(pMsgReply, &rpcMsg); - syncNodeSendMsgById(&pMsgReply->destId, ths, &rpcMsg); - + taosTmrReset(pSyncNode->FpHeartbeatTimerCB, pSyncNode->heartbeatTimerMS, pSyncNode, gSyncEnv->pTimerManager, + &pSyncNode->pHeartbeatTimer); + atomic_store_64(&pSyncNode->heartbeatTimerLogicClock, pSyncNode->heartbeatTimerLogicClockUser); return ret; } -static int32_t syncNodeOnPingReplyCb(SSyncNode* ths, SyncPingReply* pMsg) { +int32_t syncNodeStopHeartbeatTimer(SSyncNode* pSyncNode) { int32_t ret = 0; - sTrace("<-- syncNodeOnPingReplyCb -->"); - - { - cJSON* pJson = syncPingReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - sTrace("process syncMessage recv: syncNodeOnPingReplyCb pMsg:%s ", serialized); - free(serialized); - cJSON_Delete(pJson); - } - + atomic_add_fetch_64(&pSyncNode->heartbeatTimerLogicClockUser, 1); + taosTmrStop(pSyncNode->pHeartbeatTimer); + pSyncNode->pHeartbeatTimer = NULL; return ret; } -static void syncNodeEqPingTimer(void* param, void* tmrId) { - SSyncNode* pSyncNode = (SSyncNode*)param; - if (atomic_load_64(&pSyncNode->pingTimerLogicClockUser) <= atomic_load_64(&pSyncNode->pingTimerLogicClock)) { - SyncTimeout* pSyncMsg = syncTimeoutBuild2(SYNC_TIMEOUT_PING, atomic_load_64(&pSyncNode->pingTimerLogicClock), - pSyncNode->pingTimerMS, pSyncNode); - SRpcMsg rpcMsg; - syncTimeout2RpcMsg(pSyncMsg, &rpcMsg); - pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); - syncTimeoutDestroy(pSyncMsg); +// utils -------------- +int32_t syncNodeSendMsgById(const SRaftId* destRaftId, SSyncNode* pSyncNode, SRpcMsg* pMsg) { + SEpSet epSet; + syncUtilraftId2EpSet(destRaftId, &epSet); + pSyncNode->FpSendMsg(pSyncNode->rpcClient, &epSet, pMsg); + return 0; +} - // reset timer ms - // pSyncNode->pingTimerMS += 100; +int32_t syncNodeSendMsgByInfo(const SNodeInfo* nodeInfo, SSyncNode* pSyncNode, SRpcMsg* pMsg) { + SEpSet epSet; + syncUtilnodeInfo2EpSet(nodeInfo, &epSet); + pSyncNode->FpSendMsg(pSyncNode->rpcClient, &epSet, pMsg); + return 0; +} - taosTmrReset(syncNodeEqPingTimer, pSyncNode->pingTimerMS, pSyncNode, &gSyncEnv->pTimerManager, - &pSyncNode->pPingTimer); - } else { - sTrace("syncNodeEqPingTimer: pingTimerLogicClock:%lu, pingTimerLogicClockUser:%lu", pSyncNode->pingTimerLogicClock, - pSyncNode->pingTimerLogicClockUser); +cJSON* syncNode2Json(const SSyncNode* pSyncNode) { + char u64buf[128]; + cJSON* pRoot = cJSON_CreateObject(); + + // init by SSyncInfo + cJSON_AddNumberToObject(pRoot, "vgId", pSyncNode->vgId); + cJSON_AddStringToObject(pRoot, "path", pSyncNode->path); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pWal); + cJSON_AddStringToObject(pRoot, "pWal", u64buf); + + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->rpcClient); + cJSON_AddStringToObject(pRoot, "rpcClient", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpSendMsg); + cJSON_AddStringToObject(pRoot, "FpSendMsg", u64buf); + + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->queue); + cJSON_AddStringToObject(pRoot, "queue", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpEqMsg); + cJSON_AddStringToObject(pRoot, "FpEqMsg", u64buf); + + // init internal + cJSON* pMe = syncUtilNodeInfo2Json(&pSyncNode->myNodeInfo); + cJSON_AddItemToObject(pRoot, "myNodeInfo", pMe); + cJSON* pRaftId = syncUtilRaftId2Json(&pSyncNode->myRaftId); + cJSON_AddItemToObject(pRoot, "myRaftId", pRaftId); + + cJSON_AddNumberToObject(pRoot, "peersNum", pSyncNode->peersNum); + cJSON* pPeers = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "peersNodeInfo", pPeers); + for (int i = 0; i < pSyncNode->peersNum; ++i) { + cJSON_AddItemToArray(pPeers, syncUtilNodeInfo2Json(&pSyncNode->peersNodeInfo[i])); + } + cJSON* pPeersId = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "peersId", pPeersId); + for (int i = 0; i < pSyncNode->peersNum; ++i) { + cJSON_AddItemToArray(pPeersId, syncUtilRaftId2Json(&pSyncNode->peersId[i])); } -} -static void syncNodeEqElectTimer(void* param, void* tmrId) { - SSyncNode* pSyncNode = (SSyncNode*)param; - if (atomic_load_64(&pSyncNode->electTimerLogicClockUser) <= atomic_load_64(&pSyncNode->electTimerLogicClock)) { - SyncTimeout* pSyncMsg = syncTimeoutBuild2(SYNC_TIMEOUT_ELECTION, atomic_load_64(&pSyncNode->electTimerLogicClock), - pSyncNode->electTimerMS, pSyncNode); + cJSON_AddNumberToObject(pRoot, "replicaNum", pSyncNode->replicaNum); + cJSON* pReplicasId = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "replicasId", pReplicasId); + for (int i = 0; i < pSyncNode->replicaNum; ++i) { + cJSON_AddItemToArray(pReplicasId, syncUtilRaftId2Json(&pSyncNode->replicasId[i])); + } - SRpcMsg rpcMsg; - syncTimeout2RpcMsg(pSyncMsg, &rpcMsg); - pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); - syncTimeoutDestroy(pSyncMsg); + // raft algorithm + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pFsm); + cJSON_AddStringToObject(pRoot, "pFsm", u64buf); + cJSON_AddNumberToObject(pRoot, "quorum", pSyncNode->quorum); + cJSON* pLaderCache = syncUtilRaftId2Json(&pSyncNode->leaderCache); + cJSON_AddItemToObject(pRoot, "leaderCache", pLaderCache); + + // tla+ server vars + cJSON_AddNumberToObject(pRoot, "state", pSyncNode->state); + cJSON_AddStringToObject(pRoot, "state_str", syncUtilState2String(pSyncNode->state)); + char tmpBuf[RAFT_STORE_BLOCK_SIZE]; + raftStoreSerialize(pSyncNode->pRaftStore, tmpBuf, sizeof(tmpBuf)); + cJSON_AddStringToObject(pRoot, "pRaftStore", tmpBuf); + + // tla+ candidate vars + cJSON_AddItemToObject(pRoot, "pVotesGranted", voteGranted2Json(pSyncNode->pVotesGranted)); + cJSON_AddItemToObject(pRoot, "pVotesRespond", votesRespond2Json(pSyncNode->pVotesRespond)); + + // tla+ leader vars + cJSON_AddItemToObject(pRoot, "pNextIndex", syncIndexMgr2Json(pSyncNode->pNextIndex)); + cJSON_AddItemToObject(pRoot, "pMatchIndex", syncIndexMgr2Json(pSyncNode->pMatchIndex)); + + // tla+ log vars + cJSON_AddItemToObject(pRoot, "pLogStore", logStore2Json(pSyncNode->pLogStore)); + snprintf(u64buf, sizeof(u64buf), "%ld", pSyncNode->commitIndex); + cJSON_AddStringToObject(pRoot, "commitIndex", u64buf); + + // ping timer + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pPingTimer); + cJSON_AddStringToObject(pRoot, "pPingTimer", u64buf); + cJSON_AddNumberToObject(pRoot, "pingTimerMS", pSyncNode->pingTimerMS); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->pingTimerLogicClock); + cJSON_AddStringToObject(pRoot, "pingTimerLogicClock", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->pingTimerLogicClockUser); + cJSON_AddStringToObject(pRoot, "pingTimerLogicClockUser", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpPingTimerCB); + cJSON_AddStringToObject(pRoot, "FpPingTimerCB", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->pingTimerCounter); + cJSON_AddStringToObject(pRoot, "pingTimerCounter", u64buf); + + // elect timer + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pElectTimer); + cJSON_AddStringToObject(pRoot, "pElectTimer", u64buf); + cJSON_AddNumberToObject(pRoot, "electTimerMS", pSyncNode->electTimerMS); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->electTimerLogicClock); + cJSON_AddStringToObject(pRoot, "electTimerLogicClock", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->electTimerLogicClockUser); + cJSON_AddStringToObject(pRoot, "electTimerLogicClockUser", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpElectTimerCB); + cJSON_AddStringToObject(pRoot, "FpElectTimerCB", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->electTimerCounter); + cJSON_AddStringToObject(pRoot, "electTimerCounter", u64buf); + + // heartbeat timer + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->pHeartbeatTimer); + cJSON_AddStringToObject(pRoot, "pHeartbeatTimer", u64buf); + cJSON_AddNumberToObject(pRoot, "heartbeatTimerMS", pSyncNode->heartbeatTimerMS); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->heartbeatTimerLogicClock); + cJSON_AddStringToObject(pRoot, "heartbeatTimerLogicClock", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->heartbeatTimerLogicClockUser); + cJSON_AddStringToObject(pRoot, "heartbeatTimerLogicClockUser", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpHeartbeatTimerCB); + cJSON_AddStringToObject(pRoot, "FpHeartbeatTimerCB", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pSyncNode->heartbeatTimerCounter); + cJSON_AddStringToObject(pRoot, "heartbeatTimerCounter", u64buf); + + // callback + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnPing); + cJSON_AddStringToObject(pRoot, "FpOnPing", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnPingReply); + cJSON_AddStringToObject(pRoot, "FpOnPingReply", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnRequestVote); + cJSON_AddStringToObject(pRoot, "FpOnRequestVote", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnRequestVoteReply); + cJSON_AddStringToObject(pRoot, "FpOnRequestVoteReply", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnAppendEntries); + cJSON_AddStringToObject(pRoot, "FpOnAppendEntries", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnAppendEntriesReply); + cJSON_AddStringToObject(pRoot, "FpOnAppendEntriesReply", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pSyncNode->FpOnTimeout); + cJSON_AddStringToObject(pRoot, "FpOnTimeout", u64buf); + + cJSON* pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SSyncNode", pRoot); + return pJson; +} - // reset timer ms - pSyncNode->electTimerMS = syncUtilElectRandomMS(); +char* syncNode2Str(const SSyncNode* pSyncNode) { + cJSON* pJson = syncNode2Json(pSyncNode); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} - taosTmrReset(syncNodeEqPingTimer, pSyncNode->pingTimerMS, pSyncNode, &gSyncEnv->pTimerManager, - &pSyncNode->pPingTimer); - } else { - sTrace("syncNodeEqElectTimer: electTimerLogicClock:%lu, electTimerLogicClockUser:%lu", - pSyncNode->electTimerLogicClock, pSyncNode->electTimerLogicClockUser); +// raft state change -------------- +void syncNodeUpdateTerm(SSyncNode* pSyncNode, SyncTerm term) { + if (term > pSyncNode->pRaftStore->currentTerm) { + raftStoreSetTerm(pSyncNode->pRaftStore, term); + syncNodeBecomeFollower(pSyncNode); + raftStoreClearVote(pSyncNode->pRaftStore); } } -static void syncNodeEqHeartbeatTimer(void* param, void* tmrId) {} - -static void syncNodeBecomeFollower(SSyncNode* pSyncNode) { +void syncNodeBecomeFollower(SSyncNode* pSyncNode) { if (pSyncNode->state == TAOS_SYNC_STATE_LEADER) { pSyncNode->leaderCache = EMPTY_RAFT_ID; } + pSyncNode->state = TAOS_SYNC_STATE_FOLLOWER; syncNodeStopHeartbeatTimer(pSyncNode); + int32_t electMS = syncUtilElectRandomMS(); - syncNodeStartElectTimer(pSyncNode, electMS); + syncNodeRestartElectTimer(pSyncNode, electMS); } // TLA+ Spec @@ -381,26 +527,172 @@ static void syncNodeBecomeFollower(SSyncNode* pSyncNode) { // evoterLog |-> voterLog[i]]} // /\ UNCHANGED <> // -static void syncNodeBecomeLeader(SSyncNode* pSyncNode) { +void syncNodeBecomeLeader(SSyncNode* pSyncNode) { pSyncNode->state = TAOS_SYNC_STATE_LEADER; - pSyncNode->leaderCache = pSyncNode->raftId; + pSyncNode->leaderCache = pSyncNode->myRaftId; - // next Index +=1 - // match Index = 0; + for (int i = 0; i < pSyncNode->pNextIndex->replicaNum; ++i) { + pSyncNode->pNextIndex->index[i] = pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore) + 1; + } + + for (int i = 0; i < pSyncNode->pMatchIndex->replicaNum; ++i) { + pSyncNode->pMatchIndex->index[i] = SYNC_INDEX_INVALID; + } syncNodeStopElectTimer(pSyncNode); syncNodeStartHeartbeatTimer(pSyncNode); + syncNodeReplicate(pSyncNode); +} - // appendEntries; +void syncNodeCandidate2Leader(SSyncNode* pSyncNode) { + assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE); + assert(voteGrantedMajority(pSyncNode->pVotesGranted)); + syncNodeBecomeLeader(pSyncNode); } -static void syncNodeFollower2Candidate(SSyncNode* pSyncNode) { +void syncNodeFollower2Candidate(SSyncNode* pSyncNode) { assert(pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER); pSyncNode->state = TAOS_SYNC_STATE_CANDIDATE; } -static void syncNodeCandidate2Leader(SSyncNode* pSyncNode) {} +void syncNodeLeader2Follower(SSyncNode* pSyncNode) { + assert(pSyncNode->state == TAOS_SYNC_STATE_LEADER); + syncNodeBecomeFollower(pSyncNode); +} + +void syncNodeCandidate2Follower(SSyncNode* pSyncNode) { + assert(pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE); + syncNodeBecomeFollower(pSyncNode); +} + +// raft vote -------------- +void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId) { + assert(term == pSyncNode->pRaftStore->currentTerm); + assert(!raftStoreHasVoted(pSyncNode->pRaftStore)); -static void syncNodeLeader2Follower(SSyncNode* pSyncNode) {} + raftStoreVote(pSyncNode->pRaftStore, pRaftId); +} + +void syncNodeVoteForSelf(SSyncNode* pSyncNode) { + syncNodeVoteForTerm(pSyncNode, pSyncNode->pRaftStore->currentTerm, &(pSyncNode->myRaftId)); + + SyncRequestVoteReply* pMsg = syncRequestVoteReplyBuild(); + pMsg->srcId = pSyncNode->myRaftId; + pMsg->destId = pSyncNode->myRaftId; + pMsg->term = pSyncNode->pRaftStore->currentTerm; + pMsg->voteGranted = true; + + voteGrantedVote(pSyncNode->pVotesGranted, pMsg); + votesRespondAdd(pSyncNode->pVotesRespond, pMsg); + syncRequestVoteReplyDestroy(pMsg); +} + +void syncNodeMaybeAdvanceCommitIndex(SSyncNode* pSyncNode) {} + +// for debug -------------- +void syncNodePrint(SSyncNode* pObj) { + char* serialized = syncNode2Str(pObj); + printf("syncNodePrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} -static void syncNodeCandidate2Follower(SSyncNode* pSyncNode) {} +void syncNodePrint2(char* s, SSyncNode* pObj) { + char* serialized = syncNode2Str(pObj); + printf("syncNodePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncNodeLog(SSyncNode* pObj) { + char* serialized = syncNode2Str(pObj); + sTrace("syncNodeLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncNodeLog2(char* s, SSyncNode* pObj) { + char* serialized = syncNode2Str(pObj); + sTrace("syncNodeLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + +// ------ local funciton --------- +// enqueue message ---- +static void syncNodeEqPingTimer(void* param, void* tmrId) { + SSyncNode* pSyncNode = (SSyncNode*)param; + if (atomic_load_64(&pSyncNode->pingTimerLogicClockUser) <= atomic_load_64(&pSyncNode->pingTimerLogicClock)) { + SyncTimeout* pSyncMsg = syncTimeoutBuild2(SYNC_TIMEOUT_PING, atomic_load_64(&pSyncNode->pingTimerLogicClock), + pSyncNode->pingTimerMS, pSyncNode); + SRpcMsg rpcMsg; + syncTimeout2RpcMsg(pSyncMsg, &rpcMsg); + syncRpcMsgLog2((char*)"==syncNodeEqPingTimer==", &rpcMsg); + pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); + syncTimeoutDestroy(pSyncMsg); + + taosTmrReset(syncNodeEqPingTimer, pSyncNode->pingTimerMS, pSyncNode, gSyncEnv->pTimerManager, + &pSyncNode->pPingTimer); + } else { + sTrace("==syncNodeEqPingTimer== pingTimerLogicClock:%lu, pingTimerLogicClockUser:%lu", + pSyncNode->pingTimerLogicClock, pSyncNode->pingTimerLogicClockUser); + } +} + +static void syncNodeEqElectTimer(void* param, void* tmrId) { + SSyncNode* pSyncNode = (SSyncNode*)param; + if (atomic_load_64(&pSyncNode->electTimerLogicClockUser) <= atomic_load_64(&pSyncNode->electTimerLogicClock)) { + SyncTimeout* pSyncMsg = syncTimeoutBuild2(SYNC_TIMEOUT_ELECTION, atomic_load_64(&pSyncNode->electTimerLogicClock), + pSyncNode->electTimerMS, pSyncNode); + SRpcMsg rpcMsg; + syncTimeout2RpcMsg(pSyncMsg, &rpcMsg); + syncRpcMsgLog2((char*)"==syncNodeEqElectTimer==", &rpcMsg); + pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); + syncTimeoutDestroy(pSyncMsg); + + // reset timer ms + pSyncNode->electTimerMS = syncUtilElectRandomMS(); + taosTmrReset(syncNodeEqPingTimer, pSyncNode->pingTimerMS, pSyncNode, gSyncEnv->pTimerManager, + &pSyncNode->pPingTimer); + } else { + sTrace("==syncNodeEqElectTimer== electTimerLogicClock:%lu, electTimerLogicClockUser:%lu", + pSyncNode->electTimerLogicClock, pSyncNode->electTimerLogicClockUser); + } +} + +static void syncNodeEqHeartbeatTimer(void* param, void* tmrId) { + SSyncNode* pSyncNode = (SSyncNode*)param; + if (atomic_load_64(&pSyncNode->heartbeatTimerLogicClockUser) <= + atomic_load_64(&pSyncNode->heartbeatTimerLogicClock)) { + SyncTimeout* pSyncMsg = + syncTimeoutBuild2(SYNC_TIMEOUT_HEARTBEAT, atomic_load_64(&pSyncNode->heartbeatTimerLogicClock), + pSyncNode->heartbeatTimerMS, pSyncNode); + SRpcMsg rpcMsg; + syncTimeout2RpcMsg(pSyncMsg, &rpcMsg); + syncRpcMsgLog2((char*)"==syncNodeEqHeartbeatTimer==", &rpcMsg); + pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); + syncTimeoutDestroy(pSyncMsg); + + taosTmrReset(syncNodeEqHeartbeatTimer, pSyncNode->heartbeatTimerMS, pSyncNode, gSyncEnv->pTimerManager, + &pSyncNode->pHeartbeatTimer); + } else { + sTrace("==syncNodeEqHeartbeatTimer== heartbeatTimerLogicClock:%lu, heartbeatTimerLogicClockUser:%lu", + pSyncNode->heartbeatTimerLogicClock, pSyncNode->heartbeatTimerLogicClockUser); + } +} + +// on message ---- +static int32_t syncNodeOnPingCb(SSyncNode* ths, SyncPing* pMsg) { + int32_t ret = 0; + syncPingLog2("==syncNodeOnPingCb==", pMsg); + SyncPingReply* pMsgReply = syncPingReplyBuild3(&ths->myRaftId, &pMsg->srcId); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pMsgReply, &rpcMsg); + syncNodeSendMsgById(&pMsgReply->destId, ths, &rpcMsg); + + return ret; +} + +static int32_t syncNodeOnPingReplyCb(SSyncNode* ths, SyncPingReply* pMsg) { + int32_t ret = 0; + syncPingReplyLog2("==syncNodeOnPingReplyCb==", pMsg); + return ret; +} diff --git a/source/libs/sync/src/syncMessage.c b/source/libs/sync/src/syncMessage.c index 14f139a80383646c2683d027e6569d567b04ec5d..509ede274b8d0312ed2d1aee7454d02365a4dd69 100644 --- a/source/libs/sync/src/syncMessage.c +++ b/source/libs/sync/src/syncMessage.c @@ -14,7 +14,6 @@ */ #include "syncMessage.h" -#include "syncRaft.h" #include "syncUtil.h" #include "tcoding.h" @@ -24,43 +23,74 @@ cJSON* syncRpcMsg2Json(SRpcMsg* pRpcMsg) { // in compiler optimization, switch case = if else constants if (pRpcMsg->msgType == SYNC_TIMEOUT) { - SyncTimeout* pSyncMsg = (SyncTimeout*)pRpcMsg->pCont; + SyncTimeout* pSyncMsg = syncTimeoutDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncTimeout2Json(pSyncMsg); + syncTimeoutDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_PING) { - SyncPing* pSyncMsg = (SyncPing*)pRpcMsg->pCont; + SyncPing* pSyncMsg = syncPingDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncPing2Json(pSyncMsg); + syncPingDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_PING_REPLY) { - SyncPingReply* pSyncMsg = (SyncPingReply*)pRpcMsg->pCont; + SyncPingReply* pSyncMsg = syncPingReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncPingReply2Json(pSyncMsg); + syncPingReplyDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_CLIENT_REQUEST) { - pRoot = syncRpcUnknownMsg2Json(); + SyncClientRequest* pSyncMsg = syncClientRequestDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + pRoot = syncClientRequest2Json(pSyncMsg); + syncClientRequestDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_CLIENT_REQUEST_REPLY) { pRoot = syncRpcUnknownMsg2Json(); } else if (pRpcMsg->msgType == SYNC_REQUEST_VOTE) { - SyncRequestVote* pSyncMsg = (SyncRequestVote*)pRpcMsg->pCont; + SyncRequestVote* pSyncMsg = syncRequestVoteDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncRequestVote2Json(pSyncMsg); + syncRequestVoteDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_REQUEST_VOTE_REPLY) { - SyncRequestVoteReply* pSyncMsg = (SyncRequestVoteReply*)pRpcMsg->pCont; + SyncRequestVoteReply* pSyncMsg = syncRequestVoteReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncRequestVoteReply2Json(pSyncMsg); + syncRequestVoteReplyDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_APPEND_ENTRIES) { - SyncAppendEntries* pSyncMsg = (SyncAppendEntries*)pRpcMsg->pCont; + SyncAppendEntries* pSyncMsg = syncAppendEntriesDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncAppendEntries2Json(pSyncMsg); + syncAppendEntriesDestroy(pSyncMsg); } else if (pRpcMsg->msgType == SYNC_APPEND_ENTRIES_REPLY) { - SyncAppendEntriesReply* pSyncMsg = (SyncAppendEntriesReply*)pRpcMsg->pCont; + SyncAppendEntriesReply* pSyncMsg = syncAppendEntriesReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); pRoot = syncAppendEntriesReply2Json(pSyncMsg); + syncAppendEntriesReplyDestroy(pSyncMsg); + + } else if (pRpcMsg->msgType == SYNC_RESPONSE) { + pRoot = cJSON_CreateObject(); + char* s; + s = syncUtilprintBin((char*)(pRpcMsg->pCont), pRpcMsg->contLen); + cJSON_AddStringToObject(pRoot, "pCont", s); + free(s); + s = syncUtilprintBin2((char*)(pRpcMsg->pCont), pRpcMsg->contLen); + cJSON_AddStringToObject(pRoot, "pCont2", s); + free(s); } else { pRoot = syncRpcUnknownMsg2Json(); + char* s; + s = syncUtilprintBin((char*)(pRpcMsg->pCont), pRpcMsg->contLen); + cJSON_AddStringToObject(pRoot, "pCont", s); + free(s); + s = syncUtilprintBin2((char*)(pRpcMsg->pCont), pRpcMsg->contLen); + cJSON_AddStringToObject(pRoot, "pCont2", s); + free(s); } + cJSON_AddNumberToObject(pRoot, "msgType", pRpcMsg->msgType); + cJSON_AddNumberToObject(pRoot, "contLen", pRpcMsg->contLen); + cJSON_AddNumberToObject(pRoot, "code", pRpcMsg->code); + // cJSON_AddNumberToObject(pRoot, "persist", pRpcMsg->persist); + cJSON* pJson = cJSON_CreateObject(); cJSON_AddItemToObject(pJson, "RpcMsg", pRoot); return pJson; @@ -69,13 +99,47 @@ cJSON* syncRpcMsg2Json(SRpcMsg* pRpcMsg) { cJSON* syncRpcUnknownMsg2Json() { cJSON* pRoot = cJSON_CreateObject(); cJSON_AddNumberToObject(pRoot, "msgType", SYNC_UNKNOWN); - cJSON_AddStringToObject(pRoot, "data", "known message"); + cJSON_AddStringToObject(pRoot, "data", "unknown message"); cJSON* pJson = cJSON_CreateObject(); - cJSON_AddItemToObject(pJson, "SyncPing", pRoot); + cJSON_AddItemToObject(pJson, "SyncUnknown", pRoot); return pJson; } +char* syncRpcMsg2Str(SRpcMsg* pRpcMsg) { + cJSON* pJson = syncRpcMsg2Json(pRpcMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncRpcMsgPrint(SRpcMsg* pMsg) { + char* serialized = syncRpcMsg2Str(pMsg); + printf("syncRpcMsgPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncRpcMsgPrint2(char* s, SRpcMsg* pMsg) { + char* serialized = syncRpcMsg2Str(pMsg); + printf("syncRpcMsgPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncRpcMsgLog(SRpcMsg* pMsg) { + char* serialized = syncRpcMsg2Str(pMsg); + sTrace("syncRpcMsgLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncRpcMsgLog2(char* s, SRpcMsg* pMsg) { + char* serialized = syncRpcMsg2Str(pMsg); + sTrace("syncRpcMsgLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + // ---- message process SyncTimeout---- SyncTimeout* syncTimeoutBuild() { uint32_t bytes = sizeof(SyncTimeout); @@ -86,6 +150,15 @@ SyncTimeout* syncTimeoutBuild() { return pMsg; } +SyncTimeout* syncTimeoutBuild2(ESyncTimeoutType timeoutType, uint64_t logicClock, int32_t timerMS, void* data) { + SyncTimeout* pMsg = syncTimeoutBuild(); + pMsg->timeoutType = timeoutType; + pMsg->logicClock = logicClock; + pMsg->timerMS = timerMS; + pMsg->data = data; + return pMsg; +} + void syncTimeoutDestroy(SyncTimeout* pMsg) { if (pMsg != NULL) { free(pMsg); @@ -102,6 +175,25 @@ void syncTimeoutDeserialize(const char* buf, uint32_t len, SyncTimeout* pMsg) { assert(len == pMsg->bytes); } +char* syncTimeoutSerialize2(const SyncTimeout* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncTimeoutSerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncTimeout* syncTimeoutDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncTimeout* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncTimeoutDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; +} + void syncTimeout2RpcMsg(const SyncTimeout* pMsg, SRpcMsg* pRpcMsg) { memset(pRpcMsg, 0, sizeof(*pRpcMsg)); pRpcMsg->msgType = pMsg->msgType; @@ -114,6 +206,11 @@ void syncTimeoutFromRpcMsg(const SRpcMsg* pRpcMsg, SyncTimeout* pMsg) { syncTimeoutDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncTimeout* syncTimeoutFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncTimeout* pMsg = syncTimeoutDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncTimeout2Json(const SyncTimeout* pMsg) { char u64buf[128]; @@ -132,23 +229,63 @@ cJSON* syncTimeout2Json(const SyncTimeout* pMsg) { return pJson; } -SyncTimeout* syncTimeoutBuild2(ESyncTimeoutType timeoutType, uint64_t logicClock, int32_t timerMS, void* data) { - SyncTimeout* pMsg = syncTimeoutBuild(); - pMsg->timeoutType = timeoutType; - pMsg->logicClock = logicClock; - pMsg->timerMS = timerMS; - pMsg->data = data; - return pMsg; +char* syncTimeout2Str(const SyncTimeout* pMsg) { + cJSON* pJson = syncTimeout2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncTimeoutPrint(const SyncTimeout* pMsg) { + char* serialized = syncTimeout2Str(pMsg); + printf("syncTimeoutPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncTimeoutPrint2(char* s, const SyncTimeout* pMsg) { + char* serialized = syncTimeout2Str(pMsg); + printf("syncTimeoutPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncTimeoutLog(const SyncTimeout* pMsg) { + char* serialized = syncTimeout2Str(pMsg); + sTrace("syncTimeoutLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncTimeoutLog2(char* s, const SyncTimeout* pMsg) { + char* serialized = syncTimeout2Str(pMsg); + sTrace("syncTimeoutLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); } // ---- message process SyncPing---- SyncPing* syncPingBuild(uint32_t dataLen) { - uint32_t bytes = SYNC_PING_FIX_LEN + dataLen; + uint32_t bytes = sizeof(SyncPing) + dataLen; SyncPing* pMsg = malloc(bytes); memset(pMsg, 0, bytes); pMsg->bytes = bytes; pMsg->msgType = SYNC_PING; pMsg->dataLen = dataLen; + return pMsg; +} + +SyncPing* syncPingBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str) { + uint32_t dataLen = strlen(str) + 1; + SyncPing* pMsg = syncPingBuild(dataLen); + pMsg->srcId = *srcId; + pMsg->destId = *destId; + snprintf(pMsg->data, pMsg->dataLen, "%s", str); + return pMsg; +} + +SyncPing* syncPingBuild3(const SRaftId* srcId, const SRaftId* destId) { + SyncPing* pMsg = syncPingBuild2(srcId, destId, "ping"); + return pMsg; } void syncPingDestroy(SyncPing* pMsg) { @@ -165,7 +302,26 @@ void syncPingSerialize(const SyncPing* pMsg, char* buf, uint32_t bufLen) { void syncPingDeserialize(const char* buf, uint32_t len, SyncPing* pMsg) { memcpy(pMsg, buf, len); assert(len == pMsg->bytes); - assert(pMsg->bytes == SYNC_PING_FIX_LEN + pMsg->dataLen); + assert(pMsg->bytes == sizeof(SyncPing) + pMsg->dataLen); +} + +char* syncPingSerialize2(const SyncPing* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncPingSerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncPing* syncPingDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncPing* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncPingDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; } void syncPing2RpcMsg(const SyncPing* pMsg, SRpcMsg* pRpcMsg) { @@ -180,6 +336,11 @@ void syncPingFromRpcMsg(const SRpcMsg* pRpcMsg, SyncPing* pMsg) { syncPingDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncPing* syncPingFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncPing* pMsg = syncPingDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncPing2Json(const SyncPing* pMsg) { char u64buf[128]; @@ -218,35 +379,76 @@ cJSON* syncPing2Json(const SyncPing* pMsg) { cJSON_AddItemToObject(pRoot, "destId", pDestId); cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen); - cJSON_AddStringToObject(pRoot, "data", pMsg->data); + char* s; + s = syncUtilprintBin((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data", s); + free(s); + s = syncUtilprintBin2((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data2", s); + free(s); cJSON* pJson = cJSON_CreateObject(); cJSON_AddItemToObject(pJson, "SyncPing", pRoot); return pJson; } -SyncPing* syncPingBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str) { - uint32_t dataLen = strlen(str) + 1; - SyncPing* pMsg = syncPingBuild(dataLen); - pMsg->srcId = *srcId; - pMsg->destId = *destId; - snprintf(pMsg->data, pMsg->dataLen, "%s", str); - return pMsg; +char* syncPing2Str(const SyncPing* pMsg) { + cJSON* pJson = syncPing2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; } -SyncPing* syncPingBuild3(const SRaftId* srcId, const SRaftId* destId) { - SyncPing* pMsg = syncPingBuild2(srcId, destId, "ping"); - return pMsg; +// for debug ---------------------- +void syncPingPrint(const SyncPing* pMsg) { + char* serialized = syncPing2Str(pMsg); + printf("syncPingPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncPingPrint2(char* s, const SyncPing* pMsg) { + char* serialized = syncPing2Str(pMsg); + printf("syncPingPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncPingLog(const SyncPing* pMsg) { + char* serialized = syncPing2Str(pMsg); + sTrace("syncPingLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncPingLog2(char* s, const SyncPing* pMsg) { + char* serialized = syncPing2Str(pMsg); + sTrace("syncPingLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); } // ---- message process SyncPingReply---- SyncPingReply* syncPingReplyBuild(uint32_t dataLen) { - uint32_t bytes = SYNC_PING_REPLY_FIX_LEN + dataLen; + uint32_t bytes = sizeof(SyncPingReply) + dataLen; SyncPingReply* pMsg = malloc(bytes); memset(pMsg, 0, bytes); pMsg->bytes = bytes; pMsg->msgType = SYNC_PING_REPLY; pMsg->dataLen = dataLen; + return pMsg; +} + +SyncPingReply* syncPingReplyBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str) { + uint32_t dataLen = strlen(str) + 1; + SyncPingReply* pMsg = syncPingReplyBuild(dataLen); + pMsg->srcId = *srcId; + pMsg->destId = *destId; + snprintf(pMsg->data, pMsg->dataLen, "%s", str); + return pMsg; +} + +SyncPingReply* syncPingReplyBuild3(const SRaftId* srcId, const SRaftId* destId) { + SyncPingReply* pMsg = syncPingReplyBuild2(srcId, destId, "pang"); + return pMsg; } void syncPingReplyDestroy(SyncPingReply* pMsg) { @@ -263,7 +465,26 @@ void syncPingReplySerialize(const SyncPingReply* pMsg, char* buf, uint32_t bufLe void syncPingReplyDeserialize(const char* buf, uint32_t len, SyncPingReply* pMsg) { memcpy(pMsg, buf, len); assert(len == pMsg->bytes); - assert(pMsg->bytes == SYNC_PING_FIX_LEN + pMsg->dataLen); + assert(pMsg->bytes == sizeof(SyncPing) + pMsg->dataLen); +} + +char* syncPingReplySerialize2(const SyncPingReply* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncPingReplySerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncPingReply* syncPingReplyDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncPingReply* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncPingReplyDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; } void syncPingReply2RpcMsg(const SyncPingReply* pMsg, SRpcMsg* pRpcMsg) { @@ -278,6 +499,11 @@ void syncPingReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncPingReply* pMsg) { syncPingReplyDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncPingReply* syncPingReplyFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncPingReply* pMsg = syncPingReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncPingReply2Json(const SyncPingReply* pMsg) { char u64buf[128]; @@ -316,27 +542,186 @@ cJSON* syncPingReply2Json(const SyncPingReply* pMsg) { cJSON_AddItemToObject(pRoot, "destId", pDestId); cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen); - cJSON_AddStringToObject(pRoot, "data", pMsg->data); + char* s; + s = syncUtilprintBin((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data", s); + free(s); + s = syncUtilprintBin2((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data2", s); + free(s); cJSON* pJson = cJSON_CreateObject(); cJSON_AddItemToObject(pJson, "SyncPingReply", pRoot); return pJson; } -SyncPingReply* syncPingReplyBuild2(const SRaftId* srcId, const SRaftId* destId, const char* str) { - uint32_t dataLen = strlen(str) + 1; - SyncPingReply* pMsg = syncPingReplyBuild(dataLen); - pMsg->srcId = *srcId; - pMsg->destId = *destId; - snprintf(pMsg->data, pMsg->dataLen, "%s", str); +char* syncPingReply2Str(const SyncPingReply* pMsg) { + cJSON* pJson = syncPingReply2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncPingReplyPrint(const SyncPingReply* pMsg) { + char* serialized = syncPingReply2Str(pMsg); + printf("syncPingReplyPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncPingReplyPrint2(char* s, const SyncPingReply* pMsg) { + char* serialized = syncPingReply2Str(pMsg); + printf("syncPingReplyPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncPingReplyLog(const SyncPingReply* pMsg) { + char* serialized = syncPingReply2Str(pMsg); + sTrace("syncPingReplyLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncPingReplyLog2(char* s, const SyncPingReply* pMsg) { + char* serialized = syncPingReply2Str(pMsg); + sTrace("syncPingReplyLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + +// ---- message process SyncClientRequest---- +SyncClientRequest* syncClientRequestBuild(uint32_t dataLen) { + uint32_t bytes = sizeof(SyncClientRequest) + dataLen; + SyncClientRequest* pMsg = malloc(bytes); + memset(pMsg, 0, bytes); + pMsg->bytes = bytes; + pMsg->msgType = SYNC_CLIENT_REQUEST; + pMsg->seqNum = 0; + pMsg->isWeak = false; + pMsg->dataLen = dataLen; return pMsg; } -SyncPingReply* syncPingReplyBuild3(const SRaftId* srcId, const SRaftId* destId) { - SyncPingReply* pMsg = syncPingReplyBuild2(srcId, destId, "pang"); +SyncClientRequest* syncClientRequestBuild2(const SRpcMsg* pOriginalRpcMsg, uint64_t seqNum, bool isWeak) { + SyncClientRequest* pMsg = syncClientRequestBuild(pOriginalRpcMsg->contLen); + pMsg->originalRpcType = pOriginalRpcMsg->msgType; + pMsg->seqNum = seqNum; + pMsg->isWeak = isWeak; + memcpy(pMsg->data, pOriginalRpcMsg->pCont, pOriginalRpcMsg->contLen); + return pMsg; +} + +void syncClientRequestDestroy(SyncClientRequest* pMsg) { + if (pMsg != NULL) { + free(pMsg); + } +} + +void syncClientRequestSerialize(const SyncClientRequest* pMsg, char* buf, uint32_t bufLen) { + assert(pMsg->bytes <= bufLen); + memcpy(buf, pMsg, pMsg->bytes); +} + +void syncClientRequestDeserialize(const char* buf, uint32_t len, SyncClientRequest* pMsg) { + memcpy(pMsg, buf, len); + assert(len == pMsg->bytes); +} + +char* syncClientRequestSerialize2(const SyncClientRequest* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncClientRequestSerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncClientRequest* syncClientRequestDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncClientRequest* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncClientRequestDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; +} + +void syncClientRequest2RpcMsg(const SyncClientRequest* pMsg, SRpcMsg* pRpcMsg) { + memset(pRpcMsg, 0, sizeof(*pRpcMsg)); + pRpcMsg->msgType = pMsg->msgType; + pRpcMsg->contLen = pMsg->bytes; + pRpcMsg->pCont = rpcMallocCont(pRpcMsg->contLen); + syncClientRequestSerialize(pMsg, pRpcMsg->pCont, pRpcMsg->contLen); +} + +void syncClientRequestFromRpcMsg(const SRpcMsg* pRpcMsg, SyncClientRequest* pMsg) { + syncClientRequestDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); +} + +SyncClientRequest* syncClientRequestFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncClientRequest* pMsg = syncClientRequestDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); return pMsg; } +cJSON* syncClientRequest2Json(const SyncClientRequest* pMsg) { + char u64buf[128]; + + cJSON* pRoot = cJSON_CreateObject(); + cJSON_AddNumberToObject(pRoot, "bytes", pMsg->bytes); + cJSON_AddNumberToObject(pRoot, "msgType", pMsg->msgType); + cJSON_AddNumberToObject(pRoot, "originalRpcType", pMsg->originalRpcType); + snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->seqNum); + cJSON_AddStringToObject(pRoot, "seqNum", u64buf); + cJSON_AddNumberToObject(pRoot, "isWeak", pMsg->isWeak); + cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen); + + char* s; + s = syncUtilprintBin((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data", s); + free(s); + s = syncUtilprintBin2((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data2", s); + free(s); + + cJSON* pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SyncClientRequest", pRoot); + return pJson; +} + +char* syncClientRequest2Str(const SyncClientRequest* pMsg) { + cJSON* pJson = syncClientRequest2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncClientRequestPrint(const SyncClientRequest* pMsg) { + char* serialized = syncClientRequest2Str(pMsg); + printf("syncClientRequestPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncClientRequestPrint2(char* s, const SyncClientRequest* pMsg) { + char* serialized = syncClientRequest2Str(pMsg); + printf("syncClientRequestPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncClientRequestLog(const SyncClientRequest* pMsg) { + char* serialized = syncClientRequest2Str(pMsg); + sTrace("syncClientRequestLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncClientRequestLog2(char* s, const SyncClientRequest* pMsg) { + char* serialized = syncClientRequest2Str(pMsg); + sTrace("syncClientRequestLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + // ---- message process SyncRequestVote---- SyncRequestVote* syncRequestVoteBuild() { uint32_t bytes = sizeof(SyncRequestVote); @@ -344,6 +729,7 @@ SyncRequestVote* syncRequestVoteBuild() { memset(pMsg, 0, bytes); pMsg->bytes = bytes; pMsg->msgType = SYNC_REQUEST_VOTE; + return pMsg; } void syncRequestVoteDestroy(SyncRequestVote* pMsg) { @@ -362,6 +748,25 @@ void syncRequestVoteDeserialize(const char* buf, uint32_t len, SyncRequestVote* assert(len == pMsg->bytes); } +char* syncRequestVoteSerialize2(const SyncRequestVote* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncRequestVoteSerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncRequestVote* syncRequestVoteDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncRequestVote* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncRequestVoteDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; +} + void syncRequestVote2RpcMsg(const SyncRequestVote* pMsg, SRpcMsg* pRpcMsg) { memset(pRpcMsg, 0, sizeof(*pRpcMsg)); pRpcMsg->msgType = pMsg->msgType; @@ -374,6 +779,11 @@ void syncRequestVoteFromRpcMsg(const SRpcMsg* pRpcMsg, SyncRequestVote* pMsg) { syncRequestVoteDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncRequestVote* syncRequestVoteFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncRequestVote* pMsg = syncRequestVoteDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncRequestVote2Json(const SyncRequestVote* pMsg) { char u64buf[128]; @@ -410,8 +820,8 @@ cJSON* syncRequestVote2Json(const SyncRequestVote* pMsg) { cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId); cJSON_AddItemToObject(pRoot, "destId", pDestId); - snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->currentTerm); - cJSON_AddStringToObject(pRoot, "currentTerm", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term); + cJSON_AddStringToObject(pRoot, "term", u64buf); snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->lastLogIndex); cJSON_AddStringToObject(pRoot, "lastLogIndex", u64buf); snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->lastLogTerm); @@ -422,13 +832,48 @@ cJSON* syncRequestVote2Json(const SyncRequestVote* pMsg) { return pJson; } +char* syncRequestVote2Str(const SyncRequestVote* pMsg) { + cJSON* pJson = syncRequestVote2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncRequestVotePrint(const SyncRequestVote* pMsg) { + char* serialized = syncRequestVote2Str(pMsg); + printf("syncRequestVotePrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncRequestVotePrint2(char* s, const SyncRequestVote* pMsg) { + char* serialized = syncRequestVote2Str(pMsg); + printf("syncRequestVotePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncRequestVoteLog(const SyncRequestVote* pMsg) { + char* serialized = syncRequestVote2Str(pMsg); + sTrace("syncRequestVoteLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncRequestVoteLog2(char* s, const SyncRequestVote* pMsg) { + char* serialized = syncRequestVote2Str(pMsg); + sTrace("syncRequestVoteLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + // ---- message process SyncRequestVoteReply---- -SyncRequestVoteReply* SyncRequestVoteReplyBuild() { +SyncRequestVoteReply* syncRequestVoteReplyBuild() { uint32_t bytes = sizeof(SyncRequestVoteReply); SyncRequestVoteReply* pMsg = malloc(bytes); memset(pMsg, 0, bytes); pMsg->bytes = bytes; pMsg->msgType = SYNC_REQUEST_VOTE_REPLY; + return pMsg; } void syncRequestVoteReplyDestroy(SyncRequestVoteReply* pMsg) { @@ -447,6 +892,25 @@ void syncRequestVoteReplyDeserialize(const char* buf, uint32_t len, SyncRequestV assert(len == pMsg->bytes); } +char* syncRequestVoteReplySerialize2(const SyncRequestVoteReply* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncRequestVoteReplySerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncRequestVoteReply* syncRequestVoteReplyDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncRequestVoteReply* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncRequestVoteReplyDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; +} + void syncRequestVoteReply2RpcMsg(const SyncRequestVoteReply* pMsg, SRpcMsg* pRpcMsg) { memset(pRpcMsg, 0, sizeof(*pRpcMsg)); pRpcMsg->msgType = pMsg->msgType; @@ -459,6 +923,11 @@ void syncRequestVoteReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncRequestVoteReply syncRequestVoteReplyDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncRequestVoteReply* syncRequestVoteReplyFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncRequestVoteReply* pMsg = syncRequestVoteReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncRequestVoteReply2Json(const SyncRequestVoteReply* pMsg) { char u64buf[128]; @@ -504,14 +973,49 @@ cJSON* syncRequestVoteReply2Json(const SyncRequestVoteReply* pMsg) { return pJson; } +char* syncRequestVoteReply2Str(const SyncRequestVoteReply* pMsg) { + cJSON* pJson = syncRequestVoteReply2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncRequestVoteReplyPrint(const SyncRequestVoteReply* pMsg) { + char* serialized = syncRequestVoteReply2Str(pMsg); + printf("syncRequestVoteReplyPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncRequestVoteReplyPrint2(char* s, const SyncRequestVoteReply* pMsg) { + char* serialized = syncRequestVoteReply2Str(pMsg); + printf("syncRequestVoteReplyPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncRequestVoteReplyLog(const SyncRequestVoteReply* pMsg) { + char* serialized = syncRequestVoteReply2Str(pMsg); + sTrace("syncRequestVoteReplyLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncRequestVoteReplyLog2(char* s, const SyncRequestVoteReply* pMsg) { + char* serialized = syncRequestVoteReply2Str(pMsg); + sTrace("syncRequestVoteReplyLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + // ---- message process SyncAppendEntries---- SyncAppendEntries* syncAppendEntriesBuild(uint32_t dataLen) { - uint32_t bytes = SYNC_APPEND_ENTRIES_FIX_LEN + dataLen; + uint32_t bytes = sizeof(SyncAppendEntries) + dataLen; SyncAppendEntries* pMsg = malloc(bytes); memset(pMsg, 0, bytes); pMsg->bytes = bytes; pMsg->msgType = SYNC_APPEND_ENTRIES; pMsg->dataLen = dataLen; + return pMsg; } void syncAppendEntriesDestroy(SyncAppendEntries* pMsg) { @@ -528,7 +1032,26 @@ void syncAppendEntriesSerialize(const SyncAppendEntries* pMsg, char* buf, uint32 void syncAppendEntriesDeserialize(const char* buf, uint32_t len, SyncAppendEntries* pMsg) { memcpy(pMsg, buf, len); assert(len == pMsg->bytes); - assert(pMsg->bytes == SYNC_APPEND_ENTRIES_FIX_LEN + pMsg->dataLen); + assert(pMsg->bytes == sizeof(SyncAppendEntries) + pMsg->dataLen); +} + +char* syncAppendEntriesSerialize2(const SyncAppendEntries* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncAppendEntriesSerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncAppendEntries* syncAppendEntriesDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncAppendEntries* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncAppendEntriesDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; } void syncAppendEntries2RpcMsg(const SyncAppendEntries* pMsg, SRpcMsg* pRpcMsg) { @@ -543,6 +1066,11 @@ void syncAppendEntriesFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntries* pMsg syncAppendEntriesDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncAppendEntries* syncAppendEntriesFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncAppendEntries* pMsg = syncAppendEntriesDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg) { char u64buf[128]; @@ -580,6 +1108,9 @@ cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg) { cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId); cJSON_AddItemToObject(pRoot, "destId", pDestId); + snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term); + cJSON_AddStringToObject(pRoot, "term", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->prevLogIndex); cJSON_AddStringToObject(pRoot, "pre_log_index", u64buf); @@ -590,13 +1121,53 @@ cJSON* syncAppendEntries2Json(const SyncAppendEntries* pMsg) { cJSON_AddStringToObject(pRoot, "commit_index", u64buf); cJSON_AddNumberToObject(pRoot, "dataLen", pMsg->dataLen); - cJSON_AddStringToObject(pRoot, "data", pMsg->data); + char* s; + s = syncUtilprintBin((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data", s); + free(s); + s = syncUtilprintBin2((char*)(pMsg->data), pMsg->dataLen); + cJSON_AddStringToObject(pRoot, "data2", s); + free(s); cJSON* pJson = cJSON_CreateObject(); cJSON_AddItemToObject(pJson, "SyncAppendEntries", pRoot); return pJson; } +char* syncAppendEntries2Str(const SyncAppendEntries* pMsg) { + cJSON* pJson = syncAppendEntries2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncAppendEntriesPrint(const SyncAppendEntries* pMsg) { + char* serialized = syncAppendEntries2Str(pMsg); + printf("syncAppendEntriesPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncAppendEntriesPrint2(char* s, const SyncAppendEntries* pMsg) { + char* serialized = syncAppendEntries2Str(pMsg); + printf("syncAppendEntriesPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncAppendEntriesLog(const SyncAppendEntries* pMsg) { + char* serialized = syncAppendEntries2Str(pMsg); + sTrace("syncAppendEntriesLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncAppendEntriesLog2(char* s, const SyncAppendEntries* pMsg) { + char* serialized = syncAppendEntries2Str(pMsg); + sTrace("syncAppendEntriesLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + // ---- message process SyncAppendEntriesReply---- SyncAppendEntriesReply* syncAppendEntriesReplyBuild() { uint32_t bytes = sizeof(SyncAppendEntriesReply); @@ -604,6 +1175,7 @@ SyncAppendEntriesReply* syncAppendEntriesReplyBuild() { memset(pMsg, 0, bytes); pMsg->bytes = bytes; pMsg->msgType = SYNC_APPEND_ENTRIES_REPLY; + return pMsg; } void syncAppendEntriesReplyDestroy(SyncAppendEntriesReply* pMsg) { @@ -622,6 +1194,25 @@ void syncAppendEntriesReplyDeserialize(const char* buf, uint32_t len, SyncAppend assert(len == pMsg->bytes); } +char* syncAppendEntriesReplySerialize2(const SyncAppendEntriesReply* pMsg, uint32_t* len) { + char* buf = malloc(pMsg->bytes); + assert(buf != NULL); + syncAppendEntriesReplySerialize(pMsg, buf, pMsg->bytes); + if (len != NULL) { + *len = pMsg->bytes; + } + return buf; +} + +SyncAppendEntriesReply* syncAppendEntriesReplyDeserialize2(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SyncAppendEntriesReply* pMsg = malloc(bytes); + assert(pMsg != NULL); + syncAppendEntriesReplyDeserialize(buf, len, pMsg); + assert(len == pMsg->bytes); + return pMsg; +} + void syncAppendEntriesReply2RpcMsg(const SyncAppendEntriesReply* pMsg, SRpcMsg* pRpcMsg) { memset(pRpcMsg, 0, sizeof(*pRpcMsg)); pRpcMsg->msgType = pMsg->msgType; @@ -634,6 +1225,11 @@ void syncAppendEntriesReplyFromRpcMsg(const SRpcMsg* pRpcMsg, SyncAppendEntriesR syncAppendEntriesReplyDeserialize(pRpcMsg->pCont, pRpcMsg->contLen, pMsg); } +SyncAppendEntriesReply* syncAppendEntriesReplyFromRpcMsg2(const SRpcMsg* pRpcMsg) { + SyncAppendEntriesReply* pMsg = syncAppendEntriesReplyDeserialize2(pRpcMsg->pCont, pRpcMsg->contLen); + return pMsg; +} + cJSON* syncAppendEntriesReply2Json(const SyncAppendEntriesReply* pMsg) { char u64buf[128]; @@ -671,11 +1267,47 @@ cJSON* syncAppendEntriesReply2Json(const SyncAppendEntriesReply* pMsg) { cJSON_AddNumberToObject(pDestId, "vgId", pMsg->destId.vgId); cJSON_AddItemToObject(pRoot, "destId", pDestId); + snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->term); + cJSON_AddStringToObject(pRoot, "term", u64buf); cJSON_AddNumberToObject(pRoot, "success", pMsg->success); snprintf(u64buf, sizeof(u64buf), "%lu", pMsg->matchIndex); - cJSON_AddStringToObject(pRoot, "match_index", u64buf); + cJSON_AddStringToObject(pRoot, "matchIndex", u64buf); cJSON* pJson = cJSON_CreateObject(); cJSON_AddItemToObject(pJson, "SyncAppendEntriesReply", pRoot); return pJson; -} \ No newline at end of file +} + +char* syncAppendEntriesReply2Str(const SyncAppendEntriesReply* pMsg) { + cJSON* pJson = syncAppendEntriesReply2Json(pMsg); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncAppendEntriesReplyPrint(const SyncAppendEntriesReply* pMsg) { + char* serialized = syncAppendEntriesReply2Str(pMsg); + printf("syncAppendEntriesReplyPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncAppendEntriesReplyPrint2(char* s, const SyncAppendEntriesReply* pMsg) { + char* serialized = syncAppendEntriesReply2Str(pMsg); + printf("syncAppendEntriesReplyPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncAppendEntriesReplyLog(const SyncAppendEntriesReply* pMsg) { + char* serialized = syncAppendEntriesReply2Str(pMsg); + sTrace("syncAppendEntriesReplyLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncAppendEntriesReplyLog2(char* s, const SyncAppendEntriesReply* pMsg) { + char* serialized = syncAppendEntriesReply2Str(pMsg); + sTrace("syncAppendEntriesReplyLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} diff --git a/source/libs/sync/src/syncRaft.c b/source/libs/sync/src/syncRaft.c deleted file mode 100644 index b07c6ea797cab0083caa0c14ba71918c58d951e7..0000000000000000000000000000000000000000 --- a/source/libs/sync/src/syncRaft.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "syncRaft.h" -#include "sync.h" - -#if 0 - -SRaft* raftOpen(SRaftId raftId, SSyncFSM* pFsm) { - SRaft* pRaft = (SRaft*)malloc(sizeof(SRaft)); - assert(pRaft != NULL); - - pRaft->id = raftId; - pRaft->pFsm = pFsm; - - pRaft->FpPing = doRaftPing; - pRaft->FpOnPing = onRaftPing; - pRaft->FpOnPingReply = onRaftPingReply; - - pRaft->FpRequestVote = doRaftRequestVote; - pRaft->FpOnRequestVote = onRaftRequestVote; - pRaft->FpOnRequestVoteReply = onRaftRequestVoteReply; - - pRaft->FpAppendEntries = doRaftAppendEntries; - pRaft->FpOnAppendEntries = onRaftAppendEntries; - pRaft->FpOnAppendEntriesReply = onRaftAppendEntriesReply; - - return pRaft; -} - -void raftClose(SRaft* pRaft) { - assert(pRaft != NULL); - free(pRaft); -} - -static int32_t doRaftPing(struct SRaft* ths, const RaftPing* pMsg) { return 0; } - -static int32_t onRaftPing(struct SRaft* ths, RaftPing* pMsg) { return 0; } - -static int32_t onRaftPingReply(struct SRaft* ths, RaftPingReply* pMsg) { return 0; } - -static int32_t doRaftRequestVote(struct SRaft* ths, const RaftRequestVote* pMsg) { return 0; } - -static int32_t onRaftRequestVote(struct SRaft* ths, RaftRequestVote* pMsg) { return 0; } - -static int32_t onRaftRequestVoteReply(struct SRaft* ths, RaftRequestVoteReply* pMsg) { return 0; } - -static int32_t doRaftAppendEntries(struct SRaft* ths, const RaftAppendEntries* pMsg) { return 0; } - -static int32_t onRaftAppendEntries(struct SRaft* ths, RaftAppendEntries* pMsg) { return 0; } - -static int32_t onRaftAppendEntriesReply(struct SRaft* ths, RaftAppendEntriesReply* pMsg) { return 0; } - -int32_t raftPropose(SRaft* pRaft, const SSyncBuffer* pBuf, bool isWeak) { return 0; } - -static int raftSendMsg(SRaftId destRaftId, const void* pMsg, const SRaft* pRaft) { return 0; } - -#endif \ No newline at end of file diff --git a/source/libs/sync/src/syncRaftEntry.c b/source/libs/sync/src/syncRaftEntry.c index e525d3c7c26366aa5f64eb596ee0ad3e92ad9340..f29b3022d8e0b15a77d9a811b6a8db19288c697c 100644 --- a/source/libs/sync/src/syncRaftEntry.c +++ b/source/libs/sync/src/syncRaftEntry.c @@ -14,3 +14,119 @@ */ #include "syncRaftEntry.h" +#include "syncUtil.h" + +SSyncRaftEntry* syncEntryBuild(uint32_t dataLen) { + uint32_t bytes = sizeof(SSyncRaftEntry) + dataLen; + SSyncRaftEntry* pEntry = malloc(bytes); + assert(pEntry != NULL); + memset(pEntry, 0, bytes); + pEntry->bytes = bytes; + pEntry->dataLen = dataLen; + return pEntry; +} + +SSyncRaftEntry* syncEntryBuild2(SyncClientRequest* pMsg, SyncTerm term, SyncIndex index) { + SSyncRaftEntry* pEntry = syncEntryBuild(pMsg->dataLen); + assert(pEntry != NULL); + + pEntry->msgType = pMsg->msgType; + pEntry->originalRpcType = pMsg->originalRpcType; + pEntry->seqNum = pMsg->seqNum; + pEntry->isWeak = pMsg->isWeak; + pEntry->term = term; + pEntry->index = index; + pEntry->dataLen = pMsg->dataLen; + memcpy(pEntry->data, pMsg->data, pMsg->dataLen); + + return pEntry; +} + +void syncEntryDestory(SSyncRaftEntry* pEntry) { + if (pEntry != NULL) { + free(pEntry); + } +} + +char* syncEntrySerialize(const SSyncRaftEntry* pEntry, uint32_t* len) { + char* buf = malloc(pEntry->bytes); + assert(buf != NULL); + memcpy(buf, pEntry, pEntry->bytes); + if (len != NULL) { + *len = pEntry->bytes; + } + return buf; +} + +SSyncRaftEntry* syncEntryDeserialize(const char* buf, uint32_t len) { + uint32_t bytes = *((uint32_t*)buf); + SSyncRaftEntry* pEntry = malloc(bytes); + assert(pEntry != NULL); + memcpy(pEntry, buf, len); + assert(len == pEntry->bytes); + return pEntry; +} + +cJSON* syncEntry2Json(const SSyncRaftEntry* pEntry) { + char u64buf[128]; + + cJSON* pRoot = cJSON_CreateObject(); + cJSON_AddNumberToObject(pRoot, "bytes", pEntry->bytes); + cJSON_AddNumberToObject(pRoot, "msgType", pEntry->msgType); + cJSON_AddNumberToObject(pRoot, "originalRpcType", pEntry->originalRpcType); + snprintf(u64buf, sizeof(u64buf), "%lu", pEntry->seqNum); + cJSON_AddStringToObject(pRoot, "seqNum", u64buf); + cJSON_AddNumberToObject(pRoot, "isWeak", pEntry->isWeak); + snprintf(u64buf, sizeof(u64buf), "%lu", pEntry->term); + cJSON_AddStringToObject(pRoot, "term", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", pEntry->index); + cJSON_AddStringToObject(pRoot, "index", u64buf); + cJSON_AddNumberToObject(pRoot, "dataLen", pEntry->dataLen); + + char* s; + s = syncUtilprintBin((char*)(pEntry->data), pEntry->dataLen); + cJSON_AddStringToObject(pRoot, "data", s); + free(s); + + s = syncUtilprintBin2((char*)(pEntry->data), pEntry->dataLen); + cJSON_AddStringToObject(pRoot, "data2", s); + free(s); + + cJSON* pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SSyncRaftEntry", pRoot); + return pJson; +} + +char* syncEntry2Str(const SSyncRaftEntry* pEntry) { + cJSON* pJson = syncEntry2Json(pEntry); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ---------------------- +void syncEntryPrint(const SSyncRaftEntry* pObj) { + char* serialized = syncEntry2Str(pObj); + printf("syncEntryPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void syncEntryPrint2(char* s, const SSyncRaftEntry* pObj) { + char* serialized = syncEntry2Str(pObj); + printf("syncEntryPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void syncEntryLog(const SSyncRaftEntry* pObj) { + char* serialized = syncEntry2Str(pObj); + sTrace("syncEntryLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void syncEntryLog2(char* s, const SSyncRaftEntry* pObj) { + char* serialized = syncEntry2Str(pObj); + sTrace("syncEntryLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} \ No newline at end of file diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c index e467057c8f2bbe0daf866cf845057d0d7f8f1a1a..6ebeba1991c3df5a70ee2349bb3482d2b318d776 100644 --- a/source/libs/sync/src/syncRaftLog.c +++ b/source/libs/sync/src/syncRaftLog.c @@ -14,46 +14,171 @@ */ #include "syncRaftLog.h" +#include "wal.h" -int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncBuffer* pBuf) { return 0; } - -// get one log entry, user need to free pBuf->data -int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncBuffer* pBuf) { return 0; } - -// TLA+ Spec -// \* Leader i advances its commitIndex. -// \* This is done as a separate step from handling AppendEntries responses, -// \* in part to minimize atomic regions, and in part so that leaders of -// \* single-server clusters are able to mark entries committed. -// AdvanceCommitIndex(i) == -// /\ state[i] = Leader -// /\ LET \* The set of servers that agree up through index. -// Agree(index) == {i} \cup {k \in Server : -// matchIndex[i][k] >= index} -// \* The maximum indexes for which a quorum agrees -// agreeIndexes == {index \in 1..Len(log[i]) : -// Agree(index) \in Quorum} -// \* New value for commitIndex'[i] -// newCommitIndex == -// IF /\ agreeIndexes /= {} -// /\ log[i][Max(agreeIndexes)].term = currentTerm[i] -// THEN -// Max(agreeIndexes) -// ELSE -// commitIndex[i] -// IN commitIndex' = [commitIndex EXCEPT ![i] = newCommitIndex] -// /\ UNCHANGED <> -// -int32_t raftLogupdateCommitIndex(struct SSyncLogStore* pLogStore, SyncIndex index) { return 0; } - -// truncate log with index, entries after the given index (>index) will be deleted -int32_t raftLogTruncate(struct SSyncLogStore* pLogStore, SyncIndex index) { return 0; } - -// return commit index of log -SyncIndex raftLogGetCommitIndex(struct SSyncLogStore* pLogStore) { return 0; } - -// return index of last entry -SyncIndex raftLogGetLastIndex(struct SSyncLogStore* pLogStore) { return 0; } - -// return term of last entry -SyncTerm raftLogGetLastTerm(struct SSyncLogStore* pLogStore) { return 0; } \ No newline at end of file +SSyncLogStore* logStoreCreate(SSyncNode* pSyncNode) { + SSyncLogStore* pLogStore = malloc(sizeof(SSyncLogStore)); + assert(pLogStore != NULL); + + pLogStore->data = malloc(sizeof(SSyncLogStoreData)); + assert(pLogStore->data != NULL); + + SSyncLogStoreData* pData = pLogStore->data; + pData->pSyncNode = pSyncNode; + pData->pWal = pSyncNode->pWal; + + pLogStore->appendEntry = logStoreAppendEntry; + pLogStore->getEntry = logStoreGetEntry; + pLogStore->truncate = logStoreTruncate; + pLogStore->getLastIndex = logStoreLastIndex; + pLogStore->getLastTerm = logStoreLastTerm; + pLogStore->updateCommitIndex = logStoreUpdateCommitIndex; + pLogStore->getCommitIndex = logStoreGetCommitIndex; +} + +void logStoreDestory(SSyncLogStore* pLogStore) { + if (pLogStore != NULL) { + free(pLogStore->data); + free(pLogStore); + } +} + +int32_t logStoreAppendEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) { + SSyncLogStoreData* pData = pLogStore->data; + SWal* pWal = pData->pWal; + + assert(pEntry->index == logStoreLastIndex(pLogStore) + 1); + uint32_t len; + char* serialized = syncEntrySerialize(pEntry, &len); + assert(serialized != NULL); + + int code; + code = walWrite(pWal, pEntry->index, pEntry->msgType, serialized, len); + assert(code == 0); + + walFsync(pWal, true); + free(serialized); +} + +SSyncRaftEntry* logStoreGetEntry(SSyncLogStore* pLogStore, SyncIndex index) { + SSyncLogStoreData* pData = pLogStore->data; + SWal* pWal = pData->pWal; + SSyncRaftEntry* pEntry; + + SWalReadHandle* pWalHandle = walOpenReadHandle(pWal); + walReadWithHandle(pWalHandle, index); + pEntry = syncEntryDeserialize(pWalHandle->pHead->head.body, pWalHandle->pHead->head.len); + assert(pEntry != NULL); + + // need to hold, do not new every time!! + walCloseReadHandle(pWalHandle); + return pEntry; +} + +int32_t logStoreTruncate(SSyncLogStore* pLogStore, SyncIndex fromIndex) { + SSyncLogStoreData* pData = pLogStore->data; + SWal* pWal = pData->pWal; + walRollback(pWal, fromIndex); +} + +SyncIndex logStoreLastIndex(SSyncLogStore* pLogStore) { + SSyncLogStoreData* pData = pLogStore->data; + SWal* pWal = pData->pWal; + SyncIndex lastIndex = walGetLastVer(pWal); + return lastIndex; +} + +SyncTerm logStoreLastTerm(SSyncLogStore* pLogStore) { + SyncTerm lastTerm = 0; + SSyncRaftEntry* pLastEntry = logStoreGetLastEntry(pLogStore); + if (pLastEntry != NULL) { + lastTerm = pLastEntry->term; + free(pLastEntry); + } + return lastTerm; +} + +int32_t logStoreUpdateCommitIndex(SSyncLogStore* pLogStore, SyncIndex index) { + SSyncLogStoreData* pData = pLogStore->data; + SWal* pWal = pData->pWal; + walCommit(pWal, index); +} + +SyncIndex logStoreGetCommitIndex(SSyncLogStore* pLogStore) { + SSyncLogStoreData* pData = pLogStore->data; + return pData->pSyncNode->commitIndex; +} + +SSyncRaftEntry* logStoreGetLastEntry(SSyncLogStore* pLogStore) { + SSyncLogStoreData* pData = pLogStore->data; + SWal* pWal = pData->pWal; + SyncIndex lastIndex = walGetLastVer(pWal); + + SSyncRaftEntry* pEntry = NULL; + if (lastIndex > 0) { + pEntry = logStoreGetEntry(pLogStore, lastIndex); + } + return pEntry; +} + +cJSON* logStore2Json(SSyncLogStore* pLogStore) { + char u64buf[128]; + + SSyncLogStoreData* pData = (SSyncLogStoreData*)pLogStore->data; + cJSON* pRoot = cJSON_CreateObject(); + snprintf(u64buf, sizeof(u64buf), "%p", pData->pSyncNode); + cJSON_AddStringToObject(pRoot, "pSyncNode", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pData->pWal); + cJSON_AddStringToObject(pRoot, "pWal", u64buf); + snprintf(u64buf, sizeof(u64buf), "%ld", logStoreLastIndex(pLogStore)); + cJSON_AddStringToObject(pRoot, "LastIndex", u64buf); + snprintf(u64buf, sizeof(u64buf), "%lu", logStoreLastTerm(pLogStore)); + cJSON_AddStringToObject(pRoot, "LastTerm", u64buf); + + cJSON* pEntries = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "pEntries", pEntries); + SyncIndex lastIndex = logStoreLastIndex(pLogStore); + for (SyncIndex i = 0; i <= lastIndex; ++i) { + SSyncRaftEntry* pEntry = logStoreGetEntry(pLogStore, i); + cJSON_AddItemToArray(pEntries, syncEntry2Json(pEntry)); + syncEntryDestory(pEntry); + } + + cJSON* pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SSyncLogStore", pRoot); + return pJson; +} + +char* logStore2Str(SSyncLogStore* pLogStore) { + cJSON* pJson = logStore2Json(pLogStore); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ----------------- +void logStorePrint(SSyncLogStore* pLogStore) { + char* serialized = logStore2Str(pLogStore); + printf("logStorePrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void logStorePrint2(char* s, SSyncLogStore* pLogStore) { + char* serialized = logStore2Str(pLogStore); + printf("logStorePrint | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void logStoreLog(SSyncLogStore* pLogStore) { + char* serialized = logStore2Str(pLogStore); + sTrace("logStorePrint | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void logStoreLog2(char* s, SSyncLogStore* pLogStore) { + char* serialized = logStore2Str(pLogStore); + sTrace("logStorePrint | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} \ No newline at end of file diff --git a/source/libs/sync/src/syncRaftStore.c b/source/libs/sync/src/syncRaftStore.c index 7154a21bd14df0fc34cd092a2b8ac844266176f4..5ad618b9c097e7c088133314be3067c5f8d09819 100644 --- a/source/libs/sync/src/syncRaftStore.c +++ b/source/libs/sync/src/syncRaftStore.c @@ -15,6 +15,8 @@ #include "syncRaftStore.h" #include "cJSON.h" +#include "syncEnv.h" +#include "syncUtil.h" // private function static int32_t raftStoreInit(SRaftStore *pRaftStore); @@ -135,8 +137,57 @@ int32_t raftStoreDeserialize(SRaftStore *pRaftStore, char *buf, size_t len) { return 0; } -void raftStorePrint(SRaftStore *pRaftStore) { - char storeBuf[RAFT_STORE_BLOCK_SIZE]; - raftStoreSerialize(pRaftStore, storeBuf, sizeof(storeBuf)); - printf("%s\n", storeBuf); +bool raftStoreHasVoted(SRaftStore *pRaftStore) { + bool b = syncUtilEmptyId(&(pRaftStore->voteFor)); + return b; +} + +void raftStoreVote(SRaftStore *pRaftStore, SRaftId *pRaftId) { + assert(!raftStoreHasVoted(pRaftStore)); + assert(!syncUtilEmptyId(pRaftId)); + pRaftStore->voteFor = *pRaftId; + raftStorePersist(pRaftStore); +} + +void raftStoreClearVote(SRaftStore *pRaftStore) { + pRaftStore->voteFor = EMPTY_RAFT_ID; + raftStorePersist(pRaftStore); +} + +void raftStoreNextTerm(SRaftStore *pRaftStore) { + ++(pRaftStore->currentTerm); + raftStorePersist(pRaftStore); +} + +void raftStoreSetTerm(SRaftStore *pRaftStore, SyncTerm term) { + pRaftStore->currentTerm = term; + raftStorePersist(pRaftStore); +} + +// for debug ------------------- +void raftStorePrint(SRaftStore *pObj) { + char serialized[RAFT_STORE_BLOCK_SIZE]; + raftStoreSerialize(pObj, serialized, sizeof(serialized)); + printf("raftStorePrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); +} + +void raftStorePrint2(char *s, SRaftStore *pObj) { + char serialized[RAFT_STORE_BLOCK_SIZE]; + raftStoreSerialize(pObj, serialized, sizeof(serialized)); + printf("raftStorePrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); +} +void raftStoreLog(SRaftStore *pObj) { + char serialized[RAFT_STORE_BLOCK_SIZE]; + raftStoreSerialize(pObj, serialized, sizeof(serialized)); + sTrace("raftStoreLog | len:%lu | %s", strlen(serialized), serialized); + fflush(NULL); +} + +void raftStoreLog2(char *s, SRaftStore *pObj) { + char serialized[RAFT_STORE_BLOCK_SIZE]; + raftStoreSerialize(pObj, serialized, sizeof(serialized)); + sTrace("raftStoreLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + fflush(NULL); } diff --git a/source/libs/sync/src/syncReplication.c b/source/libs/sync/src/syncReplication.c index 37e8959ff33a3c2f58db762ab9fb9053154c4e87..b935943a1dd7dab3c69d2ae4c923504905ad2b14 100644 --- a/source/libs/sync/src/syncReplication.c +++ b/source/libs/sync/src/syncReplication.c @@ -14,7 +14,11 @@ */ #include "syncReplication.h" +#include "syncIndexMgr.h" #include "syncMessage.h" +#include "syncRaftEntry.h" +#include "syncRaftLog.h" +#include "syncUtil.h" // TLA+ Spec // AppendEntries(i, j) == @@ -41,7 +45,48 @@ // mdest |-> j]) // /\ UNCHANGED <> // -int32_t syncNodeAppendEntriesPeers(SSyncNode* pSyncNode) {} +int32_t syncNodeAppendEntriesPeers(SSyncNode* pSyncNode) { + assert(pSyncNode->state == TAOS_SYNC_STATE_LEADER); + + int32_t ret = 0; + for (int i = 0; i < pSyncNode->peersNum; ++i) { + SRaftId* pDestId = &(pSyncNode->peersId[i]); + SyncIndex nextIndex = syncIndexMgrGetIndex(pSyncNode->pNextIndex, pDestId); + + SyncIndex preLogIndex = nextIndex - 1; + + SyncTerm preLogTerm = 0; + if (preLogIndex >= SYNC_INDEX_BEGIN) { + SSyncRaftEntry* pPreEntry = pSyncNode->pLogStore->getEntry(pSyncNode->pLogStore, preLogIndex); + preLogTerm = pPreEntry->term; + } + + SyncIndex lastIndex = syncUtilMinIndex(pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore), nextIndex); + assert(nextIndex == lastIndex); + + SSyncRaftEntry* pEntry = logStoreGetEntry(pSyncNode->pLogStore, nextIndex); + assert(pEntry != NULL); + + SyncAppendEntries* pMsg = syncAppendEntriesBuild(pEntry->bytes); + pMsg->srcId = pSyncNode->myRaftId; + pMsg->destId = *pDestId; + pMsg->prevLogIndex = preLogIndex; + pMsg->prevLogTerm = preLogTerm; + pMsg->commitIndex = pSyncNode->commitIndex; + pMsg->dataLen = pEntry->bytes; + // add pEntry into msg + + syncNodeAppendEntries(pSyncNode, pDestId, pMsg); + } + + return ret; +} + +int32_t syncNodeReplicate(SSyncNode* pSyncNode) { + // start replicate + int32_t ret = syncNodeAppendEntriesPeers(pSyncNode); + return ret; +} int32_t syncNodeAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftId, const SyncAppendEntries* pMsg) { sTrace("syncNodeAppendEntries pSyncNode:%p ", pSyncNode); diff --git a/source/libs/sync/src/syncRequestVote.c b/source/libs/sync/src/syncRequestVote.c index 354c559a905470a9012b42897c75e88f73b46189..be4f40aaadd1aaa09bf3109341d59b988e63e646 100644 --- a/source/libs/sync/src/syncRequestVote.c +++ b/source/libs/sync/src/syncRequestVote.c @@ -14,6 +14,10 @@ */ #include "syncRequestVote.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" // TLA+ Spec // HandleRequestVoteRequest(i, j, m) == @@ -37,4 +41,34 @@ // m) // /\ UNCHANGED <> // -int32_t syncNodeOnRequestVoteCb(SSyncNode* ths, SyncRequestVote* pMsg) {} +int32_t syncNodeOnRequestVoteCb(SSyncNode* ths, SyncRequestVote* pMsg) { + int32_t ret = 0; + syncRequestVoteLog2("==syncNodeOnRequestVoteCb==", pMsg); + + if (pMsg->term > ths->pRaftStore->currentTerm) { + syncNodeUpdateTerm(ths, pMsg->term); + } + assert(pMsg->term <= ths->pRaftStore->currentTerm); + + bool logOK = (pMsg->lastLogTerm > ths->pLogStore->getLastTerm(ths->pLogStore)) || + ((pMsg->lastLogTerm == ths->pLogStore->getLastTerm(ths->pLogStore)) && + (pMsg->lastLogIndex >= ths->pLogStore->getLastIndex(ths->pLogStore))); + bool grant = (pMsg->term == ths->pRaftStore->currentTerm) && logOK && + ((!raftStoreHasVoted(ths->pRaftStore)) || (syncUtilSameId(&(ths->pRaftStore->voteFor), &(pMsg->srcId)))); + if (grant) { + raftStoreVote(ths->pRaftStore, &(pMsg->srcId)); + } + + SyncRequestVoteReply* pReply = syncRequestVoteReplyBuild(); + pReply->srcId = ths->myRaftId; + pReply->destId = pMsg->srcId; + pReply->term = ths->pRaftStore->currentTerm; + pReply->voteGranted = grant; + + SRpcMsg rpcMsg; + syncRequestVoteReply2RpcMsg(pReply, &rpcMsg); + syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg); + syncRequestVoteReplyDestroy(pReply); + + return ret; +} diff --git a/source/libs/sync/src/syncRequestVoteReply.c b/source/libs/sync/src/syncRequestVoteReply.c index 72223ea83c7abf96be9c6e24c237a340c58c0acf..7cdeace1667577eeb781e1b0908e80405c1a2ded 100644 --- a/source/libs/sync/src/syncRequestVoteReply.c +++ b/source/libs/sync/src/syncRequestVoteReply.c @@ -14,6 +14,10 @@ */ #include "syncRequestVoteReply.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" // TLA+ Spec // HandleRequestVoteResponse(i, j, m) == @@ -32,4 +36,33 @@ // /\ Discard(m) // /\ UNCHANGED <> // -int32_t syncNodeOnRequestVoteReplyCb(SSyncNode* ths, SyncRequestVoteReply* pMsg) {} +int32_t syncNodeOnRequestVoteReplyCb(SSyncNode* ths, SyncRequestVoteReply* pMsg) { + int32_t ret = 0; + syncRequestVoteReplyLog2("==syncNodeOnRequestVoteReplyCb==", pMsg); + + if (pMsg->term < ths->pRaftStore->currentTerm) { + sTrace("DropStaleResponse, receive term:%lu, current term:%lu", pMsg->term, ths->pRaftStore->currentTerm); + return ret; + } + + // no need this code, because if I receive reply.term, then I must have sent for that term. + // if (pMsg->term > ths->pRaftStore->currentTerm) { + // syncNodeUpdateTerm(ths, pMsg->term); + // } + + assert(pMsg->term == ths->pRaftStore->currentTerm); + + if (ths->state == TAOS_SYNC_STATE_CANDIDATE) { + votesRespondAdd(ths->pVotesRespond, pMsg); + if (pMsg->voteGranted) { + voteGrantedVote(ths->pVotesGranted, pMsg); + if (voteGrantedMajority(ths->pVotesGranted)) { + if (ths->pVotesGranted->toLeader) { + syncNodeCandidate2Leader(ths); + ths->pVotesGranted->toLeader = true; + } + } + } + } + return ret; +} diff --git a/source/libs/sync/src/syncSnapshot.c b/source/libs/sync/src/syncSnapshot.c index da194780ffdf17d5b511a2592b736aa927263b18..42b2bd993b515789934268f4400fece4f040f7c5 100644 --- a/source/libs/sync/src/syncSnapshot.c +++ b/source/libs/sync/src/syncSnapshot.c @@ -14,7 +14,6 @@ */ #include "syncSnapshot.h" -#include "syncRaft.h" int32_t takeSnapshot(SSyncFSM *pFsm, SSnapshot *pSnapshot) { return 0; } diff --git a/source/libs/sync/src/syncTimeout.c b/source/libs/sync/src/syncTimeout.c index df9b9d27b4a39f34f6ae7ef2100760f20baec40e..3a48b0cbb35bfcb56d3a45373360f2b8e59ec69c 100644 --- a/source/libs/sync/src/syncTimeout.c +++ b/source/libs/sync/src/syncTimeout.c @@ -19,15 +19,7 @@ int32_t syncNodeOnTimeoutCb(SSyncNode* ths, SyncTimeout* pMsg) { int32_t ret = 0; - sTrace("<-- syncNodeOnTimeoutCb -->"); - - { - cJSON* pJson = syncTimeout2Json(pMsg); - char* serialized = cJSON_Print(pJson); - sTrace("process syncMessage recv: syncNodeOnTimeoutCb pMsg:%s ", serialized); - free(serialized); - cJSON_Delete(pJson); - } + syncTimeoutLog2("==syncNodeOnTimeoutCb==", pMsg); if (pMsg->timeoutType == SYNC_TIMEOUT_PING) { if (atomic_load_64(&ths->pingTimerLogicClockUser) <= pMsg->logicClock) { @@ -44,7 +36,7 @@ int32_t syncNodeOnTimeoutCb(SSyncNode* ths, SyncTimeout* pMsg) { } else if (pMsg->timeoutType == SYNC_TIMEOUT_HEARTBEAT) { if (atomic_load_64(&ths->heartbeatTimerLogicClockUser) <= pMsg->logicClock) { ++(ths->heartbeatTimerCounter); - syncNodeAppendEntriesPeers(ths); + syncNodeReplicate(ths); } } else { sTrace("unknown timeoutType:%d", pMsg->timeoutType); diff --git a/source/libs/sync/src/syncUtil.c b/source/libs/sync/src/syncUtil.c index c70e4900254881e9e296119d9ac31ec754f3f0f7..ba8a76c1901750ae9687e22e2bf12165a8fb9238 100644 --- a/source/libs/sync/src/syncUtil.c +++ b/source/libs/sync/src/syncUtil.c @@ -74,6 +74,8 @@ bool syncUtilSameId(const SRaftId* pId1, const SRaftId* pId2) { return ret; } +bool syncUtilEmptyId(const SRaftId* pId) { return (pId->addr == 0 && pId->vgId == 0); } + // ---- SSyncBuffer ----- void syncUtilbufBuild(SSyncBuffer* syncBuf, size_t len) { syncBuf->len = len; @@ -95,6 +97,103 @@ void syncUtilbufCopyDeep(const SSyncBuffer* src, SSyncBuffer* dest) { // ---- misc ---- -int32_t syncUtilRand(int32_t max) { return rand() % max; } +int32_t syncUtilRand(int32_t max) { return taosRand() % max; } + +int32_t syncUtilElectRandomMS() { return ELECT_TIMER_MS_MIN + syncUtilRand(ELECT_TIMER_MS_RANGE); } + +int32_t syncUtilQuorum(int32_t replicaNum) { return replicaNum / 2 + 1; } + +cJSON* syncUtilNodeInfo2Json(const SNodeInfo* p) { + char u64buf[128]; + cJSON* pRoot = cJSON_CreateObject(); + + cJSON_AddStringToObject(pRoot, "nodeFqdn", p->nodeFqdn); + cJSON_AddNumberToObject(pRoot, "nodePort", p->nodePort); + + cJSON* pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SNodeInfo", pRoot); + return pJson; +} + +cJSON* syncUtilRaftId2Json(const SRaftId* p) { + char u64buf[128]; + cJSON* pRoot = cJSON_CreateObject(); + + snprintf(u64buf, sizeof(u64buf), "%lu", p->addr); + cJSON_AddStringToObject(pRoot, "addr", u64buf); + char host[128]; + uint16_t port; + syncUtilU642Addr(p->addr, host, sizeof(host), &port); + cJSON_AddStringToObject(pRoot, "host", host); + cJSON_AddNumberToObject(pRoot, "port", port); + cJSON_AddNumberToObject(pRoot, "vgId", p->vgId); + + cJSON* pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SRaftId", pRoot); + return pJson; +} + +char* syncUtilRaftId2Str(const SRaftId* p) { + cJSON* pJson = syncUtilRaftId2Json(p); + char* serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +const char* syncUtilState2String(ESyncState state) { + if (state == TAOS_SYNC_STATE_FOLLOWER) { + return "TAOS_SYNC_STATE_FOLLOWER"; + } else if (state == TAOS_SYNC_STATE_CANDIDATE) { + return "TAOS_SYNC_STATE_CANDIDATE"; + } else if (state == TAOS_SYNC_STATE_LEADER) { + return "TAOS_SYNC_STATE_LEADER"; + } else { + return "TAOS_SYNC_STATE_UNKNOWN"; + } +} + +bool syncUtilCanPrint(char c) { + if (c >= 32 && c <= 126) { + return true; + } else { + return false; + } +} + +char* syncUtilprintBin(char* ptr, uint32_t len) { + char* s = malloc(len + 1); + assert(s != NULL); + memset(s, 0, len + 1); + memcpy(s, ptr, len); + + for (int i = 0; i < len; ++i) { + if (!syncUtilCanPrint(s[i])) { + s[i] = '.'; + } + } + return s; +} + +char* syncUtilprintBin2(char* ptr, uint32_t len) { + uint32_t len2 = len * 4 + 1; + char* s = malloc(len2); + assert(s != NULL); + memset(s, 0, len2); + + char* p = s; + for (int i = 0; i < len; ++i) { + int n = sprintf(p, "%d,", ptr[i]); + p += n; + } + return s; +} + +SyncIndex syncUtilMinIndex(SyncIndex a, SyncIndex b) { + SyncIndex r = a < b ? a : b; + return r; +} -int32_t syncUtilElectRandomMS() { ELECT_TIMER_MS_MIN + syncUtilRand(ELECT_TIMER_MS_RANGE); } \ No newline at end of file +SyncIndex syncUtilMaxIndex(SyncIndex a, SyncIndex b) { + SyncIndex r = a > b ? a : b; + return r; +} \ No newline at end of file diff --git a/source/libs/sync/src/syncVoteMgr.c b/source/libs/sync/src/syncVoteMgr.c index c9f0ceab57a62116f4a786bdba3c386a28dfbd3b..5c8e70979c14b0fe8eff06aa2fffa33c3c34581d 100644 --- a/source/libs/sync/src/syncVoteMgr.c +++ b/source/libs/sync/src/syncVoteMgr.c @@ -14,15 +14,25 @@ */ #include "syncVoteMgr.h" +#include "syncUtil.h" + +// SVotesGranted ----------------------------- +static void voteGrantedClearVotes(SVotesGranted *pVotesGranted) { + memset(pVotesGranted->isGranted, 0, sizeof(pVotesGranted->isGranted)); + pVotesGranted->votes = 0; +} SVotesGranted *voteGrantedCreate(SSyncNode *pSyncNode) { SVotesGranted *pVotesGranted = malloc(sizeof(SVotesGranted)); assert(pVotesGranted != NULL); memset(pVotesGranted, 0, sizeof(SVotesGranted)); - pVotesGranted->quorum = pSyncNode->quorum; + pVotesGranted->replicas = &(pSyncNode->replicasId); + pVotesGranted->replicaNum = pSyncNode->replicaNum; + voteGrantedClearVotes(pVotesGranted); + pVotesGranted->term = 0; - pVotesGranted->votes = 0; + pVotesGranted->quorum = pSyncNode->quorum; pVotesGranted->toLeader = false; pVotesGranted->pSyncNode = pSyncNode; @@ -43,15 +53,100 @@ bool voteGrantedMajority(SVotesGranted *pVotesGranted) { void voteGrantedVote(SVotesGranted *pVotesGranted, SyncRequestVoteReply *pMsg) { assert(pMsg->voteGranted == true); assert(pMsg->term == pVotesGranted->term); - pVotesGranted->votes++; + assert(syncUtilSameId(&pVotesGranted->pSyncNode->myRaftId, &pMsg->destId)); + + int j = -1; + for (int i = 0; i < pVotesGranted->replicaNum; ++i) { + if (syncUtilSameId(&((*(pVotesGranted->replicas))[i]), &(pMsg->srcId))) { + j = i; + break; + } + } + assert(j != -1); + assert(j >= 0 && j < pVotesGranted->replicaNum); + + if (pVotesGranted->isGranted[j] != true) { + ++(pVotesGranted->votes); + pVotesGranted->isGranted[j] = true; + } + assert(pVotesGranted->votes <= pVotesGranted->replicaNum); } void voteGrantedReset(SVotesGranted *pVotesGranted, SyncTerm term) { pVotesGranted->term = term; - pVotesGranted->votes = 0; + voteGrantedClearVotes(pVotesGranted); pVotesGranted->toLeader = false; } +cJSON *voteGranted2Json(SVotesGranted *pVotesGranted) { + char u64buf[128]; + cJSON *pRoot = cJSON_CreateObject(); + + cJSON_AddNumberToObject(pRoot, "replicaNum", pVotesGranted->replicaNum); + cJSON *pReplicas = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "replicas", pReplicas); + for (int i = 0; i < pVotesGranted->replicaNum; ++i) { + cJSON_AddItemToArray(pReplicas, syncUtilRaftId2Json(&(*(pVotesGranted->replicas))[i])); + } + int *arr = (int *)malloc(sizeof(int) * pVotesGranted->replicaNum); + for (int i = 0; i < pVotesGranted->replicaNum; ++i) { + arr[i] = pVotesGranted->isGranted[i]; + } + cJSON *pIsGranted = cJSON_CreateIntArray(arr, pVotesGranted->replicaNum); + free(arr); + cJSON_AddItemToObject(pRoot, "isGranted", pIsGranted); + + cJSON_AddNumberToObject(pRoot, "votes", pVotesGranted->votes); + snprintf(u64buf, sizeof(u64buf), "%lu", pVotesGranted->term); + cJSON_AddStringToObject(pRoot, "term", u64buf); + cJSON_AddNumberToObject(pRoot, "quorum", pVotesGranted->quorum); + cJSON_AddNumberToObject(pRoot, "toLeader", pVotesGranted->toLeader); + snprintf(u64buf, sizeof(u64buf), "%p", pVotesGranted->pSyncNode); + cJSON_AddStringToObject(pRoot, "pSyncNode", u64buf); + + bool majority = voteGrantedMajority(pVotesGranted); + cJSON_AddNumberToObject(pRoot, "majority", majority); + + cJSON *pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SVotesGranted", pRoot); + return pJson; +} + +char *voteGranted2Str(SVotesGranted *pVotesGranted) { + cJSON *pJson = voteGranted2Json(pVotesGranted); + char * serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ------------------- +void voteGrantedPrint(SVotesGranted *pObj) { + char *serialized = voteGranted2Str(pObj); + printf("voteGrantedPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void voteGrantedPrint2(char *s, SVotesGranted *pObj) { + char *serialized = voteGranted2Str(pObj); + printf("voteGrantedPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void voteGrantedLog(SVotesGranted *pObj) { + char *serialized = voteGranted2Str(pObj); + sTrace("voteGrantedLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void voteGrantedLog2(char *s, SVotesGranted *pObj) { + char *serialized = voteGranted2Str(pObj); + sTrace("voteGrantedLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); +} + +// SVotesRespond ----------------------------- SVotesRespond *votesRespondCreate(SSyncNode *pSyncNode) { SVotesRespond *pVotesRespond = malloc(sizeof(SVotesRespond)); assert(pVotesRespond != NULL); @@ -65,6 +160,12 @@ SVotesRespond *votesRespondCreate(SSyncNode *pSyncNode) { return pVotesRespond; } +void votesRespondDestory(SVotesRespond *pVotesRespond) { + if (pVotesRespond != NULL) { + free(pVotesRespond); + } +} + bool votesResponded(SVotesRespond *pVotesRespond, const SRaftId *pRaftId) { bool ret = false; for (int i = 0; i < pVotesRespond->replicaNum; ++i) { @@ -79,8 +180,8 @@ bool votesResponded(SVotesRespond *pVotesRespond, const SRaftId *pRaftId) { void votesRespondAdd(SVotesRespond *pVotesRespond, const SyncRequestVoteReply *pMsg) { assert(pVotesRespond->term == pMsg->term); for (int i = 0; i < pVotesRespond->replicaNum; ++i) { - if (syncUtilSameId(&(*pVotesRespond->replicas)[i], &pMsg->srcId)) { - assert(pVotesRespond->isRespond[i] == false); + if (syncUtilSameId(&((*(pVotesRespond->replicas))[i]), &pMsg->srcId)) { + // assert(pVotesRespond->isRespond[i] == false); pVotesRespond->isRespond[i] = true; return; } @@ -88,9 +189,79 @@ void votesRespondAdd(SVotesRespond *pVotesRespond, const SyncRequestVoteReply *p assert(0); } -void Reset(SVotesRespond *pVotesRespond, SyncTerm term) { +void votesRespondReset(SVotesRespond *pVotesRespond, SyncTerm term) { pVotesRespond->term = term; + memset(pVotesRespond->isRespond, 0, sizeof(pVotesRespond->isRespond)); + /* + for (int i = 0; i < pVotesRespond->replicaNum; ++i) { + pVotesRespond->isRespond[i] = false; + } + */ +} + +cJSON *votesRespond2Json(SVotesRespond *pVotesRespond) { + char u64buf[128]; + cJSON *pRoot = cJSON_CreateObject(); + + cJSON_AddNumberToObject(pRoot, "replicaNum", pVotesRespond->replicaNum); + cJSON *pReplicas = cJSON_CreateArray(); + cJSON_AddItemToObject(pRoot, "replicas", pReplicas); for (int i = 0; i < pVotesRespond->replicaNum; ++i) { - pVotesRespond->isRespond[i] = false; + cJSON_AddItemToArray(pReplicas, syncUtilRaftId2Json(&(*(pVotesRespond->replicas))[i])); } + int respondNum = 0; + int *arr = (int *)malloc(sizeof(int) * pVotesRespond->replicaNum); + for (int i = 0; i < pVotesRespond->replicaNum; ++i) { + arr[i] = pVotesRespond->isRespond[i]; + if (pVotesRespond->isRespond[i]) { + respondNum++; + } + } + cJSON *pIsRespond = cJSON_CreateIntArray(arr, pVotesRespond->replicaNum); + free(arr); + cJSON_AddItemToObject(pRoot, "isRespond", pIsRespond); + cJSON_AddNumberToObject(pRoot, "respondNum", respondNum); + + snprintf(u64buf, sizeof(u64buf), "%lu", pVotesRespond->term); + cJSON_AddStringToObject(pRoot, "term", u64buf); + snprintf(u64buf, sizeof(u64buf), "%p", pVotesRespond->pSyncNode); + cJSON_AddStringToObject(pRoot, "pSyncNode", u64buf); + + cJSON *pJson = cJSON_CreateObject(); + cJSON_AddItemToObject(pJson, "SVotesRespond", pRoot); + return pJson; +} + +char *votesRespond2Str(SVotesRespond *pVotesRespond) { + cJSON *pJson = votesRespond2Json(pVotesRespond); + char * serialized = cJSON_Print(pJson); + cJSON_Delete(pJson); + return serialized; +} + +// for debug ------------------- +void votesRespondPrint(SVotesRespond *pObj) { + char *serialized = votesRespond2Str(pObj); + printf("votesRespondPrint | len:%lu | %s \n", strlen(serialized), serialized); + fflush(NULL); + free(serialized); +} + +void votesRespondPrint2(char *s, SVotesRespond *pObj) { + char *serialized = votesRespond2Str(pObj); + printf("votesRespondPrint2 | len:%lu | %s | %s \n", strlen(serialized), s, serialized); + fflush(NULL); + free(serialized); +} + +void votesRespondLog(SVotesRespond *pObj) { + char *serialized = votesRespond2Str(pObj); + sTrace("votesRespondLog | len:%lu | %s", strlen(serialized), serialized); + free(serialized); +} + +void votesRespondLog2(char *s, SVotesRespond *pObj) { + char *serialized = votesRespond2Str(pObj); + sTrace("votesRespondLog2 | len:%lu | %s | %s", strlen(serialized), s, serialized); + free(serialized); } \ No newline at end of file diff --git a/source/libs/sync/test/CMakeLists.txt b/source/libs/sync/test/CMakeLists.txt index 770d1d1bd81309784a456655517954bec975b93a..6ade78936d2e67b426acb0a8981c7a4283076456 100644 --- a/source/libs/sync/test/CMakeLists.txt +++ b/source/libs/sync/test/CMakeLists.txt @@ -1,15 +1,30 @@ add_executable(syncTest "") add_executable(syncEnvTest "") -add_executable(syncPingTest "") -add_executable(syncEncodeTest "") +add_executable(syncPingTimerTest "") add_executable(syncIOTickQTest "") add_executable(syncIOTickPingTest "") add_executable(syncIOSendMsgTest "") -add_executable(syncIOSendMsgClientTest "") -add_executable(syncIOSendMsgServerTest "") +add_executable(syncIOClientTest "") +add_executable(syncIOServerTest "") add_executable(syncRaftStoreTest "") add_executable(syncEnqTest "") add_executable(syncIndexTest "") +add_executable(syncInitTest "") +add_executable(syncUtilTest "") +add_executable(syncVotesGrantedTest "") +add_executable(syncVotesRespondTest "") +add_executable(syncIndexMgrTest "") +add_executable(syncLogStoreTest "") +add_executable(syncEntryTest "") +add_executable(syncRequestVoteTest "") +add_executable(syncRequestVoteReplyTest "") +add_executable(syncAppendEntriesTest "") +add_executable(syncAppendEntriesReplyTest "") +add_executable(syncClientRequestTest "") +add_executable(syncTimeoutTest "") +add_executable(syncPingTest "") +add_executable(syncPingReplyTest "") +add_executable(syncRpcMsgTest "") target_sources(syncTest @@ -20,13 +35,9 @@ target_sources(syncEnvTest PRIVATE "syncEnvTest.cpp" ) -target_sources(syncPingTest - PRIVATE - "syncPingTest.cpp" -) -target_sources(syncEncodeTest +target_sources(syncPingTimerTest PRIVATE - "syncEncodeTest.cpp" + "syncPingTimerTest.cpp" ) target_sources(syncIOTickQTest PRIVATE @@ -40,13 +51,13 @@ target_sources(syncIOSendMsgTest PRIVATE "syncIOSendMsgTest.cpp" ) -target_sources(syncIOSendMsgClientTest +target_sources(syncIOClientTest PRIVATE - "syncIOSendMsgClientTest.cpp" + "syncIOClientTest.cpp" ) -target_sources(syncIOSendMsgServerTest +target_sources(syncIOServerTest PRIVATE - "syncIOSendMsgServerTest.cpp" + "syncIOServerTest.cpp" ) target_sources(syncRaftStoreTest PRIVATE @@ -60,6 +71,70 @@ target_sources(syncIndexTest PRIVATE "syncIndexTest.cpp" ) +target_sources(syncInitTest + PRIVATE + "syncInitTest.cpp" +) +target_sources(syncUtilTest + PRIVATE + "syncUtilTest.cpp" +) +target_sources(syncVotesGrantedTest + PRIVATE + "syncVotesGrantedTest.cpp" +) +target_sources(syncVotesRespondTest + PRIVATE + "syncVotesRespondTest.cpp" +) +target_sources(syncIndexMgrTest + PRIVATE + "syncIndexMgrTest.cpp" +) +target_sources(syncLogStoreTest + PRIVATE + "syncLogStoreTest.cpp" +) +target_sources(syncEntryTest + PRIVATE + "syncEntryTest.cpp" +) +target_sources(syncRequestVoteTest + PRIVATE + "syncRequestVoteTest.cpp" +) +target_sources(syncRequestVoteReplyTest + PRIVATE + "syncRequestVoteReplyTest.cpp" +) +target_sources(syncAppendEntriesTest + PRIVATE + "syncAppendEntriesTest.cpp" +) +target_sources(syncAppendEntriesReplyTest + PRIVATE + "syncAppendEntriesReplyTest.cpp" +) +target_sources(syncClientRequestTest + PRIVATE + "syncClientRequestTest.cpp" +) +target_sources(syncTimeoutTest + PRIVATE + "syncTimeoutTest.cpp" +) +target_sources(syncPingTest + PRIVATE + "syncPingTest.cpp" +) +target_sources(syncPingReplyTest + PRIVATE + "syncPingReplyTest.cpp" +) +target_sources(syncRpcMsgTest + PRIVATE + "syncRpcMsgTest.cpp" +) target_include_directories(syncTest @@ -72,12 +147,7 @@ target_include_directories(syncEnvTest "${CMAKE_SOURCE_DIR}/include/libs/sync" "${CMAKE_CURRENT_SOURCE_DIR}/../inc" ) -target_include_directories(syncPingTest - PUBLIC - "${CMAKE_SOURCE_DIR}/include/libs/sync" - "${CMAKE_CURRENT_SOURCE_DIR}/../inc" -) -target_include_directories(syncEncodeTest +target_include_directories(syncPingTimerTest PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/sync" "${CMAKE_CURRENT_SOURCE_DIR}/../inc" @@ -97,12 +167,12 @@ target_include_directories(syncIOSendMsgTest "${CMAKE_SOURCE_DIR}/include/libs/sync" "${CMAKE_CURRENT_SOURCE_DIR}/../inc" ) -target_include_directories(syncIOSendMsgClientTest +target_include_directories(syncIOClientTest PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/sync" "${CMAKE_CURRENT_SOURCE_DIR}/../inc" ) -target_include_directories(syncIOSendMsgServerTest +target_include_directories(syncIOServerTest PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/sync" "${CMAKE_CURRENT_SOURCE_DIR}/../inc" @@ -122,6 +192,86 @@ target_include_directories(syncIndexTest "${CMAKE_SOURCE_DIR}/include/libs/sync" "${CMAKE_CURRENT_SOURCE_DIR}/../inc" ) +target_include_directories(syncInitTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncUtilTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncVotesGrantedTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncVotesRespondTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncIndexMgrTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncLogStoreTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncEntryTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncRequestVoteTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncRequestVoteReplyTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncAppendEntriesTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncAppendEntriesReplyTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncClientRequestTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncTimeoutTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncPingTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncPingReplyTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) +target_include_directories(syncRpcMsgTest + PUBLIC + "${CMAKE_SOURCE_DIR}/include/libs/sync" + "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) target_link_libraries(syncTest @@ -132,11 +282,7 @@ target_link_libraries(syncEnvTest sync gtest_main ) -target_link_libraries(syncPingTest - sync - gtest_main -) -target_link_libraries(syncEncodeTest +target_link_libraries(syncPingTimerTest sync gtest_main ) @@ -152,11 +298,11 @@ target_link_libraries(syncIOSendMsgTest sync gtest_main ) -target_link_libraries(syncIOSendMsgClientTest +target_link_libraries(syncIOClientTest sync gtest_main ) -target_link_libraries(syncIOSendMsgServerTest +target_link_libraries(syncIOServerTest sync gtest_main ) @@ -172,6 +318,70 @@ target_link_libraries(syncIndexTest sync gtest_main ) +target_link_libraries(syncInitTest + sync + gtest_main +) +target_link_libraries(syncUtilTest + sync + gtest_main +) +target_link_libraries(syncVotesGrantedTest + sync + gtest_main +) +target_link_libraries(syncVotesRespondTest + sync + gtest_main +) +target_link_libraries(syncIndexMgrTest + sync + gtest_main +) +target_link_libraries(syncLogStoreTest + sync + gtest_main +) +target_link_libraries(syncEntryTest + sync + gtest_main +) +target_link_libraries(syncRequestVoteTest + sync + gtest_main +) +target_link_libraries(syncRequestVoteReplyTest + sync + gtest_main +) +target_link_libraries(syncAppendEntriesTest + sync + gtest_main +) +target_link_libraries(syncAppendEntriesReplyTest + sync + gtest_main +) +target_link_libraries(syncClientRequestTest + sync + gtest_main +) +target_link_libraries(syncTimeoutTest + sync + gtest_main +) +target_link_libraries(syncPingTest + sync + gtest_main +) +target_link_libraries(syncPingReplyTest + sync + gtest_main +) +target_link_libraries(syncRpcMsgTest + sync + gtest_main +) enable_testing() @@ -179,3 +389,5 @@ add_test( NAME sync_test COMMAND syncTest ) + + diff --git a/source/libs/sync/test/syncAppendEntriesReplyTest.cpp b/source/libs/sync/test/syncAppendEntriesReplyTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..362da67c66869a85a06b6d34398ffd5f30d0f165 --- /dev/null +++ b/source/libs/sync/test/syncAppendEntriesReplyTest.cpp @@ -0,0 +1,100 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +SyncAppendEntriesReply *createMsg() { + SyncAppendEntriesReply *pMsg = syncAppendEntriesReplyBuild(); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->success = true; + pMsg->matchIndex = 77; + return pMsg; +} + +void test1() { + SyncAppendEntriesReply *pMsg = createMsg(); + syncAppendEntriesReplyPrint2((char *)"test1:", pMsg); + syncAppendEntriesReplyDestroy(pMsg); +} + +void test2() { + SyncAppendEntriesReply *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncAppendEntriesReplySerialize(pMsg, serialized, len); + SyncAppendEntriesReply *pMsg2 = syncAppendEntriesReplyBuild(); + syncAppendEntriesReplyDeserialize(serialized, len, pMsg2); + syncAppendEntriesReplyPrint2((char *)"test2: syncAppendEntriesReplySerialize -> syncAppendEntriesReplyDeserialize ", + pMsg2); + + free(serialized); + syncAppendEntriesReplyDestroy(pMsg); + syncAppendEntriesReplyDestroy(pMsg2); +} + +void test3() { + SyncAppendEntriesReply *pMsg = createMsg(); + uint32_t len; + char * serialized = syncAppendEntriesReplySerialize2(pMsg, &len); + SyncAppendEntriesReply *pMsg2 = syncAppendEntriesReplyDeserialize2(serialized, len); + syncAppendEntriesReplyPrint2((char *)"test3: syncAppendEntriesReplySerialize3 -> syncAppendEntriesReplyDeserialize2 ", + pMsg2); + + free(serialized); + syncAppendEntriesReplyDestroy(pMsg); + syncAppendEntriesReplyDestroy(pMsg2); +} + +void test4() { + SyncAppendEntriesReply *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncAppendEntriesReply2RpcMsg(pMsg, &rpcMsg); + SyncAppendEntriesReply *pMsg2 = syncAppendEntriesReplyBuild(); + syncAppendEntriesReplyFromRpcMsg(&rpcMsg, pMsg2); + syncAppendEntriesReplyPrint2((char *)"test4: syncAppendEntriesReply2RpcMsg -> syncAppendEntriesReplyFromRpcMsg ", + pMsg2); + + syncAppendEntriesReplyDestroy(pMsg); + syncAppendEntriesReplyDestroy(pMsg2); +} + +void test5() { + SyncAppendEntriesReply *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncAppendEntriesReply2RpcMsg(pMsg, &rpcMsg); + SyncAppendEntriesReply *pMsg2 = syncAppendEntriesReplyFromRpcMsg2(&rpcMsg); + syncAppendEntriesReplyPrint2((char *)"test5: syncAppendEntriesReply2RpcMsg -> syncAppendEntriesReplyFromRpcMsg2 ", + pMsg2); + + syncAppendEntriesReplyDestroy(pMsg); + syncAppendEntriesReplyDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncAppendEntriesTest.cpp b/source/libs/sync/test/syncAppendEntriesTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..687d9bcb945dbbcddcf0d543f67ea578c5bc4617 --- /dev/null +++ b/source/libs/sync/test/syncAppendEntriesTest.cpp @@ -0,0 +1,98 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +SyncAppendEntries *createMsg() { + SyncAppendEntries *pMsg = syncAppendEntriesBuild(20); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->prevLogIndex = 11; + pMsg->prevLogTerm = 22; + pMsg->commitIndex = 33; + strcpy(pMsg->data, "hello world"); + return pMsg; +} + +void test1() { + SyncAppendEntries *pMsg = createMsg(); + syncAppendEntriesPrint2((char *)"test1:", pMsg); + syncAppendEntriesDestroy(pMsg); +} + +void test2() { + SyncAppendEntries *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncAppendEntriesSerialize(pMsg, serialized, len); + SyncAppendEntries *pMsg2 = syncAppendEntriesBuild(pMsg->dataLen); + syncAppendEntriesDeserialize(serialized, len, pMsg2); + syncAppendEntriesPrint2((char *)"test2: syncAppendEntriesSerialize -> syncAppendEntriesDeserialize ", pMsg2); + + free(serialized); + syncAppendEntriesDestroy(pMsg); + syncAppendEntriesDestroy(pMsg2); +} + +void test3() { + SyncAppendEntries *pMsg = createMsg(); + uint32_t len; + char * serialized = syncAppendEntriesSerialize2(pMsg, &len); + SyncAppendEntries *pMsg2 = syncAppendEntriesDeserialize2(serialized, len); + syncAppendEntriesPrint2((char *)"test3: syncAppendEntriesSerialize3 -> syncAppendEntriesDeserialize2 ", pMsg2); + + free(serialized); + syncAppendEntriesDestroy(pMsg); + syncAppendEntriesDestroy(pMsg2); +} + +void test4() { + SyncAppendEntries *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncAppendEntries2RpcMsg(pMsg, &rpcMsg); + SyncAppendEntries *pMsg2 = (SyncAppendEntries *)malloc(rpcMsg.contLen); + syncAppendEntriesFromRpcMsg(&rpcMsg, pMsg2); + syncAppendEntriesPrint2((char *)"test4: syncAppendEntries2RpcMsg -> syncAppendEntriesFromRpcMsg ", pMsg2); + + syncAppendEntriesDestroy(pMsg); + syncAppendEntriesDestroy(pMsg2); +} + +void test5() { + SyncAppendEntries *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncAppendEntries2RpcMsg(pMsg, &rpcMsg); + SyncAppendEntries *pMsg2 = syncAppendEntriesFromRpcMsg2(&rpcMsg); + syncAppendEntriesPrint2((char *)"test5: syncAppendEntries2RpcMsg -> syncAppendEntriesFromRpcMsg2 ", pMsg2); + + syncAppendEntriesDestroy(pMsg); + syncAppendEntriesDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncClientRequestTest.cpp b/source/libs/sync/test/syncClientRequestTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6323f53a0354897e5b2f6525573e4eeade592014 --- /dev/null +++ b/source/libs/sync/test/syncClientRequestTest.cpp @@ -0,0 +1,96 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +SyncClientRequest *createMsg() { + SRpcMsg rpcMsg; + memset(&rpcMsg, 0, sizeof(rpcMsg)); + rpcMsg.msgType = 12345; + rpcMsg.contLen = 20; + rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen); + strcpy((char *)rpcMsg.pCont, "hello rpc"); + SyncClientRequest *pMsg = syncClientRequestBuild2(&rpcMsg, 123, true); + return pMsg; +} + +void test1() { + SyncClientRequest *pMsg = createMsg(); + syncClientRequestPrint2((char *)"test1:", pMsg); + syncClientRequestDestroy(pMsg); +} + +void test2() { + SyncClientRequest *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncClientRequestSerialize(pMsg, serialized, len); + SyncClientRequest *pMsg2 = syncClientRequestBuild(pMsg->dataLen); + syncClientRequestDeserialize(serialized, len, pMsg2); + syncClientRequestPrint2((char *)"test2: syncClientRequestSerialize -> syncClientRequestDeserialize ", pMsg2); + + free(serialized); + syncClientRequestDestroy(pMsg); + syncClientRequestDestroy(pMsg2); +} + +void test3() { + SyncClientRequest *pMsg = createMsg(); + uint32_t len; + char * serialized = syncClientRequestSerialize2(pMsg, &len); + SyncClientRequest *pMsg2 = syncClientRequestDeserialize2(serialized, len); + syncClientRequestPrint2((char *)"test3: syncClientRequestSerialize3 -> syncClientRequestDeserialize2 ", pMsg2); + + free(serialized); + syncClientRequestDestroy(pMsg); + syncClientRequestDestroy(pMsg2); +} + +void test4() { + SyncClientRequest *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncClientRequest2RpcMsg(pMsg, &rpcMsg); + SyncClientRequest *pMsg2 = (SyncClientRequest *)malloc(rpcMsg.contLen); + syncClientRequestFromRpcMsg(&rpcMsg, pMsg2); + syncClientRequestPrint2((char *)"test4: syncClientRequest2RpcMsg -> syncClientRequestFromRpcMsg ", pMsg2); + + syncClientRequestDestroy(pMsg); + syncClientRequestDestroy(pMsg2); +} + +void test5() { + SyncClientRequest *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncClientRequest2RpcMsg(pMsg, &rpcMsg); + SyncClientRequest *pMsg2 = syncClientRequestFromRpcMsg2(&rpcMsg); + syncClientRequestPrint2((char *)"test5: syncClientRequest2RpcMsg -> syncClientRequestFromRpcMsg2 ", pMsg2); + + syncClientRequestDestroy(pMsg); + syncClientRequestDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncEncodeTest.cpp b/source/libs/sync/test/syncEncodeTest.cpp deleted file mode 100644 index 61976210519ad52b0eb8bc8365b009c00b9fec80..0000000000000000000000000000000000000000 --- a/source/libs/sync/test/syncEncodeTest.cpp +++ /dev/null @@ -1,509 +0,0 @@ -#include -#include "syncEnv.h" -#include "syncIO.h" -#include "syncInt.h" -#include "syncMessage.h" -#include "syncUtil.h" - -void logTest() { - sTrace("--- sync log test: trace"); - sDebug("--- sync log test: debug"); - sInfo("--- sync log test: info"); - sWarn("--- sync log test: warn"); - sError("--- sync log test: error"); - sFatal("--- sync log test: fatal"); -} - -#define PING_MSG_LEN 20 -#define APPEND_ENTRIES_VALUE_LEN 32 - -void test1() { - sTrace("test1: ---- syncPingSerialize, syncPingDeserialize"); - - char msg[PING_MSG_LEN]; - snprintf(msg, sizeof(msg), "%s", "test ping"); - SyncPing* pMsg = syncPingBuild(PING_MSG_LEN); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1111); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 2222); - pMsg->destId.vgId = 100; - memcpy(pMsg->data, msg, PING_MSG_LEN); - - { - cJSON* pJson = syncPing2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - uint32_t bufLen = pMsg->bytes; - char* buf = (char*)malloc(bufLen); - syncPingSerialize(pMsg, buf, bufLen); - - SyncPing* pMsg2 = (SyncPing*)malloc(pMsg->bytes); - syncPingDeserialize(buf, bufLen, pMsg2); - - { - cJSON* pJson = syncPing2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncPingDestroy(pMsg); - syncPingDestroy(pMsg2); - free(buf); -} - -void test2() { - sTrace("test2: ---- syncPing2RpcMsg, syncPingFromRpcMsg"); - - char msg[PING_MSG_LEN]; - snprintf(msg, sizeof(msg), "%s", "hello raft"); - SyncPing* pMsg = syncPingBuild(PING_MSG_LEN); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 3333); - pMsg->srcId.vgId = 200; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 4444); - pMsg->destId.vgId = 200; - memcpy(pMsg->data, msg, PING_MSG_LEN); - - { - cJSON* pJson = syncPing2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SRpcMsg rpcMsg; - syncPing2RpcMsg(pMsg, &rpcMsg); - SyncPing* pMsg2 = (SyncPing*)malloc(pMsg->bytes); - syncPingFromRpcMsg(&rpcMsg, pMsg2); - rpcFreeCont(rpcMsg.pCont); - - { - cJSON* pJson = syncPing2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncPingDestroy(pMsg); - syncPingDestroy(pMsg2); -} - -void test3() { - sTrace("test3: ---- syncPingReplySerialize, syncPingReplyDeserialize"); - - char msg[PING_MSG_LEN]; - snprintf(msg, sizeof(msg), "%s", "test ping"); - SyncPingReply* pMsg = syncPingReplyBuild(PING_MSG_LEN); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 5555); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 6666); - pMsg->destId.vgId = 100; - memcpy(pMsg->data, msg, PING_MSG_LEN); - - { - cJSON* pJson = syncPingReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - uint32_t bufLen = pMsg->bytes; - char* buf = (char*)malloc(bufLen); - syncPingReplySerialize(pMsg, buf, bufLen); - - SyncPingReply* pMsg2 = (SyncPingReply*)malloc(pMsg->bytes); - syncPingReplyDeserialize(buf, bufLen, pMsg2); - - { - cJSON* pJson = syncPingReply2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncPingReplyDestroy(pMsg); - syncPingReplyDestroy(pMsg2); - free(buf); -} - -void test4() { - sTrace("test4: ---- syncPingReply2RpcMsg, syncPingReplyFromRpcMsg"); - - char msg[PING_MSG_LEN]; - snprintf(msg, sizeof(msg), "%s", "hello raft"); - SyncPingReply* pMsg = syncPingReplyBuild(PING_MSG_LEN); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 7777); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 8888); - pMsg->destId.vgId = 100; - memcpy(pMsg->data, msg, PING_MSG_LEN); - - { - cJSON* pJson = syncPingReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SRpcMsg rpcMsg; - syncPingReply2RpcMsg(pMsg, &rpcMsg); - SyncPingReply* pMsg2 = (SyncPingReply*)malloc(pMsg->bytes); - syncPingReplyFromRpcMsg(&rpcMsg, pMsg2); - rpcFreeCont(rpcMsg.pCont); - - { - cJSON* pJson = syncPingReply2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncPingReplyDestroy(pMsg); - syncPingReplyDestroy(pMsg2); -} - -void test5() { - sTrace("test5: ---- syncRequestVoteSerialize, syncRequestVoteDeserialize"); - - SyncRequestVote* pMsg = syncRequestVoteBuild(); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("8.8.8.8", 5678); - pMsg->destId.vgId = 100; - pMsg->currentTerm = 20; - pMsg->lastLogIndex = 21; - pMsg->lastLogTerm = 22; - - { - cJSON* pJson = syncRequestVote2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - uint32_t bufLen = pMsg->bytes; - char* buf = (char*)malloc(bufLen); - syncRequestVoteSerialize(pMsg, buf, bufLen); - - SyncRequestVote* pMsg2 = (SyncRequestVote*)malloc(pMsg->bytes); - syncRequestVoteDeserialize(buf, bufLen, pMsg2); - - { - cJSON* pJson = syncRequestVote2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncRequestVoteDestroy(pMsg); - syncRequestVoteDestroy(pMsg2); - free(buf); -} - -void test6() { - sTrace("test6: ---- syncRequestVote2RpcMsg, syncRequestVoteFromRpcMsg"); - - SyncRequestVote* pMsg = syncRequestVoteBuild(); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("8.8.8.8", 5678); - pMsg->destId.vgId = 100; - pMsg->currentTerm = 20; - pMsg->lastLogIndex = 21; - pMsg->lastLogTerm = 22; - - { - cJSON* pJson = syncRequestVote2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SRpcMsg rpcMsg; - syncRequestVote2RpcMsg(pMsg, &rpcMsg); - SyncRequestVote* pMsg2 = (SyncRequestVote*)malloc(pMsg->bytes); - syncRequestVoteFromRpcMsg(&rpcMsg, pMsg2); - rpcFreeCont(rpcMsg.pCont); - - { - cJSON* pJson = syncRequestVote2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncRequestVoteDestroy(pMsg); - syncRequestVoteDestroy(pMsg2); -} - -void test7() { - sTrace("test7: ---- syncRequestVoteReplySerialize, syncRequestVoteReplyDeserialize"); - - SyncRequestVoteReply* pMsg = SyncRequestVoteReplyBuild(); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("8.8.8.8", 5678); - pMsg->destId.vgId = 100; - pMsg->term = 20; - pMsg->voteGranted = 1; - - { - cJSON* pJson = syncRequestVoteReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - uint32_t bufLen = pMsg->bytes; - char* buf = (char*)malloc(bufLen); - syncRequestVoteReplySerialize(pMsg, buf, bufLen); - - SyncRequestVoteReply* pMsg2 = (SyncRequestVoteReply*)malloc(pMsg->bytes); - syncRequestVoteReplyDeserialize(buf, bufLen, pMsg2); - - { - cJSON* pJson = syncRequestVoteReply2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncRequestVoteReplyDestroy(pMsg); - syncRequestVoteReplyDestroy(pMsg2); - free(buf); -} - -void test8() { - sTrace("test8: ---- syncRequestVoteReply2RpcMsg, syncRequestVoteReplyFromRpcMsg"); - - SyncRequestVoteReply* pMsg = SyncRequestVoteReplyBuild(); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("8.8.8.8", 5678); - pMsg->destId.vgId = 100; - pMsg->term = 20; - pMsg->voteGranted = 1; - - { - cJSON* pJson = syncRequestVoteReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SRpcMsg rpcMsg; - syncRequestVoteReply2RpcMsg(pMsg, &rpcMsg); - SyncRequestVoteReply* pMsg2 = (SyncRequestVoteReply*)malloc(pMsg->bytes); - syncRequestVoteReplyFromRpcMsg(&rpcMsg, pMsg2); - rpcFreeCont(rpcMsg.pCont); - - { - cJSON* pJson = syncRequestVoteReply2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncRequestVoteReplyDestroy(pMsg); - syncRequestVoteReplyDestroy(pMsg2); -} - -void test9() { - sTrace("test9: ---- syncAppendEntriesSerialize, syncAppendEntriesDeserialize"); - - char msg[APPEND_ENTRIES_VALUE_LEN]; - snprintf(msg, sizeof(msg), "%s", "test value"); - SyncAppendEntries* pMsg = syncAppendEntriesBuild(APPEND_ENTRIES_VALUE_LEN); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1111); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 2222); - pMsg->destId.vgId = 100; - pMsg->prevLogIndex = 55; - pMsg->prevLogTerm = 66; - pMsg->commitIndex = 77; - memcpy(pMsg->data, msg, APPEND_ENTRIES_VALUE_LEN); - - { - cJSON* pJson = syncAppendEntries2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - uint32_t bufLen = pMsg->bytes; - char* buf = (char*)malloc(bufLen); - syncAppendEntriesSerialize(pMsg, buf, bufLen); - - SyncAppendEntries* pMsg2 = (SyncAppendEntries*)malloc(pMsg->bytes); - syncAppendEntriesDeserialize(buf, bufLen, pMsg2); - - { - cJSON* pJson = syncAppendEntries2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncAppendEntriesDestroy(pMsg); - syncAppendEntriesDestroy(pMsg2); - free(buf); -} - -void test10() { - sTrace("test10: ---- syncAppendEntries2RpcMsg, syncAppendEntriesFromRpcMsg"); - - char msg[APPEND_ENTRIES_VALUE_LEN]; - snprintf(msg, sizeof(msg), "%s", "test value"); - SyncAppendEntries* pMsg = syncAppendEntriesBuild(APPEND_ENTRIES_VALUE_LEN); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1111); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 2222); - pMsg->destId.vgId = 100; - pMsg->prevLogIndex = 55; - pMsg->prevLogTerm = 66; - pMsg->commitIndex = 77; - memcpy(pMsg->data, msg, APPEND_ENTRIES_VALUE_LEN); - - { - cJSON* pJson = syncAppendEntries2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SRpcMsg rpcMsg; - syncAppendEntries2RpcMsg(pMsg, &rpcMsg); - SyncAppendEntries* pMsg2 = (SyncAppendEntries*)malloc(pMsg->bytes); - syncAppendEntriesFromRpcMsg(&rpcMsg, pMsg2); - rpcFreeCont(rpcMsg.pCont); - - { - cJSON* pJson = syncAppendEntries2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncAppendEntriesDestroy(pMsg); - syncAppendEntriesDestroy(pMsg2); -} - -void test11() { - sTrace("test11: ---- syncAppendEntriesReplySerialize, syncAppendEntriesReplyDeserialize"); - - SyncAppendEntriesReply* pMsg = syncAppendEntriesReplyBuild(); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1111); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 2222); - pMsg->destId.vgId = 100; - pMsg->success = 1; - pMsg->matchIndex = 23; - - { - cJSON* pJson = syncAppendEntriesReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - uint32_t bufLen = pMsg->bytes; - char* buf = (char*)malloc(bufLen); - syncAppendEntriesReplySerialize(pMsg, buf, bufLen); - - SyncAppendEntriesReply* pMsg2 = (SyncAppendEntriesReply*)malloc(pMsg->bytes); - syncAppendEntriesReplyDeserialize(buf, bufLen, pMsg2); - - { - cJSON* pJson = syncAppendEntriesReply2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncAppendEntriesReplyDestroy(pMsg); - syncAppendEntriesReplyDestroy(pMsg2); - free(buf); -} - -void test12() { - sTrace("test12: ---- syncAppendEntriesReply2RpcMsg, syncAppendEntriesReplyFromRpcMsg"); - - SyncAppendEntriesReply* pMsg = syncAppendEntriesReplyBuild(); - pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1111); - pMsg->srcId.vgId = 100; - pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 2222); - pMsg->destId.vgId = 100; - pMsg->success = 1; - pMsg->matchIndex = 23; - - { - cJSON* pJson = syncAppendEntriesReply2Json(pMsg); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - SRpcMsg rpcMsg; - syncAppendEntriesReply2RpcMsg(pMsg, &rpcMsg); - SyncAppendEntriesReply* pMsg2 = (SyncAppendEntriesReply*)malloc(pMsg->bytes); - syncAppendEntriesReplyFromRpcMsg(&rpcMsg, pMsg2); - rpcFreeCont(rpcMsg.pCont); - - { - cJSON* pJson = syncAppendEntriesReply2Json(pMsg2); - char* serialized = cJSON_Print(pJson); - printf("\n%s\n\n", serialized); - free(serialized); - cJSON_Delete(pJson); - } - - syncAppendEntriesReplyDestroy(pMsg); - syncAppendEntriesReplyDestroy(pMsg2); -} - -int main() { - // taosInitLog((char*)"syncPingTest.log", 100000, 10); - tsAsyncLog = 0; - sDebugFlag = 143 + 64; - - test1(); - test2(); - test3(); - test4(); - test5(); - test6(); - test7(); - test8(); - test9(); - test10(); - test11(); - test12(); - - return 0; -} diff --git a/source/libs/sync/test/syncEnqTest.cpp b/source/libs/sync/test/syncEnqTest.cpp index 0bf43f933ee85610b6280c88f6120c2e8677e221..57315f40ec31a9148727ac1c4a822c267b119b36 100644 --- a/source/libs/sync/test/syncEnqTest.cpp +++ b/source/libs/sync/test/syncEnqTest.cpp @@ -1,8 +1,10 @@ +#include #include #include "syncEnv.h" #include "syncIO.h" #include "syncInt.h" #include "syncRaftStore.h" +#include "syncUtil.h" void logTest() { sTrace("--- sync log test: trace"); @@ -13,64 +15,69 @@ void logTest() { sFatal("--- sync log test: fatal"); } -uint16_t ports[3] = {7010, 7110, 7210}; +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 5; +int32_t myIndex = 0; -SSyncNode* doSync(int myIndex) { - SSyncFSM* pFsm; +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; - SSyncInfo syncInfo; - syncInfo.vgId = 1; +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; syncInfo.rpcClient = gSyncIO->clientRpc; syncInfo.FpSendMsg = syncIOSendMsg; syncInfo.queue = gSyncIO->pMsgQ; syncInfo.FpEqMsg = syncIOEqMsg; syncInfo.pFsm = pFsm; - snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./test_sync_ping"); + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); SSyncCfg* pCfg = &syncInfo.syncCfg; pCfg->myIndex = myIndex; - pCfg->replicaNum = 3; + pCfg->replicaNum = replicaNum; - pCfg->nodeInfo[0].nodePort = ports[0]; - snprintf(pCfg->nodeInfo[0].nodeFqdn, sizeof(pCfg->nodeInfo[0].nodeFqdn), "%s", "127.0.0.1"); - // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); - - pCfg->nodeInfo[1].nodePort = ports[1]; - snprintf(pCfg->nodeInfo[1].nodeFqdn, sizeof(pCfg->nodeInfo[1].nodeFqdn), "%s", "127.0.0.1"); - // taosGetFqdn(pCfg->nodeInfo[1].nodeFqdn); - - pCfg->nodeInfo[2].nodePort = ports[2]; - snprintf(pCfg->nodeInfo[2].nodeFqdn, sizeof(pCfg->nodeInfo[2].nodeFqdn), "%s", "127.0.0.1"); - // taosGetFqdn(pCfg->nodeInfo[2].nodeFqdn); + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } SSyncNode* pSyncNode = syncNodeOpen(&syncInfo); assert(pSyncNode != NULL); gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncTimeout = pSyncNode->FpOnTimeout; gSyncIO->pSyncNode = pSyncNode; return pSyncNode; } -void timerPingAll(void* param, void* tmrId) { - SSyncNode* pSyncNode = (SSyncNode*)param; - syncNodePingAll(pSyncNode); +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } } int main(int argc, char** argv) { - // taosInitLog((char*)"syncPingTest.log", 100000, 10); + // taosInitLog((char *)"syncTest.log", 100000, 10); tsAsyncLog = 0; sDebugFlag = 143 + 64; - logTest(); - - int myIndex = 0; + myIndex = 0; if (argc >= 2) { myIndex = atoi(argv[1]); - if (myIndex > 2 || myIndex < 0) { - fprintf(stderr, "myIndex:%d error. should be 0 - 2", myIndex); - return 1; - } } int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); @@ -79,21 +86,22 @@ int main(int argc, char** argv) { ret = syncEnvStart(); assert(ret == 0); - SSyncNode* pSyncNode = doSync(myIndex); - gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; - gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + syncNodePrint2((char*)"syncInitTest", pSyncNode); + + initRaftId(pSyncNode); + + //-------------------------------------------------------------- for (int i = 0; i < 10; ++i) { - SyncPingReply* pSyncMsg = syncPingReplyBuild3(&pSyncNode->raftId, &pSyncNode->raftId); + SyncPingReply* pSyncMsg = syncPingReplyBuild2(&pSyncNode->myRaftId, &pSyncNode->myRaftId, "syncEnqTest"); SRpcMsg rpcMsg; syncPingReply2RpcMsg(pSyncMsg, &rpcMsg); pSyncNode->FpEqMsg(pSyncNode->queue, &rpcMsg); taosMsleep(1000); } - while (1) { - taosMsleep(1000); - } - return 0; } diff --git a/source/libs/sync/test/syncEntryTest.cpp b/source/libs/sync/test/syncEntryTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e54daaa79a052504fd8cb8bbbb7f59baec9e6385 --- /dev/null +++ b/source/libs/sync/test/syncEntryTest.cpp @@ -0,0 +1,81 @@ +#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftLog.h" +#include "syncRaftStore.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +void test1() { + SSyncRaftEntry* pEntry = syncEntryBuild(10); + assert(pEntry != NULL); + pEntry->msgType = 1; + pEntry->originalRpcType = 2; + pEntry->seqNum = 3; + pEntry->isWeak = true; + pEntry->term = 100; + pEntry->index = 200; + strcpy(pEntry->data, "test1"); + + syncEntryPrint(pEntry); + syncEntryDestory(pEntry); +} + +void test2() { + SyncClientRequest* pSyncMsg = syncClientRequestBuild(10); + pSyncMsg->originalRpcType = 33; + pSyncMsg->seqNum = 11; + pSyncMsg->isWeak = 1; + strcpy(pSyncMsg->data, "test2"); + + SSyncRaftEntry* pEntry = syncEntryBuild2(pSyncMsg, 100, 200); + syncEntryPrint(pEntry); + + syncClientRequestDestroy(pSyncMsg); + syncEntryDestory(pEntry); +} + +void test3() { + SSyncRaftEntry* pEntry = syncEntryBuild(10); + assert(pEntry != NULL); + pEntry->msgType = 11; + pEntry->originalRpcType = 22; + pEntry->seqNum = 33; + pEntry->isWeak = true; + pEntry->term = 44; + pEntry->index = 55; + strcpy(pEntry->data, "test3"); + syncEntryPrint(pEntry); + + uint32_t len; + char* serialized = syncEntrySerialize(pEntry, &len); + assert(serialized != NULL); + SSyncRaftEntry* pEntry2 = syncEntryDeserialize(serialized, len); + syncEntryPrint(pEntry2); + + free(serialized); + syncEntryDestory(pEntry2); + syncEntryDestory(pEntry); +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + test1(); + test2(); + test3(); + + return 0; +} diff --git a/source/libs/sync/test/syncEnvTest.cpp b/source/libs/sync/test/syncEnvTest.cpp index 1ac4357c5a99c8c0a478353ba9e018b1de3b738e..a7a819e0465b34de466c132934bc2b4c209b2fd1 100644 --- a/source/libs/sync/test/syncEnvTest.cpp +++ b/source/libs/sync/test/syncEnvTest.cpp @@ -3,6 +3,7 @@ #include "syncIO.h" #include "syncInt.h" #include "syncRaftStore.h" +#include "ttime.h" void logTest() { sTrace("--- sync log test: trace"); @@ -13,26 +14,6 @@ void logTest() { sFatal("--- sync log test: fatal"); } -void doSync() { - SSyncInfo syncInfo; - syncInfo.vgId = 1; - - SSyncCfg* pCfg = &syncInfo.syncCfg; - pCfg->replicaNum = 3; - - pCfg->nodeInfo[0].nodePort = 7010; - taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); - - pCfg->nodeInfo[1].nodePort = 7110; - taosGetFqdn(pCfg->nodeInfo[1].nodeFqdn); - - pCfg->nodeInfo[2].nodePort = 7210; - taosGetFqdn(pCfg->nodeInfo[2].nodeFqdn); - - SSyncNode* pSyncNode = syncNodeOpen(&syncInfo); - assert(pSyncNode != NULL); -} - int main() { // taosInitLog((char*)"syncEnvTest.log", 100000, 10); tsAsyncLog = 0; @@ -41,17 +22,23 @@ int main() { logTest(); - // ret = syncIOStart(); - // assert(ret == 0); - ret = syncEnvStart(); assert(ret == 0); - // doSync(); + for (int i = 0; i < 5; ++i) { + ret = syncEnvStartTimer(); + assert(ret == 0); + + taosMsleep(5000); - while (1) { - taosMsleep(1000); + ret = syncEnvStopTimer(); + assert(ret == 0); + + taosMsleep(5000); } + ret = syncEnvStop(); + assert(ret == 0); + return 0; } diff --git a/source/libs/sync/test/syncIOSendMsgClientTest.cpp b/source/libs/sync/test/syncIOClientTest.cpp similarity index 61% rename from source/libs/sync/test/syncIOSendMsgClientTest.cpp rename to source/libs/sync/test/syncIOClientTest.cpp index 83ac7247897f18f248334048a0923af2e9aac1d0..dffa8b5cb9c832b492cbb2e57e2c17b9dcf0af8b 100644 --- a/source/libs/sync/test/syncIOSendMsgClientTest.cpp +++ b/source/libs/sync/test/syncIOClientTest.cpp @@ -2,7 +2,8 @@ #include #include "syncIO.h" #include "syncInt.h" -#include "syncRaftStore.h" +#include "syncMessage.h" +#include "syncUtil.h" void logTest() { sTrace("--- sync log test: trace"); @@ -22,7 +23,7 @@ int main() { int32_t ret; - ret = syncIOStart((char *)"127.0.0.1", 7010); + ret = syncIOStart((char*)"127.0.0.1", 7010); assert(ret == 0); for (int i = 0; i < 10; ++i) { @@ -31,19 +32,18 @@ int main() { epSet.numOfEps = 0; addEpIntoEpSet(&epSet, "127.0.0.1", 7030); - SRpcMsg rpcMsg; - rpcMsg.contLen = 64; - rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen); - snprintf((char *)rpcMsg.pCont, rpcMsg.contLen, "%s", "syncIOSendMsgTest"); - rpcMsg.handle = NULL; - rpcMsg.msgType = 77; + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + srcId.vgId = 100; + destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + destId.vgId = 100; - syncIOSendMsg(gSyncIO->clientRpc, &epSet, &rpcMsg); - sleep(1); - } + SyncPingReply* pSyncMsg = syncPingReplyBuild2(&srcId, &destId, "syncIOClientTest"); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pSyncMsg, &rpcMsg); - while (1) { - sleep(1); + syncIOSendMsg(gSyncIO->clientRpc, &epSet, &rpcMsg); + taosSsleep(1); } return 0; diff --git a/source/libs/sync/test/syncIOSendMsgTest.cpp b/source/libs/sync/test/syncIOSendMsgTest.cpp index c25ad3b1dddef7d41d3e727834ffddc0ca69a6ef..0fc3ebfe4cdc5e4417f34c905c039ac5c31fc707 100644 --- a/source/libs/sync/test/syncIOSendMsgTest.cpp +++ b/source/libs/sync/test/syncIOSendMsgTest.cpp @@ -1,8 +1,10 @@ #include #include +#include "syncEnv.h" #include "syncIO.h" #include "syncInt.h" #include "syncRaftStore.h" +#include "syncUtil.h" void logTest() { sTrace("--- sync log test: trace"); @@ -13,37 +15,96 @@ void logTest() { sFatal("--- sync log test: fatal"); } -int main() { +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 5; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + SSyncNode* pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncTimeout = pSyncNode->FpOnTimeout; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { // taosInitLog((char *)"syncTest.log", 100000, 10); tsAsyncLog = 0; sDebugFlag = 143 + 64; - logTest(); + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } - int32_t ret; + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); - ret = syncIOStart((char *)"127.0.0.1", 7010); + ret = syncEnvStart(); assert(ret == 0); + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + syncNodePrint2((char*)"syncInitTest", pSyncNode); + + initRaftId(pSyncNode); + + //-------------------------------------------------------------- + for (int i = 0; i < 10; ++i) { + SyncPingReply* pSyncMsg = syncPingReplyBuild2(&pSyncNode->myRaftId, &pSyncNode->myRaftId, "syncIOSendMsgTest"); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pSyncMsg, &rpcMsg); + SEpSet epSet; - epSet.inUse = 0; - epSet.numOfEps = 0; - addEpIntoEpSet(&epSet, "127.0.0.1", 7010); - - SRpcMsg rpcMsg; - rpcMsg.contLen = 64; - rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen); - snprintf((char *)rpcMsg.pCont, rpcMsg.contLen, "%s", "syncIOSendMsgTest"); - rpcMsg.handle = NULL; - rpcMsg.msgType = 77; - - syncIOSendMsg(gSyncIO->clientRpc, &epSet, &rpcMsg); - sleep(1); - } + syncUtilnodeInfo2EpSet(&pSyncNode->myNodeInfo, &epSet); + pSyncNode->FpSendMsg(pSyncNode->rpcClient, &epSet, &rpcMsg); - while (1) { - sleep(1); + taosMsleep(1000); } return 0; diff --git a/source/libs/sync/test/syncIOSendMsgServerTest.cpp b/source/libs/sync/test/syncIOServerTest.cpp similarity index 96% rename from source/libs/sync/test/syncIOSendMsgServerTest.cpp rename to source/libs/sync/test/syncIOServerTest.cpp index b0f177962fe7b8c053e221d4efeba095afa7051d..1d7402e461f26ea8c7f00508af7352c6c76ac9c8 100644 --- a/source/libs/sync/test/syncIOSendMsgServerTest.cpp +++ b/source/libs/sync/test/syncIOServerTest.cpp @@ -26,7 +26,7 @@ int main() { assert(ret == 0); while (1) { - sleep(1); + taosSsleep(1); } return 0; diff --git a/source/libs/sync/test/syncIOTickPingTest.cpp b/source/libs/sync/test/syncIOTickPingTest.cpp index 777fc035e212aec5fd8956afa56c3c4b0357bce6..9c2342828edb6e3671566ba6651e942bb6b510a5 100644 --- a/source/libs/sync/test/syncIOTickPingTest.cpp +++ b/source/libs/sync/test/syncIOTickPingTest.cpp @@ -25,11 +25,18 @@ int main() { ret = syncIOStart((char*)"127.0.0.1", 7010); assert(ret == 0); - ret = syncIOTickPing(); - assert(ret == 0); + for (int i = 0; i < 3; ++i) { + ret = syncIOPingTimerStart(); + assert(ret == 0); + taosMsleep(5000); + + ret = syncIOPingTimerStop(); + assert(ret == 0); + taosMsleep(5000); + } while (1) { - sleep(1); + taosSsleep(1); } return 0; } diff --git a/source/libs/sync/test/syncIOTickQTest.cpp b/source/libs/sync/test/syncIOTickQTest.cpp index 5615058cc3fefe119c2da21e32d06e95b0b221d0..64b65f25c8e00971de1e8f824d0d8d3cf5365030 100644 --- a/source/libs/sync/test/syncIOTickQTest.cpp +++ b/source/libs/sync/test/syncIOTickQTest.cpp @@ -25,11 +25,18 @@ int main() { ret = syncIOStart((char*)"127.0.0.1", 7010); assert(ret == 0); - ret = syncIOTickQ(); - assert(ret == 0); + for (int i = 0; i < 3; ++i) { + ret = syncIOQTimerStart(); + assert(ret == 0); + taosMsleep(5000); - while (1) { - sleep(1); + ret = syncIOQTimerStop(); + assert(ret == 0); + taosMsleep(5000); } + + ret = syncIOStop(); + assert(ret == 0); + return 0; } diff --git a/source/libs/sync/test/syncIndexMgrTest.cpp b/source/libs/sync/test/syncIndexMgrTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bad8f09cf3f5912f0ef4ba71316dd3654af91fd --- /dev/null +++ b/source/libs/sync/test/syncIndexMgrTest.cpp @@ -0,0 +1,140 @@ +#include "syncIndexMgr.h" +//#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 3; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; +SSyncNode* pSyncNode; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } + + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); + + ret = syncEnvStart(); + assert(ret == 0); + + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + char* serialized = syncNode2Str(pSyncNode); + printf("%s\n", serialized); + free(serialized); + + initRaftId(pSyncNode); + + SSyncIndexMgr* pSyncIndexMgr = syncIndexMgrCreate(pSyncNode); + assert(pSyncIndexMgr != NULL); + + printf("---------------------------------------\n"); + { + char* serialized = syncIndexMgr2Str(pSyncIndexMgr); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + syncIndexMgrSetIndex(pSyncIndexMgr, &ids[0], 100); + syncIndexMgrSetIndex(pSyncIndexMgr, &ids[1], 200); + syncIndexMgrSetIndex(pSyncIndexMgr, &ids[2], 300); + + printf("---------------------------------------\n"); + { + char* serialized = syncIndexMgr2Str(pSyncIndexMgr); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + printf("---------------------------------------\n"); + for (int i = 0; i < pSyncIndexMgr->replicaNum; ++i) { + SyncIndex idx = syncIndexMgrGetIndex(pSyncIndexMgr, &ids[i]); + printf("index %d : %lu \n", i, idx); + } + + syncIndexMgrClear(pSyncIndexMgr); + printf("---------------------------------------\n"); + { + char* serialized = syncIndexMgr2Str(pSyncIndexMgr); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + syncIndexMgrDestroy(pSyncIndexMgr); + return 0; +} diff --git a/source/libs/sync/test/syncInitTest.cpp b/source/libs/sync/test/syncInitTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7898fda8c068c7b83aa87c0a873e55c5974d8b07 --- /dev/null +++ b/source/libs/sync/test/syncInitTest.cpp @@ -0,0 +1,99 @@ +#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 5; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + SSyncNode* pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncTimeout = pSyncNode->FpOnTimeout; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } + + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); + + ret = syncEnvStart(); + assert(ret == 0); + + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + syncNodePrint2((char*)"syncInitTest", pSyncNode); + + initRaftId(pSyncNode); + + //-------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/source/libs/sync/test/syncLogStoreTest.cpp b/source/libs/sync/test/syncLogStoreTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b05f76fa2971357c923c3c43ff66a9f1ebea759 --- /dev/null +++ b/source/libs/sync/test/syncLogStoreTest.cpp @@ -0,0 +1,150 @@ +#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftLog.h" +#include "syncRaftStore.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 1; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; +SWal* pWal; +SSyncNode* pSyncNode; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + int code = walInit(); + assert(code == 0); + SWalCfg walCfg; + memset(&walCfg, 0, sizeof(SWalCfg)); + walCfg.vgId = syncInfo.vgId; + walCfg.fsyncPeriod = 1000; + walCfg.retentionPeriod = 1000; + walCfg.rollPeriod = 1000; + walCfg.retentionSize = 1000; + walCfg.segSize = 1000; + walCfg.level = TAOS_WAL_FSYNC; + pWal = walOpen("./wal_test", &walCfg); + assert(pWal != NULL); + + syncInfo.pWal = pWal; + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncTimeout = pSyncNode->FpOnTimeout; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void logStoreTest() { + logStorePrint2((char*)"logStoreTest2", pSyncNode->pLogStore); + + assert(pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore) == SYNC_INDEX_INVALID); + + for (int i = 0; i < 5; ++i) { + int32_t dataLen = 10; + SSyncRaftEntry* pEntry = syncEntryBuild(dataLen); + assert(pEntry != NULL); + pEntry->msgType = 1; + pEntry->originalRpcType = 2; + pEntry->seqNum = 3; + pEntry->isWeak = true; + pEntry->term = 100; + pEntry->index = pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore) + 1; + snprintf(pEntry->data, dataLen, "value%d", i); + + // syncEntryPrint2((char*)"write entry:", pEntry); + pSyncNode->pLogStore->appendEntry(pSyncNode->pLogStore, pEntry); + syncEntryDestory(pEntry); + + if (i == 0) { + assert(pSyncNode->pLogStore->getLastIndex(pSyncNode->pLogStore) == SYNC_INDEX_BEGIN); + } + } + logStorePrint(pSyncNode->pLogStore); + + pSyncNode->pLogStore->truncate(pSyncNode->pLogStore, 3); + logStorePrint(pSyncNode->pLogStore); +} + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } + + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); + + ret = syncEnvStart(); + assert(ret == 0); + + taosRemoveDir("./wal_test"); + + pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + // syncNodePrint((char*)"syncLogStoreTest", pSyncNode); + // initRaftId(pSyncNode); + + logStoreTest(); + + return 0; +} diff --git a/source/libs/sync/test/syncPingReplyTest.cpp b/source/libs/sync/test/syncPingReplyTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e1448e7818c8d41c6b880208c2f4fe78ecb4035 --- /dev/null +++ b/source/libs/sync/test/syncPingReplyTest.cpp @@ -0,0 +1,95 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +SyncPingReply *createMsg() { + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + srcId.vgId = 100; + destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + destId.vgId = 100; + SyncPingReply *pMsg = syncPingReplyBuild3(&srcId, &destId); + return pMsg; +} + +void test1() { + SyncPingReply *pMsg = createMsg(); + syncPingReplyPrint2((char *)"test1:", pMsg); + syncPingReplyDestroy(pMsg); +} + +void test2() { + SyncPingReply *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncPingReplySerialize(pMsg, serialized, len); + SyncPingReply *pMsg2 = syncPingReplyBuild(pMsg->dataLen); + syncPingReplyDeserialize(serialized, len, pMsg2); + syncPingReplyPrint2((char *)"test2: syncPingReplySerialize -> syncPingReplyDeserialize ", pMsg2); + + free(serialized); + syncPingReplyDestroy(pMsg); + syncPingReplyDestroy(pMsg2); +} + +void test3() { + SyncPingReply *pMsg = createMsg(); + uint32_t len; + char * serialized = syncPingReplySerialize2(pMsg, &len); + SyncPingReply *pMsg2 = syncPingReplyDeserialize2(serialized, len); + syncPingReplyPrint2((char *)"test3: syncPingReplySerialize3 -> syncPingReplyDeserialize2 ", pMsg2); + + free(serialized); + syncPingReplyDestroy(pMsg); + syncPingReplyDestroy(pMsg2); +} + +void test4() { + SyncPingReply *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pMsg, &rpcMsg); + SyncPingReply *pMsg2 = (SyncPingReply *)malloc(rpcMsg.contLen); + syncPingReplyFromRpcMsg(&rpcMsg, pMsg2); + syncPingReplyPrint2((char *)"test4: syncPingReply2RpcMsg -> syncPingReplyFromRpcMsg ", pMsg2); + + syncPingReplyDestroy(pMsg); + syncPingReplyDestroy(pMsg2); +} + +void test5() { + SyncPingReply *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pMsg, &rpcMsg); + SyncPingReply *pMsg2 = syncPingReplyFromRpcMsg2(&rpcMsg); + syncPingReplyPrint2((char *)"test5: syncPingReply2RpcMsg -> syncPingReplyFromRpcMsg2 ", pMsg2); + + syncPingReplyDestroy(pMsg); + syncPingReplyDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncPingTest.cpp b/source/libs/sync/test/syncPingTest.cpp index 4e5f7b78b5965ab5ea9f3cebdeff4d02fb527506..83394b0e77404b32ef665643fc85cdf6f8a602b6 100644 --- a/source/libs/sync/test/syncPingTest.cpp +++ b/source/libs/sync/test/syncPingTest.cpp @@ -1,8 +1,9 @@ +#include #include -#include "syncEnv.h" #include "syncIO.h" #include "syncInt.h" -#include "syncRaftStore.h" +#include "syncMessage.h" +#include "syncUtil.h" void logTest() { sTrace("--- sync log test: trace"); @@ -13,94 +14,82 @@ void logTest() { sFatal("--- sync log test: fatal"); } -uint16_t ports[3] = {7010, 7110, 7210}; - -SSyncNode* doSync(int myIndex) { - SSyncFSM* pFsm; - - SSyncInfo syncInfo; - syncInfo.vgId = 1; - syncInfo.rpcClient = gSyncIO->clientRpc; - syncInfo.FpSendMsg = syncIOSendMsg; - syncInfo.queue = gSyncIO->pMsgQ; - syncInfo.FpEqMsg = syncIOEqMsg; - syncInfo.pFsm = pFsm; - snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./test_sync_ping"); - - SSyncCfg* pCfg = &syncInfo.syncCfg; - pCfg->myIndex = myIndex; - pCfg->replicaNum = 3; +SyncPing *createMsg() { + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + srcId.vgId = 100; + destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + destId.vgId = 100; + SyncPing *pMsg = syncPingBuild3(&srcId, &destId); + return pMsg; +} - pCfg->nodeInfo[0].nodePort = ports[0]; - snprintf(pCfg->nodeInfo[0].nodeFqdn, sizeof(pCfg->nodeInfo[0].nodeFqdn), "%s", "127.0.0.1"); - // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); +void test1() { + SyncPing *pMsg = createMsg(); + syncPingPrint2((char *)"test1:", pMsg); + syncPingDestroy(pMsg); +} - pCfg->nodeInfo[1].nodePort = ports[1]; - snprintf(pCfg->nodeInfo[1].nodeFqdn, sizeof(pCfg->nodeInfo[1].nodeFqdn), "%s", "127.0.0.1"); - // taosGetFqdn(pCfg->nodeInfo[1].nodeFqdn); +void test2() { + SyncPing *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncPingSerialize(pMsg, serialized, len); + SyncPing *pMsg2 = syncPingBuild(pMsg->dataLen); + syncPingDeserialize(serialized, len, pMsg2); + syncPingPrint2((char *)"test2: syncPingSerialize -> syncPingDeserialize ", pMsg2); + + free(serialized); + syncPingDestroy(pMsg); + syncPingDestroy(pMsg2); +} - pCfg->nodeInfo[2].nodePort = ports[2]; - snprintf(pCfg->nodeInfo[2].nodeFqdn, sizeof(pCfg->nodeInfo[2].nodeFqdn), "%s", "127.0.0.1"); - // taosGetFqdn(pCfg->nodeInfo[2].nodeFqdn); +void test3() { + SyncPing *pMsg = createMsg(); + uint32_t len; + char * serialized = syncPingSerialize2(pMsg, &len); + SyncPing *pMsg2 = syncPingDeserialize2(serialized, len); + syncPingPrint2((char *)"test3: syncPingSerialize3 -> syncPingDeserialize2 ", pMsg2); - SSyncNode* pSyncNode = syncNodeOpen(&syncInfo); - assert(pSyncNode != NULL); + free(serialized); + syncPingDestroy(pMsg); + syncPingDestroy(pMsg2); +} - gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; - gSyncIO->pSyncNode = pSyncNode; +void test4() { + SyncPing *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncPing2RpcMsg(pMsg, &rpcMsg); + SyncPing *pMsg2 = (SyncPing *)malloc(rpcMsg.contLen); + syncPingFromRpcMsg(&rpcMsg, pMsg2); + syncPingPrint2((char *)"test4: syncPing2RpcMsg -> syncPingFromRpcMsg ", pMsg2); - return pSyncNode; + syncPingDestroy(pMsg); + syncPingDestroy(pMsg2); } -void timerPingAll(void* param, void* tmrId) { - SSyncNode* pSyncNode = (SSyncNode*)param; - syncNodePingAll(pSyncNode); +void test5() { + SyncPing *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncPing2RpcMsg(pMsg, &rpcMsg); + SyncPing *pMsg2 = syncPingFromRpcMsg2(&rpcMsg); + syncPingPrint2((char *)"test5: syncPing2RpcMsg -> syncPingFromRpcMsg2 ", pMsg2); + + syncPingDestroy(pMsg); + syncPingDestroy(pMsg2); } -int main(int argc, char** argv) { - // taosInitLog((char*)"syncPingTest.log", 100000, 10); +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); tsAsyncLog = 0; sDebugFlag = 143 + 64; - logTest(); - int myIndex = 0; - if (argc >= 2) { - myIndex = atoi(argv[1]); - } - - int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); - assert(ret == 0); - - ret = syncEnvStart(); - assert(ret == 0); - - SSyncNode* pSyncNode = doSync(myIndex); - gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; - gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; - gSyncIO->FpOnSyncTimeout = pSyncNode->FpOnTimeout; - - ret = syncNodeStartPingTimer(pSyncNode); - assert(ret == 0); - - taosMsleep(10000); - - ret = syncNodeStopPingTimer(pSyncNode); - assert(ret == 0); - - taosMsleep(10000); - - ret = syncNodeStartPingTimer(pSyncNode); - assert(ret == 0); - - taosMsleep(10000); - - ret = syncNodeStopPingTimer(pSyncNode); - assert(ret == 0); - - while (1) { - taosMsleep(1000); - } + test1(); + test2(); + test3(); + test4(); + test5(); return 0; } diff --git a/source/libs/sync/test/syncPingTimerTest.cpp b/source/libs/sync/test/syncPingTimerTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e69878632f809d0eb9014c69fd4576076babf385 --- /dev/null +++ b/source/libs/sync/test/syncPingTimerTest.cpp @@ -0,0 +1,130 @@ +#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 3; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + SSyncNode* pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncTimeout = pSyncNode->FpOnTimeout; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } + + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); + + ret = syncEnvStart(); + assert(ret == 0); + + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + syncNodePrint2((char*)"----1", pSyncNode); + + initRaftId(pSyncNode); + + //--------------------------- + + sTrace("syncNodeStartPingTimer ..."); + ret = syncNodeStartPingTimer(pSyncNode); + assert(ret == 0); + syncNodePrint2((char*)"----2", pSyncNode); + + sTrace("sleep ..."); + taosMsleep(10000); + + sTrace("syncNodeStopPingTimer ..."); + ret = syncNodeStopPingTimer(pSyncNode); + assert(ret == 0); + syncNodePrint2((char*)"----3", pSyncNode); + + sTrace("sleep ..."); + taosMsleep(5000); + + sTrace("syncNodeStartPingTimer ..."); + ret = syncNodeStartPingTimer(pSyncNode); + assert(ret == 0); + syncNodePrint2((char*)"----4", pSyncNode); + + sTrace("sleep ..."); + taosMsleep(10000); + + sTrace("syncNodeStopPingTimer ..."); + ret = syncNodeStopPingTimer(pSyncNode); + assert(ret == 0); + syncNodePrint2((char*)"----5", pSyncNode); + + while (1) { + sTrace("while 1 sleep ..."); + taosMsleep(1000); + } + + return 0; +} diff --git a/source/libs/sync/test/syncRaftStoreTest.cpp b/source/libs/sync/test/syncRaftStoreTest.cpp index 71c0138c8d88aa8588f02fb8da8254ff38994f53..0c1c9b881ed0ecc7978d607d3e679f7f3f35ebc9 100644 --- a/source/libs/sync/test/syncRaftStoreTest.cpp +++ b/source/libs/sync/test/syncRaftStoreTest.cpp @@ -22,15 +22,21 @@ int main() { SRaftStore *pRaftStore = raftStoreOpen("./raft_store.json"); assert(pRaftStore != NULL); - raftStorePrint(pRaftStore); +#if 0 pRaftStore->currentTerm = 100; pRaftStore->voteFor.addr = 200; pRaftStore->voteFor.vgId = 300; - + raftStorePersist(pRaftStore); raftStorePrint(pRaftStore); +#endif + + ++(pRaftStore->currentTerm); + ++(pRaftStore->voteFor.addr); + ++(pRaftStore->voteFor.vgId); raftStorePersist(pRaftStore); + raftStorePrint(pRaftStore); return 0; } diff --git a/source/libs/sync/test/syncRequestVoteReplyTest.cpp b/source/libs/sync/test/syncRequestVoteReplyTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bce3e4cd6b00e077e6e5abc54f54a94b357995e --- /dev/null +++ b/source/libs/sync/test/syncRequestVoteReplyTest.cpp @@ -0,0 +1,97 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +SyncRequestVoteReply *createMsg() { + SyncRequestVoteReply *pMsg = syncRequestVoteReplyBuild(); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->term = 77; + pMsg->voteGranted = true; + return pMsg; +} + +void test1() { + SyncRequestVoteReply *pMsg = createMsg(); + syncRequestVoteReplyPrint2((char *)"test1:", pMsg); + syncRequestVoteReplyDestroy(pMsg); +} + +void test2() { + SyncRequestVoteReply *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncRequestVoteReplySerialize(pMsg, serialized, len); + SyncRequestVoteReply *pMsg2 = syncRequestVoteReplyBuild(); + syncRequestVoteReplyDeserialize(serialized, len, pMsg2); + syncRequestVoteReplyPrint2((char *)"test2: syncRequestVoteReplySerialize -> syncRequestVoteReplyDeserialize ", pMsg2); + + free(serialized); + syncRequestVoteReplyDestroy(pMsg); + syncRequestVoteReplyDestroy(pMsg2); +} + +void test3() { + SyncRequestVoteReply *pMsg = createMsg(); + uint32_t len; + char * serialized = syncRequestVoteReplySerialize2(pMsg, &len); + SyncRequestVoteReply *pMsg2 = syncRequestVoteReplyDeserialize2(serialized, len); + syncRequestVoteReplyPrint2((char *)"test3: syncRequestVoteReplySerialize3 -> syncRequestVoteReplyDeserialize2 ", + pMsg2); + + free(serialized); + syncRequestVoteReplyDestroy(pMsg); + syncRequestVoteReplyDestroy(pMsg2); +} + +void test4() { + SyncRequestVoteReply *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncRequestVoteReply2RpcMsg(pMsg, &rpcMsg); + SyncRequestVoteReply *pMsg2 = syncRequestVoteReplyBuild(); + syncRequestVoteReplyFromRpcMsg(&rpcMsg, pMsg2); + syncRequestVoteReplyPrint2((char *)"test4: syncRequestVoteReply2RpcMsg -> syncRequestVoteReplyFromRpcMsg ", pMsg2); + + syncRequestVoteReplyDestroy(pMsg); + syncRequestVoteReplyDestroy(pMsg2); +} + +void test5() { + SyncRequestVoteReply *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncRequestVoteReply2RpcMsg(pMsg, &rpcMsg); + SyncRequestVoteReply *pMsg2 = syncRequestVoteReplyFromRpcMsg2(&rpcMsg); + syncRequestVoteReplyPrint2((char *)"test5: syncRequestVoteReply2RpcMsg -> syncRequestVoteReplyFromRpcMsg2 ", pMsg2); + + syncRequestVoteReplyDestroy(pMsg); + syncRequestVoteReplyDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncRequestVoteTest.cpp b/source/libs/sync/test/syncRequestVoteTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22f47046dea3a8d98e00e5b3fa28d89dfdfd7a04 --- /dev/null +++ b/source/libs/sync/test/syncRequestVoteTest.cpp @@ -0,0 +1,97 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +SyncRequestVote *createMsg() { + SyncRequestVote *pMsg = syncRequestVoteBuild(); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->term = 11; + pMsg->lastLogIndex = 22; + pMsg->lastLogTerm = 33; + return pMsg; +} + +void test1() { + SyncRequestVote *pMsg = createMsg(); + syncRequestVotePrint2((char *)"test1:", pMsg); + syncRequestVoteDestroy(pMsg); +} + +void test2() { + SyncRequestVote *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncRequestVoteSerialize(pMsg, serialized, len); + SyncRequestVote *pMsg2 = syncRequestVoteBuild(); + syncRequestVoteDeserialize(serialized, len, pMsg2); + syncRequestVotePrint2((char *)"test2: syncRequestVoteSerialize -> syncRequestVoteDeserialize ", pMsg2); + + free(serialized); + syncRequestVoteDestroy(pMsg); + syncRequestVoteDestroy(pMsg2); +} + +void test3() { + SyncRequestVote *pMsg = createMsg(); + uint32_t len; + char * serialized = syncRequestVoteSerialize2(pMsg, &len); + SyncRequestVote *pMsg2 = syncRequestVoteDeserialize2(serialized, len); + syncRequestVotePrint2((char *)"test3: syncRequestVoteSerialize3 -> syncRequestVoteDeserialize2 ", pMsg2); + + free(serialized); + syncRequestVoteDestroy(pMsg); + syncRequestVoteDestroy(pMsg2); +} + +void test4() { + SyncRequestVote *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncRequestVote2RpcMsg(pMsg, &rpcMsg); + SyncRequestVote *pMsg2 = syncRequestVoteBuild(); + syncRequestVoteFromRpcMsg(&rpcMsg, pMsg2); + syncRequestVotePrint2((char *)"test4: syncRequestVote2RpcMsg -> syncRequestVoteFromRpcMsg ", pMsg2); + + syncRequestVoteDestroy(pMsg); + syncRequestVoteDestroy(pMsg2); +} + +void test5() { + SyncRequestVote *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncRequestVote2RpcMsg(pMsg, &rpcMsg); + SyncRequestVote *pMsg2 = syncRequestVoteFromRpcMsg2(&rpcMsg); + syncRequestVotePrint2((char *)"test5: syncRequestVote2RpcMsg -> syncRequestVoteFromRpcMsg2 ", pMsg2); + + syncRequestVoteDestroy(pMsg); + syncRequestVoteDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncRpcMsgTest.cpp b/source/libs/sync/test/syncRpcMsgTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee6f6c0800cc594ad3b67e1499451ade21a0a23d --- /dev/null +++ b/source/libs/sync/test/syncRpcMsgTest.cpp @@ -0,0 +1,181 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +int gg = 0; +SyncTimeout *createSyncTimeout() { + SyncTimeout *pMsg = syncTimeoutBuild2(SYNC_TIMEOUT_PING, 999, 333, &gg); + return pMsg; +} + +SyncPing *createSyncPing() { + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + srcId.vgId = 100; + destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + destId.vgId = 100; + SyncPing *pMsg = syncPingBuild3(&srcId, &destId); + return pMsg; +} + +SyncPingReply *createSyncPingReply() { + SRaftId srcId, destId; + srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + srcId.vgId = 100; + destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + destId.vgId = 100; + SyncPingReply *pMsg = syncPingReplyBuild3(&srcId, &destId); + return pMsg; +} + +SyncClientRequest *createSyncClientRequest() { + SRpcMsg rpcMsg; + memset(&rpcMsg, 0, sizeof(rpcMsg)); + rpcMsg.msgType = 12345; + rpcMsg.contLen = 20; + rpcMsg.pCont = rpcMallocCont(rpcMsg.contLen); + strcpy((char *)rpcMsg.pCont, "hello rpc"); + SyncClientRequest *pMsg = syncClientRequestBuild2(&rpcMsg, 123, true); + return pMsg; +} + +SyncRequestVote *createSyncRequestVote() { + SyncRequestVote *pMsg = syncRequestVoteBuild(); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->term = 11; + pMsg->lastLogIndex = 22; + pMsg->lastLogTerm = 33; + return pMsg; +} + +SyncRequestVoteReply *createSyncRequestVoteReply() { + SyncRequestVoteReply *pMsg = syncRequestVoteReplyBuild(); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->term = 77; + pMsg->voteGranted = true; + return pMsg; +} + +SyncAppendEntries *createSyncAppendEntries() { + SyncAppendEntries *pMsg = syncAppendEntriesBuild(20); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->prevLogIndex = 11; + pMsg->prevLogTerm = 22; + pMsg->commitIndex = 33; + strcpy(pMsg->data, "hello world"); + return pMsg; +} + +SyncAppendEntriesReply *createSyncAppendEntriesReply() { + SyncAppendEntriesReply *pMsg = syncAppendEntriesReplyBuild(); + pMsg->srcId.addr = syncUtilAddr2U64("127.0.0.1", 1234); + pMsg->srcId.vgId = 100; + pMsg->destId.addr = syncUtilAddr2U64("127.0.0.1", 5678); + pMsg->destId.vgId = 100; + pMsg->success = true; + pMsg->matchIndex = 77; + return pMsg; +} + +void test1() { + SyncTimeout *pMsg = createSyncTimeout(); + SRpcMsg rpcMsg; + syncTimeout2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test1", &rpcMsg); + syncTimeoutDestroy(pMsg); +} + +void test2() { + SyncPing *pMsg = createSyncPing(); + SRpcMsg rpcMsg; + syncPing2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test2", &rpcMsg); + syncPingDestroy(pMsg); +} + +void test3() { + SyncPingReply *pMsg = createSyncPingReply(); + SRpcMsg rpcMsg; + syncPingReply2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test3", &rpcMsg); + syncPingReplyDestroy(pMsg); +} + +void test4() { + SyncRequestVote *pMsg = createSyncRequestVote(); + SRpcMsg rpcMsg; + syncRequestVote2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test4", &rpcMsg); + syncRequestVoteDestroy(pMsg); +} + +void test5() { + SyncRequestVoteReply *pMsg = createSyncRequestVoteReply(); + SRpcMsg rpcMsg; + syncRequestVoteReply2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test5", &rpcMsg); + syncRequestVoteReplyDestroy(pMsg); +} + +void test6() { + SyncAppendEntries *pMsg = createSyncAppendEntries(); + SRpcMsg rpcMsg; + syncAppendEntries2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test6", &rpcMsg); + syncAppendEntriesDestroy(pMsg); +} + +void test7() { + SyncAppendEntriesReply *pMsg = createSyncAppendEntriesReply(); + SRpcMsg rpcMsg; + syncAppendEntriesReply2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test7", &rpcMsg); + syncAppendEntriesReplyDestroy(pMsg); +} + +void test8() { + SyncClientRequest *pMsg = createSyncClientRequest(); + SRpcMsg rpcMsg; + syncClientRequest2RpcMsg(pMsg, &rpcMsg); + syncRpcMsgPrint2((char *)"test8", &rpcMsg); + syncClientRequestDestroy(pMsg); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + test8(); + + return 0; +} diff --git a/source/libs/sync/test/syncTimeoutTest.cpp b/source/libs/sync/test/syncTimeoutTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f46ab5c7cebc4283ba8edfcbc76315d1a360023 --- /dev/null +++ b/source/libs/sync/test/syncTimeoutTest.cpp @@ -0,0 +1,92 @@ +#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncMessage.h" +#include "syncUtil.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +int gg = 0; + +SyncTimeout *createMsg() { + SyncTimeout *pMsg = syncTimeoutBuild2(SYNC_TIMEOUT_PING, 999, 333, &gg); + return pMsg; +} + +void test1() { + SyncTimeout *pMsg = createMsg(); + syncTimeoutPrint2((char *)"test1:", pMsg); + syncTimeoutDestroy(pMsg); +} + +void test2() { + SyncTimeout *pMsg = createMsg(); + uint32_t len = pMsg->bytes; + char * serialized = (char *)malloc(len); + syncTimeoutSerialize(pMsg, serialized, len); + SyncTimeout *pMsg2 = syncTimeoutBuild(); + syncTimeoutDeserialize(serialized, len, pMsg2); + syncTimeoutPrint2((char *)"test2: syncTimeoutSerialize -> syncTimeoutDeserialize ", pMsg2); + + free(serialized); + syncTimeoutDestroy(pMsg); + syncTimeoutDestroy(pMsg2); +} + +void test3() { + SyncTimeout *pMsg = createMsg(); + uint32_t len; + char * serialized = syncTimeoutSerialize2(pMsg, &len); + SyncTimeout *pMsg2 = syncTimeoutDeserialize2(serialized, len); + syncTimeoutPrint2((char *)"test3: syncTimeoutSerialize3 -> syncTimeoutDeserialize2 ", pMsg2); + + free(serialized); + syncTimeoutDestroy(pMsg); + syncTimeoutDestroy(pMsg2); +} + +void test4() { + SyncTimeout *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncTimeout2RpcMsg(pMsg, &rpcMsg); + SyncTimeout *pMsg2 = (SyncTimeout *)malloc(rpcMsg.contLen); + syncTimeoutFromRpcMsg(&rpcMsg, pMsg2); + syncTimeoutPrint2((char *)"test4: syncTimeout2RpcMsg -> syncTimeoutFromRpcMsg ", pMsg2); + + syncTimeoutDestroy(pMsg); + syncTimeoutDestroy(pMsg2); +} + +void test5() { + SyncTimeout *pMsg = createMsg(); + SRpcMsg rpcMsg; + syncTimeout2RpcMsg(pMsg, &rpcMsg); + SyncTimeout *pMsg2 = syncTimeoutFromRpcMsg2(&rpcMsg); + syncTimeoutPrint2((char *)"test5: syncTimeout2RpcMsg -> syncTimeoutFromRpcMsg2 ", pMsg2); + + syncTimeoutDestroy(pMsg); + syncTimeoutDestroy(pMsg2); +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + test1(); + test2(); + test3(); + test4(); + test5(); + + return 0; +} diff --git a/source/libs/sync/test/syncUtilTest.cpp b/source/libs/sync/test/syncUtilTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..663db3a7b301eb8e020ab5f2f95066ca06d8a308 --- /dev/null +++ b/source/libs/sync/test/syncUtilTest.cpp @@ -0,0 +1,33 @@ +#include "syncUtil.h" +//#include +#include +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftStore.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +void electRandomMSTest() { + for (int i = 0; i < 10; ++i) { + int32_t ms = syncUtilElectRandomMS(); + printf("syncUtilElectRandomMS: %d \n", ms); + } +} + +int main() { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + logTest(); + + electRandomMSTest(); + + return 0; +} diff --git a/source/libs/sync/test/syncVotesGrantedTest.cpp b/source/libs/sync/test/syncVotesGrantedTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..588eb32ffd75d648879f923e619cd624aab5ba68 --- /dev/null +++ b/source/libs/sync/test/syncVotesGrantedTest.cpp @@ -0,0 +1,155 @@ +#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 3; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; +SSyncNode* pSyncNode; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } + + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); + + ret = syncEnvStart(); + assert(ret == 0); + + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + char* serialized = syncNode2Str(pSyncNode); + printf("%s\n", serialized); + free(serialized); + + initRaftId(pSyncNode); + + SVotesGranted* pVotesGranted = voteGrantedCreate(pSyncNode); + assert(pVotesGranted != NULL); + + printf("---------------------------------------\n"); + { + char* serialized = voteGranted2Str(pVotesGranted); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + SyncTerm term = 1234; + printf("---------------------------------------\n"); + voteGrantedReset(pVotesGranted, term); + { + char* serialized = voteGranted2Str(pVotesGranted); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + for (int i = 0; i < replicaNum; ++i) { + SyncRequestVoteReply* reply = syncRequestVoteReplyBuild(); + reply->destId = pSyncNode->myRaftId; + reply->srcId = ids[i]; + reply->term = term; + reply->voteGranted = true; + + voteGrantedVote(pVotesGranted, reply); + { + char* serialized = voteGranted2Str(pVotesGranted); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + voteGrantedVote(pVotesGranted, reply); + { + char* serialized = voteGranted2Str(pVotesGranted); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + } + + printf("---------------------------------------\n"); + voteGrantedReset(pVotesGranted, 123456789); + { + char* serialized = voteGranted2Str(pVotesGranted); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + voteGrantedDestroy(pVotesGranted); + return 0; +} diff --git a/source/libs/sync/test/syncVotesRespondTest.cpp b/source/libs/sync/test/syncVotesRespondTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76fd6fab4e1d807565d3f79f0d0910b6f8111953 --- /dev/null +++ b/source/libs/sync/test/syncVotesRespondTest.cpp @@ -0,0 +1,155 @@ +#include +#include +#include "syncEnv.h" +#include "syncIO.h" +#include "syncInt.h" +#include "syncRaftStore.h" +#include "syncUtil.h" +#include "syncVoteMgr.h" + +void logTest() { + sTrace("--- sync log test: trace"); + sDebug("--- sync log test: debug"); + sInfo("--- sync log test: info"); + sWarn("--- sync log test: warn"); + sError("--- sync log test: error"); + sFatal("--- sync log test: fatal"); +} + +uint16_t ports[] = {7010, 7110, 7210, 7310, 7410}; +int32_t replicaNum = 3; +int32_t myIndex = 0; + +SRaftId ids[TSDB_MAX_REPLICA]; +SSyncInfo syncInfo; +SSyncFSM* pFsm; +SSyncNode* pSyncNode; + +SSyncNode* syncNodeInit() { + syncInfo.vgId = 1234; + syncInfo.rpcClient = gSyncIO->clientRpc; + syncInfo.FpSendMsg = syncIOSendMsg; + syncInfo.queue = gSyncIO->pMsgQ; + syncInfo.FpEqMsg = syncIOEqMsg; + syncInfo.pFsm = pFsm; + snprintf(syncInfo.path, sizeof(syncInfo.path), "%s", "./"); + + SSyncCfg* pCfg = &syncInfo.syncCfg; + pCfg->myIndex = myIndex; + pCfg->replicaNum = replicaNum; + + for (int i = 0; i < replicaNum; ++i) { + pCfg->nodeInfo[i].nodePort = ports[i]; + snprintf(pCfg->nodeInfo[i].nodeFqdn, sizeof(pCfg->nodeInfo[i].nodeFqdn), "%s", "127.0.0.1"); + // taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + } + + pSyncNode = syncNodeOpen(&syncInfo); + assert(pSyncNode != NULL); + + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->FpOnSyncRequestVote = pSyncNode->FpOnRequestVote; + gSyncIO->FpOnSyncRequestVoteReply = pSyncNode->FpOnRequestVoteReply; + gSyncIO->FpOnSyncAppendEntries = pSyncNode->FpOnAppendEntries; + gSyncIO->FpOnSyncAppendEntriesReply = pSyncNode->FpOnAppendEntriesReply; + gSyncIO->FpOnSyncPing = pSyncNode->FpOnPing; + gSyncIO->FpOnSyncPingReply = pSyncNode->FpOnPingReply; + gSyncIO->pSyncNode = pSyncNode; + + return pSyncNode; +} + +SSyncNode* syncInitTest() { return syncNodeInit(); } + +void initRaftId(SSyncNode* pSyncNode) { + for (int i = 0; i < replicaNum; ++i) { + ids[i] = pSyncNode->replicasId[i]; + char* s = syncUtilRaftId2Str(&ids[i]); + printf("raftId[%d] : %s\n", i, s); + free(s); + } +} + +int main(int argc, char** argv) { + // taosInitLog((char *)"syncTest.log", 100000, 10); + tsAsyncLog = 0; + sDebugFlag = 143 + 64; + + myIndex = 0; + if (argc >= 2) { + myIndex = atoi(argv[1]); + } + + int32_t ret = syncIOStart((char*)"127.0.0.1", ports[myIndex]); + assert(ret == 0); + + ret = syncEnvStart(); + assert(ret == 0); + + SSyncNode* pSyncNode = syncInitTest(); + assert(pSyncNode != NULL); + + char* serialized = syncNode2Str(pSyncNode); + printf("%s\n", serialized); + free(serialized); + + initRaftId(pSyncNode); + + SVotesRespond* pVotesRespond = votesRespondCreate(pSyncNode); + assert(pVotesRespond != NULL); + + printf("---------------------------------------\n"); + { + char* serialized = votesRespond2Str(pVotesRespond); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + SyncTerm term = 1234; + printf("---------------------------------------\n"); + votesRespondReset(pVotesRespond, term); + { + char* serialized = votesRespond2Str(pVotesRespond); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + for (int i = 0; i < replicaNum; ++i) { + SyncRequestVoteReply* reply = syncRequestVoteReplyBuild(); + reply->destId = pSyncNode->myRaftId; + reply->srcId = ids[i]; + reply->term = term; + reply->voteGranted = true; + + votesRespondAdd(pVotesRespond, reply); + { + char* serialized = votesRespond2Str(pVotesRespond); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + votesRespondAdd(pVotesRespond, reply); + { + char* serialized = votesRespond2Str(pVotesRespond); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + } + + printf("---------------------------------------\n"); + votesRespondReset(pVotesRespond, 123456789); + { + char* serialized = votesRespond2Str(pVotesRespond); + assert(serialized != NULL); + printf("%s\n", serialized); + free(serialized); + } + + votesRespondDestory(pVotesRespond); + return 0; +} diff --git a/source/libs/tdb/src/db/tdbUtil.c b/source/libs/tdb/src/db/tdbUtil.c index fe0f3befd62717fe7748cd3b0b92217f4d6d5b11..237a39e47db8223827320e070238e7b251d3bcc0 100644 --- a/source/libs/tdb/src/db/tdbUtil.c +++ b/source/libs/tdb/src/db/tdbUtil.c @@ -27,7 +27,7 @@ int tdbGnrtFileID(const char *fname, uint8_t *fileid, bool unique) { ((uint64_t *)fileid)[0] = stDev; ((uint64_t *)fileid)[1] = stIno; if (unique) { - ((uint64_t *)fileid)[2] = rand(); + ((uint64_t *)fileid)[2] = taosRand(); } return 0; diff --git a/source/libs/tfs/inc/tfsInt.h b/source/libs/tfs/inc/tfsInt.h index 913f34d6c201b54f396493e28c4459037a614057..f16d0445c6bb2ab9eb5aaf6e5d7844527637b538 100644 --- a/source/libs/tfs/inc/tfsInt.h +++ b/source/libs/tfs/inc/tfsInt.h @@ -59,7 +59,7 @@ typedef struct STfsDir { SDiskID did; char dirname[TSDB_FILENAME_LEN]; STfsFile tfile; - DIR *dir; + TdDirPtr pDir; STfs *pTfs; } STfsDir; diff --git a/source/libs/tfs/src/tfs.c b/source/libs/tfs/src/tfs.c index 2579490791a657eaddba1297195df74f44bb474f..c46989dc5dbeda6e5b774cc817ed7a97713f8087 100644 --- a/source/libs/tfs/src/tfs.c +++ b/source/libs/tfs/src/tfs.c @@ -192,14 +192,14 @@ void tfsBasename(const STfsFile *pFile, char *dest) { char tname[TSDB_FILENAME_LEN] = "\0"; tstrncpy(tname, pFile->aname, TSDB_FILENAME_LEN); - tstrncpy(dest, basename(tname), TSDB_FILENAME_LEN); + tstrncpy(dest, taosDirEntryBaseName(tname), TSDB_FILENAME_LEN); } void tfsDirname(const STfsFile *pFile, char *dest) { char tname[TSDB_FILENAME_LEN] = "\0"; tstrncpy(tname, pFile->aname, TSDB_FILENAME_LEN); - tstrncpy(dest, dirname(tname), TSDB_FILENAME_LEN); + tstrncpy(dest, taosDirName(tname), TSDB_FILENAME_LEN); } int32_t tfsRemoveFile(const STfsFile *pFile) { return taosRemoveFile(pFile->aname); } @@ -233,7 +233,7 @@ int32_t tfsMkdirRecurAt(STfs *pTfs, const char *rname, SDiskID diskId) { // the pointer directly in this recursion. // See // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dirname.3.html - char *dir = strdup(dirname(s)); + char *dir = strdup(taosDirName(s)); if (tfsMkdirRecurAt(pTfs, dir, diskId) < 0) { free(s); @@ -324,45 +324,46 @@ STfsDir *tfsOpendir(STfs *pTfs, const char *rname) { return pDir; } -const STfsFile *tfsReaddir(STfsDir *pDir) { - if (pDir == NULL || pDir->dir == NULL) return NULL; +const STfsFile *tfsReaddir(STfsDir *pTfsDir) { + if (pTfsDir == NULL || pTfsDir->pDir == NULL) return NULL; char bname[TMPNAME_LEN * 2] = "\0"; while (true) { - struct dirent *dp = NULL; - dp = readdir(pDir->dir); - if (dp != NULL) { + TdDirEntryPtr pDirEntry = NULL; + pDirEntry = taosReadDir(pTfsDir->pDir); + if (pDirEntry != NULL) { // Skip . and .. - if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; + char *name = taosGetDirEntryName(pDirEntry); + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue; - if (pDir->dirname == NULL || pDir->dirname[0] == 0) { - snprintf(bname, TMPNAME_LEN * 2, "%s", dp->d_name); + if (pTfsDir->dirname == NULL || pTfsDir->dirname[0] == 0) { + snprintf(bname, TMPNAME_LEN * 2, "%s", name); } else { - snprintf(bname, TMPNAME_LEN * 2, "%s%s%s", pDir->dirname, TD_DIRSEP, dp->d_name); + snprintf(bname, TMPNAME_LEN * 2, "%s%s%s", pTfsDir->dirname, TD_DIRSEP, name); } - tfsInitFile(pDir->pTfs, &pDir->tfile, pDir->did, bname); - return &pDir->tfile; + tfsInitFile(pTfsDir->pTfs, &pTfsDir->tfile, pTfsDir->did, bname); + return &pTfsDir->tfile; } - if (tfsOpendirImpl(pDir->pTfs, pDir) < 0) { + if (tfsOpendirImpl(pTfsDir->pTfs, pTfsDir) < 0) { return NULL; } - if (pDir->dir == NULL) { + if (pTfsDir->pDir == NULL) { terrno = TSDB_CODE_SUCCESS; return NULL; } } } -void tfsClosedir(STfsDir *pDir) { - if (pDir) { - if (pDir->dir != NULL) { - closedir(pDir->dir); - pDir->dir = NULL; +void tfsClosedir(STfsDir *pTfsDir) { + if (pTfsDir) { + if (pTfsDir->pDir != NULL) { + taosCloseDir(pTfsDir->pDir); + pTfsDir->pDir = NULL; } - free(pDir); + free(pTfsDir); } } @@ -487,29 +488,29 @@ static STfsDisk *tfsGetDiskByName(STfs *pTfs, const char *dir) { return pDisk; } -static int32_t tfsOpendirImpl(STfs *pTfs, STfsDir *pDir) { +static int32_t tfsOpendirImpl(STfs *pTfs, STfsDir *pTfsDir) { STfsDisk *pDisk = NULL; char adir[TMPNAME_LEN * 2] = "\0"; - if (pDir->dir != NULL) { - closedir(pDir->dir); - pDir->dir = NULL; + if (pTfsDir->pDir != NULL) { + taosCloseDir(pTfsDir->pDir); + pTfsDir->pDir = NULL; } while (true) { - pDisk = tfsNextDisk(pTfs, &pDir->iter); + pDisk = tfsNextDisk(pTfs, &pTfsDir->iter); if (pDisk == NULL) return 0; - pDir->did.level = pDisk->level; - pDir->did.id = pDisk->id; + pTfsDir->did.level = pDisk->level; + pTfsDir->did.id = pDisk->id; if (pDisk->path == NULL || pDisk->path[0] == 0) { - snprintf(adir, TMPNAME_LEN * 2, "%s", pDir->dirname); + snprintf(adir, TMPNAME_LEN * 2, "%s", pTfsDir->dirname); } else { - snprintf(adir, TMPNAME_LEN * 2, "%s%s%s", pDisk->path, TD_DIRSEP, pDir->dirname); + snprintf(adir, TMPNAME_LEN * 2, "%s%s%s", pDisk->path, TD_DIRSEP, pTfsDir->dirname); } - pDir->dir = opendir(adir); - if (pDir->dir != NULL) break; + pTfsDir->pDir = taosOpenDir(adir); + if (pTfsDir->pDir != NULL) break; } return 0; diff --git a/source/libs/transport/CMakeLists.txt b/source/libs/transport/CMakeLists.txt index 465646ac9539591b92103ed22dbc3ef1efa4049a..5cc436cf3267eb68bf106f018512ea661512c92f 100644 --- a/source/libs/transport/CMakeLists.txt +++ b/source/libs/transport/CMakeLists.txt @@ -12,6 +12,7 @@ target_link_libraries( PUBLIC os PUBLIC util PUBLIC common + PUBLIC zlib ) if (${BUILD_WITH_UV_TRANS}) if (${BUILD_WITH_UV}) diff --git a/source/libs/transport/inc/transComm.h b/source/libs/transport/inc/transComm.h index 985d2f2f2f30acaa89d48bf2e1f5f551779bb63a..99f890d3a0288b6da16c8047267986213a43e5fd 100644 --- a/source/libs/transport/inc/transComm.h +++ b/source/libs/transport/inc/transComm.h @@ -120,10 +120,13 @@ typedef struct { // SEpSet* pSet; // for synchronous API } SRpcReqContext; +typedef SRpcMsg STransMsg; +typedef SRpcInfo STrans; +typedef SRpcConnInfo STransHandleInfo; + typedef struct { - SRpcInfo* pTransInst; // associated SRpcInfo - SEpSet epSet; // ip list provided by app - void* ahandle; // handle provided by app + SEpSet epSet; // ip list provided by app + void* ahandle; // handle provided by app // struct SRpcConn* pConn; // pConn allocated tmsg_t msgType; // message type uint8_t* pCont; // content provided by app @@ -135,8 +138,8 @@ typedef struct { int8_t connType; // connection type int64_t rid; // refId returned by taosAddRef - SRpcMsg* pRsp; // for synchronous API - tsem_t* pSem; // for synchronous API + STransMsg* pRsp; // for synchronous API + tsem_t* pSem; // for synchronous API int hThrdIdx; char* ip; @@ -242,8 +245,23 @@ int transDestroyBuffer(SConnBuffer* buf); int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf); bool transReadComplete(SConnBuffer* connBuf); -// int transPackMsg(SRpcMsg *rpcMsg, bool sercured, bool auth, char **msg, int32_t *msgLen); +int transSetConnOption(uv_tcp_t* stream); + +void transRefSrvHandle(void* handle); +void transUnrefSrvHandle(void* handle); + +void transRefCliHandle(void* handle); +void transUnrefCliHandle(void* handle); + +void transSendRequest(void* shandle, const char* ip, uint32_t port, STransMsg* pMsg); +void transSendRecv(void* shandle, const char* ip, uint32_t port, STransMsg* pMsg, STransMsg* pRsp); +void transSendResponse(const STransMsg* pMsg); +int transGetConnInfo(void* thandle, STransHandleInfo* pInfo); + +void* transInitServer(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle); +void* transInitClient(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle); -// int transUnpackMsg(char *msg, SRpcMsg *pMsg, bool ); +void transCloseClient(void* arg); +void transCloseServer(void* arg); #endif diff --git a/source/libs/transport/inc/transportInt.h b/source/libs/transport/inc/transportInt.h index 73137487eb610b443a679be8d79c1174b51c68e2..3924a5cf1a022349233eef43e57a00ff5d56bb40 100644 --- a/source/libs/transport/inc/transportInt.h +++ b/source/libs/transport/inc/transportInt.h @@ -54,7 +54,6 @@ typedef struct { int8_t connType; int64_t index; char label[TSDB_LABEL_LEN]; - bool noPool; // pool or not char user[TSDB_UNI_LEN]; // meter ID char spi; // security parameter index @@ -65,6 +64,7 @@ typedef struct { void (*cfp)(void* parent, SRpcMsg*, SEpSet*); int (*afp)(void* parent, char* user, char* spi, char* encrypt, char* secret, char* ckey); bool (*pfp)(void* parent, tmsg_t msgType); + void* (*mfp)(void* parent, tmsg_t msgType); int32_t refCount; void* parent; diff --git a/source/libs/transport/src/rpcMain.c b/source/libs/transport/src/rpcMain.c index e1319da1624b0b32c9cd0e987768e0ea8e66e022..86dd17bb0c8978c04d3d031f827b1b23d5a78d43 100644 --- a/source/libs/transport/src/rpcMain.c +++ b/source/libs/transport/src/rpcMain.c @@ -64,7 +64,6 @@ typedef struct { void (*cfp)(void *parent, SRpcMsg *, SEpSet *); int (*afp)(void *parent, char *user, char *spi, char *encrypt, char *secret, char *ckey); - bool noPool; int32_t refCount; void * parent; void * idPool; // handle to ID pool @@ -749,7 +748,7 @@ static SRpcConn *rpcAllocateServerConn(SRpcInfo *pRpc, SRecvInfo *pRecv) { memcpy(pConn->user, pHead->user, tListLen(pConn->user)); pConn->pRpc = pRpc; pConn->sid = sid; - pConn->tranId = (uint16_t)(rand() & 0xFFFF); + pConn->tranId = (uint16_t)(taosRand() & 0xFFFF); pConn->ownId = htonl(pConn->sid); pConn->linkUid = pHead->linkUid; if (pRpc->afp) { diff --git a/source/libs/transport/src/rpcTcp.c b/source/libs/transport/src/rpcTcp.c index d95ac3d36d5d8b233771a5953f0996cf52dd1ba3..aac38b21e8fdf570dfe76414586e6cca83961dd7 100644 --- a/source/libs/transport/src/rpcTcp.c +++ b/source/libs/transport/src/rpcTcp.c @@ -24,7 +24,7 @@ #ifndef USE_UV typedef struct SFdObj { void * signature; - SOCKET fd; // TCP socket FD + TdSocketPtr pSocket; // TCP socket FD void * thandle; // handle from upper layer, like TAOS uint32_t ip; uint16_t port; @@ -40,7 +40,7 @@ typedef struct SThreadObj { pthread_mutex_t mutex; uint32_t ip; bool stop; - EpollFd pollFd; + TdEpollPtr pEpoll; int numOfFds; int threadId; char label[TSDB_LABEL_LEN]; @@ -56,20 +56,20 @@ typedef struct { } SClientObj; typedef struct { - SOCKET fd; - uint32_t ip; - uint16_t port; - int8_t stop; - int8_t reserve; - char label[TSDB_LABEL_LEN]; - int numOfThreads; - void * shandle; - SThreadObj **pThreadObj; - pthread_t thread; + TdSocketServerPtr pSocketServer; + uint32_t ip; + uint16_t port; + int8_t stop; + int8_t reserve; + char label[TSDB_LABEL_LEN]; + int numOfThreads; + void * shandle; + SThreadObj **pThreadObj; + pthread_t thread; } SServerObj; static void * taosProcessTcpData(void *param); -static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd); +static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, TdSocketPtr pSocket); static void taosFreeFdObj(SFdObj *pFdObj); static void taosReportBrokenLink(SFdObj *pFdObj); static void * taosAcceptTcpConnection(void *arg); @@ -85,7 +85,7 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread return NULL; } - pServerObj->fd = -1; + pServerObj->pSocketServer = NULL; taosResetPthread(&pServerObj->thread); pServerObj->ip = ip; pServerObj->port = port; @@ -118,7 +118,7 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread } pServerObj->pThreadObj[i] = pThreadObj; - pThreadObj->pollFd = -1; + pThreadObj->pEpoll = NULL; taosResetPthread(&pThreadObj->thread); pThreadObj->processData = fp; tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label)); @@ -135,8 +135,8 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread break; } - pThreadObj->pollFd = (EpollFd)epoll_create(10); // size does not matter - if (pThreadObj->pollFd < 0) { + pThreadObj->pEpoll = taosCreateEpoll(10); // size does not matter + if (pThreadObj->pEpoll == NULL) { tError("%s failed to create TCP epoll", label); code = -1; break; @@ -151,8 +151,8 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread pThreadObj->threadId = i; } - pServerObj->fd = taosOpenTcpServerSocket(pServerObj->ip, pServerObj->port); - if (pServerObj->fd < 0) code = -1; + pServerObj->pSocketServer = taosOpenTcpServerSocket(pServerObj->ip, pServerObj->port); + if (pServerObj->pSocketServer == NULL) code = -1; if (code == 0) { code = pthread_create(&pServerObj->thread, &thattr, taosAcceptTcpConnection, (void *)pServerObj); @@ -196,8 +196,8 @@ void taosStopTcpServer(void *handle) { if (pServerObj == NULL) return; pServerObj->stop = 1; - if (pServerObj->fd >= 0) { - taosShutDownSocketRD(pServerObj->fd); + if (pServerObj->pSocketServer != NULL) { + taosShutDownSocketServerRD(pServerObj->pSocketServer); } if (taosCheckPthreadValid(pServerObj->thread)) { if (taosComparePthread(pServerObj->thread, pthread_self())) { @@ -227,7 +227,7 @@ void taosCleanUpTcpServer(void *handle) { } static void *taosAcceptTcpConnection(void *arg) { - SOCKET connFd = -1; + TdSocketPtr pSocket = NULL; struct sockaddr_in caddr; int threadId = 0; SThreadObj * pThreadObj; @@ -239,13 +239,13 @@ static void *taosAcceptTcpConnection(void *arg) { while (1) { socklen_t addrlen = sizeof(caddr); - connFd = accept(pServerObj->fd, (struct sockaddr *)&caddr, &addrlen); + pSocket = taosAcceptTcpConnectSocket(pServerObj->pSocketServer, (struct sockaddr *)&caddr, &addrlen); if (pServerObj->stop) { tDebug("%s TCP server stop accepting new connections", pServerObj->label); break; } - if (connFd == -1) { + if (pSocket == NULL) { if (errno == EINVAL) { tDebug("%s TCP server stop accepting new connections, exiting", pServerObj->label); break; @@ -255,11 +255,11 @@ static void *taosAcceptTcpConnection(void *arg) { continue; } - taosKeepTcpAlive(connFd); + taosKeepTcpAlive(pSocket); struct timeval to = {5, 0}; - int32_t ret = taosSetSockOpt(connFd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); + int32_t ret = taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); if (ret != 0) { - taosCloseSocket(connFd); + taosCloseSocket(&pSocket); tError("%s failed to set recv timeout fd(%s)for connection from:%s:%hu", pServerObj->label, strerror(errno), taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port)); continue; @@ -268,14 +268,14 @@ static void *taosAcceptTcpConnection(void *arg) { // pick up the thread to handle this connection pThreadObj = pServerObj->pThreadObj[threadId]; - SFdObj *pFdObj = taosMallocFdObj(pThreadObj, connFd); + SFdObj *pFdObj = taosMallocFdObj(pThreadObj, pSocket); if (pFdObj) { pFdObj->ip = caddr.sin_addr.s_addr; pFdObj->port = htons(caddr.sin_port); - tDebug("%s new TCP connection from %s:%hu, fd:%d FD:%p numOfFds:%d", pServerObj->label, - taosInetNtoa(caddr.sin_addr), pFdObj->port, connFd, pFdObj, pThreadObj->numOfFds); + tDebug("%s new TCP connection from %s:%hu, FD:%p numOfFds:%d", pServerObj->label, + taosInetNtoa(caddr.sin_addr), pFdObj->port, pFdObj, pThreadObj->numOfFds); } else { - taosCloseSocket(connFd); + taosCloseSocket(&pSocket); tError("%s failed to malloc FdObj(%s) for connection from:%s:%hu", pServerObj->label, strerror(errno), taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port)); } @@ -285,7 +285,7 @@ static void *taosAcceptTcpConnection(void *arg) { threadId = threadId % pServerObj->numOfThreads; } - taosCloseSocket(pServerObj->fd); + taosCloseSocketServer(&pServerObj->pSocketServer); return NULL; } @@ -339,8 +339,8 @@ void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int numOfThread break; } - pThreadObj->pollFd = (int64_t)epoll_create(10); // size does not matter - if (pThreadObj->pollFd < 0) { + pThreadObj->pEpoll = taosCreateEpoll(10); // size does not matter + if (pThreadObj->pEpoll == NULL) { tError("%s failed to create TCP epoll", label); code = -1; break; @@ -388,21 +388,17 @@ void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uin atomic_store_32(&pClientObj->index, index + 1); SThreadObj *pThreadObj = pClientObj->pThreadObj[index]; - SOCKET fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip); -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - if (fd == (SOCKET)-1) return NULL; -#else - if (fd <= 0) return NULL; -#endif + TdSocketPtr pSocket = taosOpenTcpClientSocket(ip, port, pThreadObj->ip); + if (pSocket == NULL) return NULL; struct sockaddr_in sin; uint16_t localPort = 0; unsigned int addrlen = sizeof(sin); - if (getsockname(fd, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET && addrlen == sizeof(sin)) { + if (taosGetSocketName(pSocket, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET && addrlen == sizeof(sin)) { localPort = (uint16_t)ntohs(sin.sin_port); } - SFdObj *pFdObj = taosMallocFdObj(pThreadObj, fd); + SFdObj *pFdObj = taosMallocFdObj(pThreadObj, pSocket); if (pFdObj) { pFdObj->thandle = thandle; @@ -415,7 +411,7 @@ void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uin ipport, localPort, pFdObj, pThreadObj->numOfFds); } else { tError("%s failed to malloc client FdObj(%s)", pThreadObj->label, strerror(errno)); - taosCloseSocket(fd); + taosCloseSocket(&pSocket); } return pFdObj; @@ -430,7 +426,7 @@ void taosCloseTcpConnection(void *chandle) { // pFdObj->thandle = NULL; pFdObj->closedByApp = 1; - taosShutDownSocketWR(pFdObj->fd); + taosShutDownSocketWR(pFdObj->pSocket); } int taosSendTcpData(uint32_t ip, uint16_t port, void *data, int len, void *chandle) { @@ -438,8 +434,8 @@ int taosSendTcpData(uint32_t ip, uint16_t port, void *data, int len, void *chand if (pFdObj == NULL || pFdObj->signature != pFdObj) return -1; SThreadObj *pThreadObj = pFdObj->pThreadObj; - int ret = taosWriteMsg(pFdObj->fd, data, len); - tTrace("%s %p TCP data is sent, FD:%p fd:%d bytes:%d", pThreadObj->label, pFdObj->thandle, pFdObj, pFdObj->fd, ret); + int ret = taosWriteMsg(pFdObj->pSocket, data, len); + tTrace("%s %p TCP data is sent, FD:%p bytes:%d", pThreadObj->label, pFdObj->thandle, pFdObj, ret); return ret; } @@ -449,7 +445,7 @@ static void taosReportBrokenLink(SFdObj *pFdObj) { // notify the upper layer, so it will clean the associated context if (pFdObj->closedByApp == 0) { - taosShutDownSocketWR(pFdObj->fd); + taosShutDownSocketWR(pFdObj->pSocket); SRecvInfo recvInfo; recvInfo.msg = NULL; @@ -473,7 +469,7 @@ static int taosReadTcpData(SFdObj *pFdObj, SRecvInfo *pInfo) { SThreadObj *pThreadObj = pFdObj->pThreadObj; - headLen = taosReadMsg(pFdObj->fd, &rpcHead, sizeof(SRpcHead)); + headLen = taosReadMsg(pFdObj->pSocket, &rpcHead, sizeof(SRpcHead)); if (headLen != sizeof(SRpcHead)) { tDebug("%s %p read error, FD:%p headLen:%d", pThreadObj->label, pFdObj->thandle, pFdObj, headLen); return -1; @@ -486,13 +482,12 @@ static int taosReadTcpData(SFdObj *pFdObj, SRecvInfo *pInfo) { tError("%s %p TCP malloc(size:%d) fail", pThreadObj->label, pFdObj->thandle, msgLen); return -1; } else { - tTrace("%s %p read data, FD:%p fd:%d TCP malloc mem:%p", pThreadObj->label, pFdObj->thandle, pFdObj, pFdObj->fd, - buffer); + tTrace("%s %p read data, FD:%p TCP malloc mem:%p", pThreadObj->label, pFdObj->thandle, pFdObj, buffer); } msg = buffer + tsRpcOverhead; leftLen = msgLen - headLen; - retLen = taosReadMsg(pFdObj->fd, msg + headLen, leftLen); + retLen = taosReadMsg(pFdObj->pSocket, msg + headLen, leftLen); if (leftLen != retLen) { tError("%s %p read error, leftLen:%d retLen:%d FD:%p", pThreadObj->label, pFdObj->thandle, leftLen, retLen, pFdObj); @@ -532,7 +527,7 @@ static void *taosProcessTcpData(void *param) { setThreadName(name); while (1) { - int fdNum = epoll_wait(pThreadObj->pollFd, events, maxEvents, TAOS_EPOLL_WAIT_TIME); + int fdNum = taosWaitEpoll(pThreadObj->pEpoll, events, maxEvents, TAOS_EPOLL_WAIT_TIME); if (pThreadObj->stop) { tDebug("%s TCP thread get stop event, exiting...", pThreadObj->label); break; @@ -561,7 +556,7 @@ static void *taosProcessTcpData(void *param) { } if (taosReadTcpData(pFdObj, &recvInfo) < 0) { - shutdown(pFdObj->fd, SHUT_WR); + taosShutDownSocketWR(pFdObj->pSocket); continue; } @@ -572,9 +567,9 @@ static void *taosProcessTcpData(void *param) { if (pThreadObj->stop) break; } - if (pThreadObj->pollFd >= 0) { - EpollClose(pThreadObj->pollFd); - pThreadObj->pollFd = -1; + if (pThreadObj->pEpoll != NULL) { + taosCloseEpoll(&pThreadObj->pEpoll); + pThreadObj->pEpoll = NULL; } while (pThreadObj->pHead) { @@ -590,7 +585,7 @@ static void *taosProcessTcpData(void *param) { return NULL; } -static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd) { +static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, TdSocketPtr pSocket) { struct epoll_event event; SFdObj *pFdObj = (SFdObj *)calloc(sizeof(SFdObj), 1); @@ -599,13 +594,13 @@ static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd) { } pFdObj->closedByApp = 0; - pFdObj->fd = fd; + pFdObj->pSocket = pSocket; pFdObj->pThreadObj = pThreadObj; pFdObj->signature = pFdObj; event.events = EPOLLIN | EPOLLRDHUP; event.data.ptr = pFdObj; - if (epoll_ctl(pThreadObj->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) { + if (taosCtlEpoll(pThreadObj->pEpoll, EPOLL_CTL_ADD, pSocket, &event) < 0) { tfree(pFdObj); terrno = TAOS_SYSTEM_ERROR(errno); return NULL; @@ -635,8 +630,8 @@ static void taosFreeFdObj(SFdObj *pFdObj) { } pFdObj->signature = NULL; - epoll_ctl(pThreadObj->pollFd, EPOLL_CTL_DEL, pFdObj->fd, NULL); - taosCloseSocket(pFdObj->fd); + taosCtlEpoll(pThreadObj->pEpoll, EPOLL_CTL_DEL, pFdObj->pSocket, NULL); + taosCloseSocket(&pFdObj->pSocket); pThreadObj->numOfFds--; if (pThreadObj->numOfFds < 0) @@ -655,8 +650,7 @@ static void taosFreeFdObj(SFdObj *pFdObj) { pthread_mutex_unlock(&pThreadObj->mutex); - tDebug("%s %p TCP connection is closed, FD:%p fd:%d numOfFds:%d", pThreadObj->label, pFdObj->thandle, pFdObj, - pFdObj->fd, pThreadObj->numOfFds); + tDebug("%s %p TCP connection is closed, FD:%p numOfFds:%d", pThreadObj->label, pFdObj->thandle, pFdObj, pThreadObj->numOfFds); tfree(pFdObj); } diff --git a/source/libs/transport/src/rpcUdp.c b/source/libs/transport/src/rpcUdp.c index 3640414a4c4ec8c75cebd9175d5ec477ac1ea644..81c8d0af7616598c886ce9dad9fb5be16c83c117 100644 --- a/source/libs/transport/src/rpcUdp.c +++ b/source/libs/transport/src/rpcUdp.c @@ -30,17 +30,17 @@ #define RPC_MAX_UDP_SIZE 65480 typedef struct { - int index; - SOCKET fd; - uint16_t port; // peer port - uint16_t localPort; // local port - char label[TSDB_LABEL_LEN]; // copy from udpConnSet; - pthread_t thread; - void * hash; - void * shandle; // handle passed by upper layer during server initialization - void * pSet; - void *(*processData)(SRecvInfo *pRecv); - char *buffer; // buffer to receive data + int index; + TdSocketPtr pSocket; + uint16_t port; // peer port + uint16_t localPort; // local port + char label[TSDB_LABEL_LEN]; // copy from udpConnSet; + pthread_t thread; + void *hash; + void *shandle; // handle passed by upper layer during server initialization + void *pSet; + void *(*processData)(SRecvInfo *pRecv); + char *buffer; // buffer to receive data } SUdpConn; typedef struct { @@ -86,8 +86,8 @@ void *taosInitUdpConnection(uint32_t ip, uint16_t port, char *label, int threads for (i = 0; i < threads; ++i) { pConn = pSet->udpConn + i; ownPort = (port ? port + i : 0); - pConn->fd = taosOpenUdpSocket(ip, ownPort); - if (pConn->fd < 0) { + pConn->pSocket = taosOpenUdpSocket(ip, ownPort); + if (pConn->pSocket == NULL) { tError("%s failed to open UDP socket %x:%hu", label, ip, port); break; } @@ -100,7 +100,7 @@ void *taosInitUdpConnection(uint32_t ip, uint16_t port, char *label, int threads struct sockaddr_in sin; unsigned int addrlen = sizeof(sin); - if (getsockname(pConn->fd, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET && + if (taosGetSocketName(pConn->pSocket, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET && addrlen == sizeof(sin)) { pConn->localPort = (uint16_t)ntohs(sin.sin_port); } @@ -138,9 +138,9 @@ void taosStopUdpConnection(void *handle) { for (int i = 0; i < pSet->threads; ++i) { pConn = pSet->udpConn + i; - if (pConn->fd >= 0) shutdown(pConn->fd, SHUT_RDWR); - if (pConn->fd >= 0) taosCloseSocket(pConn->fd); - pConn->fd = -1; + if (pConn->pSocket != NULL) taosShutDownSocketRDWR(pConn->pSocket); + if (pConn->pSocket != NULL) taosCloseSocket(&pConn->pSocket); + pConn->pSocket = NULL; } for (int i = 0; i < pSet->threads; ++i) { @@ -163,7 +163,7 @@ void taosCleanUpUdpConnection(void *handle) { for (int i = 0; i < pSet->threads; ++i) { pConn = pSet->udpConn + i; - if (pConn->fd >= 0) taosCloseSocket(pConn->fd); + if (pConn->pSocket != NULL) taosCloseSocket(&pConn->pSocket); } tDebug("%s UDP is cleaned up", pSet->label); @@ -199,13 +199,12 @@ static void *taosRecvUdpData(void *param) { setThreadName("recvUdpData"); while (1) { - dataLen = recvfrom(pConn->fd, pConn->buffer, RPC_MAX_UDP_SIZE, 0, (struct sockaddr *)&sourceAdd, &addLen); + dataLen = taosReadFromSocket(pConn->pSocket, pConn->buffer, RPC_MAX_UDP_SIZE, 0, (struct sockaddr *)&sourceAdd, &addLen); if (dataLen <= 0) { - tDebug("%s UDP socket was closed, exiting(%s), dataLen:%d fd:%d", pConn->label, strerror(errno), (int32_t)dataLen, - pConn->fd); + tDebug("%s UDP socket was closed, exiting(%s), dataLen:%d", pConn->label, strerror(errno), (int32_t)dataLen); // for windows usage, remote shutdown also returns - 1 in windows client - if (pConn->fd == -1) { + if (pConn->pSocket == NULL) { break; } else { continue; @@ -255,7 +254,7 @@ int taosSendUdpData(uint32_t ip, uint16_t port, void *data, int dataLen, void *c destAdd.sin_addr.s_addr = ip; destAdd.sin_port = htons(port); - int ret = (int)taosSendto(pConn->fd, data, (size_t)dataLen, 0, (struct sockaddr *)&destAdd, sizeof(destAdd)); + int ret = taosSendto(pConn->pSocket, data, (size_t)dataLen, 0, (struct sockaddr *)&destAdd, sizeof(destAdd)); return ret; } diff --git a/source/libs/transport/src/thttp.c b/source/libs/transport/src/thttp.c index 95e67290acb085c5412d270aea8562ac26463749..6d1c691b9ba17ac001bfcdf35212cc225f11b0d6 100644 --- a/source/libs/transport/src/thttp.c +++ b/source/libs/transport/src/thttp.c @@ -173,7 +173,7 @@ int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32 #else int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag) { int32_t code = -1; - SOCKET fd = 0; + TdSocketPtr pSocket = NULL; uint32_t ip = taosGetIpv4FromFqdn(server); if (ip == 0xffffffff) { @@ -182,8 +182,8 @@ int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32 goto SEND_OVER; } - fd = taosOpenTcpClientSocket(ip, port, 0); - if (fd < 0) { + pSocket = taosOpenTcpClientSocket(ip, port, 0); + if (pSocket == NULL) { terrno = TAOS_SYSTEM_ERROR(errno); uError("failed to create http socket to %s:%u since %s", server, port, terrstr()); goto SEND_OVER; @@ -200,21 +200,20 @@ int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32 char header[1024] = {0}; int32_t headLen = taosBuildHttpHeader(server, contLen, header, sizeof(header), flag); - - if (taosWriteSocket(fd, header, headLen) < 0) { + if (taosWriteMsg(pSocket, header, headLen) < 0) { terrno = TAOS_SYSTEM_ERROR(errno); uError("failed to send http header to %s:%u since %s", server, port, terrstr()); goto SEND_OVER; } - if (taosWriteSocket(fd, (void*)pCont, contLen) < 0) { + if (taosWriteMsg(pSocket, (void*)pCont, contLen) < 0) { terrno = TAOS_SYSTEM_ERROR(errno); uError("failed to send http content to %s:%u since %s", server, port, terrstr()); goto SEND_OVER; } // read something to avoid nginx error 499 - if (taosReadSocket(fd, header, 10) < 0) { + if (taosWriteMsg(pSocket, header, 10) < 0) { terrno = TAOS_SYSTEM_ERROR(errno); uError("failed to receive response from %s:%u since %s", server, port, terrstr()); goto SEND_OVER; @@ -223,8 +222,8 @@ int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32 code = 0; SEND_OVER: - if (fd != 0) { - taosCloseSocket(fd); + if (pSocket != NULL) { + taosCloseSocket(&pSocket); } return code; diff --git a/source/libs/transport/src/trans.c b/source/libs/transport/src/trans.c index b45683617f6343f5df79fb85e95e44aac3a8c056..58809ee3be24519d494bd2161cd44859f3417312 100644 --- a/source/libs/transport/src/trans.c +++ b/source/libs/transport/src/trans.c @@ -18,8 +18,9 @@ #include "transComm.h" void* (*taosInitHandle[])(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle) = { - taosInitServer, taosInitClient}; -void (*taosCloseHandle[])(void* arg) = {taosCloseServer, taosCloseClient}; + transInitServer, transInitClient}; + +void (*taosCloseHandle[])(void* arg) = {transCloseServer, transCloseClient}; void* rpcOpen(const SRpcInit* pInit) { SRpcInfo* pRpc = calloc(1, sizeof(SRpcInfo)); @@ -34,14 +35,14 @@ void* rpcOpen(const SRpcInit* pInit) { pRpc->cfp = pInit->cfp; pRpc->afp = pInit->afp; pRpc->pfp = pInit->pfp; + pRpc->mfp = pInit->mfp; if (pInit->connType == TAOS_CONN_SERVER) { pRpc->numOfThreads = pInit->numOfThreads > TSDB_MAX_RPC_THREADS ? TSDB_MAX_RPC_THREADS : pInit->numOfThreads; } else { - pRpc->numOfThreads = pInit->numOfThreads; + pRpc->numOfThreads = pInit->numOfThreads > TSDB_MAX_RPC_THREADS ? TSDB_MAX_RPC_THREADS : pInit->numOfThreads; } - pRpc->noPool = pInit->noPool; pRpc->connType = pInit->connType; pRpc->idleTime = pInit->idleTime; pRpc->tcphandle = (*taosInitHandle[pRpc->connType])(0, pInit->localPort, pRpc->label, pRpc->numOfThreads, NULL, pRpc); @@ -52,7 +53,6 @@ void* rpcOpen(const SRpcInit* pInit) { if (pInit->secret) { memcpy(pRpc->secret, pInit->secret, strlen(pInit->secret)); } - return pRpc; } void rpcClose(void* arg) { @@ -112,14 +112,40 @@ void rpcSendRedirectRsp(void* thandle, const SEpSet* pEpSet) { int rpcReportProgress(void* pConn, char* pCont, int contLen) { return -1; } void rpcCancelRequest(int64_t rid) { return; } +void rpcSendRequest(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* pRid) { + char* ip = (char*)(pEpSet->eps[pEpSet->inUse].fqdn); + uint32_t port = pEpSet->eps[pEpSet->inUse].port; + transSendRequest(shandle, ip, port, pMsg); +} +void rpcSendRecv(void* shandle, SEpSet* pEpSet, SRpcMsg* pMsg, SRpcMsg* pRsp) { + char* ip = (char*)(pEpSet->eps[pEpSet->inUse].fqdn); + uint32_t port = pEpSet->eps[pEpSet->inUse].port; + transSendRecv(shandle, ip, port, pMsg, pRsp); +} + +void rpcSendResponse(const SRpcMsg* pMsg) { transSendResponse(pMsg); } +int rpcGetConnInfo(void* thandle, SRpcConnInfo* pInfo) { return transGetConnInfo((void*)thandle, pInfo); } + +void (*taosRefHandle[])(void* handle) = {transRefSrvHandle, transRefCliHandle}; +void (*taosUnRefHandle[])(void* handle) = {transUnrefSrvHandle, transUnrefCliHandle}; + +void rpcRefHandle(void* handle, int8_t type) { + assert(type == TAOS_CONN_SERVER || type == TAOS_CONN_CLIENT); + (*taosRefHandle[type])(handle); +} + +void rpcUnrefHandle(void* handle, int8_t type) { + assert(type == TAOS_CONN_SERVER || type == TAOS_CONN_CLIENT); + (*taosUnRefHandle[type])(handle); +} + int32_t rpcInit() { // impl later return 0; } - void rpcCleanup(void) { // impl later - // return; } + #endif diff --git a/source/libs/transport/src/transCli.c b/source/libs/transport/src/transCli.c index fb76f38fe51711b17bdb940adf0d241143ebe936..2f6ff3763f9255f8613cb6ca2cdfd4c4db729800 100644 --- a/source/libs/transport/src/transCli.c +++ b/source/libs/transport/src/transCli.c @@ -17,59 +17,58 @@ #include "transComm.h" -#define CONN_HOST_THREAD_INDEX(conn) (conn ? ((SCliConn*)conn)->hThrdIdx : -1) -#define CONN_PERSIST_TIME(para) (para * 1000 * 10) - typedef struct SCliConn { + T_REF_DECLARE() uv_connect_t connReq; uv_stream_t* stream; - uv_write_t* writeReq; + uv_write_t writeReq; void* hostThrd; SConnBuffer readBuf; void* data; queue conn; uint64_t expireTime; - int8_t ctnRdCnt; // continue read count int hThrdIdx; + bool broken; // link broken or not - SRpcPush* push; - int persist; // + int persist; // // spi configure - char spi; - char secured; - int32_t ref; + char spi; + char secured; // debug and log info struct sockaddr_in addr; struct sockaddr_in locaddr; + } SCliConn; typedef struct SCliMsg { STransConnCtx* ctx; - SRpcMsg msg; + STransMsg msg; queue q; uint64_t st; } SCliMsg; typedef struct SCliThrdObj { - pthread_t thread; - uv_loop_t* loop; - // uv_async_t* cliAsync; // - SAsyncPool* asyncPool; - uv_timer_t* timer; - void* pool; // conn pool + pthread_t thread; + uv_loop_t* loop; + SAsyncPool* asyncPool; + uv_timer_t timer; + void* pool; // conn pool + + // msg queue queue msg; pthread_mutex_t msgMtx; - uint64_t nextTimeout; // next timeout - void* pTransInst; // - bool quit; + + uint64_t nextTimeout; // next timeout + void* pTransInst; // + bool quit; } SCliThrdObj; -typedef struct SClientObj { +typedef struct SCliObj { char label[TSDB_LABEL_LEN]; int32_t index; int numOfThreads; SCliThrdObj** pThreadObj; -} SClientObj; +} SCliObj; typedef struct SConnList { queue conn; @@ -77,151 +76,185 @@ typedef struct SConnList { // conn pool // add expire timeout and capacity limit -static void* creatConnPool(int size); +static void* createConnPool(int size); static void* destroyConnPool(void* pool); static SCliConn* getConnFromPool(void* pool, char* ip, uint32_t port); static void addConnToPool(void* pool, char* ip, uint32_t port, SCliConn* conn); // register timer in each thread to clear expire conn -static void clientTimeoutCb(uv_timer_t* handle); -// alloc buf for read -static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); -// callback after read nbytes from socket -static void clientReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf); +static void cliTimeoutCb(uv_timer_t* handle); +// alloc buf for recv +static void cliAllocRecvBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); +// callback after read nbytes from socket +static void cliRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf); // callback after write data to socket -static void clientWriteCb(uv_write_t* req, int status); +static void cliSendCb(uv_write_t* req, int status); // callback after conn to server -static void clientConnCb(uv_connect_t* req, int status); -static void clientAsyncCb(uv_async_t* handle); -static void clientDestroy(uv_handle_t* handle); -static void clientConnDestroy(SCliConn* pConn, bool clear /*clear tcp handle or not*/); +static void cliConnCb(uv_connect_t* req, int status); +static void cliAsyncCb(uv_async_t* handle); + +static SCliConn* cliCreateConn(SCliThrdObj* thrd); +static void cliDestroyConn(SCliConn* pConn, bool clear /*clear tcp handle or not*/); +static void cliDestroy(uv_handle_t* handle); -// process data read from server, auth/decompress etc later -static void clientHandleResp(SCliConn* conn); +// process data read from server, add decompress etc later +static void cliHandleResp(SCliConn* conn); // handle except about conn -static void clientHandleExcept(SCliConn* conn); +static void cliHandleExcept(SCliConn* conn); // handle req from app -static void clientHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd); -static void clientHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd); -static void clientSendQuit(SCliThrdObj* thrd); +static void cliHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd); +static void cliHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd); +static void cliSendQuit(SCliThrdObj* thrd); +static void destroyUserdata(STransMsg* userdata); -static void destroyUserdata(SRpcMsg* userdata); +static int cliRBChoseIdx(STrans* pTransInst); static void destroyCmsg(SCliMsg* cmsg); static void transDestroyConnCtx(STransConnCtx* ctx); // thread obj static SCliThrdObj* createThrdObj(); static void destroyThrdObj(SCliThrdObj* pThrd); -// thread -static void* clientThread(void* arg); -static void clientHandleResp(SCliConn* conn) { - SCliMsg* pMsg = conn->data; - STransConnCtx* pCtx = pMsg->ctx; - SRpcInfo* pRpc = pCtx->pTransInst; +#define CONN_HOST_THREAD_INDEX(conn) (conn ? ((SCliConn*)conn)->hThrdIdx : -1) +#define CONN_PERSIST_TIME(para) (para * 1000 * 10) + +#define CONN_GET_INST_LABEL(conn) (((STrans*)(((SCliThrdObj*)conn->hostThrd)->pTransInst))->label) +#define CONN_HANDLE_THREAD_QUIT(conn, thrd) \ + do { \ + if (thrd->quit) { \ + cliHandleExcept(conn); \ + goto _RETURE; \ + } \ + } while (0) + +#define CONN_HANDLE_BROKEN(conn) \ + do { \ + if (conn->broken) { \ + cliHandleExcept(conn); \ + goto _RETURE; \ + } \ + } while (0); + +#define CONN_SET_PERSIST_BY_APP(conn) \ + do { \ + if (conn->persist == false) { \ + conn->persist = true; \ + transRefCliHandle(conn); \ + } \ + } while (0) +#define CONN_NO_PERSIST_BY_APP(conn) ((conn)->persist == false) + +static void* cliWorkThread(void* arg); + +void cliHandleResp(SCliConn* conn) { + SCliThrdObj* pThrd = conn->hostThrd; + STrans* pTransInst = pThrd->pTransInst; STransMsgHead* pHead = (STransMsgHead*)(conn->readBuf.buf); pHead->code = htonl(pHead->code); pHead->msgLen = htonl(pHead->msgLen); - // buf's mem alread translated to rpcMsg.pCont - transClearBuffer(&conn->readBuf); + STransMsg transMsg = {0}; + transMsg.contLen = transContLenFromMsg(pHead->msgLen); + transMsg.pCont = transContFromHead((char*)pHead); + transMsg.code = pHead->code; + transMsg.msgType = pHead->msgType; + transMsg.ahandle = NULL; - SRpcMsg rpcMsg = {0}; - rpcMsg.contLen = transContLenFromMsg(pHead->msgLen); - rpcMsg.pCont = transContFromHead((char*)pHead); - rpcMsg.code = pHead->code; - rpcMsg.msgType = pHead->msgType; - rpcMsg.ahandle = pCtx->ahandle; + SCliMsg* pMsg = conn->data; + STransConnCtx* pCtx = pMsg ? pMsg->ctx : NULL; + if (pMsg == NULL && !CONN_NO_PERSIST_BY_APP(conn)) { + transMsg.ahandle = pTransInst->mfp ? (*pTransInst->mfp)(pTransInst->parent, transMsg.msgType) : NULL; + } else { + transMsg.ahandle = pCtx ? pCtx->ahandle : NULL; + } + // if (rpcMsg.ahandle == NULL) { + // tDebug("%s cli conn %p handle except", CONN_GET_INST_LABEL(conn), conn); + // return; + //} - if (pRpc->pfp != NULL && (pRpc->pfp)(pRpc->parent, rpcMsg.msgType)) { - rpcMsg.handle = conn; - conn->persist = 1; - tDebug("client conn %p persist by app", conn); + // buf's mem alread translated to transMsg.pCont + transClearBuffer(&conn->readBuf); + + if (pTransInst->pfp != NULL && (*pTransInst->pfp)(pTransInst->parent, transMsg.msgType)) { + transMsg.handle = conn; + CONN_SET_PERSIST_BY_APP(conn); + tDebug("%s cli conn %p ref by app", CONN_GET_INST_LABEL(conn), conn); } - tDebug("%s client conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pRpc->label, conn, + tDebug("%s cli conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pTransInst->label, conn, TMSG_INFO(pHead->msgType), inet_ntoa(conn->addr.sin_addr), ntohs(conn->addr.sin_port), - inet_ntoa(conn->locaddr.sin_addr), ntohs(conn->locaddr.sin_port), rpcMsg.contLen); + inet_ntoa(conn->locaddr.sin_addr), ntohs(conn->locaddr.sin_port), transMsg.contLen); conn->secured = pHead->secured; - if (conn->push != NULL && conn->ctnRdCnt != 0) { - (*conn->push->callback)(conn->push->arg, &rpcMsg); - conn->push = NULL; + + if (pCtx == NULL || pCtx->pSem == NULL) { + tTrace("%s cli conn %p handle resp", pTransInst->label, conn); + (pTransInst->cfp)(pTransInst->parent, &transMsg, NULL); } else { - if (pCtx->pSem == NULL) { - tTrace("%s client conn %p handle resp", pRpc->label, conn); - (pRpc->cfp)(pRpc->parent, &rpcMsg, NULL); - } else { - tTrace("%s client conn(sync) %p handle resp", pRpc->label, conn); - memcpy((char*)pCtx->pRsp, (char*)&rpcMsg, sizeof(rpcMsg)); - tsem_post(pCtx->pSem); - } + tTrace("%s cli conn(sync) %p handle resp", pTransInst->label, conn); + memcpy((char*)pCtx->pRsp, (char*)&transMsg, sizeof(transMsg)); + tsem_post(pCtx->pSem); } - conn->ctnRdCnt += 1; - - uv_read_start((uv_stream_t*)conn->stream, clientAllocBufferCb, clientReadCb); - SCliThrdObj* pThrd = conn->hostThrd; + uv_read_start((uv_stream_t*)conn->stream, cliAllocRecvBufferCb, cliRecvCb); - // user owns conn->persist = 1 - if (conn->push == NULL && conn->persist == 0) { - if (pRpc->noPool == true) { - } else { - addConnToPool(pThrd->pool, pCtx->ip, pCtx->port, conn); - } + if (CONN_NO_PERSIST_BY_APP(conn)) { + addConnToPool(pThrd->pool, pCtx->ip, pCtx->port, conn); } destroyCmsg(conn->data); conn->data = NULL; + // start thread's timer of conn pool if not active - if (!uv_is_active((uv_handle_t*)pThrd->timer) && pRpc->idleTime > 0) { - // uv_timer_start((uv_timer_t*)pThrd->timer, clientTimeoutCb, CONN_PERSIST_TIME(pRpc->idleTime) / 2, 0); + if (!uv_is_active((uv_handle_t*)&pThrd->timer) && pTransInst->idleTime > 0) { + // uv_timer_start((uv_timer_t*)&pThrd->timer, cliTimeoutCb, CONN_PERSIST_TIME(pRpc->idleTime) / 2, 0); } } -static void clientHandleExcept(SCliConn* pConn) { - if (pConn->data == NULL && pConn->push == NULL) { - // handle conn except in conn pool - clientConnDestroy(pConn, true); - return; + +void cliHandleExcept(SCliConn* pConn) { + if (pConn->data == NULL) { + if (pConn->broken == true || CONN_NO_PERSIST_BY_APP(pConn)) { + transUnrefCliHandle(pConn); + return; + } } + SCliThrdObj* pThrd = pConn->hostThrd; + STrans* pTransInst = pThrd->pTransInst; + SCliMsg* pMsg = pConn->data; - STransConnCtx* pCtx = pMsg->ctx; + STransConnCtx* pCtx = pMsg ? pMsg->ctx : NULL; - SRpcMsg rpcMsg = {0}; - rpcMsg.ahandle = pCtx->ahandle; - rpcMsg.code = TSDB_CODE_RPC_NETWORK_UNAVAIL; - rpcMsg.msgType = pMsg->msg.msgType + 1; + STransMsg transMsg = {0}; + transMsg.code = TSDB_CODE_RPC_NETWORK_UNAVAIL; + transMsg.msgType = pMsg ? pMsg->msg.msgType + 1 : 0; + transMsg.ahandle = NULL; - if (pConn->push != NULL && pConn->ctnRdCnt != 0) { - (*pConn->push->callback)(pConn->push->arg, &rpcMsg); - pConn->push = NULL; + if (pMsg == NULL && !CONN_NO_PERSIST_BY_APP(pConn)) { + transMsg.ahandle = pTransInst->mfp ? (*pTransInst->mfp)(pTransInst->parent, transMsg.msgType) : NULL; } else { - if (pCtx->pSem == NULL) { - (pCtx->pTransInst->cfp)(pCtx->pTransInst->parent, &rpcMsg, NULL); - } else { - memcpy((char*)(pCtx->pRsp), (char*)(&rpcMsg), sizeof(rpcMsg)); - tsem_post(pCtx->pSem); - } - if (pConn->push != NULL) { - (*pConn->push->callback)(pConn->push->arg, &rpcMsg); - } - pConn->push = NULL; + transMsg.ahandle = pCtx ? pCtx->ahandle : NULL; } - tTrace("%s client conn %p start to destroy", pCtx->pTransInst->label, pConn); - if (pConn->push == NULL) { - destroyCmsg(pConn->data); - pConn->data = NULL; + + if (pCtx == NULL || pCtx->pSem == NULL) { + tTrace("%s cli conn %p handle resp", pTransInst->label, pConn); + (pTransInst->cfp)(pTransInst->parent, &transMsg, NULL); + } else { + tTrace("%s cli conn(sync) %p handle resp", pTransInst->label, pConn); + memcpy((char*)(pCtx->pRsp), (char*)(&transMsg), sizeof(transMsg)); + tsem_post(pCtx->pSem); } - // transDestroyConnCtx(pCtx); - clientConnDestroy(pConn, true); - pConn->ctnRdCnt += 1; + destroyCmsg(pConn->data); + pConn->data = NULL; + + tTrace("%s cli conn %p start to destroy", CONN_GET_INST_LABEL(pConn), pConn); + transUnrefCliHandle(pConn); } -static void clientTimeoutCb(uv_timer_t* handle) { +void cliTimeoutCb(uv_timer_t* handle) { SCliThrdObj* pThrd = handle->data; - SRpcInfo* pRpc = pThrd->pTransInst; + STrans* pTransInst = pThrd->pTransInst; int64_t currentTime = pThrd->nextTimeout; - tTrace("%s, client conn timeout, try to remove expire conn from conn pool", pRpc->label); + tTrace("%s, cli conn timeout, try to remove expire conn from conn pool", pTransInst->label); SConnList* p = taosHashIterate((SHashObj*)pThrd->pool, NULL); while (p != NULL) { @@ -230,9 +263,7 @@ static void clientTimeoutCb(uv_timer_t* handle) { SCliConn* c = QUEUE_DATA(h, SCliConn, conn); if (c->expireTime < currentTime) { QUEUE_REMOVE(h); - // uv_stream_t stm = *(c->stream); - // uv_close((uv_handle_t*)&stm, clientDestroy); - clientConnDestroy(c, true); + transUnrefCliHandle(c); } else { break; } @@ -240,25 +271,26 @@ static void clientTimeoutCb(uv_timer_t* handle) { p = taosHashIterate((SHashObj*)pThrd->pool, p); } - pThrd->nextTimeout = taosGetTimestampMs() + CONN_PERSIST_TIME(pRpc->idleTime); - uv_timer_start(handle, clientTimeoutCb, CONN_PERSIST_TIME(pRpc->idleTime) / 2, 0); + pThrd->nextTimeout = taosGetTimestampMs() + CONN_PERSIST_TIME(pTransInst->idleTime); + uv_timer_start(handle, cliTimeoutCb, CONN_PERSIST_TIME(pTransInst->idleTime) / 2, 0); } -static void* creatConnPool(int size) { + +void* createConnPool(int size) { // thread local, no lock return taosHashInit(size, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); } -static void* destroyConnPool(void* pool) { +void* destroyConnPool(void* pool) { SConnList* connList = taosHashIterate((SHashObj*)pool, NULL); while (connList != NULL) { while (!QUEUE_IS_EMPTY(&connList->conn)) { queue* h = QUEUE_HEAD(&connList->conn); QUEUE_REMOVE(h); SCliConn* c = QUEUE_DATA(h, SCliConn, conn); - clientConnDestroy(c, true); + cliDestroyConn(c, true); } connList = taosHashIterate((SHashObj*)pool, connList); } - taosHashClear(pool); + taosHashCleanup(pool); } static SCliConn* getConnFromPool(void* pool, char* ip, uint32_t port) { @@ -290,23 +322,22 @@ static void addConnToPool(void* pool, char* ip, uint32_t port, SCliConn* conn) { tstrncpy(key, ip, strlen(ip)); tstrncpy(key + strlen(key), (char*)(&port), sizeof(port)); - tTrace("client conn %p added to conn pool, read buf cap: %d", conn, conn->readBuf.cap); + tTrace("cli conn %p added to conn pool, read buf cap: %d", conn, conn->readBuf.cap); - SRpcInfo* pRpc = ((SCliThrdObj*)conn->hostThrd)->pTransInst; + STrans* pTransInst = ((SCliThrdObj*)conn->hostThrd)->pTransInst; - conn->expireTime = taosGetTimestampMs() + CONN_PERSIST_TIME(pRpc->idleTime); + conn->expireTime = taosGetTimestampMs() + CONN_PERSIST_TIME(pTransInst->idleTime); SConnList* plist = taosHashGet((SHashObj*)pool, key, strlen(key)); - conn->ctnRdCnt = 0; // list already create before assert(plist != NULL); QUEUE_PUSH(&plist->conn, &conn->conn); } -static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { +static void cliAllocRecvBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { SCliConn* conn = handle->data; SConnBuffer* pBuf = &conn->readBuf; transAllocBuffer(pBuf, buf); } -static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { +static void cliRecvCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { // impl later if (handle->data == NULL) { return; @@ -316,17 +347,14 @@ static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf if (nread > 0) { pBuf->len += nread; if (transReadComplete(pBuf)) { - tTrace("client conn %p read complete", conn); - clientHandleResp(conn); + tTrace("%s cli conn %p read complete", CONN_GET_INST_LABEL(conn), conn); + cliHandleResp(conn); } else { - tTrace("client conn %p read partial packet, continue to read", conn); + tTrace("%s cli conn %p read partial packet, continue to read", CONN_GET_INST_LABEL(conn), conn); } return; } - if (nread == UV_EOF) { - tError("client conn %p read error: %s", conn, uv_err_name(nread)); - clientHandleExcept(conn); - } + assert(nread <= 0); if (nread == 0) { // ref http://docs.libuv.org/en/v1.x/stream.html?highlight=uv_read_start#c.uv_read_cb @@ -335,61 +363,72 @@ static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf return; } if (nread < 0) { - tError("client conn %p read error: %s", conn, uv_err_name(nread)); - clientHandleExcept(conn); + tError("%s cli conn %p read error: %s", CONN_GET_INST_LABEL(conn), conn, uv_err_name(nread)); + conn->broken = true; + cliHandleExcept(conn); } - // tDebug("Read error %s\n", uv_err_name(nread)); - // uv_close((uv_handle_t*)handle, clientDestroy); } -static void clientConnDestroy(SCliConn* conn, bool clear) { - // - conn->ref--; - if (conn->ref == 0) { - tTrace("client conn %p remove from conn pool", conn); - QUEUE_REMOVE(&conn->conn); - if (clear) { - uv_close((uv_handle_t*)conn->stream, clientDestroy); - } +static SCliConn* cliCreateConn(SCliThrdObj* pThrd) { + SCliConn* conn = calloc(1, sizeof(SCliConn)); + // read/write stream handle + conn->stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t)); + uv_tcp_init(pThrd->loop, (uv_tcp_t*)(conn->stream)); + conn->stream->data = conn; + + conn->writeReq.data = conn; + conn->connReq.data = conn; + + QUEUE_INIT(&conn->conn); + conn->hostThrd = pThrd; + conn->persist = false; + conn->broken = false; + transRefCliHandle(conn); + return conn; +} +static void cliDestroyConn(SCliConn* conn, bool clear) { + tTrace("%s cli conn %p remove from conn pool", CONN_GET_INST_LABEL(conn), conn); + QUEUE_REMOVE(&conn->conn); + if (clear) { + uv_close((uv_handle_t*)conn->stream, cliDestroy); } } -static void clientDestroy(uv_handle_t* handle) { +static void cliDestroy(uv_handle_t* handle) { SCliConn* conn = handle->data; - // transDestroyBuffer(&conn->readBuf); free(conn->stream); - free(conn->writeReq); - tTrace("client conn %p destroy successfully", conn); + tTrace("%s cli conn %p destroy successfully", CONN_GET_INST_LABEL(conn), conn); free(conn); - - // clientConnDestroy(conn, false); } -static void clientWriteCb(uv_write_t* req, int status) { +static void cliSendCb(uv_write_t* req, int status) { SCliConn* pConn = req->data; + if (status == 0) { - tTrace("client conn %p data already was written out", pConn); + tTrace("%s cli conn %p data already was written out", CONN_GET_INST_LABEL(pConn), pConn); SCliMsg* pMsg = pConn->data; if (pMsg == NULL) { - // handle return; } destroyUserdata(&pMsg->msg); } else { - tError("client conn %p failed to write: %s", pConn, uv_err_name(status)); - clientHandleExcept(pConn); + tError("%s cli conn %p failed to write: %s", CONN_GET_INST_LABEL(pConn), pConn, uv_err_name(status)); + cliHandleExcept(pConn); return; } - SCliThrdObj* pThrd = pConn->hostThrd; - uv_read_start((uv_stream_t*)pConn->stream, clientAllocBufferCb, clientReadCb); + uv_read_start((uv_stream_t*)pConn->stream, cliAllocRecvBufferCb, cliRecvCb); } -static void clientWrite(SCliConn* pConn) { +void cliSend(SCliConn* pConn) { + CONN_HANDLE_BROKEN(pConn); + SCliMsg* pCliMsg = pConn->data; STransConnCtx* pCtx = pCliMsg->ctx; - SRpcInfo* pTransInst = pCtx->pTransInst; - SRpcMsg* pMsg = (SRpcMsg*)(&pCliMsg->msg); + SCliThrdObj* pThrd = pConn->hostThrd; + STrans* pTransInst = pThrd->pTransInst; + + STransMsg* pMsg = (STransMsg*)(&pCliMsg->msg); STransMsgHead* pHead = transHeadFromCont(pMsg->pCont); int msgLen = transMsgLenFromCont(pMsg->contLen); @@ -416,21 +455,24 @@ static void clientWrite(SCliConn* pConn) { pHead->msgType = pMsg->msgType; pHead->msgLen = (int32_t)htonl((uint32_t)msgLen); - // if (pHead->msgType == TDMT_VND_QUERY || pHead->msgType == TDMT_VND_) - uv_buf_t wb = uv_buf_init((char*)pHead, msgLen); - tDebug("client conn %p %s is send to %s:%d, local info %s:%d", pConn, TMSG_INFO(pHead->msgType), - inet_ntoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr), - ntohs(pConn->locaddr.sin_port)); - uv_write(pConn->writeReq, (uv_stream_t*)pConn->stream, &wb, 1, clientWriteCb); + tDebug("%s cli conn %p %s is send to %s:%d, local info %s:%d", CONN_GET_INST_LABEL(pConn), pConn, + TMSG_INFO(pHead->msgType), inet_ntoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), + inet_ntoa(pConn->locaddr.sin_addr), ntohs(pConn->locaddr.sin_port)); + + uv_write(&pConn->writeReq, (uv_stream_t*)pConn->stream, &wb, 1, cliSendCb); + + return; +_RETURE: + return; } -static void clientConnCb(uv_connect_t* req, int status) { + +void cliConnCb(uv_connect_t* req, int status) { // impl later SCliConn* pConn = req->data; if (status != 0) { - // tError("failed to connect server(%s, %d), errmsg: %s", pCtx->ip, pCtx->port, uv_strerror(status)); - tError("client conn %p failed to connect server: %s", pConn, uv_strerror(status)); - clientHandleExcept(pConn); + tError("%s cli conn %p failed to connect server: %s", CONN_GET_INST_LABEL(pConn), pConn, uv_strerror(status)); + cliHandleExcept(pConn); return; } int addrlen = sizeof(pConn->addr); @@ -439,100 +481,75 @@ static void clientConnCb(uv_connect_t* req, int status) { addrlen = sizeof(pConn->locaddr); uv_tcp_getsockname((uv_tcp_t*)pConn->stream, (struct sockaddr*)&pConn->locaddr, &addrlen); - tTrace("client conn %p connect to server successfully", pConn); + tTrace("%s cli conn %p connect to server successfully", CONN_GET_INST_LABEL(pConn), pConn); assert(pConn->stream == req->handle); - clientWrite(pConn); + cliSend(pConn); } -static void clientHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd) { - tDebug("client work thread %p start to quit", pThrd); +static void cliHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd) { + tDebug("cli work thread %p start to quit", pThrd); destroyCmsg(pMsg); destroyConnPool(pThrd->pool); - // transDestroyAsyncPool(pThr) uv_close((uv_handle_t*)pThrd->cliAsync, NULL); - uv_timer_stop(pThrd->timer); + + uv_timer_stop(&pThrd->timer); + pThrd->quit = true; - // uv__async_stop(pThrd->cliAsync); uv_stop(pThrd->loop); } -static void clientHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd) { - uint64_t et = taosGetTimestampUs(); - uint64_t el = et - pMsg->st; - tTrace("client msg tran time cost: %" PRIu64 "us", el); - et = taosGetTimestampUs(); - - STransConnCtx* pCtx = pMsg->ctx; +SCliConn* cliGetConn(SCliMsg* pMsg, SCliThrdObj* pThrd) { SCliConn* conn = NULL; - if (pMsg->msg.handle == NULL) { - if (pCtx->pTransInst->noPool == true) { - } else { - conn = getConnFromPool(pThrd->pool, pCtx->ip, pCtx->port); - } - if (conn != NULL) { - tTrace("client conn %p get from conn pool", conn); - } - } else { + if (pMsg->msg.handle != NULL) { conn = (SCliConn*)(pMsg->msg.handle); if (conn != NULL) { - tTrace("client conn %p reused", conn); + tTrace("%s cli conn %p reused", CONN_GET_INST_LABEL(conn), conn); } + } else { + STransConnCtx* pCtx = pMsg->ctx; + conn = getConnFromPool(pThrd->pool, pCtx->ip, pCtx->port); + if (conn != NULL) tTrace("%s cli conn %p get from conn pool", CONN_GET_INST_LABEL(conn), conn); } + return conn; +} + +void cliHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd) { + uint64_t et = taosGetTimestampUs(); + uint64_t el = et - pMsg->st; + tTrace("%s cli msg tran time cost: %" PRIu64 "us", ((STrans*)pThrd->pTransInst)->label, el); + + STransConnCtx* pCtx = pMsg->ctx; + STrans* pTransInst = pThrd->pTransInst; + SCliConn* conn = cliGetConn(pMsg, pThrd); if (conn != NULL) { conn->data = pMsg; - conn->writeReq->data = conn; transDestroyBuffer(&conn->readBuf); - - if (pThrd->quit) { - clientHandleExcept(conn); - return; - } - clientWrite(conn); - + cliSend(conn); } else { - conn = calloc(1, sizeof(SCliConn)); - conn->ref++; - // read/write stream handle - conn->stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t)); - uv_tcp_init(pThrd->loop, (uv_tcp_t*)(conn->stream)); - conn->stream->data = conn; - uv_tcp_nodelay((uv_tcp_t*)conn->stream, 1); - int ret = uv_tcp_keepalive((uv_tcp_t*)conn->stream, 1, 1); - if (ret) { - tTrace("client conn %p failed to set keepalive, %s", conn, uv_err_name(ret)); - } - // write req handle - conn->writeReq = malloc(sizeof(uv_write_t)); - conn->writeReq->data = conn; - - QUEUE_INIT(&conn->conn); - - conn->connReq.data = conn; + conn = cliCreateConn(pThrd); conn->data = pMsg; - conn->hostThrd = pThrd; - - // conn->push = pMsg->msg.push; - // conn->ctnRdCnt = 0; + int ret = transSetConnOption((uv_tcp_t*)conn->stream); + if (ret) { + tError("%s cli conn %p failed to set conn option, errmsg %s", pTransInst->label, conn, uv_err_name(ret)); + } struct sockaddr_in addr; uv_ip4_addr(pMsg->ctx->ip, pMsg->ctx->port, &addr); // handle error in callback if fail to connect - tTrace("client conn %p try to connect to %s:%d", conn, pMsg->ctx->ip, pMsg->ctx->port); - uv_tcp_connect(&conn->connReq, (uv_tcp_t*)(conn->stream), (const struct sockaddr*)&addr, clientConnCb); + tTrace("%s cli conn %p try to connect to %s:%d", pTransInst->label, conn, pMsg->ctx->ip, pMsg->ctx->port); + uv_tcp_connect(&conn->connReq, (uv_tcp_t*)(conn->stream), (const struct sockaddr*)&addr, cliConnCb); } - conn->push = pMsg->msg.push; - conn->ctnRdCnt = 0; conn->hThrdIdx = pCtx->hThrdIdx; } -static void clientAsyncCb(uv_async_t* handle) { +static void cliAsyncCb(uv_async_t* handle) { SAsyncItem* item = handle->data; SCliThrdObj* pThrd = item->pThrd; SCliMsg* pMsg = NULL; - queue wq; // batch process to avoid to lock/unlock frequently + queue wq; pthread_mutex_lock(&item->mtx); QUEUE_MOVE(&item->qmsg, &wq); pthread_mutex_unlock(&item->mtx); @@ -544,47 +561,46 @@ static void clientAsyncCb(uv_async_t* handle) { SCliMsg* pMsg = QUEUE_DATA(h, SCliMsg, q); if (pMsg->ctx == NULL) { - clientHandleQuit(pMsg, pThrd); + cliHandleQuit(pMsg, pThrd); } else { - clientHandleReq(pMsg, pThrd); + cliHandleReq(pMsg, pThrd); } - // clientHandleReq(pMsg, pThrd); count++; } if (count >= 2) { - tTrace("client process batch size: %d", count); + tTrace("cli process batch size: %d", count); } } -static void* clientThread(void* arg) { +static void* cliWorkThread(void* arg) { SCliThrdObj* pThrd = (SCliThrdObj*)arg; - setThreadName("trans-client-work"); + setThreadName("trans-cli-work"); uv_run(pThrd->loop, UV_RUN_DEFAULT); } -void* taosInitClient(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle) { - SClientObj* cli = calloc(1, sizeof(SClientObj)); +void* transInitClient(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle) { + SCliObj* cli = calloc(1, sizeof(SCliObj)); - SRpcInfo* pRpc = shandle; + STrans* pTransInst = shandle; memcpy(cli->label, label, strlen(label)); cli->numOfThreads = numOfThreads; cli->pThreadObj = (SCliThrdObj**)calloc(cli->numOfThreads, sizeof(SCliThrdObj*)); for (int i = 0; i < cli->numOfThreads; i++) { SCliThrdObj* pThrd = createThrdObj(); - pThrd->nextTimeout = taosGetTimestampMs() + CONN_PERSIST_TIME(pRpc->idleTime); + pThrd->nextTimeout = taosGetTimestampMs() + CONN_PERSIST_TIME(pTransInst->idleTime); pThrd->pTransInst = shandle; - int err = pthread_create(&pThrd->thread, NULL, clientThread, (void*)(pThrd)); + int err = pthread_create(&pThrd->thread, NULL, cliWorkThread, (void*)(pThrd)); if (err == 0) { - tDebug("success to create tranport-client thread %d", i); + tDebug("success to create tranport-cli thread %d", i); } cli->pThreadObj[i] = pThrd; } return cli; } -static void destroyUserdata(SRpcMsg* userdata) { +static void destroyUserdata(STransMsg* userdata) { if (userdata->pCont == NULL) { return; } @@ -602,19 +618,19 @@ static void destroyCmsg(SCliMsg* pMsg) { static SCliThrdObj* createThrdObj() { SCliThrdObj* pThrd = (SCliThrdObj*)calloc(1, sizeof(SCliThrdObj)); + QUEUE_INIT(&pThrd->msg); pthread_mutex_init(&pThrd->msgMtx, NULL); pThrd->loop = (uv_loop_t*)malloc(sizeof(uv_loop_t)); uv_loop_init(pThrd->loop); - pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 5, pThrd, clientAsyncCb); + pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 5, pThrd, cliAsyncCb); - pThrd->timer = malloc(sizeof(uv_timer_t)); - uv_timer_init(pThrd->loop, pThrd->timer); - pThrd->timer->data = pThrd; + uv_timer_init(pThrd->loop, &pThrd->timer); + pThrd->timer.data = pThrd; - pThrd->pool = creatConnPool(4); + pThrd->pool = createConnPool(4); pThrd->quit = false; return pThrd; @@ -627,8 +643,8 @@ static void destroyThrdObj(SCliThrdObj* pThrd) { pthread_join(pThrd->thread, NULL); pthread_mutex_destroy(&pThrd->msgMtx); transDestroyAsyncPool(pThrd->asyncPool); - // free(pThrd->cliAsync); - free(pThrd->timer); + + uv_timer_stop(&pThrd->timer); free(pThrd->loop); free(pThrd); } @@ -640,53 +656,64 @@ static void transDestroyConnCtx(STransConnCtx* ctx) { free(ctx); } // -static void clientSendQuit(SCliThrdObj* thrd) { +void cliSendQuit(SCliThrdObj* thrd) { // cli can stop gracefully SCliMsg* msg = calloc(1, sizeof(SCliMsg)); - msg->ctx = NULL; // - transSendAsync(thrd->asyncPool, &msg->q); } -void taosCloseClient(void* arg) { - SClientObj* cli = arg; +int cliRBChoseIdx(STrans* pTransInst) { + int64_t index = pTransInst->index; + if (pTransInst->index++ >= pTransInst->numOfThreads) { + pTransInst->index = 0; + } + return index % pTransInst->numOfThreads; +} + +void transCloseClient(void* arg) { + SCliObj* cli = arg; for (int i = 0; i < cli->numOfThreads; i++) { - clientSendQuit(cli->pThreadObj[i]); + cliSendQuit(cli->pThreadObj[i]); destroyThrdObj(cli->pThreadObj[i]); } free(cli->pThreadObj); free(cli); } -static int clientRBChoseIdx(SRpcInfo* pRpc) { - int64_t index = pRpc->index; - if (pRpc->index++ >= pRpc->numOfThreads) { - pRpc->index = 0; +void transRefCliHandle(void* handle) { + if (handle == NULL) { + return; + } + int ref = T_REF_INC((SCliConn*)handle); + UNUSED(ref); +} +void transUnrefCliHandle(void* handle) { + if (handle == NULL) { + return; + } + int ref = T_REF_DEC((SCliConn*)handle); + if (ref == 0) { + cliDestroyConn((SCliConn*)handle, true); } - return index % pRpc->numOfThreads; } -void rpcSendRequest(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* pRid) { - // impl later - char* ip = (char*)(pEpSet->eps[pEpSet->inUse].fqdn); - uint32_t port = pEpSet->eps[pEpSet->inUse].port; - - SRpcInfo* pRpc = (SRpcInfo*)shandle; - int index = CONN_HOST_THREAD_INDEX(pMsg->handle); +void transSendRequest(void* shandle, const char* ip, uint32_t port, STransMsg* pMsg) { + STrans* pTransInst = (STrans*)shandle; + int index = CONN_HOST_THREAD_INDEX((SCliConn*)pMsg->handle); if (index == -1) { - index = clientRBChoseIdx(pRpc); + index = cliRBChoseIdx(pTransInst); } int32_t flen = 0; if (transCompressMsg(pMsg->pCont, pMsg->contLen, &flen)) { // imp later } + tDebug("send request at thread:%d %p", index, pMsg); STransConnCtx* pCtx = calloc(1, sizeof(STransConnCtx)); - pCtx->pTransInst = (SRpcInfo*)shandle; pCtx->ahandle = pMsg->ahandle; pCtx->msgType = pMsg->msgType; pCtx->ip = strdup(ip); pCtx->port = port; pCtx->hThrdIdx = index; - assert(pRpc->connType == TAOS_CONN_CLIENT); + assert(pTransInst->connType == TAOS_CONN_CLIENT); // atomic or not SCliMsg* cliMsg = malloc(sizeof(SCliMsg)); @@ -694,23 +721,17 @@ void rpcSendRequest(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* cliMsg->msg = *pMsg; cliMsg->st = taosGetTimestampUs(); - SCliThrdObj* thrd = ((SClientObj*)pRpc->tcphandle)->pThreadObj[index]; + SCliThrdObj* thrd = ((SCliObj*)pTransInst->tcphandle)->pThreadObj[index]; transSendAsync(thrd->asyncPool, &(cliMsg->q)); } - -void rpcSendRecv(void* shandle, SEpSet* pEpSet, SRpcMsg* pReq, SRpcMsg* pRsp) { - char* ip = (char*)(pEpSet->eps[pEpSet->inUse].fqdn); - uint32_t port = pEpSet->eps[pEpSet->inUse].port; - - SRpcInfo* pRpc = (SRpcInfo*)shandle; - - int index = CONN_HOST_THREAD_INDEX(pReq->handle); +void transSendRecv(void* shandle, const char* ip, uint32_t port, STransMsg* pReq, STransMsg* pRsp) { + STrans* pTransInst = (STrans*)shandle; + int index = CONN_HOST_THREAD_INDEX(pReq->handle); if (index == -1) { - index = clientRBChoseIdx(pRpc); + index = cliRBChoseIdx(pTransInst); } STransConnCtx* pCtx = calloc(1, sizeof(STransConnCtx)); - pCtx->pTransInst = (SRpcInfo*)shandle; pCtx->ahandle = pReq->ahandle; pCtx->msgType = pReq->msgType; pCtx->ip = strdup(ip); @@ -725,13 +746,12 @@ void rpcSendRecv(void* shandle, SEpSet* pEpSet, SRpcMsg* pReq, SRpcMsg* pRsp) { cliMsg->msg = *pReq; cliMsg->st = taosGetTimestampUs(); - SCliThrdObj* thrd = ((SClientObj*)pRpc->tcphandle)->pThreadObj[index]; + SCliThrdObj* thrd = ((SCliObj*)pTransInst->tcphandle)->pThreadObj[index]; transSendAsync(thrd->asyncPool, &(cliMsg->q)); tsem_t* pSem = pCtx->pSem; tsem_wait(pSem); tsem_destroy(pSem); free(pSem); - - return; } + #endif diff --git a/source/libs/transport/src/transComm.c b/source/libs/transport/src/transComm.c index 9a8607b0edfd93e56820855f55b2ed324a36c1b8..367cb33fc9b31665cddfb635d46fceaa39cfe929 100644 --- a/source/libs/transport/src/transComm.c +++ b/source/libs/transport/src/transComm.c @@ -16,20 +16,6 @@ #include "transComm.h" -int rpcAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey) { - T_MD5_CTX context; - int ret = -1; - - tMD5Init(&context); - tMD5Update(&context, (uint8_t*)pKey, TSDB_PASSWORD_LEN); - tMD5Update(&context, (uint8_t*)pMsg, msgLen); - tMD5Update(&context, (uint8_t*)pKey, TSDB_PASSWORD_LEN); - tMD5Final(&context); - - if (memcmp(context.digest, pAuth, sizeof(context.digest)) == 0) ret = 0; - - return ret; -} int transAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey) { T_MD5_CTX context; int ret = -1; @@ -44,17 +30,7 @@ int transAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey) { return ret; } -void rpcBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey) { - T_MD5_CTX context; - tMD5Init(&context); - tMD5Update(&context, (uint8_t*)pKey, TSDB_PASSWORD_LEN); - tMD5Update(&context, (uint8_t*)pMsg, msgLen); - tMD5Update(&context, (uint8_t*)pKey, TSDB_PASSWORD_LEN); - tMD5Final(&context); - - memcpy(pAuth, context.digest, sizeof(context.digest)); -} void transBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey) { T_MD5_CTX context; @@ -67,45 +43,6 @@ void transBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey) { memcpy(pAuth, context.digest, sizeof(context.digest)); } -int32_t rpcCompressRpcMsg(char* pCont, int32_t contLen) { - SRpcHead* pHead = rpcHeadFromCont(pCont); - int32_t finalLen = 0; - int overhead = sizeof(SRpcComp); - - if (!NEEDTO_COMPRESSS_MSG(contLen)) { - return contLen; - } - - char* buf = malloc(contLen + overhead + 8); // 8 extra bytes - if (buf == NULL) { - tError("failed to allocate memory for rpc msg compression, contLen:%d", contLen); - return contLen; - } - - int32_t compLen = LZ4_compress_default(pCont, buf, contLen, contLen + overhead); - tDebug("compress rpc msg, before:%d, after:%d, overhead:%d", contLen, compLen, overhead); - - /* - * only the compressed size is less than the value of contLen - overhead, the compression is applied - * The first four bytes is set to 0, the second four bytes are utilized to keep the original length of message - */ - if (compLen > 0 && compLen < contLen - overhead) { - SRpcComp* pComp = (SRpcComp*)pCont; - pComp->reserved = 0; - pComp->contLen = htonl(contLen); - memcpy(pCont + overhead, buf, compLen); - - pHead->comp = 1; - tDebug("compress rpc msg, before:%d, after:%d", contLen, compLen); - finalLen = compLen + overhead; - } else { - finalLen = contLen; - } - - free(buf); - return finalLen; -} - bool transCompressMsg(char* msg, int32_t len, int32_t* flen) { return false; // SRpcHead* pHead = rpcHeadFromCont(pCont); @@ -154,39 +91,6 @@ bool transDecompressMsg(char* msg, int32_t len, int32_t* flen) { return false; } -SRpcHead* rpcDecompressRpcMsg(SRpcHead* pHead) { - int overhead = sizeof(SRpcComp); - SRpcHead* pNewHead = NULL; - uint8_t* pCont = pHead->content; - SRpcComp* pComp = (SRpcComp*)pHead->content; - - if (pHead->comp) { - // decompress the content - assert(pComp->reserved == 0); - int contLen = htonl(pComp->contLen); - - // prepare the temporary buffer to decompress message - char* temp = (char*)malloc(contLen + RPC_MSG_OVERHEAD); - pNewHead = (SRpcHead*)(temp + sizeof(SRpcReqContext)); // reserve SRpcReqContext - - if (pNewHead) { - int compLen = rpcContLenFromMsg(pHead->msgLen) - overhead; - int origLen = LZ4_decompress_safe((char*)(pCont + overhead), (char*)pNewHead->content, compLen, contLen); - assert(origLen == contLen); - - memcpy(pNewHead, pHead, sizeof(SRpcHead)); - pNewHead->msgLen = rpcMsgLenFromCont(origLen); - /// rpcFreeMsg(pHead); // free the compressed message buffer - pHead = pNewHead; - tTrace("decomp malloc mem:%p", temp); - } else { - tError("failed to allocate memory to decompress msg, contLen:%d", contLen); - } - } - - return pHead; -} - void transConnCtxDestroy(STransConnCtx* ctx) { free(ctx->ip); free(ctx); @@ -226,9 +130,13 @@ int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf) { uvBuf->base = p->buf; uvBuf->len = CAPACITY; + } else if (p->total == -1 && p->len < CAPACITY) { + uvBuf->base = p->buf + p->len; + uvBuf->len = CAPACITY - p->len; } else { p->cap = p->total; p->buf = realloc(p->buf, p->cap); + uvBuf->base = p->buf + p->len; uvBuf->len = p->cap - p->len; } @@ -257,6 +165,12 @@ int transDestroyBuffer(SConnBuffer* buf) { transClearBuffer(buf); } +int transSetConnOption(uv_tcp_t* stream) { + uv_tcp_nodelay(stream, 1); + int ret = uv_tcp_keepalive(stream, 5, 5); + return ret; +} + SAsyncPool* transCreateAsyncPool(uv_loop_t* loop, int sz, void* arg, AsyncCB cb) { SAsyncPool* pool = calloc(1, sizeof(SAsyncPool)); pool->index = 0; @@ -305,7 +219,7 @@ int transSendAsync(SAsyncPool* pool, queue* q) { if (el > 50) { // tInfo("lock and unlock cost: %d", (int)el); } - return uv_async_send(async); } + #endif diff --git a/source/libs/transport/src/transSrv.c b/source/libs/transport/src/transSrv.c index ce78d83bdf1324284e9516520171ca1602147b83..cb3bbaefec847a764e1059f6d9dc1dbc54825d20 100644 --- a/source/libs/transport/src/transSrv.c +++ b/source/libs/transport/src/transSrv.c @@ -18,11 +18,11 @@ #include "transComm.h" typedef struct SSrvConn { - uv_tcp_t* pTcp; - uv_write_t* pWriter; - uv_timer_t* pTimer; + T_REF_DECLARE() + uv_tcp_t* pTcp; + uv_write_t pWriter; + uv_timer_t pTimer; - // uv_async_t* pWorkerAsync; queue queue; int ref; int persist; // persist connection or not @@ -32,13 +32,12 @@ typedef struct SSrvConn { void* ahandle; // void* hostThrd; SArray* srvMsgs; - // void* pSrvMsg; + + bool broken; // conn broken; struct sockaddr_in addr; struct sockaddr_in locaddr; - // SRpcMsg sendMsg; - // del later char secured; int spi; char info[64]; @@ -49,7 +48,7 @@ typedef struct SSrvConn { typedef struct SSrvMsg { SSrvConn* pConn; - SRpcMsg msg; + STransMsg msg; queue q; } SSrvMsg; @@ -59,24 +58,29 @@ typedef struct SWorkThrdObj { uv_os_fd_t fd; uv_loop_t* loop; SAsyncPool* asyncPool; - // uv_async_t* workerAsync; // + queue msg; - queue conn; pthread_mutex_t msgMtx; - void* pTransInst; + + queue conn; + void* pTransInst; + bool quit; } SWorkThrdObj; typedef struct SServerObj { - pthread_t thread; - uv_tcp_t server; - uv_loop_t* loop; + pthread_t thread; + uv_tcp_t server; + uv_loop_t* loop; + + // work thread info int workerIdx; int numOfThreads; SWorkThrdObj** pThreadObj; - uv_pipe_t** pipe; - uint32_t ip; - uint32_t port; - uv_async_t* pAcceptAsync; // just to quit from from accept thread + + uv_pipe_t** pipe; + uint32_t ip; + uint32_t port; + uv_async_t* pAcceptAsync; // just to quit from from accept thread } SServerObj; static const char* notify = "a"; @@ -87,10 +91,10 @@ static int transAddAuthPart(SSrvConn* pConn, char* msg, int msgLen); static int uvAuthMsg(SSrvConn* pConn, char* msg, int msgLen); static void uvAllocConnBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); -static void uvAllocReadBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); -static void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf); +static void uvAllocRecvBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); +static void uvOnRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf); static void uvOnTimeoutCb(uv_timer_t* handle); -static void uvOnWriteCb(uv_write_t* req, int status); +static void uvOnSendCb(uv_write_t* req, int status); static void uvOnPipeWriteCb(uv_write_t* req, int status); static void uvOnAcceptCb(uv_stream_t* stream, int status); static void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf); @@ -117,7 +121,7 @@ static void* acceptThread(void* arg); static bool addHandleToWorkloop(void* arg); static bool addHandleToAcceptloop(void* arg); -void uvAllocReadBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { +void uvAllocRecvBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { SSrvConn* conn = handle->data; SConnBuffer* pBuf = &conn->readBuf; transAllocBuffer(pBuf, buf); @@ -159,7 +163,7 @@ static int uvAuthMsg(SSrvConn* pConn, char* msg, int len) { tWarn("%s, time diff:%d is too big, msg discarded", pConn->info, delta); code = TSDB_CODE_RPC_INVALID_TIME_STAMP; } else { - if (rpcAuthenticateMsg(pHead, len - TSDB_AUTH_LEN, pDigest->auth, pConn->secret) < 0) { + if (transAuthenticateMsg(pHead, len - TSDB_AUTH_LEN, pDigest->auth, pConn->secret) < 0) { // tDebug("%s, authentication failed, msg discarded", pConn->info); code = TSDB_CODE_RPC_AUTH_FAILURE; } else { @@ -200,43 +204,42 @@ static void uvHandleReq(SSrvConn* pConn) { memcpy(pConn->user, uMsg->user, tListLen(uMsg->user)); memcpy(pConn->secret, uMsg->secret, tListLen(uMsg->secret)); } - - pConn->inType = pHead->msgType; - // assert(transIsReq(pHead->msgType)); - - SRpcInfo* pRpc = (SRpcInfo*)p->shandle; pHead->code = htonl(pHead->code); int32_t dlen = 0; if (transDecompressMsg(NULL, 0, NULL)) { // add compress later - // pHead = rpcDecompressRpcMsg(pHead); + // pHead = rpcDecompresSTransMsg(pHead); } else { pHead->msgLen = htonl(pHead->msgLen); // impl later // } - SRpcMsg rpcMsg; - rpcMsg.contLen = transContLenFromMsg(pHead->msgLen); - rpcMsg.pCont = pHead->content; - rpcMsg.msgType = pHead->msgType; - rpcMsg.code = pHead->code; - rpcMsg.ahandle = NULL; - rpcMsg.handle = pConn; + STransMsg transMsg; + transMsg.contLen = transContLenFromMsg(pHead->msgLen); + transMsg.pCont = pHead->content; + transMsg.msgType = pHead->msgType; + transMsg.code = pHead->code; + transMsg.ahandle = NULL; + transMsg.handle = pConn; transClearBuffer(&pConn->readBuf); - pConn->ref++; - tDebug("server conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pConn, TMSG_INFO(rpcMsg.msgType), + pConn->inType = pHead->msgType; + transRefSrvHandle(pConn); + + tDebug("server conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pConn, TMSG_INFO(transMsg.msgType), inet_ntoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr), - ntohs(pConn->locaddr.sin_port), rpcMsg.contLen); - (*(pRpc->cfp))(pRpc->parent, &rpcMsg, NULL); - // uv_timer_start(pConn->pTimer, uvHandleActivityTimeout, pRpc->idleTime * 10000, 0); + ntohs(pConn->locaddr.sin_port), transMsg.contLen); + + STrans* pTransInst = (STrans*)p->shandle; + (*((STrans*)p->shandle)->cfp)(pTransInst->parent, &transMsg, NULL); + // uv_timer_start(&pConn->pTimer, uvHandleActivityTimeout, pRpc->idleTime * 10000, 0); // auth // validate msg type } -void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) { +void uvOnRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) { // opt SSrvConn* conn = cli->data; SConnBuffer* pBuf = &conn->readBuf; @@ -251,23 +254,20 @@ void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) { } return; } - if (nread == UV_EOF) { - tError("server conn %p read error: %s", conn, uv_err_name(nread)); - if (conn->ref > 1) { - conn->ref++; // ref > 1 signed that write is in progress - } - destroyConn(conn, true); - return; - } if (nread == 0) { return; } - if (nread < 0 || nread != UV_EOF) { - if (conn->ref > 1) { - conn->ref++; // ref > 1 signed that write is in progress - } - tError("server conn %p read error: %s", conn, uv_err_name(nread)); - destroyConn(conn, true); + + tError("server conn %p read error: %s", conn, uv_err_name(nread)); + if (nread < 0) { + conn->broken = true; + transUnrefSrvHandle(conn); + + // if (conn->ref > 1) { + // conn->ref++; // ref > 1 signed that write is in progress + //} + // tError("server conn %p read error: %s", conn, uv_err_name(nread)); + // destroyConn(conn, true); } } void uvAllocConnBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { @@ -281,7 +281,7 @@ void uvOnTimeoutCb(uv_timer_t* handle) { tError("server conn %p time out", pConn); } -void uvOnWriteCb(uv_write_t* req, int status) { +void uvOnSendCb(uv_write_t* req, int status) { SSrvConn* conn = req->data; transClearBuffer(&conn->readBuf); if (status == 0) { @@ -300,10 +300,9 @@ void uvOnWriteCb(uv_write_t* req, int status) { } } else { tError("server conn %p failed to write data, %s", conn, uv_err_name(status)); - // - destroyConn(conn, true); + conn->broken = false; + transUnrefSrvHandle(conn); } - // opt } static void uvOnPipeWriteCb(uv_write_t* req, int status) { if (status == 0) { @@ -311,14 +310,15 @@ static void uvOnPipeWriteCb(uv_write_t* req, int status) { } else { tError("fail to dispatch conn to work thread"); } + free(req); } static void uvPrepareSendData(SSrvMsg* smsg, uv_buf_t* wb) { // impl later; tTrace("server conn %p prepare to send resp", smsg->pConn); - SSrvConn* pConn = smsg->pConn; - SRpcMsg* pMsg = &smsg->msg; + SSrvConn* pConn = smsg->pConn; + STransMsg* pMsg = &smsg->msg; if (pMsg->pCont == 0) { pMsg->pCont = (void*)rpcMallocCont(0); pMsg->contLen = 0; @@ -348,16 +348,19 @@ static void uvStartSendRespInternal(SSrvMsg* smsg) { uvPrepareSendData(smsg, &wb); SSrvConn* pConn = smsg->pConn; - uv_timer_stop(pConn->pTimer); - - // pConn->pSrvMsg = smsg; - // conn->pWriter->data = smsg; - uv_write(pConn->pWriter, (uv_stream_t*)pConn->pTcp, &wb, 1, uvOnWriteCb); + uv_timer_stop(&pConn->pTimer); + uv_write(&pConn->pWriter, (uv_stream_t*)pConn->pTcp, &wb, 1, uvOnSendCb); } static void uvStartSendResp(SSrvMsg* smsg) { // impl SSrvConn* pConn = smsg->pConn; - pConn->ref--; // + + if (pConn->broken == true) { + transUnrefSrvHandle(pConn); + return; + } + transUnrefSrvHandle(pConn); + if (taosArrayGetSize(pConn->srvMsgs) > 0) { tDebug("server conn %p push data to client %s:%d, local info: %s:%d", pConn, inet_ntoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr), ntohs(pConn->locaddr.sin_port)); @@ -382,7 +385,7 @@ static void destroyAllConn(SWorkThrdObj* pThrd) { QUEUE_INIT(h); SSrvConn* c = QUEUE_DATA(h, SSrvConn, queue); - destroyConn(c, true); + transUnrefSrvHandle(c); } } void uvWorkerAsyncCb(uv_async_t* handle) { @@ -390,11 +393,11 @@ void uvWorkerAsyncCb(uv_async_t* handle) { SWorkThrdObj* pThrd = item->pThrd; SSrvConn* conn = NULL; queue wq; + // batch process to avoid to lock/unlock frequently pthread_mutex_lock(&item->mtx); QUEUE_MOVE(&item->qmsg, &wq); pthread_mutex_unlock(&item->mtx); - // pthread_mutex_unlock(&mtx); while (!QUEUE_IS_EMPTY(&wq)) { queue* head = QUEUE_HEAD(&wq); @@ -407,11 +410,15 @@ void uvWorkerAsyncCb(uv_async_t* handle) { } if (msg->pConn == NULL) { free(msg); - - destroyAllConn(pThrd); - - uv_loop_close(pThrd->loop); - uv_stop(pThrd->loop); + bool noConn = QUEUE_IS_EMPTY(&pThrd->conn); + if (noConn == true) { + uv_loop_close(pThrd->loop); + uv_stop(pThrd->loop); + } else { + destroyAllConn(pThrd); + // uv_loop_close(pThrd->loop); + pThrd->quit = true; + } } else { uvStartSendResp(msg); } @@ -419,12 +426,15 @@ void uvWorkerAsyncCb(uv_async_t* handle) { } static void uvAcceptAsyncCb(uv_async_t* async) { SServerObj* srv = async->data; + tDebug("close server port %d", srv->port); uv_close((uv_handle_t*)&srv->server, NULL); uv_stop(srv->loop); } static void uvShutDownCb(uv_shutdown_t* req, int status) { - tDebug("conn failed to shut down: %s", uv_err_name(status)); + if (status != 0) { + tDebug("conn failed to shut down: %s", uv_err_name(status)); + } uv_close((uv_handle_t*)req->handle, uvDestroyConn); free(req); } @@ -482,9 +492,8 @@ void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf) { pConn->pTransInst = pThrd->pTransInst; /* init conn timer*/ - pConn->pTimer = malloc(sizeof(uv_timer_t)); - uv_timer_init(pThrd->loop, pConn->pTimer); - pConn->pTimer->data = pConn; + uv_timer_init(pThrd->loop, &pConn->pTimer); + pConn->pTimer.data = pConn; pConn->hostThrd = pThrd; @@ -493,12 +502,9 @@ void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf) { uv_tcp_init(pThrd->loop, pConn->pTcp); pConn->pTcp->data = pConn; - // uv_tcp_nodelay(pConn->pTcp, 1); - // uv_tcp_keepalive(pConn->pTcp, 1, 1); + pConn->pWriter.data = pConn; - // init write request, just - pConn->pWriter = calloc(1, sizeof(uv_write_t)); - pConn->pWriter->data = pConn; + transSetConnOption((uv_tcp_t*)pConn->pTcp); if (uv_accept(q, (uv_stream_t*)(pConn->pTcp)) == 0) { uv_os_fd_t fd; @@ -508,22 +514,22 @@ void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf) { int addrlen = sizeof(pConn->addr); if (0 != uv_tcp_getpeername(pConn->pTcp, (struct sockaddr*)&pConn->addr, &addrlen)) { tError("server conn %p failed to get peer info", pConn); - destroyConn(pConn, true); + transUnrefSrvHandle(pConn); return; } addrlen = sizeof(pConn->locaddr); if (0 != uv_tcp_getsockname(pConn->pTcp, (struct sockaddr*)&pConn->locaddr, &addrlen)) { tError("server conn %p failed to get local info", pConn); - destroyConn(pConn, true); + transUnrefSrvHandle(pConn); return; } - uv_read_start((uv_stream_t*)(pConn->pTcp), uvAllocReadBufferCb, uvOnReadCb); + uv_read_start((uv_stream_t*)(pConn->pTcp), uvAllocRecvBufferCb, uvOnRecvCb); } else { tDebug("failed to create new connection"); - destroyConn(pConn, true); + transUnrefSrvHandle(pConn); } } @@ -540,7 +546,6 @@ static bool addHandleToWorkloop(void* arg) { return false; } - // SRpcInfo* pRpc = pThrd->shandle; uv_pipe_init(pThrd->loop, pThrd->pipe, 1); uv_pipe_open(pThrd->pipe, pThrd->fd); @@ -599,7 +604,10 @@ static SSrvConn* createConn(void* hThrd) { QUEUE_PUSH(&pThrd->conn, &pConn->queue); pConn->srvMsgs = taosArrayInit(2, sizeof(void*)); // tTrace("conn %p created", pConn); - ++pConn->ref; + + pConn->broken = false; + + transRefSrvHandle(pConn); return pConn; } @@ -607,10 +615,6 @@ static void destroyConn(SSrvConn* conn, bool clear) { if (conn == NULL) { return; } - tTrace("server conn %p try to destroy, ref: %d", conn, conn->ref); - if (--conn->ref > 0) { - return; - } transDestroyBuffer(&conn->readBuf); for (int i = 0; i < taosArrayGetSize(conn->srvMsgs); i++) { @@ -618,25 +622,29 @@ static void destroyConn(SSrvConn* conn, bool clear) { destroySmsg(msg); } conn->srvMsgs = taosArrayDestroy(conn->srvMsgs); - QUEUE_REMOVE(&conn->queue); - if (clear) { tTrace("try to destroy conn %p", conn); - uv_tcp_close_reset(conn->pTcp, uvDestroyConn); - // uv_shutdown_t* req = malloc(sizeof(uv_shutdown_t)); - // uv_shutdown(req, (uv_stream_t*)conn->pTcp, uvShutDownCb); - // uv_unref((uv_handle_t*)conn->pTcp); - // uv_close((uv_handle_t*)conn->pTcp, uvDestroyConn); + uv_shutdown_t* req = malloc(sizeof(uv_shutdown_t)); + uv_shutdown(req, (uv_stream_t*)conn->pTcp, uvShutDownCb); } } static void uvDestroyConn(uv_handle_t* handle) { SSrvConn* conn = handle->data; + if (conn == NULL) { + return; + } + SWorkThrdObj* thrd = conn->hostThrd; + tDebug("server conn %p destroy", conn); - uv_timer_stop(conn->pTimer); - // free(conn->pTimer); + uv_timer_stop(&conn->pTimer); + QUEUE_REMOVE(&conn->queue); free(conn->pTcp); - free(conn->pWriter); free(conn); + + if (thrd->quit && QUEUE_IS_EMPTY(&thrd->conn)) { + uv_loop_close(thrd->loop); + uv_stop(thrd->loop); + } } static int transAddAuthPart(SSrvConn* pConn, char* msg, int msgLen) { STransMsgHead* pHead = (STransMsgHead*)msg; @@ -658,7 +666,7 @@ static int transAddAuthPart(SSrvConn* pConn, char* msg, int msgLen) { return msgLen; } -void* taosInitServer(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle) { +void* transInitServer(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle) { SServerObj* srv = calloc(1, sizeof(SServerObj)); srv->loop = (uv_loop_t*)malloc(sizeof(uv_loop_t)); srv->numOfThreads = numOfThreads; @@ -671,6 +679,7 @@ void* taosInitServer(uint32_t ip, uint32_t port, char* label, int numOfThreads, for (int i = 0; i < srv->numOfThreads; i++) { SWorkThrdObj* thrd = (SWorkThrdObj*)calloc(1, sizeof(SWorkThrdObj)); + thrd->quit = false; srv->pThreadObj[i] = thrd; srv->pipe[i] = (uv_pipe_t*)calloc(2, sizeof(uv_pipe_t)); @@ -709,7 +718,7 @@ void* taosInitServer(uint32_t ip, uint32_t port, char* label, int numOfThreads, return srv; End: - taosCloseServer(srv); + transCloseServer(srv); return NULL; } @@ -720,8 +729,6 @@ void destroyWorkThrd(SWorkThrdObj* pThrd) { pthread_join(pThrd->thread, NULL); free(pThrd->loop); transDestroyAsyncPool(pThrd->asyncPool); - - // free(pThrd->workerAsync); free(pThrd); } void sendQuitToWorkThrd(SWorkThrdObj* pThrd) { @@ -731,7 +738,7 @@ void sendQuitToWorkThrd(SWorkThrdObj* pThrd) { transSendAsync(pThrd->asyncPool, &srvMsg->q); } -void taosCloseServer(void* arg) { +void transCloseServer(void* arg) { // impl later SServerObj* srv = arg; for (int i = 0; i < srv->numOfThreads; i++) { @@ -755,7 +762,29 @@ void taosCloseServer(void* arg) { free(srv); } -void rpcSendResponse(const SRpcMsg* pMsg) { +void transRefSrvHandle(void* handle) { + if (handle == NULL) { + return; + } + SSrvConn* conn = handle; + + int ref = T_REF_INC((SSrvConn*)handle); + UNUSED(ref); +} + +void transUnrefSrvHandle(void* handle) { + if (handle == NULL) { + return; + } + int ref = T_REF_DEC((SSrvConn*)handle); + tDebug("handle %p ref count: %d", handle, ref); + + if (ref == 0) { + destroyConn((SSrvConn*)handle, true); + } + // unref srv handle +} +void transSendResponse(const STransMsg* pMsg) { if (pMsg->handle == NULL) { return; } @@ -768,14 +797,12 @@ void rpcSendResponse(const SRpcMsg* pMsg) { tTrace("server conn %p start to send resp", pConn); transSendAsync(pThrd->asyncPool, &srvMsg->q); } - -int rpcGetConnInfo(void* thandle, SRpcConnInfo* pInfo) { - SSrvConn* pConn = thandle; - +int transGetConnInfo(void* thandle, STransHandleInfo* pInfo) { + SSrvConn* pConn = thandle; struct sockaddr_in addr = pConn->addr; + pInfo->clientIp = (uint32_t)(addr.sin_addr.s_addr); pInfo->clientPort = ntohs(addr.sin_port); - tstrncpy(pInfo->user, pConn->user, sizeof(pInfo->user)); return 0; } diff --git a/source/libs/transport/test/CMakeLists.txt b/source/libs/transport/test/CMakeLists.txt index b4f50219ff574c2dceb5985f0bd4896b5d329f00..b29bad07f08982c7644287d4ef9fa98cf10245bc 100644 --- a/source/libs/transport/test/CMakeLists.txt +++ b/source/libs/transport/test/CMakeLists.txt @@ -3,7 +3,6 @@ add_executable(client "") add_executable(server "") add_executable(transUT "") add_executable(syncClient "") -add_executable(pushClient "") add_executable(pushServer "") target_sources(transUT @@ -27,10 +26,6 @@ target_sources (syncClient "syncClient.c" ) -target_sources(pushClient - PRIVATE - "pushClient.c" -) target_sources(pushServer PRIVATE "pushServer.c" @@ -102,19 +97,6 @@ target_link_libraries (syncClient transport ) -target_include_directories(pushClient - PUBLIC - "${CMAKE_SOURCE_DIR}/include/libs/transport" - "${CMAKE_CURRENT_SOURCE_DIR}/../inc" -) -target_link_libraries (pushClient - os - util - common - gtest_main - transport -) - target_include_directories(pushServer PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/transport" diff --git a/source/libs/transport/test/pushClient.c b/source/libs/transport/test/pushClient.c deleted file mode 100644 index f4babc998059aee1aa0aac109476995a840fc045..0000000000000000000000000000000000000000 --- a/source/libs/transport/test/pushClient.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ -#include - -#include -#include "os.h" -#include "rpcLog.h" -#include "taoserror.h" -#include "tglobal.h" -#include "trpc.h" -#include "tutil.h" - -typedef struct { - int index; - SEpSet epSet; - int num; - int numOfReqs; - int msgSize; - tsem_t rspSem; - tsem_t * pOverSem; - pthread_t thread; - void * pRpc; -} SInfo; -static void processResponse(void *pParent, SRpcMsg *pMsg, SEpSet *pEpSet) { - SInfo *pInfo = (SInfo *)pMsg->ahandle; - tDebug("thread:%d, response is received, type:%d contLen:%d code:0x%x", pInfo->index, pMsg->msgType, pMsg->contLen, - pMsg->code); - - if (pEpSet) pInfo->epSet = *pEpSet; - - rpcFreeCont(pMsg->pCont); - // tsem_post(&pInfo->rspSem); - tsem_post(&pInfo->rspSem); -} - -static int tcount = 0; - -typedef struct SPushArg { - tsem_t sem; -} SPushArg; -// ping -int pushCallback(void *arg, SRpcMsg *msg) { - SPushArg *push = arg; - tsem_post(&push->sem); -} -SRpcPush *createPushArg() { - SRpcPush *push = calloc(1, sizeof(SRpcPush)); - push->arg = calloc(1, sizeof(SPushArg)); - - tsem_init(&(((SPushArg *)push->arg)->sem), 0, 0); - push->callback = pushCallback; - return push; -} -static void *sendRequest(void *param) { - SInfo * pInfo = (SInfo *)param; - SRpcMsg rpcMsg = {0}; - - tDebug("thread:%d, start to send request", pInfo->index); - - tDebug("thread:%d, reqs: %d", pInfo->index, pInfo->numOfReqs); - int u100 = 0; - int u500 = 0; - int u1000 = 0; - int u10000 = 0; - - while (pInfo->numOfReqs == 0 || pInfo->num < pInfo->numOfReqs) { - SRpcPush *push = createPushArg(); - pInfo->num++; - rpcMsg.pCont = rpcMallocCont(pInfo->msgSize); - rpcMsg.contLen = pInfo->msgSize; - rpcMsg.ahandle = pInfo; - rpcMsg.msgType = 1; - rpcMsg.push = push; - // tDebug("thread:%d, send request, contLen:%d num:%d", pInfo->index, pInfo->msgSize, pInfo->num); - int64_t start = taosGetTimestampUs(); - rpcSendRequest(pInfo->pRpc, &pInfo->epSet, &rpcMsg, NULL); - if (pInfo->num % 20000 == 0) tInfo("thread:%d, %d requests have been sent", pInfo->index, pInfo->num); - tsem_wait(&pInfo->rspSem); // ping->pong - // tsem_wait(&pInfo->rspSem); - SPushArg *arg = push->arg; - /// e - tsem_wait(&arg->sem); // push callback - - // query_fetch(client->h) - int64_t end = taosGetTimestampUs() - start; - if (end <= 100) { - u100++; - } else if (end > 100 && end <= 500) { - u500++; - } else if (end > 500 && end < 1000) { - u1000++; - } else { - u10000++; - } - - tDebug("recv response succefully"); - - // usleep(100000000); - } - - tError("send and recv sum: %d, %d, %d, %d", u100, u500, u1000, u10000); - tDebug("thread:%d, it is over", pInfo->index); - tcount++; - - return NULL; -} - -int main(int argc, char *argv[]) { - SRpcInit rpcInit; - SEpSet epSet; - int msgSize = 128; - int numOfReqs = 0; - int appThreads = 1; - char serverIp[40] = "127.0.0.1"; - char secret[20] = "mypassword"; - struct timeval systemTime; - int64_t startTime, endTime; - pthread_attr_t thattr; - - // server info - epSet.inUse = 0; - addEpIntoEpSet(&epSet, serverIp, 7000); - addEpIntoEpSet(&epSet, "192.168.0.1", 7000); - - // client info - memset(&rpcInit, 0, sizeof(rpcInit)); - rpcInit.localPort = 0; - rpcInit.label = "APP"; - rpcInit.numOfThreads = 1; - rpcInit.cfp = processResponse; - rpcInit.sessions = 100; - rpcInit.idleTime = 100; - rpcInit.user = "michael"; - rpcInit.secret = secret; - rpcInit.ckey = "key"; - rpcInit.spi = 1; - rpcInit.connType = TAOS_CONN_CLIENT; - - for (int i = 1; i < argc; ++i) { - if (strcmp(argv[i], "-p") == 0 && i < argc - 1) { - epSet.eps[0].port = atoi(argv[++i]); - } else if (strcmp(argv[i], "-i") == 0 && i < argc - 1) { - tstrncpy(epSet.eps[0].fqdn, argv[++i], sizeof(epSet.eps[0].fqdn)); - } else if (strcmp(argv[i], "-t") == 0 && i < argc - 1) { - rpcInit.numOfThreads = atoi(argv[++i]); - } else if (strcmp(argv[i], "-m") == 0 && i < argc - 1) { - msgSize = atoi(argv[++i]); - } else if (strcmp(argv[i], "-s") == 0 && i < argc - 1) { - rpcInit.sessions = atoi(argv[++i]); - } else if (strcmp(argv[i], "-n") == 0 && i < argc - 1) { - numOfReqs = atoi(argv[++i]); - } else if (strcmp(argv[i], "-a") == 0 && i < argc - 1) { - appThreads = atoi(argv[++i]); - } else if (strcmp(argv[i], "-o") == 0 && i < argc - 1) { - tsCompressMsgSize = atoi(argv[++i]); - } else if (strcmp(argv[i], "-u") == 0 && i < argc - 1) { - rpcInit.user = argv[++i]; - } else if (strcmp(argv[i], "-k") == 0 && i < argc - 1) { - rpcInit.secret = argv[++i]; - } else if (strcmp(argv[i], "-spi") == 0 && i < argc - 1) { - rpcInit.spi = atoi(argv[++i]); - } else if (strcmp(argv[i], "-d") == 0 && i < argc - 1) { - rpcDebugFlag = atoi(argv[++i]); - } else { - printf("\nusage: %s [options] \n", argv[0]); - printf(" [-i ip]: first server IP address, default is:%s\n", serverIp); - printf(" [-p port]: server port number, default is:%d\n", epSet.eps[0].port); - printf(" [-t threads]: number of rpc threads, default is:%d\n", rpcInit.numOfThreads); - printf(" [-s sessions]: number of rpc sessions, default is:%d\n", rpcInit.sessions); - printf(" [-m msgSize]: message body size, default is:%d\n", msgSize); - printf(" [-a threads]: number of app threads, default is:%d\n", appThreads); - printf(" [-n requests]: number of requests per thread, default is:%d\n", numOfReqs); - printf(" [-o compSize]: compression message size, default is:%d\n", tsCompressMsgSize); - printf(" [-u user]: user name for the connection, default is:%s\n", rpcInit.user); - printf(" [-k secret]: password for the connection, default is:%s\n", rpcInit.secret); - printf(" [-spi SPI]: security parameter index, default is:%d\n", rpcInit.spi); - printf(" [-d debugFlag]: debug flag, default:%d\n", rpcDebugFlag); - printf(" [-h help]: print out this help\n\n"); - exit(0); - } - } - - taosInitLog("client.log", 10); - - void *pRpc = rpcOpen(&rpcInit); - if (pRpc == NULL) { - tError("failed to initialize RPC"); - return -1; - } - - tInfo("client is initialized"); - tInfo("threads:%d msgSize:%d requests:%d", appThreads, msgSize, numOfReqs); - - gettimeofday(&systemTime, NULL); - startTime = systemTime.tv_sec * 1000000 + systemTime.tv_usec; - - SInfo *pInfo = (SInfo *)calloc(1, sizeof(SInfo) * appThreads); - - pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); - - for (int i = 0; i < appThreads; ++i) { - pInfo->index = i; - pInfo->epSet = epSet; - pInfo->numOfReqs = numOfReqs; - pInfo->msgSize = msgSize; - tsem_init(&pInfo->rspSem, 0, 0); - pInfo->pRpc = pRpc; - pthread_create(&pInfo->thread, &thattr, sendRequest, pInfo); - pInfo++; - } - - do { - usleep(1); - } while (tcount < appThreads); - - gettimeofday(&systemTime, NULL); - endTime = systemTime.tv_sec * 1000000 + systemTime.tv_usec; - float usedTime = (endTime - startTime) / 1000.0f; // mseconds - - tInfo("it takes %.3f mseconds to send %d requests to server", usedTime, numOfReqs * appThreads); - tInfo("Performance: %.3f requests per second, msgSize:%d bytes", 1000.0 * numOfReqs * appThreads / usedTime, msgSize); - - int ch = getchar(); - UNUSED(ch); - - taosCloseLog(); - - return 0; -} diff --git a/source/libs/transport/test/pushServer.c b/source/libs/transport/test/pushServer.c index c763b7bd8adf8acfc9b3d72aa5defe78ca1fa11d..f4ad73f743a10eb20b726ba27ed6f44dbc0e1e2b 100644 --- a/source/libs/transport/test/pushServer.c +++ b/source/libs/transport/test/pushServer.c @@ -77,7 +77,7 @@ void processShellMsg() { taosFreeQitem(pRpcMsg); { - // sleep(1); + // taosSsleep(1); SRpcMsg nRpcMsg = {0}; nRpcMsg.pCont = rpcMallocCont(msgSize); nRpcMsg.contLen = msgSize; @@ -176,7 +176,7 @@ int main(int argc, char *argv[]) { tError("failed to start RPC server"); return -1; } - // sleep(5); + // taosSsleep(5); tInfo("RPC server is running, ctrl-c to exit"); diff --git a/source/libs/transport/test/rclient.c b/source/libs/transport/test/rclient.c index 6fc935cb613c7341296549624b30d71b815d0584..c6ff2480efa9c44a5ba9a6526c1934c67baf6cb8 100644 --- a/source/libs/transport/test/rclient.c +++ b/source/libs/transport/test/rclient.c @@ -84,7 +84,7 @@ static void *sendRequest(void *param) { tDebug("recv response succefully"); - // usleep(100000000); + // taosSsleep(100); } tError("send and recv sum: %d, %d, %d, %d", u100, u500, u1000, u10000); @@ -124,6 +124,7 @@ int main(int argc, char *argv[]) { rpcInit.ckey = "key"; rpcInit.spi = 1; rpcInit.connType = TAOS_CONN_CLIENT; + rpcDebugFlag = 143; for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "-p") == 0 && i < argc - 1) { @@ -180,7 +181,7 @@ int main(int argc, char *argv[]) { tInfo("client is initialized"); tInfo("threads:%d msgSize:%d requests:%d", appThreads, msgSize, numOfReqs); - gettimeofday(&systemTime, NULL); + taosGetTimeOfDay(&systemTime); startTime = systemTime.tv_sec * 1000000 + systemTime.tv_usec; SInfo *pInfo = (SInfo *)calloc(1, sizeof(SInfo) * appThreads); @@ -200,10 +201,10 @@ int main(int argc, char *argv[]) { } do { - usleep(1); + taosUsleep(1); } while (tcount < appThreads); - gettimeofday(&systemTime, NULL); + taosGetTimeOfDay(&systemTime); endTime = systemTime.tv_sec * 1000000 + systemTime.tv_usec; float usedTime = (endTime - startTime) / 1000.0f; // mseconds diff --git a/source/libs/transport/test/rsclient.c b/source/libs/transport/test/rsclient.c index 26a02eb05b7b704e32025731238453ffc3daece9..1fe13a35b1bd33e17f3b6a452d497caedf0e899c 100644 --- a/source/libs/transport/test/rsclient.c +++ b/source/libs/transport/test/rsclient.c @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) { tInfo("client is initialized"); - gettimeofday(&systemTime, NULL); + taosGetTimeOfDay(&systemTime); startTime = systemTime.tv_sec*1000000 + systemTime.tv_usec; SInfo *pInfo = (SInfo *)calloc(1, sizeof(SInfo)*appThreads); @@ -178,10 +178,10 @@ int main(int argc, char *argv[]) { } do { - usleep(1); + taosUsleep(1); } while ( tcount < appThreads); - gettimeofday(&systemTime, NULL); + taosGetTimeOfDay(&systemTime); endTime = systemTime.tv_sec*1000000 + systemTime.tv_usec; float usedTime = (endTime - startTime)/1000.0; // mseconds diff --git a/source/libs/transport/test/rserver.c b/source/libs/transport/test/rserver.c index da5284b5c50b4d24c190955ced72a6ec6f84e021..3a086371b0199d580b745b832809c3032ab0b304 100644 --- a/source/libs/transport/test/rserver.c +++ b/source/libs/transport/test/rserver.c @@ -125,6 +125,8 @@ int main(int argc, char *argv[]) { rpcInit.idleTime = 2 * 1500; rpcInit.afp = retrieveAuthInfo; + rpcDebugFlag = 143; + for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "-p") == 0 && i < argc - 1) { rpcInit.localPort = atoi(argv[++i]); diff --git a/source/libs/transport/test/syncClient.c b/source/libs/transport/test/syncClient.c index f43fa7aae6a1f494c5e7b783ec14f5251616eeeb..b3c2f6ebdc6de3352259e52bf93322bfc2eb01ea 100644 --- a/source/libs/transport/test/syncClient.c +++ b/source/libs/transport/test/syncClient.c @@ -85,7 +85,7 @@ static void *sendRequest(void *param) { tDebug("recv response succefully"); - // usleep(100000000); + // taosSsleep(100); } tError("send and recv sum: %d, %d, %d, %d", u100, u500, u1000, u10000); @@ -181,7 +181,7 @@ int main(int argc, char *argv[]) { tInfo("client is initialized"); tInfo("threads:%d msgSize:%d requests:%d", appThreads, msgSize, numOfReqs); - gettimeofday(&systemTime, NULL); + taosGetTimeOfDay(&systemTime); startTime = systemTime.tv_sec * 1000000 + systemTime.tv_usec; SInfo *pInfo = (SInfo *)calloc(1, sizeof(SInfo) * appThreads); @@ -201,10 +201,10 @@ int main(int argc, char *argv[]) { } do { - usleep(1); + taosUsleep(1); } while (tcount < appThreads); - gettimeofday(&systemTime, NULL); + taosGetTimeOfDay(&systemTime); endTime = systemTime.tv_sec * 1000000 + systemTime.tv_usec; float usedTime = (endTime - startTime) / 1000.0f; // mseconds diff --git a/source/libs/transport/test/transUT.cc b/source/libs/transport/test/transUT.cc index 5edddb006bba8dcc24af4f94996eece4a0e4f5dd..fa20327003d82095857fe4cf60c3e3b5840c1d0d 100644 --- a/source/libs/transport/test/transUT.cc +++ b/source/libs/transport/test/transUT.cc @@ -29,24 +29,25 @@ const char *ckey = "ckey"; class Server; int port = 7000; // server process +typedef void (*CB)(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet); static void processReq(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet); // client process; static void processResp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet); class Client { public: void Init(int nThread) { - memset(&rpcInit, 0, sizeof(rpcInit)); - rpcInit.localPort = 0; - rpcInit.label = (char *)label; - rpcInit.numOfThreads = nThread; - rpcInit.cfp = processResp; - rpcInit.user = (char *)user; - rpcInit.secret = (char *)secret; - rpcInit.ckey = (char *)ckey; - rpcInit.spi = 1; - rpcInit.parent = this; - rpcInit.connType = TAOS_CONN_CLIENT; - this->transCli = rpcOpen(&rpcInit); + memset(&rpcInit_, 0, sizeof(rpcInit_)); + rpcInit_.localPort = 0; + rpcInit_.label = (char *)label; + rpcInit_.numOfThreads = nThread; + rpcInit_.cfp = processResp; + rpcInit_.user = (char *)user; + rpcInit_.secret = (char *)secret; + rpcInit_.ckey = (char *)ckey; + rpcInit_.spi = 1; + rpcInit_.parent = this; + rpcInit_.connType = TAOS_CONN_CLIENT; + this->transCli = rpcOpen(&rpcInit_); tsem_init(&this->sem, 0, 0); } void SetResp(SRpcMsg *pMsg) { @@ -55,9 +56,27 @@ class Client { } SRpcMsg *Resp() { return &this->resp; } - void Restart() { + void Restart(CB cb) { + rpcClose(this->transCli); + rpcInit_.cfp = cb; + this->transCli = rpcOpen(&rpcInit_); + } + void setPersistFP(bool (*pfp)(void *parent, tmsg_t msgType)) { + rpcClose(this->transCli); + rpcInit_.pfp = pfp; + this->transCli = rpcOpen(&rpcInit_); + } + void setConstructFP(void *(*mfp)(void *parent, tmsg_t msgType)) { rpcClose(this->transCli); - this->transCli = rpcOpen(&rpcInit); + rpcInit_.mfp = mfp; + this->transCli = rpcOpen(&rpcInit_); + } + void setPAndMFp(bool (*pfp)(void *parent, tmsg_t msgType), void *(*mfp)(void *parent, tmsg_t msgType)) { + rpcClose(this->transCli); + + rpcInit_.pfp = pfp; + rpcInit_.mfp = mfp; + this->transCli = rpcOpen(&rpcInit_); } void SendAndRecv(SRpcMsg *req, SRpcMsg *resp) { @@ -79,7 +98,7 @@ class Client { private: tsem_t sem; - SRpcInit rpcInit; + SRpcInit rpcInit_; void * transCli; SRpcMsg resp; }; @@ -133,39 +152,56 @@ static void processResp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { client->SetResp(pMsg); client->SemPost(); } + +static void initEnv() { + dDebugFlag = 143; + vDebugFlag = 0; + mDebugFlag = 143; + cDebugFlag = 0; + jniDebugFlag = 0; + tmrDebugFlag = 143; + uDebugFlag = 143; + rpcDebugFlag = 143; + qDebugFlag = 0; + wDebugFlag = 0; + sDebugFlag = 0; + tsdbDebugFlag = 0; + tsLogEmbedded = 1; + tsAsyncLog = 0; + + std::string path = "/tmp/transport"; + taosRemoveDir(path.c_str()); + taosMkDir(path.c_str()); + + tstrncpy(tsLogDir, path.c_str(), PATH_MAX); + if (taosInitLog("taosdlog", 1) != 0) { + printf("failed to init log file\n"); + } +} class TransObj { public: TransObj() { - dDebugFlag = 143; - vDebugFlag = 0; - mDebugFlag = 143; - cDebugFlag = 0; - jniDebugFlag = 0; - tmrDebugFlag = 143; - uDebugFlag = 143; - rpcDebugFlag = 143; - qDebugFlag = 0; - wDebugFlag = 0; - sDebugFlag = 0; - tsdbDebugFlag = 0; - tsLogEmbedded = 1; - tsAsyncLog = 0; - - std::string path = "/tmp/transport"; - taosRemoveDir(path.c_str()); - taosMkDir(path.c_str()); - - tstrncpy(tsLogDir, path.c_str(), PATH_MAX); - if (taosInitLog("taosdlog", 1) != 0) { - printf("failed to init log file\n"); - } + initEnv(); cli = new Client; cli->Init(1); srv = new Server; srv->Start(); } - void RestartCli() { cli->Restart(); } + + void RestartCli(CB cb) { cli->Restart(cb); } void StopSrv() { srv->Stop(); } + void SetCliPersistFp(bool (*pfp)(void *parent, tmsg_t msgType)) { + // do nothing + cli->setPersistFP(pfp); + } + void SetCliMFp(void *(*mfp)(void *parent, tmsg_t msgType)) { + // do nothing + cli->setConstructFP(mfp); + } + void SetMAndPFp(bool (*pfp)(void *parent, tmsg_t msgType), void *(*mfp)(void *parent, tmsg_t msgType)) { + // do nothing + cli->setPAndMFp(pfp, mfp); + } void RestartSrv() { srv->Restart(); } void cliSendAndRecv(SRpcMsg *req, SRpcMsg *resp) { cli->SendAndRecv(req, resp); } ~TransObj() { @@ -191,16 +227,16 @@ class TransEnv : public ::testing::Test { TransObj *tr = NULL; }; -// TEST_F(TransEnv, 01sendAndRec) { -// for (int i = 0; i < 1; i++) { -// SRpcMsg req = {0}, resp = {0}; -// req.msgType = 0; -// req.pCont = rpcMallocCont(10); -// req.contLen = 10; -// tr->cliSendAndRecv(&req, &resp); -// assert(resp.code == 0); -// } -//} +TEST_F(TransEnv, 01sendAndRec) { + for (int i = 0; i < 1; i++) { + SRpcMsg req = {0}, resp = {0}; + req.msgType = 0; + req.pCont = rpcMallocCont(10); + req.contLen = 10; + tr->cliSendAndRecv(&req, &resp); + assert(resp.code == 0); + } +} TEST_F(TransEnv, 02StopServer) { for (int i = 0; i < 1; i++) { @@ -218,6 +254,31 @@ TEST_F(TransEnv, 02StopServer) { tr->StopSrv(); // tr->RestartSrv(); tr->cliSendAndRecv(&req, &resp); - assert(resp.code != 0); } +TEST_F(TransEnv, clientUserDefined) {} + +TEST_F(TransEnv, cliPersistHandle) { + // impl late +} +TEST_F(TransEnv, srvPersistHandle) { + // impl later +} + +TEST_F(TransEnv, srvPersisHandleExcept) { + // conn breken + // +} +TEST_F(TransEnv, cliPersisHandleExcept) { + // conn breken +} + +TEST_F(TransEnv, multiCliPersisHandleExcept) { + // conn breken +} +TEST_F(TransEnv, multiSrvPersisHandleExcept) { + // conn breken +} +TEST_F(TransEnv, queryExcept) { + // query and conn is broken +} diff --git a/source/libs/wal/src/walMeta.c b/source/libs/wal/src/walMeta.c index 2a4f3497e4806e905ac416189b2b0b0950010bf6..248f758787d277f0b319d6e89f09a1fde925b80f 100644 --- a/source/libs/wal/src/walMeta.c +++ b/source/libs/wal/src/walMeta.c @@ -130,16 +130,16 @@ int walCheckAndRepairMeta(SWal* pWal) { regcomp(&logRegPattern, logPattern, REG_EXTENDED); regcomp(&idxRegPattern, idxPattern, REG_EXTENDED); - DIR* dir = opendir(pWal->path); - if (dir == NULL) { + TdDirPtr pDir = taosOpenDir(pWal->path); + if (pDir == NULL) { wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno)); return -1; } // scan log files and build new meta - struct dirent* ent; - while ((ent = readdir(dir)) != NULL) { - char* name = basename(ent->d_name); + TdDirEntryPtr pDirEntry; + while ((pDirEntry = taosReadDir(pDir)) != NULL) { + char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry)); int code = regexec(&logRegPattern, name, 0, NULL, 0); if (code == 0) { SWalFileInfo fileInfo; @@ -149,7 +149,7 @@ int walCheckAndRepairMeta(SWal* pWal) { } } - closedir(dir); + taosCloseDir(pDir); regfree(&logRegPattern); regfree(&idxRegPattern); @@ -337,25 +337,25 @@ static int walFindCurMetaVer(SWal* pWal) { regex_t walMetaRegexPattern; regcomp(&walMetaRegexPattern, pattern, REG_EXTENDED); - DIR* dir = opendir(pWal->path); - if (dir == NULL) { + TdDirPtr pDir = taosOpenDir(pWal->path); + if (pDir == NULL) { wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno)); return -1; } - struct dirent* ent; + TdDirEntryPtr pDirEntry; // find existing meta-ver[x].json int metaVer = -1; - while ((ent = readdir(dir)) != NULL) { - char* name = basename(ent->d_name); + while ((pDirEntry = taosReadDir(pDir)) != NULL) { + char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry)); int code = regexec(&walMetaRegexPattern, name, 0, NULL, 0); if (code == 0) { sscanf(name, "meta-ver%d", &metaVer); break; } } - closedir(dir); + taosCloseDir(pDir); regfree(&walMetaRegexPattern); return metaVer; } diff --git a/source/libs/wal/test/walMetaTest.cpp b/source/libs/wal/test/walMetaTest.cpp index 3908c97175b2c56ca3aada9b150a7af5f9ece2fa..69ae83154acc7bbdbedc1f05654bbf8993c5c5e7 100644 --- a/source/libs/wal/test/walMetaTest.cpp +++ b/source/libs/wal/test/walMetaTest.cpp @@ -305,7 +305,7 @@ TEST_F(WalKeepEnv, readHandleRead) { ASSERT_EQ(code, 0); } for (int i = 0; i < 1000; i++) { - int ver = rand() % 100; + int ver = taosRand() % 100; code = walReadWithHandle(pRead, ver); ASSERT_EQ(code, 0); @@ -357,7 +357,7 @@ TEST_F(WalRetentionEnv, repairMeta1) { ASSERT(pRead != NULL); for (int i = 0; i < 1000; i++) { - int ver = rand() % 100; + int ver = taosRand() % 100; code = walReadWithHandle(pRead, ver); ASSERT_EQ(code, 0); @@ -387,7 +387,7 @@ TEST_F(WalRetentionEnv, repairMeta1) { } for (int i = 0; i < 1000; i++) { - int ver = rand() % 200; + int ver = taosRand() % 200; code = walReadWithHandle(pRead, ver); ASSERT_EQ(code, 0); diff --git a/source/os/CMakeLists.txt b/source/os/CMakeLists.txt index e52f349338f793b61d8bb9d0e5fb69b6ee548297..27906c262753f2bf02bd9cd09b4ca9227ba26bba 100644 --- a/source/os/CMakeLists.txt +++ b/source/os/CMakeLists.txt @@ -3,7 +3,9 @@ add_library(os STATIC ${OS_SRC}) target_include_directories( os PUBLIC "${CMAKE_SOURCE_DIR}/include/os" - PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include" + PRIVATE "${CMAKE_SOURCE_DIR}/include" + PRIVATE "${CMAKE_SOURCE_DIR}/include/util" + PRIVATE "${CMAKE_SOURCE_DIR}/contrib/pthread-win32" ) target_link_libraries( os pthread dl rt m diff --git a/source/os/src/osDir.c b/source/os/src/osDir.c index 7d7382d83fdfbb98c354e864c95c971eb379a2ba..b4058b3c0ed3218694e24ad6ce429064d329ff03 100644 --- a/source/os/src/osDir.c +++ b/source/os/src/osDir.c @@ -14,6 +14,7 @@ */ #define _DEFAULT_SOURCE +#define ALLOW_FORBID_FUNC #include "os.h" #include "osString.h" @@ -36,6 +37,10 @@ #include #include +typedef struct dirent dirent; +typedef struct DIR TdDir; +typedef struct dirent TdDirent; + void taosRemoveDir(const char *dirname) { DIR *dir = opendir(dirname); if (dir == NULL) return; @@ -149,4 +154,47 @@ bool taosIsDir(const char *dirname) { return false; } +char* taosDirName(char *name) { + return dirname(name); +} + +char* taosDirEntryBaseName(char *name) { + return basename(name); +} + +TdDirPtr taosOpenDir(const char *dirname) { + if (dirname == NULL) { + return NULL; + } + return (TdDirPtr)opendir(dirname); +} + +TdDirEntryPtr taosReadDir(TdDirPtr pDir) { + if (pDir == NULL) { + return NULL; + } + return (TdDirEntryPtr)readdir((DIR*)pDir); +} + +bool taosDirEntryIsDir(TdDirEntryPtr pDirEntry) { + if (pDirEntry == NULL) { + return false; + } + return (((dirent*)pDirEntry)->d_type & DT_DIR) != 0; +} + +char* taosGetDirEntryName(TdDirEntryPtr pDirEntry) { + if (pDirEntry == NULL) { + return NULL; + } + return ((dirent*)pDirEntry)->d_name; +} + +int32_t taosCloseDir(TdDirPtr pDir) { + if (pDir == NULL) { + return -1; + } + return closedir((DIR*)pDir); +} + #endif diff --git a/source/os/src/osEnv.c b/source/os/src/osEnv.c index 0b2fe904b37427b85dbf44f847af21c5a46472d6..63fa60021752686ea80a591160c6b7e2f65ae2a8 100644 --- a/source/os/src/osEnv.c +++ b/source/os/src/osEnv.c @@ -38,7 +38,7 @@ float tsNumOfCores = 0; int64_t tsTotalMemoryKB = 0; void osInit() { - srand(taosSafeRand()); + taosSeedRand(taosSafeRand()); taosGetSystemLocale(tsLocale, tsCharset); taosGetSystemTimezone(tsTimezone); taosSetSystemTimezone(tsTimezone, tsTimezone, &tsDaylight); diff --git a/source/os/src/osFile.c b/source/os/src/osFile.c index fb926610bd41d68113508584587587e8de620207..6472202bf98df8999e0fb4d188b652b0356c0864 100644 --- a/source/os/src/osFile.c +++ b/source/os/src/osFile.c @@ -265,7 +265,7 @@ TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) { return NULL; } #if FILE_WITH_LOCK - pthread_rwlock_init(&(pFile->rwlock),NULL); + pthread_rwlock_init(&(pFile->rwlock), NULL); #endif pFile->fd = fd; pFile->fp = fp; @@ -735,6 +735,7 @@ void taosFprintfFile(TdFilePtr pFile, const char *format, ...) { fflush(pFile->fp); } +#if !defined(WINDOWS) void *taosMmapReadOnlyFile(TdFilePtr pFile, int64_t length) { if (pFile == NULL) { return NULL; @@ -744,6 +745,7 @@ void *taosMmapReadOnlyFile(TdFilePtr pFile, int64_t length) { void *ptr = mmap(NULL, length, PROT_READ, MAP_SHARED, pFile->fd, 0); return ptr; } +#endif bool taosValidFile(TdFilePtr pFile) { return pFile != NULL; } @@ -773,6 +775,9 @@ int32_t taosEOFFile(TdFilePtr pFile) { return feof(pFile->fp); } + +#if !defined(WINDOWS) + bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) { int flags = 0; @@ -790,4 +795,7 @@ bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) { return access(pathname, flags) == 0; } -bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); }; \ No newline at end of file + +bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); }; + +#endif // WINDOWS diff --git a/source/os/src/osLocale.c b/source/os/src/osLocale.c index 47546f7deb2ddaf03106fd63e6f82a716f23a7fd..e9d6ed7c5424aff687175391942171f57c43c5f8 100644 --- a/source/os/src/osLocale.c +++ b/source/os/src/osLocale.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "osLocale.h" diff --git a/source/os/src/osRand.c b/source/os/src/osRand.c index b81e41b3cf3b9631ee778a233f9d12cddfe534ed..847f3a52a60da49f87be579cea8f9a4e008918a5 100644 --- a/source/os/src/osRand.c +++ b/source/os/src/osRand.c @@ -12,7 +12,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ - +#define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "os.h" #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) @@ -21,19 +21,23 @@ #include #endif +void taosSeedRand(uint32_t seed) { return srand(seed); } + uint32_t taosRand(void) { return rand(); } +uint32_t taosRandR(uint32_t *pSeed) { return rand_r(pSeed); } + uint32_t taosSafeRand(void) { TdFilePtr pFile; int seed; pFile = taosOpenFile("/dev/urandom", TD_FILE_READ); if (pFile == NULL) { - seed = (int)time(0); + seed = (int)taosGetTimestampSec(); } else { int len = taosReadFile(pFile, &seed, sizeof(seed)); if (len < 0) { - seed = (int)time(0); + seed = (int)taosGetTimestampSec(); } taosCloseFile(&pFile); } diff --git a/source/os/src/osSemaphore.c b/source/os/src/osSemaphore.c index 0d7066b5c8eac3bc7e312651ef0b1888410d62f2..e5b506e8d835375205a2ffc18a7242d1e65506a1 100644 --- a/source/os/src/osSemaphore.c +++ b/source/os/src/osSemaphore.c @@ -99,7 +99,7 @@ static void *sem_thread_routine(void *arg) { sem_port = mach_task_self(); kern_return_t ret = semaphore_create(sem_port, &sem_exit, SYNC_POLICY_FIFO, 0); if (ret != KERN_SUCCESS) { - fprintf(stderr, "==%s[%d]%s()==failed to create sem_exit\n", basename(__FILE__), __LINE__, __func__); + fprintf(stderr, "==%s[%d]%s()==failed to create sem_exit\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__); sem_inited = -1; return NULL; } @@ -112,7 +112,7 @@ static void once_init(void) { int r = 0; r = pthread_create(&sem_thread, NULL, sem_thread_routine, NULL); if (r) { - fprintf(stderr, "==%s[%d]%s()==failed to create thread\n", basename(__FILE__), __LINE__, __func__); + fprintf(stderr, "==%s[%d]%s()==failed to create thread\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__); return; } while (sem_inited == 0) { @@ -139,14 +139,14 @@ struct tsem_s { }; int tsem_init(tsem_t *sem, int pshared, unsigned int value) { - // fprintf(stderr, "==%s[%d]%s():[%p]==creating\n", basename(__FILE__), __LINE__, __func__, sem); + // fprintf(stderr, "==%s[%d]%s():[%p]==creating\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); if (*sem) { - fprintf(stderr, "==%s[%d]%s():[%p]==already initialized\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==already initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } struct tsem_s *p = (struct tsem_s *)calloc(1, sizeof(*p)); if (!p) { - fprintf(stderr, "==%s[%d]%s():[%p]==out of memory\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==out of memory\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } @@ -162,7 +162,7 @@ int tsem_init(tsem_t *sem, int pshared, unsigned int value) { p->val = value; } while (0); if (r) { - fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } #elif defined(SEM_USE_POSIX) @@ -181,27 +181,27 @@ int tsem_init(tsem_t *sem, int pshared, unsigned int value) { int e = errno; if (e == EEXIST) continue; if (e == EINTR) continue; - fprintf(stderr, "==%s[%d]%s():[%p]==not created[%d]%s\n", basename(__FILE__), __LINE__, __func__, sem, e, + fprintf(stderr, "==%s[%d]%s():[%p]==not created[%d]%s\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem, e, strerror(e)); abort(); } while (p->sem == SEM_FAILED); #elif defined(SEM_USE_SEM) pthread_once(&sem_once, once_init); if (sem_inited != 1) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal resource init failed\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal resource init failed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); errno = ENOMEM; return -1; } kern_return_t ret = semaphore_create(sem_port, &p->sem, SYNC_POLICY_FIFO, value); if (ret != KERN_SUCCESS) { - fprintf(stderr, "==%s[%d]%s():[%p]==semophore_create failed\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==semophore_create failed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); // we fail-fast here, because we have less-doc about semaphore_create for the moment abort(); } #else // SEM_USE_PTHREAD p->sem = dispatch_semaphore_create(value); if (p->sem == NULL) { - fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } #endif // SEM_USE_PTHREAD @@ -215,28 +215,28 @@ int tsem_init(tsem_t *sem, int pshared, unsigned int value) { int tsem_wait(tsem_t *sem) { if (!*sem) { - fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } struct tsem_s *p = *sem; if (!p->valid) { - fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } #ifdef SEM_USE_PTHREAD if (pthread_mutex_lock(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } p->val -= 1; if (p->val < 0) { if (pthread_cond_wait(&p->cond, &p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } } if (pthread_mutex_unlock(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } return 0; @@ -251,28 +251,28 @@ int tsem_wait(tsem_t *sem) { int tsem_post(tsem_t *sem) { if (!*sem) { - fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } struct tsem_s *p = *sem; if (!p->valid) { - fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } #ifdef SEM_USE_PTHREAD if (pthread_mutex_lock(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } p->val += 1; if (p->val <= 0) { if (pthread_cond_signal(&p->cond)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } } if (pthread_mutex_unlock(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } return 0; @@ -286,34 +286,34 @@ int tsem_post(tsem_t *sem) { } int tsem_destroy(tsem_t *sem) { - // fprintf(stderr, "==%s[%d]%s():[%p]==destroying\n", basename(__FILE__), __LINE__, __func__, sem); + // fprintf(stderr, "==%s[%d]%s():[%p]==destroying\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); if (!*sem) { - // fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", basename(__FILE__), __LINE__, __func__, sem); + // fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); // abort(); return 0; } struct tsem_s *p = *sem; if (!p->valid) { - // fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", basename(__FILE__), __LINE__, __func__, sem); + // fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); // abort(); return 0; } #ifdef SEM_USE_PTHREAD if (pthread_mutex_lock(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } p->valid = 0; if (pthread_cond_destroy(&p->cond)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } if (pthread_mutex_unlock(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } if (pthread_mutex_destroy(&p->lock)) { - fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", basename(__FILE__), __LINE__, __func__, sem); + fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem); abort(); } #elif defined(SEM_USE_POSIX) @@ -322,7 +322,7 @@ int tsem_destroy(tsem_t *sem) { int r = sem_unlink(name); if (r) { int e = errno; - fprintf(stderr, "==%s[%d]%s():[%p]==unlink failed[%d]%s\n", basename(__FILE__), __LINE__, __func__, sem, e, + fprintf(stderr, "==%s[%d]%s():[%p]==unlink failed[%d]%s\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem, e, strerror(e)); abort(); } diff --git a/source/os/src/osSleep.c b/source/os/src/osSleep.c index 3b90fbdad88059e370673b150070785823eec571..724347b0bc9fb4ff27de2d2d69d8be253cb10743 100644 --- a/source/os/src/osSleep.c +++ b/source/os/src/osSleep.c @@ -13,47 +13,35 @@ * along with this program. If not, see . */ +#define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "os.h" -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - -void taosMsleep(int32_t ms) { Sleep(ms); } - -#else +#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) #include +#endif -/* - to make taosMsleep work, - signal SIGALRM shall be blocked in the calling thread, - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_BLOCK, &set, NULL); -*/ -void taosMsleep(int32_t mseconds) { -#if 1 - usleep(mseconds * 1000); +void taosSsleep(int32_t s) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + Sleep(1000 * s); #else - struct timeval timeout; - int32_t seconds, useconds; - - seconds = mseconds / 1000; - useconds = (mseconds % 1000) * 1000; - timeout.tv_sec = seconds; - timeout.tv_usec = useconds; - - /* sigset_t set; */ - /* sigemptyset(&set); */ - /* sigaddset(&set, SIGALRM); */ - /* pthread_sigmask(SIG_BLOCK, &set, NULL); */ - - select(0, NULL, NULL, NULL, &timeout); + sleep(s); +#endif +} -/* pthread_sigmask(SIG_UNBLOCK, &set, NULL); */ +void taosMsleep(int32_t ms) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + Sleep(ms); +#else + usleep(ms * 1000); #endif } +void taosUsleep(int32_t us) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + nanosleep(1000 * us); +#else + usleep(us); #endif +} diff --git a/source/os/src/osSocket.c b/source/os/src/osSocket.c index 096516a98daa8137a1427565cbabfdbf9545c118..698ceded1694fb44565b2cf717cb369b22e6acf8 100644 --- a/source/os/src/osSocket.c +++ b/source/os/src/osSocket.c @@ -18,176 +18,206 @@ #include "os.h" #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - #include "winsock2.h" - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "winsock2.h" #else - #include - #include - #include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif -// typedef struct TdSocketServer { -// #if SOCKET_WITH_LOCK -// pthread_rwlock_t rwlock; -// #endif -// int refId; -// SocketFd fd; -// } * TdSocketServerPtr, TdSocketServer; - -// typedef struct TdSocketConnector { -// #if SOCKET_WITH_LOCK -// pthread_rwlock_t rwlock; -// #endif -// int refId; -// SocketFd fd; -// } * TdSocketConnectorPtr, TdSocketConnector; - -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +typedef int32_t SocketFd; +typedef SocketFd EpollFd; -#define taosSend(sockfd, buf, len, flags) send((SOCKET)sockfd, buf, len, flags) -int32_t taosSendto(SocketFd fd, void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen) { - return sendto((SOCKET)sockfd, buf, len, flags, dest_addr, addrlen); -} -int32_t taosWriteSocket(SocketFd fd, void *buf, int len) { return send((SOCKET)fd, buf, len, 0); } -int32_t taosReadSocket(SocketFd fd, void *buf, int len) { return recv((SOCKET)fd, buf, len, 0)(); } -int32_t taosCloseSocketNoCheck(SocketFd fd) { return closesocket((SOCKET)fd); } -int32_t taosCloseSocket(SocketFd fd) { closesocket((SOCKET)fd) } +typedef struct TdSocketServer { +#if SOCKET_WITH_LOCK + pthread_rwlock_t rwlock; +#endif + int refId; + SocketFd fd; +} *TdSocketServerPtr, TdSocketServer; -#else +typedef struct TdSocket { +#if SOCKET_WITH_LOCK + pthread_rwlock_t rwlock; +#endif + int refId; + SocketFd fd; +} *TdSocketPtr, TdSocket; - #define taosSend(sockfd, buf, len, flags) send(sockfd, buf, len, flags) - int32_t taosSendto(SocketFd fd, void * buf, int len, unsigned int flags, const struct sockaddr * dest_addr, int addrlen) { - return sendto(fd, buf, len, flags, dest_addr, addrlen); - } +typedef struct TdEpoll { +#if SOCKET_WITH_LOCK + pthread_rwlock_t rwlock; +#endif + int refId; + EpollFd fd; +} *TdEpollPtr, TdEpoll; - int32_t taosWriteSocket(SocketFd fd, void *buf, int len) { - return write(fd, buf, len); +int32_t taosSendto(TdSocketPtr pSocket, void *buf, int len, unsigned int flags, const struct sockaddr *dest_addr, + int addrlen) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; } - - int32_t taosReadSocket(SocketFd fd, void *buf, int len) { - return read(fd, buf, len); +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return sendto(pSocket->fd, buf, len, flags, dest_addr, addrlen); +#else + return sendto(pSocket->fd, buf, len, flags, dest_addr, addrlen); +#endif +} +int32_t taosWriteSocket(TdSocketPtr pSocket, void *buf, int len) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; } - - int32_t taosCloseSocketNoCheck(SocketFd fd) { - return close(fd); +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return send(pSocket->fd, buf, len, 0); + ; +#else + return write(pSocket->fd, buf, len); +#endif +} +int32_t taosReadSocket(TdSocketPtr pSocket, void *buf, int len) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; } +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return recv(pSocket->fd, buf, len, 0); + ; +#else + return read(pSocket->fd, buf, len); +#endif +} - int32_t taosCloseSocket(SocketFd fd) { - if (fd > -1) { - close(fd); - } +int32_t taosReadFromSocket(TdSocketPtr pSocket, void *buf, int32_t len, int32_t flags, struct sockaddr *destAddr, socklen_t *addrLen) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; } + return recvfrom(pSocket->fd, buf, len, flags, destAddr, addrLen); +} +int32_t taosCloseSocketNoCheck1(SocketFd fd) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return closesocket(fd); +#else + return close(fd); #endif +} +int32_t taosCloseSocket(TdSocketPtr *ppSocket) { + int32_t code; + if (ppSocket == NULL || *ppSocket == NULL || (*ppSocket)->fd < 0) { + return -1; + } + code = taosCloseSocketNoCheck1((*ppSocket)->fd); + (*ppSocket)->fd = -1; + free(*ppSocket); + return code; +} +int32_t taosCloseSocketServer(TdSocketServerPtr *ppSocketServer) { + int32_t code; + if (ppSocketServer == NULL || *ppSocketServer == NULL || (*ppSocketServer)->fd < 0) { + return -1; + } + code = taosCloseSocketNoCheck1((*ppSocketServer)->fd); + (*ppSocketServer)->fd = -1; + free(*ppSocketServer); + return code; +} -void taosShutDownSocketRD(SOCKET fd) { +int32_t taosShutDownSocketRD(TdSocketPtr pSocket) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } #ifdef WINDOWS - closesocket(fd); + return closesocket(pSocket->fd); #elif __APPLE__ - close(fd); + return close(pSocket->fd); #else - shutdown(fd, SHUT_RD); + return shutdown(pSocket->fd, SHUT_RD); #endif } - -void taosShutDownSocketWR(SOCKET fd) { +int32_t taosShutDownSocketServerRD(TdSocketServerPtr pSocketServer) { + if (pSocketServer == NULL || pSocketServer->fd < 0) { + return -1; + } #ifdef WINDOWS - closesocket(fd); + return closesocket(pSocketServer->fd); #elif __APPLE__ - close(fd); + return close(pSocketServer->fd); #else - shutdown(fd, SHUT_WR); + return shutdown(pSocketServer->fd, SHUT_RD); #endif } -#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) - -int32_t taosSetNonblocking(SOCKET sock, int32_t on) { - int32_t flags = 0; - if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { - //printf("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); - return 1; - } - - if (on) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - - if ((flags = fcntl(sock, F_SETFL, flags)) < 0) { - //printf("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno)); - return 1; +int32_t taosShutDownSocketWR(TdSocketPtr pSocket) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; } - - return 0; -} - - - - +#ifdef WINDOWS + return closesocket(pSocket->fd); +#elif __APPLE__ + return close(pSocket->fd); +#else + return shutdown(pSocket->fd, SHUT_WR); #endif - -#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) || defined(_TD_DARWIN_32)) - -int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t optlen) { - return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); -} - -int32_t taosGetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t *optlen) { - return getsockopt(socketfd, level, optname, optval, (socklen_t *)optlen); } - -#endif - -#if !((defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) && defined(_MSC_VER)) - -uint32_t taosInetAddr(const char *ipAddr) { return inet_addr(ipAddr); } - -const char *taosInetNtoa(struct in_addr ipInt) { return inet_ntoa(ipInt); } - +int32_t taosShutDownSocketServerWR(TdSocketServerPtr pSocketServer) { + if (pSocketServer == NULL || pSocketServer->fd < 0) { + return -1; + } +#ifdef WINDOWS + return closesocket(pSocketServer->fd); +#elif __APPLE__ + return close(pSocketServer->fd); +#else + return shutdown(pSocketServer->fd, SHUT_WR); #endif - -#if defined(_TD_DARWIN_64) - -/* - * darwin implementation - */ - -int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { - if (level == SOL_SOCKET && optname == SO_SNDBUF) { - return 0; +} +int32_t taosShutDownSocketRDWR(TdSocketPtr pSocket) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; } - - if (level == SOL_SOCKET && optname == SO_RCVBUF) { - return 0; +#ifdef WINDOWS + return closesocket(pSocket->fd); +#elif __APPLE__ + return close(pSocket->fd); +#else + return shutdown(pSocket->fd, SHUT_RDWR); +#endif +} +int32_t taosShutDownSocketServerRDWR(TdSocketServerPtr pSocketServer) { + if (pSocketServer == NULL || pSocketServer->fd < 0) { + return -1; } - - return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); +#ifdef WINDOWS + return closesocket(pSocketServer->fd); +#elif __APPLE__ + return close(pSocketServer->fd); +#else + return shutdown(pSocketServer->fd, SHUT_RDWR); +#endif } + +#if (defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) + #if defined(_TD_GO_DLL_) + uint64_t htonll(uint64_t val) { return (((uint64_t)htonl(val)) << 32) + htonl(val >> 32); } + #endif #endif +void taosWinSocketInit1() { #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - -/* - * windows implementation - */ - -#include -#include -#include -#include -#include -#include -#include - -void taosWinSocketInit() { static char flag = 0; if (flag == 0) { WORD wVersionRequested; @@ -197,21 +227,46 @@ void taosWinSocketInit() { flag = 1; } } +#else +#endif } - -int32_t taosSetNonblocking(SOCKET sock, int32_t on) { +int32_t taosSetNonblocking(TdSocketPtr pSocket, int32_t on) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) u_long mode; if (on) { mode = 1; - ioctlsocket(sock, FIONBIO, &mode); + ioctlsocket(pSocket->fd, FIONBIO, &mode); } else { mode = 0; - ioctlsocket(sock, FIONBIO, &mode); + ioctlsocket(pSocket->fd, FIONBIO, &mode); + } +#else + int32_t flags = 0; + if ((flags = fcntl(pSocket->fd, F_GETFL, 0)) < 0) { + // printf("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); + return 1; } + + if (on) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + + if ((flags = fcntl(pSocket->fd, F_SETFL, flags)) < 0) { + // printf("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno)); + return 1; + } +#endif return 0; } - -int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t optlen) { +int32_t taosSetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t optlen) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) if (level == SOL_SOCKET && optname == TCP_KEEPCNT) { return 0; } @@ -228,13 +283,23 @@ int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *op return 0; } - return setsockopt(socketfd, level, optname, optval, optlen); + return setsockopt(pSocket->fd, level, optname, optval, optlen); +#else + return setsockopt(pSocket->fd, level, optname, optval, (socklen_t)optlen); +#endif +} +int32_t taosGetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void *optval, int32_t *optlen) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return 0; +#else + return getsockopt(pSocket->fd, level, optname, optval, (socklen_t *)optlen); +#endif } - -#ifdef _MSC_VER -//#if _MSC_VER >= 1900 - uint32_t taosInetAddr(const char *ipAddr) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) uint32_t value; int32_t ret = inet_pton(AF_INET, ipAddr, &value); if (ret <= 0) { @@ -242,39 +307,37 @@ uint32_t taosInetAddr(const char *ipAddr) { } else { return value; } +#else + return inet_addr(ipAddr); +#endif } - const char *taosInetNtoa(struct in_addr ipInt) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) // not thread safe, only for debug usage while print log static char tmpDstStr[16]; return inet_ntop(AF_INET, &ipInt, tmpDstStr, INET6_ADDRSTRLEN); -} - -//#endif -#endif - -#if defined(_TD_GO_DLL_) - -uint64_t htonll(uint64_t val) { return (((uint64_t)htonl(val)) << 32) + htonl(val >> 32); } - -#endif - +#else + return inet_ntoa(ipInt); #endif +} #ifndef SIGPIPE - #define SIGPIPE EPIPE +#define SIGPIPE EPIPE #endif #define TCP_CONN_TIMEOUT 3000 // conn timeout -int32_t taosWriteMsg(SOCKET fd, void *buf, int32_t nbytes) { +int32_t taosWriteMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } int32_t nleft, nwritten; - char * ptr = (char *)buf; + char *ptr = (char *)buf; nleft = nbytes; while (nleft > 0) { - nwritten = (int32_t)taosWriteSocket(fd, (char *)ptr, (size_t)nleft); + nwritten = taosWriteSocket(pSocket, (char *)ptr, (size_t)nleft); if (nwritten <= 0) { if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK */) continue; @@ -293,20 +356,21 @@ int32_t taosWriteMsg(SOCKET fd, void *buf, int32_t nbytes) { return (nbytes - nleft); } -int32_t taosReadMsg(SOCKET fd, void *buf, int32_t nbytes) { +int32_t taosReadMsg(TdSocketPtr pSocket, void *buf, int32_t nbytes) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } int32_t nleft, nread; - char * ptr = (char *)buf; + char *ptr = (char *)buf; nleft = nbytes; - if (fd < 0) return -1; - while (nleft > 0) { - nread = (int32_t)taosReadSocket(fd, ptr, (size_t)nleft); + nread = taosReadSocket(pSocket, ptr, (size_t)nleft); if (nread == 0) { break; } else if (nread < 0) { - if (errno == EINTR/* || errno == EAGAIN || errno == EWOULDBLOCK*/) { + if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK*/) { continue; } else { return -1; @@ -324,11 +388,14 @@ int32_t taosReadMsg(SOCKET fd, void *buf, int32_t nbytes) { return (nbytes - nleft); } -int32_t taosNonblockwrite(SOCKET fd, char *ptr, int32_t nbytes) { - taosSetNonblocking(fd, 1); +int32_t taosNonblockwrite(TdSocketPtr pSocket, char *ptr, int32_t nbytes) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } + taosSetNonblocking(pSocket, 1); - int32_t nleft, nwritten, nready; - fd_set fset; + int32_t nleft, nwritten, nready; + fd_set fset; struct timeval tv; nleft = nbytes; @@ -336,24 +403,24 @@ int32_t taosNonblockwrite(SOCKET fd, char *ptr, int32_t nbytes) { tv.tv_sec = 30; tv.tv_usec = 0; FD_ZERO(&fset); - FD_SET(fd, &fset); - if ((nready = select((int32_t)(fd + 1), NULL, &fset, NULL, &tv)) == 0) { + FD_SET(pSocket->fd, &fset); + if ((nready = select((SocketFd)(pSocket->fd + 1), NULL, &fset, NULL, &tv)) == 0) { errno = ETIMEDOUT; - //printf("fd %d timeout, no enough space to write", fd); + // printf("fd %d timeout, no enough space to write", fd); break; } else if (nready < 0) { if (errno == EINTR) continue; - //printf("select error, %d (%s)", errno, strerror(errno)); + // printf("select error, %d (%s)", errno, strerror(errno)); return -1; } - nwritten = (int32_t)taosSend(fd, ptr, (size_t)nleft, MSG_NOSIGNAL); + nwritten = (int32_t)send(pSocket->fd, ptr, (size_t)nleft, MSG_NOSIGNAL); if (nwritten <= 0) { if (errno == EAGAIN || errno == EINTR) continue; - //printf("write error, %d (%s)", errno, strerror(errno)); + // printf("write error, %d (%s)", errno, strerror(errno)); return -1; } @@ -361,121 +428,99 @@ int32_t taosNonblockwrite(SOCKET fd, char *ptr, int32_t nbytes) { ptr += nwritten; } - taosSetNonblocking(fd, 0); + taosSetNonblocking(pSocket, 0); return (nbytes - nleft); } -int32_t taosReadn(SOCKET fd, char *ptr, int32_t nbytes) { - int32_t nread, nready, nleft = nbytes; - - fd_set fset; - struct timeval tv; - - while (nleft > 0) { - tv.tv_sec = 30; - tv.tv_usec = 0; - FD_ZERO(&fset); - FD_SET(fd, &fset); - if ((nready = select((int32_t)(fd + 1), NULL, &fset, NULL, &tv)) == 0) { - errno = ETIMEDOUT; - //printf("fd %d timeout\n", fd); - break; - } else if (nready < 0) { - if (errno == EINTR) continue; - //printf("select error, %d (%s)", errno, strerror(errno)); - return -1; - } - - if ((nread = (int32_t)taosReadSocket(fd, ptr, (size_t)nleft)) < 0) { - if (errno == EINTR) continue; - //printf("read error, %d (%s)", errno, strerror(errno)); - return -1; - - } else if (nread == 0) { - //printf("fd %d EOF", fd); - break; // EOF - } - - nleft -= nread; - ptr += nread; - } - - return (nbytes - nleft); -} - -SOCKET taosOpenUdpSocket(uint32_t ip, uint16_t port) { +TdSocketPtr taosOpenUdpSocket(uint32_t ip, uint16_t port) { struct sockaddr_in localAddr; - SOCKET sockFd; - int32_t bufSize = 1024000; + SocketFd fd; + int32_t bufSize = 1024000; - //printf("open udp socket:0x%x:%hu", ip, port); + // printf("open udp socket:0x%x:%hu", ip, port); memset((char *)&localAddr, 0, sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = ip; localAddr.sin_port = (uint16_t)htons(port); - if ((sockFd = socket(AF_INET, SOCK_DGRAM, 0)) <= 2) { - //printf("failed to open udp socket: %d (%s)", errno, strerror(errno)); - taosCloseSocketNoCheck(sockFd); - return -1; + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) <= 2) { + // printf("failed to open udp socket: %d (%s)", errno, strerror(errno)); + taosCloseSocketNoCheck1(fd); + return NULL; } - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { - //printf("failed to set the send buffer size for UDP socket\n"); - taosCloseSocket(sockFd); - return -1; + TdSocketPtr pSocket = (TdSocketPtr)malloc(sizeof(TdSocket)); + if (pSocket == NULL) { + taosCloseSocketNoCheck1(fd); + return NULL; } + pSocket->fd = fd; + pSocket->refId = 0; - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { - //printf("failed to set the receive buffer size for UDP socket\n"); - taosCloseSocket(sockFd); - return -1; + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { + // printf("failed to set the send buffer size for UDP socket\n"); + taosCloseSocket(&pSocket); + return NULL; + } + + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { + // printf("failed to set the receive buffer size for UDP socket\n"); + taosCloseSocket(&pSocket); + return NULL; } /* bind socket to local address */ - if (bind(sockFd, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) { - //printf("failed to bind udp socket: %d (%s), 0x%x:%hu", errno, strerror(errno), ip, port); - taosCloseSocket(sockFd); - return -1; + if (bind(pSocket->fd, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) { + // printf("failed to bind udp socket: %d (%s), 0x%x:%hu", errno, strerror(errno), ip, port); + taosCloseSocket(&pSocket); + return NULL; } - return sockFd; + return pSocket; } -SOCKET taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) { - SOCKET sockFd = 0; - int32_t ret; +TdSocketPtr taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) { + SocketFd fd = -1; + int32_t ret; struct sockaddr_in serverAddr, clientAddr; - int32_t bufSize = 1024 * 1024; + int32_t bufSize = 1024 * 1024; - sockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockFd <= 2) { - //printf("failed to open the socket: %d (%s)", errno, strerror(errno)); - taosCloseSocketNoCheck(sockFd); - return -1; + if (fd <= 2) { + // printf("failed to open the socket: %d (%s)", errno, strerror(errno)); + if (fd >= 0) taosCloseSocketNoCheck1(fd); + return NULL; } + TdSocketPtr pSocket = (TdSocketPtr)malloc(sizeof(TdSocket)); + if (pSocket == NULL) { + taosCloseSocketNoCheck1(fd); + return NULL; + } + pSocket->fd = fd; + pSocket->refId = 0; + /* set REUSEADDR option, so the portnumber can be re-used */ int32_t reuse = 1; - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { - //printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); - taosCloseSocket(sockFd); - return -1; + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { + // printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { - //printf("failed to set the send buffer size for TCP socket\n"); - taosCloseSocket(sockFd); - return -1; + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { + // printf("failed to set the send buffer size for TCP socket\n"); + taosCloseSocket(&pSocket); + return NULL; } - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { - //printf("failed to set the receive buffer size for TCP socket\n"); - taosCloseSocket(sockFd); - return -1; + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { + // printf("failed to set the receive buffer size for TCP socket\n"); + taosCloseSocket(&pSocket); + return NULL; } if (clientIp != 0) { @@ -485,11 +530,11 @@ SOCKET taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clie clientAddr.sin_port = 0; /* bind socket to client address */ - if (bind(sockFd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) { - //printf("bind tcp client socket failed, client(0x%x:0), dest(0x%x:%d), reason:(%s)", clientIp, destIp, destPort, - // strerror(errno)); - taosCloseSocket(sockFd); - return -1; + if (bind(pSocket->fd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) { + // printf("bind tcp client socket failed, client(0x%x:0), dest(0x%x:%d), reason:(%s)", clientIp, destIp, destPort, + // strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } } @@ -498,159 +543,193 @@ SOCKET taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clie serverAddr.sin_addr.s_addr = destIp; serverAddr.sin_port = (uint16_t)htons((uint16_t)destPort); -#ifdef _TD_LINUX - taosSetNonblocking(sockFd, 1); - ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); +#ifdef _TD_LINUX + taosSetNonblocking(pSocket, 1); + ret = connect(pSocket->fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); if (ret == -1) { if (errno == EHOSTUNREACH) { - //printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno)); - taosCloseSocket(sockFd); - return -1; + // printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno)); + taosCloseSocket(&pSocket); + return -1; } else if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) { - struct pollfd wfd[1]; + struct pollfd wfd[1]; - wfd[0].fd = sockFd; + wfd[0].fd = pSocket->fd; wfd[0].events = POLLOUT; - + int res = poll(wfd, 1, TCP_CONN_TIMEOUT); if (res == -1 || res == 0) { - //printf("failed to connect socket, ip:0x%x, port:%hu(poll error/conn timeout)", destIp, destPort); - taosCloseSocket(sockFd); // + // printf("failed to connect socket, ip:0x%x, port:%hu(poll error/conn timeout)", destIp, destPort); + taosCloseSocket(&pSocket); // return -1; } - int optVal = -1, optLen = sizeof(int); - if ((0 != taosGetSockOpt(sockFd, SOL_SOCKET, SO_ERROR, &optVal, &optLen)) || (optVal != 0)) { - //printf("failed to connect socket, ip:0x%x, port:%hu(connect host error)", destIp, destPort); - taosCloseSocket(sockFd); // + int optVal = -1, optLen = sizeof(int); + if ((0 != taosGetSockOpt(pSocket, SOL_SOCKET, SO_ERROR, &optVal, &optLen)) || (optVal != 0)) { + // printf("failed to connect socket, ip:0x%x, port:%hu(connect host error)", destIp, destPort); + taosCloseSocket(&pSocket); // return -1; } ret = 0; - } else { // Other error - //printf("failed to connect socket, ip:0x%x, port:%hu(target host cannot be reached)", destIp, destPort); - taosCloseSocket(sockFd); // - return -1; - } + } else { // Other error + // printf("failed to connect socket, ip:0x%x, port:%hu(target host cannot be reached)", destIp, destPort); + taosCloseSocket(&pSocket); // + return -1; + } } - taosSetNonblocking(sockFd, 0); + taosSetNonblocking(pSocket, 0); #else - ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); + ret = connect(pSocket->fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); #endif if (ret != 0) { - //printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno)); - taosCloseSocket(sockFd); - sockFd = -1; + // printf("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } else { - taosKeepTcpAlive(sockFd); + taosKeepTcpAlive(pSocket); } - return sockFd; + return pSocket; } -int32_t taosKeepTcpAlive(SOCKET sockFd) { +int32_t taosKeepTcpAlive(TdSocketPtr pSocket) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } int32_t alive = 1; - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&alive, sizeof(alive)) < 0) { - //printf("fd:%d setsockopt SO_KEEPALIVE failed: %d (%s)", sockFd, errno, strerror(errno)); - taosCloseSocket(sockFd); + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_KEEPALIVE, (void *)&alive, sizeof(alive)) < 0) { + // printf("fd:%d setsockopt SO_KEEPALIVE failed: %d (%s)", sockFd, errno, strerror(errno)); + taosCloseSocket(&pSocket); return -1; } #ifndef __APPLE__ // all fails on macosx int32_t probes = 3; - if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPCNT, (void *)&probes, sizeof(probes)) < 0) { - //printf("fd:%d setsockopt SO_KEEPCNT failed: %d (%s)", sockFd, errno, strerror(errno)); - taosCloseSocket(sockFd); + if (taosSetSockOpt(pSocket, SOL_TCP, TCP_KEEPCNT, (void *)&probes, sizeof(probes)) < 0) { + // printf("fd:%d setsockopt SO_KEEPCNT failed: %d (%s)", sockFd, errno, strerror(errno)); + taosCloseSocket(&pSocket); return -1; } int32_t alivetime = 10; - if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPIDLE, (void *)&alivetime, sizeof(alivetime)) < 0) { - //printf("fd:%d setsockopt SO_KEEPIDLE failed: %d (%s)", sockFd, errno, strerror(errno)); - taosCloseSocket(sockFd); + if (taosSetSockOpt(pSocket, SOL_TCP, TCP_KEEPIDLE, (void *)&alivetime, sizeof(alivetime)) < 0) { + // printf("fd:%d setsockopt SO_KEEPIDLE failed: %d (%s)", sockFd, errno, strerror(errno)); + taosCloseSocket(&pSocket); return -1; } int32_t interval = 3; - if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&interval, sizeof(interval)) < 0) { - //printf("fd:%d setsockopt SO_KEEPINTVL failed: %d (%s)", sockFd, errno, strerror(errno)); - taosCloseSocket(sockFd); + if (taosSetSockOpt(pSocket, SOL_TCP, TCP_KEEPINTVL, (void *)&interval, sizeof(interval)) < 0) { + // printf("fd:%d setsockopt SO_KEEPINTVL failed: %d (%s)", sockFd, errno, strerror(errno)); + taosCloseSocket(&pSocket); return -1; } -#endif // __APPLE__ +#endif // __APPLE__ int32_t nodelay = 1; - if (taosSetSockOpt(sockFd, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(nodelay)) < 0) { - //printf("fd:%d setsockopt TCP_NODELAY failed %d (%s)", sockFd, errno, strerror(errno)); - taosCloseSocket(sockFd); + if (taosSetSockOpt(pSocket, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(nodelay)) < 0) { + // printf("fd:%d setsockopt TCP_NODELAY failed %d (%s)", sockFd, errno, strerror(errno)); + taosCloseSocket(&pSocket); return -1; } struct linger linger = {0}; linger.l_onoff = 1; linger.l_linger = 3; - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) { - //printf("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno)); - taosCloseSocket(sockFd); + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) { + // printf("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno)); + taosCloseSocket(&pSocket); return -1; } return 0; } -SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { +TdSocketServerPtr taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { struct sockaddr_in serverAdd; - SOCKET sockFd; + SocketFd fd; int32_t reuse; - //printf("open tcp server socket:0x%x:%hu", ip, port); + // printf("open tcp server socket:0x%x:%hu", ip, port); bzero((char *)&serverAdd, sizeof(serverAdd)); serverAdd.sin_family = AF_INET; serverAdd.sin_addr.s_addr = ip; serverAdd.sin_port = (uint16_t)htons(port); - if ((sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 2) { - //printf("failed to open TCP socket: %d (%s)", errno, strerror(errno)); - taosCloseSocketNoCheck(sockFd); - return -1; + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 2) { + // printf("failed to open TCP socket: %d (%s)", errno, strerror(errno)); + taosCloseSocketNoCheck1(fd); + return NULL; + } + + TdSocketPtr pSocket = (TdSocketPtr)malloc(sizeof(TdSocket)); + if (pSocket == NULL) { + taosCloseSocketNoCheck1(fd); + return NULL; } + pSocket->refId = 0; + pSocket->fd = fd; /* set REUSEADDR option, so the portnumber can be re-used */ reuse = 1; - if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { - //printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); - taosCloseSocket(sockFd); - return -1; + if (taosSetSockOpt(pSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { + // printf("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } /* bind socket to server address */ - if (bind(sockFd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) { - //printf("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); - taosCloseSocket(sockFd); - return -1; + if (bind(pSocket->fd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) { + // printf("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } - if (taosKeepTcpAlive(sockFd) < 0) { - //printf("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno)); - taosCloseSocket(sockFd); - return -1; + if (taosKeepTcpAlive(pSocket) < 0) { + // printf("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } - if (listen(sockFd, 1024) < 0) { - //printf("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); - taosCloseSocket(sockFd); - return -1; + if (listen(pSocket->fd, 1024) < 0) { + // printf("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); + taosCloseSocket(&pSocket); + return NULL; } - return sockFd; + return (TdSocketServerPtr)pSocket; } +TdSocketPtr taosAcceptTcpConnectSocket(TdSocketServerPtr pServerSocket, struct sockaddr *destAddr, + socklen_t *addrLen) { + if (pServerSocket == NULL || pServerSocket->fd < 0) { + return NULL; + } + SocketFd fd = accept(pServerSocket->fd, destAddr, addrLen); + if (fd == -1) { + // tError("TCP accept failure(%s)", strerror(errno)); + return NULL; + } + + TdSocketPtr pSocket = (TdSocketPtr)malloc(sizeof(TdSocket)); + if (pSocket == NULL) { + taosCloseSocketNoCheck1(fd); + return NULL; + } + pSocket->fd = fd; + pSocket->refId = 0; + return pSocket; +} #define COPY_SIZE 32768 // sendfile shall be used -int64_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len) { +int64_t taosCopyFds(TdSocketPtr pSrcSocket, TdSocketPtr pDestSocket, int64_t len) { + if (pSrcSocket == NULL || pSrcSocket->fd < 0 || pDestSocket == NULL || pDestSocket->fd < 0) { + return -1; + } int64_t leftLen; int64_t readLen, writeLen; char temp[COPY_SIZE]; @@ -663,18 +742,18 @@ int64_t taosCopyFds(SOCKET sfd, int32_t dfd, int64_t len) { else readLen = COPY_SIZE; // 4K - int64_t retLen = taosReadMsg(sfd, temp, (int32_t)readLen); + int64_t retLen = taosReadMsg(pSrcSocket, temp, (int32_t)readLen); if (readLen != retLen) { - //printf("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", - // readLen, retLen, len, leftLen, strerror(errno)); + // printf("read error, readLen:%" PRId64 " retLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", + // readLen, retLen, len, leftLen, strerror(errno)); return -1; } - writeLen = taosWriteMsg(dfd, temp, (int32_t)readLen); + writeLen = taosWriteMsg(pDestSocket, temp, (int32_t)readLen); if (readLen != writeLen) { - //printf("copy error, readLen:%" PRId64 " writeLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", - // readLen, writeLen, len, leftLen, strerror(errno)); + // printf("copy error, readLen:%" PRId64 " writeLen:%" PRId64 " len:%" PRId64 " leftLen:%" PRId64 ", reason:%s", + // readLen, writeLen, len, leftLen, strerror(errno)); return -1; } @@ -692,7 +771,7 @@ void taosBlockSIGPIPE() { sigaddset(&signal_mask, SIGPIPE); int32_t rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); if (rc != 0) { - //printf("failed to block SIGPIPE"); + // printf("failed to block SIGPIPE"); } #endif } @@ -706,7 +785,7 @@ uint32_t taosGetIpv4FromFqdn(const char *fqdn) { int32_t ret = getaddrinfo(fqdn, NULL, &hints, &result); if (result) { - struct sockaddr * sa = result->ai_addr; + struct sockaddr *sa = result->ai_addr; struct sockaddr_in *si = (struct sockaddr_in *)sa; struct in_addr ia = si->sin_addr; uint32_t ip = ia.s_addr; @@ -715,12 +794,12 @@ uint32_t taosGetIpv4FromFqdn(const char *fqdn) { } else { #ifdef EAI_SYSTEM if (ret == EAI_SYSTEM) { - //printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, strerror(errno)); + // printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, strerror(errno)); } else { - //printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret)); + // printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret)); } #else - //printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret)); + // printf("failed to get the ip address, fqdn:%s, since:%s", fqdn, gai_strerror(ret)); #endif return 0xFFFFFFFF; } @@ -730,7 +809,8 @@ int32_t taosGetFqdn(char *fqdn) { char hostname[1024]; hostname[1023] = '\0'; if (gethostname(hostname, 1023) == -1) { - //printf("failed to get hostname, reason:%s", strerror(errno)); + printf("failed to get hostname, reason:%s", strerror(errno)); + assert(0); return -1; } @@ -742,21 +822,22 @@ int32_t taosGetFqdn(char *fqdn) { // thus, we choose AF_INET (ipv4 for the moment) to make getaddrinfo return // immediately hints.ai_family = AF_INET; -#else // __APPLE__ +#else // __APPLE__ hints.ai_flags = AI_CANONNAME; -#endif // __APPLE__ +#endif // __APPLE__ int32_t ret = getaddrinfo(hostname, NULL, &hints, &result); if (!result) { - //printf("failed to get fqdn, code:%d, reason:%s", ret, gai_strerror(ret)); + printf("failed to get fqdn, code:%d, reason:%s", ret, gai_strerror(ret)); + assert(0); return -1; } #ifdef __APPLE__ // refer to comments above strcpy(fqdn, hostname); -#else // __APPLE__ +#else // __APPLE__ strcpy(fqdn, result->ai_canonname); -#endif // __APPLE__ +#endif // __APPLE__ freeaddrinfo(result); return 0; } @@ -793,7 +874,6 @@ void tinet_ntoa(char *ipstr, uint32_t ip) { sprintf(ipstr, "%d.%d.%d.%d", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24); } - void taosIgnSIGPIPE() { #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) #else @@ -809,7 +889,67 @@ void taosSetMaskSIGPIPE() { sigaddset(&signal_mask, SIGPIPE); int32_t rc = pthread_sigmask(SIG_SETMASK, &signal_mask, NULL); if (rc != 0) { - //printf("failed to setmask SIGPIPE"); + // printf("failed to setmask SIGPIPE"); + } +#endif +} + +int32_t taosGetSocketName(TdSocketPtr pSocket, struct sockaddr *destAddr, socklen_t *addrLen) { + if (pSocket == NULL || pSocket->fd < 0) { + return -1; + } + return getsockname(pSocket->fd, destAddr, addrLen); +} + + +TdEpollPtr taosCreateEpoll(int32_t size) { + EpollFd fd = -1; +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#else + fd = epoll_create(size); +#endif + if (fd < 0) { + return NULL; + } + + TdEpollPtr pEpoll = (TdEpollPtr)malloc(sizeof(TdEpoll)); + if (pEpoll == NULL) { + taosCloseSocketNoCheck1(fd); + return NULL; + } + pEpoll->fd = fd; + pEpoll->refId = 0; + return pEpoll; +} +int32_t taosCtlEpoll(TdEpollPtr pEpoll, int32_t epollOperate, TdSocketPtr pSocket, struct epoll_event *event) { + int32_t code = -1; + if (pEpoll == NULL || pEpoll->fd < 0) { + return -1; + } +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#else + code = epoll_ctl(pEpoll->fd, epollOperate, pSocket->fd, event); +#endif + return code; +} +int32_t taosWaitEpoll(TdEpollPtr pEpoll, struct epoll_event *event, int32_t maxEvents, int32_t timeout) { + int32_t code = -1; + if (pEpoll == NULL || pEpoll->fd < 0) { + return -1; } +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#else + code = epoll_wait(pEpoll->fd, event, maxEvents, timeout); #endif -} \ No newline at end of file + return code; +} +int32_t taosCloseEpoll(TdEpollPtr *ppEpoll) { + int32_t code; + if (ppEpoll == NULL || *ppEpoll == NULL || (*ppEpoll)->fd < 0) { + return -1; + } + code = taosCloseSocketNoCheck1((*ppEpoll)->fd); + (*ppEpoll)->fd = -1; + free(*ppEpoll); + return code; +} diff --git a/source/os/src/osString.c b/source/os/src/osString.c index 88ea4b3e1521103b4827c7b5646ec2ed92b556e6..1052d108af43599ae2fb6706388a2ce9b4b2e115 100644 --- a/source/os/src/osString.c +++ b/source/os/src/osString.c @@ -15,6 +15,7 @@ #define _DEFAULT_SOURCE #include "os.h" +#include "tdef.h" #include #include @@ -291,11 +292,10 @@ int32_t twcslen(const wchar_t *wcs) { return n; } - int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes) { - for (int32_t i = 0; i < bytes; ++i) { - int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i * 4); - int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i * 4); + for (int32_t i = 0; i < bytes; i += TSDB_NCHAR_SIZE) { + int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i); + int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i); if ((f1 == 0 && f2 != 0) || (f1 != 0 && f2 == 0)) { return f1 - f2; @@ -361,4 +361,4 @@ int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes, int8_t ncha return wcsncmp((wchar_t *)f1_ucs4, (wchar_t *)f2_ucs4, bytes / ncharSize); } -#endif \ No newline at end of file +#endif diff --git a/source/os/src/osStrptime.c b/source/os/src/osStrptime.c index e8c873bc492ee33f1833ca38bcd7111bd6838d1b..99549f02cb9bd78b23ca7e51f97113662f2f4432 100644 --- a/source/os/src/osStrptime.c +++ b/source/os/src/osStrptime.c @@ -38,366 +38,368 @@ // //#include "lukemftp.h" -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - -#include -#include -#include -#include -//#define TM_YEAR_BASE 1970 //origin -#define TM_YEAR_BASE 1900 //slguan -/* -* We do not implement alternate representations. However, we always -* check whether a given modifier is allowed for a certain conversion. -*/ -#define ALT_E 0x01 -#define ALT_O 0x02 -#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } - - -static int conv_num(const char **, int *, int, int); - -static const char *day[7] = { - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", - "Friday", "Saturday" -}; -static const char *abday[7] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; -static const char *mon[12] = { - "January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December" -}; -static const char *abmon[12] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; -static const char *am_pm[2] = { - "AM", "PM" -}; - - -char * -strptime(const char *buf, const char *fmt, struct tm *tm) -{ - char c; - const char *bp; - size_t len = 0; - int alt_format, i, split_year = 0; - - bp = buf; - - while ((c = *fmt) != '\0') { - /* Clear `alternate' modifier prior to new conversion. */ - alt_format = 0; - - /* Eat up white-space. */ - if (isspace(c)) { - while (isspace(*bp)) - bp++; - - fmt++; - continue; - } - - if ((c = *fmt++) != '%') - goto literal; - - - again: switch (c = *fmt++) { - case '%': /* "%%" is converted to "%". */ - literal : - if (c != *bp++) - return (0); - break; - - /* - * "Alternative" modifiers. Just set the appropriate flag - * and start over again. - */ - case 'E': /* "%E?" alternative conversion modifier. */ - LEGAL_ALT(0); - alt_format |= ALT_E; - goto again; - - case 'O': /* "%O?" alternative conversion modifier. */ - LEGAL_ALT(0); - alt_format |= ALT_O; - goto again; - - /* - * "Complex" conversion rules, implemented through recursion. - */ - case 'c': /* Date and time, using the locale's format. */ - LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%x %X", tm))) - return (0); - break; - - case 'D': /* The date as "%m/%d/%y". */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%m/%d/%y", tm))) - return (0); - break; - - case 'R': /* The time as "%H:%M". */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%H:%M", tm))) - return (0); - break; - - case 'r': /* The time in 12-hour clock representation. */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%I:%M:%S %p", tm))) - return (0); - break; - - case 'T': /* The time as "%H:%M:%S". */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%H:%M:%S", tm))) - return (0); - break; - - case 'X': /* The time, using the locale's format. */ - LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%H:%M:%S", tm))) - return (0); - break; - - case 'x': /* The date, using the locale's format. */ - LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%m/%d/%y", tm))) - return (0); - break; - - /* - * "Elementary" conversion rules. - */ - case 'A': /* The day of week, using the locale's form. */ - case 'a': - LEGAL_ALT(0); - for (i = 0; i < 7; i++) { - /* Full name. */ - len = strlen(day[i]); - if (strncmp(day[i], bp, len) == 0) - break; - - /* Abbreviated name. */ - len = strlen(abday[i]); - if (strncmp(abday[i], bp, len) == 0) - break; - } - - /* Nothing matched. */ - if (i == 7) - return (0); - - tm->tm_wday = i; - bp += len; - break; - - case 'B': /* The month, using the locale's form. */ - case 'b': - case 'h': - LEGAL_ALT(0); - for (i = 0; i < 12; i++) { - /* Full name. */ - len = strlen(mon[i]); - if (strncmp(mon[i], bp, len) == 0) - break; - - /* Abbreviated name. */ - len = strlen(abmon[i]); - if (strncmp(abmon[i], bp, len) == 0) - break; - } - - /* Nothing matched. */ - if (i == 12) - return (0); - - tm->tm_mon = i; - bp += len; - break; - - case 'C': /* The century number. */ - LEGAL_ALT(ALT_E); - if (!(conv_num(&bp, &i, 0, 99))) - return (0); - - if (split_year) { - tm->tm_year = (tm->tm_year % 100) + (i * 100); - } - else { - tm->tm_year = i * 100; - split_year = 1; - } - break; - - case 'd': /* The day of month. */ - case 'e': - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) - return (0); - break; - - case 'k': /* The hour (24-hour clock representation). */ - LEGAL_ALT(0); - /* FALLTHROUGH */ - case 'H': - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) - return (0); - break; - - case 'l': /* The hour (12-hour clock representation). */ - LEGAL_ALT(0); - /* FALLTHROUGH */ - case 'I': - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) - return (0); - if (tm->tm_hour == 12) - tm->tm_hour = 0; - break; - - case 'j': /* The day of year. */ - LEGAL_ALT(0); - if (!(conv_num(&bp, &i, 1, 366))) - return (0); - tm->tm_yday = i - 1; - break; - - case 'M': /* The minute. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_min, 0, 59))) - return (0); - break; - - case 'm': /* The month. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &i, 1, 12))) - return (0); - tm->tm_mon = i - 1; - break; - - case 'p': /* The locale's equivalent of AM/PM. */ - LEGAL_ALT(0); - /* AM? */ - if (strcmp(am_pm[0], bp) == 0) { - if (tm->tm_hour > 11) - return (0); - - bp += strlen(am_pm[0]); - break; - } - /* PM? */ - else if (strcmp(am_pm[1], bp) == 0) { - if (tm->tm_hour > 11) - return (0); - - tm->tm_hour += 12; - bp += strlen(am_pm[1]); - break; - } - - /* Nothing matched. */ - return (0); - - case 'S': /* The seconds. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) - return (0); - break; - - case 'U': /* The week of year, beginning on sunday. */ - case 'W': /* The week of year, beginning on monday. */ - LEGAL_ALT(ALT_O); - /* - * XXX This is bogus, as we can not assume any valid - * information present in the tm structure at this - * point to calculate a real value, so just check the - * range for now. - */ - if (!(conv_num(&bp, &i, 0, 53))) - return (0); - break; - - case 'w': /* The day of week, beginning on sunday. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) - return (0); - break; - - case 'Y': /* The year. */ - LEGAL_ALT(ALT_E); - if (!(conv_num(&bp, &i, 0, 9999))) - return (0); - - tm->tm_year = i - TM_YEAR_BASE; - break; - - case 'y': /* The year within 100 years of the epoch. */ - LEGAL_ALT(ALT_E | ALT_O); - if (!(conv_num(&bp, &i, 0, 99))) - return (0); - - if (split_year) { - tm->tm_year = ((tm->tm_year / 100) * 100) + i; - break; - } - split_year = 1; - if (i <= 68) - tm->tm_year = i + 2000 - TM_YEAR_BASE; - else - tm->tm_year = i + 1900 - TM_YEAR_BASE; - break; - - /* - * Miscellaneous conversions. - */ - case 'n': /* Any kind of white-space. */ - case 't': - LEGAL_ALT(0); - while (isspace(*bp)) - bp++; - break; - - - default: /* Unknown/unsupported conversion. */ - return (0); - } - - - } - - /* LINTED functional specification */ - return ((char *)bp); -} - - -static int -conv_num(const char **buf, int *dest, int llim, int ulim) -{ - int result = 0; - - /* The limit also determines the number of valid digits. */ - int rulim = ulim; - - if (**buf < '0' || **buf > '9') - return (0); - - do { - result *= 10; - result += *(*buf)++ - '0'; - rulim /= 10; - } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); - - if (result < llim || result > ulim) - return (0); - - *dest = result; - return (1); -} - -#endif \ No newline at end of file +// #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + +// #include +// #include +// #include +// #include +// //#define TM_YEAR_BASE 1970 //origin +// #define TM_YEAR_BASE 1900 //slguan +// /* +// * We do not implement alternate representations. However, we always +// * check whether a given modifier is allowed for a certain conversion. +// */ +// #define ALT_E 0x01 +// #define ALT_O 0x02 +// #define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } + + +// static int conv_num(const char **buf, int *dest, int llim, int ulim) +// { +// int result = 0; + +// /* The limit also determines the number of valid digits. */ +// int rulim = ulim; + +// if (**buf < '0' || **buf > '9') +// return (0); + +// do { +// result *= 10; +// result += *(*buf)++ - '0'; +// rulim /= 10; +// } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + +// if (result < llim || result > ulim) +// return (0); + +// *dest = result; +// return (1); +// } + +// static const char *day[7] = { +// "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", +// "Friday", "Saturday" +// }; +// static const char *abday[7] = { +// "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +// }; +// static const char *mon[12] = { +// "January", "February", "March", "April", "May", "June", "July", +// "August", "September", "October", "November", "December" +// }; +// static const char *abmon[12] = { +// "Jan", "Feb", "Mar", "Apr", "May", "Jun", +// "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +// }; +// static const char *am_pm[2] = { +// "AM", "PM" +// }; + +// #endif + +// char *taosStrpTime(const char *buf, const char *fmt, struct tm *tm) { +// #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +// char c; +// const char *bp; +// size_t len = 0; +// int alt_format, i, split_year = 0; + +// bp = buf; + +// while ((c = *fmt) != '\0') { +// /* Clear `alternate' modifier prior to new conversion. */ +// alt_format = 0; + +// /* Eat up white-space. */ +// if (isspace(c)) { +// while (isspace(*bp)) +// bp++; + +// fmt++; +// continue; +// } + +// if ((c = *fmt++) != '%') +// goto literal; + + +// again: switch (c = *fmt++) { +// case '%': /* "%%" is converted to "%". */ +// literal : +// if (c != *bp++) +// return (0); +// break; + +// /* +// * "Alternative" modifiers. Just set the appropriate flag +// * and start over again. +// */ +// case 'E': /* "%E?" alternative conversion modifier. */ +// LEGAL_ALT(0); +// alt_format |= ALT_E; +// goto again; + +// case 'O': /* "%O?" alternative conversion modifier. */ +// LEGAL_ALT(0); +// alt_format |= ALT_O; +// goto again; + +// /* +// * "Complex" conversion rules, implemented through recursion. +// */ +// case 'c': /* Date and time, using the locale's format. */ +// LEGAL_ALT(ALT_E); +// if (!(bp = taosStrpTime(bp, "%x %X", tm))) +// return (0); +// break; + +// case 'D': /* The date as "%m/%d/%y". */ +// LEGAL_ALT(0); +// if (!(bp = taosStrpTime(bp, "%m/%d/%y", tm))) +// return (0); +// break; + +// case 'R': /* The time as "%H:%M". */ +// LEGAL_ALT(0); +// if (!(bp = taosStrpTime(bp, "%H:%M", tm))) +// return (0); +// break; + +// case 'r': /* The time in 12-hour clock representation. */ +// LEGAL_ALT(0); +// if (!(bp = taosStrpTime(bp, "%I:%M:%S %p", tm))) +// return (0); +// break; + +// case 'T': /* The time as "%H:%M:%S". */ +// LEGAL_ALT(0); +// if (!(bp = taosStrpTime(bp, "%H:%M:%S", tm))) +// return (0); +// break; + +// case 'X': /* The time, using the locale's format. */ +// LEGAL_ALT(ALT_E); +// if (!(bp = taosStrpTime(bp, "%H:%M:%S", tm))) +// return (0); +// break; + +// case 'x': /* The date, using the locale's format. */ +// LEGAL_ALT(ALT_E); +// if (!(bp = taosStrpTime(bp, "%m/%d/%y", tm))) +// return (0); +// break; + +// /* +// * "Elementary" conversion rules. +// */ +// case 'A': /* The day of week, using the locale's form. */ +// case 'a': +// LEGAL_ALT(0); +// for (i = 0; i < 7; i++) { +// /* Full name. */ +// len = strlen(day[i]); +// if (strncmp(day[i], bp, len) == 0) +// break; + +// /* Abbreviated name. */ +// len = strlen(abday[i]); +// if (strncmp(abday[i], bp, len) == 0) +// break; +// } + +// /* Nothing matched. */ +// if (i == 7) +// return (0); + +// tm->tm_wday = i; +// bp += len; +// break; + +// case 'B': /* The month, using the locale's form. */ +// case 'b': +// case 'h': +// LEGAL_ALT(0); +// for (i = 0; i < 12; i++) { +// /* Full name. */ +// len = strlen(mon[i]); +// if (strncmp(mon[i], bp, len) == 0) +// break; + +// /* Abbreviated name. */ +// len = strlen(abmon[i]); +// if (strncmp(abmon[i], bp, len) == 0) +// break; +// } + +// /* Nothing matched. */ +// if (i == 12) +// return (0); + +// tm->tm_mon = i; +// bp += len; +// break; + +// case 'C': /* The century number. */ +// LEGAL_ALT(ALT_E); +// if (!(conv_num(&bp, &i, 0, 99))) +// return (0); + +// if (split_year) { +// tm->tm_year = (tm->tm_year % 100) + (i * 100); +// } +// else { +// tm->tm_year = i * 100; +// split_year = 1; +// } +// break; + +// case 'd': /* The day of month. */ +// case 'e': +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) +// return (0); +// break; + +// case 'k': /* The hour (24-hour clock representation). */ +// LEGAL_ALT(0); +// /* FALLTHROUGH */ +// case 'H': +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) +// return (0); +// break; + +// case 'l': /* The hour (12-hour clock representation). */ +// LEGAL_ALT(0); +// /* FALLTHROUGH */ +// case 'I': +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) +// return (0); +// if (tm->tm_hour == 12) +// tm->tm_hour = 0; +// break; + +// case 'j': /* The day of year. */ +// LEGAL_ALT(0); +// if (!(conv_num(&bp, &i, 1, 366))) +// return (0); +// tm->tm_yday = i - 1; +// break; + +// case 'M': /* The minute. */ +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &tm->tm_min, 0, 59))) +// return (0); +// break; + +// case 'm': /* The month. */ +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &i, 1, 12))) +// return (0); +// tm->tm_mon = i - 1; +// break; + +// case 'p': /* The locale's equivalent of AM/PM. */ +// LEGAL_ALT(0); +// /* AM? */ +// if (strcmp(am_pm[0], bp) == 0) { +// if (tm->tm_hour > 11) +// return (0); + +// bp += strlen(am_pm[0]); +// break; +// } +// /* PM? */ +// else if (strcmp(am_pm[1], bp) == 0) { +// if (tm->tm_hour > 11) +// return (0); + +// tm->tm_hour += 12; +// bp += strlen(am_pm[1]); +// break; +// } + +// /* Nothing matched. */ +// return (0); + +// case 'S': /* The seconds. */ +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) +// return (0); +// break; + +// case 'U': /* The week of year, beginning on sunday. */ +// case 'W': /* The week of year, beginning on monday. */ +// LEGAL_ALT(ALT_O); +// /* +// * XXX This is bogus, as we can not assume any valid +// * information present in the tm structure at this +// * point to calculate a real value, so just check the +// * range for now. +// */ +// if (!(conv_num(&bp, &i, 0, 53))) +// return (0); +// break; + +// case 'w': /* The day of week, beginning on sunday. */ +// LEGAL_ALT(ALT_O); +// if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) +// return (0); +// break; + +// case 'Y': /* The year. */ +// LEGAL_ALT(ALT_E); +// if (!(conv_num(&bp, &i, 0, 9999))) +// return (0); + +// tm->tm_year = i - TM_YEAR_BASE; +// break; + +// case 'y': /* The year within 100 years of the epoch. */ +// LEGAL_ALT(ALT_E | ALT_O); +// if (!(conv_num(&bp, &i, 0, 99))) +// return (0); + +// if (split_year) { +// tm->tm_year = ((tm->tm_year / 100) * 100) + i; +// break; +// } +// split_year = 1; +// if (i <= 68) +// tm->tm_year = i + 2000 - TM_YEAR_BASE; +// else +// tm->tm_year = i + 1900 - TM_YEAR_BASE; +// break; + +// /* +// * Miscellaneous conversions. +// */ +// case 'n': /* Any kind of white-space. */ +// case 't': +// LEGAL_ALT(0); +// while (isspace(*bp)) +// bp++; +// break; + + +// default: /* Unknown/unsupported conversion. */ +// return (0); +// } + + +// } + +// /* LINTED functional specification */ +// return ((char *)bp); +// #elif defined(_TD_DARWIN_64) +// return strptime(buf, fmt, tm); +// #else +// return strptime(buf, fmt, tm); +// #endif +// } + + + diff --git a/source/os/src/osSysinfo.c b/source/os/src/osSysinfo.c index ff9d5fb71b95b74b744f60f1abf9716717263cf6..9bff7605097f20794b9a2d7b89e1127dc3a7d3b7 100644 --- a/source/os/src/osSysinfo.c +++ b/source/os/src/osSysinfo.c @@ -15,6 +15,7 @@ #define _DEFAULT_SOURCE #include "os.h" +#include "taoserror.h" #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) @@ -39,115 +40,6 @@ #include #pragma warning(pop) -int32_t taosGetTotalMemory(int64_t *totalKB) { - MEMORYSTATUSEX memsStat; - memsStat.dwLength = sizeof(memsStat); - if (!GlobalMemoryStatusEx(&memsStat)) { - return -1; - } - - *totalKB = memsStat.ullTotalPhys / 1024; - return 0; -} - -int32_t taosGetSysMemory(int64_t *usedKB) { - MEMORYSTATUSEX memsStat; - memsStat.dwLength = sizeof(memsStat); - if (!GlobalMemoryStatusEx(&memsStat)) { - return -1; - } - - int64_t nMemFree = memsStat.ullAvailPhys / 1024; - int64_t nMemTotal = memsStat.ullTotalPhys / 1024.0; - - *usedKB = nMemTotal - nMemFree; - return 0; -} - -int32_t taosGetProcMemory(int64_t *usedKB) { - unsigned bytes_used = 0; - -#if defined(_WIN64) && defined(_MSC_VER) - PROCESS_MEMORY_COUNTERS pmc; - HANDLE cur_proc = GetCurrentProcess(); - - if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) { - bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage); - } -#endif - - *usedKB = bytes_used / 1024; - return 0; -} - -int32_t taosGetCpuCores(float *numOfCores) { - SYSTEM_INFO info; - GetSystemInfo(&info); - *numOfCores = info.dwNumberOfProcessors; - return 0; -} - -int32_t taosGetCpuUsage(double *sysCpuUsage, double *procCpuUsage) { - *sysCpuUsage = 0; - *procCpuUsage = 0; - return 0; -} - -int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize) { - unsigned _int64 i64FreeBytesToCaller; - unsigned _int64 i64TotalBytes; - unsigned _int64 i64FreeBytes; - - BOOL fResult = GetDiskFreeSpaceExA(dataDir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes, - (PULARGE_INTEGER)&i64FreeBytes); - if (fResult) { - diskSize->tsize = (int64_t)(i64TotalBytes); - diskSize->avail = (int64_t)(i64FreeBytesToCaller); - diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes); - return 0; - } else { - // printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } -} - -int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { - *receive_bytes = 0; - *transmit_bytes = 0; - return 0; -} - -int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) { - IO_COUNTERS io_counter; - if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) { - if (rchars) *rchars = io_counter.ReadTransferCount; - if (wchars) *wchars = io_counter.WriteTransferCount; - if (read_bytes) *read_bytes = 0; - if (write_bytes) *write_bytes = 0; - return 0; - } - return -1; -} - -void taosGetSystemInfo() { - taosGetCpuCores(&tsNumOfCores); - taosGetTotalMemory(&tsTotalMemoryKB); - - double tmp1, tmp2, tmp3, tmp4; - taosGetCpuUsage(&tmp1, &tmp2); -} - -void taosKillSystem() { - // printf("function taosKillSystem, exit!"); - exit(0); -} - -int taosSystem(const char *cmd) { - // printf("taosSystem not support"); - return -1; -} - LONG WINAPI FlCrashDump(PEXCEPTION_POINTERS ep) { typedef BOOL(WINAPI * FxMiniDumpWriteDump)(IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile, IN MINIDUMP_TYPE DumpType, @@ -184,124 +76,13 @@ LONG WINAPI FlCrashDump(PEXCEPTION_POINTERS ep) { return EXCEPTION_CONTINUE_SEARCH; } -void taosSetCoreDump() { SetUnhandledExceptionFilter(&FlCrashDump); } - -int32_t taosGetSystemUUID(char *uid, int32_t uidlen) { - GUID guid; - CoCreateGuid(&guid); - - sprintf(uid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], - guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); - - return 0; -} - -char *taosGetCmdlineByPID(int pid) { return ""; } - #elif defined(_TD_DARWIN_64) -/* - * darwin implementation - */ - #include #include -void taosKillSystem() { - // printf("function taosKillSystem, exit!"); - exit(0); -} - -int32_t taosGetCpuCores(float *numOfCores) { - *numOfCores = sysconf(_SC_NPROCESSORS_ONLN); - return 0; -} - -void taosGetSystemInfo() { - long physical_pages = sysconf(_SC_PHYS_PAGES); - long page_size = sysconf(_SC_PAGESIZE); - tsTotalMemoryKB = physical_pages * page_size / 1024; - tsPageSizeKB = page_size / 1024; - tsNumOfCores = sysconf(_SC_NPROCESSORS_ONLN); -} - -int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) { - if (rchars) *rchars = 0; - if (wchars) *wchars = 0; - if (read_bytes) *read_bytes = 0; - if (write_bytes) *write_bytes = 0; - return 0; -} - -int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { - *receive_bytes = 0; - *transmit_bytes = 0; - return 0; -} - -int32_t taosGetCpuUsage(double *sysCpuUsage, double *procCpuUsage) { - *sysCpuUsage = 0; - *procCpuUsage = 0; - return 0; -} - -int32_t taosGetProcMemory(int64_t *usedKB) { - *usedKB = 0; - return 0; -} - -int32_t taosGetSysMemory(int64_t *usedKB) { - *usedKB = 0; - return 0; -} - -int taosSystem(const char *cmd) { - // printf("un support funtion"); - return -1; -} - -void taosSetCoreDump() {} - -int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize) { - struct statvfs info; - if (statvfs(dataDir, &info)) { - // printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } else { - diskSize->tsize = info.f_blocks * info.f_frsize; - diskSize->avail = info.f_bavail * info.f_frsize; - diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize; - return 0; - } -} - -int32_t taosGetSystemUUID(char *uid, int32_t uidlen) { - uuid_t uuid = {0}; - uuid_generate(uuid); - // it's caller's responsibility to make enough space for `uid`, that's 36-char + 1-null - uuid_unparse_lower(uuid, uid); - return 0; -} - -char *taosGetCmdlineByPID(int pid) { - static char cmdline[1024]; - errno = 0; - - if (proc_pidpath(pid, cmdline, sizeof(cmdline)) <= 0) { - fprintf(stderr, "PID is %d, %s", pid, strerror(errno)); - return strerror(errno); - } - - return cmdline; -} - #else -/* - * linux implementation - */ - #include #include #include @@ -345,49 +126,6 @@ static void taosGetProcIOnfos() { snprintf(tsProcIOFile, sizeof(tsProcIOFile), "/proc/%d/io", tsProcId); } -int32_t taosGetTotalMemory(int64_t *totalKB) { - *totalKB = (int64_t)(sysconf(_SC_PHYS_PAGES) * tsPageSizeKB); - return 0; -} - -int32_t taosGetSysMemory(int64_t *usedKB) { - *usedKB = sysconf(_SC_AVPHYS_PAGES) * tsPageSizeKB; - return 0; -} - -int32_t taosGetProcMemory(int64_t *usedKB) { - TdFilePtr pFile = taosOpenFile(tsProcMemFile, TD_FILE_READ | TD_FILE_STREAM); - if (pFile == NULL) { - // printf("open file:%s failed", tsProcMemFile); - return -1; - } - - ssize_t _bytes = 0; - char *line = NULL; - while (!taosEOFFile(pFile)) { - _bytes = taosGetLineFile(pFile, &line); - if ((_bytes < 0) || (line == NULL)) { - break; - } - if (strstr(line, "VmRSS:") != NULL) { - break; - } - } - - if (line == NULL) { - // printf("read file:%s failed", tsProcMemFile); - taosCloseFile(&pFile); - return -1; - } - - char tmp[10]; - sscanf(line, "%s %" PRId64, tmp, usedKB); - - if (line != NULL) tfree(line); - taosCloseFile(&pFile); - return 0; -} - static int32_t taosGetSysCpuInfo(SysCpuInfo *cpuInfo) { TdFilePtr pFile = taosOpenFile(tsSysCpuFile, TD_FILE_READ | TD_FILE_STREAM); if (pFile == NULL) { @@ -441,18 +179,216 @@ static int32_t taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) { return 0; } -int32_t taosGetCpuCores(float *numOfCores) { - *numOfCores = sysconf(_SC_NPROCESSORS_ONLN); - return 0; -} +#endif -int32_t taosGetCpuUsage(double *cpu_system, double *cpu_engine) { - static uint64_t lastSysUsed = 0; - static uint64_t lastSysTotal = 0; - static uint64_t lastProcTotal = 0; +bool taosCheckSystemIsSmallEnd() { + union check{ + int16_t i; + char ch[2]; + }c; + c.i=1; + return c.ch[0]==1; +} - SysCpuInfo sysCpu; - ProcCpuInfo procCpu; +void taosGetSystemInfo() { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + taosGetCpuCores(&tsNumOfCores); + taosGetTotalMemory(&tsTotalMemoryKB); + + double tmp1, tmp2, tmp3, tmp4; + taosGetCpuUsage(&tmp1, &tmp2); +#elif defined(_TD_DARWIN_64) + long physical_pages = sysconf(_SC_PHYS_PAGES); + long page_size = sysconf(_SC_PAGESIZE); + tsTotalMemoryKB = physical_pages * page_size / 1024; + tsPageSizeKB = page_size / 1024; + tsNumOfCores = sysconf(_SC_NPROCESSORS_ONLN); +#else + taosGetProcIOnfos(); + taosGetCpuCores(&tsNumOfCores); + taosGetTotalMemory(&tsTotalMemoryKB); + + double tmp1, tmp2, tmp3, tmp4; + taosGetCpuUsage(&tmp1, &tmp2); +#endif +} + +int32_t taosGetEmail(char *email, int32_t maxLen) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#elif defined(_TD_DARWIN_64) + const char *filepath = "/usr/local/taos/email"; + + TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ); + if (pFile == NULL) return false; + + if (taosReadFile(pFile, (void *)email, maxLen) < 0) { + taosCloseFile(&pFile); + return -1; + } + + taosCloseFile(&pFile); + return 0; +#else + const char *filepath = "/usr/local/taos/email"; + + TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ); + if (pFile == NULL) return false; + + if (taosReadFile(pFile, (void *)email, maxLen) < 0) { + taosCloseFile(&pFile); + return -1; + } + + taosCloseFile(&pFile); + return 0; +#endif +} + +int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#elif defined(_TD_DARWIN_64) + char *line = NULL; + size_t size = 0; + int32_t code = -1; + + TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) return false; + + while ((size = taosGetLineFile(pFile, &line)) != -1) { + line[size - 1] = '\0'; + if (strncmp(line, "PRETTY_NAME", 11) == 0) { + const char *p = strchr(line, '=') + 1; + if (*p == '"') { + p++; + line[size - 2] = 0; + } + tstrncpy(releaseName, p, maxLen); + code = 0; + break; + } + } + + if (line != NULL) free(line); + taosCloseFile(&pFile); + return code; +#else + char *line = NULL; + size_t size = 0; + int32_t code = -1; + + TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) return false; + + while ((size = taosGetLineFile(pFile, &line)) != -1) { + line[size - 1] = '\0'; + if (strncmp(line, "PRETTY_NAME", 11) == 0) { + const char *p = strchr(line, '=') + 1; + if (*p == '"') { + p++; + line[size - 2] = 0; + } + tstrncpy(releaseName, p, maxLen); + code = 0; + break; + } + } + + if (line != NULL) free(line); + taosCloseFile(&pFile); + return code; +#endif +} + +int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#elif defined(_TD_DARWIN_64) + char *line = NULL; + size_t size = 0; + int32_t done = 0; + int32_t code = -1; + + TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) return false; + + while (done != 3 && (size = taosGetLineFile(pFile, &line)) != -1) { + line[size - 1] = '\0'; + if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) { + const char *v = strchr(line, ':') + 2; + tstrncpy(cpuModel, v, maxLen); + code = 0; + done |= 1; + } else if (((done & 2) == 0) && strncmp(line, "cpu cores", 9) == 0) { + const char *v = strchr(line, ':') + 2; + *numOfCores = atof(v); + done |= 2; + } + } + + if (line != NULL) free(line); + taosCloseFile(&pFile); + + return code; +#else + char *line = NULL; + size_t size = 0; + int32_t done = 0; + int32_t code = -1; + + TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) return false; + + while (done != 3 && (size = taosGetLineFile(pFile, &line)) != -1) { + line[size - 1] = '\0'; + if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) { + const char *v = strchr(line, ':') + 2; + tstrncpy(cpuModel, v, maxLen); + code = 0; + done |= 1; + } else if (((done & 2) == 0) && strncmp(line, "cpu cores", 9) == 0) { + const char *v = strchr(line, ':') + 2; + *numOfCores = atof(v); + done |= 2; + } + } + + if (line != NULL) free(line); + taosCloseFile(&pFile); + + return code; +#endif +} + +int32_t taosGetCpuCores(float *numOfCores) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + SYSTEM_INFO info; + GetSystemInfo(&info); + *numOfCores = info.dwNumberOfProcessors; + return 0; +#elif defined(_TD_DARWIN_64) + *numOfCores = sysconf(_SC_NPROCESSORS_ONLN); + return 0; +#else + *numOfCores = sysconf(_SC_NPROCESSORS_ONLN); + return 0; +#endif +} + +int32_t taosGetCpuUsage(double *cpu_system, double *cpu_engine) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + *cpu_system = 0; + *cpu_engine = 0; + return 0; +#elif defined(_TD_DARWIN_64) + *cpu_system = 0; + *cpu_engine = 0; + return 0; +#else + static uint64_t lastSysUsed = 0; + static uint64_t lastSysTotal = 0; + static uint64_t lastProcTotal = 0; + + SysCpuInfo sysCpu; + ProcCpuInfo procCpu; if (taosGetSysCpuInfo(&sysCpu) != 0) { return -1; } @@ -483,9 +419,132 @@ int32_t taosGetCpuUsage(double *cpu_system, double *cpu_engine) { lastProcTotal = curProcTotal; return 0; +#endif +} + +int32_t taosGetTotalMemory(int64_t *totalKB) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + MEMORYSTATUSEX memsStat; + memsStat.dwLength = sizeof(memsStat); + if (!GlobalMemoryStatusEx(&memsStat)) { + return -1; + } + + *totalKB = memsStat.ullTotalPhys / 1024; + return 0; +#elif defined(_TD_DARWIN_64) + return 0; +#else + *totalKB = (int64_t)(sysconf(_SC_PHYS_PAGES) * tsPageSizeKB); + return 0; +#endif +} + +int32_t taosGetProcMemory(int64_t *usedKB) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + unsigned bytes_used = 0; + +#if defined(_WIN64) && defined(_MSC_VER) + PROCESS_MEMORY_COUNTERS pmc; + HANDLE cur_proc = GetCurrentProcess(); + + if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) { + bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage); + } +#endif + + *usedKB = bytes_used / 1024; + return 0; +#elif defined(_TD_DARWIN_64) + *usedKB = 0; + return 0; +#else + TdFilePtr pFile = taosOpenFile(tsProcMemFile, TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) { + // printf("open file:%s failed", tsProcMemFile); + return -1; + } + + ssize_t _bytes = 0; + char *line = NULL; + while (!taosEOFFile(pFile)) { + _bytes = taosGetLineFile(pFile, &line); + if ((_bytes < 0) || (line == NULL)) { + break; + } + if (strstr(line, "VmRSS:") != NULL) { + break; + } + } + + if (line == NULL) { + // printf("read file:%s failed", tsProcMemFile); + taosCloseFile(&pFile); + return -1; + } + + char tmp[10]; + sscanf(line, "%s %" PRId64, tmp, usedKB); + + if (line != NULL) tfree(line); + taosCloseFile(&pFile); + return 0; +#endif +} + +int32_t taosGetSysMemory(int64_t *usedKB) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + MEMORYSTATUSEX memsStat; + memsStat.dwLength = sizeof(memsStat); + if (!GlobalMemoryStatusEx(&memsStat)) { + return -1; + } + + int64_t nMemFree = memsStat.ullAvailPhys / 1024; + int64_t nMemTotal = memsStat.ullTotalPhys / 1024.0; + + *usedKB = nMemTotal - nMemFree; + return 0; +#elif defined(_TD_DARWIN_64) + *usedKB = 0; + return 0; +#else + *usedKB = sysconf(_SC_AVPHYS_PAGES) * tsPageSizeKB; + return 0; +#endif } int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize) { +#if defined(WINDOWS) + unsigned _int64 i64FreeBytesToCaller; + unsigned _int64 i64TotalBytes; + unsigned _int64 i64FreeBytes; + + BOOL fResult = GetDiskFreeSpaceExA(dataDir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes, + (PULARGE_INTEGER)&i64FreeBytes); + if (fResult) { + diskSize->total = (int64_t)(i64TotalBytes); + diskSize->avail = (int64_t)(i64FreeBytesToCaller); + diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes); + return 0; + } else { + // printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); + terrno = TAOS_SYSTEM_ERROR(errno); + return -1; + } +#elif defined(_TD_DARWIN_64) + struct statvfs info; + if (statvfs(dataDir, &info)) { + // printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); + terrno = TAOS_SYSTEM_ERROR(errno); + return -1; + } else { + diskSize->total = info.f_blocks * info.f_frsize; + diskSize->avail = info.f_bavail * info.f_frsize; + diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize; + return 0; + } +#else struct statvfs info; if (statvfs(dataDir, &info)) { return -1; @@ -495,9 +554,79 @@ int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize) { diskSize->used = diskSize->total - diskSize->avail; return 0; } +#endif +} + +int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + IO_COUNTERS io_counter; + if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) { + if (rchars) *rchars = io_counter.ReadTransferCount; + if (wchars) *wchars = io_counter.WriteTransferCount; + if (read_bytes) *read_bytes = 0; + if (write_bytes) *write_bytes = 0; + return 0; + } + return -1; +#elif defined(_TD_DARWIN_64) + if (rchars) *rchars = 0; + if (wchars) *wchars = 0; + if (read_bytes) *read_bytes = 0; + if (write_bytes) *write_bytes = 0; + return 0; +#else + TdFilePtr pFile = taosOpenFile(tsProcIOFile, TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) return -1; + + ssize_t _bytes = 0; + char *line = NULL; + char tmp[24]; + int readIndex = 0; + + while (!taosEOFFile(pFile)) { + _bytes = taosGetLineFile(pFile, &line); + if (_bytes < 10 || line == NULL) { + break; + } + if (strstr(line, "rchar:") != NULL) { + sscanf(line, "%s %" PRId64, tmp, rchars); + readIndex++; + } else if (strstr(line, "wchar:") != NULL) { + sscanf(line, "%s %" PRId64, tmp, wchars); + readIndex++; + } else if (strstr(line, "read_bytes:") != NULL) { // read_bytes + sscanf(line, "%s %" PRId64, tmp, read_bytes); + readIndex++; + } else if (strstr(line, "write_bytes:") != NULL) { // write_bytes + sscanf(line, "%s %" PRId64, tmp, write_bytes); + readIndex++; + } else { + } + + if (readIndex >= 4) break; + } + + if (line != NULL) tfree(line); + taosCloseFile(&pFile); + + if (readIndex < 4) { + return -1; + } + + return 0; +#endif } int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + *receive_bytes = 0; + *transmit_bytes = 0; + return 0; +#elif defined(_TD_DARWIN_64) + *receive_bytes = 0; + *transmit_bytes = 0; + return 0; +#else TdFilePtr pFile = taosOpenFile(tsSysNetFile, TD_FILE_READ | TD_FILE_STREAM); if (pFile == NULL) return -1; @@ -540,93 +669,100 @@ int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { taosCloseFile(&pFile); return 0; +#endif } -int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) { - TdFilePtr pFile = taosOpenFile(tsProcIOFile, TD_FILE_READ | TD_FILE_STREAM); - if (pFile == NULL) return -1; - - ssize_t _bytes = 0; - char *line = NULL; - char tmp[24]; - int readIndex = 0; +void taosKillSystem() { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + printf("function taosKillSystem, exit!"); + exit(0); +#elif defined(_TD_DARWIN_64) + printf("function taosKillSystem, exit!"); + exit(0); +#else + // SIGINT + printf("taosd will shut down soon"); + kill(tsProcId, 2); +#endif +} - while (!taosEOFFile(pFile)) { - _bytes = taosGetLineFile(pFile, &line); - if (_bytes < 10 || line == NULL) { - break; - } - if (strstr(line, "rchar:") != NULL) { - sscanf(line, "%s %" PRId64, tmp, rchars); - readIndex++; - } else if (strstr(line, "wchar:") != NULL) { - sscanf(line, "%s %" PRId64, tmp, wchars); - readIndex++; - } else if (strstr(line, "read_bytes:") != NULL) { // read_bytes - sscanf(line, "%s %" PRId64, tmp, read_bytes); - readIndex++; - } else if (strstr(line, "write_bytes:") != NULL) { // write_bytes - sscanf(line, "%s %" PRId64, tmp, write_bytes); - readIndex++; - } else { - } +int32_t taosGetSystemUUID(char *uid, int32_t uidlen) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + GUID guid; + CoCreateGuid(&guid); - if (readIndex >= 4) break; - } + sprintf(uid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], + guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); - if (line != NULL) tfree(line); - taosCloseFile(&pFile); + return 0; +#elif defined(_TD_DARWIN_64) + uuid_t uuid = {0}; + uuid_generate(uuid); + // it's caller's responsibility to make enough space for `uid`, that's 36-char + 1-null + uuid_unparse_lower(uuid, uid); + return 0; +#else + int len = 0; - if (readIndex < 4) { + // fd = open("/proc/sys/kernel/random/uuid", 0); + TdFilePtr pFile = taosOpenFile("/proc/sys/kernel/random/uuid", TD_FILE_READ); + if (pFile == NULL) { return -1; + } else { + len = taosReadFile(pFile, uid, uidlen); + taosCloseFile(&pFile); + } + + if (len >= 36) { + uid[36] = 0; + return 0; } return 0; +#endif } -void taosGetSystemInfo() { - taosGetProcIOnfos(); - taosGetCpuCores(&tsNumOfCores); - taosGetTotalMemory(&tsTotalMemoryKB); +char *taosGetCmdlineByPID(int pid) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return ""; +#elif defined(_TD_DARWIN_64) + static char cmdline[1024]; + errno = 0; - double tmp1, tmp2, tmp3, tmp4; - taosGetCpuUsage(&tmp1, &tmp2); -} + if (proc_pidpath(pid, cmdline, sizeof(cmdline)) <= 0) { + fprintf(stderr, "PID is %d, %s", pid, strerror(errno)); + return strerror(errno); + } -void taosKillSystem() { - // SIGINT - // printf("taosd will shut down soon"); - kill(tsProcId, 2); -} + return cmdline; +#else + static char cmdline[1024]; + sprintf(cmdline, "/proc/%d/cmdline", pid); -int taosSystem(const char *cmd) { - FILE *fp; - int res; - char buf[1024]; - if (cmd == NULL) { - // printf("taosSystem cmd is NULL!"); - return -1; - } + // int fd = open(cmdline, O_RDONLY); + TdFilePtr pFile = taosOpenFile(cmdline, TD_FILE_READ); + if (pFile != NULL) { + int n = taosReadFile(pFile, cmdline, sizeof(cmdline) - 1); + if (n < 0) n = 0; - if ((fp = popen(cmd, "r")) == NULL) { - // printf("popen cmd:%s error: %s", cmd, strerror(errno)); - return -1; - } else { - while (fgets(buf, sizeof(buf), fp)) { - // printf("popen result:%s", buf); - } + if (n > 0 && cmdline[n - 1] == '\n') --n; - if ((res = pclose(fp)) == -1) { - // printf("close popen file pointer fp error!"); - } else { - // printf("popen res is :%d", res); - } + cmdline[n] = 0; - return res; + taosCloseFile(&pFile); + } else { + cmdline[0] = 0; } + + return cmdline; +#endif } void taosSetCoreDump(bool enable) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + SetUnhandledExceptionFilter(&FlCrashDump); +#elif defined(_TD_DARWIN_64) +#else if (!enable) return; // 1. set ulimit -c unlimited @@ -699,55 +835,12 @@ void taosSetCoreDump(bool enable) { // printf("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid); #endif -} - -int32_t taosGetSystemUUID(char *uid, int32_t uidlen) { - int len = 0; - - // fd = open("/proc/sys/kernel/random/uuid", 0); - TdFilePtr pFile = taosOpenFile("/proc/sys/kernel/random/uuid", TD_FILE_READ); - if (pFile == NULL) { - return -1; - } else { - len = taosReadFile(pFile, uid, uidlen); - taosCloseFile(&pFile); - } - - if (len >= 36) { - uid[36] = 0; - return 0; - } - - return 0; -} - -char *taosGetCmdlineByPID(int pid) { - static char cmdline[1024]; - sprintf(cmdline, "/proc/%d/cmdline", pid); - - // int fd = open(cmdline, O_RDONLY); - TdFilePtr pFile = taosOpenFile(cmdline, TD_FILE_READ); - if (pFile != NULL) { - int n = taosReadFile(pFile, cmdline, sizeof(cmdline) - 1); - if (n < 0) n = 0; - - if (n > 0 && cmdline[n - 1] == '\n') --n; - - cmdline[n] = 0; - - taosCloseFile(&pFile); - } else { - cmdline[0] = 0; - } - - return cmdline; -} - #endif - -#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) +} SysNameInfo taosGetSysNameInfo() { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#elif defined(_TD_DARWIN_64) SysNameInfo info = {0}; struct utsname uts; @@ -760,77 +853,18 @@ SysNameInfo taosGetSysNameInfo() { } return info; -} - -int32_t taosGetEmail(char *email, int32_t maxLen) { - const char *filepath = "/usr/local/taos/email"; - - TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ); - if (pFile == NULL) return false; - - if (taosReadFile(pFile, (void *)email, maxLen) < 0) { - taosCloseFile(&pFile); - return -1; - } - - taosCloseFile(&pFile); - return 0; -} - -int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen) { - char *line = NULL; - size_t size = 0; - int32_t code = -1; - - TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM); - if (pFile == NULL) return false; - - while ((size = taosGetLineFile(pFile, &line)) != -1) { - line[size - 1] = '\0'; - if (strncmp(line, "PRETTY_NAME", 11) == 0) { - const char *p = strchr(line, '=') + 1; - if (*p == '"') { - p++; - line[size - 2] = 0; - } - tstrncpy(releaseName, p, maxLen); - code = 0; - break; - } - } - - if (line != NULL) free(line); - taosCloseFile(&pFile); - return code; -} - -int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { - char *line = NULL; - size_t size = 0; - int32_t done = 0; - int32_t code = -1; - - TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM); - if (pFile == NULL) return false; +#else + SysNameInfo info = {0}; - while (done != 3 && (size = taosGetLineFile(pFile, &line)) != -1) { - line[size - 1] = '\0'; - if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) { - const char *v = strchr(line, ':') + 2; - tstrncpy(cpuModel, v, maxLen); - code = 0; - done |= 1; - } else if (((done & 2) == 0) && strncmp(line, "cpu cores", 9) == 0) { - const char *v = strchr(line, ':') + 2; - *numOfCores = atof(v); - done |= 2; - } + struct utsname uts; + if (!uname(&uts)) { + tstrncpy(info.sysname, uts.sysname, sizeof(info.sysname)); + tstrncpy(info.nodename, uts.nodename, sizeof(info.nodename)); + tstrncpy(info.release, uts.release, sizeof(info.release)); + tstrncpy(info.version, uts.version, sizeof(info.version)); + tstrncpy(info.machine, uts.machine, sizeof(info.machine)); } - if (line != NULL) free(line); - taosCloseFile(&pFile); - - return code; -} - + return info; #endif +} diff --git a/source/os/src/osSystem.c b/source/os/src/osSystem.c index 717cae0fbd1b5f1ab464a93fb16038a99613ea63..8ccbe9d78004760ab9f2377ede3a41dbfbe87f46 100644 --- a/source/os/src/osSystem.c +++ b/source/os/src/osSystem.c @@ -13,78 +13,83 @@ * along with this program. If not, see . */ +#define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "os.h" -#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) +#if defined(WINDOWS) +#elif defined(_TD_DARWIN_64) +#else +#include +#include +#include +#endif -/* - * windows implementation - */ +#if !defined(WINDOWS) +struct termios oldtio; +#endif -void* taosLoadDll(const char* filename) { return NULL; } -void* taosLoadSym(void* handle, char* name) { return NULL; } -void taosCloseDll(void* handle) {} +int32_t taosSystem(const char *cmd, char *buf, int32_t bufSize) { +#if defined(WINDOWS) + FILE *fp; + if (cmd == NULL) { + // printf("taosSystem cmd is NULL!"); + return -1; + } -int taosSetConsoleEcho(bool on) { - HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); - DWORD mode = 0; - GetConsoleMode(hStdin, &mode); - if (on) { - mode |= ENABLE_ECHO_INPUT; + if ((fp = _popen(cmd, "r")) == NULL) { + // printf("popen cmd:%s error: %s", cmd, strerror(errno)); + return -1; } else { - mode &= ~ENABLE_ECHO_INPUT; - } - SetConsoleMode(hStdin, mode); + while (fgets(buf, bufSize, fp)) { + // printf("popen result:%s", buf); + } - return 0; -} + if (!_pclose(fp)) { + // printf("close popen file pointer fp error!"); + return -1; + } else { + // printf("popen res is :%d", res); + } + return 0; + } #elif defined(_TD_DARWIN_64) - -/* - * darwin implementation - */ - -void* taosLoadDll(const char* filename) { return NULL; } -void* taosLoadSym(void* handle, char* name) { return NULL; } -void taosCloseDll(void* handle) {} - -int taosSetConsoleEcho(bool on) { -#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL) - int err; - struct termios term; - - if (tcgetattr(STDIN_FILENO, &term) == -1) { - perror("Cannot get the attribution of the terminal"); + printf("no support funtion"); + return -1; +#else + FILE *fp; + int32_t res; + if (cmd == NULL) { + // printf("taosSystem cmd is NULL!"); return -1; } - if (on) - term.c_lflag |= ECHOFLAGS; - else - term.c_lflag &= ~ECHOFLAGS; - - err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); - if (err == -1 && err == EINTR) { - perror("Cannot set the attribution of the terminal"); + if ((fp = popen(cmd, "r")) == NULL) { + // printf("popen cmd:%s error: %s", cmd, strerror(errno)); return -1; - } - - return 0; -} + } else { + while (fgets(buf, bufSize, fp)) { + // printf("popen result:%s", buf); + } -#else + if ((res = pclose(fp)) == -1) { + // printf("close popen file pointer fp error!"); + } else { + // printf("popen res is :%d", res); + } -/* - * linux implementation - */ - -#include -#include -#include + return res; + } +#endif +} void* taosLoadDll(const char* filename) { +#if defined(WINDOWS) + return NULL; +#elif defined(_TD_DARWIN_64) + return NULL; +#else void* handle = dlopen(filename, RTLD_LAZY); if (!handle) { //printf("load dll:%s failed, error:%s", filename, dlerror()); @@ -94,9 +99,15 @@ void* taosLoadDll(const char* filename) { //printf("dll %s loaded", filename); return handle; +#endif } void* taosLoadSym(void* handle, char* name) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return NULL; +#elif defined(_TD_DARWIN_64) + return NULL; +#else void* sym = dlsym(handle, name); char* error = NULL; @@ -108,15 +119,57 @@ void* taosLoadSym(void* handle, char* name) { //printf("sym %s loaded", name); return sym; +#endif } -void taosCloseDll(void* handle) { +void taosCloseDll(void* handle) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + return; +#elif defined(_TD_DARWIN_64) + return; +#else if (handle) { dlclose(handle); } +#endif } int taosSetConsoleEcho(bool on) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode = 0; + GetConsoleMode(hStdin, &mode); + if (on) { + mode |= ENABLE_ECHO_INPUT; + } else { + mode &= ~ENABLE_ECHO_INPUT; + } + SetConsoleMode(hStdin, mode); + + return 0; +#elif defined(_TD_DARWIN_64) +#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL) + int err; + struct termios term; + + if (tcgetattr(STDIN_FILENO, &term) == -1) { + perror("Cannot get the attribution of the terminal"); + return -1; + } + + if (on) + term.c_lflag |= ECHOFLAGS; + else + term.c_lflag &= ~ECHOFLAGS; + + err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + if (err == -1 && err == EINTR) { + perror("Cannot set the attribution of the terminal"); + return -1; + } + + return 0; +#else #define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL) int err; struct termios term; @@ -138,6 +191,111 @@ int taosSetConsoleEcho(bool on) { } return 0; +#endif } +void setTerminalMode() { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + +#elif defined(_TD_DARWIN_64) + struct termios newtio; + + /* if (atexit() != 0) { */ + /* fprintf(stderr, "Error register exit function!\n"); */ + /* exit(EXIT_FAILURE); */ + /* } */ + + memcpy(&newtio, &oldtio, sizeof(oldtio)); + + // Set new terminal attributes. + newtio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL | ISTRIP); + newtio.c_iflag |= IGNBRK; + + // newtio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); + newtio.c_oflag |= OPOST; + newtio.c_oflag |= ONLCR; + newtio.c_oflag &= ~(OCRNL | ONLRET); + + newtio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG); + newtio.c_cc[VMIN] = 1; + newtio.c_cc[VTIME] = 0; + + if (tcsetattr(0, TCSANOW, &newtio) != 0) { + fprintf(stderr, "Fail to set terminal properties!\n"); + exit(EXIT_FAILURE); + } +#else + struct termios newtio; + + /* if (atexit() != 0) { */ + /* fprintf(stderr, "Error register exit function!\n"); */ + /* exit(EXIT_FAILURE); */ + /* } */ + + memcpy(&newtio, &oldtio, sizeof(oldtio)); + + // Set new terminal attributes. + newtio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL | ISTRIP); + newtio.c_iflag |= IGNBRK; + + // newtio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); + newtio.c_oflag |= OPOST; + newtio.c_oflag |= ONLCR; + newtio.c_oflag &= ~(OCRNL | ONLRET); + + newtio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG); + newtio.c_cc[VMIN] = 1; + newtio.c_cc[VTIME] = 0; + + if (tcsetattr(0, TCSANOW, &newtio) != 0) { + fprintf(stderr, "Fail to set terminal properties!\n"); + exit(EXIT_FAILURE); + } +#endif +} + +int32_t getOldTerminalMode() { +#if defined(WINDOWS) + +#elif defined(_TD_DARWIN_64) + /* Make sure stdin is a terminal. */ + if (!isatty(STDIN_FILENO)) { + return -1; + } + + // Get the parameter of current terminal + if (tcgetattr(0, &oldtio) != 0) { + return -1; + } + + return 1; +#else + /* Make sure stdin is a terminal. */ + if (!isatty(STDIN_FILENO)) { + return -1; + } + + // Get the parameter of current terminal + if (tcgetattr(0, &oldtio) != 0) { + return -1; + } + + return 1; #endif +} + +void resetTerminalMode() { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + +#elif defined(_TD_DARWIN_64) + if (tcsetattr(0, TCSANOW, &oldtio) != 0) { + fprintf(stderr, "Fail to reset the terminal properties!\n"); + exit(EXIT_FAILURE); + } +#else + if (tcsetattr(0, TCSANOW, &oldtio) != 0) { + fprintf(stderr, "Fail to reset the terminal properties!\n"); + exit(EXIT_FAILURE); + } +#endif +} diff --git a/source/os/src/osTime.c b/source/os/src/osTime.c index 7c655c0251362e405469a121f4f1380731822e32..2b0de948805c7a02ea98a849b8f75b7ff372d6e4 100644 --- a/source/os/src/osTime.c +++ b/source/os/src/osTime.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#define ALLOW_FORBID_FUNC #define _BSD_SOURCE #ifdef DARWIN @@ -26,16 +27,373 @@ #include "os.h" #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) -/* - * windows implementation - */ #include +#include +#include #include +//#define TM_YEAR_BASE 1970 //origin +#define TM_YEAR_BASE 1900 //slguan +/* +* We do not implement alternate representations. However, we always +* check whether a given modifier is allowed for a certain conversion. +*/ +#define ALT_E 0x01 +#define ALT_O 0x02 +#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } + + +static int conv_num(const char **buf, int *dest, int llim, int ulim) +{ + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} + +static const char *day[7] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" +}; +static const char *abday[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; +static const char *mon[12] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" +}; +static const char *abmon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +static const char *am_pm[2] = { + "AM", "PM" +}; + + +#else +#include +#endif + +char *taosStrpTime(const char *buf, const char *fmt, struct tm *tm) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + char c; + const char *bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (isspace(c)) { + while (isspace(*bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + + again: switch (c = *fmt++) { + case '%': /* "%%" is converted to "%". */ + literal : + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = taosStrpTime(bp, "%x %X", tm))) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + if (!(bp = taosStrpTime(bp, "%m/%d/%y", tm))) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + if (!(bp = taosStrpTime(bp, "%H:%M", tm))) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + if (!(bp = taosStrpTime(bp, "%I:%M:%S %p", tm))) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + if (!(bp = taosStrpTime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = taosStrpTime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = taosStrpTime(bp, "%m/%d/%y", tm))) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) { + /* Full name. */ + len = strlen(day[i]); + if (strncmp(day[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abday[i]); + if (strncmp(abday[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) { + /* Full name. */ + len = strlen(mon[i]); + if (strncmp(mon[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abmon[i]); + if (strncmp(abmon[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } + else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; -int taosGetTimeOfDay(struct timeval *tv, struct timezone *tz) { + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; + + case 'p': /* The locale's equivalent of AM/PM. */ + LEGAL_ALT(0); + /* AM? */ + if (strcmp(am_pm[0], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + bp += strlen(am_pm[0]); + break; + } + /* PM? */ + else if (strcmp(am_pm[1], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + tm->tm_hour += 12; + bp += strlen(am_pm[1]); + break; + } + + /* Nothing matched. */ + return (0); + + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (isspace(*bp)) + bp++; + break; + + + default: /* Unknown/unsupported conversion. */ + return (0); + } + + + } + + /* LINTED functional specification */ + return ((char *)bp); +#else + return strptime(buf, fmt, tm); +#endif +} + +FORCE_INLINE int32_t taosGetTimeOfDay(struct timeval *tv) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) time_t t; - t = time(NULL); + t = taosGetTimestampSec(); SYSTEMTIME st; GetLocalTime(&st); @@ -43,26 +401,18 @@ int taosGetTimeOfDay(struct timeval *tv, struct timezone *tz) { tv->tv_usec = st.wMilliseconds * 1000; return 0; +#else + return gettimeofday(tv, NULL); +#endif } -struct tm *localtime_r(const time_t *timep, struct tm *result) { +struct tm *taosLocalTime(const time_t *timep, struct tm *result) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) localtime_s(result, timep); - return result; -} - #else - -/* - * linux and darwin implementation - */ - -#include -// #include "monotonic.h" - -FORCE_INLINE int32_t taosGetTimeOfDay(struct timeval *tv) { - return gettimeofday(tv, NULL); + localtime_r(timep, result); +#endif + return result; } int32_t taosGetTimestampSec() { return (int32_t)time(NULL); } - -#endif diff --git a/source/os/src/osTimer.c b/source/os/src/osTimer.c index bb526e0ba0ca40c38e2832125abd902946c5aea0..c95ca72bd57fd9e8165cda69edcdb003992816c0 100644 --- a/source/os/src/osTimer.c +++ b/source/os/src/osTimer.c @@ -13,15 +13,11 @@ * along with this program. If not, see . */ +#define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "os.h" #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - -/* - * windows implementation - */ - #include #include #include @@ -39,24 +35,9 @@ void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR } static MMRESULT timerId; -int taosInitTimer(win_timer_f callback, int ms) { - DWORD_PTR param = *((int64_t *)&callback); - - timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC); - if (timerId == 0) { - return -1; - } - return 0; -} - -void taosUninitTimer() { timeKillEvent(timerId); } #elif defined(_TD_DARWIN_64) -/* - * darwin implementation - */ - #include #include #include @@ -79,7 +60,7 @@ static void* timer_routine(void* arg) { struct kevent64_s kev[10] = {0}; r = kevent64(timer_kq, NULL, 0, kev, sizeof(kev) / sizeof(kev[0]), 0, &to); if (r != 0) { - fprintf(stderr, "==%s[%d]%s()==kevent64 failed\n", basename(__FILE__), __LINE__, __func__); + fprintf(stderr, "==%s[%d]%s()==kevent64 failed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__); abort(); } timer_callback(SIGALRM); // just mock @@ -88,53 +69,12 @@ static void* timer_routine(void* arg) { return NULL; } -int taosInitTimer(void (*callback)(int), int ms) { - int r = 0; - timer_kq = -1; - timer_stop = 0; - timer_ms = ms; - timer_callback = callback; - - timer_kq = kqueue(); - if (timer_kq == -1) { - fprintf(stderr, "==%s[%d]%s()==failed to create timer kq\n", basename(__FILE__), __LINE__, __func__); - // since no caller of this func checks the return value for the moment - abort(); - } - - r = pthread_create(&timer_thread, NULL, timer_routine, NULL); - if (r) { - fprintf(stderr, "==%s[%d]%s()==failed to create timer thread\n", basename(__FILE__), __LINE__, __func__); - // since no caller of this func checks the return value for the moment - abort(); - } - return 0; -} - -void taosUninitTimer() { - int r = 0; - timer_stop = 1; - r = pthread_join(timer_thread, NULL); - if (r) { - fprintf(stderr, "==%s[%d]%s()==failed to join timer thread\n", basename(__FILE__), __LINE__, __func__); - // since no caller of this func checks the return value for the moment - abort(); - } - close(timer_kq); - timer_kq = -1; -} - void taos_block_sigalrm(void) { // we don't know if there's any specific API for SIGALRM to deliver to specific thread // this implementation relies on kqueue rather than SIGALRM } #else - -/* - * linux implementation - */ - #include #include @@ -200,8 +140,39 @@ static void * taosProcessAlarmSignal(void *tharg) { return NULL; } +#endif int taosInitTimer(void (*callback)(int), int ms) { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + DWORD_PTR param = *((int64_t *)&callback); + + timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC); + if (timerId == 0) { + return -1; + } + return 0; +#elif defined(_TD_DARWIN_64) + int r = 0; + timer_kq = -1; + timer_stop = 0; + timer_ms = ms; + timer_callback = callback; + + timer_kq = kqueue(); + if (timer_kq == -1) { + fprintf(stderr, "==%s[%d]%s()==failed to create timer kq\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__); + // since no caller of this func checks the return value for the moment + abort(); + } + + r = pthread_create(&timer_thread, NULL, timer_routine, NULL); + if (r) { + fprintf(stderr, "==%s[%d]%s()==failed to create timer thread\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__); + // since no caller of this func checks the return value for the moment + abort(); + } + return 0; +#else stopTimer = false; pthread_attr_t tattr; pthread_attr_init(&tattr); @@ -215,13 +186,29 @@ int taosInitTimer(void (*callback)(int), int ms) { } return 0; +#endif } void taosUninitTimer() { +#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) + timeKillEvent(timerId); +#elif defined(_TD_DARWIN_64) + int r = 0; + timer_stop = 1; + r = pthread_join(timer_thread, NULL); + if (r) { + fprintf(stderr, "==%s[%d]%s()==failed to join timer thread\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__); + // since no caller of this func checks the return value for the moment + abort(); + } + close(timer_kq); + timer_kq = -1; +#else stopTimer = true; // printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread)); pthread_join(timerThread, NULL); +#endif } int64_t taosGetMonotonicMs() { @@ -239,5 +226,3 @@ const char *taosMonotonicInit() { return NULL; #endif } - -#endif diff --git a/source/os/src/osTimezone.c b/source/os/src/osTimezone.c index 68da2ce25e1da8058dfeb1de60c6fb25c4f80ea3..864a60b706c2283628e36aefe6873a2aeeea5264 100644 --- a/source/os/src/osTimezone.c +++ b/source/os/src/osTimezone.c @@ -128,9 +128,9 @@ void taosGetSystemTimezone(char *outTimezone) { * Enforce set the correct daylight saving time(DST) flag according * to current time */ - time_t tx1 = time(NULL); + time_t tx1 = taosGetTimestampSec(); struct tm tm1; - localtime_r(&tx1, &tm1); + taosLocalTime(&tx1, &tm1); /* * format example: @@ -147,9 +147,9 @@ void taosGetSystemTimezone(char *outTimezone) { * Enforce set the correct daylight saving time(DST) flag according * to current time */ - time_t tx1 = time(NULL); + time_t tx1 = taosGetTimestampSec(); struct tm tm1; - localtime_r(&tx1, &tm1); + taosLocalTime(&tx1, &tm1); /* load time zone string from /etc/timezone */ // FILE *f = fopen("/etc/timezone", "r"); diff --git a/source/util/CMakeLists.txt b/source/util/CMakeLists.txt index 4b28800c28e66b5a7c2e15518249a3361e878271..08fa0a240903736007605d349f11b953c4aacc64 100644 --- a/source/util/CMakeLists.txt +++ b/source/util/CMakeLists.txt @@ -5,12 +5,16 @@ target_include_directories( util PUBLIC "${CMAKE_SOURCE_DIR}/include/util" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" +IF(${TD_WINDOWS}) + PRIVATE "${CMAKE_SOURCE_DIR}/contrib/pthread-win32" + PRIVATE "${CMAKE_SOURCE_DIR}/contrib/gnuregex" +ENDIF () ) target_link_libraries( util PRIVATE os PUBLIC lz4_static - PUBLIC api cjson zlib + PUBLIC api cjson ) if(${BUILD_TEST}) diff --git a/source/util/src/tdes.c b/source/util/src/tdes.c index 105dd7f95fc204d11ad9233372984944760dfd70..a7f5131c2641cf84dd665b7357ad6ed38cefb880 100644 --- a/source/util/src/tdes.c +++ b/source/util/src/tdes.c @@ -31,8 +31,8 @@ void process_message(uint8_t* message_piece, uint8_t* processed_piece, key_set* #if 0 int64_t taosDesGenKey() { - uint32_t iseed = (uint32_t)time(NULL); - srand(iseed); + uint32_t iseed = (uint32_t)taosGetTimestampSec(); + taosSeedRand(iseed); uint8_t key[8] = {0}; generate_key(key); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index c1cb4f8a410665fae27b4a24848c4de8ff3a7f30..f97df62ccc380773b10c4e63b2e6814ad636b531 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -349,6 +349,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TDB_NO_AVAIL_DISK, "No available disk") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_MESSED_MSG, "TSDB messed message") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_IVLD_TAG_VAL, "TSDB invalid tag value") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_NO_CACHE_LAST_ROW, "TSDB no cache last row data") +TAOS_DEFINE_ERROR(TSDB_CODE_TDB_NO_SMA_INDEX_IN_META, "No sma index in meta") // query TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INVALID_QHANDLE, "Invalid handle") diff --git a/source/util/src/tjson.c b/source/util/src/tjson.c index 27848c4e2389cc0ff39ce3d248a2ab5cd06af159..634cfcb026eb7b34c350886f43ededa2dc11f885 100644 --- a/source/util/src/tjson.c +++ b/source/util/src/tjson.c @@ -98,7 +98,6 @@ int32_t tjsonAddObject(SJson* pJson, const char* pName, FToJson func, const void SJson* pJobj = tjsonCreateObject(); if (NULL == pJobj || TSDB_CODE_SUCCESS != func(pObj, pJobj)) { - printf("%s:%d code = %d\n", __FUNCTION__, __LINE__, TSDB_CODE_FAILED); tjsonDelete(pJobj); return TSDB_CODE_FAILED; } @@ -114,6 +113,22 @@ int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj) { return tjsonAddItemToArray(pJson, pJobj); } +int32_t tjsonAddArray(SJson* pJson, const char* pName, FToJson func, const void* pArray, int32_t itemSize, int32_t num) { + if (num > 0) { + SJson* pJsonArray = tjsonAddArrayToObject(pJson, pName); + if (NULL == pJsonArray) { + return TSDB_CODE_OUT_OF_MEMORY; + } + for (size_t i = 0; i < num; ++i) { + int32_t code = tjsonAddItem(pJsonArray, func, (const char*)pArray + itemSize * i); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + } + return TSDB_CODE_SUCCESS; +} + char* tjsonToString(const SJson* pJson) { return cJSON_Print((cJSON*)pJson); } char* tjsonToUnformattedString(const SJson* pJson) { return cJSON_PrintUnformatted((cJSON*)pJson); } @@ -143,9 +158,9 @@ int32_t tjsonGetBigIntValue(const SJson* pJson, const char* pName, int64_t* pVal if (NULL == p) { return TSDB_CODE_FAILED; } - char* pEnd = NULL; - *pVal = strtol(p, &pEnd, 10); - return (NULL == pEnd ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED); + + *pVal = strtol(p, NULL, 10); + return (errno == EINVAL || errno == ERANGE) ? TSDB_CODE_FAILED:TSDB_CODE_SUCCESS; } int32_t tjsonGetIntValue(const SJson* pJson, const char* pName, int32_t* pVal) { @@ -174,9 +189,9 @@ int32_t tjsonGetUBigIntValue(const SJson* pJson, const char* pName, uint64_t* pV if (NULL == p) { return TSDB_CODE_FAILED; } - char* pEnd = NULL; - *pVal = strtoul(p, &pEnd, 10); - return (NULL == pEnd ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED); + + *pVal = strtoul(p, NULL, 10); + return (errno == ERANGE||errno == EINVAL) ? TSDB_CODE_FAILED:TSDB_CODE_SUCCESS; } int32_t tjsonGetUTinyIntValue(const SJson* pJson, const char* pName, uint8_t* pVal) { @@ -188,7 +203,7 @@ int32_t tjsonGetUTinyIntValue(const SJson* pJson, const char* pName, uint8_t* pV int32_t tjsonGetBoolValue(const SJson* pJson, const char* pName, bool* pVal) { const SJson* pObject = tjsonGetObjectItem(pJson, pName); - if (cJSON_IsBool(pObject)) { + if (!cJSON_IsBool(pObject)) { return TSDB_CODE_FAILED; } *pVal = cJSON_IsTrue(pObject) ? true : false; @@ -216,4 +231,16 @@ int32_t tjsonToObject(const SJson* pJson, const char* pName, FToObject func, voi return func(pJsonObj, pObj); } +int32_t tjsonToArray(const SJson* pJson, const char* pName, FToObject func, void* pArray, int32_t itemSize) { + const cJSON* jArray = tjsonGetObjectItem(pJson, pName); + int32_t size = (NULL == jArray ? 0 : tjsonGetArraySize(jArray)); + for (int32_t i = 0; i < size; ++i) { + int32_t code = func(tjsonGetArrayItem(jArray, i), (char*)pArray + itemSize * i); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + return TSDB_CODE_SUCCESS; +} + SJson* tjsonParse(const char* pStr) { return cJSON_Parse(pStr); } diff --git a/source/util/src/tlog.c b/source/util/src/tlog.c index 7f5664b9cdc0c48e8a9b104d5634bcbbb045e17d..6dedc3f7406d3653c1513cb345b68cd17c966e1e 100644 --- a/source/util/src/tlog.c +++ b/source/util/src/tlog.c @@ -401,7 +401,7 @@ static inline int32_t taosBuildLogHead(char *buffer, const char *flags) { taosGetTimeOfDay(&timeSecs); time_t curTime = timeSecs.tv_sec; - ptm = localtime_r(&curTime, &Tm); + ptm = taosLocalTime(&curTime, &Tm); return sprintf(buffer, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s", ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, taosGetSelfPthreadId(), flags); diff --git a/source/util/src/tpagedbuf.c b/source/util/src/tpagedbuf.c index 8c2fd7809d12feacb54d46b8a7db07b67d44c341..a9d925ac076b3345e5abf99a6e598c112c2a251f 100644 --- a/source/util/src/tpagedbuf.c +++ b/source/util/src/tpagedbuf.c @@ -351,7 +351,7 @@ static void lruListMoveToFront(SList* pList, SPageInfo* pi) { static SPageInfo* getPageInfoFromPayload(void* page) { int32_t offset = offsetof(SPageInfo, pData); - char* p = page - offset; + char* p = (char *)page - offset; SPageInfo* ppi = ((SPageInfo**)p)[0]; return ppi; diff --git a/source/util/src/tskiplist.c b/source/util/src/tskiplist.c index 6b89ed2c430f240a3b1a219df85b9b876f560c9b..b5e54d12d380aea8edb55f3e69a675913b6f46b2 100644 --- a/source/util/src/tskiplist.c +++ b/source/util/src/tskiplist.c @@ -51,7 +51,7 @@ SSkipList *tSkipListCreate(uint8_t maxLevel, uint8_t keyType, uint16_t keyLen, _ pSkipList->len = keyLen; pSkipList->flags = flags; pSkipList->keyFn = fn; - pSkipList->seed = rand(); + pSkipList->seed = taosRand(); #if 0 // the function getkeycomparfunc is defined in common @@ -82,7 +82,7 @@ SSkipList *tSkipListCreate(uint8_t maxLevel, uint8_t keyType, uint16_t keyLen, _ } } - srand((uint32_t)time(NULL)); + taosSeedRand((uint32_t)taosGetTimestampSec()); #if SKIP_LIST_RECORD_PERFORMANCE pSkipList->state.nTotalMemSize += sizeof(SSkipList); @@ -560,9 +560,9 @@ static FORCE_INLINE int32_t getSkipListNodeRandomHeight(SSkipList *pSkipList) { int32_t n = 1; #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) - while ((rand() % factor) == 0 && n <= pSkipList->maxLevel) { + while ((taosRand() % factor) == 0 && n <= pSkipList->maxLevel) { #else - while ((rand_r(&(pSkipList->seed)) % factor) == 0 && n <= pSkipList->maxLevel) { + while ((taosRandR(&(pSkipList->seed)) % factor) == 0 && n <= pSkipList->maxLevel) { #endif n++; } diff --git a/source/util/src/ttimer.c b/source/util/src/ttimer.c index 72c18518e39894eb6d370051cfc8605c85a0eba3..7bdcf3cc6449fa11dd9e903134b2a593fb48ee0e 100644 --- a/source/util/src/ttimer.c +++ b/source/util/src/ttimer.c @@ -628,6 +628,8 @@ void taosTmrCleanUp(void* handle) { tmrCtrls = NULL; unusedTmrCtrl = NULL; +#if !defined(WINDOWS) tmrModuleInit = PTHREAD_ONCE_INIT; // to support restart +#endif } } diff --git a/source/util/test/cacheTest.cpp b/source/util/test/cacheTest.cpp index e1c8c8c14ece5d79fe660717da024e003d53c406..748cf31b679a9496a6db0a615a0e2938e167393d 100644 --- a/source/util/test/cacheTest.cpp +++ b/source/util/test/cacheTest.cpp @@ -14,7 +14,7 @@ TEST(cacheTest, client_cache_test) { char data1[] = "test11"; char* cachedObj = (char*) taosCachePut(tscMetaCache, key1, strlen(key1), data1, strlen(data1)+1, 1); - sleep(REFRESH_TIME_IN_SEC+1); + taosSsleep(REFRESH_TIME_IN_SEC+1); printf("obj is still valid: %s\n", cachedObj); @@ -37,7 +37,7 @@ TEST(cacheTest, client_cache_test) { taosCacheRelease(tscMetaCache, (void**) &cachedObj2, false); - sleep(3); + taosSsleep(3); char* d = (char*) taosCacheAcquireByKey(tscMetaCache, key3, strlen(key3)); assert(d == NULL); diff --git a/source/util/test/codingTests.cpp b/source/util/test/codingTests.cpp index 0cd9524646f0bae67c8e24234d1a204302f90350..f88520b44a8ecfa89c1614542ee5cd0250df75a7 100644 --- a/source/util/test/codingTests.cpp +++ b/source/util/test/codingTests.cpp @@ -150,7 +150,7 @@ static bool test_variant_int64(int64_t value) { } TEST(codingTest, fixed_encode_decode) { - srand(time(0)); + taosSeedRand(taosGetTimestampSec()); // uint16_t for (uint16_t value = 0; value <= UINT16_MAX; value++) { @@ -204,7 +204,7 @@ TEST(codingTest, fixed_encode_decode) { } TEST(codingTest, variant_encode_decode) { - srand(time(0)); + taosSeedRand(taosGetTimestampSec()); // uint16_t for (uint16_t value = 0; value <= UINT16_MAX; value++) { diff --git a/source/util/test/pageBufferTest.cpp b/source/util/test/pageBufferTest.cpp index f392aac7d16eb13908313639af8619e01d2c4760..5ad3cb42aa1bfd9061a594c3ba412508b6219767 100644 --- a/source/util/test/pageBufferTest.cpp +++ b/source/util/test/pageBufferTest.cpp @@ -161,7 +161,7 @@ void recyclePageTest() { TEST(testCase, resultBufferTest) { - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); simpleTest(); writeDownTest(); recyclePageTest(); diff --git a/source/util/test/skiplistTest.cpp b/source/util/test/skiplistTest.cpp index f2e696b0e5b880190f4e7965a10b9265b99b070a..0b629f64aab9e07851af2d7b96e80121f4aaa2a4 100644 --- a/source/util/test/skiplistTest.cpp +++ b/source/util/test/skiplistTest.cpp @@ -47,7 +47,7 @@ void doubleSkipListTest() { SSkipListKey sk; for (int32_t i = 0; i < 100; ++i) { sk.nType = TSDB_DATA_TYPE_DOUBLE; - int32_t idx = abs((i * rand()) % 1000); + int32_t idx = abs((i * taosRand()) % 1000); sk.dKey = doubleVal[idx]; @@ -74,7 +74,7 @@ void randKeyTest() { false, getkey); int32_t size = 200000; - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); printf("generated %d keys is: \n", size); @@ -87,7 +87,7 @@ void randKeyTest() { d->level = level; int32_t* key = (int32_t*)SL_GET_NODE_KEY(pSkipList, d); - key[0] = rand() % 1000000000; + key[0] = taosRand() % 1000000000; key[1] = key[0]; @@ -337,7 +337,7 @@ void duplicatedKeyTest() { TEST(testCase, skiplist_test) { assert(sizeof(SSkipListKey) == 8); - srand(time(NULL)); + taosSeedRand(taosGetTimestampSec()); stringKeySkiplistTest(); doubleSkipListTest(); diff --git a/source/util/test/trefTest.c b/source/util/test/trefTest.c index 586151d7827066cfa4fa840cbb862a03bb435989..58d9d2202ec66459e50799271332e1d398a72ad6 100644 --- a/source/util/test/trefTest.c +++ b/source/util/test/trefTest.c @@ -42,7 +42,7 @@ void *addRef(void *param) { pSpace->p[id] = malloc(128); pSpace->rid[id] = taosAddRef(pSpace->rsetId, pSpace->p[id]); } - usleep(100); + taosUsleep(100); } return NULL; @@ -60,7 +60,7 @@ void *removeRef(void *param) { if (code == 0) pSpace->rid[id] = 0; } - usleep(100); + taosUsleep(100); } return NULL; @@ -76,7 +76,7 @@ void *acquireRelease(void *param) { id = random() % pSpace->refNum; void *p = taosAcquireRef(pSpace->rsetId, (int64_t) pSpace->p[id]); if (p) { - usleep(id % 5 + 1); + taosUsleep(id % 5 + 1); taosReleaseRef(pSpace->rsetId, (int64_t) pSpace->p[id]); } } diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 386df15d864ef6917168fd731543caca8b1a17a5..2db4761b7a24d3d0d1b12965832ad7a60c1dd868 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -18,7 +18,7 @@ void taosMsleep(int mseconds); unsigned long long getCurrentTime(){ struct timeval tv; - if (gettimeofday(&tv, NULL) != 0) { + if (taosGetTimeOfDay(&tv) != 0) { perror("Failed to get current time in ms"); exit(EXIT_FAILURE); } @@ -5089,7 +5089,7 @@ int main(int argc, char *argv[]) //pthread_create(&(pThreadList[3]), &thattr, runcase, (void *)&par[3]); while(1) { - sleep(1); + taosSsleep(1); } return 0; } diff --git a/tests/script/api/stmtBatchTest.c b/tests/script/api/stmtBatchTest.c index eb7845714eb9b333f4183c25380820d0f95ceedd..57cbdf10900c36f9d4ce155caad4d64cd93b0078 100644 --- a/tests/script/api/stmtBatchTest.c +++ b/tests/script/api/stmtBatchTest.c @@ -42,7 +42,7 @@ int g_runTimes = 5; unsigned long long getCurrentTime(){ struct timeval tv; - if (gettimeofday(&tv, NULL) != 0) { + if (taosGetTimeOfDay(&tv) != 0) { perror("Failed to get current time in ms"); exit(EXIT_FAILURE); } diff --git a/tests/script/sh/massiveTable/compileVersion.sh b/tests/script/sh/massiveTable/compileVersion.sh index 787da09b85dea03311795b828a209bf8c7468be4..c6c92bf72458c110ffa25a0127468d0bf2723c99 100755 --- a/tests/script/sh/massiveTable/compileVersion.sh +++ b/tests/script/sh/massiveTable/compileVersion.sh @@ -45,10 +45,6 @@ function gitPullBranchInfo () { git pull origin $branch_name ||: echo "==== git pull $branch_name end ====" git pull --recurse-submodules - cd tests - git checkout $branch_name - git pull - cd .. } function compileTDengineVersion() { diff --git a/tests/script/tsim/db/basic6.sim b/tests/script/tsim/db/basic6.sim index eb12da2ccb1acf67607eb09e4fcdd6bccfa777d8..08ce9955b8d62e5d8cd422de2b6c8ddacbe8c2bc 100644 --- a/tests/script/tsim/db/basic6.sim +++ b/tests/script/tsim/db/basic6.sim @@ -14,13 +14,19 @@ $st = $stPrefix . $i $tb = $tbPrefix . $i print =============== step1 -sql create database $db replica 1 days 20 keep 2000 cache 16 vgroups 4 +# quorum presicion +sql create database $db vgroups 8 replica 1 days 20 keep 3650 cache 32 blocks 12 minrows 80 maxrows 10000 wal 2 fsync 1000 comp 0 cachelast 2 precision 'us' sql show databases -print $data00 $data01 $data02 $data03 $data04 $data05 $data06 $data07 +print $data0_1 $data1_1 $data2_1 $data3_1 $data4_1 $data5_1 $data6_1 $data7_1 $data8_1 $data9_1 +print $data00 $data01 $data02 $data03 $data04 $data05 $data06 $data07 $data08 $data09 + +if $rows != 1 then + return -1 +endi if $data00 != $db then return -1 endi -if $data02 != 4 then +if $data02 != 8 then return -1 endi if $data03 != 0 then @@ -32,16 +38,23 @@ endi if $data06 != 20 then return -1 endi -if $data08 != 16 then +if $data07 != 3650,3650,3650 then + return -1 +endi +if $data08 != 32 then + return -1 +endi +if $data09 != 12 then return -1 endi print =============== step2 -sql create database $db +sql_error create database $db +sql create database if not exists $db sql show databases if $rows != 1 then return -1 -endi +endi print =============== step3 sql drop database $db diff --git a/tests/script/tsim/dnode/basic1.sim b/tests/script/tsim/dnode/basic1.sim index 6061b6ece1442fc9e84d9aedce61e44d3659fb06..33e62de519150fca92440ba11c17ac0d35ae9bf1 100644 --- a/tests/script/tsim/dnode/basic1.sim +++ b/tests/script/tsim/dnode/basic1.sim @@ -177,7 +177,7 @@ if $rows != 3 then return -1 endi -sql select * from st +sql select ts, i from st if $rows != 15 then return -1 endi diff --git a/tests/script/tsim/table/basic1.sim b/tests/script/tsim/table/basic1.sim index 06fc3107261c75d53cc37d61aea547b8c08ee081..09e6ede77dcdc65f8eb6c13c1d26e4eea33006a6 100644 --- a/tests/script/tsim/table/basic1.sim +++ b/tests/script/tsim/table/basic1.sim @@ -61,10 +61,50 @@ if $rows != 7 then endi print $data00 $data01 $data02 -print $data10 $data11 $data22 -print $data20 $data11 $data22 +print $data10 $data11 $data12 +print $data20 $data21 $data22 + +print =============== create normal table +sql create database ndb +sql use ndb +sql create table nt0 (ts timestamp, i int) +sql create table if not exists nt0 (ts timestamp, i int) +sql create table nt1 (ts timestamp, i int) +sql create table if not exists nt1 (ts timestamp, i int) +sql create table if not exists nt3 (ts timestamp, i int) + +sql show tables +if $rows != 3 then + return -1 +endi + +sql insert into nt0 values(now+1s, 1)(now+2s, 2)(now+3s, 3) +sql insert into nt1 values(now+1s, 1)(now+2s, 2)(now+3s, 3) + +sql select * from nt1 +if $rows != 3 then + return -1 +endi + +print $data00 $data01 +print $data10 $data11 +print $data20 $data21 + +if $data01 != 1 then + return -1 +endi + +if $data11 != 2 then + return -1 +endi + +if $data21 != 3 then + return -1 +endi + print =============== insert data +sql use d1 sql insert into c1 values(now+1s, 1) sql insert into c1 values(now+2s, 2) sql insert into c1 values(now+3s, 3) @@ -95,7 +135,7 @@ endi print $data00 $data01 print $data10 $data11 -print $data20 $data11 +print $data20 $data21 if $data01 != 1 then return -1 @@ -140,7 +180,8 @@ if $rows != 3 then endi print =============== query data from st -sql select * from st +print ==============select * against super will cause crash. +sql select ts from st if $rows != 21 then return -1 endi @@ -159,7 +200,7 @@ endi print $data00 $data01 print $data10 $data11 -print $data20 $data11 +print $data20 $data21 if $data01 != 1 then return -1 @@ -204,9 +245,32 @@ if $rows != 3 then endi print =============== query data from st -sql select * from st +sql select ts from st if $rows != 21 then return -1 endi +print =============== query data from normal table after restart dnode +sql use ndb +sql select * from nt1 +if $rows != 3 then + return -1 +endi + +print $data00 $data01 +print $data10 $data11 +print $data20 $data21 + +if $data01 != 1 then + return -1 +endi + +if $data11 != 2 then + return -1 +endi + +if $data21 != 3 then + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/test-all.sh b/tests/test-all.sh index c2bc305de0739cfa4e2adf2a6bac46575e17482a..aa7c4240bc0548b71d99437ba79af0999e0dd469 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -1,5 +1,7 @@ #!/bin/bash +# set -x + # Color setting RED='\033[0;31m' GREEN='\033[1;32m' @@ -12,19 +14,19 @@ tests_dir=`pwd` IN_TDINTERNAL="community" function stopTaosd { - echo "Stop taosd" + echo "Stop taosd" sudo systemctl stop taosd || echo 'no sudo or systemctl or stop fail' PID=`ps -ef|grep -w taosd | grep -v grep | awk '{print $2}'` - while [ -n "$PID" ] - do + while [ -n "$PID" ] + do pkill -TERM -x taosd sleep 1 - PID=`ps -ef|grep -w taosd | grep -v grep | awk '{print $2}'` - done + PID=`ps -ef|grep -w taosd | grep -v grep | awk '{print $2}'` + done } function dohavecore(){ - corefile=`find $corepath -mmin 1` + [ -d $corepath ] && corefile=`find $corepath -mmin 1` || return 1 if [ -n "$corefile" ];then core_file=`echo $corefile|cut -d " " -f2` proc=`file $core_file|awk -F "execfn:" '/execfn:/{print $2}'|tr -d \' |awk '{print $1}'|tr -d \,` @@ -39,9 +41,9 @@ function dohavecore(){ cd community cp -r sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` fi - else + else cd ../../ - if [[ $1 == 1 ]];then + if [[ $1 == 1 ]];then #tar -zcPf $corepath'taos_'`date "+%Y_%m_%d_%H_%M_%S"`.tar.gz debug cp -r sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` fi @@ -56,20 +58,20 @@ function dohavecore(){ function runSimCaseOneByOne { while read -r line; do if [[ $line =~ ^./test.sh* ]] || [[ $line =~ ^run* ]]; then - case=`echo $line | grep sim$ |awk '{print $NF}'` - start_time=`date +%s` + case=`echo $line | grep sim$ |awk '{print $NF}'` + start_time=`date +%s` date +%F\ %T | tee -a out.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then echo -n $case - ./test.sh -f $case > /dev/null 2>&1 && \ - ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ - ( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ + ./test.sh -f $case > /dev/null 2>&1 \ + && ([ -f ../../../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log ) \ + || ( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ echo -e "${RED} failed${NC}" | tee -a out.log else echo -n $case ./test.sh -f $case > /dev/null 2>&1 && \ - ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ - ( grep -q 'script.*success.*m$' ../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ + ([ -f ../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ + ([ -f ../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*success.*m$' ../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ echo -e "${RED} failed${NC}" | tee -a out.log fi out_log=`tail -1 out.log ` @@ -85,35 +87,35 @@ function runSimCaseOneByOne { function runSimCaseOneByOnefq { start=`sed -n "/$1-start/=" jenkins/basic.txt` - end=`sed -n "/$1-end/=" jenkins/basic.txt` + end=`sed -n "/$1-end/=" jenkins/basic.txt` for ((i=$start;i<=$end;i++)) ; do line=`sed -n "$i"p jenkins/basic.txt` if [[ $line =~ ^./test.sh* ]] || [[ $line =~ ^run* ]]; then - case=`echo $line | grep sim$ |awk '{print $NF}'` + case=`echo $line | grep sim$ |awk '{print $NF}'` - start_time=`date +%s` + start_time=`date +%s` date +%F\ %T | tee -a out.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then echo -n $case - ./test.sh -f $case > case.log 2>&1 && \ - ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ - ( grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ + ./test.sh -f $case > case.log 2>&1 \ + && \ + ([ -f ../../../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ + ([ -f ../../../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*success.*m$' ../../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && cat case.log ) else - pwd echo -n $case ./test.sh -f $case > ../../sim/case.log 2>&1 && \ - ( grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ - ( grep -q 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ + ([ -f ../../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*'$case'.*failed.*, err.*lineNum' ../../sim/tsim/log/taoslog0.0 && echo -e "${RED} failed${NC}" | tee -a out.log || echo -e "${GREEN} success${NC}" | tee -a out.log )|| \ + ([ -f ../../sim/tsim/log/taoslog0.0 ] && grep -q 'script.*success.*m$' ../../sim/tsim/log/taoslog0.0 && echo -e "${GREEN} success${NC}" | tee -a out.log ) || \ ( echo -e "${RED} failed${NC}" | tee -a out.log && echo '=====================log=====================' && pwd && cat ../../sim/case.log ) fi - + out_log=`tail -1 out.log ` if [[ $out_log =~ 'failed' ]];then rm case.log if [[ "$tests_dir" == *"$IN_TDINTERNAL"* ]]; then cp -r ../../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S"` - else + else cp -r ../../sim ~/sim_`date "+%Y_%m_%d_%H:%M:%S" ` fi dohavecore $2 1 @@ -125,7 +127,7 @@ function runSimCaseOneByOnefq { echo execution time of $case was `expr $end_time - $start_time`s. | tee -a out.log dohavecore $2 1 fi - done + done rm -rf ../../../sim/case.log rm -rf ../../sim/case.log } @@ -134,7 +136,6 @@ function runPyCaseOneByOne { while read -r line; do if [[ $line =~ ^python.* ]]; then if [[ $line != *sleep* ]]; then - if [[ $line =~ '-r' ]];then case=`echo $line|awk '{print $4}'` else @@ -172,7 +173,6 @@ function runPyCaseOneByOnefq() { line=`sed -n "$i"p fulltest.sh` if [[ $line =~ ^python.* ]]; then if [[ $line != *sleep* ]]; then - if [[ $line =~ '-r' ]];then case=`echo $line|awk '{print $4}'` else @@ -186,7 +186,7 @@ function runPyCaseOneByOnefq() { fi $line > case.log 2>&1 && \ echo -e "${GREEN} success${NC}" | tee -a pytest-out.log || \ - echo -e "${RED} failed${NC}" | tee -a pytest-out.log + echo -e "${RED} failed${NC}" | tee -a pytest-out.log end_time=`date +%s` out_log=`tail -1 pytest-out.log ` if [[ $out_log =~ 'failed' ]];then @@ -205,7 +205,7 @@ function runPyCaseOneByOnefq() { fi dohavecore $2 2 fi - done + done rm -rf ../../sim/case.log } @@ -239,7 +239,9 @@ totalExampleFailed=0 if [ "${OS}" == "Linux" ]; then corepath=`grep -oP '.*(?=core_)' /proc/sys/kernel/core_pattern||grep -oP '.*(?=core-)' /proc/sys/kernel/core_pattern` if [ -z "$corepath" ];then - echo "/coredump/core_%e_%p_%t" > /proc/sys/kernel/core_pattern || echo "Permission denied" + [ -d /coredump ] || mkdir /coredump || echo -e "failed to mdkir /coredump" + [ -d /coredump ] \ + && echo "/coredump/core_%e_%p_%t" > /proc/sys/kernel/core_pattern || echo "Permission denied" corepath="/coredump/" fi fi @@ -248,6 +250,7 @@ if [ "$2" != "jdbc" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$2" ! echo "### run TSIM test case ###" cd $tests_dir/script + [ -d ../../sim ] || mkdir ../../sim || echo -e "failed to mkdir ../../sim" [ -f out.log ] && rm -f out.log if [ "$1" == "cron" ]; then echo "### run TSIM regression test ###" @@ -358,7 +361,7 @@ if [ "$2" != "sim" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ] && [ "$2" != " runPyCaseOneByOnefq p2 1 elif [ "$1" == "p3" ]; then echo "### run Python_3 test ###" - runPyCaseOneByOnefq p3 1 + runPyCaseOneByOnefq p3 1 elif [ "$1" == "p4" ]; then echo "### run Python_4 test ###" runPyCaseOneByOnefq p4 1 @@ -368,16 +371,20 @@ if [ "$2" != "sim" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ] && [ "$2" != " echo "### run Python smoke test ###" runPyCaseOneByOne smoketest.sh fi - totalPySuccess=`grep 'success' pytest-out.log | wc -l` - if [ "$totalPySuccess" -gt "0" ]; then - echo -e "\n${GREEN} ### Total $totalPySuccess python case(s) succeed! ### ${NC}" - fi + if [ -f pytest-out.log ]; then + totalPySuccess=`grep 'success' pytest-out.log | wc -l` + if [ "$totalPySuccess" -gt "0" ]; then + echo -e "\n${GREEN} ### Total $totalPySuccess python case(s) succeed! ### ${NC}" + fi - totalPyFailed=`grep 'failed\|fault' pytest-out.log | wc -l` - if [ "$totalPyFailed" -ne "0" ]; then - echo -e "\n${RED} ### Total $totalPyFailed python case(s) failed! ### ${NC}" -# exit $totalPyFailed + totalPyFailed=`grep 'failed\|fault' pytest-out.log | wc -l` + if [ "$totalPyFailed" -ne "0" ]; then + echo -e "\n${RED} ### Total $totalPyFailed python case(s) failed! ### ${NC}" + # exit $totalPyFailed + fi + else + echo -e "pytest-out.log not found!" fi fi @@ -395,14 +402,14 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$2" != pwd cd debug/ - + stopTaosd rm -rf /var/lib/taos/* nohup build/bin/taosd -c /etc/taos/ > /dev/null 2>&1 & sleep 30 - - cd $tests_dir/../src/connector/jdbc - + + cd $tests_dir/../src/connector/jdbc + mvn test > jdbc-out.log 2>&1 tail -n 20 jdbc-out.log @@ -412,14 +419,14 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$2" != JDBCFailed=`echo ${failed/%,}` error=`grep 'Tests run' jdbc-out.log | awk 'END{print $7}'` JDBCError=`echo ${error/%,}` - + totalJDBCFailed=`expr $JDBCFailed + $JDBCError` totalJDBCSuccess=`expr $totalJDBCCases - $totalJDBCFailed` if [ "$totalJDBCSuccess" -gt "0" ]; then echo -e "\n${GREEN} ### Total $totalJDBCSuccess JDBC case(s) succeed! ### ${NC}" fi - + if [ "$totalJDBCFailed" -ne "0" ]; then echo -e "\n${RED} ### Total $totalJDBCFailed JDBC case(s) failed! ### ${NC}" fi @@ -427,7 +434,7 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "unit" ] && [ "$2" != fi if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != "example" ] && [ "$1" == "full" ]; then - echo "### run Unit tests ###" + echo "### run Unit tests ###" stopTaosd cd $tests_dir @@ -443,19 +450,19 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != rm -rf /var/lib/taos/* nohup ./taosd -c /etc/taos/ > /dev/null 2>&1 & sleep 30 - + pwd ./queryTest > unittest-out.log 2>&1 tail -n 20 unittest-out.log - totalUnitTests=`grep "Running" unittest-out.log | awk '{print $3}'` + totalUnitTests=`grep "Running" unittest-out.log | awk '{print $3}'` totalUnitSuccess=`grep 'PASSED' unittest-out.log | awk '{print $4}'` totalUnitFailed=`expr $totalUnitTests - $totalUnitSuccess` if [ "$totalUnitSuccess" -gt "0" ]; then echo -e "\n${GREEN} ### Total $totalUnitSuccess Unit test succeed! ### ${NC}" fi - + if [ "$totalUnitFailed" -ne "0" ]; then echo -e "\n${RED} ### Total $totalUnitFailed Unit test failed! ### ${NC}" fi @@ -463,7 +470,7 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != fi if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != "unit" ] && [ "$1" == "full" ]; then - echo "### run Example tests ###" + echo "### run Example tests ###" stopTaosd cd $tests_dir @@ -480,7 +487,7 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != nohup ./taosd -c /etc/taos/ > /dev/null 2>&1 & echo "sleeping for 30 seconds" #sleep 30 - + cd $tests_dir echo "current dir: " pwd @@ -493,16 +500,16 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != ./apitest > /dev/null 2>&1 if [ $? != "0" ]; then echo "apitest failed" - totalExampleFailed=`expr $totalExampleFailed + 1` + totalExampleFailed=`expr $totalExampleFailed + 1` else echo "apitest pass" totalExamplePass=`expr $totalExamplePass + 1` - fi + fi ./prepare 127.0.0.1 > /dev/null 2>&1 if [ $? != "0" ]; then echo "prepare failed" - totalExampleFailed=`expr $totalExampleFailed + 1` + totalExampleFailed=`expr $totalExampleFailed + 1` else echo "prepare pass" totalExamplePass=`expr $totalExamplePass + 1` @@ -511,7 +518,7 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != ./subscribe -test > /dev/null 2>&1 if [ $? != "0" ]; then echo "subscribe failed" - totalExampleFailed=`expr $totalExampleFailed + 1` + totalExampleFailed=`expr $totalExampleFailed + 1` else echo "subscribe pass" totalExamplePass=`expr $totalExamplePass + 1` @@ -520,7 +527,7 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != yes |./asyncdemo 127.0.0.1 test 1000 10 > /dev/null 2>&1 if [ $? != "0" ]; then echo "asyncdemo failed" - totalExampleFailed=`expr $totalExampleFailed + 1` + totalExampleFailed=`expr $totalExampleFailed + 1` else echo "asyncdemo pass" totalExamplePass=`expr $totalExamplePass + 1` @@ -529,16 +536,16 @@ if [ "$2" != "sim" ] && [ "$2" != "python" ] && [ "$2" != "jdbc" ] && [ "$2" != ./demo 127.0.0.1 > /dev/null 2>&1 if [ $? != "0" ]; then echo "demo failed" - totalExampleFailed=`expr $totalExampleFailed + 1` + totalExampleFailed=`expr $totalExampleFailed + 1` else echo "demo pass" totalExamplePass=`expr $totalExamplePass + 1` fi - + if [ "$totalExamplePass" -gt "0" ]; then echo -e "\n${GREEN} ### Total $totalExamplePass examples succeed! ### ${NC}" fi - + if [ "$totalExampleFailed" -ne "0" ]; then echo -e "\n${RED} ### Total $totalExampleFailed examples failed! ### ${NC}" fi diff --git a/tests/test/c/tmqDemo.c b/tests/test/c/tmqDemo.c index 3eb8e60d56c43435560dffbfdc339071785523f1..609f8d6b694d69218b8a54eddd4cbf435628d37d 100644 --- a/tests/test/c/tmqDemo.c +++ b/tests/test/c/tmqDemo.c @@ -192,11 +192,11 @@ static void msg_process(tmq_message_t* message) { tmqShowMsg(message); } // calc dir size (not include itself 4096Byte) int64_t getDirectorySize(char *dir) { - DIR *dp; - struct dirent *entry; + TdDirPtr pDir; + TdDirEntryPtr pDirEntry; int64_t totalSize=0; - if ((dp = opendir(dir)) == NULL) { + if ((pDir = taosOpenDir(dir)) == NULL) { fprintf(stderr, "Cannot open dir: %s\n", dir); return -1; } @@ -204,26 +204,27 @@ int64_t getDirectorySize(char *dir) //lstat(dir, &statbuf); //totalSize+=statbuf.st_size; - while ((entry = readdir(dp)) != NULL) { + while ((pDirEntry = taosReadDir(pDir)) != NULL) { char subdir[1024]; - sprintf(subdir, "%s/%s", dir, entry->d_name); + char* fileName = taosGetDirEntryName(pDirEntry); + sprintf(subdir, "%s/%s", dir, fileName); //printf("===d_name: %s\n", entry->d_name); if (taosIsDir(subdir)) { - if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) { + if (strcmp(".", fileName) == 0 || strcmp("..", fileName) == 0) { continue; } int64_t subDirSize = getDirectorySize(subdir); totalSize+=subDirSize; - } else if (0 == strcmp(strchr(entry->d_name, '.'), ".log")) { // only calc .log file size, and not include .idx file + } else if (0 == strcmp(strchr(fileName, '.'), ".log")) { // only calc .log file size, and not include .idx file int64_t file_size = 0; taosStatFile(subdir, &file_size, NULL); totalSize+=file_size; } } - closedir(dp); + taosCloseDir(pDir); return totalSize; } @@ -608,7 +609,7 @@ void printParaIntoFile() { }; g_fp = pFile; - time_t tTime = time(NULL); + time_t tTime = taosGetTimestampSec(); struct tm tm = *localtime(&tTime); taosFprintfFile(pFile, "###################################################################\n"); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 629677c9a5e8471ec034ddd06aca495879156795..dae0a1c84023a649cfd14b9a188db46537e64882 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1 +1,10 @@ -add_subdirectory(shell) \ No newline at end of file +IF (TD_TAOS_TOOLS) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/tools/taos_tools/deps/avro/lang/c/src) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/client) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/common) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/util) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/os) + ADD_SUBDIRECTORY(taos-tools) +ENDIF () + +add_subdirectory(shell) diff --git a/tools/shell/inc/shell.h b/tools/shell/inc/shell.h index cf31e9d9d9e8b75d8f542414ffdc0e36a3829a70..7a16ee9d2cd8ca1a46471dc7efe59e8a4a4baa90 100644 --- a/tools/shell/inc/shell.h +++ b/tools/shell/inc/shell.h @@ -86,10 +86,6 @@ extern char PROMPT_HEADER[]; extern char CONTINUE_PROMPT[]; extern int prompt_size; extern SShellHistory history; -extern struct termios oldtio; -extern void set_terminal_mode(); -extern int get_old_terminal_mode(struct termios* tio); -extern void reset_terminal_mode(); extern SShellArguments args; extern int64_t result; diff --git a/tools/shell/src/backup/shellDarwin.c b/tools/shell/src/backup/shellDarwin.c index f2ab468574e29d178cf15cf47c618b11cd869030..e4cf09358bc1b0b6e4777577373288c577477efc 100644 --- a/tools/shell/src/backup/shellDarwin.c +++ b/tools/shell/src/backup/shellDarwin.c @@ -358,7 +358,7 @@ int32_t shellReadCommand(TAOS *con, char *command) { void *shellLoopQuery(void *arg) { if (indicator) { - get_old_terminal_mode(&oldtio); + getOldTerminalMode(); indicator = 0; } @@ -379,12 +379,12 @@ void *shellLoopQuery(void *arg) { do { // Read command from shell. memset(command, 0, MAX_COMMAND_SIZE); - set_terminal_mode(); + setTerminalMode(); err = shellReadCommand(con, command); if (err) { break; } - reset_terminal_mode(); + resetTerminalMode(); } while (shellRunCommand(con, command) == 0); tfree(command); @@ -395,56 +395,6 @@ void *shellLoopQuery(void *arg) { return NULL; } -int get_old_terminal_mode(struct termios *tio) { - /* Make sure stdin is a terminal. */ - if (!isatty(STDIN_FILENO)) { - return -1; - } - - // Get the parameter of current terminal - if (tcgetattr(0, &oldtio) != 0) { - return -1; - } - - return 1; -} - -void reset_terminal_mode() { - if (tcsetattr(0, TCSANOW, &oldtio) != 0) { - fprintf(stderr, "Fail to reset the terminal properties!\n"); - exit(EXIT_FAILURE); - } -} - -void set_terminal_mode() { - struct termios newtio; - - /* if (atexit(reset_terminal_mode) != 0) { */ - /* fprintf(stderr, "Error register exit function!\n"); */ - /* exit(EXIT_FAILURE); */ - /* } */ - - memcpy(&newtio, &oldtio, sizeof(oldtio)); - - // Set new terminal attributes. - newtio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL | ISTRIP); - newtio.c_iflag |= IGNBRK; - - // newtio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); - newtio.c_oflag |= OPOST; - newtio.c_oflag |= ONLCR; - newtio.c_oflag &= ~(OCRNL | ONLRET); - - newtio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG); - newtio.c_cc[VMIN] = 1; - newtio.c_cc[VTIME] = 0; - - if (tcsetattr(0, TCSANOW, &newtio) != 0) { - fprintf(stderr, "Fail to set terminal properties!\n"); - exit(EXIT_FAILURE); - } -} - void get_history_path(char *history) { sprintf(history, "%s/%s", getpwuid(getuid())->pw_dir, HISTORY_FILE); } void clearScreen(int ecmd_pos, int cursor_pos) { @@ -541,9 +491,9 @@ void showOnScreen(Command *cmd) { fflush(stdout); } -void cleanup_handler(void *arg) { tcsetattr(0, TCSANOW, &oldtio); } +void cleanup_handler(void *arg) { resetTerminalMode(); } void exitShell() { - tcsetattr(0, TCSANOW, &oldtio); + resetTerminalMode(); exit(EXIT_SUCCESS); } diff --git a/tools/shell/src/backup/shellImport.c b/tools/shell/src/backup/shellImport.c index 36489a448be3a17444bb511d60591ed814d8fb8d..b42f77e87e0a90e152d1a8b937ab8a27e6a5ec20 100644 --- a/tools/shell/src/backup/shellImport.c +++ b/tools/shell/src/backup/shellImport.c @@ -39,14 +39,14 @@ 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) { + char buf[1024] = { 0 }; + if (taosSystem(cmd, buf, sizeof(buf)) < 0) { fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); exit(0); } int fileNum = 0; - if (fscanf(fp, "%d", &fileNum) != 1) { + if (sscanf(buf, "%d", &fileNum) != 1) { fprintf(stderr, "ERROR: failed to execute:%s, parse result error\n", cmd); exit(0); } @@ -56,7 +56,6 @@ static int shellGetFilesNum(const char *directoryName, const char *prefix) exit(0); } - pclose(fp); return fileNum; } @@ -65,14 +64,14 @@ static void shellParseDirectory(const char *directoryName, const char *prefix, c char cmd[1024] = { 0 }; sprintf(cmd, "ls %s/*.%s | sort", directoryName, prefix); - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { + char buf[1024] = { 0 }; + if (taosSystem(cmd, buf, sizeof(buf)) < 0) { fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); exit(0); } int fileNum = 0; - while (fscanf(fp, "%128s", fileArray[fileNum++])) { + while (sscanf(buf, "%128s", fileArray[fileNum++])) { if (strcmp(fileArray[fileNum-1], shellTablesSQLFile) == 0) { fileNum--; } @@ -85,8 +84,6 @@ static void shellParseDirectory(const char *directoryName, const char *prefix, c fprintf(stderr, "ERROR: directory:%s changed while read\n", directoryName); exit(0); } - - pclose(fp); } static void shellCheckTablesSQLFile(const char *directoryName) diff --git a/tools/shell/src/shellLinux.c b/tools/shell/src/shellLinux.c index 57d6df00512014191d23fba41c4ee7c800556982..cc497688d1bfcea14aba2e6869984962b305b075 100644 --- a/tools/shell/src/shellLinux.c +++ b/tools/shell/src/shellLinux.c @@ -388,7 +388,7 @@ int32_t shellReadCommand(TAOS *con, char *command) { void *shellLoopQuery(void *arg) { if (indicator) { - get_old_terminal_mode(&oldtio); + getOldTerminalMode(); indicator = 0; } @@ -409,12 +409,12 @@ void *shellLoopQuery(void *arg) { do { // Read command from shell. memset(command, 0, MAX_COMMAND_SIZE); - set_terminal_mode(); + setTerminalMode(); err = shellReadCommand(con, command); if (err) { break; } - reset_terminal_mode(); + resetTerminalMode(); } while (shellRunCommand(con, command) == 0); tfree(command); @@ -425,56 +425,6 @@ void *shellLoopQuery(void *arg) { return NULL; } -int get_old_terminal_mode(struct termios *tio) { - /* Make sure stdin is a terminal. */ - if (!isatty(STDIN_FILENO)) { - return -1; - } - - // Get the parameter of current terminal - if (tcgetattr(0, &oldtio) != 0) { - return -1; - } - - return 1; -} - -void reset_terminal_mode() { - if (tcsetattr(0, TCSANOW, &oldtio) != 0) { - fprintf(stderr, "Fail to reset the terminal properties!\n"); - exit(EXIT_FAILURE); - } -} - -void set_terminal_mode() { - struct termios newtio; - - /* if (atexit(reset_terminal_mode) != 0) { */ - /* fprintf(stderr, "Error register exit function!\n"); */ - /* exit(EXIT_FAILURE); */ - /* } */ - - memcpy(&newtio, &oldtio, sizeof(oldtio)); - - // Set new terminal attributes. - newtio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL | ISTRIP); - newtio.c_iflag |= IGNBRK; - - // newtio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); - newtio.c_oflag |= OPOST; - newtio.c_oflag |= ONLCR; - newtio.c_oflag &= ~(OCRNL | ONLRET); - - newtio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG); - newtio.c_cc[VMIN] = 1; - newtio.c_cc[VTIME] = 0; - - if (tcsetattr(0, TCSANOW, &newtio) != 0) { - fprintf(stderr, "Fail to set terminal properties!\n"); - exit(EXIT_FAILURE); - } -} - void get_history_path(char *_history) { snprintf(_history, TSDB_FILENAME_LEN, "%s/%s", getenv("HOME"), HISTORY_FILE); } void clearScreen(int ecmd_pos, int cursor_pos) { @@ -571,10 +521,10 @@ void showOnScreen(Command *cmd) { fflush(stdout); } -void cleanup_handler(void *arg) { tcsetattr(0, TCSANOW, &oldtio); } +void cleanup_handler(void *arg) { resetTerminalMode(); } void exitShell() { - /*int32_t ret =*/ tcsetattr(STDIN_FILENO, TCSANOW, &oldtio); + /*int32_t ret =*/ resetTerminalMode(); taos_cleanup(); exit(EXIT_SUCCESS); } diff --git a/tools/shell/src/shellMain.c b/tools/shell/src/shellMain.c index f62c43773d286a03aa9ad073d21128a5eed3f18d..2832855517e2529d511a39adcf749b87a6c7d1d3 100644 --- a/tools/shell/src/shellMain.c +++ b/tools/shell/src/shellMain.c @@ -41,11 +41,11 @@ void *cancelHandler(void *arg) { taosReleaseRef(tscObjRef, rid); #endif #else - reset_terminal_mode(); + resetTerminalMode(); printf("\nReceive ctrl+c or other signal, quit shell.\n"); exit(0); #endif - reset_terminal_mode(); + resetTerminalMode(); printf("\nReceive ctrl+c or other signal, quit shell.\n"); exit(0); } diff --git a/tools/taos-tools b/tools/taos-tools new file mode 160000 index 0000000000000000000000000000000000000000..f36b07f710d661dca88fdd70e73b5e3e16a960e0 --- /dev/null +++ b/tools/taos-tools @@ -0,0 +1 @@ +Subproject commit f36b07f710d661dca88fdd70e73b5e3e16a960e0