#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <mysql.h>

#define MY_HOST "localhost"
#define MY_USER	"root"
#define MY_PASS	"root"
#define MY_DB	"test"

int bail(MYSQL *mysql, MYSQL_STMT *stmt, char* msg);

int main(void)
{
	MYSQL *mysql = mysql_init(NULL);
	MYSQL_STMT *stmt;
	MYSQL_BIND bind[2];
	my_ulonglong	query_insert1, query_insert2, query_update1;
	my_ulonglong	stmt_insert1, stmt_insert2, stmt_update1;
	const char insert[] = "INSERT INTO test(id, label) VALUES (?, ?)";
	int id;
	char label[2];
	unsigned long label_len;

	if (mysql_server_init(-1, NULL, NULL))
		return EXIT_FAILURE;

	printf("\n\nStarting ...\n\n");

    if (!mysql_real_connect(mysql, MY_HOST, MY_USER, MY_PASS, MY_DB, 0, NULL, 0))
		return bail(mysql, NULL, "Cannot connect");

	printf("... mysql_get_client_info() = %s\n", mysql_get_client_info());
	printf("... mysql_get_client_version() = %d\n", (int)mysql_get_client_version());
	printf("... mysql_get_server_info() = %s\n", mysql_get_server_info(mysql));
	printf("... mysql_get_server_version() = %d\n", (int)mysql_get_server_version(mysql));
	printf("... mysql_get_host_info() = %s\n", mysql_get_host_info(mysql));
	printf("... mysql_get_proto_info() = %d\n", mysql_get_proto_info(mysql));
	printf("\n");

	if (mysql_query(mysql, "DROP TABLE IF EXISTS test"))
		return bail(mysql, NULL, "Cannot drop test table");

	if (mysql_query(mysql, 	"CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, "
							"label VARCHAR(32), "
							"PRIMARY KEY(id))"))
		return bail(mysql, NULL, "Cannot create test table");

	if (mysql_query(mysql, "INSERT INTO test(id, label) VALUES (1, 'a')"))
		return bail(mysql, NULL, "mysql_query - INSERT 1");

	query_insert1 = mysql_affected_rows(mysql);
	mysql_query(mysql, "INSERT INTO test(id, label) VALUES (1, 'a')");
	query_insert2 = mysql_affected_rows(mysql);
	mysql_query(mysql, "UPDATE TEST SET label = 'b' WHERE id = 2");
	query_update1 = mysql_affected_rows(mysql);

	printf("... Test with mysql_affected_rows():\n"
		"...    INSERT OK = %d\n"
		"...    INSERT duplicate = %d\n"
		"...    UPDATE unknown = %d\n",
		((my_ulonglong)-1 == query_insert1) ? -1 : (int)query_insert1,
		((my_ulonglong)-1 == query_insert2) ? -1 : (int)query_insert2,
		((my_ulonglong)-1 == query_update1) ? -1 : (int)query_update1);

	if (mysql_query(mysql, "DROP TABLE IF EXISTS test"))
		return bail(mysql, NULL, "Cannot drop test table");

	if (mysql_query(mysql, 	"CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, "
							"label VARCHAR(32), "
							"PRIMARY KEY(id))"))
		return bail(mysql, NULL, "Cannot create test table");

	if (!(stmt = mysql_stmt_init(mysql)))
		return bail(mysql, NULL, "mysql_stmt_init() failed");

	if (mysql_stmt_prepare(stmt, insert, (unsigned long)strlen(insert)))
		return bail(mysql, stmt, "mysql_stmt_prepare() failed");

	if (mysql_stmt_param_count(stmt) != 2)
		return bail(mysql, stmt, "mysql_stmt_param_count() failed");

	memset(bind, 0, sizeof(bind));

	bind[0].buffer_type = MYSQL_TYPE_LONG;
	bind[0].buffer = (char *)&id;
	bind[0].is_null = (my_bool *)0;
	bind[0].length = 0;

	bind[1].buffer_type = MYSQL_TYPE_STRING;
	bind[1].buffer = (char *)label;
	bind[1].is_null = (my_bool*)0;
	bind[1].length = &label_len;

	if (mysql_stmt_bind_param(stmt, bind))
		return bail(mysql, stmt, "mysql_stmt_bind_param() failed");

	id = 1;
	strncpy(label, "a", 2);
	label_len = (unsigned long)strlen(label);
	if (mysql_stmt_execute(stmt))
		return bail(mysql, stmt, "mysql_stmt_execute - INSERT 1");

	stmt_insert1 = mysql_stmt_affected_rows(stmt);
	mysql_stmt_execute(stmt);
	stmt_insert2 = mysql_stmt_affected_rows(stmt);

	id = 2;
	strncpy(label, "b", 2);
	label_len = (unsigned long)strlen(label);
	mysql_stmt_execute(stmt);
	stmt_update1 = mysql_stmt_affected_rows(stmt);

	mysql_stmt_close(stmt);

	printf("... Test with mysql_stmt_affected_rows():\n"
		"...    INSERT OK = %d\n"
		"...    INSERT duplicate = %d\n"
		"...    UPDATE unknown = %d\n",
		((my_ulonglong)-1 == stmt_insert1) ? -1 : (int)stmt_insert1,
		((my_ulonglong)-1 == stmt_insert2) ? -1 : (int)stmt_insert2,
		((my_ulonglong)-1 == stmt_update1) ? -1 : (int)stmt_update1);

	mysql_close(mysql);
	mysql_server_end();

	printf("\n\nDone!\n\n");

	return EXIT_SUCCESS;
}

int bail(MYSQL *mysql, MYSQL_STMT *stmt, char *msg) {

	printf("\n\n%s\n", msg);

	if (stmt) {
		printf("[%d] %s\n\n", mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
		mysql_stmt_close(stmt);
		mysql_close(mysql);
	} else {
		printf("[%d] %s\n\n", mysql_errno(mysql), mysql_error(mysql));
		mysql_close(mysql);
	}

	return EXIT_FAILURE;
}
