/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, 0); // done tb_size_t score = 0; tb_stream_ref_t stream = tb_null; do { // the url arguments tb_char_t const* args = tb_url_args(url); if (args) { // find the database type tb_char_t const* ptype = tb_stristr(args, "type="); if (ptype && !tb_strnicmp(ptype + 5, "sqlite3", 7)) { // ok score = 100; break; } } // has host or port? no sqlite3 if (tb_url_host(url) || tb_url_port(url)) break; // the database path tb_char_t const* path = tb_url_cstr((tb_url_ref_t)url); tb_assert_and_check_break(path); // is file? if (tb_url_protocol(url) == TB_URL_PROTOCOL_FILE) score += 20; // init stream stream = tb_stream_init_from_url(path); tb_assert_and_check_break(stream); // open stream if (!tb_stream_open(stream)) break; // read head tb_char_t head[16] = {0}; if (!tb_stream_bread(stream, (tb_byte_t*)head, 15)) break; // is sqlite3? if (!tb_stricmp(head, "SQLite format 3")) score = 100; } while (0); // exit stream if (stream) tb_stream_exit(stream); stream = tb_null; // trace tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score); // ok? return score; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_database_sql_ref_t tb_database_sql_init(tb_char_t const* url) { // check tb_assert_and_check_return_val(url, tb_null); // done tb_bool_t ok = tb_false; tb_database_sql_ref_t database = tb_null; tb_url_t database_url; do { // trace tb_trace_d("init: %s: ..", url); // init url if (!tb_url_init(&database_url)) break; // make url if (!tb_url_cstr_set(&database_url, url)) break; // check protocol tb_size_t protocol = tb_url_protocol(&database_url); tb_assert_and_check_break(protocol == TB_URL_PROTOCOL_SQL || protocol == TB_URL_PROTOCOL_FILE); // the probe func static tb_size_t (*s_probe[])(tb_url_ref_t) = { tb_null #ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL , tb_database_mysql_probe #endif #ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3 , tb_database_sqlite3_probe #endif }; // the init func static tb_database_sql_ref_t (*s_init[])(tb_url_ref_t) = { tb_null #ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL , tb_database_mysql_init #endif #ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3 , tb_database_sqlite3_init #endif }; // probe the database type tb_size_t i = 1; tb_size_t n = tb_arrayn(s_probe); tb_size_t s = 0; tb_size_t m = 0; for (; i < n; i++) { if (s_probe[i]) { // probe it tb_size_t score = s_probe[i](&database_url); if (score > s) { // save the max score s = score; m = i; // ok? if (score == 100) break; } } } tb_check_break(m < n && s_init[m]); // init it database = s_init[m](&database_url); tb_assert_and_check_break(database); // trace tb_trace_d("init: %s: ok", url); // ok ok = tb_true; } while (0); // exit url tb_url_exit(&database_url); // failed? if (!ok) { // trace tb_trace_d("init: %s: no", url); // exit database if (database) tb_database_sql_exit(database); database = tb_null; } // ok? return database; }