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

📄 dblib.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
static char *dbstring_get(DBSTRING * dbstr){	DBSTRING *next;	int len;	char *ret;	char *cp;	/* tdsdump_log(TDS_DBG_FUNC, "dbstring_get(%p)\n", dbstr); */	if (dbstr == NULL) {		return NULL;	}	len = dbstring_length(dbstr);	if ((ret = malloc(len + 1)) == NULL) {		dbperror(NULL, SYBEMEM, errno);		return NULL;	}	cp = ret;	for (next = dbstr; next != NULL; next = next->strnext) {		memcpy(cp, next->strtext, next->strtotlen);		cp += next->strtotlen;	}	*cp = '\0';	return ret;}static const char *const opttext[DBNUMOPTIONS] = {	"parseonly",	"estimate",	"showplan",	"noexec",	"arithignore",	"nocount",	"arithabort",	"textlimit",	"browse",	"offsets",	"statistics",	"errlvl",	"confirm",	"spid",	"buffer",	"noautofree",	"rowcount",	"textsize",	"language",	"dateformat",	"prpad",	"prcolsep",	"prlinelen",	"prlinesep",	"lfconvert",	"datefirst",	"chained",	"fipsflagger",	"transaction isolation level",	"auth",	"identity_insert",	"no_identity_column",	"cnv_date2char_short",	"client cursors",	"set time",	"quoted_identifier"};static DBOPTION *init_dboptions(void){	DBOPTION *dbopts;	int i;	if ((dbopts = calloc(DBNUMOPTIONS, sizeof(DBOPTION))) == NULL) {		dbperror(NULL, SYBEMEM, errno);		return NULL;	}	for (i = 0; i < DBNUMOPTIONS; i++) {		tds_strlcpy(dbopts[i].text, opttext[i], sizeof(dbopts[i].text));		dbopts[i].param = NULL;		dbopts[i].factive = FALSE;	}	dbstring_assign(&(dbopts[DBPRPAD].param), " ");	dbstring_assign(&(dbopts[DBPRCOLSEP].param), " ");	dbstring_assign(&(dbopts[DBPRLINELEN].param), "80");	dbstring_assign(&(dbopts[DBPRLINESEP].param), "\n");	dbstring_assign(&(dbopts[DBCLIENTCURSORS].param), " ");	dbstring_assign(&(dbopts[DBSETTIME].param), " ");	return dbopts;}/** \internal * \ingroup dblib_internal * \brief Form a connection with the server. *    * Called by the \c dbopen() macro, normally.  If FreeTDS was configured with \c --enable-msdblib, this * function is called by (exported) \c dbopen() function.  \c tdsdbopen is so-named to avoid * namespace conflicts with other database libraries that use the same function name.   * \param login \c LOGINREC* carrying the account information. * \param server name of the dataserver to connect to.   * \return valid pointer on successful login.   * \retval NULL insufficient memory, unable to connect for any reason. * \sa dbopen() * \todo use \c asprintf() to avoid buffer overflow. * \todo separate error messages for \em no-such-server and \em no-such-user.  */DBPROCESS *tdsdbopen(LOGINREC * login, const char *server, int msdblib){	DBPROCESS *dbproc;	TDSCONNECTION *connection;	tdsdump_log(TDS_DBG_FUNC, "dbopen(%p, %s, [%s])\n", login, server, msdblib? "microsoft" : "sybase");	if ((dbproc = calloc(1, sizeof(DBPROCESS))) == NULL) {		dbperror(NULL, SYBEMEM, errno);		return NULL;	}	dbproc->msdblib = msdblib;	dbproc->dbopts = init_dboptions();	if (dbproc->dbopts == NULL) {		free(dbproc);		return NULL;	}		dbproc->dboptcmd = NULL;	dbproc->avail_flag = TRUE;	dbproc->command_state = DBCMDNONE;	tds_set_server(login->tds_login, server);	dbproc->tds_socket = tds_alloc_socket(dblib_get_tds_ctx(), 512);	tds_set_parent(dbproc->tds_socket, dbproc);	dbproc->tds_socket->option_flag2 &= ~0x02;	/* we're not an ODBC driver */	dbproc->tds_socket->env_chg_func = db_env_chg;	dbproc->envchange_rcv = 0;	dbproc->dbcurdb[0] = '\0';	dbproc->servcharset[0] = '\0';	connection = tds_read_config_info(NULL, login->tds_login, g_dblib_ctx.tds_ctx->locale);	if (!connection) {		dbclose(dbproc);		return NULL;	}	dbproc->chkintr = NULL;	dbproc->hndlintr = NULL;	TDS_MUTEX_LOCK(&dblib_mutex);	/* override connection timeout if dbsetlogintime() was called */	if (g_dblib_ctx.login_timeout > 0) {		connection->connect_timeout = g_dblib_ctx.login_timeout;	}	/* override query timeout if dbsettime() was called */	if (g_dblib_ctx.query_timeout > 0) {		connection->query_timeout = g_dblib_ctx.query_timeout;	}	TDS_MUTEX_UNLOCK(&dblib_mutex);	if (tds_connect(dbproc->tds_socket, connection) == TDS_FAIL) {		tds_free_connection(connection);		dbclose(dbproc);		return NULL;	}	tds_free_connection(connection);	dbproc->dbbuf = NULL;	dbproc->dbbufsz = 0;	TDS_MUTEX_LOCK(&dblib_mutex);	dblib_add_connection(&g_dblib_ctx, dbproc->tds_socket);	TDS_MUTEX_UNLOCK(&dblib_mutex);	/* set the DBBUFFER capacity to nil */	buffer_set_capacity(dbproc, 0);	TDS_MUTEX_LOCK(&dblib_mutex);	if (g_dblib_ctx.recftos_filename != NULL) {		char *temp_filename = NULL;		const int len = asprintf(&temp_filename, "%s.%d", 					 g_dblib_ctx.recftos_filename, g_dblib_ctx.recftos_filenum);		if (len >= 0) {			dbproc->ftos = fopen(temp_filename, "w");			if (dbproc->ftos != NULL) {				fprintf(dbproc->ftos, "/* dbopen() at %s */\n", _dbprdate(temp_filename));				fflush(dbproc->ftos);				g_dblib_ctx.recftos_filenum++;			}			free(temp_filename);		}	}		memcpy(dbproc->nullreps, default_null_representations, sizeof(default_null_representations));	TDS_MUTEX_UNLOCK(&dblib_mutex);	return dbproc;}/** * \ingroup dblib_core * \brief \c printf-like way to form SQL to send to the server.   * * Forms a command string and writes to the command buffer with dbcmd().   * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param fmt <tt> man vasprintf</tt> for details.   * \retval SUCCEED success. * \retval FAIL insufficient memory, or dbcmd() failed. * \sa dbcmd(), dbfreebuf(), dbgetchar(), dbopen(), dbstrcpy(), dbstrlen(). */RETCODEdbfcmd(DBPROCESS * dbproc, const char *fmt, ...){	va_list ap;	char *s;	int len;	RETCODE ret;	tdsdump_log(TDS_DBG_FUNC, "dbfcmd(%p, %s, ...)\n", dbproc, fmt);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	CHECK_NULP(fmt, "dbfcmd", 2, FAIL);		va_start(ap, fmt);	len = vasprintf(&s, fmt, ap);	va_end(ap);	if (len < 0) {		dbperror(NULL, SYBEMEM, errno);		return FAIL;	}	ret = dbcmd(dbproc, s);	free(s);	return ret;}/** * \ingroup dblib_core * \brief \c Append SQL to the command buffer.   * * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param cmdstring SQL to append to the command buffer.   * \retval SUCCEED success. * \retval FAIL insufficient memory.   * \remarks set command state to \c  DBCMDPEND unless the command state is DBCMDSENT, in which case  * it frees the command buffer.  This latter may or may not be the Right Thing to do.   * \sa dbfcmd(), dbfreebuf(), dbgetchar(), dbopen(), dbstrcpy(), dbstrlen(). */RETCODEdbcmd(DBPROCESS * dbproc, const char *cmdstring){	int newsz;	void *p;	tdsdump_log(TDS_DBG_FUNC, "dbcmd(%p, %s)\n", dbproc, cmdstring);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	CHECK_NULP(cmdstring, "dbcmd", 2, FAIL);	dbproc->avail_flag = FALSE;	tdsdump_log(TDS_DBG_FUNC, "dbcmd() bufsz = %d\n", dbproc->dbbufsz);	if (dbproc->command_state == DBCMDSENT) {		if (!dbproc->noautofree) {			dbfreebuf(dbproc);		}	}	if (dbproc->dbbufsz == 0) {		dbproc->dbbuf = malloc(strlen(cmdstring) + 1);		if (dbproc->dbbuf == NULL) {			dbperror(NULL, SYBEMEM, errno);			return FAIL;		}		strcpy((char *) dbproc->dbbuf, cmdstring);		dbproc->dbbufsz = strlen(cmdstring) + 1;	} else {		newsz = strlen(cmdstring) + dbproc->dbbufsz;		if ((p = realloc(dbproc->dbbuf, newsz)) == NULL) {			dbperror(NULL, SYBEMEM, errno);			return FAIL;		}		dbproc->dbbuf = (unsigned char *) p;		strcat((char *) dbproc->dbbuf, cmdstring);		dbproc->dbbufsz = newsz;	}	dbproc->command_state = DBCMDPEND;	return SUCCEED;}/** * \ingroup dblib_core * \brief send the SQL command to the server and wait for an answer.   *  * Please be patient.  This function waits for the server to respond.   \c dbsqlexec is equivalent * to dbsqlsend() followed by dbsqlok().  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \retval SUCCEED query was processed without errors. * \retval FAIL was returned by dbsqlsend() or dbsqlok(). * \sa dbcmd(), dbfcmd(), dbnextrow(), dbresults(), dbretstatus(), dbsettime(), dbsqlok(), dbsqlsend() */RETCODEdbsqlexec(DBPROCESS * dbproc){	RETCODE rc = FAIL;	tdsdump_log(TDS_DBG_FUNC, "dbsqlexec(%p)\n", dbproc);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	if (SUCCEED == (rc = dbsqlsend(dbproc))) {		rc = dbsqlok(dbproc);	}	return rc;}/** * \ingroup dblib_core * \brief Change current database.  *  * Analagous to the unix command \c cd, dbuse() makes \a name the default database.  Waits for an answer * from the server.   * \param dbproc contains all information needed by db-lib to manage communications with the server. * \param name database to use. * \retval SUCCEED query was processed without errors. * \retval FAIL query was not processed * \todo \a name should be quoted. * \sa dbchange(), dbname(). */RETCODEdbuse(DBPROCESS * dbproc, const char *name){	RETCODE rc;	char *query;	tdsdump_log(TDS_DBG_FUNC, "dbuse(%p, %s)\n", dbproc, name);	CHECK_DBPROC();	DBPERROR_RETURN(IS_TDSDEAD(dbproc->tds_socket), SYBEDDNE);	CHECK_NULP(name, "dbuse", 2, FAIL);	if (!dbproc->tds_socket)		return FAIL;	/* quote name */	query = malloc(tds_quote_id(dbproc->tds_socket, NULL, name, -1) + 6);	if (!query) {		dbperror(NULL, SYBEMEM, errno);		return FAIL;	}	strcpy(query, "use ");	/* TODO PHP suggest to quote by yourself with []... what should I do ?? quote or not ?? */	if (name[0] == '[' && name[strlen(name)-1] == ']')		strcat(query, name);	else		tds_quote_id(dbproc->tds_socket, query + 4, name, -1);	rc = SUCCEED;	if ((dbcmd(dbproc, query) == FAIL)	    || (dbsqlexec(dbproc) == FAIL)	    || (dbresults(dbproc) == FAIL)	    || (dbcanquery(dbproc) == FAIL))		rc = FAIL;	free(query);	return rc;}/** * \ingroup dblib_core * \brief Close a connection to the server and free associated resources.   *  * \param dbproc contains all information needed by db-lib to manage communications with the server. * \sa dbexit(), dbopen(). */voiddbclose(DBPROCESS * dbproc){	TDSSOCKET *tds;	int i;	char timestr[256];	tdsdump_log(TDS_DBG_FUNC, "dbclose(%p)\n", dbproc);		CHECK_PARAMETER(dbproc, SYBENULL, );	tds = dbproc->tds_socket;	if (tds) {		/* 		 * this MUST be done before socket destruction		 * it is possible that a TDSSOCKET is allocated on same position		 */		TDS_MUTEX_LOCK(&dblib_mutex);		dblib_del_connection(&g_dblib_ctx, dbproc->tds_socket);		TDS_MUTEX_UNLOCK(&dblib_mutex);		tds_free_socket(tds);		dblib_release_tds_ctx(1);	}	buffer_free(&(dbproc->row_buf));	if (dbproc->ftos != NULL) {		fprintf(dbproc->ftos, "/* dbclose() at %s */\n", _dbprdate(timestr));		fclose(dbproc->ftos);	}	if (dbproc->bcpinfo)		free(dbproc->bcpinfo->tablename);	if (dbproc->hostfileinfo) {		free(dbproc->hostfileinfo->hostfile);		free(dbproc->hostfileinfo->errorfile);		if (dbproc->hostfileinfo->host_columns) {			for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {				free(dbproc->hostfileinfo->host_columns[i]->terminator);				free(dbproc->hostfileinfo->host_columns[i]);			}			free(dbproc->hostfileinfo->host_columns);		}	}	for (i = 0; i < DBNUMOPTIONS; i++) {		dbstring_free(&(dbproc->dbopts[i].param));	}	free(dbproc->dbopts);	dbstring_free(&(dbproc->dboptcmd));	for (i=0; i < MAXBINDTYPES; i++) {		if (dbproc->nullreps[i].bindval != default_null_representations[i].bindval)			free((BYTE*)dbproc->nullreps[i].bindval);	}	dbfreebuf(dbproc);	free(dbproc);	return;}/** * \ingroup dblib_core * \brief Close server connections and free all related structures.   *  * \sa dbclose(), dbinit(), dbopen(). * \todo breaks if ctlib/dblib used in same process. */voiddbexit(){	TDSSOCKET *tds;	DBPROCESS *dbproc;	int i, list_size;	int count = 1;	tdsdump_log(TDS_DBG_FUNC, "dbexit(void)\n");	TDS_MUTEX_LOCK(&dblib_mutex);	if (--g_dblib_ctx.ref_count != 0) {		TDS_MUTEX_UNLOCK(&dblib_mutex);		return;	}	list_size = g_dblib_ctx.connection_list_size;	for (i = 0; i < list_size; i++) {		tds = g_dblib_ctx.connection_list[i];		g_dblib_ctx.connection_list[i] = NULL;		if (tds) {			++count;			dbproc = (DBPROCESS *) tds->parent;			tds_free_socket(tds);			if (dbproc) {				/* avoid locking in dbclose */				dbproc->tds_socket = NULL;				dbclose(dbproc);			}		}	}	if (g_dblib_ctx.connection_list) {		TDS_ZERO_FREE(g_dblib_ctx.connection_list);		g_dblib_ctx.connection_list_size = 0;	}

⌨️ 快捷键说明

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