コード例 #1
0
ファイル: transaction2.c プロジェクト: RQZeng/freetds
static int
CheckDirtyRead(void)
{
	SQLRETURN RetCode;

	/* transaction 1 try to change a row but not commit */
	odbc_command("UPDATE test_transaction SET t = 'second' WHERE n = 1");

	SWAP_CONN();

	/* second transaction try to fetch uncommited row */
	RetCode = odbc_command2("SELECT * FROM test_transaction WHERE t = 'second' AND n = 1", "SE");
	if (RetCode == SQL_ERROR) {
		EndTransaction(SQL_ROLLBACK);
		SWAP_CONN();
		EndTransaction(SQL_ROLLBACK);
		return 0;	/* no dirty read */
	}

	CHKFetch("S");
	CHKFetch("No");
	SQLMoreResults(odbc_stmt);
	EndTransaction(SQL_ROLLBACK);
	SWAP_CONN();
	EndTransaction(SQL_ROLLBACK);
	return 1;
}
コード例 #2
0
ファイル: lang_error.c プロジェクト: DavidRueter/freetds
int
main(int argc, char *argv[])
{
	odbc_connect();

	/* issue print statement and test message returned */
	odbc_command2("SELECT DATEADD(dd,-100000,getdate())", "E");

	odbc_disconnect();

	printf("Done.\n");
	return 0;
}
コード例 #3
0
ファイル: cancel.c プロジェクト: angcoch/freetds
static void
Test(int use_threads, int return_data)
{
	tds_thread wait_thread;

#if !HAVE_ALARM
	if (!use_threads) return;
#endif

	printf("testing with %s\n", use_threads ? "threads" : "signals");
	printf(">> Wait 5 minutes...\n");
	if (!use_threads) {
		alarm(4);
		signal(SIGALRM, sigalrm_handler);
	} else {
		int err;

		exit_thread = 0;
		err = tds_thread_create(&wait_thread, wait_thread_proc, NULL);
		if (err != 0) {
			perror("tds_thread_create");
			exit(1);
		}
	}
	if (!return_data)
		CHKExecDirect(T("WAITFOR DELAY '000:05:00'"), SQL_NTS, "E");
	else
		odbc_command2("SELECT MAX(p1.k) FROM tab1 p1, tab1 p2, tab1 p3, tab1 p4", "E");

	tds_mutex_lock(&mtx);
	exit_thread = 1;
	tds_mutex_unlock(&mtx);
	if (!use_threads) {
		alarm(0);
	} else {
		tds_thread_join(wait_thread, NULL);
	}
	getErrorInfo(SQL_HANDLE_STMT, odbc_stmt);
	if (strcmp(C(sqlstate), "HY008") != 0) {
		fprintf(stderr, "Unexpected sql state returned\n");
		odbc_disconnect();
		exit(1);
	}

	odbc_reset_statement();

	odbc_command("SELECT name FROM sysobjects WHERE 0=1");
}
コード例 #4
0
ファイル: data.c プロジェクト: DavidRueter/freetds
static void
Test(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, const char *expected)
{
	char sbuf[1024];
	unsigned char out_buf[256];
	SQLLEN out_len = 0;

	SQLFreeStmt(odbc_stmt, SQL_UNBIND);
	SQLFreeStmt(odbc_stmt, SQL_RESET_PARAMS);

	/* execute a select to get data as wire */
	sprintf(sbuf, "SELECT CONVERT(%s, '%s') AS data", type, value_to_convert);
	if (strncmp(value_to_convert, "0x", 2) == 0)
		sprintf(sbuf, "SELECT CONVERT(%s, %s) COLLATE Latin1_General_CI_AS AS data", type, value_to_convert);
	else if (strcmp(type, "SQL_VARIANT") == 0)
		sprintf(sbuf, "SELECT CONVERT(SQL_VARIANT, %s) AS data", value_to_convert);
	else if (strncmp(value_to_convert, "u&'", 3) == 0)
		sprintf(sbuf, "SELECT CONVERT(%s, %s) AS data", type, value_to_convert);
	if (ignore_select_error) {
		if (odbc_command2(sbuf, "SENo") == SQL_ERROR) {
			odbc_reset_statement();
			ignore_select_error = 0;
			ignore_result = 0;
			return;
		}
	} else {
		odbc_command(sbuf);
	}
	SQLBindCol(odbc_stmt, 1, out_c_type, out_buf, sizeof(out_buf), &out_len);
	CHKFetch("S");
	CHKFetch("No");
	CHKMoreResults("No");

	/* test results */
	odbc_c2string(sbuf, out_c_type, out_buf, out_len);

	if (!ignore_result && strcmp(sbuf, expected) != 0) {
		fprintf(stderr, "Wrong result\n  Got:      %s\n  Expected: %s\n", sbuf, expected);
		result = 1;
	}
	ignore_select_error = 0;
	ignore_result = 0;
}
コード例 #5
0
ファイル: transaction2.c プロジェクト: RQZeng/freetds
static int
CheckPhantom(void)
{
	SQLRETURN RetCode;

	/* transaction 2 read a row */
	SWAP_CONN();
	odbc_command("SELECT * FROM test_transaction WHERE t = 'initial'");
	SQLMoreResults(odbc_stmt);

	/* transaction 1 insert a row that match critera */
	SWAP_CONN();
	RetCode = odbc_command2("INSERT INTO test_transaction(n, t) VALUES(2, 'initial')", "SE");
	if (RetCode == SQL_ERROR) {
		EndTransaction(SQL_ROLLBACK);
		SWAP_CONN();
		EndTransaction(SQL_ROLLBACK);
		SWAP_CONN();
		return 0;	/* no dirty read */
	}
	EndTransaction(SQL_COMMIT);

	SWAP_CONN();

	/* second transaction try to fetch commited row */
	odbc_command("SELECT * FROM test_transaction WHERE t = 'initial'");

	CHKFetch("S");
	CHKFetch("S");
	CHKFetch("No");
	SQLMoreResults(odbc_stmt);
	EndTransaction(SQL_ROLLBACK);
	SWAP_CONN();
	odbc_command("DELETE test_transaction WHERE n = 2");
	EndTransaction(SQL_COMMIT);
	return 1;
}
コード例 #6
0
ファイル: transaction2.c プロジェクト: RQZeng/freetds
static int
CheckNonrepeatableRead(void)
{
	SQLRETURN RetCode;

	/* transaction 2 read a row */
	SWAP_CONN();
	odbc_command("SELECT * FROM test_transaction WHERE t = 'initial' AND n = 1");
	SQLMoreResults(odbc_stmt);

	/* transaction 1 change a row and commit */
	SWAP_CONN();
	RetCode = odbc_command2("UPDATE test_transaction SET t = 'second' WHERE n = 1", "SE");
	if (RetCode == SQL_ERROR) {
		EndTransaction(SQL_ROLLBACK);
		SWAP_CONN();
		EndTransaction(SQL_ROLLBACK);
		SWAP_CONN();
		return 0;	/* no dirty read */
	}
	EndTransaction(SQL_COMMIT);

	SWAP_CONN();

	/* second transaction try to fetch commited row */
	odbc_command("SELECT * FROM test_transaction WHERE t = 'second' AND n = 1");

	CHKFetch("S");
	CHKFetch("No");
	SQLMoreResults(odbc_stmt);
	EndTransaction(SQL_ROLLBACK);
	SWAP_CONN();
	odbc_command("UPDATE test_transaction SET t = 'initial' WHERE n = 1");
	EndTransaction(SQL_COMMIT);
	return 1;
}
コード例 #7
0
ファイル: getdata.c プロジェクト: angcoch/freetds
int
main(int argc, char *argv[])
{
	char buf[32];
	SQLINTEGER int_buf;
	SQLLEN len;
	SQLRETURN rc;

	odbc_connect();

	lc = 1;
	type = SQL_C_CHAR;
	test_split("");

	lc = sizeof(SQLWCHAR);
	type = SQL_C_WCHAR;
	test_split("");

	if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x07000000u) {
		lc = 1;
		type = SQL_C_CHAR;
		test_split("N");

		lc = sizeof(SQLWCHAR);
		type = SQL_C_WCHAR;
		test_split("N");
	}

	/* test with fixed length */
	odbc_command("SELECT CONVERT(INT, 12345)");

	CHKFetch("S");

	int_buf = 0xdeadbeef;
	CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "S");
	if (int_buf != 12345) {
		printf("Wrong data result\n");
		exit(1);
	}

	CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "No");
	if (int_buf != 12345) {
		printf("Wrong data result 2 res = %d\n", (int) int_buf);
		exit(1);
	}

	odbc_reset_statement();

	/* test with numeric */
	odbc_command("SELECT CONVERT(NUMERIC(18,5), 1850000000000)");

	CHKFetch("S");

	memset(buf, 'x', sizeof(buf));
	CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "S");
	buf[sizeof(buf)-1] = 0;
	if (strcmp(buf, "1850000000000") != 0) {
		printf("Wrong data result: %s\n", buf);
		exit(1);
	}

	/* should give NO DATA */
	CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "No");
	buf[sizeof(buf)-1] = 0;
	if (strcmp(buf, "1850000000000") != 0) {
		printf("Wrong data result 3 res = %s\n", buf);
		exit(1);
	}

	odbc_reset_statement();


	/* test int to truncated string */
	odbc_command("SELECT CONVERT(INTEGER, 12345)");
	CHKFetch("S");

	/* error 22003 */
	memset(buf, 'x', sizeof(buf));
	CHKGetData(1, SQL_C_CHAR, buf, 4, NULL, "E");
#ifdef ENABLE_DEVELOPING
	buf[4] = 0;
	if (strcmp(buf, "xxxx") != 0) {
		fprintf(stderr, "Wrong buffer result buf = %s\n", buf);
		exit(1);
	}
#endif
	odbc_read_error();
	if (strcmp(odbc_sqlstate, "22003") != 0) {
		fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
		odbc_disconnect();
		exit(1);
	}
	CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No");
	odbc_reset_statement();

	/* test unique identifier to truncated string */
	rc = odbc_command2("SELECT CONVERT(UNIQUEIDENTIFIER, 'AA7DF450-F119-11CD-8465-00AA00425D90')", "SENo");
	if (rc != SQL_ERROR) {
		CHKFetch("S");

		/* error 22003 */
		CHKGetData(1, SQL_C_CHAR, buf, 17, NULL, "E");
		odbc_read_error();
		if (strcmp(odbc_sqlstate, "22003") != 0) {
			fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
			odbc_disconnect();
			exit(1);
		}
		CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No");
	}
	odbc_reset_statement();


	odbc_disconnect();

	odbc_use_version3 = 1;
	odbc_connect();

	/* test error from SQLGetData */
	/* wrong constant, SQL_VARCHAR is invalid as C type */
	test_err("prova 123",           SQL_VARCHAR,     "HY003");
	/* use ARD but no ARD data column */
	test_err("prova 123",           SQL_ARD_TYPE,    "07009");
	/* wrong conversion, int */
	test_err("prova 123",           SQL_C_LONG,      "22018");
	/* wrong conversion, date */
	test_err("prova 123",           SQL_C_TIMESTAMP, "22018");
	/* overflow */
	test_err("1234567890123456789", SQL_C_LONG,      "22003");

	/* test for empty string from mssql */
	if (odbc_db_is_microsoft()) {
		lc = 1;
		type = SQL_C_CHAR;

		for (;;) {
			void *buf = ODBC_GET(lc);

			odbc_command("SELECT CONVERT(TEXT,'')");

			CHKFetch("S");

			len = 1234;
			CHKGetData(1, type, buf, lc, &len, "S");

			if (len != 0) {
				fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
				return 1;
			}

			CHKGetData(1, type, buf, lc, NULL, "No");
			odbc_reset_statement();
			ODBC_FREE();

			buf = ODBC_GET(4096*lc);

			odbc_command("SELECT CONVERT(TEXT,'')");

			CHKFetch("S");

			len = 1234;
			CHKGetData(1, type, buf, lc*4096, &len, "S");

			if (len != 0) {
				fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
				return 1;
			}

			CHKGetData(1, type, buf, lc*4096, NULL, "No");
			odbc_reset_statement();
			ODBC_FREE();

			if (type != SQL_C_CHAR)
				break;
			lc = sizeof(SQLWCHAR);
			type = SQL_C_WCHAR;
		}	

		odbc_command("SELECT CONVERT(TEXT,'')");

		CHKFetch("S");

		len = 1234;
		CHKGetData(1, SQL_C_BINARY, buf, 1, &len, "S");

		if (len != 0) {
			fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
			return 1;
		}

		CHKGetData(1, SQL_C_BINARY, buf, 1, NULL, "No");
	}

	odbc_disconnect();

	printf("Done.\n");
	return 0;
}
コード例 #8
0
ファイル: print.c プロジェクト: DmitrySigaev/ncbi
static int
test(int odbc3)
{
	SQLLEN cnamesize;
	const char *query;

	odbc_use_version3 = odbc3;

	odbc_connect();

	/* issue print statement and test message returned */
	output[0] = 0;
	query = "print 'START' select count(*) from sysobjects where name='sysobjects' print 'END'";
	odbc_command2(query, "I");
	odbc_read_error();
	if (!strstr(odbc_err, "START")) {
		printf("Message invalid\n");
		return 1;
	}
	odbc_err[0] = 0;

	if (odbc3) {
		ODBC_CHECK_COLS(0);
		ODBC_CHECK_ROWS(-1);
		CHKFetch("E");
		CHKMoreResults("S");
	}
    
	ODBC_CHECK_COLS(1);
	ODBC_CHECK_ROWS(-1);

	CHKFetch("S");
	ODBC_CHECK_COLS(1);
	ODBC_CHECK_ROWS(-1);
	/* check no data */
	CHKFetch("No");
	ODBC_CHECK_COLS(1);
	ODBC_CHECK_ROWS(1);

	/* SQLMoreResults return NO DATA or SUCCESS WITH INFO ... */
	if (tds_no_dm && !odbc3)
		CHKMoreResults("No");
	else if (odbc3)
		CHKMoreResults("I");
	else
		CHKMoreResults("INo");

	/*
	 * ... but read error
	 * (unixODBC till 2.2.11 do not read errors on NO DATA, skip test)
	 */
	if (tds_no_dm || odbc3) {
		odbc_read_error();
		if (!strstr(odbc_err, "END")) {
			printf("Message invalid\n");
			return 1;
		}
		odbc_err[0] = 0;
	}

	if (odbc3) {
		ODBC_CHECK_COLS(0);
		ODBC_CHECK_ROWS(-1);

		CHKMoreResults("No");
	}

	/* issue invalid command and test error */
	odbc_command2("SELECT donotexistsfield FROM donotexiststable", "E");
	odbc_read_error();

	/* test no data returned */
	CHKFetch("E");
	odbc_read_error();

	CHKGetData(1, SQL_C_CHAR, output, sizeof(output), &cnamesize, "E");
	odbc_read_error();

	odbc_disconnect();

	return 0;
}
コード例 #9
0
ファイル: mars1.c プロジェクト: DmitrySigaev/ncbi
int
main(int argc, char *argv[])
{
	SQLINTEGER len, out;
	int i;
	SQLHSTMT stmt1, stmt2;
	SQLHSTMT *pcur_stmt = NULL;

	odbc_use_version3 = 1;
	odbc_set_conn_attr = my_attrs;
	odbc_connect();

	stmt1 = odbc_stmt;

	out = 0;
	len = sizeof(out);
	CHKGetConnectAttr(1224, (SQLPOINTER) &out, sizeof(out), &len, "S");

	/* test we really support MARS on this connection */
	/* TODO should out be correct ?? */
	printf("Following row can contain an error due to MARS detection (is expected)\n");
	if (!out || odbc_command2("BEGIN TRANSACTION", "SNoE") != SQL_ERROR) {
		printf("MARS not supported for this connection\n");
		odbc_disconnect();
		odbc_test_skipped();
		return 0;
	}
	odbc_read_error();
	if (!strstr(odbc_err, "MARS")) {
		printf("Error message invalid \"%s\"\n", odbc_err);
		return 1;
	}

	/* create a test table with some data */
	odbc_command("create table #mars1 (n int, v varchar(100))");
	for (i = 0; i < 60; ++i) {
		char cmd[120], buf[80];
		memset(buf, 'a' + (i % 26), sizeof(buf));
		buf[i * 7 % 73] = 0;
		sprintf(cmd, "insert into #mars1 values(%d, '%s')", i, buf);
		odbc_command(cmd);
	}

	/* and another to avid locking problems */
	odbc_command("create table #mars2 (n int, v varchar(100))");

	AutoCommit(SQL_AUTOCOMMIT_OFF);

	/* try to do a select which return a lot of data (to test server didn't cache everything) */
	odbc_command("select a.n, b.n, a.v from #mars1 a, #mars1 b order by a.n, b.n");
	CHKFetch("S");

	/* try to do other commands */
	CHKAllocStmt(&stmt2, "S");
	SET_STMT(stmt2);
	odbc_command("insert into #mars2 values(1, 'foo')");
	SET_STMT(stmt1);

	CHKFetch("S");

	/* reset statements */
	odbc_reset_statement();
	SET_STMT(stmt2);
	odbc_reset_statement();

	/* now to 2 select with prepare/execute */
	CHKPrepare(T("select a.n, b.n, a.v from #mars1 a, #mars1 b order by a.n, b.n"), SQL_NTS, "S");
	SET_STMT(stmt1);
	CHKPrepare(T("select a.n, b.n, a.v from #mars1 a, #mars1 b order by a.n desc, b.n"), SQL_NTS, "S");
	SET_STMT(stmt2);
	CHKExecute("S");
	SET_STMT(stmt1);
	CHKExecute("S");
	SET_STMT(stmt2);
	CHKFetch("S");
	SET_STMT(stmt1);
	CHKFetch("S");
	SET_STMT(stmt2);
	CHKFetch("S");
	odbc_reset_statement();
	SET_STMT(stmt1);
	CHKFetch("S");
	odbc_reset_statement();

	EndTransaction(SQL_COMMIT);

	/* TODO test receiving large data should not take much memory */

	odbc_disconnect();
	return 0;
}
コード例 #10
0
ファイル: data.c プロジェクト: smalinin/FreeTDS
static void
Test(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, const char *expected)
{
	unsigned char out_buf[256];
	SQLLEN out_len = 0;
	SQL_NUMERIC_STRUCT *num;
	SQLWCHAR *wp;
	int i;

	SQLFreeStmt(odbc_stmt, SQL_UNBIND);
	SQLFreeStmt(odbc_stmt, SQL_RESET_PARAMS);

	/* execute a select to get data as wire */
	sprintf(sbuf, "SELECT CONVERT(%s, '%s') AS data", type, value_to_convert);
	if (strncmp(value_to_convert, "0x", 2) == 0)
		sprintf(sbuf, "SELECT CONVERT(%s, %s) COLLATE Latin1_General_CI_AS AS data", type, value_to_convert);
	else if (strcmp(type, "SQL_VARIANT") == 0)
		sprintf(sbuf, "SELECT CONVERT(SQL_VARIANT, %s) AS data", value_to_convert);
	else if (strncmp(value_to_convert, "u&'", 3) == 0)
		sprintf(sbuf, "SELECT CONVERT(%s, %s) AS data", type, value_to_convert);
	if (ignore_select_error) {
		if (odbc_command2(sbuf, "SENo") == SQL_ERROR) {
			odbc_reset_statement();
			return;
		}
	} else {
		odbc_command(sbuf);
	}
	ignore_select_error = 0;
	SQLBindCol(odbc_stmt, 1, out_c_type, out_buf, sizeof(out_buf), &out_len);
	CHKFetch("S");
	CHKFetch("No");
	CHKMoreResults("No");

	/* test results */
	sbuf[0] = 0;
	switch (out_c_type) {
	case SQL_C_NUMERIC:
		num = (SQL_NUMERIC_STRUCT *) out_buf;
		sprintf(sbuf, "%d %d %d ", num->precision, num->scale, num->sign);
		i = SQL_MAX_NUMERIC_LEN;
		for (; i > 0 && !num->val[--i];);
		for (; i >= 0; --i)
			sprintf(strchr(sbuf, 0), "%02X", num->val[i]);
		break;
	case SQL_C_BINARY:
		assert(out_len >= 0);
		for (i = 0; i < out_len; ++i)
			sprintf(strchr(sbuf, 0), "%02X", (int) out_buf[i]);
		break;
	case SQL_C_CHAR:
		out_buf[sizeof(out_buf) - 1] = 0;
		sprintf(sbuf,"%u %s", (unsigned int) strlen((char *) out_buf), out_buf);
		break;
	case SQL_C_WCHAR:
		assert(out_len >=0 && (out_len % sizeof(SQLWCHAR)) == 0);
		sprintf(sbuf, "%u ", (unsigned int) (out_len / sizeof(SQLWCHAR)));
		wp = (SQLWCHAR*) out_buf;
		for (i = 0; i < out_len / sizeof(SQLWCHAR); ++i)
			if ((unsigned int) wp[i] < 256)
				sprintf(strchr(sbuf, 0), "%c", (char) wp[i]);
			else
				sprintf(strchr(sbuf, 0), "\\u%04x", (unsigned int) wp[i]);
		break;
	case SQL_C_LONG:
		assert(out_len == sizeof(SQLINTEGER));
		sprintf(sbuf, "%ld", (long int) *((SQLINTEGER *) out_buf));
		break;
	default:
		/* not supported */
		assert(0);
		break;
	}

	if (strcmp(sbuf, expected) != 0) {
		fprintf(stderr, "Wrong result\n  Got:      %s\n  Expected: %s\n", sbuf, expected);
		result = 1;
	}
}
コード例 #11
0
ファイル: data.c プロジェクト: DavidRueter/freetds
int
main(int argc, char *argv[])
{
	int cond = 1;

#define TEST_FILE "data.in"
	const char *in_file = FREETDS_SRCDIR "/" TEST_FILE;
	FILE *f;

	odbc_connect();

	odbc_init_bools();

	f = fopen(in_file, "r");
	if (!f)
		f = fopen(TEST_FILE, "r");
	if (!f) {
		fprintf(stderr, "error opening test file\n");
		exit(1);
	}

	odbc_init_parser(f);
	for (;;) {
		char *p;
		const char *cmd = odbc_get_cmd_line(&p, &cond);

		if (!cmd)
			break;

		/* select type */
		if (!strcmp(cmd, "select")) {
			const char *type = odbc_get_tok(&p);
			const char *value = odbc_get_str(&p);
			int c_type = lookup(odbc_get_tok(&p), sql_c_types);
			const char *expected = odbc_get_str(&p);

			if (!cond) continue;

			ignore_select_error = 1;
			Test(type, value, c_type, expected);
			continue;
		}
		/* select type setting condition */
		if (!strcmp(cmd, "select_cond")) {
			const char *bool_name = odbc_get_tok(&p);
			const char *type = odbc_get_tok(&p);
			const char *value = odbc_get_str(&p);
			int c_type = lookup(odbc_get_tok(&p), sql_c_types);
			const char *expected = odbc_get_str(&p);
			int save_result = result;

			if (!bool_name) odbc_fatal(": no condition name\n");
			if (!cond) continue;

			ignore_select_error = 1;
			ignore_result = 1;
			result = 0;
			Test(type, value, c_type, expected);
			odbc_set_bool(bool_name, result == 0);
			result = save_result;
			continue;
		}
		/* execute a sql command */
		if (!strcmp(cmd, "sql")) {
			const char *sql = odbc_get_str(&p);

			if (!cond) continue;

			odbc_command(sql);
			continue;
		}
		if (!strcmp(cmd, "sql_cond")) {
			const char *bool_name = odbc_get_tok(&p);
			const char *sql = odbc_get_str(&p);

			if (!cond) continue;

			odbc_set_bool(bool_name, odbc_command2(sql, "SENo") != SQL_ERROR);
			continue;
		}
		odbc_fatal(": unknown command\n");
	}
	odbc_clear_bools();
	fclose(f);

	printf("\n");

	odbc_disconnect();

	if (!result)
		printf("Done successfully!\n");
	return result;
}