📄 attributes.c
字号:
#include "common.h"#include <ctype.h>/* * SQLSetStmtAttr */static char software_version[] = "$Id: attributes.c,v 1.4 2007/12/31 10:06:50 freddy77 Exp $";static void *no_unused_var_warn[] = { software_version, no_unused_var_warn };static int g_result = 0;static unsigned int line_num;static voidfatal(const char *msg, ...){ va_list ap; va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap); exit(1);}static intget_int(const char *s){ char *end; long l; if (!s) fatal("Line %u: NULL int\n", line_num); l = strtol(s, &end, 0); if (end[0]) fatal("Line %u: Invalid int\n", line_num); return (int) l;}struct lookup_int{ const char *name; int value;};static intlookup(const char *name, const struct lookup_int *table){ if (!table) return get_int(name); for (; table->name; ++table) if (strcmp(table->name, name) == 0) return table->value; return get_int(name);}static const char *unlookup(int value, const struct lookup_int *table){ if (!table) return "??"; for (; table->name; ++table) if (table->value == value) return table->name; return "??";}static struct lookup_int concurrency[] = {#define TYPE(s) { #s, s } TYPE(SQL_CONCUR_READ_ONLY), TYPE(SQL_CONCUR_LOCK), TYPE(SQL_CONCUR_ROWVER), TYPE(SQL_CONCUR_VALUES),#undef TYPE { NULL, 0 }};static struct lookup_int scrollable[] = {#define TYPE(s) { #s, s } TYPE(SQL_NONSCROLLABLE), TYPE(SQL_SCROLLABLE),#undef TYPE { NULL, 0 }};static struct lookup_int sensitivity[] = {#define TYPE(s) { #s, s } TYPE(SQL_UNSPECIFIED), TYPE(SQL_INSENSITIVE), TYPE(SQL_SENSITIVE),#undef TYPE { NULL, 0 }};static struct lookup_int cursor_type[] = {#define TYPE(s) { #s, s } TYPE(SQL_CURSOR_FORWARD_ONLY), TYPE(SQL_CURSOR_STATIC), TYPE(SQL_CURSOR_KEYSET_DRIVEN), TYPE(SQL_CURSOR_DYNAMIC),#undef TYPE { NULL, 0 }};static struct lookup_int noscan[] = {#define TYPE(s) { #s, s } TYPE(SQL_NOSCAN_OFF), TYPE(SQL_NOSCAN_ON),#undef TYPE { NULL, 0 }};static struct lookup_int retrieve_data[] = {#define TYPE(s) { #s, s } TYPE(SQL_RD_ON), TYPE(SQL_RD_OFF),#undef TYPE { NULL, 0 }};static struct lookup_int simulate_cursor[] = {#define TYPE(s) { #s, s } TYPE(SQL_SC_NON_UNIQUE), TYPE(SQL_SC_TRY_UNIQUE), TYPE(SQL_SC_UNIQUE),#undef TYPE { NULL, 0 }};static struct lookup_int use_bookmarks[] = {#define TYPE(s) { #s, s } TYPE(SQL_UB_OFF), TYPE(SQL_UB_VARIABLE), TYPE(SQL_UB_FIXED),#undef TYPE { NULL, 0 }};typedef enum{ type_INTEGER, type_UINTEGER, type_SMALLINT, type_LEN, type_CHARP, type_DESC, type_VOIDP} test_type_t;struct attribute{ const char *name; int value; test_type_t type; const struct lookup_int *lookup;};static const struct attribute attributes[] = {#define ATTR(s,t) { #s, s, type_##t, NULL }#define ATTR2(s,t,l) { #s, s, type_##t, l } ATTR(SQL_ATTR_APP_PARAM_DESC, DESC), ATTR(SQL_ATTR_APP_ROW_DESC, DESC), ATTR(SQL_ATTR_ASYNC_ENABLE, UINTEGER), ATTR2(SQL_ATTR_CONCURRENCY, UINTEGER, concurrency), ATTR2(SQL_ATTR_CURSOR_SCROLLABLE, UINTEGER, scrollable), ATTR2(SQL_ATTR_CURSOR_SENSITIVITY, UINTEGER, sensitivity), ATTR2(SQL_ATTR_CURSOR_TYPE, UINTEGER, cursor_type), ATTR(SQL_ATTR_ENABLE_AUTO_IPD, UINTEGER), ATTR(SQL_ATTR_FETCH_BOOKMARK_PTR, VOIDP), ATTR(SQL_ATTR_IMP_PARAM_DESC, DESC), ATTR(SQL_ATTR_IMP_ROW_DESC, DESC), ATTR(SQL_ATTR_KEYSET_SIZE, UINTEGER), ATTR(SQL_ATTR_MAX_LENGTH, UINTEGER), ATTR(SQL_ATTR_MAX_ROWS, UINTEGER), ATTR(SQL_ATTR_METADATA_ID, UINTEGER), ATTR2(SQL_ATTR_NOSCAN, UINTEGER, noscan), ATTR(SQL_ATTR_PARAM_BIND_OFFSET_PTR, VOIDP), ATTR(SQL_ATTR_PARAM_BIND_OFFSET_PTR, VOIDP), ATTR(SQL_ATTR_PARAM_BIND_TYPE, UINTEGER), ATTR(SQL_ATTR_PARAM_OPERATION_PTR, VOIDP), ATTR(SQL_ATTR_PARAM_STATUS_PTR, VOIDP), ATTR(SQL_ATTR_PARAMS_PROCESSED_PTR, VOIDP), ATTR(SQL_ATTR_PARAMSET_SIZE, UINTEGER), ATTR(SQL_ATTR_QUERY_TIMEOUT, UINTEGER), ATTR2(SQL_ATTR_RETRIEVE_DATA, UINTEGER, retrieve_data), ATTR(SQL_ATTR_ROW_ARRAY_SIZE, UINTEGER), ATTR(SQL_ATTR_ROW_BIND_OFFSET_PTR, VOIDP), ATTR(SQL_ATTR_ROW_BIND_TYPE, UINTEGER), ATTR(SQL_ATTR_ROW_NUMBER, UINTEGER), ATTR(SQL_ATTR_ROW_OPERATION_PTR, VOIDP), ATTR(SQL_ATTR_ROW_STATUS_PTR, VOIDP), ATTR(SQL_ATTR_ROWS_FETCHED_PTR, VOIDP), ATTR2(SQL_ATTR_SIMULATE_CURSOR, UINTEGER, simulate_cursor), ATTR2(SQL_ATTR_USE_BOOKMARKS, UINTEGER, use_bookmarks),#undef ATTR2#undef ATTR};static const struct attribute *lookup_attr(const char *name){ unsigned int i; if (!name) fatal("Line %u: NULL attribute\n", line_num); for (i = 0; i < sizeof(attributes) / sizeof(attributes[0]); ++i) if (strcmp(attributes[i].name, name) == 0 || strcmp(attributes[i].name + 4, name) == 0) return &attributes[i]; fatal("Line %u: attribute %s not found\n", line_num, name); return NULL;}#define SEP " \t\n"#define ATTR_PARAMS const struct attribute *attr, int expectedtypedef int (*get_attr_t) (ATTR_PARAMS);static intget_attr_stmt(ATTR_PARAMS){ SQLINTEGER i, ind; SQLSMALLINT si; SQLLEN li; SQLRETURN ret; ret = SQL_ERROR; switch (attr->type) { case type_INTEGER: case type_UINTEGER: i = 0xdeadbeef; ret = SQLGetStmtAttr(Statement, attr->value, (SQLPOINTER) & i, sizeof(SQLINTEGER), &ind); break; case type_SMALLINT: si = 0xbeef; ret = SQLGetStmtAttr(Statement, attr->value, (SQLPOINTER) & si, sizeof(SQLSMALLINT), &ind); i = si; break; case type_LEN: li = 0xdeadbeef; ret = SQLGetStmtAttr(Statement, attr->value, (SQLPOINTER) & li, sizeof(SQLLEN), &ind); i = li; break; case type_VOIDP: case type_DESC: case type_CHARP: fatal("Line %u: CHAR* check still not supported\n", line_num); break; } if (!SQL_SUCCEEDED(ret)) fatal("Line %u: failure not expected\n", line_num); return i;}#if 0/* do not retry any attribute just return expected value so to make caller happy */static intget_attr_none(ATTR_PARAMS){ return expected;}#endifintmain(int argc, char *argv[]){#define TEST_FILE "attributes.in" const char *in_file = FREETDS_SRCDIR "/" TEST_FILE; FILE *f; char buf[256]; SQLINTEGER i; SQLLEN len; get_attr_t get_attr_p = get_attr_stmt; Connect(); /* TODO find another way */ CheckCursor(); Command(Statement, "SET TEXTSIZE 4096"); SQLBindCol(Statement, 1, SQL_C_SLONG, &i, sizeof(i), &len); f = fopen(in_file, "r"); if (!f) fopen(TEST_FILE, "r"); if (!f) { fprintf(stderr, "error opening test file\n"); exit(1); } line_num = 0; while (fgets(buf, sizeof(buf), f)) { char *p = buf, *cmd; ++line_num; while (isspace((unsigned char) *p)) ++p; cmd = strtok(p, SEP); /* skip comments */ if (!cmd || cmd[0] == '#' || cmd[0] == 0 || cmd[0] == '\n') continue; if (strcmp(cmd, "odbc") == 0) { int odbc3 = get_int(strtok(NULL, SEP)) == 3 ? 1 : 0; if (use_odbc_version3 != odbc3) { use_odbc_version3 = odbc3; Disconnect(); Connect(); Command(Statement, "SET TEXTSIZE 4096"); SQLBindCol(Statement, 1, SQL_C_SLONG, &i, sizeof(i), &len); } continue; } /* set attribute */ if (strcmp(cmd, "set") == 0) { const struct attribute *attr = lookup_attr(strtok(NULL, SEP)); char *value = strtok(NULL, SEP); SQLRETURN ret; if (!value) fatal("Line %u: value not defined\n", line_num); ret = SQL_ERROR; switch (attr->type) { case type_UINTEGER: case type_INTEGER: ret = SQLSetStmtAttr(Statement, attr->value, int2ptr(lookup(value, attr->lookup)), sizeof(SQLINTEGER)); break; case type_SMALLINT: ret = SQLSetStmtAttr(Statement, attr->value, int2ptr(lookup(value, attr->lookup)), sizeof(SQLSMALLINT)); break; case type_LEN: ret = SQLSetStmtAttr(Statement, attr->value, int2ptr(lookup(value, attr->lookup)), sizeof(SQLLEN)); break; case type_CHARP: ret = SQLSetStmtAttr(Statement, attr->value, (SQLPOINTER) value, SQL_NTS); break; case type_VOIDP: case type_DESC: fatal("Line %u: not implemented\n"); } if (!SQL_SUCCEEDED(ret)) fatal("Line %u: failure not expected setting statement attribute\n", line_num); get_attr_p = get_attr_stmt; continue; } /* test attribute */ if (strcmp(cmd, "attr") == 0) { const struct attribute *attr = lookup_attr(strtok(NULL, SEP)); char *value = strtok(NULL, SEP); int i, expected = lookup(value, attr->lookup); if (!value) fatal("Line %u: value not defined\n", line_num); i = get_attr_p(attr, expected); if (i != expected) { g_result = 1; fprintf(stderr, "Line %u: invalid %s got %d(%s) expected %s\n", line_num, attr->name, i, unlookup(i, attr->lookup), value); } continue; } if (strcmp(cmd, "reset") == 0) { ResetStatement(); continue; } fatal("Line %u: command '%s' not handled\n", line_num, cmd); } fclose(f); Disconnect(); printf("Done.\n"); return g_result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -