📄 odbc.c
字号:
if (pibScale) { if (drec->sql_desc_type == SQL_NUMERIC || drec->sql_desc_type == SQL_DECIMAL || drec->sql_desc_type == SQL_DATETIME || drec->sql_desc_type == SQL_FLOAT) { *pibScale = drec->sql_desc_scale; } else { /* TODO test setting desc directly, SQLDescribeCol return just descriptor data ?? */ *pibScale = 0; } } if (pfNullable) { *pfNullable = drec->sql_desc_nullable; } ODBC_RETURN_(stmt);}static SQLRETURN_SQLColAttribute(SQLHSTMT hstmt, SQLUSMALLINT icol, SQLUSMALLINT fDescType, SQLPOINTER rgbDesc, SQLSMALLINT cbDescMax, SQLSMALLINT FAR * pcbDesc, SQLLEN FAR * pfDesc){ TDS_DESC *ird; struct _drecord *drec; SQLRETURN result = SQL_SUCCESS; INIT_HSTMT; tdsdump_log(TDS_DBG_FUNC, "_SQLColAttribute(%p, %u, %u, %p, %d, %p, %p)\n", hstmt, icol, fDescType, rgbDesc, cbDescMax, pcbDesc, pfDesc); ird = stmt->ird;#define COUT(src) result = odbc_set_string(rgbDesc, cbDescMax, pcbDesc, src ? src : "", -1);#define SOUT(src) result = odbc_set_string(rgbDesc, cbDescMax, pcbDesc, tds_dstr_cstr(&src), -1);/* SQLColAttribute returns always attributes using SQLINTEGER */#if ENABLE_EXTRA_CHECKS#define IOUT(type, src) do { \ /* trick warning if type wrong */ \ type *p_test = &src; p_test = p_test; \ *pfDesc = src; } while(0)#else#define IOUT(type, src) *pfDesc = src#endif /* dont check column index for these */ switch (fDescType) {#if SQL_COLUMN_COUNT != SQL_DESC_COUNT case SQL_COLUMN_COUNT:#endif case SQL_DESC_COUNT: IOUT(SQLSMALLINT, ird->header.sql_desc_count); ODBC_RETURN(stmt, SQL_SUCCESS); break; } if (!ird->header.sql_desc_count) { odbc_errs_add(&stmt->errs, "07005", NULL); ODBC_RETURN(stmt, SQL_ERROR); } if (icol <= 0 || icol > ird->header.sql_desc_count) { odbc_errs_add(&stmt->errs, "07009", "Column out of range"); ODBC_RETURN(stmt, SQL_ERROR); } drec = &ird->records[icol - 1]; tdsdump_log(TDS_DBG_INFO1, "odbc:SQLColAttribute: fDescType is %d\n", fDescType); switch (fDescType) { case SQL_DESC_AUTO_UNIQUE_VALUE: IOUT(SQLUINTEGER, drec->sql_desc_auto_unique_value); break; case SQL_DESC_BASE_COLUMN_NAME: SOUT(drec->sql_desc_base_column_name); break; case SQL_DESC_BASE_TABLE_NAME: SOUT(drec->sql_desc_base_table_name); break; case SQL_DESC_CASE_SENSITIVE: IOUT(SQLINTEGER, drec->sql_desc_case_sensitive); break; case SQL_DESC_CATALOG_NAME: SOUT(drec->sql_desc_catalog_name); break;#if SQL_COLUMN_TYPE != SQL_DESC_CONCISE_TYPE case SQL_COLUMN_TYPE: /* special case, get ODBC 2 type, not ODBC 3 SQL_DESC_CONCISE_TYPE (different for datetime) */ if (stmt->dbc->env->attr.odbc_version == SQL_OV_ODBC3) { IOUT(SQLSMALLINT, drec->sql_desc_concise_type); break; } /* get type and convert it to ODBC 2 type */ { SQLSMALLINT type = drec->sql_desc_concise_type; switch (type) { case SQL_TYPE_DATE: type = SQL_DATE; break; case SQL_TYPE_TIME: type = SQL_TIME; break; case SQL_TYPE_TIMESTAMP: type = SQL_TIMESTAMP; break; } IOUT(SQLSMALLINT, type); } break;#else case SQL_DESC_CONCISE_TYPE: IOUT(SQLSMALLINT, drec->sql_desc_concise_type); break;#endif case SQL_DESC_DISPLAY_SIZE: IOUT(SQLLEN, drec->sql_desc_display_size); break; case SQL_DESC_FIXED_PREC_SCALE: IOUT(SQLSMALLINT, drec->sql_desc_fixed_prec_scale); break; case SQL_DESC_LABEL: SOUT(drec->sql_desc_label); break; /* FIXME special cases for SQL_COLUMN_LENGTH */ case SQL_COLUMN_LENGTH: IOUT(SQLLEN, drec->sql_desc_octet_length); break; case SQL_DESC_LENGTH: IOUT(SQLULEN, drec->sql_desc_length); break; case SQL_DESC_LITERAL_PREFIX: COUT(drec->sql_desc_literal_prefix); break; case SQL_DESC_LITERAL_SUFFIX: COUT(drec->sql_desc_literal_suffix); break; case SQL_DESC_LOCAL_TYPE_NAME: SOUT(drec->sql_desc_local_type_name); break;#if SQL_COLUMN_NAME != SQL_DESC_NAME case SQL_COLUMN_NAME:#endif case SQL_DESC_NAME: SOUT(drec->sql_desc_name); break;#if SQL_COLUMN_NULLABLE != SQL_DESC_NULLABLE case SQL_COLUMN_NULLABLE:#endif case SQL_DESC_NULLABLE: IOUT(SQLSMALLINT, drec->sql_desc_nullable); break; case SQL_DESC_NUM_PREC_RADIX: IOUT(SQLINTEGER, drec->sql_desc_num_prec_radix); break; case SQL_DESC_OCTET_LENGTH: IOUT(SQLLEN, drec->sql_desc_octet_length); break; /* FIXME special cases for SQL_COLUMN_PRECISION */ case SQL_COLUMN_PRECISION: if (drec->sql_desc_concise_type == SQL_REAL) { *pfDesc = 7; break; } if (drec->sql_desc_concise_type == SQL_DOUBLE) { *pfDesc = 15; break; } if (drec->sql_desc_concise_type == SQL_TYPE_TIMESTAMP) { *pfDesc = drec->sql_desc_precision ? 23 : 16; break; } case SQL_DESC_PRECISION: /* this section may be wrong */ if (drec->sql_desc_concise_type == SQL_NUMERIC || drec->sql_desc_concise_type == SQL_DECIMAL || drec->sql_desc_concise_type == SQL_TYPE_TIMESTAMP) IOUT(SQLSMALLINT, drec->sql_desc_precision); else *pfDesc = drec->sql_desc_length; break; /* FIXME special cases for SQL_COLUMN_SCALE */ case SQL_COLUMN_SCALE: case SQL_DESC_SCALE: /* this section may be wrong */ if (drec->sql_desc_concise_type == SQL_NUMERIC || drec->sql_desc_concise_type == SQL_DECIMAL || drec->sql_desc_concise_type == SQL_TYPE_TIMESTAMP || drec->sql_desc_concise_type == SQL_FLOAT) IOUT(SQLSMALLINT, drec->sql_desc_scale); else *pfDesc = 0; break; case SQL_DESC_SCHEMA_NAME: SOUT(drec->sql_desc_schema_name); break; case SQL_DESC_SEARCHABLE: IOUT(SQLSMALLINT, drec->sql_desc_searchable); break; case SQL_DESC_TABLE_NAME: SOUT(drec->sql_desc_table_name); break; case SQL_DESC_TYPE: IOUT(SQLSMALLINT, drec->sql_desc_type); break; case SQL_DESC_TYPE_NAME: COUT(drec->sql_desc_type_name); break; case SQL_DESC_UNNAMED: IOUT(SQLSMALLINT, drec->sql_desc_unnamed); break; case SQL_DESC_UNSIGNED: IOUT(SQLSMALLINT, drec->sql_desc_unsigned); break; case SQL_DESC_UPDATABLE: IOUT(SQLSMALLINT, drec->sql_desc_updatable); break; default: tdsdump_log(TDS_DBG_INFO2, "odbc:SQLColAttribute: fDescType %d not catered for...\n", fDescType); odbc_errs_add(&stmt->errs, "HY091", NULL); ODBC_RETURN(stmt, SQL_ERROR); break; } if (result == SQL_SUCCESS_WITH_INFO) odbc_errs_add(&stmt->errs, "01004", NULL); ODBC_RETURN(stmt, result);#undef COUT#undef SOUT#undef IOUT}SQLRETURN ODBC_APISQLColAttributes(SQLHSTMT hstmt, SQLUSMALLINT icol, SQLUSMALLINT fDescType, SQLPOINTER rgbDesc, SQLSMALLINT cbDescMax, SQLSMALLINT FAR * pcbDesc, SQLLEN FAR * pfDesc){ tdsdump_log(TDS_DBG_FUNC, "SQLColAttributes(%p, %d, %d, %p, %d, %p, %p)\n", hstmt, icol, fDescType, rgbDesc, cbDescMax, pcbDesc, pfDesc); return _SQLColAttribute(hstmt, icol, fDescType, rgbDesc, cbDescMax, pcbDesc, pfDesc);}#if (ODBCVER >= 0x0300)SQLRETURN ODBC_APISQLColAttribute(SQLHSTMT hstmt, SQLUSMALLINT icol, SQLUSMALLINT fDescType, SQLPOINTER rgbDesc, SQLSMALLINT cbDescMax, SQLSMALLINT FAR * pcbDesc,#ifdef TDS_SQLCOLATTRIBUTE_SQLLEN SQLLEN FAR * pfDesc#else SQLPOINTER pfDesc#endif ){ tdsdump_log(TDS_DBG_FUNC, "SQLColAttribute(%p, %u, %u, %p, %d, %p, %p)\n", hstmt, icol, fDescType, rgbDesc, cbDescMax, pcbDesc, pfDesc); return _SQLColAttribute(hstmt, icol, fDescType, rgbDesc, cbDescMax, pcbDesc, pfDesc);}#endifSQLRETURN ODBC_APISQLDisconnect(SQLHDBC hdbc){ int i; INIT_HDBC; tdsdump_log(TDS_DBG_FUNC, "SQLDisconnect(%p)\n", hdbc); /* free all associated statements */ while (dbc->stmt_list) _SQLFreeStmt(dbc->stmt_list, SQL_DROP, 1); /* free all associated descriptors */ for (i = 0; i < TDS_MAX_APP_DESC; ++i) { if (dbc->uad[i]) { desc_free(dbc->uad[i]); dbc->uad[i] = NULL; } } tds_free_socket(dbc->tds_socket); dbc->tds_socket = NULL; dbc->cursor_support = 0; ODBC_RETURN_(dbc);}static intodbc_errmsg_handler(const TDSCONTEXT * ctx, TDSSOCKET * tds, TDSMESSAGE * msg){ struct _sql_errors *errs = NULL; TDS_DBC *dbc = NULL; tdsdump_log(TDS_DBG_INFO1, "msgno %d %d\n", (int) msg->msgno, TDSETIME); if (msg->msgno == TDSETIME) { tdsdump_log(TDS_DBG_INFO1, "in timeout\n"); if (tds && (dbc = (TDS_DBC *) tds->parent) && dbc->current_statement) { TDS_STMT *stmt = dbc->current_statement; /* cancel sent, handling interrupt */ if (tds->in_cancel && stmt->cancel_sent) { stmt->cancel_sent = 0; tdsdump_log(TDS_DBG_INFO1, "returning from timeout\n"); return TDS_INT_TIMEOUT; } if (!tds->in_cancel) odbc_errs_add(&stmt->errs, "HYT00", "Timeout expired"); stmt->errs.lastrc = SQL_ERROR; /* attent indefinitely cancel */ /* stmt->dbc->tds_socket->query_timeout = 0; */ } else if (dbc) { odbc_errs_add(&dbc->errs, "HYT00", "Timeout expired"); dbc->errs.lastrc = SQL_ERROR; tds_close_socket(tds); tdsdump_log(TDS_DBG_INFO1, "returning cancel from timeout\n"); return TDS_INT_CANCEL; } if (tds->in_cancel) { tds_close_socket(tds); tdsdump_log(TDS_DBG_INFO1, "returning cancel from timeout\n"); return TDS_INT_CANCEL; } tdsdump_log(TDS_DBG_INFO1, "returning from timeout\n"); return TDS_INT_TIMEOUT; } if (tds && tds->parent) { dbc = (TDS_DBC *) tds->parent; errs = &dbc->errs; if (dbc->current_statement) errs = &dbc->current_statement->errs; /* set server info if not setted in dbc */ if (msg->server && tds_dstr_isempty(&dbc->server)) tds_dstr_copy(&dbc->server, msg->server); } else if (ctx->parent) { errs = &((TDS_ENV *) ctx->parent)->errs; } if (errs) { int severity = msg->severity; const char * state = msg->sql_state; /* fix severity for Sybase */ if (severity <= 10 && dbc && !TDS_IS_MSSQL(dbc->tds_socket) && msg->sql_state && msg->sql_state[0] && strncmp(msg->sql_state, "00", 2) != 0) { if (strncmp(msg->sql_state, "01", 2) != 0 && strncmp(msg->sql_state, "IM", 2) != 0) severity = 11; } /* compute state if not available */ if (!state) state = severity <= 10 ? "01000" : "42000"; /* add error, do not overwrite connection timeout error */ if (msg->msgno != TDSEFCON || errs->lastrc != SQL_ERROR || errs->num_errors < 1) odbc_errs_add_rdbms(errs, msg->msgno, state, msg->message, msg->line_number, msg->severity, msg->server); /* set lastc according */ if (severity <= 10) { if (errs->lastrc == SQL_SUCCESS) errs->lastrc = SQL_SUCCESS_WITH_INFO; } else { errs->lastrc = SQL_ERROR; } } return TDS_INT_CANCEL;}/* TODO optimize, change only if some data change (set same value should not set this flag) */#define DESC_SET_NEED_REPREPARE \ do {\ if (desc->type == DESC_IPD) {\ assert(IS_HSTMT(desc->parent));\ ((TDS_STMT *) desc->parent)->need_reprepare = 1;\ }\ } while(0)SQLRETURN ODBC_APISQLSetDescRec(SQLHDESC hdesc, SQLSMALLINT nRecordNumber, SQLSMALLINT nType, SQLSMALLINT nSubType, SQLLEN nLength, SQLSMALLINT nPrecision, SQLSMALLINT nScale, SQLPOINTER pData, SQLLEN FAR * pnStringLength, SQLLEN FAR * pnIndicator){ struct _drecord *drec; SQLSMALLINT concise_type; INIT_HDESC; tdsdump_log(TDS_DBG_FUNC, "SQLSetDescRec(%p, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n", hdesc, nRecordNumber, nType, nSubType, (int)nLength, nPrecision, nScale, pData, pnStringLength, pnIndicator); if (desc->type == DESC_IRD) { odbc_errs_add(&desc->errs, "HY016", NULL); ODBC_RETURN(desc, SQL_ERROR); } if (nRecordNumber > desc->header.sql_desc_count || nRecordNumber < 0) { odbc_errs_add(&desc->errs, "07009", NULL); ODBC_RETURN(desc, SQL_ERROR); } drec = &desc->records[nRecordNumber]; /* check for valid types and return "HY021" if not */ if (desc->type == DESC_IPD) { DESC_SET_NEED_REPREPARE; concise_type = odbc_get_concise_sql_type(nType, nSubType); } else { concise_type = odbc_get_concise_c_type(nType, nSubType); } if (nType == SQL_INTERVAL || nType == SQL_DATETIME) { if (!concise_type) { odbc_errs_add(&desc->errs, "HY021", NULL); ODBC_RETURN(desc, SQL_ERROR); } } else { if (concise_type != nType) { odbc_errs_add(&desc->errs, "HY021", NULL); ODBC_RETURN(desc, SQL_ERROR); } nSubType = 0; } drec->sql_desc_concise_type = concise_type; drec->sql_desc_type = nType; drec->sql_desc_datetime_interval_code = nSubType; drec->sql_desc_octet_length = nLength; drec->sql_desc_precision = nPrecision; drec->sql_desc_scale = nScale; drec->sql_desc_data_ptr = pData; drec->sql_desc_octet_length_ptr = pnStringLength; drec->sql_desc_indicator_ptr = pnIndicator; ODBC_RETURN_(desc);}SQLRETURN ODBC_APISQLGetDescRec(SQLHDESC hdesc, SQLSMALLINT RecordNumber, SQLCH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -