예제 #1
0
파일: seaf-db.c 프로젝트: WeiY/seafile
gboolean
seaf_db_trans_check_for_existence (SeafDBTrans *trans,
                                   const char *sql,
                                   gboolean *db_err)
{
    ResultSet_T result;
    gboolean ret = TRUE;

    *db_err = FALSE;

    TRY
        result = Connection_executeQuery (trans->conn, "%s", sql);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        *db_err = TRUE;
        return FALSE;
    END_TRY;

    TRY
        if (!ResultSet_next (result))
            ret = FALSE;
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        *db_err = TRUE;
        return FALSE;
    END_TRY;

    return ret;
}
예제 #2
0
int RuleInit::get_mod_from_db(Connection_T conn , RULE_TYPE type)
{
    std::string get_mod_sql;

    get_mod_sql = ext_info_prefix + DBP->get_order_table_name(type)
            + " where command = \"" EXTENSION_COMMAND + "\"" + ext_info_mid;

    ResultSet_T rets = NULL;
    int rows = 0;
    if(!(rets = DBP->execute_query(conn , get_mod_sql))) 
    {
        LOG_ERROR("RuleInit::get current mod from database error : " + get_mod_sql);
        return -1;
    }
    if(!ResultSet_next(rets))
    {
        LOG_EVENT("RuleInit::Extent infomation empty !");
        return 0;
    }
    if((rows = DBP->get_int_result(rets , 1)) < 0)
    {
        LOG_ERROR("RuleInit::get Extent infomation result error !");
        return -1;
    }

    return rows;
}
예제 #3
0
파일: seaf-db.c 프로젝트: WeiY/seafile
int
seaf_db_trans_foreach_selected_row (SeafDBTrans *trans, const char *sql, 
                              SeafDBRowFunc callback, void *data)
{
    ResultSet_T result;
    SeafDBRow seaf_row;
    int n_rows = 0;

    TRY
        result = Connection_executeQuery (trans->conn, "%s", sql);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        return -1;
    END_TRY;

    seaf_row.res = result;
    TRY
    while (ResultSet_next (result)) {
        n_rows++;
        if (!callback (&seaf_row, data))
            break;
    }
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        return -1;
    END_TRY;

    return n_rows;
}
예제 #4
0
파일: seaf-db.c 프로젝트: WeiY/seafile
gint64
seaf_db_get_int64 (SeafDB *db, const char *sql)
{
    gint64 ret = -1;
    Connection_T conn;
    ResultSet_T result;
    SeafDBRow seaf_row;

    conn = get_db_connection (db);
    if (!conn)
        return -1;

    TRY
        result = Connection_executeQuery (conn, "%s", sql);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return -1;
    END_TRY;

    seaf_row.res = result;

    TRY
        if (ResultSet_next (result))
            ret = seaf_db_row_get_column_int64 (&seaf_row, 0);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return -1;
    END_TRY;

    Connection_close (conn);
    return ret;
}
예제 #5
0
파일: ccnet-db.c 프로젝트: bvleur/ccnet
gboolean
ccnet_db_check_for_existence (CcnetDB *db, const char *sql)
{
    Connection_T conn;
    ResultSet_T result;
    gboolean ret = TRUE;

    conn = get_db_connection (db);
    if (!conn) {
        return FALSE;
    }

    TRY
        result = Connection_executeQuery (conn, "%s", sql);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return FALSE;
    END_TRY;

    TRY
        if (!ResultSet_next (result))
            ret = FALSE;
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return FALSE;
    END_TRY;

    Connection_close (conn);

    return ret;
}
예제 #6
0
/*==============================================================================
* Name	 :	int8 Client_init_acquire(DEVICE_INFO* device)
* Abstr	 :	Acquire ip address and port of the target db servers according to 
*			the protocol version of each device
* Params :	DEVICE_INFO* device : device information
* Return :	int8	  :
*			EXEC_SUCS : execute success
*			EXEC_FAIL : execute failed
* Modify :	
*=============================================================================*/
int8 Client_init_acquire(DEVICE_INFO* device)
{
	int8			err;
	cint8 			sql[SQL_TEXT_LEN];	/* sql text 		*/
	CONN_INFO*		conn;				/* temp connection 	*/
	ResultSet_T 	result;				/* query result 	*/

	err  = EXEC_SUCS;
	conn = NULL;
	result = NULL;
	memset(&sql[0], 0x00, SQL_TEXT_LEN);

	TRY {
		snprintf(&sql[0], SQL_TEXT_LEN, 
				 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
				 device->pt_ver);

		result = Connection_executeQuery(db_conn, &sql[0]);

		while ((ResultSet_next(result)) && (device->slv_num < SLV_NUM_MAX)) {
			conn = NULL;
			conn = &(device->s_conn[device->slv_num]);
			/* initialize device pointer */
			conn->dev = device;
			/* ip address */
			strncpy(&(conn->addr[0]), ResultSet_getString(result, 1), IP_ADDR_LEN);
			/* listen port */
			conn->port = (uint16)ResultSet_getInt(result, 2);
			/* connection name */
			snprintf(&(conn->name[0]), CONN_NM_LEN, "%s [%s:%d]", 
					 &(device->key_id[0]), &(conn->addr[0]), conn->port);
			/* prepare send data */
			memcpy (&conn->s_buf[0], &(device->d_conn.r_buf[0]), RECV_LEN_MAX);

			log_debug(log_cat, "%s: summon servant success", &conn->name[0]);

			device->slv_num++;
		}

		log_debug(log_cat, "%s: [servant num=%d]", &(device->key_id[0]), device->slv_num);
		
		(device->slv_num == 0) ? (err = EXEC_FAIL) : (err = EXEC_SUCS);

	} CATCH(SQLException) {
		log_fatal(log_cat, "%s: SQLException -> %s", &(device->key_id[0]), 
				  Exception_frame.message);
		err = EXEC_FAIL;
	} END_TRY;

	return err;
}
예제 #7
0
//查看当前数据库是否存在规则表的桶,如果存在说明已初始化,否则没有初始化!
bool RuleInit::system_if_initialized(Connection_T conn , RULE_TYPE type)
{
    std::string rule_sql = std::string(show_table_prefix) + "\"" + DBP->get_rule_table_name(type) + "\"";

    ResultSet_T ret = DBP->execute_query(conn , rule_sql);
    if(NULL == ret)
    {
        LOG_ERROR("RuleInit::execute query rule table error : " + rule_sql);
        return false;
    }
    
    //如果查询结果为空
    if(!ResultSet_next(ret))
        return false;
    else 
        return true;
}
예제 #8
0
int RuleInit::get_bucket_number(Connection_T conn , RULE_TYPE type)
{
    std::string get_rows_sql ;
    if(MU_RULER == type)
        get_rows_sql = rows_prefix + CSConfiguration::getInstance()->mu_rule_table;
    else
        get_rows_sql = rows_prefix + CSConfiguration::getInstance()->su_rule_table;

    ResultSet_T rets = NULL;
    int rows = 0;
    if((!(rets = DBP->execute_query(conn , get_rows_sql))) || (!ResultSet_next(rets)) 
            || ((rows = DBP->get_int_result(rets , 1)) < 0))
    {
        LOG_ERROR("RuleInit::get sum bucket number error : " + get_rows_sql);
        return -1;
    }

    return rows;    
}
예제 #9
0
파일: test.c 프로젝트: irr/c-labs
int main(void) {
    URL_T url = URL_new("sqlite:///tmp/test.db");

    ConnectionPool_T pool = ConnectionPool_new(url);
    ConnectionPool_start(pool);
    Connection_T con = ConnectionPool_getConnection(pool);

    TRY
    {
        Connection_execute(con, "create table bleach(name varchar(255))");
        PreparedStatement_T p = Connection_prepareStatement(con, "insert into bleach values (?)"); 
        const char *bleach[] = {
            "Ichigo Kurosaki", "Rukia Kuchiki", "Orihime Inoue",  "Yasutora \"Chad\" Sado", 
            "Kisuke Urahara", "Uryū Ishida", "Renji Abarai", 0
        };
        for (int i = 0; bleach[i]; i++) {
            PreparedStatement_setString(p, 1, bleach[i]);
            PreparedStatement_execute(p);
        }
        
        ResultSet_T r = Connection_executeQuery(con, "select name from bleach");
        while (ResultSet_next(r))
            printf("%s\n", ResultSet_getString(r, 1));
        
        Connection_execute(con, "drop table bleach;");
    }
    CATCH(SQLException)
    {
        printf("SQLException -- %s\n", Exception_frame.message);
    }
    FINALLY
    {
        Connection_close(con);
    }
    END_TRY;
    
    ConnectionPool_free(&pool);
    URL_free(&url);
        
    return 0;
}
예제 #10
0
파일: mysql-pool.c 프로젝트: hy0kl/study
int main(int argc, char *argv[])
{

    URL_T url = URL_new("mysql://127.0.0.1:3306/oauth2?user=dev&password=dev");
    ConnectionPool_T pool = ConnectionPool_new(url);
    ConnectionPool_start(pool);

    Connection_T con = ConnectionPool_getConnection(pool);

    TRY
    {
        ResultSet_T result = Connection_executeQuery(con,
            "SELECT access_token, client_id, user_id, expires FROM oauth_access_tokens");
        while (ResultSet_next(result))
        {
            const char *access_token = ResultSet_getStringByName(result, "access_token");
            printf("%s\t", access_token);

            const char *client_id = ResultSet_getStringByName(result, "client_id");
            printf("%s\t", client_id);

            printf("\n");
        }
    }
    CATCH(SQLException)
    {
        printf("SQLException -- %s\n", Exception_frame.message);
    }
    FINALLY
    {
        Connection_close(con);
    }
    END_TRY;

    ConnectionPool_free(&pool);
    URL_free(&url);

    return 0;
}
예제 #11
0
파일: seaf-db.c 프로젝트: WeiY/seafile
char *
seaf_db_get_string (SeafDB *db, const char *sql)
{
    char *ret = NULL;
    const char *s;
    Connection_T conn;
    ResultSet_T result;
    SeafDBRow seaf_row;

    conn = get_db_connection (db);
    if (!conn)
        return NULL;

    TRY
        result = Connection_executeQuery (conn, "%s", sql);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return NULL;
    END_TRY;

    seaf_row.res = result;
    
    TRY
        if (ResultSet_next (result)) {
            s = seaf_db_row_get_column_text (&seaf_row, 0);
            ret = g_strdup(s);
        }
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return NULL;
    END_TRY;

    Connection_close (conn);
    return ret;
}
예제 #12
0
파일: seaf-db.c 프로젝트: WeiY/seafile
int
seaf_db_foreach_selected_row (SeafDB *db, const char *sql, 
                              SeafDBRowFunc callback, void *data)
{
    Connection_T conn;
    ResultSet_T result;
    SeafDBRow seaf_row;
    int n_rows = 0;

    conn = get_db_connection (db);
    if (!conn)
        return -1;

    TRY
        result = Connection_executeQuery (conn, "%s", sql);
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return -1;
    END_TRY;

    seaf_row.res = result;
    TRY
        while (ResultSet_next (result)) {
            n_rows++;
            if (!callback (&seaf_row, data))
                break;
        }
    CATCH (SQLException)
        g_warning ("Error exec query %s: %s.\n", sql, Exception_frame.message);
        Connection_close (conn);
        return -1;
    END_TRY;

    Connection_close (conn);
    return n_rows;
}
예제 #13
0
int RuleInit::generate_all_order(Connection_T conn , RULE_TYPE type)
{
    std::string table_name = DBP->get_order_table_name(type);
    std::string order_sql = select_order_prefix + table_name;

    std::string cmd;
    std::string src_ip , dest_ip;
    int bucket , mod , version;

    ResultSet_T rets = DBP->execute_query(conn , order_sql);
    if(rets == NULL)
    {
        LOG_ERROR("RuleInit::execute query order table sql error : " + order_sql);
        return -1;
    }
    struct OrderRule order;
    int ver_n = 0;
    //循环查找每一个结果
    while(ResultSet_next(rets))
    {
        memset(&order , 0 , sizeof(order));
        if((version = DBP->get_int_result(rets , 1)) < 0)
        {
            LOG_ERROR("RuleInit::get 1 int result of order result error !");
            return -1;
        }
        if(DBP->get_string_result(rets , 2 , cmd) < 0)
        {
            LOG_ERROR("RuleInit::get 2 string result of order select result error !");
            return -1;
        }
        //如果是桶迁移需要将new_mod那一列当成迁移的桶号
        if(!cmd.compare(MIGRATION_COMMAND))
        {
            if(((bucket = DBP->get_int_result(rets , 3)) < 0) || 
                (DBP->get_string_result(rets , 4 , src_ip) < 0) || 
                (DBP->get_string_result(rets , 5 , dest_ip) < 0))
            {
                LOG_ERROR("RuleInit::get other result of migration info error !");
                return -1;
            }
            uint32_t ip_src , ip_dest;
            if((string_to_int_ip(src_ip , ip_src) < 0) || 
               (string_to_int_ip(dest_ip , ip_dest) < 0))
            {
                LOG_ERROR("RuleInit::change ip to string error : " + src_ip + " and " + dest_ip);
                return -1;
            }
            struct Migration_Info info;
            info.bucket_nr = bucket;
            info.src_ip = ip_src;
            info.dest_ip = ip_dest;
            order.cmd = MIGRATION;
            order.order.migration = info;
        }
        else if(!cmd.compare(EXTENSION_COMMAND))
        {
            if((mod = DBP->get_int_result(rets , 3)) < 0)
            {
                LOG_ERROR("RuleInit::get 3 mod result of order result error !");
                return -1;
            }
            struct Extent_Info info;
            info.new_mod = mod;
            order.cmd = EXTENT;
            order.order.extent = info;
        }
        else
        {
            LOG_ERROR("exit here !");
            exit(-1);
        }
        order.version = version;
        RulerManager::getInstance()->add_new_order_item(order , type);
        ++ ver_n;
    }
    RulerManager::getInstance()->set_current_version(type , ver_n);
    std::cerr<<(type == MU_RULER ? "MU " : "SU")<<"Current version "<<ver_n<<std::endl;

    return 0;
}
예제 #14
0
int RuleInit::generate_all_rule(Connection_T conn , RULE_TYPE type , int bucket_num)
{
//    int bucket_num = cs_pow(mod);
    std::string rule_table = DBP->get_rule_table_name(type);

    std::string select_sql = select_rule_prefix + rule_table + select_rule_mid;
    PreparedStatement_T pre = DBP->prepare_execute(conn , select_sql);
    if(NULL == pre)
    {
        LOG_ERROR("RuleInit::Prepare statement query sql error : " + select_sql);
        return -1;
    }

    ResultSet_T rets = NULL;
    std::string temp_ip;
    uint32_t ip = 0;
    struct HashRule rule;
    for(int i = 0 ; i < bucket_num ; ++ i)
    {
        memset(&rule , 0 , sizeof(rule));
        if(DBP->bind_int_parameter(pre , 1 , i) < 0)
        {
            LOG_ERROR("RuleInit::bind int parameter to bucket error ! bucket : " 
                    + int_to_str(i));
            return -1;
        }
        if(!(rets = DBP->prepare_execute_query(pre)) || (!ResultSet_next(rets)))
        {
            LOG_ERROR("RuleInit::get result error ! bucket : " + int_to_str(i));
            return -1;
        }
        //只获得IP,因此需要从第二个数开始
        for(int j = 0 ; j < MAX_IP_NUM ; ++ j)
        {
            if(DBP->get_string_result(rets , j + 2 , temp_ip) < 0)
            {
                LOG_ERROR("RuleInit::Get string result of index " + int_to_str(j + 2) + "error !");
                return -1;
            }
            //如果这是一个无效的IP
            if(!temp_ip.compare(INVALID_IP_STR))
            {
                ip = INVALID_IP;
            }
            else 
            {
                if(string_to_int_ip(temp_ip , ip) < 0)
                {
                    LOG_ERROR("RuleInit::Change string ip to int error : " + temp_ip);
                    return -1;
                }
            }
            rule.ip[j] = ip;
        }
        rule.bucket_nr = i;
        RulerManager::getInstance()->add_new_hash_item(rule , type);
    }
    int mod = cs_log(bucket_num);
    if(mod == -1)
        mod = 0;

    RulerManager::getInstance()->set_current_mod(type , mod) ;
        
    return 0;
}
예제 #15
0
static void login_request_cb(conn *c, unsigned char *msg, size_t sz)
{
	Connection_T dbc = ConnectionPool_getConnection(pool);
	if (NULL == dbc) {
		mwarn("ConnectionPool_getConnection failed!");
		return;
	}

	TRY {
		/* check account && passwd */
		login::login_request lr;
		msg_body<login::login_request>(msg, sz, &lr);
		ResultSet_T result = Connection_executeQuery(dbc,
				"SELECT `id` FROM `profile` WHERE `account`='%s' AND `passwd`='%s';",
				lr.account().c_str(), lr.passwd().c_str());

		if (ResultSet_next(result)) {
			uint64_t uid = ResultSet_getLLong(result, 1);
			login::error err = login::success;
			do {
				int tempid = user_manager_t::get_guid();
				user_t *user = (user_t *)malloc(sizeof(user_t));
				if (NULL == user) {
					mdebug("user_t alloc failed!");
					err = login::unknow;
					break;
				}
				user->id = tempid;
				user->c = NULL;
				user->refcnt = 1;
				pthread_mutex_init(&user->lock, NULL);

				if (0 > user_mgr->add_user(user)) {
					mdebug("add_user failed!");
					err = login::unknow;
					break;
				}

				user_lock(user);
				user->c = c;
				user_unlock(user);

				conn_lock(c);
				c->user = user;
				conn_unlock(c);

				/* tell center */
				login::user_login_request ulr;
				ulr.set_tempid(tempid);
				ulr.set_uid(uid);
				center_info_t *info = center_info_mgr->get_center_info_incref(1);
				if (info) {
					conn_write<login::user_login_request>(info->c, le_user_login_request, &ulr);
					center_info_decref(info);
				}
				return;
			} while (0);
			login::login_reply lr;
			lr.set_err(err);
			conn_write<login::login_reply>(c, lc_login_reply, &lr);
		} else {
			login::login_reply lr;
			lr.set_err(login::auth);
			conn_write<login::login_reply>(c, lc_login_reply, &lr);
		}
	} CATCH(SQLException) {
		merror("SQLException -- %s", Exception_frame.message);
	} FINALLY {
		Connection_close(dbc);
	} END_TRY;
}
예제 #16
0
파일: pool.c 프로젝트: SteffenBaresel/id2sc
static void testPool(const char *testURL) {
        URL_T url;
        char *schema;
        ConnectionPool_T pool;
        char *data[]= {"Fry", "Leela", "Bender", "Farnsworth",
                "Zoidberg", "Amy", "Hermes", "Nibbler", "Cubert",
                "Zapp", "Joey Mousepad", "ЯΣ༆", 0}; 
        
        if (Str_startsWith(testURL, "mysql")) {
                schema = SCHEMA_MYSQL;
        } else if (Str_startsWith(testURL, "postgresql")) {
                schema = SCHEMA_POSTGRESQL;
        } else if (Str_startsWith(testURL, "sqlite")) {
                schema = SCHEMA_SQLITE;
        } else if (Str_startsWith(testURL, "oracle")) {
                schema = SCHEMA_ORACLE;
        }
        else {
                printf("Unsupported database protocol\n");
                exit(1);
        }

        printf("=> Test1: create/destroy\n");
        {
                pool = ConnectionPool_new(URL_new(testURL));
                assert(pool);
                url = ConnectionPool_getURL(pool);
                ConnectionPool_free(&pool);
                assert(! pool);
                URL_free(&url);
        }
        printf("=> Test1: OK\n\n");
        
        printf("=> Test2: NULL value\n");
        {
                url = URL_new(NULL);
                assert(! url);
                pool = ConnectionPool_new(url);
                assert(! pool);
        }
        printf("=> Test2: OK\n\n");
        
        printf("=> Test3: start/stop\n");
        {
                url = URL_new(testURL);
                pool = ConnectionPool_new(url);
                assert(pool);
                ConnectionPool_start(pool);
                ConnectionPool_stop(pool);
                ConnectionPool_free(&pool);
                assert(pool==NULL);
                URL_free(&url);
                // Test that exception is thrown on start error
                TRY
                {
                        url = URL_new("not://a/database");
                        pool = ConnectionPool_new(url);
                        assert(pool);
                        ConnectionPool_start(pool);
                        printf("\tResult: Test failed -- exception not thrown\n");
                        exit(1);
                }
                CATCH(SQLException) {
                        // OK
                }
                FINALLY {
                        ConnectionPool_free(&pool);
                        assert(pool==NULL);
                        URL_free(&url);
                }
                END_TRY;
        }
        printf("=> Test3: OK\n\n");
        
        printf("=> Test4: Connection execute & transaction\n");
        {
                int i;
                Connection_T con;
                url = URL_new(testURL);
                pool = ConnectionPool_new(url);
                assert(pool);
                ConnectionPool_setAbortHandler(pool, TabortHandler);
                ConnectionPool_start(pool);
                con = ConnectionPool_getConnection(pool);
                assert(con);
                TRY Connection_execute(con, "drop table zild_t;"); ELSE END_TRY;
                Connection_execute(con, "%s", schema);
                Connection_beginTransaction(con);
                /* Insert values into database and assume that auto increment of id works */
                for (i = 0; data[i]; i++) 
                        Connection_execute(con, "insert into zild_t (name, percent) values('%s', %d.%d);", data[i], i+1, i);
                // Assert that the last insert statement added one row
                assert(Connection_rowsChanged(con) == 1);
                /* Assert that last row id works for MySQL and SQLite. Neither Oracle nor PostgreSQL
                 support last row id directly. The way to do this in PostgreSQL is to use 
                 currval() or return the id on insert. */
                if (IS(URL_getProtocol(url), "sqlite") || IS(URL_getProtocol(url), "mysql")) 
                        assert(Connection_lastRowId(con) == 12);
                Connection_commit(con);
                printf("\tResult: table zild_t successfully created\n");
                Connection_close(con);
        }
        printf("=> Test4: OK\n\n");     
        
        
        printf("=> Test5: Prepared Statement\n");
        {
                int i;
                char blob[8192];
                char *images[]= {"Ceci n'est pas une pipe", "Mona Lisa",
                        "Bryllup i Hardanger", "The Scream",
                        "Vampyre", "Balcony", "Cycle", "Day & Night", 
                        "Hand with Reflecting Sphere",
                        "Drawing Hands", "Ascending and Descending", 0}; 
                Connection_T con = ConnectionPool_getConnection(pool);
                assert(con);
                // 1. Prepared statement, perform a nonsense update to test rowsChanged
                PreparedStatement_T p1 = Connection_prepareStatement(con, "update zild_t set image=?;");
                PreparedStatement_setString(p1, 1, "");
                PreparedStatement_execute(p1);
                printf("\tRows changed: %lld\n", PreparedStatement_rowsChanged(p1));
                // Assert that all 12 rows in the data set was changed
                assert(PreparedStatement_rowsChanged(p1) == 12);
                // 2. Prepared statement, update the table proper with "images". 
                PreparedStatement_T pre = Connection_prepareStatement(con, "update zild_t set image=? where id=?;");
                assert(pre);
                for (i = 0; images[i]; i++) {
                        PreparedStatement_setBlob(pre, 1, images[i], (int)strlen(images[i])+1);
                        PreparedStatement_setInt(pre, 2, i + 1);
                        PreparedStatement_execute(pre);
                }
                // The last execute changed one row only
                assert(PreparedStatement_rowsChanged(pre) == 1);
                /* Add a database null blob value */
                PreparedStatement_setBlob(pre, 1, NULL, 0);
                PreparedStatement_setInt(pre, 2, 5);
                PreparedStatement_execute(pre);
                /* Add a database null string value */
                PreparedStatement_setString(pre, 1, NULL);
                PreparedStatement_setInt(pre, 2, 1);
                PreparedStatement_execute(pre);
                /* Add a large blob */
                memset(blob, 'x', 8192);
                blob[8191] = 0;
                /* Mark start and end */
                *blob='S'; blob[8190] = 'E';
                PreparedStatement_setBlob(pre, 1, blob, 8192);
                PreparedStatement_setInt(pre, 2, i + 1);
                PreparedStatement_execute(pre);
                printf("\tResult: prepared statement successfully executed\n");
                Connection_close(con);
        }
        printf("=> Test5: OK\n\n");     
        
        
        printf("=> Test6: Result Sets\n");
        {
                int i;
                int imagesize = 0;
                Connection_T con;
                ResultSet_T rset;
                ResultSet_T names;
                PreparedStatement_T pre;
                con = ConnectionPool_getConnection(pool);
                assert(con);
                rset = Connection_executeQuery(con, "select id, name, percent, image from zild_t where id < %d order by id;", 100);
                assert(rset);
                printf("\tResult:\n");
                printf("\tNumber of columns in resultset: %d\n\t", ResultSet_getColumnCount(rset));
                assert(4==ResultSet_getColumnCount(rset));
                i = 1;
                printf("%-5s", ResultSet_getColumnName(rset, i++));
                printf("%-16s", ResultSet_getColumnName(rset, i++));
                printf("%-10s", ResultSet_getColumnName(rset, i++));
                printf("%-16s", ResultSet_getColumnName(rset, i++));
                printf("\n\t------------------------------------------------------\n");
                while (ResultSet_next(rset)) {
                        int id = ResultSet_getIntByName(rset, "id");
                        const char *name = ResultSet_getString(rset, 2);
                        double percent = ResultSet_getDoubleByName(rset, "percent");
                        const char *blob = (char*)ResultSet_getBlob(rset, 4, &imagesize);
                        printf("\t%-5d%-16s%-10.2f%-16.38s\n", id, name ? name : "null", percent, imagesize ? blob : "");
                }
                rset = Connection_executeQuery(con, "select image from zild_t where id=12;");
                assert(1==ResultSet_getColumnCount(rset));
                // Assert that types are interchangeable (to some degree) and that all data is returned
                while (ResultSet_next(rset)) {
                        const char *image = ResultSet_getStringByName(rset, "image");
                        const void *blob = ResultSet_getBlobByName(rset, "image", &imagesize);
                        assert(image && blob);
                        assert(strlen(image) + 1 == 8192);
                        assert(imagesize == 8192);
                }
                printf("\tResult: check max rows..");
                Connection_setMaxRows(con, 3);
                rset = Connection_executeQuery(con, "select id from zild_t;");
                assert(rset);
                i = 0;
                while (ResultSet_next(rset)) i++;
                assert((i)==3);
                printf("success\n");
                printf("\tResult: check prepared statement resultset..");
                Connection_setMaxRows(con, 0);
                pre = Connection_prepareStatement(con, "select name from zild_t where id=?");
                assert(pre);
                PreparedStatement_setInt(pre, 1, 2);
                names = PreparedStatement_executeQuery(pre);
                assert(names);
                assert(ResultSet_next(names));
                assert(Str_isEqual("Leela", ResultSet_getString(names, 1)));
                printf("success\n");
                printf("\tResult: check prepared statement re-execute..");
                PreparedStatement_setInt(pre, 1, 1);
                names = PreparedStatement_executeQuery(pre);
                assert(names);
                assert(ResultSet_next(names));
                assert(Str_isEqual("Fry", ResultSet_getString(names, 1)));
                printf("success\n");
                printf("\tResult: check prepared statement without in-params..");
                pre = Connection_prepareStatement(con, "select name from zild_t;");
                assert(pre);
                names = PreparedStatement_executeQuery(pre);
                assert(names);
                for (i = 0; ResultSet_next(names); i++);
                assert(i==12);
                printf("success\n");
                /* Need to close and release statements before
                   we can drop the table, sqlite need this */
                Connection_clear(con);
                Connection_execute(con, "drop table zild_t;");
                Connection_close(con);
                ConnectionPool_stop(pool);
                ConnectionPool_free(&pool);
                assert(pool==NULL);
                URL_free(&url);
        }
        printf("=> Test6: OK\n\n");
        
        
        printf("=> Test7: reaper start/stop\n");
        {
                int i;
                Vector_T v = Vector_new(20);
                url = URL_new(testURL);
                pool = ConnectionPool_new(url);
                assert(pool);
                ConnectionPool_setInitialConnections(pool, 4);
                ConnectionPool_setMaxConnections(pool, 20);
                ConnectionPool_setConnectionTimeout(pool, 4);
                ConnectionPool_setReaper(pool, 4);
                ConnectionPool_setAbortHandler(pool, TabortHandler);
                ConnectionPool_start(pool);
                assert(4==ConnectionPool_size(pool));
                printf("Creating 20 Connections..");
                for (i = 0; i<20; i++)
                        Vector_push(v, ConnectionPool_getConnection(pool));
                assert(ConnectionPool_size(pool) == 20);
                assert(ConnectionPool_active(pool) == 20);
                printf("success\n");
                printf("Closing Connections down to initial..");
                while (! Vector_isEmpty(v))
                        Connection_close(Vector_pop(v));
                assert(ConnectionPool_active(pool) == 0);
                assert(ConnectionPool_size(pool) == 20);
                printf("success\n");
                printf("Please wait 10 sec for reaper to harvest closed connections..");
                Connection_T con = ConnectionPool_getConnection(pool); // Activate one connection to verify the reaper does not close any active
                fflush(stdout);
                sleep(10);
                assert(5 == ConnectionPool_size(pool)); // 4 initial connections + the one active we got above
                assert(1 == ConnectionPool_active(pool));
                printf("success\n");
                Connection_close(con);
                ConnectionPool_stop(pool);
                ConnectionPool_free(&pool);
                Vector_free(&v);
                assert(pool==NULL);
                URL_free(&url);
        }
        printf("=> Test7: OK\n\n");

        printf("=> Test8: Exceptions handling\n");
        {
                int i;
                Connection_T con;
                ResultSet_T result;
                url = URL_new(testURL);
                pool = ConnectionPool_new(url);
                assert(pool);
                ConnectionPool_setAbortHandler(pool, TabortHandler);
                ConnectionPool_start(pool);
                con = ConnectionPool_getConnection(pool);
                assert(con);
                /* 
                 * The following should work without throwing exceptions 
                 */
                TRY
                {
                        Connection_execute(con, "%s", schema);
                }
                ELSE
                {
                        printf("\tResult: Creating table zild_t failed -- %s\n", Exception_frame.message);
                        assert(false); // Should not fail
                }
                END_TRY;
                TRY
                {
                        Connection_beginTransaction(con);
                        for (i = 0; data[i]; i++) 
                                Connection_execute(con, "insert into zild_t (name, percent) values('%s', %d.%d);", data[i], i+1, i);
                        Connection_commit(con);
                        printf("\tResult: table zild_t successfully created\n");
                }
                ELSE
                {
                        printf("\tResult: Test failed -- %s\n", Exception_frame.message);
                        assert(false); // Should not fail
                }
                FINALLY
                {
                        Connection_close(con);
                }
                END_TRY;
                assert((con = ConnectionPool_getConnection(pool)));
                TRY
                {
                        int i, j;
                        const char *bg[]= {"Starbuck", "Sharon Valerii",
                                "Number Six", "Gaius Baltar", "William Adama",
                                "Lee \"Apollo\" Adama", "Laura Roslin", 0};
                        PreparedStatement_T p = Connection_prepareStatement
                        (con, "insert into zild_t (name) values(?);");
                        /* If we did not get a statement, an SQLException is thrown
                           and we will not get here. So we can safely use the 
                           statement now. Likewise, below, we do not have to 
                           check return values from the statement since any error
                           will throw an SQLException and transfer the control
                           to the exception handler
                        */
                        for (i = 0, j = 42; bg[i]; i++, j++) {
                                PreparedStatement_setString(p, 1, bg[i]);
                                PreparedStatement_execute(p);
                        }
                }
                CATCH(SQLException)
                {
                        printf("\tResult: prepare statement failed -- %s\n", Exception_frame.message);
                        assert(false);
                }
                END_TRY;
                TRY
                {
                        printf("\t\tBattlestar Galactica: \n");
                        result = Connection_executeQuery(con, "select name from zild_t where id > 12;");
                        while (ResultSet_next(result))
                                printf("\t\t%s\n", ResultSet_getString(result, 1));
                }
                CATCH(SQLException)
                {
                        printf("\tResult: resultset failed -- %s\n", Exception_frame.message);
                       assert(false);
                }
                FINALLY
                {
                        Connection_close(con);
                }
                END_TRY;
                /* 
                 * The following should fail and throw exceptions. The exception error 
                 * message can be obtained with Exception_frame.message, or from 
                 * Connection_getLastError(con). Exception_frame.message contains both
                 * SQL errors or api errors such as prepared statement parameter index
                 * out of range, while Connection_getLastError(con) only has SQL errors
                 */
                TRY
                {
                        assert((con = ConnectionPool_getConnection(pool)));
                        Connection_execute(con, "%s", schema);
                        /* Creating the table again should fail and we 
                        should not come here */
                        printf("\tResult: Test failed -- exception not thrown\n");
                        exit(1);
                }
                CATCH(SQLException)
                {
                        Connection_close(con);
                }
                END_TRY;
                TRY
                {
                        assert((con = ConnectionPool_getConnection(pool)));
                        printf("\tTesting: Query with errors.. ");
                        Connection_executeQuery(con, "blablabala;");
                        printf("\tResult: Test failed -- exception not thrown\n");
                        exit(1);
                }
                CATCH(SQLException)
                {
                        printf("ok\n");
                        Connection_close(con);
                }
                END_TRY;
                TRY
                {
                        printf("\tTesting: Prepared statement query with errors.. ");
                        assert((con = ConnectionPool_getConnection(pool)));
                        PreparedStatement_T p = Connection_prepareStatement(con, "blablabala;");
                        ResultSet_T r = PreparedStatement_executeQuery(p);
                        while(ResultSet_next(r));
                        printf("\tResult: Test failed -- exception not thrown\n");
                        exit(1);
                }
                CATCH(SQLException)
                {
                        printf("ok\n");
                        Connection_close(con);
                }
                END_TRY;
                TRY
                {
                        assert((con = ConnectionPool_getConnection(pool)));
                        printf("\tTesting: Column index out of range.. ");
                        result = Connection_executeQuery(con, "select id, name from zild_t;");
                        while (ResultSet_next(result)) {
                                int id = ResultSet_getInt(result, 1);  
                                const char *name = ResultSet_getString(result, 2);
                                /* So far so good, now, try access an invalid
                                   column, which should throw an SQLException */
                                int bogus = ResultSet_getInt(result, 3);
                                printf("\tResult: Test failed -- exception not thrown\n");
                                printf("%d, %s, %d", id, name, bogus);
                                exit(1);
                        }
                }
                CATCH(SQLException)
                {
                        printf("ok\n");
                        Connection_close(con);
                }
                END_TRY;
                TRY
                {
                        assert((con = ConnectionPool_getConnection(pool)));
                        printf("\tTesting: Invalid column name.. ");
                        result = Connection_executeQuery(con, "select name from zild_t;");
                        while (ResultSet_next(result)) {
                                const char *name = ResultSet_getStringByName(result, "nonexistingcolumnname");
                                printf("%s", name);
                                printf("\tResult: Test failed -- exception not thrown\n");
                                exit(1);
                        }
                }
                CATCH(SQLException)
                {
                        printf("ok\n");
                        Connection_close(con);
                }
                END_TRY;
                TRY
                {
                        assert((con = ConnectionPool_getConnection(pool)));
                        PreparedStatement_T p = Connection_prepareStatement(con, "update zild_t set name = ? where id = ?;");
                        printf("\tTesting: Parameter index out of range.. ");
                        PreparedStatement_setInt(p, 3, 123);
                        printf("\tResult: Test failed -- exception not thrown\n");
                        exit(1);
                }
                CATCH(SQLException)
                {
                        printf("ok\n");
                }
                FINALLY
                {
                        Connection_close(con);
                }
                END_TRY;
                assert((con = ConnectionPool_getConnection(pool)));
                Connection_execute(con, "drop table zild_t;");
                Connection_close(con);
                ConnectionPool_stop(pool);
                ConnectionPool_free(&pool);
                assert(pool==NULL);
                URL_free(&url);
        }
        printf("=> Test8: OK\n\n");
        
        printf("=> Test9: Ensure Capacity\n");
        {
                /* Check that MySQL ensureCapacity works for columns that exceed the preallocated buffer and that no truncation is done */
                if ( Str_startsWith(testURL, "mysql")) {
                        int myimagesize;
                        url = URL_new(testURL);
                        pool = ConnectionPool_new(url);
                        assert(pool);
                        ConnectionPool_start(pool);
                        Connection_T con = ConnectionPool_getConnection(pool);
                        assert(con);
                        Connection_execute(con, "CREATE TABLE zild_t(id INTEGER AUTO_INCREMENT PRIMARY KEY, image BLOB, string TEXT);");
                        PreparedStatement_T p = Connection_prepareStatement(con, "insert into zild_t (image, string) values(?, ?);");
                        char t[4096];
                        memset(t, 'x', 4096);
                        t[4095] = 0;
                        for (int i = 0; i < 4; i++) {
                                PreparedStatement_setBlob(p, 1, t, (i+1)*512); // store successive larger string-blobs to trigger realloc on ResultSet_getBlobByName
                                PreparedStatement_setString(p, 2, t);
                                PreparedStatement_execute(p);
                        }
                        ResultSet_T r = Connection_executeQuery(con, "select image, string from zild_t;");
                        for (int i = 0; ResultSet_next(r); i++) {
                                ResultSet_getBlobByName(r, "image", &myimagesize);
                                const char *image = ResultSet_getStringByName(r, "image"); // Blob as image should be terminated
                                const char *string = ResultSet_getStringByName(r, "string");
                                assert(myimagesize == (i+1)*512);
                                assert(strlen(image) == ((i+1)*512));
                                assert(strlen(string) == 4095);
                        }
                        p = Connection_prepareStatement(con, "select image, string from zild_t;");
                        r = PreparedStatement_executeQuery(p);
                        for (int i = 0; ResultSet_next(r); i++) {
                                ResultSet_getBlobByName(r, "image", &myimagesize);
                                const char *image = ResultSet_getStringByName(r, "image");
                                const char *string = (char*)ResultSet_getStringByName(r, "string");
                                assert(myimagesize == (i+1)*512);
                                assert(strlen(image) == ((i+1)*512));
                                assert(strlen(string) == 4095);
                        }
                        Connection_execute(con, "drop table zild_t;");
                        Connection_close(con);
                        ConnectionPool_stop(pool);
                        ConnectionPool_free(&pool);
                        URL_free(&url);
                }
        }
        printf("=> Test9: OK\n\n");

        printf("============> Connection Pool Tests: OK\n\n");
}