static stmt_code(stream, node, brk, cont, ret) { /* Handle the null expression. */ if ( !node ) return; auto op = node[0]; /* For debugging purposes, put a blank line between each statement. */ fputs("\n", stream); if ( op == 'dcls' ) declaration( stream, node ); else if ( op == 'brea' ) branch( stream, brk ); else if ( op == 'cont' ) branch( stream, cont ); else if ( op == 'retu' ) return_stmt( stream, node, ret ); else if ( op == 'goto' ) goto_stmt( stream, node ); else if ( op == 'if' ) if_stmt( stream, node, brk, cont, ret ); else if ( op == 'whil' ) while_stmt( stream, node, brk, cont, ret ); else if ( op == 'for' ) for_stmt( stream, node, brk, cont, ret ); else if ( op == 'do' ) do_stmt( stream, node, brk, cont, ret ); else if ( op == 'swit' ) switch_stmt( stream, node, brk, cont, ret ); else if ( op == 'case' || op == 'defa' ) case_stmt( stream, node, brk, cont, ret ); else if ( op == ':' ) label_stmt( stream, node, brk, cont, ret ); else if ( op == '{}' ) do_block( stream, node, brk, cont, ret ); else expr_code( stream, node, 0 ); }
int main(int argc, const char** argv) { ndb_init(); const char* usage = "Usage: ndbsql [-h] [-d dsn] [-f file] [stmt]\n-h help\n-d <database name or connect string>\n-f <file name> batch mode\nstmt single SQL statement\n"; const char* dsn = "TEST_DB"; bool helpFlg = false, batchMode = false; const char* fileName = 0; FILE* inputFile = stdin; const char* singleStmt = 0; s_readBuf = (char*)malloc(s_bufSize); while (++argv, --argc > 0) { const char* arg = argv[0]; if (arg[0] != '-') break; if (strcmp(arg, "-d") == 0) { if (++argv, --argc > 0) { dsn = argv[0]; continue; } } if (strcmp(arg, "-h") == 0) { helpFlg = true; continue; } if (strcmp(arg, "-f") == 0) { if (++argv, --argc > 0) { fileName = argv[0]; continue; } } ndbout << usage; return 1; } if (helpFlg) { ndbout << usage << "\n"; print_help(); return 0; } if (fileName != 0) { if (argc > 0) { ndbout << usage; return 1; } if ((inputFile = fopen(fileName, "r")) == 0) { ndbout << "Could not read file " << fileName << ": " << strerror(errno) << endl; return 1; } batchMode = true; } if (argc > 0) { singleStmt = argv[0]; batchMode = true; } if (! batchMode) ndbout << "NDB Cluster NDB SQL -- A simple SQL Command-line Interface\n\n"; Con con(dsn); if (do_connect(con) < 0) return 1; if (! batchMode) ndbout << "Terminate SQL statements with a semi-colon ';'\n"; char* line = 0; char* line2 = 0; char* line3 = 0; unsigned lineno = 0; bool has_semi; bool exit_on_error = false; int exit_code = 0; while (1) { free(line); line = 0; lineno = 0; more_lines: free(line2); free(line3); line2 = line3 = 0; lineno++; has_semi = false; char prompt[20]; if (lineno == 1) strcpy(prompt, "SQL> "); else sprintf(prompt, "%4d ", lineno); if (singleStmt != 0) { line = strdup(singleStmt); int n = strlen(line); while (n > 0 && isspace(line[n - 1])) { line[--n] = 0; } if (n > 0 && line[n - 1] == ';') line[n - 1] = 0; has_semi = true; // regardless } else { const char *line1 = readline_gets(prompt, batchMode, inputFile); if (line1 != 0) { if (line == 0) line = strdup(line1); else { line = (char*)realloc(line, strlen(line) + 1 + strlen(line1) + 1); strcat(line, "\n"); strcat(line, line1); } if (batchMode) ndbout << prompt << line1 << endl; } else { if (! batchMode) ndbout << endl; if (line != 0) ndbout << "Ignored unterminated SQL statement" << endl; break; } } line2 = (char*)malloc(strlen(line) + 1); { char* p = line2; char* q = line; bool str = false; while (*q != 0) { if (*q == '\'') { str = !str; *p++ = *q++; } else if (!str && *q == '-' && *(q + 1) == '-') { while (*q != 0 && *q != '\n') q++; } else *p++ = *q++; } *p = 0; int n = strlen(line2); while (n > 0 && isspace(line2[n - 1])) line2[--n] = 0; if (n > 0 && line2[n - 1] == ';') { line2[--n] = 0; has_semi = true; } } line3 = strdup(line2); char* tok[10]; int ntok = 0; tok[ntok] = strtok(line3, " "); while (tok[ntok] != 0) { ntok++; if (ntok == 10) break; tok[ntok] = strtok(0, " "); } if (ntok == 0) continue; if (!strcasecmp(tok[0], "help") || !strcmp(tok[0], "?")) { if (ntok != 2) print_help(); else if (!strcasecmp(tok[1], "create")) print_help_create(); else if (!strcasecmp(tok[1], "insert")) print_help_insert(); else if (strcasecmp(tok[1], "select")) print_help_select(); else if (!strcasecmp(tok[1], "delete")) print_help_update(); else if (!strcasecmp(tok[1], "update")) print_help_update(); else if (!strcasecmp(tok[1], "virtual")) print_help_virtual(); else print_help(); continue; } if (!strcasecmp(tok[0], "list")) { if (ntok == 2 && !strcasecmp(tok[1], "tables")) { free(line2); line2 = strdup("SELECT TABLE_NAME FROM ODBC$TABLES"); has_semi = true; } else { ndbout << "Invalid list option - try help" << endl; continue; } } if (ntok == 1 && !strcasecmp(tok[0], "quit")) break; if (ntok == 1 && !strcasecmp(tok[0], "exit")) break; if (ntok == 1 && !strcasecmp(tok[0], "bye")) break; if (!strcasecmp(tok[0], "set")) { if (ntok == 1) { char* p; p = getenv("NDB_ODBC_TRACE"); ndbout << "Trace level is " << (p ? atoi(p) : 0) << endl; int ret = get_autocommit(con); if (ret != -1) ndbout << "Autocommit is " << (ret == SQL_AUTOCOMMIT_ON ? "on" : "off") << endl; } else if (ntok == 3 && !strcasecmp(tok[1], "trace")) { static char env[40]; int n = tok[2] ? atoi(tok[2]) : 0; sprintf(env, "NDB_ODBC_TRACE=%d", n); putenv(env); ndbout << "Trace level set to " << n << endl; } else if (ntok == 3 && !strcasecmp(tok[1], "autocommit")) { if (tok[2] && !strcasecmp(tok[2], "on")) { int ret = set_autocommit(con, SQL_AUTOCOMMIT_ON); if (ret != -1) ndbout << "Autocommit set to ON" << endl; } else if (tok[2] && !strcasecmp(tok[2], "off")) { int ret = set_autocommit(con, SQL_AUTOCOMMIT_OFF); if (ret != -1) ndbout << "Autocommit set to OFF - transaction may time out" << endl; } else { ndbout << "Invalid autocommit option - try help" << endl; } } else { ndbout << "Invalid set command - try help" << endl; } continue; } if (ntok >= 2 && !strcasecmp(tok[0], "whenever") && !strcasecmp(tok[1], "sqlerror")) { if (ntok == 3 && !strcasecmp(tok[2], "exit")) exit_on_error = true; else if (ntok == 3 && !strcasecmp(tok[2], "continue")) exit_on_error = false; else { ndbout << "Invalid whenever clause - try help" << endl; } continue; } if (!strcasecmp(tok[0], "commit")) { if (ntok == 1) { if (do_commit(con) != -1) ndbout << "Commit done" << endl; else { exit_code = 1; if (exit_on_error) { ndbout << "Exit on error" << endl; break; } } } else { ndbout << "Invalid commit command - try help" << endl; } continue; } if (!strcasecmp(tok[0], "rollback")) { if (ntok == 1) { if (do_rollback(con) != -1) ndbout << "Rollback done" << endl; else { exit_code = 1; if (exit_on_error) { ndbout << "Exit on error" << endl; break; } } } else { ndbout << "Invalid commit command - try help" << endl; } continue; } if (! has_semi) goto more_lines; if (do_stmt(con, line2) != 0) { exit_code = 1; if (exit_on_error) { ndbout << "Exit on error" << endl; break; } } if (singleStmt) break; } do_disconnect(con); return exit_code; }