📄 odbc.c
字号:
#endif tds_dstr_init(&dbc->attr.translate_lib); dbc->attr.translate_option = 0; dbc->attr.txn_isolation = SQL_TXN_READ_COMMITTED; *phdbc = (SQLHDBC) dbc; ODBC_RETURN_(env);}SQLRETURN ODBC_APISQLAllocConnect(SQLHENV henv, SQLHDBC FAR * phdbc){ tdsdump_log(TDS_DBG_FUNC, "SQLAllocConnect(%p, %p)\n", henv, phdbc); odbc_errs_reset(&((TDS_ENV *) henv)->errs); return _SQLAllocConnect(henv, phdbc);}static SQLRETURN_SQLAllocEnv(SQLHENV FAR * phenv){ TDS_ENV *env; TDSCONTEXT *ctx; tdsdump_log(TDS_DBG_FUNC, "_SQLAllocEnv(%p)\n", phenv); env = (TDS_ENV *) calloc(1, sizeof(TDS_ENV)); if (!env) return SQL_ERROR; env->htype = SQL_HANDLE_ENV; env->attr.odbc_version = SQL_OV_ODBC2; /* TODO use it */ env->attr.output_nts = SQL_TRUE; ctx = tds_alloc_context(env); if (!ctx) { free(env); return SQL_ERROR; } env->tds_ctx = ctx; ctx->msg_handler = odbc_errmsg_handler; ctx->err_handler = odbc_errmsg_handler; /* ODBC has its own format */ free(ctx->locale->date_fmt); ctx->locale->date_fmt = strdup("%Y-%m-%d %H:%M:%S.%z"); *phenv = (SQLHENV) env; return SQL_SUCCESS;}SQLRETURN ODBC_APISQLAllocEnv(SQLHENV FAR * phenv){ tdsdump_log(TDS_DBG_FUNC, "SQLAllocEnv(%p)\n", phenv); return _SQLAllocEnv(phenv);}static SQLRETURN_SQLAllocDesc(SQLHDBC hdbc, SQLHDESC FAR * phdesc){ int i; INIT_HDBC; tdsdump_log(TDS_DBG_FUNC, "_SQLAllocDesc(%p, %p)\n", hdbc, phdesc); for (i = 0; i < TDS_MAX_APP_DESC; ++i) { if (dbc->uad[i] == NULL) { TDS_DESC *desc = desc_alloc(dbc, DESC_ARD, SQL_DESC_ALLOC_USER); if (desc == NULL) { odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } dbc->uad[i] = desc; *phdesc = (SQLHDESC) desc; ODBC_RETURN_(dbc); } } odbc_errs_add(&dbc->errs, "HY014", NULL); ODBC_RETURN(dbc, SQL_ERROR);}static SQLRETURN_SQLAllocStmt(SQLHDBC hdbc, SQLHSTMT FAR * phstmt){ TDS_STMT *stmt; char *pstr; INIT_HDBC; tdsdump_log(TDS_DBG_FUNC, "_SQLAllocStmt(%p, %p)\n", hdbc, phstmt); stmt = (TDS_STMT *) calloc(1, sizeof(TDS_STMT)); if (!stmt) { odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } tds_dstr_init(&stmt->cursor_name); stmt->htype = SQL_HANDLE_STMT; stmt->dbc = dbc; stmt->num_param_rows = 1; pstr = NULL; /* TODO test initial cursor ... */ if (asprintf(&pstr, "SQL_CUR%lx", (unsigned long) stmt) < 0 || !tds_dstr_set(&stmt->cursor_name, pstr)) { free(stmt); free(pstr); odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } /* do not free pstr tds_dstr_set do it if necessary */ /* allocate descriptors */ stmt->ird = desc_alloc(stmt, DESC_IRD, SQL_DESC_ALLOC_AUTO); stmt->ard = desc_alloc(stmt, DESC_ARD, SQL_DESC_ALLOC_AUTO); stmt->ipd = desc_alloc(stmt, DESC_IPD, SQL_DESC_ALLOC_AUTO); stmt->apd = desc_alloc(stmt, DESC_APD, SQL_DESC_ALLOC_AUTO); if (!stmt->ird || !stmt->ard || !stmt->ipd || !stmt->apd) { tds_dstr_free(&stmt->cursor_name); desc_free(stmt->ird); desc_free(stmt->ard); desc_free(stmt->ipd); desc_free(stmt->apd); free(stmt); odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } /* save original ARD and APD */ stmt->orig_apd = stmt->apd; stmt->orig_ard = stmt->ard; /* set the default statement attributes *//* stmt->attr.app_param_desc = stmt->apd; *//* stmt->attr.app_row_desc = stmt->ard; */ stmt->attr.async_enable = SQL_ASYNC_ENABLE_OFF; stmt->attr.concurrency = SQL_CONCUR_READ_ONLY; stmt->attr.cursor_scrollable = SQL_NONSCROLLABLE; stmt->attr.cursor_sensitivity = SQL_INSENSITIVE; stmt->attr.cursor_type = SQL_CURSOR_FORWARD_ONLY; /* TODO ?? why two attributes */ stmt->attr.enable_auto_ipd = dbc->attr.auto_ipd = SQL_FALSE; stmt->attr.fetch_bookmark_ptr = NULL;/* stmt->attr.imp_param_desc = stmt->ipd; *//* stmt->attr.imp_row_desc = stmt->ird; */ stmt->attr.keyset_size = 0; stmt->attr.max_length = 0; stmt->attr.max_rows = 0; stmt->attr.metadata_id = dbc->attr.metadata_id; /* TODO check this flag in prepare_call */ stmt->attr.noscan = SQL_NOSCAN_OFF; assert(stmt->apd->header.sql_desc_bind_offset_ptr == NULL); assert(stmt->apd->header.sql_desc_bind_type == SQL_PARAM_BIND_BY_COLUMN); assert(stmt->apd->header.sql_desc_array_status_ptr == NULL); assert(stmt->ipd->header.sql_desc_array_status_ptr == NULL); assert(stmt->ipd->header.sql_desc_rows_processed_ptr == NULL); assert(stmt->apd->header.sql_desc_array_size == 1); stmt->attr.query_timeout = DEFAULT_QUERY_TIMEOUT; stmt->attr.retrieve_data = SQL_RD_ON; assert(stmt->ard->header.sql_desc_array_size == 1); assert(stmt->ard->header.sql_desc_bind_offset_ptr == NULL); assert(stmt->ard->header.sql_desc_bind_type == SQL_BIND_BY_COLUMN); stmt->attr.row_number = 0; assert(stmt->ard->header.sql_desc_array_status_ptr == NULL); assert(stmt->ird->header.sql_desc_array_status_ptr == NULL); assert(stmt->ird->header.sql_desc_rows_processed_ptr == NULL); stmt->attr.simulate_cursor = SQL_SC_NON_UNIQUE; stmt->attr.use_bookmarks = SQL_UB_OFF; stmt->sql_rowset_size = 1; stmt->row_count = TDS_NO_COUNT; stmt->row_status = NOT_IN_ROW; /* insert into list */ stmt->next = dbc->stmt_list; if (dbc->stmt_list) dbc->stmt_list->prev = stmt; dbc->stmt_list = stmt; *phstmt = (SQLHSTMT) stmt; if (dbc->attr.cursor_type != SQL_CURSOR_FORWARD_ONLY) _SQLSetStmtAttr(stmt, SQL_CURSOR_TYPE, (SQLPOINTER) (TDS_INTPTR) dbc->attr.cursor_type, SQL_IS_INTEGER); ODBC_RETURN_(dbc);}SQLRETURN ODBC_APISQLAllocStmt(SQLHDBC hdbc, SQLHSTMT FAR * phstmt){ tdsdump_log(TDS_DBG_FUNC, "SQLAllocStmt(%p, %p)\n", hdbc, phstmt); return _SQLAllocStmt(hdbc, phstmt);}SQLRETURN ODBC_APISQLBindCol(SQLHSTMT hstmt, SQLUSMALLINT icol, SQLSMALLINT fCType, SQLPOINTER rgbValue, SQLLEN cbValueMax, SQLLEN FAR * pcbValue){ SQLRETURN rc = SQL_SUCCESS; TDS_DESC *ard; struct _drecord *drec; SQLSMALLINT orig_ard_size; INIT_HSTMT; tdsdump_log(TDS_DBG_FUNC, "SQLBindCol(%p, %d, %d, %p, %d, %p)\n", hstmt, icol, fCType, rgbValue, (int)cbValueMax, pcbValue); /* TODO - More error checking XXX smurph */#ifdef TDS_NO_DM /* check conversion type */ switch (fCType) { case SQL_C_CHAR: case SQL_C_BINARY: case SQL_C_DEFAULT: /* check max buffer length */ if (!IS_VALID_LEN(cbValueMax)) { odbc_errs_add(&stmt->errs, "HY090", NULL); rc = SQL_ERROR; } break; }#endif if (icol <= 0 || icol > 4000) { odbc_errs_add(&stmt->errs, "07009", NULL); rc = SQL_ERROR; } if (rc != SQL_SUCCESS) { ODBC_RETURN(stmt, rc); } ard = stmt->ard; orig_ard_size = ard->header.sql_desc_count; if (icol > ard->header.sql_desc_count && desc_alloc_records(ard, icol) != SQL_SUCCESS) { odbc_errs_add(&stmt->errs, "HY001", NULL); ODBC_RETURN(stmt, SQL_ERROR); } drec = &ard->records[icol - 1]; if (odbc_set_concise_c_type(fCType, drec, 0) != SQL_SUCCESS) { desc_alloc_records(ard, orig_ard_size); odbc_errs_add(&stmt->errs, "HY003", NULL); ODBC_RETURN(stmt, SQL_ERROR); } drec->sql_desc_octet_length = cbValueMax; drec->sql_desc_octet_length_ptr = pcbValue; drec->sql_desc_indicator_ptr = pcbValue; drec->sql_desc_data_ptr = rgbValue; /* force rebind */ stmt->row = 0; ODBC_RETURN_(stmt);}SQLRETURN ODBC_APISQLCancel(SQLHSTMT hstmt){ TDSSOCKET *tds; /* * FIXME this function can be called from other thread, do not free * errors for this function * If function is called from another thread errors are not touched */ /* TODO some tests required */ INIT_HSTMT; tdsdump_log(TDS_DBG_FUNC, "SQLCancel(%p)\n", hstmt); tds = stmt->dbc->tds_socket; /* FIXME test current statement */ stmt->cancel_sent = 1; if (tds_send_cancel(tds) == TDS_FAIL) { ODBC_SAFE_ERROR(stmt); ODBC_RETURN(stmt, SQL_ERROR); } if (tds_process_cancel(tds) == TDS_FAIL) { ODBC_SAFE_ERROR(stmt); ODBC_RETURN(stmt, SQL_ERROR); } /* only if we processed cancel reset statement */ if (stmt->dbc->current_statement && stmt->dbc->current_statement == stmt && tds->state == TDS_IDLE) stmt->dbc->current_statement = NULL; ODBC_RETURN_(stmt);}SQLRETURN ODBC_APISQLConnect(SQLHDBC hdbc, SQLCHAR FAR * szDSN, SQLSMALLINT cbDSN, SQLCHAR FAR * szUID, SQLSMALLINT cbUID, SQLCHAR FAR * szAuthStr, SQLSMALLINT cbAuthStr){ SQLRETURN result; TDSCONNECTION *connection; INIT_HDBC; tdsdump_log(TDS_DBG_FUNC, "SQLConnect(%p, %p, %d, %p, %d, %p, %d)\n", hdbc, szDSN, cbDSN, szUID, cbUID, szAuthStr, cbAuthStr);#ifdef TDS_NO_DM if (szDSN && !IS_VALID_LEN(cbDSN)) { odbc_errs_add(&dbc->errs, "HY090", "Invalid DSN buffer length"); ODBC_RETURN(dbc, SQL_ERROR); } if (szUID && !IS_VALID_LEN(cbUID)) { odbc_errs_add(&dbc->errs, "HY090", "Invalid UID buffer length"); ODBC_RETURN(dbc, SQL_ERROR); } if (szAuthStr && !IS_VALID_LEN(cbAuthStr)) { odbc_errs_add(&dbc->errs, "HY090", "Invalid PWD buffer length"); ODBC_RETURN(dbc, SQL_ERROR); }#endif connection = tds_alloc_connection(dbc->env->tds_ctx->locale); if (!connection) { odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } /* data source name */ if (szDSN || (*szDSN)) tds_dstr_copyn(&dbc->dsn, (const char *) szDSN, odbc_get_string_size(cbDSN, szDSN)); else tds_dstr_copy(&dbc->dsn, "DEFAULT"); if (!odbc_get_dsn_info(tds_dstr_cstr(&dbc->dsn), connection)) { tds_free_connection(connection); odbc_errs_add(&dbc->errs, "IM007", "Error getting DSN information"); ODBC_RETURN(dbc, SQL_ERROR); } if (!tds_dstr_isempty(&dbc->attr.current_catalog)) tds_dstr_dup(&connection->database, &dbc->attr.current_catalog); /* * username/password are never saved to ini file, * so you do not check in ini file */ /* user id */ if (szUID && (*szUID)) { if (!tds_dstr_copyn(&connection->user_name, (char *) szUID, odbc_get_string_size(cbUID, szUID))) { tds_free_connection(connection); odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } } /* password */ if (szAuthStr) { if (!tds_dstr_copyn(&connection->password, (char *) szAuthStr, odbc_get_string_size(cbAuthStr, szAuthStr))) { tds_free_connection(connection); odbc_errs_add(&dbc->errs, "HY001", NULL); ODBC_RETURN(dbc, SQL_ERROR); } } /* DO IT */ if ((result = odbc_connect(dbc, connection)) != SQL_SUCCESS) { tds_free_connection(connection); ODBC_RETURN_(dbc); } tds_free_connection(connection); ODBC_RETURN_(dbc);}SQLRETURN ODBC_APISQLDescribeCol(SQLHSTMT hstmt, SQLUSMALLINT icol, SQLCHAR FAR * szColName, SQLSMALLINT cbColNameMax, SQLSMALLINT FAR * pcbColName, SQLSMALLINT FAR * pfSqlType, SQLULEN FAR * pcbColDef, SQLSMALLINT FAR * pibScale, SQLSMALLINT FAR * pfNullable){ TDS_DESC *ird; struct _drecord *drec; INIT_HSTMT; tdsdump_log(TDS_DBG_FUNC, "SQLDescribeCol(%p, %d, %p, %d, %p, %p, %p, %p, %p)\n", hstmt, icol, szColName, cbColNameMax, pcbColName, pfSqlType, pcbColDef, pibScale, pfNullable); ird = stmt->ird; if (icol <= 0 || icol > ird->header.sql_desc_count) { odbc_errs_add(&stmt->errs, "07009", "Column out of range"); ODBC_RETURN(stmt, SQL_ERROR); } /* check name length */ if (cbColNameMax < 0) { odbc_errs_add(&stmt->errs, "HY090", NULL); ODBC_RETURN(stmt, SQL_ERROR); } drec = &ird->records[icol - 1]; /* cbColNameMax can be 0 (to retrieve name length) */ if (szColName && cbColNameMax) { SQLRETURN result; /* straight copy column name up to cbColNameMax */ result = odbc_set_string(szColName, cbColNameMax, pcbColName, tds_dstr_cstr(&drec->sql_desc_label), -1); if (result == SQL_SUCCESS_WITH_INFO) { odbc_errs_add(&stmt->errs, "01004", NULL); stmt->errs.lastrc = SQL_SUCCESS_WITH_INFO; } } if (pfSqlType) { /* TODO sure ? check documentation for date and intervals */ *pfSqlType = drec->sql_desc_concise_type; } if (pcbColDef) { if (drec->sql_desc_type == SQL_NUMERIC || drec->sql_desc_type == SQL_DECIMAL) { *pcbColDef = drec->sql_desc_precision; } else { *pcbColDef = drec->sql_desc_length; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -