I had a hard time finding a free open source C++ Sybase driver that would be lightweight with no dependencies, easy to add and use, having a generic extensible interface in case database would be switched later on. Since then I also added SQLite driver.
The driver functions are thread-safe, all other objects (connection, statement, result_set) are not.
It's up to the users to decide whether to use (and what kind) any synchronization means or use a different design, eg:
The code has not been extensively tested, thus there could be some bugs.
Especial concerns would be the large data type (text, blob, unitext) and utf support.
1 #include "sybase_driver.hpp"
4 using namespace vgi::dbconn::dbi;
5 using namespace vgi::dbconn::dbd;
7 int main(int argc, char** argv)
11 connection conn = driver<sybase::driver>::load().get_connection("DBSYB1", "sa", "");
14 statement stmt = conn.get_statement();
17 stmt.execute("use tempdb");
19 stmt.execute("if object_id('tempdb..test') is not null drop table test");
22 stmt.execute("create table test (id int, txt varchar(10) null, num numeric(18, 8) null, primary key(id))");
25 stmt.execute("insert into test (id, txt) values (1, 'txt1') \
26 insert into test (id, txt) values (2, 'txt2')");
29 stmt.execute("update test set txt = 'test1' where id = 1 \
30 update test set txt = 'test2' where id = 2");
33 result_set rs = stmt.execute("select * from test");
36 cout << rs.column_name(0) << ": " << rs.get_int(0) << endl;
37 cout << rs.column_name(1) << ": " << rs.get_string(1) << endl;
38 cout << "column id: " << rs.get_int("id") << endl;
39 cout << "column txt1: " << rs.get_string("txt") << endl;
43 stmt.prepare("delete from test where id = 2");
45 cout << "rows affected = " << rs.rows_affected() << endl;
48 stmt.prepare("insert into test values (?, ?)");
50 stmt.set_string(1, "test2");
54 rs = stmt.execute("select id, txt from test", true);
57 cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
58 cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
62 rs = stmt.execute("select id, txt from test", true, true);
65 cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
66 cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
71 cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
72 cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
77 cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
78 cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
82 stmt.execute("create procedure test_proc @id int, @error varchar(128) output AS \
89 SET @error = 'id must be > 0' \
92 SELECT txt FROM test WHERE id = @id \
95 stmt.call("test_proc");
99 cout << rs.column_name(0) << ": " << (rs.is_null(0) ? "NULL" : rs.get_string(0)) << endl;
100 cout << "rows affected = " << rs.rows_affected() << endl;
101 cout << "stored proc return = " << stmt.proc_retval() << endl;
102 cout << "@error: >" << (rs.is_null(0) ? "NULL" : rs.get_string("@error")) << endl;
105 stmt.execute("truncate table test");
108 conn.autocommit(false);
109 stmt.execute("insert into test values (1, 'test1')");
111 stmt.execute("insert into test values (2, 'test2')");
112 stmt.execute("insert into test values (3, 'test3')");
114 conn.autocommit(true);
115 rs = stmt.execute("select count(*) from test");
117 cout << "Table has " << rs.get_int(0) << " rows\n";
120 stmt.execute("drop table test");
123 cout << "failed to connect!\n";
125 catch (const exception& e)
127 cout << "exception: " << e.what() << endl;
Limited amount of testing was done.
If someone would like to contribute please ping me.