⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bsqldb.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
				/* 				 * Jump through hoops to determine a useful name for the computed column 				 * If the query says "compute count(c) by a,b", we get a "by list" indicating a & b.  				 */				bylist = dbbylist(dbproc, c+1, &nby);				bynames = strdup("by (");				for (iby=0; iby < nby; iby++) {					char *s = NULL; 					int ret = asprintf(&s, "%s%s%s", bynames, dbcolname(dbproc, bylist[iby]), 										(iby+1 < nby)? ", " : ")");					if (ret < 0) {						fprintf(options.verbose, "Insufficient room to create name for column %d:\n", 1+c);						break;					}					free(bynames);					bynames = s;				}								if( altcolid == -1 ) {					colname = "*";				} else {					assert(0 < altcolid && altcolid <= dbnumcols(dbproc));					colname = metadata[--altcolid].name;				}				asprintf(&metacompute[i]->meta[c].name, "%s(%s)", dbprtype(dbaltop(dbproc, i+1, c+1)), colname);				assert(metacompute[i]->meta[c].name);									metacompute[i]->meta[c].width = get_printable_size(metacompute[i]->meta[c].type, 										   metacompute[i]->meta[c].size);				if (metacompute[i]->meta[c].width < strlen(metacompute[i]->meta[c].name))					metacompute[i]->meta[c].width = strlen(metacompute[i]->meta[c].name);				ret = set_format_string(meta, (c+1 < metacompute[i]->numalts)? options.colsep : "\n");				if (ret <= 0) {					free(bynames);					fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1);					return;				}								fprintf(options.verbose, "\tcolumn %d is %s, type %s, size %d %s\n", 					c+1, metacompute[i]->meta[c].name, dbprtype(metacompute[i]->meta[c].type),					metacompute[i]->meta[c].size, (nby > 0)? bynames : "");				free(bynames);					/* allocate buffer */				assert(metacompute[i]->data);				metacompute[i]->data[c].buffer = calloc(1, metacompute[i]->meta[c].width);				assert(metacompute[i]->data[c].buffer);								/* bind */				erc = dbaltbind(dbproc, i+1, c+1, bindtype, -1, (BYTE*) metacompute[i]->data[c].buffer);				if (erc == FAIL) {					fprintf(stderr, "%s:%d: dbaltbind(), column %d failed\n", options.appname, __LINE__, c+1);					return;				}			}		}				fprintf(options.verbose, "\n");		fprintf(options.verbose, "Data\n");		if (!options.fquiet) {			/* Print the column headers to stderr to keep them separate from the data.  */			for (c=0; c < ncols; c++) {				fprintf(options.headers, metadata[c].format_string, metadata[c].name);			}			/* Underline the column headers.  */			for (c=0; c < ncols; c++) {				fprintf(options.headers, metadata[c].format_string, dashes);			}		}		/* 		 * Print the data to stdout.  		 */		while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {			switch (row_code) {			case REG_ROW:				for (c=0; c < ncols; c++) {					switch (data[c].status) { /* handle nulls */					case -1: /* is null */						/* TODO: FreeTDS 0.62 does not support dbsetnull() */						fprintf(stdout, metadata[c].format_string, "NULL");						break;					case 0:					/* case >1 is datlen when buffer is too small */					default:						fprintf(stdout, metadata[c].format_string, data[c].buffer);						break;					}				}				break;							case BUF_FULL:				assert(row_code != BUF_FULL);				break;							case FAIL:				fprintf(stderr, "bsqldb: fatal error: dbnextrow returned FAIL\n");				assert(row_code != FAIL);				exit(EXIT_FAILURE);				break;							default: /* computeid */				fprintf(options.verbose, "Data for computeid %d\n", row_code);				for (c=0; c < metacompute[row_code-1]->numalts; c++) {					char fmt[256] = "%-";					struct METADATA *meta = &metacompute[row_code-1]->meta[c];										/* left justify the names */					strcat(fmt, &meta->format_string[1]);					fprintf(options.headers, fmt, meta->name);				}				/* Underline the column headers.  */				for (c=0; c < metacompute[row_code-1]->numalts; c++) {					fprintf(options.headers, metacompute[row_code-1]->meta[c].format_string, dashes);				}									for (c=0; c < metacompute[row_code-1]->numalts; c++) {					struct METADATA *meta = &metacompute[row_code-1]->meta[c];					struct     DATA *data = &metacompute[row_code-1]->data[c];										switch (data->status) { /* handle nulls */					case -1: /* is null */						/* TODO: FreeTDS 0.62 does not support dbsetnull() */						fprintf(stdout, meta->format_string, "NULL");						break;					case 0:					/* case >1 is datlen when buffer is too small */					default:						fprintf(stdout, meta->format_string, data->buffer);						break;					}				}			}		}		/* Check return status */		if (!options.fquiet) {			fprintf(options.verbose, "Retrieving return status... ");			if (dbhasretstat(dbproc) == TRUE) {				fprintf(stderr, "Procedure returned %d\n", dbretstatus(dbproc));			} else {				fprintf(options.verbose, "none\n");			}		}				/* 		 * Get row count, if available.   		 */		if (!options.fquiet) {			if (DBCOUNT(dbproc) > -1)				fprintf(stderr, "%d rows affected\n", DBCOUNT(dbproc));			else 				fprintf(stderr, "@@rowcount not available\n");		}					/* 		 * Check return parameter values 		 */		fprintf(options.verbose, "Retrieving output parameters... ");		if (dbnumrets(dbproc) > 0) {			for (i = 1; i <= dbnumrets(dbproc); i++) {				char parameter_string[1024];								return_status.name = dbretname(dbproc, i);				fprintf(stderr, "ret name %d is %s\n", i, return_status.name);								return_status.type = dbrettype(dbproc, i);				fprintf(options.verbose, "\n\tret type %d is %d", i, return_status.type);								return_status.size = dbretlen(dbproc, i);				fprintf(options.verbose, "\n\tret len %d is %d\n", i, return_status.size);								dbconvert(dbproc, return_status.type, dbretdata(dbproc, i), return_status.size, 					  SYBVARCHAR, (BYTE *) parameter_string, -1);				fprintf(stderr, "ret data %d is %s\n", i, parameter_string);			}		} else {			fprintf(options.verbose, "none\n");		}	} /* wend dbresults */	fprintf(options.verbose, "%s:%d: dbresults() returned NO_MORE_RESULTS (%d):\n", options.appname, __LINE__, erc);}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);	if(0 == strcmp(options.colsep, default_colsep)) { 		/* 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);	} else {		/* For anything except the default two-space separator, don't justify the strings. */		ret = asprintf(&meta->format_string, "%%s%s", 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] [-e error filename]\n"			, invoked_as);}static void unescape(char arg[]){	char *p = arg;	char escaped = '1'; /* any digit will do for an initial value */	while ((p = strchr(p, '\\')) != NULL) {			switch (p[1]) {		case '0':			/* FIXME we use strlen() of field/row terminators, which obviously won't work here */			fprintf(stderr, "bsqldb, line %d: NULL terminators ('\\0') not yet supported.\n", __LINE__);			escaped = '\0';			break;		case 't':			escaped = '\t';			break;		case 'r':			escaped = '\r';			break;		case 'n':			escaped = '\n';			break;		case '\\':			escaped = '\\';			break;		default:			break;		}					/* Overwrite the backslash with the intended character, and shift everything down one */		if (!isdigit((unsigned char) escaped)) {			*p++ = escaped;			memmove(p, p+1, 1 + strlen(p+1));			escaped = '1';		}	}}LOGINREC *get_login(int argc, char *argv[], OPTIONS *options){	LOGINREC *login;	int ch;	extern char *optarg;	assert(options && argv);		options->appname = tds_basename(argv[0]);	options->colsep = default_colsep; /* may be overridden by -t */		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:dD:i:o:e:t:hqv")) != -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 'e':			options->error_filename = strdup(optarg);			break;		case 't':			unescape(optarg);			options->colsep = strdup(optarg);			break;		case 'h':			options->headers = stdout;			break;		case 'q':			options->fquiet = 1;			break;		case 'v':			options->fverbose = 1;			break;		case '?':		default:			usage(options->appname);			exit(1);		}	}		if (!options->servername) {		usage(options->appname);		exit(1);	}		return login;}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;}intmsg_handler(DBPROCESS * dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line){	enum {changed_database = 5701, changed_language = 5703 };		if (msgno == changed_database || msgno == changed_language) 		return 0;	if (msgno > 0) {		fprintf(stderr, "Msg %ld, Level %d, State %d\n", (long) msgno, severity, msgstate);		if (strlen(srvname) > 0)			fprintf(stderr, "Server '%s', ", srvname);		if (strlen(procname) > 0)			fprintf(stderr, "Procedure '%s', ", procname);		if (line > 0)			fprintf(stderr, "Line %d", line);		fprintf(stderr, "\n\t");	}	fprintf(stderr, "%s\n", msgtext);		if (severity > 10) {		fprintf(stderr, "%s: error: severity %d >

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -