From 9c1f236543c394ed6c32e938dbdb94b5659e2255 Mon Sep 17 00:00:00 2001 From: frozehu <166183471+frozehu@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:55:37 -0400 Subject: [PATCH] feat: support multiline SQL input in obclient #<573> --- src/obclient/client.cpp | 73 +++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/src/obclient/client.cpp b/src/obclient/client.cpp index 45fa3e7c2..f65f43604 100644 --- a/src/obclient/client.cpp +++ b/src/obclient/client.cpp @@ -89,6 +89,14 @@ int init_tcp_sock(const char *server_host, int server_port) } return sockfd; } +static void replace_all(std::string &s) { + for (auto &ch : s) { + if (ch == '\n' || ch == '\r') { + ch = ' '; + } + } +} + const char *startup_tips = R"( Welcome to the OceanBase database implementation course. @@ -135,8 +143,14 @@ int main(int argc, char *argv[]) std::string input_command = ""; MiniobLineReader::instance().init(LINE_HISTORY_FILE); + const char *const_prompt = " -> "; + + std::string sql_buffer; + + while (true) { - input_command = MiniobLineReader::instance().my_readline(prompt_str); + const char *prompt = sql_buffer.empty() ? prompt_str : const_prompt; + input_command = MiniobLineReader::instance().my_readline(prompt); if (input_command.empty() || common::is_blank(input_command.c_str())) { continue; @@ -145,38 +159,47 @@ int main(int argc, char *argv[]) if (MiniobLineReader::instance().is_exit_command(input_command)) { break; } + + sql_buffer += input_command + ' '; - if ((send_bytes = write(sockfd, input_command.c_str(), input_command.length() + 1)) == -1) { // TODO writen - fprintf(stderr, "send error: %d:%s \n", errno, strerror(errno)); - exit(1); - } - - memset(send_buf, 0, sizeof(send_buf)); + std::string trimmed = sql_buffer; + replace_all(trimmed); - int len = 0; - while ((len = recv(sockfd, send_buf, MAX_MEM_BUFFER_SIZE, 0)) > 0) { - bool msg_end = false; - for (int i = 0; i < len; i++) { - if (0 == send_buf[i]) { - msg_end = true; + if (!trimmed.empty() && trimmed.find(';') != std::string::npos) { + if ((send_bytes = write(sockfd, trimmed.c_str(), trimmed.length() + 1)) == -1) { // TODO writen + fprintf(stderr, "send error: %d:%s \n", errno, strerror(errno)); + exit(1); + } + sql_buffer.clear(); + + memset(send_buf, 0, sizeof(send_buf)); + + int len = 0; + while ((len = recv(sockfd, send_buf, MAX_MEM_BUFFER_SIZE, 0)) > 0) { + bool msg_end = false; + for (int i = 0; i < len; i++) { + if (0 == send_buf[i]) { + msg_end = true; + break; + } + printf("%c", send_buf[i]); + } + if (msg_end) { break; } - printf("%c", send_buf[i]); + memset(send_buf, 0, MAX_MEM_BUFFER_SIZE); } - if (msg_end) { + + if (len < 0) { + fprintf(stderr, "Connection was broken: %s\n", strerror(errno)); + break; + } + if (0 == len) { + printf("Connection has been closed\n"); break; } - memset(send_buf, 0, MAX_MEM_BUFFER_SIZE); - } - - if (len < 0) { - fprintf(stderr, "Connection was broken: %s\n", strerror(errno)); - break; - } - if (0 == len) { - printf("Connection has been closed\n"); - break; } + } close(sockfd);