Merge pull request #28486 from taosdata/feat/TS-4989-3.0

enh: add new key words for shell
This commit is contained in:
Shengliang Guan 2024-10-29 10:41:05 +08:00 committed by GitHub
commit a11ad2a871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 424 additions and 112 deletions

View File

@ -49,3 +49,32 @@ target_include_directories(
) )
SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos)
#
# generator library shell_ut for uint test
#
IF(TD_LINUX)
# include
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
# shell_ut library
add_library(shell_ut STATIC ${SHELL_SRC})
IF(TD_WEBSOCKET)
ADD_DEPENDENCIES(shell_ut taosws-rs)
ENDIF()
target_link_libraries(shell_ut PUBLIC taos ${LINK_WEBSOCKET} ${LINK_JEMALLOC} ${LINK_ARGP})
target_link_libraries(shell_ut PRIVATE os common transport geometry util)
# util depends
target_link_directories(
shell_ut
PUBLIC "${TD_SOURCE_DIR}/contrib/lzma2"
PUBLIC "${TD_SOURCE_DIR}/contrib/pcre2"
)
# unit test
IF(${BUILD_TEST})
ADD_SUBDIRECTORY(test)
ENDIF(${BUILD_TEST})
ENDIF()

View File

@ -16,6 +16,10 @@
#ifndef __SHELL_AUTO__ #ifndef __SHELL_AUTO__
#define __SHELL_AUTO__ #define __SHELL_AUTO__
#ifdef __cplusplus
extern "C" {
#endif
#include "shellInt.h" #include "shellInt.h"
#define TAB_KEY 0x09 #define TAB_KEY 0x09
@ -47,4 +51,15 @@ void showAD(bool end);
// show all commands help // show all commands help
void showHelp(); void showHelp();
//
// for unit test
//
bool fieldOptionsArea(char* p);
bool isCreateFieldsArea(char* p);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -46,6 +46,7 @@ typedef struct SWord {
int32_t len; int32_t len;
struct SWord* next; struct SWord* next;
bool free; // if true need free bool free; // if true need free
bool end; // if true is last keyword
} SWord; } SWord;
typedef struct { typedef struct {
@ -95,59 +96,62 @@ SWords shellCommands[] = {
"<db_options> <anyword> <db_options> <anyword> ;", 0, 0, NULL}, "<db_options> <anyword> <db_options> <anyword> ;", 0, 0, NULL},
{"create dnode <anyword>", 0, 0, NULL}, {"create dnode <anyword>", 0, 0, NULL},
{"create index <anyword> on <stb_name> ()", 0, 0, NULL}, {"create index <anyword> on <stb_name> ()", 0, 0, NULL},
{"create mnode on dnode <dnode_id> ;", 0, 0, NULL}, {"create mnode on dnode <dnode_id>;", 0, 0, NULL},
{"create qnode on dnode <dnode_id> ;", 0, 0, NULL}, {"create qnode on dnode <dnode_id>;", 0, 0, NULL},
{"create stream <anyword> into <anyword> as select", 0, 0, NULL}, // 26 append sub sql {"create stream <anyword> into <anyword> as select", 0, 0, NULL}, // 26 append sub sql
{"create topic <anyword> as select", 0, 0, NULL}, // 27 append sub sql {"create topic <anyword> as select", 0, 0, NULL}, // 27 append sub sql
{"create function <anyword> as <anyword> outputtype <data_types> language <udf_language>", 0, 0, NULL}, {"create tsma <anyword> on <all_table> function", 0, 0, NULL},
{"create or replace <anyword> as <anyword> outputtype <data_types> language <udf_language>", 0, 0, NULL}, {"create recursive tsma <anyword> on <tsma_name> interval(", 0, 0, NULL},
{"create aggregate function <anyword> as <anyword> outputtype <data_types> bufsize <anyword> language <udf_language>", 0, 0, NULL}, {"create function <anyword> as <anyword> outputtype <data_types> language <udf_language>;", 0, 0, NULL},
{"create or replace aggregate function <anyword> as <anyword> outputtype <data_types> bufsize <anyword> language <udf_language>", 0, 0, NULL}, {"create or replace <anyword> as <anyword> outputtype <data_types> language <udf_language>;", 0, 0, NULL},
{"create aggregate function <anyword> as <anyword> outputtype <data_types> bufsize <anyword> language <udf_language>;", 0, 0, NULL},
{"create or replace aggregate function <anyword> as <anyword> outputtype <data_types> bufsize <anyword> language <udf_language>;", 0, 0, NULL},
{"create user <anyword> pass <anyword> sysinfo 0;", 0, 0, NULL}, {"create user <anyword> pass <anyword> sysinfo 0;", 0, 0, NULL},
{"create user <anyword> pass <anyword> sysinfo 1;", 0, 0, NULL}, {"create user <anyword> pass <anyword> sysinfo 1;", 0, 0, NULL},
#ifdef TD_ENTERPRISE #ifdef TD_ENTERPRISE
{"create view <anyword> as select", 0, 0, NULL}, {"create view <anyword> as select", 0, 0, NULL},
{"compact database <db_name>", 0, 0, NULL}, {"compact database <db_name>", 0, 0, NULL},
#endif #endif
{"describe <all_table>", 0, 0, NULL}, {"describe <all_table>;", 0, 0, NULL},
{"delete from <all_table> where ", 0, 0, NULL}, {"delete from <all_table> where ", 0, 0, NULL},
{"drop database <db_name>", 0, 0, NULL}, {"drop database <db_name>;", 0, 0, NULL},
{"drop index <anyword>", 0, 0, NULL}, {"drop index <anyword>;", 0, 0, NULL},
{"drop table <all_table>", 0, 0, NULL}, {"drop table <all_table>;", 0, 0, NULL},
{"drop dnode <dnode_id>", 0, 0, NULL}, {"drop dnode <dnode_id>;", 0, 0, NULL},
{"drop mnode on dnode <dnode_id> ;", 0, 0, NULL}, {"drop mnode on dnode <dnode_id>;", 0, 0, NULL},
{"drop qnode on dnode <dnode_id> ;", 0, 0, NULL}, {"drop qnode on dnode <dnode_id>;", 0, 0, NULL},
{"drop user <user_name> ;", 0, 0, NULL}, {"drop user <user_name>;", 0, 0, NULL},
// 40 // 40
{"drop function <udf_name> ;", 0, 0, NULL}, {"drop function <udf_name>;", 0, 0, NULL},
{"drop consumer group <anyword> on ", 0, 0, NULL}, {"drop consumer group <anyword> on ", 0, 0, NULL},
{"drop topic <topic_name> ;", 0, 0, NULL}, {"drop topic <topic_name>;", 0, 0, NULL},
{"drop stream <stream_name> ;", 0, 0, NULL}, {"drop stream <stream_name>;", 0, 0, NULL},
{"explain select", 0, 0, NULL}, // 44 append sub sql {"drop tsma <tsma_name>;", 0, 0, NULL},
{"flush database <db_name> ;", 0, 0, NULL}, {"explain select ", 0, 0, NULL}, // 44 append sub sql
{"flush database <db_name>;", 0, 0, NULL},
{"help;", 0, 0, NULL}, {"help;", 0, 0, NULL},
{"grant all on <anyword> to <user_name> ;", 0, 0, NULL}, {"grant all on <anyword> to <user_name>;", 0, 0, NULL},
{"grant read on <anyword> to <user_name> ;", 0, 0, NULL}, {"grant read on <anyword> to <user_name>;", 0, 0, NULL},
{"grant write on <anyword> to <user_name> ;", 0, 0, NULL}, {"grant write on <anyword> to <user_name>;", 0, 0, NULL},
{"kill connection <anyword> ;", 0, 0, NULL}, {"kill connection <anyword>;", 0, 0, NULL},
{"kill query ", 0, 0, NULL}, {"kill query ", 0, 0, NULL},
{"kill transaction ", 0, 0, NULL}, {"kill transaction ", 0, 0, NULL},
#ifdef TD_ENTERPRISE #ifdef TD_ENTERPRISE
{"merge vgroup <vgroup_id> <vgroup_id>", 0, 0, NULL}, {"merge vgroup <vgroup_id> <vgroup_id>;", 0, 0, NULL},
#endif #endif
{"pause stream <stream_name> ;", 0, 0, NULL}, {"pause stream <stream_name>;", 0, 0, NULL},
#ifdef TD_ENTERPRISE #ifdef TD_ENTERPRISE
{"redistribute vgroup <vgroup_id> dnode <dnode_id> ;", 0, 0, NULL}, {"redistribute vgroup <vgroup_id> dnode <dnode_id>;", 0, 0, NULL},
#endif #endif
{"resume stream <stream_name> ;", 0, 0, NULL}, {"resume stream <stream_name>;", 0, 0, NULL},
{"reset query cache;", 0, 0, NULL}, {"reset query cache;", 0, 0, NULL},
{"restore dnode <dnode_id> ;", 0, 0, NULL}, {"restore dnode <dnode_id>;", 0, 0, NULL},
{"restore vnode on dnode <dnode_id> ;", 0, 0, NULL}, {"restore vnode on dnode <dnode_id>;", 0, 0, NULL},
{"restore mnode on dnode <dnode_id> ;", 0, 0, NULL}, {"restore mnode on dnode <dnode_id>;", 0, 0, NULL},
{"restore qnode on dnode <dnode_id> ;", 0, 0, NULL}, {"restore qnode on dnode <dnode_id>;", 0, 0, NULL},
{"revoke all on <anyword> from <user_name> ;", 0, 0, NULL}, {"revoke all on <anyword> from <user_name>;", 0, 0, NULL},
{"revoke read on <anyword> from <user_name> ;", 0, 0, NULL}, {"revoke read on <anyword> from <user_name>;", 0, 0, NULL},
{"revoke write on <anyword> from <user_name> ;", 0, 0, NULL}, {"revoke write on <anyword> from <user_name>;", 0, 0, NULL},
{"select * from <all_table>", 0, 0, NULL}, {"select * from <all_table>", 0, 0, NULL},
{"select client_version();", 0, 0, NULL}, {"select client_version();", 0, 0, NULL},
// 60 // 60
@ -160,15 +164,17 @@ SWords shellCommands[] = {
{"select timezone();", 0, 0, NULL}, {"select timezone();", 0, 0, NULL},
{"set max_binary_display_width ", 0, 0, NULL}, {"set max_binary_display_width ", 0, 0, NULL},
{"show apps;", 0, 0, NULL}, {"show apps;", 0, 0, NULL},
{"show alive;", 0, 0, NULL},
{"show create database <db_name> \\G;", 0, 0, NULL}, {"show create database <db_name> \\G;", 0, 0, NULL},
{"show create stable <stb_name> \\G;", 0, 0, NULL}, {"show create stable <stb_name> \\G;", 0, 0, NULL},
{"show create table <tb_name> \\G;", 0, 0, NULL}, {"show create table <tb_name> \\G;", 0, 0, NULL},
#ifdef TD_ENTERPRISE #ifdef TD_ENTERPRISE
{"show create view <all_table> \\G;", 0, 0, NULL}, {"show create view <all_table> \\G;", 0, 0, NULL},
#endif
{"show connections;", 0, 0, NULL},
{"show compact", 0, 0, NULL}, {"show compact", 0, 0, NULL},
{"show compacts;", 0, 0, NULL}, {"show compacts;", 0, 0, NULL},
#endif
{"show connections;", 0, 0, NULL},
{"show cluster;", 0, 0, NULL}, {"show cluster;", 0, 0, NULL},
{"show cluster alive;", 0, 0, NULL}, {"show cluster alive;", 0, 0, NULL},
{"show cluster machines;", 0, 0, NULL}, {"show cluster machines;", 0, 0, NULL},
@ -190,16 +196,17 @@ SWords shellCommands[] = {
{"show subscriptions;", 0, 0, NULL}, {"show subscriptions;", 0, 0, NULL},
{"show tables;", 0, 0, NULL}, {"show tables;", 0, 0, NULL},
{"show tables like", 0, 0, NULL}, {"show tables like", 0, 0, NULL},
{"show table distributed <all_table>", 0, 0, NULL}, {"show table distributed <all_table>;", 0, 0, NULL},
{"show tags from <tb_name>", 0, 0, NULL}, {"show tags from <tb_name>;", 0, 0, NULL},
{"show tags from <db_name>", 0, 0, NULL}, {"show table tags from <all_table>;", 0, 0, NULL},
{"show table tags from <all_table>", 0, 0, NULL},
{"show topics;", 0, 0, NULL}, {"show topics;", 0, 0, NULL},
{"show transactions;", 0, 0, NULL}, {"show transactions;", 0, 0, NULL},
{"show tsmas;", 0, 0, NULL},
{"show users;", 0, 0, NULL}, {"show users;", 0, 0, NULL},
{"show variables;", 0, 0, NULL}, {"show variables;", 0, 0, NULL},
{"show local variables;", 0, 0, NULL}, {"show local variables;", 0, 0, NULL},
{"show vnodes <dnode_id>", 0, 0, NULL}, {"show vnodes;", 0, 0, NULL},
{"show vnodes on dnode <dnode_id>;", 0, 0, NULL},
{"show vgroups;", 0, 0, NULL}, {"show vgroups;", 0, 0, NULL},
{"show consumers;", 0, 0, NULL}, {"show consumers;", 0, 0, NULL},
{"show grants;", 0, 0, NULL}, {"show grants;", 0, 0, NULL},
@ -207,22 +214,26 @@ SWords shellCommands[] = {
{"show grants logs;", 0, 0, NULL}, {"show grants logs;", 0, 0, NULL},
#ifdef TD_ENTERPRISE #ifdef TD_ENTERPRISE
{"show views;", 0, 0, NULL}, {"show views;", 0, 0, NULL},
{"split vgroup <vgroup_id>", 0, 0, NULL}, {"show arbgroups;", 0, 0, NULL},
{"split vgroup <vgroup_id>;", 0, 0, NULL},
{"s3migrate database <db_name>;", 0, 0, NULL},
#endif #endif
{"insert into <tb_name> values(", 0, 0, NULL}, {"insert into <tb_name> values(", 0, 0, NULL},
{"insert into <tb_name> using <stb_name> tags(", 0, 0, NULL}, {"insert into <tb_name> using <stb_name> tags(", 0, 0, NULL},
{"insert into <tb_name> using <stb_name> <anyword> values(", 0, 0, NULL}, {"insert into <tb_name> using <stb_name> <anyword> values(", 0, 0, NULL},
{"insert into <tb_name> file ", 0, 0, NULL}, {"insert into <tb_name> file ", 0, 0, NULL},
{"trim database <db_name>", 0, 0, NULL}, {"trim database <db_name>;", 0, 0, NULL},
{"s3migrate database <db_name>", 0, 0, NULL}, {"use <db_name>;", 0, 0, NULL},
{"use <db_name>", 0, 0, NULL},
{"quit", 0, 0, NULL}}; {"quit", 0, 0, NULL}};
// where keyword
char* keywords[] = { char* keywords[] = {
"and ", "asc ", "desc ", "from ", "fill(", "limit ", "where ", "where ", "and ", "asc ", "desc ", "from ", "fill(", "limit ",
"interval(", "order by ", "order by ", "offset ", "or ", "group by ", "now()", "interval(", "order by ", "order by ", "offset ", "or ", "group by ", "now()",
"session(", "sliding ", "slimit ", "soffset ", "state_window(", "today() ", "union all select ", "session(", "sliding ", "slimit ", "soffset ", "state_window(", "today() ", "union all select ",
"partition by "}; "partition by ", "match", "nmatch ", "between ", "like ", "is null ", "is not null ",
"event_window ", "count_window("
};
char* functions[] = { char* functions[] = {
"count(", "sum(", "count(", "sum(",
@ -255,6 +266,20 @@ char* functions[] = {
"timezone(", "timetruncate(", "timezone(", "timetruncate(",
"twa(", "to_unixtimestamp(", "twa(", "to_unixtimestamp(",
"unique(", "upper(", "unique(", "upper(",
"pi(", "round(",
"truncate(", "exp(",
"ln(", "mod(",
"rand(", "sign(",
"degrees(", "radians(",
"greatest(", "least(",
"char_length(", "char(",
"ascii(", "position(",
"trim(", "replace(",
"repeat(", "substring(",
"substring_index(","timediff(",
"week(", "weekday(",
"weekofyear(", "dayofweek(",
"stddev_pop(", "var_pop("
}; };
char* tb_actions[] = { char* tb_actions[] = {
@ -275,7 +300,7 @@ char* db_options[] = {"keep ",
"cachesize ", "cachesize ",
"comp ", "comp ",
"duration ", "duration ",
"wal_fsync_period", "wal_fsync_period ",
"maxrows ", "maxrows ",
"minrows ", "minrows ",
"pages ", "pages ",
@ -284,17 +309,22 @@ char* db_options[] = {"keep ",
"wal_level ", "wal_level ",
"vgroups ", "vgroups ",
"single_stable ", "single_stable ",
"s3_chunksize ", "s3_chunksize ",
"s3_keeplocal ", "s3_keeplocal ",
"s3_compact ", "s3_compact ",
"wal_retention_period ", "wal_retention_period ",
"wal_roll_period ", "wal_roll_period ",
"wal_retention_size ", "wal_retention_size ",
"wal_segment_size "}; #ifdef TD_ENTERPRISE
"encrypt_algorithm "
#endif
"keep_time_offset ",
"wal_segment_size "
};
char* alter_db_options[] = {"cachemodel ", "replica ", "keep ", "stt_trigger ", char* alter_db_options[] = {"cachemodel ", "replica ", "keep ", "stt_trigger ",
"wal_retention_period ", "wal_retention_size ", "cachesize ", "wal_retention_period ", "wal_retention_size ", "cachesize ",
"s3_keeplocal ", "s3_compact ", "s3_keeplocal ", "s3_compact ",
"wal_fsync_period ", "buffer ", "pages " ,"wal_level "}; "wal_fsync_period ", "buffer ", "pages " ,"wal_level "};
char* data_types[] = {"timestamp", "int", char* data_types[] = {"timestamp", "int",
@ -304,6 +334,7 @@ char* data_types[] = {"timestamp", "int",
"bigint", "bigint unsigned", "bigint", "bigint unsigned",
"smallint", "smallint unsigned", "smallint", "smallint unsigned",
"tinyint", "tinyint unsigned", "tinyint", "tinyint unsigned",
"geometry(64)", "varbinary(16)",
"bool", "json"}; "bool", "json"};
char* key_tags[] = {"tags("}; char* key_tags[] = {"tags("};
@ -319,10 +350,20 @@ char* key_systable[] = {
char* udf_language[] = {"\'Python\'", "\'C\'"}; char* udf_language[] = {"\'Python\'", "\'C\'"};
char* field_options[] = {
"encode ", "compress ", "level ",
"\'lz4\' ", "\'zlib\' ", "\'zstd\' ", "\'xz\' ", "\'tsz\' ", "\'disabled\' ", // compress
"\'simple8b\' ", "\'delta-i\' ", "\'delta-d\' ", "\'bit-packing\' ",
"\'high\' ", "\'medium\' ", "\'low\' ",
"comment ",
"primary key "
};
// global keys can tips on anywhere // global keys can tips on anywhere
char* global_keys[] = { char* global_keys[] = {
"tbname", "tbname",
"now", "now",
"vgroups",
"_wstart", "_wstart",
"_wend", "_wend",
"_wduration", "_wduration",
@ -354,27 +395,29 @@ bool waitAutoFill = false;
#define WT_VAR_STREAM 6 #define WT_VAR_STREAM 6
#define WT_VAR_UDFNAME 7 #define WT_VAR_UDFNAME 7
#define WT_VAR_VGROUPID 8 #define WT_VAR_VGROUPID 8
#define WT_VAR_TSMA 9
#define WT_FROM_DB_MAX 8 // max get content from db #define WT_FROM_DB_MAX 9 // max get content from db
#define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1) #define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1)
#define WT_VAR_ALLTABLE 9 #define WT_VAR_ALLTABLE 10
#define WT_VAR_FUNC 10 #define WT_VAR_FUNC 11
#define WT_VAR_KEYWORD 11 #define WT_VAR_KEYWORD 12
#define WT_VAR_TBACTION 12 #define WT_VAR_TBACTION 13
#define WT_VAR_DBOPTION 13 #define WT_VAR_DBOPTION 14
#define WT_VAR_ALTER_DBOPTION 14 #define WT_VAR_ALTER_DBOPTION 15
#define WT_VAR_DATATYPE 15 #define WT_VAR_DATATYPE 16
#define WT_VAR_KEYTAGS 16 #define WT_VAR_KEYTAGS 17
#define WT_VAR_ANYWORD 17 #define WT_VAR_ANYWORD 18
#define WT_VAR_TBOPTION 18 #define WT_VAR_TBOPTION 19
#define WT_VAR_USERACTION 19 #define WT_VAR_USERACTION 20
#define WT_VAR_KEYSELECT 20 #define WT_VAR_KEYSELECT 21
#define WT_VAR_SYSTABLE 21 #define WT_VAR_SYSTABLE 22
#define WT_VAR_LANGUAGE 22 #define WT_VAR_LANGUAGE 23
#define WT_VAR_GLOBALKEYS 23 #define WT_VAR_GLOBALKEYS 24
#define WT_VAR_FIELD_OPTIONS 25
#define WT_VAR_CNT 24 #define WT_VAR_CNT 26
#define WT_TEXT 0xFF #define WT_TEXT 0xFF
@ -387,12 +430,17 @@ TdThreadMutex tiresMutex;
TdThread* threads[WT_FROM_DB_CNT]; TdThread* threads[WT_FROM_DB_CNT];
// obtain var name with sql from server // obtain var name with sql from server
char varTypes[WT_VAR_CNT][64] = { char varTypes[WT_VAR_CNT][64] = {
// get from db
"<db_name>", "<stb_name>", "<tb_name>", "<dnode_id>", "<user_name>", "<topic_name>", "<stream_name>", "<db_name>", "<stb_name>", "<tb_name>", "<dnode_id>", "<user_name>", "<topic_name>", "<stream_name>",
"<udf_name>", "<vgroup_id>", "<all_table>", "<function>", "<keyword>", "<tb_actions>", "<db_options>", "<alter_db_options>", "<udf_name>", "<vgroup_id>", "<tsma_name>",
"<data_types>", "<key_tags>", "<anyword>", "<tb_options>", "<user_actions>", "<key_select>", "<sys_table>", "<udf_language>"}; // get from code
"<all_table>", "<function>", "<keyword>", "<tb_actions>", "<db_options>", "<alter_db_options>",
"<data_types>", "<key_tags>", "<anyword>", "<tb_options>", "<user_actions>", "<key_select>", "<sys_table>",
"<udf_language>", "<global_keys>", "<field_options>"};
char varSqls[WT_FROM_DB_CNT][64] = {"show databases;", "show stables;", "show tables;", "show dnodes;", char varSqls[WT_FROM_DB_CNT][64] = {"show databases;", "show stables;", "show tables;", "show dnodes;",
"show users;", "show topics;", "show streams;", "show functions;", "show vgroups;"}; "show users;", "show topics;", "show streams;", "show functions;",
"show vgroups;", "show tsmas;"};
// var words current cursor, if user press any one key except tab, cursorVar can be reset to -1 // var words current cursor, if user press any one key except tab, cursorVar can be reset to -1
int cursorVar = -1; int cursorVar = -1;
@ -534,6 +582,7 @@ void showHelp() {
select timezone();\n\ select timezone();\n\
set max_binary_display_width ...\n\ set max_binary_display_width ...\n\
show apps;\n\ show apps;\n\
show alive;\n\
show create database <db_name>;\n\ show create database <db_name>;\n\
show create stable <stb_name>;\n\ show create stable <stb_name>;\n\
show create table <tb_name>;\n\ show create table <tb_name>;\n\
@ -567,7 +616,8 @@ void showHelp() {
show users;\n\ show users;\n\
show variables;\n\ show variables;\n\
show local variables;\n\ show local variables;\n\
show vnodes <dnode_id>\n\ show vnodes;\n\
show vnodes on dnode <dnode_id>;\n\
show vgroups;\n\ show vgroups;\n\
show consumers;\n\ show consumers;\n\
show grants;\n\ show grants;\n\
@ -588,8 +638,10 @@ void showHelp() {
create view <view_name> as select ...\n\ create view <view_name> as select ...\n\
redistribute vgroup <vgroup_id> dnode <dnode_id> ;\n\ redistribute vgroup <vgroup_id> dnode <dnode_id> ;\n\
split vgroup <vgroup_id>;\n\ split vgroup <vgroup_id>;\n\
s3migrate database <db_name>;\n\
show compacts;\n\ show compacts;\n\
show compact \n\ show compact \n\
show arbgroups;\n\
show views;\n\ show views;\n\
show create view <all_table>;"); show create view <all_table>;");
#endif #endif
@ -648,7 +700,12 @@ SWord* addWord(const char* p, int32_t len, bool pattern) {
// check format // check format
if (pattern && len > 0) { if (pattern && len > 0) {
word->type = wordType(p, len); if (p[len - 1] == ';') {
word->type = wordType(p, len - 1);
word->end = true;
} else {
word->type = wordType(p, len);
}
} else { } else {
word->type = WT_TEXT; word->type = WT_TEXT;
} }
@ -756,6 +813,7 @@ bool shellAutoInit() {
GenerateVarType(WT_VAR_SYSTABLE, key_systable, sizeof(key_systable) / sizeof(char*)); GenerateVarType(WT_VAR_SYSTABLE, key_systable, sizeof(key_systable) / sizeof(char*));
GenerateVarType(WT_VAR_LANGUAGE, udf_language, sizeof(udf_language) / sizeof(char*)); GenerateVarType(WT_VAR_LANGUAGE, udf_language, sizeof(udf_language) / sizeof(char*));
GenerateVarType(WT_VAR_GLOBALKEYS, global_keys, sizeof(global_keys) / sizeof(char*)); GenerateVarType(WT_VAR_GLOBALKEYS, global_keys, sizeof(global_keys) / sizeof(char*));
GenerateVarType(WT_VAR_FIELD_OPTIONS, field_options, sizeof(field_options) / sizeof(char*));
return true; return true;
} }
@ -1254,9 +1312,9 @@ void printScreen(TAOS* con, SShellCmd* cmd, SWords* match) {
const char* str = NULL; const char* str = NULL;
int strLen = 0; int strLen = 0;
SWord* word = MATCH_WORD(match);
if (firstMatchIndex == curMatchIndex && lastWordBytes == -1) { if (firstMatchIndex == curMatchIndex && lastWordBytes == -1) {
// first press tab // first press tab
SWord* word = MATCH_WORD(match);
str = word->word + match->matchLen; str = word->word + match->matchLen;
strLen = word->len - match->matchLen; strLen = word->len - match->matchLen;
lastMatchIndex = firstMatchIndex; lastMatchIndex = firstMatchIndex;
@ -1264,8 +1322,6 @@ void printScreen(TAOS* con, SShellCmd* cmd, SWords* match) {
} else { } else {
if (lastWordBytes == -1) return; if (lastWordBytes == -1) return;
deleteCount(cmd, lastWordBytes); deleteCount(cmd, lastWordBytes);
SWord* word = MATCH_WORD(match);
str = word->word; str = word->word;
strLen = word->len; strLen = word->len;
// set current to last // set current to last
@ -1273,8 +1329,22 @@ void printScreen(TAOS* con, SShellCmd* cmd, SWords* match) {
lastWordBytes = word->len; lastWordBytes = word->len;
} }
// insert new if (word->end && str[strLen - 1] != ';') {
shellInsertStr(cmd, (char*)str, strLen); // append end ';'
char* p = taosMemoryCalloc(strLen + 8, 1);
if (p) {
tstrncpy(p, str, strLen + 1);
tstrncpy(p + strLen, ";", 1 + 1);
lastWordBytes += 1;
shellInsertStr(cmd, (char*)p, strLen + 1);
taosMemoryFree(p);
} else {
shellInsertStr(cmd, (char*)str, strLen);
}
} else {
// insert new
shellInsertStr(cmd, (char*)str, strLen);
}
} }
// main key press tab , matched return true else false // main key press tab , matched return true else false
@ -1648,38 +1718,69 @@ bool matchSelectQuery(TAOS* con, SShellCmd* cmd) {
return appendAfterSelect(con, cmd, p, len); return appendAfterSelect(con, cmd, p, len);
} }
// is fields option area
bool fieldOptionsArea(char* p) {
char* p1 = strrchr(p, '(');
char* p2 = strrchr(p, ',');
if (p1 == NULL && p2 == NULL) {
return false;
}
// find tags
if (strstr(p, " tags") != NULL) {
return false;
}
if (p2 == NULL) {
// first field area
p2 = p1;
}
// find blank count
int32_t cnt = 0;
while (p2) {
p2 = strchr(p2, ' ');
if (p2) {
// get prev char
char prec = *(p2 - 1);
if (prec != ',' && prec != '(') {
// blank if before comma, not calc count. like st(ts timestamp, age int + BLANK + TAB only two blank
cnt++;
}
// continue blank is one blank
while (p2[1] != 0 && p2[1] == ' ') {
// move next if blank again
p2 += 1;
}
p2 += 1;
}
}
// like create table st(ts timestamp TAB-KEY or st(ts timestamp , age int TAB-KEY
return cnt >= 2;
}
// if is input create fields or tags area, return true // if is input create fields or tags area, return true
bool isCreateFieldsArea(char* p) { bool isCreateFieldsArea(char* p) {
// put to while, support like create table st(ts timestamp, bin1 binary(16), bin2 + blank + TAB int32_t n = 0; // count
char* p1 = taosStrdup(p); char* p1 = p;
bool ret = false; while (*p1 != 0) {
while (1) { switch (*p1) {
char* left = strrchr(p1, '('); case '(':
if (left == NULL) { ++n;
// like 'create table st' break;
ret = false; case ')':
break; --n;
break;
default:
break;
} }
// move next
char* right = strrchr(p1, ')'); ++p1;
if (right == NULL) {
// like 'create table st( '
ret = true;
break;
}
if (left > right) {
// like 'create table st( ts timestamp, age int) tags(area '
ret = true;
break;
}
// set string end by small for next strrchr search
*left = 0;
} }
taosMemoryFree(p1);
return ret; return n > 0;
} }
bool matchCreateTable(TAOS* con, SShellCmd* cmd) { bool matchCreateTable(TAOS* con, SShellCmd* cmd) {
@ -1718,7 +1819,13 @@ bool matchCreateTable(TAOS* con, SShellCmd* cmd) {
// check in create fields or tags input area // check in create fields or tags input area
if (isCreateFieldsArea(ps)) { if (isCreateFieldsArea(ps)) {
ret = fillWithType(con, cmd, last, WT_VAR_DATATYPE); if (fieldOptionsArea(ps)) {
// fill field options
ret = fillWithType(con, cmd, last, WT_VAR_FIELD_OPTIONS);
} else {
// fill field
ret = fillWithType(con, cmd, last, WT_VAR_DATATYPE);
}
} }
// tags // tags
@ -1726,7 +1833,7 @@ bool matchCreateTable(TAOS* con, SShellCmd* cmd) {
// find only one ')' , can insert tags // find only one ')' , can insert tags
char* p1 = strchr(ps, ')'); char* p1 = strchr(ps, ')');
if (p1) { if (p1) {
if (strchr(p1 + 1, ')') == NULL && strstr(p1 + 1, "tags") == NULL) { if (strstr(p1 + 1, "tags") == NULL) {
// can insert tags keyword // can insert tags keyword
ret = fillWithType(con, cmd, last, WT_VAR_KEYTAGS); ret = fillWithType(con, cmd, last, WT_VAR_KEYTAGS);
} }

View File

@ -22,6 +22,8 @@
#include "shellAuto.h" #include "shellAuto.h"
#include "shellInt.h" #include "shellInt.h"
SShellObj shell = {0};
typedef struct { typedef struct {
const char *sql; const char *sql;
bool vertical; bool vertical;

View File

@ -17,8 +17,7 @@
#include "shellInt.h" #include "shellInt.h"
#include "shellAuto.h" #include "shellAuto.h"
SShellObj shell = {0}; extern SShellObj shell;
void shellCrashHandler(int signum, void *sigInfo, void *context) { void shellCrashHandler(int signum, void *sigInfo, void *context) {
taosIgnSignal(SIGTERM); taosIgnSignal(SIGTERM);

View File

@ -0,0 +1,25 @@
MESSAGE(STATUS "build taos-CLI unit test")
IF(NOT TD_DARWIN)
# GoogleTest requires at least C++11
SET(CMAKE_CXX_STANDARD 11)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
ADD_EXECUTABLE(shellTest ${SOURCE_LIST})
TARGET_LINK_LIBRARIES(
shellTest
PRIVATE shell_ut gtest os common transport geometry util
)
target_include_directories(
shell_ut
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
)
add_test(
NAME shellTest
COMMAND shellTest
)
ENDIF()

View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#include <iostream>
#include "shellAuto.h"
TEST(fieldOptionsArea, autoTabTest) {
printf("hellow world SHELL tab test\n");
// str false
const char *s0[] = {
"create table st(ts ",
"create table st(ts timestamp, age ",
"create table st(ts timestamp, age",
"create table st(ts timestamp, age int , name ",
"create table st(ts timestamp, age int , name binary(16)",
"create table st(ts timestamp, age int , name binary(16) ) tags( ",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int, addr ",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int,addr varbinary",
"create table st(ts timestamp, age int, name binary(16)) tags(area int , addr varbinary(32)",
"create table st( ts timestamp, age int, name binary(16)) tags( area int, addr",
"create table st (ts timestamp , age int, name binary(16) , area int,",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int ,addr varbinary",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) level "
"'high' , no i",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) encode "
"'simple8b' level 'high', no in",
};
// str true
const char *s1[] = {
"create table st(ts timestamp ",
"create table st(ts timestamp, age int ",
"create table st(ts timestamp, age int ",
"create table st(ts timestamp, age int , name binary(16) ",
"create table st(ts timestamp, age int , name binary(16) ",
"create table st(ts timestamp, age int , name binary(16) , addr varbinary( 32 ) ",
"create table st(ts timestamp, age int , name binary(16) ,area int, addr varbinary(32) ",
"create table st(ts timestamp, age int , name binary(16), area int,addr varbinary(32) ",
"create table st(ts timestamp, age int, name binary(16) , area int,addr varbinary(32) ",
"create table st( ts timestamp, age int, name binary(16) ,area int,addr varbinary(32) ",
"create table st (ts timestamp , age int, name binary(16), area int,addr varbinary(32) ",
"create table st (ts timestamp , age int, name binary(16), area int , addr varbinary(32) compress 'zlib' ",
"create table st (ts timestamp , age int, name binary(16), area int , addr varbinary(32) level 'high' ",
"create table st (ts timestamp , age int, name binary(16) , area int , addr varbinary(32) encode 'simple8b' "
"level 'high' ",
};
// s0 is false
for (int32_t i = 0; i < sizeof(s0) / sizeof(char *); i++) {
printf("s0 i=%d fieldOptionsArea %s expect false \n", i, s0[i]);
ASSERT(fieldOptionsArea((char *)s0[i]) == false);
}
// s1 is true
for (int32_t i = 0; i < sizeof(s1) / sizeof(char *); i++) {
printf("s1 i=%d fieldOptionsArea %s expect true \n", i, s1[i]);
ASSERT(fieldOptionsArea((char *)s1[i]) == true);
}
}
TEST(isCreateFieldsArea, autoTabTest) {
printf("hellow world SHELL tab test\n");
// str false
const char *s0[] = {
"create table st(ts )",
"create table st(ts timestamp, age) ",
"create table st(ts timestamp, age)",
"create table st(ts timestamp, age int , name binary(16) )",
"create table st(ts timestamp, age int , name binary(16))",
"create table st(ts timestamp, age int , name binary(16) ) tags( )",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int, addr )",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int,addr varbinary)",
"create table st(ts timestamp, age int, name binary(16)) tags(area int , addr varbinary(32))",
"create table st( ts timestamp, age int, name binary(16)) tags( area int, addr int)",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int,addr varbinary(32) )",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int ,addr varbinary(14))",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) level "
"'high' )",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) encode "
"'simple8b' level 'high' ) ",
};
// str true
const char *s1[] = {
"create table st(ts timestamp ",
"create table st(ts timestamp, age int ",
"create table st(ts timestamp, age int ,",
"create table st(ts timestamp, age int , name binary(16), ",
"create table st(ts timestamp, age int , name binary(16) ",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int ",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int, addr varbinary(32) ",
"create table st(ts timestamp, age int , name binary(16) ) tags( area int,addr varbinary(32)",
"create table st(ts timestamp, age int, name binary(16)) tags(area int,addr varbinary(32) ",
"create table st( ts timestamp, age int, name binary(16)) tags(area int,addr varbinary(32) ",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int, addr varbinary(32) ",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) compress "
"'zlib' ",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) level "
"'high' ",
"create table st (ts timestamp , age int, name binary(16) ) tags ( area int , addr varbinary(32) encode "
"'simple8b' level 'high' ",
};
// s0 is false
for (int32_t i = 0; i < sizeof(s0) / sizeof(char *); i++) {
printf("s0 i=%d isCreateFieldsArea %s expect false. \n", i, s0[i]);
ASSERT(isCreateFieldsArea((char *)s0[i]) == false);
}
// s1 is true
for (int32_t i = 0; i < sizeof(s1) / sizeof(char *); i++) {
printf("s1 i=%d isCreateFieldsArea %s expect true. \n", i, s1[i]);
ASSERT(isCreateFieldsArea((char *)s1[i]) == true);
}
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}