diff --git a/src/kit/shell/src/shellAuto.c b/src/kit/shell/src/shellAuto.c index cff639f88546fdd80f7536e564fab8223f5d082b..fc78361f95d5e9f8a5689be9cfb6bd49ae33aa1f 100644 --- a/src/kit/shell/src/shellAuto.c +++ b/src/kit/shell/src/shellAuto.c @@ -78,6 +78,7 @@ SWords shellCommands[] = { {"alter user privilege read", 0, 0, NULL}, {"alter user privilege write", 0, 0, NULL}, {"create table using tags(", 0, 0, NULL}, + {"create table as select ", 0, 0, NULL}, {"create database ", 0, 0, NULL}, {"create table as ", 0, 0, NULL}, {"create dnode ", 0, 0, NULL}, @@ -126,6 +127,7 @@ SWords shellCommands[] = { {"show vgroups;", 0, 0, NULL}, {"insert into values(", 0, 0, NULL}, {"insert into using tags( ) values(", 0, 0, NULL}, + {"insert into using values(", 0, 0, NULL}, {"use ", 0, 0, NULL}, {"quit", 0, 0, NULL} }; @@ -251,6 +253,9 @@ char * key_tags[] = { "tags(" }; +char * key_select[] = { + "select " +}; // // ------- gobal variant define --------- @@ -278,7 +283,8 @@ bool waitAutoFill = false; #define WT_VAR_DATATYPE 10 #define WT_VAR_KEYTAGS 11 #define WT_VAR_ANYWORD 12 -#define WT_VAR_CNT 13 +#define WT_VAR_KEYSELECT 13 +#define WT_VAR_CNT 14 #define WT_FROM_DB_MAX 4 // max get content from db #define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1) @@ -305,7 +311,8 @@ char varTypes[WT_VAR_CNT][64] = { "", "", "", - "" + "", + "" }; char varSqls[WT_FROM_DB_CNT][64] = { @@ -330,9 +337,10 @@ int cntDel = 0; // delete byte count after next press tab // show auto tab introduction void printfIntroduction() { - printf(" ********************* How to Use TAB in TAOS Shell ******************************\n"); - printf(" * Taos shell supports pressing TAB key to complete word. You can try it. *\n"); - printf(" * Press TAB key anywhere, You'll get surprise. *\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"); @@ -346,7 +354,7 @@ void printfIntroduction() { } void showHelp() { - printf("\nThe following are supported commands for Taos shell:"); + printf("\nThe following are supported commands for TDengine Command Line:"); printf("\n\ ----- A ----- \n\ alter database \n\ @@ -586,6 +594,7 @@ bool shellAutoInit() { 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_KEYSELECT,key_select, sizeof(key_select) /sizeof(char *)); printfIntroduction(); @@ -613,7 +622,7 @@ void shellAutoExit() { pthread_mutex_destroy(&tiresMutex); // free threads - for (int32_t i = 0; i < WT_VAR_CNT; i++) { + for (int32_t i = 0; i < WT_FROM_DB_CNT; i++) { if (threads[i]) { taosDestroyThread(threads[i]); threads[i] = NULL; @@ -1242,7 +1251,7 @@ char * lastWord(char * p) { char * p2 = strrchr(p, ','); if (p1 && p2) { - return MAX(p1, p2) + 1; + return p1 > p2 ? p1 : p2 + 1; } else if (p1) { return p1 + 1; } else if(p2) { @@ -1325,37 +1334,9 @@ bool needInsertFrom(char * sql, int len) { return true; } -bool matchSelectQuery(TAOS * con, Command * cmd) { - // if continue press Tab , delete bytes by previous autofill - if (cntDel > 0) { - deleteCount(cmd, cntDel); - cntDel = 0; - } - - // match select ... - int len = cmd->commandSize; - char * p = cmd->command; - - // remove prefix blank - while (p[0] == ' ' && len > 0) { - p++; - len--; - } - - // special range - if(len < 7 || len > 512) { - return false; - } - - // select and from - if(strncasecmp(p, "select ", 7) != 0) { - // not select query clause - return false; - } - p += 7; - len -= 7; - - char* ps = p = strndup(p, len); +// p is string following select keyword +bool appendAfterSelect(TAOS * con, Command * cmd, char* sql, int32_t len) { + char* p = strndup(sql, len); // union all char * p1; @@ -1375,7 +1356,7 @@ bool matchSelectQuery(TAOS * con, Command * cmd) { // cheeck fields input end then insert from keyword if (fieldEnd && p[len-1] == ' ') { insertChar(cmd, "from", 4); - free(ps); + free(p); return true; } @@ -1387,7 +1368,7 @@ bool matchSelectQuery(TAOS * con, Command * cmd) { ret = fillWithType(con, cmd, last, WT_VAR_FUNC); } - free(ps); + free(p); return ret; } @@ -1400,10 +1381,73 @@ bool matchSelectQuery(TAOS * con, Command * cmd) { ret = fillWithType(con, cmd, last, WT_VAR_KEYWORD); } - free(ps); + free(p); return ret; } +int32_t searchAfterSelect(char* p, int32_t len) { + // select * from st; + if(strncasecmp(p, "select ", 7) == 0) { + // check nest query + char *p1 = p + 7; + while(1) { + char *p2 = strstr(p1, "select "); + if(p2 == NULL) + break; + p1 = p2 + 7; + } + + return p1 - p; + } + + char* as_pos_end = strstr(p, " as select "); + if (as_pos_end == NULL) + return -1; + as_pos_end += 11; + + // create table as select + if(strncasecmp(p, "create table ", 13) == 0) { + return as_pos_end - p;; + } + + return -1; +} + +bool matchSelectQuery(TAOS * con, Command * cmd) { + // if continue press Tab , delete bytes by previous autofill + if (cntDel > 0) { + deleteCount(cmd, cntDel); + cntDel = 0; + } + + // match select ... + int len = cmd->commandSize; + char * p = cmd->command; + + // remove prefix blank + while (p[0] == ' ' && len > 0) { + p++; + len--; + } + + // special range + if(len < 7 || len > 512) { + return false; + } + + // search + char* sql_cp = strndup(p, len); + int32_t n = searchAfterSelect(sql_cp, len); + free(sql_cp); + if(n == -1 || n > len) + return false; + p += n; + len -= n; + + // append + return appendAfterSelect(con, cmd, p, len); +} + // if is input create fields or tags area, return true bool isCreateFieldsArea(char * p) { char * left = strrchr(p, '('); @@ -1460,6 +1504,12 @@ bool matchCreateTable(TAOS * con, Command * cmd) { bool ret = false; char * last = lastWord(ps); + // except create table m1 as select .... + if (strstr(ps, " as select")) { + free(ps); + return false; + } + // check in create fields or tags input area if (isCreateFieldsArea(ps)) { ret = fillWithType(con, cmd, last, WT_VAR_DATATYPE); @@ -1484,18 +1534,76 @@ bool matchCreateTable(TAOS * con, Command * cmd) { bool matchOther(TAOS * con, Command * cmd) { int len = cmd->commandSize; char* p = cmd->command; - + // '\\' if (p[len - 1] == '\\') { // append '\G' char a[] = "G;"; insertChar(cmd, a, 2); return true; } - + + // too small + if(len < 8) + return false; + + // like 'from ( ' + char* sql = strndup(p, len); + char* last = lastWord(sql); + + if (strcmp(last, "from(") == 0) { + fillWithType(con, cmd, "", WT_VAR_KEYSELECT); + free(sql); + return true; + } + if (strncmp(last, "(", 1) == 0) { + last += 1; + } + + char* from = strstr(sql, " from"); + // find last ' from' + while (from) { + char* p1 = strstr(from + 5, " from"); + 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 '(' + while (1) { + if ( p2 == last || *p2 == '\0') { + // last word or string end + if (found1) { + found = true; + } + break; + } else if(*p2 == '(') { + found1 = true; + } else if(*p2 == ' ') { + // do nothing + } else { + // have any other char + break; + } + + // move next + p2++; + } + + if (found) { + fillWithType(con, cmd, last, WT_VAR_KEYSELECT); + free(sql); + return true; + } + } + + free(sql); return false; } - // main key press tab void pressTabKey(TAOS * con, Command * cmd) { // check @@ -1761,4 +1869,4 @@ void callbackAutoTab(char* sqlstr, TAOS* pSql, bool usedb) { } return ; -} +} \ No newline at end of file diff --git a/src/kit/shell/src/shellDarwin.c b/src/kit/shell/src/shellDarwin.c index 0108d92e8f6a73317bc510857e17d8c81a62d512..8d461723faf568af993e179443cd8977fa3186f1 100644 --- a/src/kit/shell/src/shellDarwin.c +++ b/src/kit/shell/src/shellDarwin.c @@ -35,7 +35,7 @@ void insertChar(Command *cmd, char *c, int size); void printHelp() { char indent[10] = " "; - printf("taos shell is used to test the TDengine database\n"); + printf("TDengine Command Line is used to test the TDengine database\n"); printf("%s%s\n", indent, "-h"); printf("%s%s%s\n", indent, indent, "TDengine server IP address to connect. The default host is localhost."); @@ -68,7 +68,7 @@ void printHelp() { exit(EXIT_SUCCESS); } -char DARWINCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n" +char DARWINCLIENT_VERSION[] = "Welcome to the TDengine Command Line Interface from %s, Client Version:%s\n" "Copyright (c) 2022 by TAOS Data, Inc. All rights reserved.\n\n"; char g_password[SHELL_MAX_PASSWORD_LEN]; diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index b0c3f4934d2d7180413b2e5a3463b8eb9da8428a..dcd1261a06386e7bd5e6ed1395e125d4d1b3a555 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -32,7 +32,7 @@ #include /**************** Global variables ****************/ -char CLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n" +char CLIENT_VERSION[] = "Welcome to the TDengine Command Line Interface from %s, Client Version:%s\n" "Copyright (c) 2022 by TAOS Data, Inc. All rights reserved.\n\n"; char PROMPT_HEADER[] = "taos> "; char CONTINUE_PROMPT[] = " -> "; diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index fd24a61c7d55c8a91ac9631a7263ca44b81d1606..001ae7bbe0261b7159309fd633e25c9aba6e2158 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -194,7 +194,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc}; -char LINUXCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n" +char LINUXCLIENT_VERSION[] = "Welcome to the TDengine Command Line Interface from %s, Client Version:%s\n" "Copyright (c) 2022 by TAOS Data, Inc. All rights reserved.\n\n"; char g_password[SHELL_MAX_PASSWORD_LEN]; diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index 0133caf997f60a17748a536371479c11b354888d..b5567504edb47d99f4f2b69cf46d2c6d44900e8f 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -21,7 +21,7 @@ extern char configDir[]; -char WINCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n" +char WINCLIENT_VERSION[] = "Welcome to the TDengine Command Line Interface from %s, Client Version:%s\n" "Copyright (c) 2022 by TAOS Data, Inc. All rights reserved.\n\n"; void printVersion() { @@ -30,7 +30,7 @@ void printVersion() { void printHelp() { char indent[10] = " "; - printf("taos shell is used to test the TDengine database\n"); + printf("TDengine Command Line is used to test the TDengine database\n"); printf("%s%s\n", indent, "-h"); printf("%s%s%s\n", indent, indent, "TDengine server FQDN to connect. The default host is localhost.");