未验证 提交 1c106bfd 编写于 作者: S Shengliang Guan 提交者: GitHub

Merge pull request #17235 from taosdata/feat/TD-17777-V30

feat(shell): Supported the word completed by press Tab key for 3.0
......@@ -24,7 +24,7 @@ void pressTabKey(SShellCmd* cmd);
// press othr key
void pressOtherKey(char c);
// init shell auto funciton , shell start call once
// init shell auto funciton , shell start call once
bool shellAutoInit();
// set conn
......
......@@ -16,68 +16,65 @@
#ifndef __TRIE__
#define __TRIE__
//
//
// The prefix search tree is a efficient storage words and search words tree, it support 95 visible ascii code character
//
#define FIRST_ASCII 40 // first visiable char is '0'
#define LAST_ASCII 122 // last visilbe char is 'z'
// capacity save char is 95
#define CHAR_CNT (LAST_ASCII - FIRST_ASCII + 1)
#define MAX_WORD_LEN 256 // max insert word length
#define CHAR_CNT (LAST_ASCII - FIRST_ASCII + 1)
#define MAX_WORD_LEN 256 // max insert word length
// define STire
#define TIRE_TREE 0
#define TIRE_LIST 1
#define TIRE_TREE 0
#define TIRE_LIST 1
typedef struct STireNode {
struct STireNode** d;
bool end; // record end flag
}STireNode;
struct STireNode** d;
bool end; // record end flag
} STireNode;
typedef struct StrName {
char * name;
struct StrName * next;
}StrName;
char* name;
struct StrName* next;
} StrName;
typedef struct STire {
char type; // see define TIRE_
STireNode root;
char type; // see define TIRE_
STireNode root;
StrName * head;
StrName * tail;
StrName* head;
StrName* tail;
int count; // all count
int ref;
}STire;
int count; // all count
int ref;
} STire;
typedef struct SMatchNode {
char* word;
struct SMatchNode* next;
}SMatchNode;
char* word;
struct SMatchNode* next;
} SMatchNode;
typedef struct SMatch {
SMatchNode* head;
SMatchNode* tail; // append node to tail
int count;
char pre[MAX_WORD_LEN];
}SMatch;
SMatchNode* head;
SMatchNode* tail; // append node to tail
int count;
char pre[MAX_WORD_LEN];
} SMatch;
// ----------- interface -------------
// create prefix search tree, return value call freeTire to free
// create prefix search tree, return value call freeTire to free
STire* createTire(char type);
// destroy prefix search tree
void freeTire(STire* tire);
// add a new word
// add a new word
bool insertWord(STire* tire, char* word);
// add a new word
// add a new word
bool deleteWord(STire* tire, char* word);
// match prefix words, if match is not NULL , put all item to match and return match
......
......@@ -25,441 +25,326 @@
//
#define UNION_ALL " union all "
// extern function
void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width);
void shellShowOnScreen(SShellCmd *cmd);
void shellInsertChar(SShellCmd *cmd, char *c, int size);
bool appendAfterSelect(TAOS * con, SShellCmd * cmd, char* p, int32_t len);
void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos);
void shellGetPrevCharSize(const char* str, int32_t pos, int32_t* size, int32_t* width);
void shellShowOnScreen(SShellCmd* cmd);
void shellInsertChar(SShellCmd* cmd, char* c, int size);
bool appendAfterSelect(TAOS* con, SShellCmd* cmd, char* p, int32_t len);
typedef struct SAutoPtr {
STire* p;
int ref;
}SAutoPtr;
int ref;
} SAutoPtr;
typedef struct SWord{
int type ; // word type , see WT_ define
char * word;
int32_t len;
struct SWord * next;
bool free; // if true need free
}SWord;
typedef struct SWord {
int type; // word type , see WT_ define
char* word;
int32_t len;
struct SWord* next;
bool free; // if true need free
} SWord;
typedef struct {
char * source;
int32_t source_len; // valid data length in source
char* source;
int32_t source_len; // valid data length in source
int32_t count;
SWord* head;
// matched information
int32_t matchIndex; // matched word index in words
int32_t matchLen; // matched length at matched word
}SWords;
int32_t matchIndex; // matched word index in words
int32_t matchLen; // matched length at matched word
} SWords;
SWords shellCommands[] = {
{"alter database <db_name> <alter_db_options> <anyword> <alter_db_options> <anyword> <alter_db_options> <anyword> <alter_db_options> <anyword> <alter_db_options> <anyword> ;", 0, 0, NULL},
{"alter dnode <dnode_id> balance ", 0, 0, NULL},
{"alter dnode <dnode_id> resetlog;", 0, 0, NULL},
{"alter dnode <dnode_id> debugFlag 141;", 0, 0, NULL},
{"alter dnode <dnode_id> monitor 1;", 0, 0, NULL},
{"alter all dnodes monitor ", 0, 0, NULL},
{"alter alldnodes balance ", 0, 0, NULL},
{"alter alldnodes resetlog;", 0, 0, NULL},
{"alter alldnodes debugFlag 141;", 0, 0, NULL},
{"alter alldnodes monitor 1;", 0, 0, NULL},
{"alter table <tb_name> <tb_actions> <anyword> ;", 0, 0, NULL},
{"alter table modify column", 0, 0, NULL},
{"alter local resetlog;", 0, 0, NULL},
{"alter local DebugFlag 143;", 0, 0, NULL},
{"alter local cDebugFlag 143;", 0, 0, NULL},
{"alter local uDebugFlag 143;", 0, 0, NULL},
{"alter local rpcDebugFlag 143;", 0, 0, NULL},
{"alter local tmrDebugFlag 143;", 0, 0, NULL},
{"alter topic", 0, 0, NULL},
{"alter user <user_name> <user_actions> <anyword> ;", 0, 0, NULL},
// 20
{"create table <anyword> using <stb_name> tags(", 0, 0, NULL},
{"create database <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> ;", 0, 0, NULL},
{"create dnode ", 0, 0, NULL},
{"create index ", 0, 0, NULL},
{"create mnode 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 topic <anyword> as select", 0, 0, NULL}, // 27 append sub sql
{"create function ", 0, 0, NULL},
{"create user <anyword> pass <anyword> sysinfo 0;", 0, 0, NULL},
{"create user <anyword> pass <anyword> sysinfo 1;", 0, 0, NULL},
{"describe <all_table>", 0, 0, NULL},
{"delete from <all_table> where ", 0, 0, NULL},
{"drop database <db_name>", 0, 0, NULL},
{"drop table <all_table>", 0, 0, NULL},
{"drop 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 user <user_name> ;", 0, 0, NULL},
// 40
{"drop function", 0, 0, NULL},
{"drop consumer group <anyword> on ", 0, 0, NULL},
{"drop topic <topic_name> ;", 0, 0, NULL},
{"drop stream <stream_name> ;", 0, 0, NULL},
{"explain select", 0, 0, NULL}, // 44 append sub sql
{"grant all 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},
{"kill connection <anyword> ;", 0, 0, NULL},
{"kill query ", 0, 0, NULL},
{"kill transaction ", 0, 0, NULL},
{"merge vgroup ", 0, 0, NULL},
{"reset query cache;", 0, 0, NULL},
{"revoke all 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},
{"select * from <all_table>", 0, 0, NULL},
{"select _block_dist() from <all_table> \\G;", 0, 0, NULL},
{"select client_version();", 0, 0, NULL},
// 60
{"select current_user();", 0, 0, NULL},
{"select database();", 0, 0, NULL},
{"select server_version();", 0, 0, NULL},
{"select server_status();", 0, 0, NULL},
{"select now();", 0, 0, NULL},
{"select today();", 0, 0, NULL},
{"select timezone();", 0, 0, NULL},
{"set max_binary_display_width ", 0, 0, NULL},
{"show apps;", 0, 0, NULL},
{"show create database <db_name> \\G;", 0, 0, NULL},
{"show create stable <stb_name> \\G;", 0, 0, NULL},
{"show create table <tb_name> \\G;", 0, 0, NULL},
{"show connections;", 0, 0, NULL},
{"show cluster;", 0, 0, NULL},
{"show databases;", 0, 0, NULL},
{"show dnodes;", 0, 0, NULL},
{"show dnode <dnode_id> variables;", 0, 0, NULL},
{"show functions;", 0, 0, NULL},
{"show mnodes;", 0, 0, NULL},
{"show queries;", 0, 0, NULL},
// 80
{"show query <anyword> ;", 0, 0, NULL},
{"show qnodes;", 0, 0, NULL},
{"show snodes;", 0, 0, NULL},
{"show stables;", 0, 0, NULL},
{"show stables like ", 0, 0, NULL},
{"show streams;", 0, 0, NULL},
{"show scores;", 0, 0, NULL},
{"show subscriptions;", 0, 0, NULL},
{"show tables;", 0, 0, NULL},
{"show tables like", 0, 0, NULL},
{"show table distributed <all_table>", 0, 0, NULL},
{"show tags from <tb_name>", 0, 0, NULL},
{"show tags from <db_name>", 0, 0, NULL},
{"show topics;", 0, 0, NULL},
{"show transactions;", 0, 0, NULL},
{"show users;", 0, 0, NULL},
{"show variables;", 0, 0, NULL},
{"show local variables;", 0, 0, NULL},
{"show vnodes <dnode_id>", 0, 0, NULL},
{"show vgroups;", 0, 0, NULL},
{"show consumers;", 0, 0, NULL},
{"show grants;", 0, 0, NULL},
{"split vgroup ", 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> <anyword> values(", 0, 0, NULL},
{"insert into <tb_name> file ", 0, 0, NULL},
{"trim database <db_name>", 0, 0, NULL},
{"use <db_name>", 0, 0, NULL},
{"quit", 0, 0, NULL}
};
char * keywords[] = {
"and ",
"asc ",
"desc ",
"from ",
"fill(",
"limit ",
"where ",
"interval(",
"order by ",
"order by ",
"offset ",
"or ",
"group by ",
"now()",
"session(",
"sliding ",
"slimit ",
"soffset ",
"state_window(",
"today() ",
"union all select ",
"partition by "
};
char * functions[] = {
"count(",
"sum(",
"avg(",
"last(",
"last_row(",
"top(",
"interp(",
"max(",
"min(",
"now()",
"today()",
"percentile(",
"tail(",
"pow(",
"abs(",
"atan(",
"acos(",
"asin(",
"apercentile(",
"bottom(",
"cast(",
"ceil(",
"char_length(",
"cos(",
"concat(",
"concat_ws(",
"csum(",
"diff(",
"derivative(",
"elapsed(",
"first(",
"floor(",
"hyperloglog(",
"histogram(",
"irate(",
"leastsquares(",
"length(",
"log(",
"lower(",
"ltrim(",
"mavg(",
"mode(",
"tan(",
"round(",
"rtrim(",
"sample(",
"sin(",
"spread(",
"substr(",
"statecount(",
"stateduration(",
"stddev(",
"sqrt(",
"timediff(",
"timezone(",
"timetruncate(",
"twa(",
"to_unixtimestamp(",
"unique(",
"upper(",
};
char * tb_actions[] = {
"add column ",
"modify column ",
"drop column ",
"rename column ",
"add tag ",
"modify tag ",
"drop tag ",
"rename tag ",
"set tag ",
};
char * user_actions[] = {
"pass ",
"enable ",
"sysinfo "
};
char * tb_options[] = {
"comment ",
"watermark ",
"max_delay ",
"ttl ",
"rollup(",
"sma("
};
char * db_options[] = {
"keep ",
"replica ",
"precision ",
"strict ",
"buffer ",
"cachemodel ",
"cachesize ",
"comp ",
"duration ",
"wal_fsync_period",
"maxrows ",
"minrows ",
"pages ",
"pagesize ",
"retentions ",
"wal_level ",
"vgroups ",
"single_stable ",
"wal_retention_period ",
"wal_roll_period ",
"wal_retention_size ",
"wal_segment_size "
};
char * alter_db_options[] = {
"keep ",
"cachemodel ",
"cachesize ",
"wal_fsync_period ",
"wal_level "
};
char * data_types[] = {
"timestamp",
"int",
"int unsigned",
"varchar(16)",
"float",
"double",
"binary(16)",
"nchar(16)",
"bigint",
"bigint unsigned",
"smallint",
"smallint unsigned",
"tinyint",
"tinyint unsigned",
"bool",
"json"
{"alter database <db_name> <alter_db_options> <anyword> <alter_db_options> <anyword> <alter_db_options> <anyword> "
"<alter_db_options> <anyword> <alter_db_options> <anyword> ;",
0, 0, NULL},
{"alter dnode <dnode_id> balance ", 0, 0, NULL},
{"alter dnode <dnode_id> resetlog;", 0, 0, NULL},
{"alter dnode <dnode_id> debugFlag 141;", 0, 0, NULL},
{"alter dnode <dnode_id> monitor 1;", 0, 0, NULL},
{"alter all dnodes monitor ", 0, 0, NULL},
{"alter alldnodes balance ", 0, 0, NULL},
{"alter alldnodes resetlog;", 0, 0, NULL},
{"alter alldnodes debugFlag 141;", 0, 0, NULL},
{"alter alldnodes monitor 1;", 0, 0, NULL},
{"alter table <tb_name> <tb_actions> <anyword> ;", 0, 0, NULL},
{"alter table modify column", 0, 0, NULL},
{"alter local resetlog;", 0, 0, NULL},
{"alter local DebugFlag 143;", 0, 0, NULL},
{"alter local cDebugFlag 143;", 0, 0, NULL},
{"alter local uDebugFlag 143;", 0, 0, NULL},
{"alter local rpcDebugFlag 143;", 0, 0, NULL},
{"alter local tmrDebugFlag 143;", 0, 0, NULL},
{"alter topic", 0, 0, NULL},
{"alter user <user_name> <user_actions> <anyword> ;", 0, 0, NULL},
// 20
{"create table <anyword> using <stb_name> tags(", 0, 0, NULL},
{"create database <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> "
"<anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> <db_options> <anyword> "
"<db_options> <anyword> <db_options> <anyword> ;",
0, 0, NULL},
{"create dnode ", 0, 0, NULL},
{"create index ", 0, 0, NULL},
{"create mnode 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 topic <anyword> as select", 0, 0, NULL}, // 27 append sub sql
{"create function ", 0, 0, NULL},
{"create user <anyword> pass <anyword> sysinfo 0;", 0, 0, NULL},
{"create user <anyword> pass <anyword> sysinfo 1;", 0, 0, NULL},
{"describe <all_table>", 0, 0, NULL},
{"delete from <all_table> where ", 0, 0, NULL},
{"drop database <db_name>", 0, 0, NULL},
{"drop table <all_table>", 0, 0, NULL},
{"drop 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 user <user_name> ;", 0, 0, NULL},
// 40
{"drop function", 0, 0, NULL},
{"drop consumer group <anyword> on ", 0, 0, NULL},
{"drop topic <topic_name> ;", 0, 0, NULL},
{"drop stream <stream_name> ;", 0, 0, NULL},
{"explain select", 0, 0, NULL}, // 44 append sub sql
{"grant all 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},
{"kill connection <anyword> ;", 0, 0, NULL},
{"kill query ", 0, 0, NULL},
{"kill transaction ", 0, 0, NULL},
{"merge vgroup ", 0, 0, NULL},
{"reset query cache;", 0, 0, NULL},
{"revoke all 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},
{"select * from <all_table>", 0, 0, NULL},
{"select _block_dist() from <all_table> \\G;", 0, 0, NULL},
{"select client_version();", 0, 0, NULL},
// 60
{"select current_user();", 0, 0, NULL},
{"select database();", 0, 0, NULL},
{"select server_version();", 0, 0, NULL},
{"select server_status();", 0, 0, NULL},
{"select now();", 0, 0, NULL},
{"select today();", 0, 0, NULL},
{"select timezone();", 0, 0, NULL},
{"set max_binary_display_width ", 0, 0, NULL},
{"show apps;", 0, 0, NULL},
{"show create database <db_name> \\G;", 0, 0, NULL},
{"show create stable <stb_name> \\G;", 0, 0, NULL},
{"show create table <tb_name> \\G;", 0, 0, NULL},
{"show connections;", 0, 0, NULL},
{"show cluster;", 0, 0, NULL},
{"show databases;", 0, 0, NULL},
{"show dnodes;", 0, 0, NULL},
{"show dnode <dnode_id> variables;", 0, 0, NULL},
{"show functions;", 0, 0, NULL},
{"show mnodes;", 0, 0, NULL},
{"show queries;", 0, 0, NULL},
// 80
{"show query <anyword> ;", 0, 0, NULL},
{"show qnodes;", 0, 0, NULL},
{"show stables;", 0, 0, NULL},
{"show stables like ", 0, 0, NULL},
{"show streams;", 0, 0, NULL},
{"show scores;", 0, 0, NULL},
{"show snodes;", 0, 0, NULL},
{"show subscriptions;", 0, 0, NULL},
{"show tables;", 0, 0, NULL},
{"show tables like", 0, 0, NULL},
{"show table distributed <all_table>", 0, 0, NULL},
{"show tags from <tb_name>", 0, 0, NULL},
{"show tags from <db_name>", 0, 0, NULL},
{"show topics;", 0, 0, NULL},
{"show transactions;", 0, 0, NULL},
{"show users;", 0, 0, NULL},
{"show variables;", 0, 0, NULL},
{"show local variables;", 0, 0, NULL},
{"show vnodes <dnode_id>", 0, 0, NULL},
{"show vgroups;", 0, 0, NULL},
{"show consumers;", 0, 0, NULL},
{"show grants;", 0, 0, NULL},
{"split vgroup ", 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> <anyword> values(", 0, 0, NULL},
{"insert into <tb_name> file ", 0, 0, NULL},
{"trim database <db_name>", 0, 0, NULL},
{"use <db_name>", 0, 0, NULL},
{"quit", 0, 0, NULL}};
char* keywords[] = {
"and ", "asc ", "desc ", "from ", "fill(", "limit ", "where ",
"interval(", "order by ", "order by ", "offset ", "or ", "group by ", "now()",
"session(", "sliding ", "slimit ", "soffset ", "state_window(", "today() ", "union all select ",
"partition by "};
char* functions[] = {
"count(", "sum(",
"avg(", "last(",
"last_row(", "top(",
"interp(", "max(",
"min(", "now()",
"today()", "percentile(",
"tail(", "pow(",
"abs(", "atan(",
"acos(", "asin(",
"apercentile(", "bottom(",
"cast(", "ceil(",
"char_length(", "cos(",
"concat(", "concat_ws(",
"csum(", "diff(",
"derivative(", "elapsed(",
"first(", "floor(",
"hyperloglog(", "histogram(",
"irate(", "leastsquares(",
"length(", "log(",
"lower(", "ltrim(",
"mavg(", "mode(",
"tan(", "round(",
"rtrim(", "sample(",
"sin(", "spread(",
"substr(", "statecount(",
"stateduration(", "stddev(",
"sqrt(", "timediff(",
"timezone(", "timetruncate(",
"twa(", "to_unixtimestamp(",
"unique(", "upper(",
};
char * key_tags[] = {
"tags("
char* tb_actions[] = {
"add column ", "modify column ", "drop column ", "rename column ", "add tag ",
"modify tag ", "drop tag ", "rename tag ", "set tag ",
};
char * key_select[] = {
"select "
};
char* user_actions[] = {"pass ", "enable ", "sysinfo "};
char* tb_options[] = {"comment ", "watermark ", "max_delay ", "ttl ", "rollup(", "sma("};
char* db_options[] = {"keep ",
"replica ",
"precision ",
"strict ",
"buffer ",
"cachemodel ",
"cachesize ",
"comp ",
"duration ",
"wal_fsync_period",
"maxrows ",
"minrows ",
"pages ",
"pagesize ",
"retentions ",
"wal_level ",
"vgroups ",
"single_stable ",
"wal_retention_period ",
"wal_roll_period ",
"wal_retention_size ",
"wal_segment_size "};
char* alter_db_options[] = {"keep ", "cachemodel ", "cachesize ", "wal_fsync_period ", "wal_level "};
char* data_types[] = {"timestamp", "int",
"int unsigned", "varchar(16)",
"float", "double",
"binary(16)", "nchar(16)",
"bigint", "bigint unsigned",
"smallint", "smallint unsigned",
"tinyint", "tinyint unsigned",
"bool", "json"};
char* key_tags[] = {"tags("};
char* key_select[] = {"select "};
//
// ------- gobal variant define ---------
//
int32_t firstMatchIndex = -1; // first match shellCommands index
int32_t lastMatchIndex = -1; // last match shellCommands index
int32_t curMatchIndex = -1; // current match shellCommands index
int32_t lastWordBytes = -1; // printShow last word length
bool waitAutoFill = false;
int32_t firstMatchIndex = -1; // first match shellCommands index
int32_t lastMatchIndex = -1; // last match shellCommands index
int32_t curMatchIndex = -1; // current match shellCommands index
int32_t lastWordBytes = -1; // printShow last word length
bool waitAutoFill = false;
//
// ----------- global var array define -----------
//
#define WT_VAR_DBNAME 0
#define WT_VAR_STABLE 1
#define WT_VAR_TABLE 2
#define WT_VAR_DNODEID 3
#define WT_VAR_USERNAME 4
#define WT_VAR_TOPIC 5
#define WT_VAR_STREAM 6
#define WT_VAR_ALLTABLE 7
#define WT_VAR_FUNC 8
#define WT_VAR_KEYWORD 9
#define WT_VAR_TBACTION 10
#define WT_VAR_DBOPTION 11
#define WT_VAR_DBNAME 0
#define WT_VAR_STABLE 1
#define WT_VAR_TABLE 2
#define WT_VAR_DNODEID 3
#define WT_VAR_USERNAME 4
#define WT_VAR_TOPIC 5
#define WT_VAR_STREAM 6
#define WT_VAR_ALLTABLE 7
#define WT_VAR_FUNC 8
#define WT_VAR_KEYWORD 9
#define WT_VAR_TBACTION 10
#define WT_VAR_DBOPTION 11
#define WT_VAR_ALTER_DBOPTION 12
#define WT_VAR_DATATYPE 13
#define WT_VAR_KEYTAGS 14
#define WT_VAR_ANYWORD 15
#define WT_VAR_TBOPTION 16
#define WT_VAR_USERACTION 17
#define WT_VAR_KEYSELECT 18
#define WT_VAR_DATATYPE 13
#define WT_VAR_KEYTAGS 14
#define WT_VAR_ANYWORD 15
#define WT_VAR_TBOPTION 16
#define WT_VAR_USERACTION 17
#define WT_VAR_KEYSELECT 18
#define WT_VAR_CNT 19
#define WT_VAR_CNT 19
#define WT_FROM_DB_MAX 6 // max get content from db
#define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1)
#define WT_FROM_DB_MAX 6 // max get content from db
#define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1)
#define WT_TEXT 0xFF
#define WT_TEXT 0xFF
char dbName[256] = ""; // save use database name;
char dbName[256] = ""; // save use database name;
// tire array
STire* tires[WT_VAR_CNT];
STire* tires[WT_VAR_CNT];
TdThreadMutex tiresMutex;
//save thread handle obtain var name from db server
// save thread handle obtain var name from db server
TdThread* threads[WT_FROM_DB_CNT];
// obtain var name with sql from server
char varTypes[WT_VAR_CNT][64] = {
"<db_name>",
"<stb_name>",
"<tb_name>",
"<dnode_id>",
"<user_name>",
"<topic_name>",
"<stream_name>",
"<all_table>",
"<function>",
"<keyword>",
"<tb_actions>",
"<db_options>",
"<alter_db_options>",
"<data_types>",
"<key_tags>",
"<anyword>",
"<tb_options>",
"<user_actions>",
"<key_select>"
};
char varSqls[WT_FROM_DB_CNT][64] = {
"show databases;",
"show stables;",
"show tables;",
"show dnodes;",
"show users;",
"show topics;",
"show streams;"
};
char varTypes[WT_VAR_CNT][64] = {"<db_name>", "<stb_name>", "<tb_name>", "<dnode_id>", "<user_name>",
"<topic_name>", "<stream_name>", "<all_table>", "<function>", "<keyword>",
"<tb_actions>", "<db_options>", "<alter_db_options>", "<data_types>", "<key_tags>",
"<anyword>", "<tb_options>", "<user_actions>", "<key_select>"};
char varSqls[WT_FROM_DB_CNT][64] = {"show databases;", "show stables;", "show tables;", "show dnodes;",
"show users;", "show topics;", "show streams;"};
// var words current cursor, if user press any one key except tab, cursorVar can be reset to -1
int cursorVar = -1;
bool varMode = false; // enter var names list mode
TAOS* varCon = NULL;
SShellCmd* varCmd = NULL;
SMatch* lastMatch = NULL; // save last match result
int cntDel = 0; // delete byte count after next press tab
int cursorVar = -1;
bool varMode = false; // enter var names list mode
TAOS* varCon = NULL;
SShellCmd* varCmd = NULL;
SMatch* lastMatch = NULL; // save last match result
int cntDel = 0; // delete byte count after next press tab
// show auto tab introduction
void printfIntroduction() {
printf(" **************************** How To Use TAB Key ********************************\n");
printf(" * TDengine Command Line supports pressing TAB key to complete word, *\n");
printf(" **************************** How To Use TAB Key ********************************\n");
printf(" * TDengine Command Line supports pressing TAB key to complete word, *\n");
printf(" * including database name, table name, function name and keywords. *\n");
printf(" * Press TAB key anywhere, you'll get surprise. *\n");
printf(" * KEYBOARD SHORTCUT: *\n");
printf(" * [ TAB ] ...... Complete the word or show help if no input *\n");
printf(" * [ Ctrl + A ] ...... move cursor to [A]head of line *\n");
printf(" * [ Ctrl + E ] ...... move cursor to [E]nd of line *\n");
printf(" * [ Ctrl + W ] ...... move cursor to line of middle *\n");
printf(" * [ Ctrl + W ] ...... move cursor to line of middle *\n");
printf(" * [ Ctrl + L ] ...... clean screen *\n");
printf(" * [ Ctrl + K ] ...... clean after cursor *\n");
printf(" * [ Ctrl + U ] ...... clean before cursor *\n");
printf(" * *\n");
printf(" **********************************************************************************\n\n");
printf(" **********************************************************************************\n\n");
}
void showHelp() {
printf("\nThe following are supported commands for TDengine Command Line:");
printf("\n\
printf(
"\n\
----- A ----- \n\
alter database <db_name> <db_options> \n\
alter dnode <dnode_id> balance \n\
......@@ -572,9 +457,10 @@ void showHelp() {
use <db_name>;");
printf("\n\n");
//define in getDuration() function
printf("\
// define in getDuration() function
printf(
"\
Timestamp expression Format:\n\
b - nanosecond \n\
u - microsecond \n\
......@@ -597,11 +483,10 @@ void showHelp() {
#define SHELL_COMMAND_COUNT() (sizeof(shellCommands) / sizeof(SWords))
// get at
SWord * atWord(SWords * command, int32_t index) {
SWord * word = command->head;
SWord* atWord(SWords* command, int32_t index) {
SWord* word = command->head;
for (int32_t i = 0; i < index; i++) {
if (word == NULL)
return NULL;
if (word == NULL) return NULL;
word = word->next;
}
......@@ -612,18 +497,17 @@ SWord * atWord(SWords * command, int32_t index) {
int wordType(const char* p, int32_t len) {
for (int i = 0; i < WT_VAR_CNT; i++) {
if (strncmp(p, varTypes[i], len) == 0)
return i;
if (strncmp(p, varTypes[i], len) == 0) return i;
}
return WT_TEXT;
}
// add word
SWord * addWord(const char* p, int32_t len, bool pattern) {
SWord* word = (SWord *) taosMemoryMalloc(sizeof(SWord));
SWord* addWord(const char* p, int32_t len, bool pattern) {
SWord* word = (SWord*)taosMemoryMalloc(sizeof(SWord));
memset(word, 0, sizeof(SWord));
word->word = (char* )p;
word->len = len;
word->word = (char*)p;
word->len = len;
// check format
if (pattern) {
......@@ -636,10 +520,10 @@ SWord * addWord(const char* p, int32_t len, bool pattern) {
}
// parse one command
void parseCommand(SWords * command, bool pattern) {
char * p = command->source;
void parseCommand(SWords* command, bool pattern) {
char* p = command->source;
int32_t start = 0;
int32_t size = command->source_len > 0 ? command->source_len : strlen(p);
int32_t size = command->source_len > 0 ? command->source_len : strlen(p);
bool lastBlank = false;
for (int i = 0; i <= size; i++) {
......@@ -647,28 +531,28 @@ void parseCommand(SWords * command, bool pattern) {
// check continue blank like ' '
if (p[i] == ' ') {
if (lastBlank) {
start ++;
start++;
continue;
}
if (i == 0) { // first blank
if (i == 0) { // first blank
lastBlank = true;
start ++;
start++;
continue;
}
lastBlank = true;
}
}
// found split or string end , append word
if (command->head == NULL) {
command->head = addWord(p + start, i - start, pattern);
command->count = 1;
} else {
SWord * word = command->head;
SWord* word = command->head;
while (word->next) {
word = word->next;
}
word->next = addWord(p + start, i - start, pattern);
command->count ++;
command->count++;
}
start = i + 1;
} else {
......@@ -678,25 +562,23 @@ void parseCommand(SWords * command, bool pattern) {
}
// free SShellCmd
void freeCommand(SWords * command) {
SWord * word = command->head;
void freeCommand(SWords* command) {
SWord* word = command->head;
if (word == NULL) {
return ;
return;
}
// loop
// loop
while (word->next) {
SWord * tmp = word;
SWord* tmp = word;
word = word->next;
// if malloc need free
if(tmp->free && tmp->word)
taosMemoryFree(tmp->word);
if (tmp->free && tmp->word) taosMemoryFree(tmp->word);
taosMemoryFree(tmp);
}
// if malloc need free
if(word->free && word->word)
taosMemoryFree(word->word);
if (word->free && word->word) taosMemoryFree(word->word);
taosMemoryFree(word);
}
......@@ -715,12 +597,11 @@ void GenerateVarType(int type, char** p, int count) {
// -------------------- shell auto ----------------
//
// init shell auto funciton , shell start call once
// init shell auto funciton , shell start call once
bool shellAutoInit() {
// command
int32_t count = SHELL_COMMAND_COUNT();
for (int32_t i = 0; i < count; i ++) {
for (int32_t i = 0; i < count; i++) {
parseCommand(shellCommands + i, true);
}
......@@ -732,30 +613,28 @@ bool shellAutoInit() {
memset(threads, 0, sizeof(TdThread*) * WT_FROM_DB_CNT);
// generate varType
GenerateVarType(WT_VAR_FUNC, functions, sizeof(functions) /sizeof(char *));
GenerateVarType(WT_VAR_KEYWORD, keywords, sizeof(keywords) /sizeof(char *));
GenerateVarType(WT_VAR_DBOPTION, db_options, sizeof(db_options) /sizeof(char *));
GenerateVarType(WT_VAR_ALTER_DBOPTION, alter_db_options, sizeof(alter_db_options) /sizeof(char *));
GenerateVarType(WT_VAR_TBACTION, tb_actions, sizeof(tb_actions) /sizeof(char *));
GenerateVarType(WT_VAR_DATATYPE, data_types, sizeof(data_types) /sizeof(char *));
GenerateVarType(WT_VAR_KEYTAGS, key_tags, sizeof(key_tags) /sizeof(char *));
GenerateVarType(WT_VAR_TBOPTION, tb_options, sizeof(tb_options) /sizeof(char *));
GenerateVarType(WT_VAR_USERACTION, user_actions, sizeof(user_actions) /sizeof(char *));
GenerateVarType(WT_VAR_KEYSELECT,key_select, sizeof(key_select) /sizeof(char *));
GenerateVarType(WT_VAR_FUNC, functions, sizeof(functions) / sizeof(char*));
GenerateVarType(WT_VAR_KEYWORD, keywords, sizeof(keywords) / sizeof(char*));
GenerateVarType(WT_VAR_DBOPTION, db_options, sizeof(db_options) / sizeof(char*));
GenerateVarType(WT_VAR_ALTER_DBOPTION, alter_db_options, sizeof(alter_db_options) / sizeof(char*));
GenerateVarType(WT_VAR_TBACTION, tb_actions, sizeof(tb_actions) / sizeof(char*));
GenerateVarType(WT_VAR_DATATYPE, data_types, sizeof(data_types) / sizeof(char*));
GenerateVarType(WT_VAR_KEYTAGS, key_tags, sizeof(key_tags) / sizeof(char*));
GenerateVarType(WT_VAR_TBOPTION, tb_options, sizeof(tb_options) / sizeof(char*));
GenerateVarType(WT_VAR_USERACTION, user_actions, sizeof(user_actions) / sizeof(char*));
GenerateVarType(WT_VAR_KEYSELECT, key_select, sizeof(key_select) / sizeof(char*));
return true;
}
// set conn
void shellSetConn(TAOS* conn) {
varCon = conn;
}
void shellSetConn(TAOS* conn) { varCon = conn; }
// exit shell auto funciton, shell exit call once
void shellAutoExit() {
// free command
int32_t count = SHELL_COMMAND_COUNT();
for (int32_t i = 0; i < count; i ++) {
for (int32_t i = 0; i < count; i++) {
freeCommand(shellCommands + i);
}
......@@ -765,7 +644,7 @@ void shellAutoExit() {
if (tires[i]) {
freeTire(tires[i]);
tires[i] = NULL;
}
}
}
taosThreadMutexUnlock(&tiresMutex);
// destory
......@@ -790,8 +669,7 @@ void shellAutoExit() {
// ------------------- auto ptr for tires --------------------------
//
bool setNewAuotPtr(int type, STire* pNew) {
if (pNew == NULL)
return false;
if (pNew == NULL) return false;
taosThreadMutexLock(&tiresMutex);
STire* pOld = tires[type];
......@@ -826,63 +704,61 @@ STire* getAutoPtr(int type) {
// put back tire to tires[type], if tire not equal tires[type].p, need free tire
void putBackAutoPtr(int type, STire* tire) {
if (tire == NULL) {
return ;
return;
}
taosThreadMutexLock(&tiresMutex);
if (tires[type] != tire) {
//update by out, can't put back , so free
// update by out, can't put back , so free
if (--tire->ref == 1) {
// support multi thread getAuotPtr
freeTire(tire);
}
} else {
tires[type]->ref--;
assert(tires[type]->ref > 0);
}
taosThreadMutexUnlock(&tiresMutex);
return ;
return;
}
//
// ------------------- var Word --------------------------
//
#define MAX_CACHED_CNT 100000 // max cached rows 10w
#define MAX_CACHED_CNT 100000 // max cached rows 10w
// write sql result to var name, return write rows cnt
int writeVarNames(int type, TAOS_RES* tres) {
// fetch row
// fetch row
TAOS_ROW row = taos_fetch_row(tres);
if (row == NULL) {
return 0;
}
TAOS_FIELD *fields = taos_fetch_fields(tres);
TAOS_FIELD* fields = taos_fetch_fields(tres);
// create new tires
char tireType = type == WT_VAR_TABLE ? TIRE_TREE : TIRE_LIST;
char tireType = type == WT_VAR_TABLE ? TIRE_TREE : TIRE_LIST;
STire* tire = createTire(tireType);
// enum rows
char name[1024];
int numOfRows = 0;
int numOfRows = 0;
do {
int32_t* lengths = taos_fetch_lengths(tres);
int32_t bytes = lengths[0];
if(fields[0].type == TSDB_DATA_TYPE_INT) {
sprintf(name,"%d", *(int16_t*)row[0]);
int32_t bytes = lengths[0];
if (fields[0].type == TSDB_DATA_TYPE_INT) {
sprintf(name, "%d", *(int16_t*)row[0]);
} else {
memcpy(name, row[0], bytes);
}
name[bytes] = 0; //set string end
name[bytes] = 0; // set string end
// insert to tire
insertWord(tire, name);
if (++numOfRows > MAX_CACHED_CNT ) {
if (++numOfRows > MAX_CACHED_CNT) {
break;
}
......@@ -895,12 +771,12 @@ int writeVarNames(int type, TAOS_RES* tres) {
return numOfRows;
}
bool firstMatchCommand(TAOS * con, SShellCmd * cmd);
bool firstMatchCommand(TAOS* con, SShellCmd* cmd);
//
// thread obtain var thread from db server
// thread obtain var thread from db server
//
void* varObtainThread(void* param) {
int type = *(int* )param;
int type = *(int*)param;
taosMemoryFree(param);
if (varCon == NULL || type > WT_FROM_DB_MAX) {
......@@ -919,7 +795,7 @@ void* varObtainThread(void* param) {
// free sql
taos_free_result(pSql);
// check need call auto tab
// check need call auto tab
if (cnt > 0 && waitAutoFill) {
// press tab key by program
firstMatchCommand(varCon, varCmd);
......@@ -949,11 +825,10 @@ char* matchNextPrefix(STire* tire, char* pre) {
// NOT EMPTY
match = matchPrefix(tire, pre, NULL);
}
// save to lastMatch
if (match) {
if (lastMatch)
freeMatch(lastMatch);
if (lastMatch) freeMatch(lastMatch);
lastMatch = match;
}
}
......@@ -967,11 +842,11 @@ char* matchNextPrefix(STire* tire, char* pre) {
if (cursorVar == -1) {
// first
cursorVar = 0;
return strdup(match->head->word);
return strdup(match->head->word);
}
// according to cursorVar , calculate next one
int i = 0;
int i = 0;
SMatchNode* item = match->head;
while (item) {
if (i == cursorVar + 1) {
......@@ -1008,12 +883,11 @@ char* tireSearchWord(int type, char* pre) {
return NULL;
}
if(type > WT_FROM_DB_MAX) {
if (type > WT_FROM_DB_MAX) {
// NOT FROM DB , tires[type] alwary not null
STire* tire = tires[type];
if (tire == NULL)
return NULL;
return matchNextPrefix(tire, pre);
if (tire == NULL) return NULL;
return matchNextPrefix(tire, pre);
}
// TYPE CONTEXT GET FROM DB
......@@ -1025,7 +899,7 @@ char* tireSearchWord(int type, char* pre) {
// need async obtain var names from db sever
if (threads[type] != NULL) {
if (taosThreadRunning(threads[type])) {
// thread running , need not obtain again, return
// thread running , need not obtain again, return
taosThreadMutexUnlock(&tiresMutex);
return NULL;
}
......@@ -1033,10 +907,10 @@ char* tireSearchWord(int type, char* pre) {
taosDestroyThread(threads[type]);
threads[type] = NULL;
}
// create new
void * param = taosMemoryMalloc(sizeof(int));
*((int* )param) = type;
void* param = taosMemoryMalloc(sizeof(int));
*((int*)param) = type;
threads[type] = taosCreateThread(varObtainThread, param);
taosThreadMutexUnlock(&tiresMutex);
return NULL;
......@@ -1056,9 +930,9 @@ char* tireSearchWord(int type, char* pre) {
return str;
}
// match var word, word1 is pattern , word2 is input from shell
// match var word, word1 is pattern , word2 is input from shell
bool matchVarWord(SWord* word1, SWord* word2) {
// search input word from tire tree
// search input word from tire tree
char pre[512];
memcpy(pre, word2->word, word2->len);
pre[word2->len] = 0;
......@@ -1069,8 +943,7 @@ bool matchVarWord(SWord* word1, SWord* word2) {
str = tireSearchWord(WT_VAR_STABLE, pre);
if (str == NULL) {
str = tireSearchWord(WT_VAR_TABLE, pre);
if(str == NULL)
return false;
if (str == NULL) return false;
}
} else {
// OTHER
......@@ -1082,15 +955,15 @@ bool matchVarWord(SWord* word1, SWord* word2) {
}
// free previous malloc
if(word1->free && word1->word) {
if (word1->free && word1->word) {
taosMemoryFree(word1->word);
}
// save
word1->word = str;
word1->len = strlen(str);
word1->free = true; // need free
word1->len = strlen(str);
word1->free = true; // need free
return true;
}
......@@ -1098,11 +971,10 @@ bool matchVarWord(SWord* word1, SWord* word2) {
// ------------------- match words --------------------------
//
// compare command cmd1 come from shellCommands , cmd2 come from user input
int32_t compareCommand(SWords * cmd1, SWords * cmd2) {
SWord * word1 = cmd1->head;
SWord * word2 = cmd2->head;
int32_t compareCommand(SWords* cmd1, SWords* cmd2) {
SWord* word1 = cmd1->head;
SWord* word2 = cmd2->head;
if (word1 == NULL || word2 == NULL) {
return -1;
......@@ -1112,8 +984,7 @@ int32_t compareCommand(SWords * cmd1, SWords * cmd2) {
if (word1->type == WT_TEXT) {
// WT_TEXT match
if (word1->len == word2->len) {
if (strncasecmp(word1->word, word2->word, word1->len) != 0)
return -1;
if (strncasecmp(word1->word, word2->word, word1->len) != 0) return -1;
} else if (word1->len < word2->len) {
return -1;
} else {
......@@ -1128,7 +999,7 @@ int32_t compareCommand(SWords * cmd1, SWords * cmd2) {
}
} else {
// WT_VAR auto match any one word
if (word2->next == NULL) { // input words last one
if (word2->next == NULL) { // input words last one
if (matchVarWord(word1, word2)) {
cmd1->matchIndex = i;
cmd1->matchLen = word2->len;
......@@ -1151,10 +1022,10 @@ int32_t compareCommand(SWords * cmd1, SWords * cmd2) {
}
// match command
SWords * matchCommand(SWords * input, bool continueSearch) {
SWords* matchCommand(SWords* input, bool continueSearch) {
int32_t count = SHELL_COMMAND_COUNT();
for (int32_t i = 0; i < count; i ++) {
SWords * shellCommand = shellCommands + i;
for (int32_t i = 0; i < count; i++) {
SWords* shellCommand = shellCommands + i;
if (continueSearch && lastMatchIndex != -1 && i <= lastMatchIndex) {
// new match must greate than lastMatchIndex
if (varMode && i == lastMatchIndex) {
......@@ -1165,15 +1036,14 @@ SWords * matchCommand(SWords * input, bool continueSearch) {
}
// command is large
if (input->count > shellCommand->count ) {
if (input->count > shellCommand->count) {
continue;
}
// compare
int32_t index = compareCommand(shellCommand, input);
if (index != -1) {
if (firstMatchIndex == -1)
firstMatchIndex = i;
if (firstMatchIndex == -1) firstMatchIndex = i;
curMatchIndex = i;
return &shellCommands[i];
}
......@@ -1188,7 +1058,7 @@ SWords * matchCommand(SWords * input, bool continueSearch) {
//
// delete char count
void deleteCount(SShellCmd * cmd, int count) {
void deleteCount(SShellCmd* cmd, int count) {
int size = 0;
int width = 0;
int prompt_size = 6;
......@@ -1207,55 +1077,53 @@ void deleteCount(SShellCmd * cmd, int count) {
}
// show screen
void printScreen(TAOS * con, SShellCmd * cmd, SWords * match) {
void printScreen(TAOS* con, SShellCmd* cmd, SWords* match) {
// modify SShellCmd
if (firstMatchIndex == -1 || curMatchIndex == -1) {
// no match
return ;
return;
}
// first tab press
const char * str = NULL;
int strLen = 0;
// first tab press
const char* str = NULL;
int strLen = 0;
if (firstMatchIndex == curMatchIndex && lastWordBytes == -1) {
// first press tab
SWord * word = MATCH_WORD(match);
SWord* word = MATCH_WORD(match);
str = word->word + match->matchLen;
strLen = word->len - match->matchLen;
lastMatchIndex = firstMatchIndex;
lastWordBytes = word->len;
} else {
if (lastWordBytes == -1)
return ;
if (lastWordBytes == -1) return;
deleteCount(cmd, lastWordBytes);
SWord * word = MATCH_WORD(match);
SWord* word = MATCH_WORD(match);
str = word->word;
strLen = word->len;
// set current to last
lastMatchIndex = curMatchIndex;
lastWordBytes = word->len;
}
// insert new
shellInsertChar(cmd, (char *)str, strLen);
shellInsertChar(cmd, (char*)str, strLen);
}
// main key press tab , matched return true else false
bool firstMatchCommand(TAOS * con, SShellCmd * cmd) {
bool firstMatchCommand(TAOS* con, SShellCmd* cmd) {
// parse command
SWords* input = (SWords *)taosMemoryMalloc(sizeof(SWords));
SWords* input = (SWords*)taosMemoryMalloc(sizeof(SWords));
memset(input, 0, sizeof(SWords));
input->source = cmd->command;
input->source_len = cmd->commandSize;
parseCommand(input, false);
// if have many , default match first, if press tab again , switch to next
curMatchIndex = -1;
curMatchIndex = -1;
lastMatchIndex = -1;
SWords * match = matchCommand(input, true);
SWords* match = matchCommand(input, true);
if (match == NULL) {
// not match , nothing to do
freeCommand(input);
......@@ -1271,21 +1139,21 @@ bool firstMatchCommand(TAOS * con, SShellCmd * cmd) {
}
// create input source
void createInputFromFirst(SWords* input, SWords * firstMatch) {
void createInputFromFirst(SWords* input, SWords* firstMatch) {
//
// if next pressTabKey , input context come from firstMatch, set matched length with source_len
//
input->source = (char*)taosMemoryMalloc(1024);
memset((void* )input->source, 0, 1024);
memset((void*)input->source, 0, 1024);
SWord * word = firstMatch->head;
SWord* word = firstMatch->head;
// source_len = full match word->len + half match with firstMatch->matchLen
// source_len = full match word->len + half match with firstMatch->matchLen
for (int i = 0; i < firstMatch->matchIndex && word; i++) {
// combine source from each word
strncpy(input->source + input->source_len, word->word, word->len);
strcat(input->source, " "); // append blank splite
input->source_len += word->len + 1; // 1 is blank length
strcat(input->source, " "); // append blank splite
input->source_len += word->len + 1; // 1 is blank length
// move next
word = word->next;
}
......@@ -1297,11 +1165,11 @@ void createInputFromFirst(SWords* input, SWords * firstMatch) {
}
// user press Tabkey again is named next , matched return true else false
bool nextMatchCommand(TAOS * con, SShellCmd * cmd, SWords * firstMatch) {
bool nextMatchCommand(TAOS* con, SShellCmd* cmd, SWords* firstMatch) {
if (firstMatch == NULL || firstMatch->head == NULL) {
return false;
}
SWords* input = (SWords *)taosMemoryMalloc(sizeof(SWords));
SWords* input = (SWords*)taosMemoryMalloc(sizeof(SWords));
memset(input, 0, sizeof(SWords));
// create input from firstMatch
......@@ -1311,16 +1179,15 @@ bool nextMatchCommand(TAOS * con, SShellCmd * cmd, SWords * firstMatch) {
parseCommand(input, false);
// if have many , default match first, if press tab again , switch to next
SWords * match = matchCommand(input, true);
SWords* match = matchCommand(input, true);
if (match == NULL) {
// if not match , reset all index
firstMatchIndex = -1;
curMatchIndex = -1;
curMatchIndex = -1;
match = matchCommand(input, false);
if (match == NULL) {
freeCommand(input);
if (input->source)
taosMemoryFree(input->source);
if (input->source) taosMemoryFree(input->source);
taosMemoryFree(input);
return false;
}
......@@ -1341,41 +1208,40 @@ bool nextMatchCommand(TAOS * con, SShellCmd * cmd, SWords * firstMatch) {
}
// fill with type
bool fillWithType(TAOS * con, SShellCmd * cmd, char* pre, int type) {
bool fillWithType(TAOS* con, SShellCmd* cmd, char* pre, int type) {
// get type
STire* tire = tires[type];
char* str = matchNextPrefix(tire, pre);
char* str = matchNextPrefix(tire, pre);
if (str == NULL) {
return false;
}
// need insert part string
char * part = str + strlen(pre);
char* part = str + strlen(pre);
// show
int count = strlen(part);
shellInsertChar(cmd, part, count);
cntDel = count; // next press tab delete current append count
cntDel = count; // next press tab delete current append count
taosMemoryFree(str);
return true;
}
// fill with type
bool fillTableName(TAOS * con, SShellCmd * cmd, char* pre) {
bool fillTableName(TAOS* con, SShellCmd* cmd, char* pre) {
// search stable and table
char * str = tireSearchWord(WT_VAR_STABLE, pre);
char* str = tireSearchWord(WT_VAR_STABLE, pre);
if (str == NULL) {
str = tireSearchWord(WT_VAR_TABLE, pre);
if(str == NULL)
return false;
if (str == NULL) return false;
}
// need insert part string
char * part = str + strlen(pre);
char* part = str + strlen(pre);
// delete autofill count last append
if(cntDel > 0) {
if (cntDel > 0) {
deleteCount(cmd, cntDel);
cntDel = 0;
}
......@@ -1383,8 +1249,8 @@ bool fillTableName(TAOS * con, SShellCmd * cmd, char* pre) {
// show
int count = strlen(part);
shellInsertChar(cmd, part, count);
cntDel = count; // next press tab delete current append count
cntDel = count; // next press tab delete current append count
taosMemoryFree(str);
return true;
}
......@@ -1396,20 +1262,20 @@ bool fillTableName(TAOS * con, SShellCmd * cmd, char* pre) {
// 2 select count(*),su -> select count(*), sum(
// 3 select count(*), su -> select count(*), sum(
//
char * lastWord(char * p) {
// get near from end revert find ' ' and ','
char * p1 = strrchr(p, ' ');
char * p2 = strrchr(p, ',');
char* lastWord(char* p) {
// get near from end revert find ' ' and ','
char* p1 = strrchr(p, ' ');
char* p2 = strrchr(p, ',');
if (p1 && p2) {
return p1 > p2 ? p1 : p2 + 1;
} else if (p1) {
return p1 + 1;
} else if(p2) {
} else if (p2) {
return p2 + 1;
} else {
return p;
}
}
}
bool fieldsInputEnd(char* sql) {
......@@ -1425,18 +1291,18 @@ bool fieldsInputEnd(char* sql) {
}
// not in ','
char * p3 = strrchr(sql, ',');
char * p = p3;
// like select ts, age,' '
char* p3 = strrchr(sql, ',');
char* p = p3;
// like select ts, age,' '
if (p) {
++p;
bool allBlank = true; // after last ',' all char is blank
int cnt = 0; // blank count , like ' ' as one blank
char * plast = NULL; // last blank position
while(*p) {
bool allBlank = true; // after last ',' all char is blank
int cnt = 0; // blank count , like ' ' as one blank
char* plast = NULL; // last blank position
while (*p) {
if (*p == ' ') {
plast = p;
cnt ++;
cnt++;
} else {
allBlank = false;
}
......@@ -1444,7 +1310,7 @@ bool fieldsInputEnd(char* sql) {
}
// any one word is not blank
if(allBlank) {
if (allBlank) {
return false;
}
......@@ -1454,13 +1320,13 @@ bool fieldsInputEnd(char* sql) {
}
// if last char not ' ', then not end field, like 'select count(*), su' can fill sum(
if(sql[strlen(sql)-1] != ' ' && cnt <= 1) {
if (sql[strlen(sql) - 1] != ' ' && cnt <= 1) {
return false;
}
}
char * p4 = strrchr(sql, ' ');
if(p4 == NULL) {
char* p4 = strrchr(sql, ' ');
if (p4 == NULL) {
// only one word
return false;
}
......@@ -1469,9 +1335,9 @@ bool fieldsInputEnd(char* sql) {
}
// need insert from
bool needInsertFrom(char * sql, int len) {
// last is blank
if(sql[len-1] != ' ') {
bool needInsertFrom(char* sql, int len) {
// last is blank
if (sql[len - 1] != ' ') {
// insert from keyword
return false;
}
......@@ -1486,45 +1352,45 @@ bool needInsertFrom(char * sql, int len) {
}
// p is string following select keyword
bool appendAfterSelect(TAOS * con, SShellCmd * cmd, char* sql, int32_t len) {
bool appendAfterSelect(TAOS* con, SShellCmd* cmd, char* sql, int32_t len) {
char* p = strndup(sql, len);
// union all
char * p1;
char* p1;
do {
p1 = strstr(p, UNION_ALL);
if(p1) {
if (p1) {
p = p1 + strlen(UNION_ALL);
}
} while (p1);
char * from = strstr(p, " from ");
//last word , maybe empty string or some letters of a string
char * last = lastWord(p);
bool ret = false;
char* from = strstr(p, " from ");
// last word , maybe empty string or some letters of a string
char* last = lastWord(p);
bool ret = false;
if (from == NULL) {
bool fieldEnd = fieldsInputEnd(p);
// cheeck fields input end then insert from keyword
if (fieldEnd && p[len-1] == ' ') {
if (fieldEnd && p[len - 1] == ' ') {
shellInsertChar(cmd, "from", 4);
taosMemoryFree(p);
return true;
}
// fill funciton
if(fieldEnd) {
if (fieldEnd) {
// fields is end , need match keyword
ret = fillWithType(con, cmd, last, WT_VAR_KEYWORD);
} else {
ret = fillWithType(con, cmd, last, WT_VAR_FUNC);
}
taosMemoryFree(p);
return ret;
}
// have from
char * blank = strstr(from + 6, " ");
char* blank = strstr(from + 6, " ");
if (blank == NULL) {
// no table name, need fill
ret = fillTableName(con, cmd, last);
......@@ -1538,13 +1404,12 @@ bool appendAfterSelect(TAOS * con, SShellCmd * cmd, char* sql, int32_t len) {
int32_t searchAfterSelect(char* p, int32_t len) {
// select * from st;
if(strncasecmp(p, "select ", 7) == 0) {
if (strncasecmp(p, "select ", 7) == 0) {
// check nest query
char *p1 = p + 7;
while(1) {
char *p2 = strstr(p1, "select ");
if(p2 == NULL)
break;
char* p1 = p + 7;
while (1) {
char* p2 = strstr(p1, "select ");
if (p2 == NULL) break;
p1 = p2 + 7;
}
......@@ -1552,29 +1417,29 @@ int32_t searchAfterSelect(char* p, int32_t len) {
}
// explain as select * from st;
if(strncasecmp(p, "explain select ", 15) == 0) {
if (strncasecmp(p, "explain select ", 15) == 0) {
return 15;
}
char* as_pos_end = strstr(p, " as select ");
if (as_pos_end == NULL)
return -1;
if (as_pos_end == NULL) return -1;
as_pos_end += 11;
// create stream <stream_name> as select
if(strncasecmp(p, "create stream ", 14) == 0) {
return as_pos_end - p;;
if (strncasecmp(p, "create stream ", 14) == 0) {
return as_pos_end - p;
;
}
// create topic <topic_name> as select
if(strncasecmp(p, "create topic ", 13) == 0) {
if (strncasecmp(p, "create topic ", 13) == 0) {
return as_pos_end - p;
}
return -1;
}
bool matchSelectQuery(TAOS * con, SShellCmd * cmd) {
bool matchSelectQuery(TAOS* con, SShellCmd* cmd) {
// if continue press Tab , delete bytes by previous autofill
if (cntDel > 0) {
deleteCount(cmd, cntDel);
......@@ -1582,8 +1447,8 @@ bool matchSelectQuery(TAOS * con, SShellCmd * cmd) {
}
// match select ...
int len = cmd->commandSize;
char * p = cmd->command;
int len = cmd->commandSize;
char* p = cmd->command;
// remove prefix blank
while (p[0] == ' ' && len > 0) {
......@@ -1592,17 +1457,16 @@ bool matchSelectQuery(TAOS * con, SShellCmd * cmd) {
}
// special range
if(len < 7 || len > 512) {
if (len < 7 || len > 512) {
return false;
}
// search
char* sql_cp = strndup(p, len);
char* sql_cp = strndup(p, len);
int32_t n = searchAfterSelect(sql_cp, len);
taosMemoryFree(sql_cp);
if(n == -1 || n > len)
return false;
p += n;
if (n == -1 || n > len) return false;
p += n;
len -= n;
// append
......@@ -1610,15 +1474,15 @@ bool matchSelectQuery(TAOS * con, SShellCmd * cmd) {
}
// if is input create fields or tags area, return true
bool isCreateFieldsArea(char * p) {
char * left = strrchr(p, '(');
bool isCreateFieldsArea(char* p) {
char* left = strrchr(p, '(');
if (left == NULL) {
// like 'create table st'
return false;
}
char * right = strrchr(p, ')');
if(right == NULL) {
char* right = strrchr(p, ')');
if (right == NULL) {
// like 'create table st( '
return true;
}
......@@ -1631,7 +1495,7 @@ bool isCreateFieldsArea(char * p) {
return false;
}
bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
bool matchCreateTable(TAOS* con, SShellCmd* cmd) {
// if continue press Tab , delete bytes by previous autofill
if (cntDel > 0) {
deleteCount(cmd, cntDel);
......@@ -1639,8 +1503,8 @@ bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
}
// match select ...
int len = cmd->commandSize;
char * p = cmd->command;
int len = cmd->commandSize;
char* p = cmd->command;
// remove prefix blank
while (p[0] == ' ' && len > 0) {
......@@ -1649,12 +1513,12 @@ bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
}
// special range
if(len < 7 || len > 1024) {
if (len < 7 || len > 1024) {
return false;
}
// select and from
if(strncasecmp(p, "create table ", 13) != 0) {
// select and from
if (strncasecmp(p, "create table ", 13) != 0) {
// not select query clause
return false;
}
......@@ -1662,8 +1526,8 @@ bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
len -= 13;
char* ps = strndup(p, len);
bool ret = false;
char * last = lastWord(ps);
bool ret = false;
char* last = lastWord(ps);
// check in create fields or tags input area
if (isCreateFieldsArea(ps)) {
......@@ -1673,9 +1537,9 @@ bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
// tags
if (!ret) {
// find only one ')' , can insert tags
char * p1 = strchr(ps, ')');
char* p1 = strchr(ps, ')');
if (p1) {
if(strchr(p1 + 1, ')') == NULL && strstr(p1 + 1, "tags") == NULL) {
if (strchr(p1 + 1, ')') == NULL && strstr(p1 + 1, "tags") == NULL) {
// can insert tags keyword
ret = fillWithType(con, cmd, last, WT_VAR_KEYTAGS);
}
......@@ -1685,9 +1549,9 @@ bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
// tb options
if (!ret) {
// find like create talbe st (...) tags(..) <here is fill tb option area>
char * p1 = strchr(ps, ')'); // first ')' end
char* p1 = strchr(ps, ')'); // first ')' end
if (p1) {
if(strchr(p1 + 1, ')')) { // second ')' end
if (strchr(p1 + 1, ')')) { // second ')' end
// here is tb options area, can insert option
ret = fillWithType(con, cmd, last, WT_VAR_TBOPTION);
}
......@@ -1698,8 +1562,8 @@ bool matchCreateTable(TAOS * con, SShellCmd * cmd) {
return ret;
}
bool matchOther(TAOS * con, SShellCmd * cmd) {
int len = cmd->commandSize;
bool matchOther(TAOS* con, SShellCmd* cmd) {
int len = cmd->commandSize;
char* p = cmd->command;
// '\\'
......@@ -1711,8 +1575,7 @@ bool matchOther(TAOS * con, SShellCmd * cmd) {
}
// too small
if(len < 8)
return false;
if (len < 8) return false;
// like 'from ( '
char* sql = strndup(p, len);
......@@ -1721,36 +1584,35 @@ bool matchOther(TAOS * con, SShellCmd * cmd) {
if (strcmp(last, "from(") == 0) {
fillWithType(con, cmd, "", WT_VAR_KEYSELECT);
taosMemoryFree(sql);
return true;
return true;
}
if (strncmp(last, "(", 1) == 0) {
last += 1;
last += 1;
}
char* from = strstr(sql, " from");
// find last ' from'
while (from) {
char* p1 = strstr(from + 5, " from");
if (p1 == NULL)
break;
if (p1 == NULL) break;
from = p1;
}
if (from) {
// find next is '('
char * p2 = from + 5;
bool found = false; // found 'from ... ( ...' ... is any count of blank
bool found1 = false; // found '('
char* p2 = from + 5;
bool found = false; // found 'from ... ( ...' ... is any count of blank
bool found1 = false; // found '('
while (1) {
if ( p2 == last || *p2 == '\0') {
if (p2 == last || *p2 == '\0') {
// last word or string end
if (found1) {
found = true;
}
break;
} else if(*p2 == '(') {
} else if (*p2 == '(') {
found1 = true;
} else if(*p2 == ' ') {
} else if (*p2 == ' ') {
// do nothing
} else {
// have any other char
......@@ -1768,24 +1630,22 @@ bool matchOther(TAOS * con, SShellCmd * cmd) {
}
}
// INSERT
// INSERT
taosMemoryFree(sql);
return false;
}
// main key press tab
void pressTabKey(SShellCmd * cmd) {
// check
if (cmd->commandSize == 0) {
void pressTabKey(SShellCmd* cmd) {
// check
if (cmd->commandSize == 0) {
// empty
showHelp();
shellShowOnScreen(cmd);
return ;
}
return;
}
// save connection to global
varCmd = cmd;
......@@ -1793,45 +1653,41 @@ void pressTabKey(SShellCmd * cmd) {
// manual match like create table st( ...
matched = matchCreateTable(varCon, cmd);
if (matched)
return ;
if (matched) return;
// shellCommands match
// shellCommands match
if (firstMatchIndex == -1) {
matched = firstMatchCommand(varCon, cmd);
} else {
matched = nextMatchCommand(varCon, cmd, &shellCommands[firstMatchIndex]);
}
if (matched)
return ;
if (matched) return;
// NOT MATCHED ANYONE
// match other like '\G' ...
matched = matchOther(varCon, cmd);
if (matched)
return ;
if (matched) return;
// manual match like select * from ...
matched = matchSelectQuery(varCon, cmd);
if (matched)
return ;
if (matched) return;
return ;
return;
}
// press othr key
void pressOtherKey(char c) {
// reset global variant
firstMatchIndex = -1;
lastMatchIndex = -1;
curMatchIndex = -1;
lastWordBytes = -1;
lastMatchIndex = -1;
curMatchIndex = -1;
lastWordBytes = -1;
// var names
cursorVar = -1;
varMode = false;
cursorVar = -1;
varMode = false;
waitAutoFill = false;
cntDel = 0;
cntDel = 0;
if (lastMatch) {
freeMatch(lastMatch);
......@@ -1840,18 +1696,18 @@ void pressOtherKey(char c) {
}
// put name into name, return name length
int getWordName(char* p, char * name, int nameLen) {
//remove prefix blank
int getWordName(char* p, char* name, int nameLen) {
// remove prefix blank
while (*p == ' ') {
p++;
}
// get databases name;
int i = 0;
while(p[i] != 0 && i < nameLen - 1) {
name[i] = p[i];
while (p[i] != 0 && i < nameLen - 1) {
name[i] = p[i];
i++;
if(p[i] == ' ' || p[i] == ';'|| p[i] == '(') {
if (p[i] == ' ' || p[i] == ';' || p[i] == '(') {
// name end
break;
}
......@@ -1862,22 +1718,22 @@ int getWordName(char* p, char * name, int nameLen) {
}
// deal use db, if have 'use' return true
bool dealUseDB(char * sql) {
// check use keyword
if(strncasecmp(sql, "use ", 4) != 0) {
bool dealUseDB(char* sql) {
// check use keyword
if (strncasecmp(sql, "use ", 4) != 0) {
return false;
}
char db[256];
char *p = sql + 4;
char db[256];
char* p = sql + 4;
if (getWordName(p, db, sizeof(db)) == 0) {
// no name , return
// no name , return
return true;
}
// dbName is previous use open db name
if (strcasecmp(db, dbName) == 0) {
// same , no need switch
// same , no need switch
return true;
}
......@@ -1886,13 +1742,13 @@ bool dealUseDB(char * sql) {
// STABLE set null
STire* tire = tires[WT_VAR_STABLE];
tires[WT_VAR_STABLE] = NULL;
if(tire) {
if (tire) {
freeTire(tire);
}
// TABLE set null
tire = tires[WT_VAR_TABLE];
tires[WT_VAR_TABLE] = NULL;
if(tire) {
if (tire) {
freeTire(tire);
}
// save
......@@ -1903,16 +1759,16 @@ bool dealUseDB(char * sql) {
}
// deal create, if have 'create' return true
bool dealCreateCommand(char * sql) {
// check keyword
if(strncasecmp(sql, "create ", 7) != 0) {
bool dealCreateCommand(char* sql) {
// check keyword
if (strncasecmp(sql, "create ", 7) != 0) {
return false;
}
char name[1024];
char *p = sql + 7;
char name[1024];
char* p = sql + 7;
if (getWordName(p, name, sizeof(name)) == 0) {
// no name , return
// no name , return
return true;
}
......@@ -1921,7 +1777,7 @@ bool dealCreateCommand(char * sql) {
if (strcasecmp(name, "database") == 0) {
type = WT_VAR_DBNAME;
} else if (strcasecmp(name, "table") == 0) {
if(strstr(sql, " tags") != NULL && strstr(sql, " using ") == NULL)
if (strstr(sql, " tags") != NULL && strstr(sql, " using ") == NULL)
type = WT_VAR_STABLE;
else
type = WT_VAR_TABLE;
......@@ -1932,7 +1788,7 @@ bool dealCreateCommand(char * sql) {
} else if (strcasecmp(name, "stream") == 0) {
type = WT_VAR_STREAM;
} else {
// no match , return
// no match , return
return true;
}
......@@ -1941,7 +1797,7 @@ bool dealCreateCommand(char * sql) {
// get next word , that is table name
if (getWordName(p, name, sizeof(name)) == 0) {
// no name , return
// no name , return
return true;
}
......@@ -1949,7 +1805,7 @@ bool dealCreateCommand(char * sql) {
taosThreadMutexLock(&tiresMutex);
// STABLE set null
STire* tire = tires[type];
if(tire) {
if (tire) {
insertWord(tire, name);
}
taosThreadMutexUnlock(&tiresMutex);
......@@ -1958,16 +1814,16 @@ bool dealCreateCommand(char * sql) {
}
// deal create, if have 'drop' return true
bool dealDropCommand(char * sql) {
// check keyword
if(strncasecmp(sql, "drop ", 5) != 0) {
bool dealDropCommand(char* sql) {
// check keyword
if (strncasecmp(sql, "drop ", 5) != 0) {
return false;
}
char name[1024];
char *p = sql + 5;
char name[1024];
char* p = sql + 5;
if (getWordName(p, name, sizeof(name)) == 0) {
// no name , return
// no name , return
return true;
}
......@@ -1986,7 +1842,7 @@ bool dealDropCommand(char * sql) {
} else if (strcasecmp(name, "stream") == 0) {
type = WT_VAR_STREAM;
} else {
// no match , return
// no match , return
return true;
}
......@@ -1995,30 +1851,27 @@ bool dealDropCommand(char * sql) {
// get next word , that is table name
if (getWordName(p, name, sizeof(name)) == 0) {
// no name , return
// no name , return
return true;
}
// switch new db
taosThreadMutexLock(&tiresMutex);
// STABLE set null
if(type == WT_VAR_ALLTABLE) {
if (type == WT_VAR_ALLTABLE) {
bool del = false;
// del in stable
STire* tire = tires[WT_VAR_STABLE];
if(tire)
del = deleteWord(tire, name);
if (tire) del = deleteWord(tire, name);
// del in table
if(!del) {
if (!del) {
tire = tires[WT_VAR_TABLE];
if(tire)
del = deleteWord(tire, name);
if (tire) del = deleteWord(tire, name);
}
} else {
// OTHER TYPE
STire* tire = tires[type];
if(tire)
deleteWord(tire, name);
if (tire) deleteWord(tire, name);
}
taosThreadMutexUnlock(&tiresMutex);
......@@ -2027,26 +1880,26 @@ bool dealDropCommand(char * sql) {
// callback autotab module after shell sql execute
void callbackAutoTab(char* sqlstr, TAOS* pSql, bool usedb) {
char * sql = sqlstr;
char* sql = sqlstr;
// remove prefix blank
while (*sql == ' ') {
sql++;
}
if(dealUseDB(sql)) {
if (dealUseDB(sql)) {
// change to new db
return ;
return;
}
// create command add name to autotab
if(dealCreateCommand(sql)) {
return ;
if (dealCreateCommand(sql)) {
return;
}
// drop command remove name from autotab
if(dealDropCommand(sql)) {
return ;
if (dealDropCommand(sql)) {
return;
}
return ;
return;
}
......@@ -22,414 +22,405 @@
// create prefix search tree
STire* createTire(char type) {
STire* tire = taosMemoryMalloc(sizeof(STire));
memset(tire, 0, sizeof(STire));
tire->ref = 1; // init is 1
tire->type = type;
tire->root.d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *));
return tire;
STire* tire = taosMemoryMalloc(sizeof(STire));
memset(tire, 0, sizeof(STire));
tire->ref = 1; // init is 1
tire->type = type;
tire->root.d = (STireNode**)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode*));
return tire;
}
// free tire node
void freeTireNode(STireNode* node) {
if (node == NULL)
return ;
// nest free sub node on array d
if(node->d) {
for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(node->d[i]);
}
taosMemoryFree(node->d);
if (node == NULL) return;
// nest free sub node on array d
if (node->d) {
for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(node->d[i]);
}
taosMemoryFree(node->d);
}
// free self
taosMemoryFree(node);
// free self
taosMemoryFree(node);
}
// destroy prefix search tree
void freeTire(STire* tire) {
// free nodes
for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(tire->root.d[i]);
}
taosMemoryFree(tire->root.d);
// free from list
StrName * item = tire->head;
while (item) {
StrName * next = item->next;
// free string
taosMemoryFree(item->name);
// free node
taosMemoryFree(item);
// move next
item = next;
}
tire->head = tire->tail = NULL;
// free tire
taosMemoryFree(tire);
// free nodes
for (int i = 0; i < CHAR_CNT; i++) {
freeTireNode(tire->root.d[i]);
}
taosMemoryFree(tire->root.d);
// free from list
StrName* item = tire->head;
while (item) {
StrName* next = item->next;
// free string
taosMemoryFree(item->name);
// free node
taosMemoryFree(item);
// move next
item = next;
}
tire->head = tire->tail = NULL;
// free tire
taosMemoryFree(tire);
}
// insert a new word to list
bool insertToList(STire* tire, char* word) {
StrName * p = (StrName *)taosMemoryMalloc(sizeof(StrName));
p->name = strdup(word);
p->next = NULL;
if(tire->head == NULL) {
tire->head = p;
tire->tail = p;
}else {
tire->tail->next = p;
tire->tail = p;
}
return true;
StrName* p = (StrName*)taosMemoryMalloc(sizeof(StrName));
p->name = strdup(word);
p->next = NULL;
if (tire->head == NULL) {
tire->head = p;
tire->tail = p;
} else {
tire->tail->next = p;
tire->tail = p;
}
return true;
}
// insert a new word to tree
bool insertToTree(STire* tire, char* word, int len) {
int m = 0;
STireNode ** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) {
return false;
}
if (nodes[m] == NULL) {
// no pointer
STireNode* p = (STireNode* )taosMemoryMalloc(sizeof(STireNode));
memset(p, 0, sizeof(STireNode));
nodes[m] = p;
if (i == len - 1) {
// is end
p->end = true;
break;
}
}
if (nodes[m]->d == NULL) {
// malloc d
nodes[m]->d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *));
}
// move to next node
nodes = nodes[m]->d;
int m = 0;
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) {
return false;
}
// add count
tire->count += 1;
return true;
if (nodes[m] == NULL) {
// no pointer
STireNode* p = (STireNode*)taosMemoryMalloc(sizeof(STireNode));
memset(p, 0, sizeof(STireNode));
nodes[m] = p;
if (i == len - 1) {
// is end
p->end = true;
break;
}
}
if (nodes[m]->d == NULL) {
// malloc d
nodes[m]->d = (STireNode**)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode*));
}
// move to next node
nodes = nodes[m]->d;
}
// add count
tire->count += 1;
return true;
}
// insert a new word
// insert a new word
bool insertWord(STire* tire, char* word) {
int len = strlen(word);
if (len >= MAX_WORD_LEN) {
return false;
}
switch (tire->type) {
case TIRE_TREE:
return insertToTree(tire, word, len);
case TIRE_LIST:
return insertToList(tire, word);
default:
break;
}
int len = strlen(word);
if (len >= MAX_WORD_LEN) {
return false;
}
switch (tire->type) {
case TIRE_TREE:
return insertToTree(tire, word, len);
case TIRE_LIST:
return insertToList(tire, word);
default:
break;
}
return false;
}
// delete one word from list
bool deleteFromList(STire* tire, char* word) {
StrName * item = tire->head;
while (item) {
if (strcmp(item->name, word) == 0) {
// found, reset empty to delete
item->name[0] = 0;
}
// move next
item = item->next;
StrName* item = tire->head;
while (item) {
if (strcmp(item->name, word) == 0) {
// found, reset empty to delete
item->name[0] = 0;
}
return true;
// move next
item = item->next;
}
return true;
}
// delete one word from tree
// delete one word from tree
bool deleteFromTree(STire* tire, char* word, int len) {
int m = 0;
bool del = false;
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII;
if (m < 0 || m >= CHAR_CNT) {
return false;
}
if (nodes[m] == NULL) {
// no found
return false;
} else {
// not null
if(i == len - 1) {
// this is last, only set end false , not free node
nodes[m]->end = false;
del = true;
break;
}
}
if(nodes[m]->d == NULL)
break;
// move to next node
nodes = nodes[m]->d;
int m = 0;
bool del = false;
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = word[i] - FIRST_ASCII;
if (m < 0 || m >= CHAR_CNT) {
return false;
}
// reduce count
if (del) {
tire->count -= 1;
if (nodes[m] == NULL) {
// no found
return false;
} else {
// not null
if (i == len - 1) {
// this is last, only set end false , not free node
nodes[m]->end = false;
del = true;
break;
}
}
return del;
if (nodes[m]->d == NULL) break;
// move to next node
nodes = nodes[m]->d;
}
// reduce count
if (del) {
tire->count -= 1;
}
return del;
}
// insert a new word
// insert a new word
bool deleteWord(STire* tire, char* word) {
int len = strlen(word);
if (len >= MAX_WORD_LEN) {
return false;
}
switch (tire->type) {
case TIRE_TREE:
return deleteFromTree(tire, word, len);
case TIRE_LIST:
return deleteFromList(tire, word);
default:
break;
}
int len = strlen(word);
if (len >= MAX_WORD_LEN) {
return false;
}
switch (tire->type) {
case TIRE_TREE:
return deleteFromTree(tire, word, len);
case TIRE_LIST:
return deleteFromList(tire, word);
default:
break;
}
return false;
}
void addWordToMatch(SMatch* match, char* word){
// malloc new
SMatchNode* node = (SMatchNode* )taosMemoryMalloc(sizeof(SMatchNode));
memset(node, 0, sizeof(SMatchNode));
node->word = strdup(word);
// append to match
if (match->head == NULL) {
match->head = match->tail = node;
} else {
match->tail->next = node;
match->tail = node;
}
match->count += 1;
void addWordToMatch(SMatch* match, char* word) {
// malloc new
SMatchNode* node = (SMatchNode*)taosMemoryMalloc(sizeof(SMatchNode));
memset(node, 0, sizeof(SMatchNode));
node->word = strdup(word);
// append to match
if (match->head == NULL) {
match->head = match->tail = node;
} else {
match->tail->next = node;
match->tail = node;
}
match->count += 1;
}
// enum all words from node
void enumAllWords(STireNode** nodes, char* prefix, SMatch* match) {
STireNode * c;
char word[MAX_WORD_LEN];
int len = strlen(prefix);
for (int i = 0; i < CHAR_CNT; i++) {
c = nodes[i];
if (c == NULL) {
// chain end node
continue;
} else {
// combine word string
memset(word, 0, sizeof(word));
strcpy(word, prefix);
word[len] = FIRST_ASCII + i; // append current char
// chain middle node
if (c->end) {
// have end flag
addWordToMatch(match, word);
}
// nested call next layer
if (c->d)
enumAllWords(c->d, word, match);
}
void enumAllWords(STireNode** nodes, char* prefix, SMatch* match) {
STireNode* c;
char word[MAX_WORD_LEN];
int len = strlen(prefix);
for (int i = 0; i < CHAR_CNT; i++) {
c = nodes[i];
if (c == NULL) {
// chain end node
continue;
} else {
// combine word string
memset(word, 0, sizeof(word));
strcpy(word, prefix);
word[len] = FIRST_ASCII + i; // append current char
// chain middle node
if (c->end) {
// have end flag
addWordToMatch(match, word);
}
// nested call next layer
if (c->d) enumAllWords(c->d, word, match);
}
}
}
// match prefix from list
void matchPrefixFromList(STire* tire, char* prefix, SMatch* match) {
StrName * item = tire->head;
int len = strlen(prefix);
while (item) {
if ( strncmp(item->name, prefix, len) == 0) {
// prefix matched
addWordToMatch(match, item->name);
}
// move next
item = item->next;
StrName* item = tire->head;
int len = strlen(prefix);
while (item) {
if (strncmp(item->name, prefix, len) == 0) {
// prefix matched
addWordToMatch(match, item->name);
}
// move next
item = item->next;
}
}
// match prefix words, if match is not NULL , put all item to match and return match
void matchPrefixFromTree(STire* tire, char* prefix, SMatch* match) {
SMatch* root = match;
int m = 0;
STireNode* c = 0;
int len = strlen(prefix);
if (len >= MAX_WORD_LEN) {
return;
SMatch* root = match;
int m = 0;
STireNode* c = 0;
int len = strlen(prefix);
if (len >= MAX_WORD_LEN) {
return;
}
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = prefix[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) {
return;
}
STireNode** nodes = tire->root.d;
for (int i = 0; i < len; i++) {
m = prefix[i] - FIRST_ASCII;
if (m < 0 || m > CHAR_CNT) {
return;
}
// match
c = nodes[m];
if (c == NULL) {
// arrive end
break;
}
// previous items already matched
if (i == len - 1) {
// malloc match if not pass by param match
if (root == NULL) {
root = (SMatch* )taosMemoryMalloc(sizeof(SMatch));
memset(root, 0, sizeof(SMatch));
strcpy(root->pre, prefix);
}
// prefix is match to end char
if (c->d)
enumAllWords(c->d, prefix, root);
} else {
// move to next node continue match
if(c->d == NULL)
break;
nodes = c->d;
}
}
// return
return ;
}
SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match) {
if(match == NULL) {
match = (SMatch* )taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch));
// match
c = nodes[m];
if (c == NULL) {
// arrive end
break;
}
switch (tire->type) {
case TIRE_TREE:
matchPrefixFromTree(tire, prefix, match);
case TIRE_LIST:
matchPrefixFromList(tire, prefix, match);
default:
break;
// previous items already matched
if (i == len - 1) {
// malloc match if not pass by param match
if (root == NULL) {
root = (SMatch*)taosMemoryMalloc(sizeof(SMatch));
memset(root, 0, sizeof(SMatch));
strcpy(root->pre, prefix);
}
// prefix is match to end char
if (c->d) enumAllWords(c->d, prefix, root);
} else {
// move to next node continue match
if (c->d == NULL) break;
nodes = c->d;
}
}
// return if need
if (match->count == 0) {
freeMatch(match);
match = NULL;
}
return match;
// return
return;
}
SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match) {
if (match == NULL) {
match = (SMatch*)taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch));
}
switch (tire->type) {
case TIRE_TREE:
matchPrefixFromTree(tire, prefix, match);
case TIRE_LIST:
matchPrefixFromList(tire, prefix, match);
default:
break;
}
// return if need
if (match->count == 0) {
freeMatch(match);
match = NULL;
}
return match;
}
// get all items from tires tree
void enumFromList(STire* tire, SMatch* match) {
StrName * item = tire->head;
while (item) {
if (item->name[0] != 0) {
// not delete
addWordToMatch(match, item->name);
}
// move next
item = item->next;
StrName* item = tire->head;
while (item) {
if (item->name[0] != 0) {
// not delete
addWordToMatch(match, item->name);
}
// move next
item = item->next;
}
}
// get all items from tires tree
void enumFromTree(STire* tire, SMatch* match) {
char pre[2] ={0, 0};
STireNode* c;
// enum first layer
for (int i = 0; i < CHAR_CNT; i++) {
pre[0] = FIRST_ASCII + i;
// each node
c = tire->root.d[i];
if (c == NULL) {
// this branch no data
continue;
}
// this branch have data
if(c->end)
addWordToMatch(match, pre);
else
matchPrefix(tire, pre, match);
char pre[2] = {0, 0};
STireNode* c;
// enum first layer
for (int i = 0; i < CHAR_CNT; i++) {
pre[0] = FIRST_ASCII + i;
// each node
c = tire->root.d[i];
if (c == NULL) {
// this branch no data
continue;
}
// this branch have data
if (c->end)
addWordToMatch(match, pre);
else
matchPrefix(tire, pre, match);
}
}
// get all items from tires tree
SMatch* enumAll(STire* tire) {
SMatch* match = (SMatch* )taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch));
switch (tire->type) {
case TIRE_TREE:
enumFromTree(tire, match);
case TIRE_LIST:
enumFromList(tire, match);
default:
break;
}
// return if need
if (match->count == 0) {
freeMatch(match);
match = NULL;
}
return match;
SMatch* match = (SMatch*)taosMemoryMalloc(sizeof(SMatch));
memset(match, 0, sizeof(SMatch));
switch (tire->type) {
case TIRE_TREE:
enumFromTree(tire, match);
case TIRE_LIST:
enumFromList(tire, match);
default:
break;
}
// return if need
if (match->count == 0) {
freeMatch(match);
match = NULL;
}
return match;
}
// free match result
void freeMatchNode(SMatchNode* node) {
// first free next
if (node->next)
freeMatchNode(node->next);
// second free self
if (node->word)
taosMemoryFree(node->word);
taosMemoryFree(node);
// first free next
if (node->next) freeMatchNode(node->next);
// second free self
if (node->word) taosMemoryFree(node->word);
taosMemoryFree(node);
}
// free match result
void freeMatch(SMatch* match) {
// first free next
if (match->head) {
freeMatchNode(match->head);
}
// second free self
taosMemoryFree(match);
}
// first free next
if (match->head) {
freeMatchNode(match->head);
}
// second free self
taosMemoryFree(match);
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册