📄 dblib.c
字号:
case SYBDATETIME: return DATETIMEBIND; case SYBDATETIME4: return SMALLDATETIMEBIND; case SYBDECIMAL: return DECIMALBIND; case SYBNUMERIC: return NUMERICBIND; case SYBFLT8: return FLT8BIND; case SYBREAL: return REALBIND; case SYBINT1: return TINYBIND; case SYBINT2: return SMALLBIND; case SYBINT4: return INTBIND; case SYBMONEY: return MONEYBIND; case SYBMONEY4: return SMALLMONEYBIND; default: assert(0 == "no such datatype"); } return 0;}/** \internal * dbbind() says: "Note that if varlen is 0, no padding takes place" * dbgetnull() will not pad varaddr unless varlen is positive. * Vartype Program Type Padding Terminator * ------------------- -------------- -------------- ---------- * CHARBIND DBCHAR blanks none * STRINGBIND DBCHAR blanks \0 * NTBSTRINGBIND DBCHAR none \0 * VARYCHARBIND DBVARYCHAR none none * BOUNDARYBIND DBCHAR none \0 * SENSITIVITYBIND DBCHAR none \0 */static RETCODEdbgetnull(DBPROCESS *dbproc, int bindtype, int varlen, BYTE* varaddr){ NULLREP *pnullrep; tdsdump_log(TDS_DBG_FUNC, "dbgetnull(%p, %d, %d, %p)\n", dbproc, bindtype, varlen, varaddr); CHECK_PARAMETER(dbproc, SYBENULL, FAIL); CHECK_PARAMETER(varaddr, SYBENULL, FAIL); CHECK_PARAMETER(!IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE, FAIL); CHECK_PARAMETER(0 <= bindtype && bindtype < MAXBINDTYPES, SYBEBTYP, FAIL); if (!varaddr) { dbperror(dbproc, SYBENULP, 0, "dbgetnull", "varaddr"); return FAIL; } assert(dbproc->nullreps); pnullrep = dbproc->nullreps + bindtype; /* * Fixed types: ignore varlen * Other types: ignore varlen if <= 0, else varlen must be >= pnullrep->len. */ switch (bindtype) { case DATETIMEBIND: case DECIMALBIND: case FLT8BIND: case INTBIND: case MONEYBIND: case NUMERICBIND: case REALBIND: case SMALLBIND: case SMALLDATETIMEBIND: case SMALLMONEYBIND: case TINYBIND: memcpy(varaddr, pnullrep->bindval, pnullrep->len); return SUCCEED; default: if (pnullrep->bindval && (varlen <= 0 || varlen >= pnullrep->len)) { memcpy(varaddr, pnullrep->bindval, pnullrep->len); } } /* * For variable-length types, nonpositive varlen indicates * buffer is "big enough" but also not to pad. * Apply terminator (if applicable) and go home. */ if (varlen <= 0) { switch (bindtype) { case STRINGBIND: case NTBSTRINGBIND: varaddr[pnullrep->len] = '\0'; /* fall thru */ case CHARBIND: case VARYCHARBIND: break;#if 0 case BOUNDARYBIND: case SENSITIVITYBIND:#endif default: assert(!"unknown bindtype with unknown varlen"); } return SUCCEED; } if (varlen < (long)pnullrep->len) { tdsdump_log(TDS_DBG_FUNC, "dbgetnull: error: not setting varaddr(%p) because %d < %lu\n", varaddr, varlen, (unsigned long int) pnullrep->len); return FAIL; } tdsdump_log(TDS_DBG_FUNC, "varaddr(%p) varlen %d < %lu?\n", varaddr, varlen, (unsigned long int) pnullrep->len); assert(varlen > 0); /* * CHARBIND Empty string (padded with blanks) * STRINGBIND Empty string (padded with blanks, null-terminated) * BINARYBIND Empty array (padded with zeros) */ varaddr += pnullrep->len; varlen -= pnullrep->len; if (varlen > 0) { switch (bindtype) { case CHARBIND: memset(varaddr, ' ', varlen); break; case STRINGBIND: memset(varaddr, ' ', varlen); varaddr[varlen-1] = '\0'; break; case BINARYBIND: memset(varaddr, 0, varlen); break; default: assert(!"unknown bindtype"); } } return SUCCEED;}/** * \ingroup dblib_core * \brief Initialize db-lib. * * \remarks Call this function before trying to use db-lib in any way. * Allocates various internal structures and reads \c locales.conf (if any) to determine the default * date format. * \retval SUCCEED normal. * \retval FAIL cannot allocate an array of \c TDS_MAX_CONN \c TDSSOCKET pointers. */RETCODEdbinit(void){ _dblib_err_handler = default_err_handler; TDS_MUTEX_LOCK(&dblib_mutex); tdsdump_log(TDS_DBG_FUNC, "dbinit(void)\n"); if (++g_dblib_ctx.ref_count != 1) { TDS_MUTEX_UNLOCK(&dblib_mutex); return SUCCEED; } /* * DBLIBCONTEXT stores a list of current connections so they may be closed with dbexit() */ g_dblib_ctx.connection_list = calloc(TDS_MAX_CONN, sizeof(TDSSOCKET *)); if (g_dblib_ctx.connection_list == NULL) { tdsdump_log(TDS_DBG_FUNC, "dbinit: out of memory\n"); TDS_MUTEX_UNLOCK(&dblib_mutex); return FAIL; } g_dblib_ctx.connection_list_size = TDS_MAX_CONN; g_dblib_ctx.connection_list_size_represented = TDS_MAX_CONN; g_dblib_ctx.login_timeout = -1; g_dblib_ctx.query_timeout = -1; TDS_MUTEX_UNLOCK(&dblib_mutex); dblib_get_tds_ctx(); return SUCCEED;}/** * \ingroup dblib_core * \brief Allocate a \c LOGINREC structure. * * \remarks A \c LOGINREC structure is passed to \c dbopen() to create a connection to the database. * Does not communicate to the server; interacts strictly with library. * \retval NULL the \c LOGINREC cannot be allocated. * \retval LOGINREC* to valid memory, otherwise. */LOGINREC *dblogin(void){ LOGINREC *loginrec; tdsdump_log(TDS_DBG_FUNC, "dblogin(void)\n"); if ((loginrec = malloc(sizeof(LOGINREC))) == NULL) { dbperror(NULL, SYBEMEM, errno); return NULL; } if ((loginrec->tds_login = tds_alloc_login()) == NULL) { dbperror(NULL, SYBEMEM, errno); free(loginrec); return NULL; } /* set default values for loginrec */ tds_set_library(loginrec->tds_login, "DB-Library"); return loginrec;}/** * \ingroup dblib_core * \brief free the \c LOGINREC * */voiddbloginfree(LOGINREC * login){ tdsdump_log(TDS_DBG_FUNC, "dbloginfree(%p)\n", login); if (login) { tds_free_login(login->tds_login); TDS_ZERO_FREE(login); }}/** \internal * \ingroup dblib_internal * \brief Set the value of a string in a \c LOGINREC structure. * * Called by various macros to populate \a login. * \param login the \c LOGINREC* to modify. * \param value the value to set it to. * \param which the field to set. * \retval SUCCEED the value was set. * \retval FAIL \c DBSETHID or other invalid \a which was tried. */RETCODEdbsetlname(LOGINREC * login, const char *value, int which){ tdsdump_log(TDS_DBG_FUNC, "dbsetlname(%p, %s, %d)\n", login, value, which); if( login == NULL ) { dbperror(NULL, SYBEASNL, 0); return FAIL; } switch (which) { case DBSETHOST: tds_set_host(login->tds_login, value); return SUCCEED; break; case DBSETUSER: tds_set_user(login->tds_login, value); return SUCCEED; break; case DBSETPWD: tds_set_passwd(login->tds_login, value); return SUCCEED; break; case DBSETAPP: tds_set_app(login->tds_login, value); return SUCCEED; break; case DBSETCHARSET: tds_set_client_charset(login->tds_login, value ? value : ""); return SUCCEED; break; case DBSETNATLANG: tds_set_language(login->tds_login, value); return SUCCEED; break; case DBSETHID: default: dbperror(NULL, SYBEASUL, 0); /* Attempt to set unknown LOGINREC field */ return FAIL; break; }}/** \internal * \ingroup dblib_internal * \brief Set an integer value in a \c LOGINREC structure. * * Called by various macros to populate \a login. * \param login the \c LOGINREC* to modify. * \param value the value to set it to. * \param which the field to set. * \retval SUCCEED the value was set. * \retval FAIL anything other than \c DBSETPACKET was passed for \a which. */RETCODEdbsetllong(LOGINREC * login, long value, int which){ tdsdump_log(TDS_DBG_FUNC, "dbsetllong(%p, %ld, %d)\n", login, value, which); switch (which) { case DBSETPACKET: if (0 <= value && value <= 999999) { tds_set_packet(login->tds_login, value); return SUCCEED; } dbperror(0, SYBEBADPK, 0, (int) value, (int) login->tds_login->block_size); return FAIL; break; default: tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetllong() which = %d\n", which); return FAIL; break; }}/** \internal * \ingroup dblib_internal * \brief Set an integer value in a \c LOGINREC structure. * * Called by various macros to populate \a login. * \param login the \c LOGINREC* to modify. * \param value the value to set it to. * \param which the field to set. * \retval SUCCEED the value was set. * \retval FAIL anything other than \c DBSETHIER was passed for \a which. */RETCODEdbsetlshort(LOGINREC * login, int value, int which){ tdsdump_log(TDS_DBG_FUNC, "dbsetlshort(%p, %d, %d)\n", login, value, which); switch (which) { case DBSETHIER: default: tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetlshort() which = %d\n", which); return FAIL; break; }}/** \internal * \ingroup dblib_internal * \brief Set a boolean value in a \c LOGINREC structure. * * Called by various macros to populate \a login. * \param login the \c LOGINREC* to modify. * \param value the value to set it to. * \param which the field to set. * \remark Only DBSETBCP is implemented. * \retval SUCCEED the value was set. * \retval FAIL invalid value passed for \a which. * \todo DBSETNOSHORT, DBSETENCRYPT, DBSETLABELED */RETCODEdbsetlbool(LOGINREC * login, int value, int which){ tdsdump_log(TDS_DBG_FUNC, "dbsetlbool(%p, %d, %d)\n", login, value, which); switch (which) { case DBSETBCP: tds_set_bulk(login->tds_login, (TDS_TINYINT) value); return SUCCEED; break; case DBSETNOSHORT: case DBSETENCRYPT: case DBSETLABELED: default: tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetlbool() which = %d\n", which); return FAIL; break; }}/** * \ingroup dblib_core * \brief Set TDS version for future connections * */RETCODE dbsetlversion (LOGINREC * login, BYTE version){ tdsdump_log(TDS_DBG_FUNC, "dbsetlversion(%p, %x)\n", login, version); if (login == NULL || login->tds_login == NULL) return FAIL; switch (version) { case DBVER42: login->tds_login->major_version = 4; login->tds_login->minor_version = 2; return SUCCEED; case DBVER60: login->tds_login->major_version = 6; login->tds_login->minor_version = 0; return SUCCEED; } return FAIL;}static voiddbstring_free(DBSTRING ** dbstrp){ DBSTRING *curr, *next; /* tdsdump_log(TDS_DBG_FUNC, "dbstring_free(%p)\n", dbstrp); */ if (!dbstrp) return; curr = *dbstrp; *dbstrp = NULL; for (; curr; ) { next = curr->strnext; free(curr->strtext); free(curr); curr = next; }}static RETCODEdbstring_concat(DBSTRING ** dbstrp, const char *p){ DBSTRING **strp = dbstrp; /* tdsdump_log(TDS_DBG_FUNC, "dbstring_concat(%p, %s)\n", *dbstrp, p); */ while (*strp != NULL) { strp = &((*strp)->strnext); } if ((*strp = malloc(sizeof(DBSTRING))) == NULL) { dbperror(NULL, SYBEMEM, errno); return FAIL; } (*strp)->strtotlen = strlen(p); if (((*strp)->strtext = malloc((*strp)->strtotlen)) == NULL) { TDS_ZERO_FREE(*strp); dbperror(NULL, SYBEMEM, errno); return FAIL; } memcpy((*strp)->strtext, p, (*strp)->strtotlen); (*strp)->strnext = NULL; return SUCCEED;}static RETCODEdbstring_assign(DBSTRING ** dbstrp, const char *p){ /* tdsdump_log(TDS_DBG_FUNC, "dbstring_assign(%p, %s)\n", *dbstrp, p); */ dbstring_free(dbstrp); return dbstring_concat(dbstrp, p);}static DBINTdbstring_length(DBSTRING * dbstr){ DBINT len = 0; DBSTRING *next; /* tdsdump_log(TDS_DBG_FUNC, "dbstring_length(%p)\n", dbstr); */ for (next = dbstr; next != NULL; next = next->strnext) { len += next->strtotlen; } return len;}static intdbstring_getchar(DBSTRING * dbstr, int i){ /* tdsdump_log(TDS_DBG_FUNC, "dbstring_getchar(%p, %d)\n", dbstr, i); */ if (dbstr == NULL) { return -1; } if (i < 0) { return -1; } if (i < dbstr->strtotlen) { return dbstr->strtext[i]; } return dbstring_getchar(dbstr->strnext, i - dbstr->strtotlen);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -