📄 tsql.c
字号:
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns * Copyright (C) 2006, 2007 Frediano Ziglio * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#if HAVE_CONFIG_H#include <config.h>#endif /* HAVE_CONFIG_H */#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#include <stdio.h>#include <assert.h>#include <ctype.h>#if HAVE_FORK#include <sys/wait.h>#endif#include <signal.h>#ifdef HAVE_READLINE#include <readline/readline.h>#include <readline/history.h>#endif /* HAVE_READLINE */#if HAVE_ERRNO_H#include <errno.h>#endif /* HAVE_ERRNO_H */#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#if HAVE_STRING_H#include <string.h>#endif /* HAVE_STRING_H */#if HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H *//* HP-UX require some constants defined by limits.h */#ifdef HAVE_LIMITS_H#include <limits.h>#endif /* HAVE_LIMITS_H */#if defined(__hpux__) && !defined(_POSIX_PATH_MAX)#define _POSIX_PATH_MAX 255#endif#ifdef HAVE_LOCALE_H#include <locale.h>#endif /* HAVE_LOCALE_H */#ifdef HAVE_LANGINFO_H#include <langinfo.h>#endif /* HAVE_LANGINFO_H */#include "tds.h"#include "tdsiconv.h"#include "tdsstring.h"#include "tdsconvert.h"#include "replacements.h"TDS_RCSID(var, "$Id: tsql.c,v 1.112.2.1 2008/01/11 12:46:52 freddy77 Exp $");enum{ OPT_VERSION = 0x01, OPT_TIMER = 0x02, OPT_NOFOOTER = 0x04, OPT_NOHEADER = 0x08, OPT_QUIET = 0x10};static int istty = 0;static int global_opt_flags = 0;#define QUIET (global_opt_flags & OPT_QUIET)static char *opt_col_term = "\t";static char *opt_row_term = "\n";static char *opt_default_db = NULL;static int do_query(TDSSOCKET * tds, char *buf, int opt_flags);static void tsql_print_usage(const char *progname);static int get_opt_flags(char *s, int *opt_flags);static void populate_login(TDSLOGIN * login, int argc, char **argv);static int tsql_handle_message(const TDSCONTEXT * context, TDSSOCKET * tds, TDSMESSAGE * msg);static void slurp_input_file(char *fname, char **mybuf, int *bufsz, size_t *buflen, int *line);static char *tsql_readline(char *prompt){ size_t sz, pos; char *line, *p;#ifdef HAVE_READLINE if (istty) return readline(prompt);#endif sz = 1024; pos = 0; line = (char*) malloc(sz); if (!line) return NULL; if (prompt && prompt[0]) printf("%s", prompt); for (;;) { /* read a piece */ if (fgets(line + pos, sz - pos, stdin) == NULL) { if (pos) return line; break; } /* got end-of-line ? */ p = strchr(line + pos, '\n'); if (p) { *p = 0; return line; } /* allocate space if needed */ pos += strlen(line + pos); if (pos + 1024 >= sz) { sz += 1024; p = (char*) realloc(line, sz); if (!p) break; line = p; } } free(line); return NULL;}static voidtsql_add_history(const char *s){#ifdef HAVE_READLINE if (istty) add_history(s);#endif}static intdo_query(TDSSOCKET * tds, char *buf, int opt_flags){ int rows = 0; int rc, i; TDSCOLUMN *col; int ctype; CONV_RESULT dres; unsigned char *src; TDS_INT srclen; TDS_INT resulttype; struct timeval start, stop; int print_rows = 1; char message[128]; rc = tds_submit_query(tds, buf); if (rc != TDS_SUCCEED) { fprintf(stderr, "tds_submit_query() failed\n"); return 1; } while ((rc = tds_process_tokens(tds, &resulttype, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCEED) { if (opt_flags & OPT_TIMER) { gettimeofday(&start, NULL); print_rows = 0; } switch (resulttype) { case TDS_ROWFMT_RESULT: if ((!(opt_flags & OPT_NOHEADER)) && tds->current_results) { for (i = 0; i < tds->current_results->num_cols; i++) { if (i) fputs(opt_col_term, stdout); fputs(tds->current_results->columns[i]->column_name, stdout); } fputs(opt_row_term, stdout); } break; case TDS_COMPUTE_RESULT: case TDS_ROW_RESULT: rows = 0; while ((rc = tds_process_tokens(tds, &resulttype, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)) == TDS_SUCCEED) { if (resulttype != TDS_ROW_RESULT && resulttype != TDS_COMPUTE_RESULT) break; rows++; if (!tds->current_results) continue; for (i = 0; i < tds->current_results->num_cols; i++) { col = tds->current_results->columns[i]; if (col->column_cur_size < 0) { if (print_rows) { if (i) fputs(opt_col_term, stdout); fputs("NULL", stdout); } continue; } ctype = tds_get_conversion_type(col->column_type, col->column_size); src = col->column_data; if (is_blob_type(col->column_type)) src = (unsigned char *) ((TDSBLOB *) src)->textvalue; srclen = col->column_cur_size; if (tds_convert(tds->tds_ctx, ctype, (TDS_CHAR *) src, srclen, SYBVARCHAR, &dres) < 0) continue; if (print_rows) { if (i) fputs(opt_col_term, stdout); fputs(dres.c, stdout); } free(dres.c); } if (print_rows) fputs(opt_row_term, stdout); } if (!QUIET) fprintf(stdout, "(%d row%s affected)\n", rows, rows == 1 ? "" : "s"); break; case TDS_STATUS_RESULT: if (!QUIET) printf("(return status = %d)\n", tds->ret_status); break; default: break; } if (opt_flags & OPT_VERSION) { char version[64]; int line = 0; line = tds_version(tds, version); if (line) { TDSMESSAGE msg; memset(&msg, 0, sizeof(TDSMESSAGE)); msg.server = "tsql"; sprintf(message, "using TDS version %s", version); msg.message = message; tsql_handle_message(tds->tds_ctx, tds, &msg); } } if (opt_flags & OPT_TIMER) { TDSMESSAGE msg; gettimeofday(&stop, NULL); sprintf(message, "Total time for processing %d rows: %ld msecs\n", rows, (long) ((stop.tv_sec - start.tv_sec) * 1000) + ((stop.tv_usec - start.tv_usec) / 1000)); memset(&msg, 0, sizeof(TDSMESSAGE)); msg.server = "tsql"; msg.message = message; tsql_handle_message(tds->tds_ctx, tds, &msg); } } return 0;}static voidtsql_print_usage(const char *progname){ fprintf(stderr, "Usage:\t%s [-S <server> | -H <hostname> -p <port>] -U <username> [-P <password>] [-I <config file>] [-o <options>] [-t delim] [-r delim] [-D database]\n" "\t%s -C\n" "Options:\n" "\tf\tDo not print footer\n" "\th\tDo not print header\n" "\tt\tPrint time informations\n" "\tv\tPrint TDS version\n" "\tq\tQuiet\n\n" "\tDelimiters can be multi-char strings appropriately escaped for your shell.\n" "\tDefault column delimitor is <tab>; default row delimiter is <newline>\n", progname, progname);}/* * The 'GO' command may be followed by options that apply to the batch. * If they don't appear to be right, assume the letters "go" are part of the * SQL, not a batch separator. */static intget_opt_flags(char *s, int *opt_flags){ char **argv; int argc; int opt; /* make sure we have enough elements */ assert(s && opt_flags); argv = (char **) calloc(strlen(s) + 2, sizeof(char*)); if (!argv) return 0; /* parse the command line and assign to argv */ for (argc=0; (argv[argc] = strtok(s, " ")) != NULL; argc++) s = NULL; *opt_flags = 0; optind = 0; /* reset getopt */ opterr = 0; /* suppress error messages */ while ((opt = getopt(argc, argv, "fhqtv")) != -1) { switch (opt) { case 'f': *opt_flags |= OPT_NOFOOTER; break; case 'h': *opt_flags |= OPT_NOHEADER; break; case 't': *opt_flags |= OPT_TIMER; break; case 'v': *opt_flags |= OPT_VERSION; break; case 'q': *opt_flags |= OPT_QUIET; break; default: fprintf(stderr, "Warning: invalid option '%s' found: \"go\" treated as simple SQL\n", argv[optind-1]); free(argv); return 0; } } free(argv); return 1;}static voidpopulate_login(TDSLOGIN * login, int argc, char **argv){ const TDS_COMPILETIME_SETTINGS *settings; char *hostname = NULL; char *servername = NULL; char *username = NULL; char *password = NULL; char *confile = NULL; int port = 0; int opt; const char *locale = NULL; const char *charset = NULL; char *opt_flags_str = NULL; setlocale(LC_ALL, ""); locale = setlocale(LC_ALL, NULL);#if HAVE_LOCALE_CHARSET charset = locale_charset();#endif#if HAVE_NL_LANGINFO && defined(CODESET) if (!charset) charset = nl_langinfo(CODESET);#endif while ((opt = getopt(argc, argv, "H:S:I:P:U:p:Co:t:r:D:")) != -1) { switch (opt) { case 't': opt_col_term = strdup(optarg); break; case 'r': opt_row_term = strdup(optarg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -