📄 defncopy.c
字号:
ret = asprintf(&type, "%s(%d)", ddl[i].type, *(int*)ddl[i].length); break; } } } if (colmap == sybase_colmap) is_null = *(int*)ddl[i].nullable == 1; else is_null = (0 == strcasecmp("1", ddl[i].nullable) || 0 == strcasecmp("yes", ddl[i].nullable)); /* {(|,} name type [NOT] NULL */ printf("\t%c %-*s %-15s %3s NULL\n", (i==0? '(' : ','), maxnamelen, ddl[i].name, (type? type : ddl[i].type), (is_null? "" : "NOT")); free(type); } printf("\t)\nGO\n\n"); /* print the CREATE INDEX statements */ rewind(create_index); while ((i = fgetc(create_index)) != EOF) { fputc(i, stdout); } fclose(create_index); return nrows;}int /* return count of SQL text rows */print_results(DBPROCESS *dbproc) { static const char empty_string[] = ""; struct METADATA *metadata = NULL; struct DATA { char *buffer; int status; } *data = NULL; RETCODE erc; int row_code; int c, ret; int iresultset; int nrows=0, ncols=0, ncomputeids; /* * Set up each result set with dbresults() */ for (iresultset=1; (erc = dbresults(dbproc)) != NO_MORE_RESULTS; iresultset++) { if (erc == FAIL) { fprintf(stderr, "%s:%d: dbresults(), result set %d failed\n", options.appname, __LINE__, iresultset); return -1; } if (SUCCEED != dbrows(dbproc)) { return 0; } /* Free prior allocations, if any. */ for (c=0; c < ncols; c++) { free(metadata[c].format_string); free(data[c].buffer); } free(metadata); metadata = NULL; free(data); data = NULL; ncols = 0; /* * Allocate memory for metadata and bound columns */ ncols = dbnumcols(dbproc); metadata = (struct METADATA*) calloc(ncols, sizeof(struct METADATA)); assert(metadata); data = (struct DATA*) calloc(ncols, sizeof(struct DATA)); assert(data); /* The hard-coded queries don't generate compute rows. */ ncomputeids = dbnumcompute(dbproc); assert(0 == ncomputeids); /* * For each column, get its name, type, and size. * Allocate a buffer to hold the data, and bind the buffer to the column. * "bind" here means to give db-lib the address of the buffer we want filled as each row is fetched. */ for (c=0; c < ncols; c++) { int width; /* Get and print the metadata. Optional: get only what you need. */ char *name = dbcolname(dbproc, c+1); metadata[c].name = (name)? name : (char*) empty_string; name = dbcolsource(dbproc, c+1); metadata[c].source = (name)? name : (char*) empty_string; metadata[c].type = dbcoltype(dbproc, c+1); metadata[c].size = dbcollen(dbproc, c+1); assert(metadata[c].size != -1); /* -1 means indicates an out-of-range request*/#if 0 fprintf(stderr, "%6d %30s %30s %15s %6d %6d \n", c+1, metadata[c].name, metadata[c].source, dbprtype(metadata[c].type), metadata[c].size, dbvarylen(dbproc, c+1));#endif /* * Build the column header format string, based on the column width. * This is just one solution to the question, "How wide should my columns be when I print them out?" */ width = get_printable_size(metadata[c].type, metadata[c].size); if (width < strlen(metadata[c].name)) width = strlen(metadata[c].name); ret = set_format_string(&metadata[c], (c+1 < ncols)? " " : "\n"); if (ret <= 0) { fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1); return -1; } /* * Bind the column to our variable. * We bind everything to strings, because we want db-lib to convert everything to strings for us. * If you're performing calculations on the data in your application, you'd bind the numeric data * to C integers and floats, etc. instead. * * It is not necessary to bind to every column returned by the query. * Data in unbound columns are simply never copied to the user's buffers and are thus * inaccesible to the application. */ data[c].buffer = calloc(1, metadata[c].size); assert(data[c].buffer); erc = dbbind(dbproc, c+1, STRINGBIND, -1, (BYTE *) data[c].buffer); if (erc == FAIL) { fprintf(stderr, "%s:%d: dbbind(), column %d failed\n", options.appname, __LINE__, c+1); return -1; } erc = dbnullbind(dbproc, c+1, &data[c].status); if (erc == FAIL) { fprintf(stderr, "%s:%d: dbnullbind(), column %d failed\n", options.appname, __LINE__, c+1); return -1; } } /* * Print the data to stdout. */ for (;(row_code = dbnextrow(dbproc)) != NO_MORE_ROWS; nrows++) { switch (row_code) { case REG_ROW: for (c=0; c < ncols; c++) { switch (data[c].status) { /* handle nulls */ case -1: /* is null */ fprintf(stderr, "defncopy: error: unexpected NULL row in SQL text\n"); break; case 0: /* OK */ default: /* >1 is datlen when buffer is too small */ fprintf(stdout, "%s", data[c].buffer); break; } } break; case BUF_FULL: default: fprintf(stderr, "defncopy: error: expected REG_ROW (%d), got %d instead\n", REG_ROW, row_code); assert(row_code == REG_ROW); break; } /* row_code */ } /* wend dbnextrow */ fprintf(stdout, "\n"); } /* wend dbresults */ return nrows;}static intget_printable_size(int type, int size) /* adapted from src/dblib/dblib.c */{ switch (type) { case SYBINTN: switch (size) { case 1: return 3; case 2: return 6; case 4: return 11; case 8: return 21; } case SYBINT1: return 3; case SYBINT2: return 6; case SYBINT4: return 11; case SYBINT8: return 21; case SYBVARCHAR: case SYBCHAR: return size; case SYBFLT8: return 11; /* FIX ME -- we do not track precision */ case SYBREAL: return 11; /* FIX ME -- we do not track precision */ case SYBMONEY: return 12; /* FIX ME */ case SYBMONEY4: return 12; /* FIX ME */ case SYBDATETIME: return 26; /* FIX ME */ case SYBDATETIME4: return 26; /* FIX ME */#if 0 /* seems not to be exported to sybdb.h */ case SYBBITN:#endif case SYBBIT: return 1; /* FIX ME -- not all types present */ default: return 0; }}/** * Build the column header format string, based on the column width. * This is just one solution to the question, "How wide should my columns be when I print them out?" */#define is_character_data(x) (x==SYBTEXT || x==SYBCHAR || x==SYBVARCHAR)static intset_format_string(struct METADATA * meta, const char separator[]){ int width, ret; const char *size_and_width; assert(meta); /* right justify numbers, left justify strings */ size_and_width = is_character_data(meta->type)? "%%-%d.%ds%s" : "%%%d.%ds%s"; width = get_printable_size(meta->type, meta->size); if (width < strlen(meta->name)) width = strlen(meta->name); ret = asprintf(&meta->format_string, size_and_width, width, width, separator); return ret;}static voidusage(const char invoked_as[]){ fprintf(stderr, "usage: %s \n" " [-U username] [-P password]\n" " [-S servername] [-D database]\n" " [-i input filename] [-o output filename]\n" " [owner.]object_name [[owner.]object_name...]\n" , invoked_as);/**defncopy Syntax ErrorUsage: defncopy [-v] [-X]-- [-a <display_charset>]-- [-I <interfaces_file>]-- [-J [<client_charset>]]-- [-K <keytab_file>] [-P <password>]-- [-R <remote_server_principal>] [-S [<server_name>]] [-U <user_name>]-- [-V <security_options>]-- [-Z <security_mechanism>]-- [-z <language>] { in <file_name> <database_name> | out <file_name> <database_name> [<owner>.]<object_name> [[<owner>.]<object_name>...] }**/ }static LOGINREC *get_login(int argc, char *argv[], OPTIONS *options){ LOGINREC *login; int ch; extern char *optarg; extern int optind; assert(options && argv); options->appname = tds_basename(argv[0]); login = dblogin(); if (!login) { fprintf(stderr, "%s: unable to allocate login structure\n", options->appname); exit(1); } DBSETLAPP(login, options->appname); if (-1 == gethostname(options->hostname, sizeof(options->hostname))) { perror("unable to get hostname"); } else { DBSETLHOST(login, options->hostname); } while ((ch = getopt(argc, argv, "U:P:S:d:D:i:o:v")) != -1) { switch (ch) { case 'U': DBSETLUSER(login, optarg); break; case 'P': DBSETLPWD(login, optarg); break; case 'S': options->servername = strdup(optarg); break; case 'd': case 'D': options->database = strdup(optarg); break; case 'i': options->input_filename = strdup(optarg); break; case 'o': options->output_filename = strdup(optarg); break; case 'v': printf("%s\n\n%s", software_version, "Copyright (C) 2004 James K. Lowden\n" "This program is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU General Public\n" "License as published by the Free Software Foundation\n"); exit(1); break; case '?': default: usage(options->appname); exit(1); } } if (!options->servername) { usage(options->appname); exit(1); } options->optind = optind; return login;}static interr_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr){ if (dberr) { fprintf(stderr, "%s: Msg %d, Level %d\n", options.appname, dberr, severity); fprintf(stderr, "%s\n\n", dberrstr); } else { fprintf(stderr, "%s: DB-LIBRARY error:\n\t", options.appname); fprintf(stderr, "%s\n", dberrstr); } return INT_CANCEL;}static intmsg_handler(DBPROCESS * dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line){ char *dbname, *endquote; switch (msgno) { case 5701: /* Print "USE dbname" for "Changed database context to 'dbname'" */ dbname = strchr(msgtext, '\''); if (!dbname) break; endquote = strchr(++dbname, '\''); if (!endquote) break; *endquote = '\0'; fprintf(stdout, "USE %s\nGO\n\n", dbname); return 0; case 0: /* Ignore print messages */ case 5703: /* Ignore "Changed language setting to <language>". */ return 0; default: break; }#if 0 printf("Msg %ld, Severity %d, State %d\n", (long) msgno, severity, msgstate); if (strlen(srvname) > 0) printf("Server '%s', ", srvname); if (strlen(procname) > 0) printf("Procedure '%s', ", procname); if (line > 0) printf("Line %d", line);#endif printf("\t/* %s */\n", msgtext); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -