@@ -8,144 +8,165 @@ Header files based C++ database connection API based on KISS principle
8
8
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.
9
9
10
10
11
+ ### Thread safety:
12
+
13
+ The driver functions are thread-safe, all other objects (connection, statement, result_set) are not.
14
+
15
+ It's up to the users to decide whether to use (and what kind) any synchronization means or use a different design, eg:
16
+
17
+ * use a single connection per thread
18
+ * create a connection pool
19
+ * create a separate database connection thread with its own connection
20
+
21
+
11
22
### Currently supported databases:
12
23
13
24
* Sybase ASE (ASA was not tested) - see sybase_example.cpp
14
25
15
26
16
- ### Usage example
27
+ ### Development state:
28
+
29
+ The code has not been extensively tested, thus there could be some bugs.
30
+
31
+ Especial concerns would be the large data type (text, blob, unitext) and utf support.
17
32
18
- @code
19
- #include "sybase_driver.hpp"
20
33
21
- using namespace std;
22
- using namespace vgi::dbconn::dbi;
23
- using namespace vgi::dbconn::dbd;
34
+ ### Usage example
24
35
25
- int main(int argc, char** argv)
26
- {
27
- try
36
+ @code
37
+
38
+ #include "sybase_driver.hpp"
39
+
40
+ using namespace std;
41
+ using namespace vgi::dbconn::dbi;
42
+ using namespace vgi::dbconn::dbd;
43
+
44
+ int main(int argc, char** argv)
28
45
{
29
- connection conn = driver< sybase::driver > ::load().get_connection("DBSYB1", "sa", "");
30
- if (conn.connect())
46
+ try
31
47
{
32
- statement stmt = conn.get_statement();
33
-
34
- // change database
35
- stmt.execute("use tempdb");
36
-
37
- stmt.execute("if object_id('tempdb..test') is not null drop table test");
38
-
39
- // create
40
- stmt.execute("create table test (id int, txt varchar(10) null, num numeric(18, 8) null, primary key(id))");
41
-
42
- // insert
43
- stmt.execute("insert into test (id, txt) values (1, 'txt1') \
44
- insert into test (id, txt) values (2, 'txt2')");
45
-
46
- // update
47
- stmt.execute("update test set txt = 'test1' where id = 1 \
48
- update test set txt = 'test2' where id = 2");
49
-
50
- // select
51
- result_set rs = stmt.execute("select * from test");
52
- while (rs.next())
48
+ connection conn = driver< sybase::driver > ::load().get_connection("DBSYB1", "sa", "");
49
+ if (conn.connect())
53
50
{
54
- cout << rs.column_name(0) << ": " << rs.get_int(0) << endl;
55
- cout << rs.column_name(1) << ": " << rs.get_string(1) << endl;
56
- cout << "column id: " << rs.get_int("id") << endl;
57
- cout << "column txt1: " << rs.get_string("txt") << endl;
51
+ statement stmt = conn.get_statement();
52
+
53
+ // change database
54
+ stmt.execute("use tempdb");
55
+
56
+ stmt.execute("if object_id('tempdb..test') is not null drop table test");
57
+
58
+ // create
59
+ stmt.execute("create table test (id int, txt varchar(10) null, num numeric(18, 8) null, primary key(id))");
60
+
61
+ // insert
62
+ stmt.execute("insert into test (id, txt) values (1, 'txt1') \
63
+ insert into test (id, txt) values (2, 'txt2')");
64
+
65
+ // update
66
+ stmt.execute("update test set txt = 'test1' where id = 1 \
67
+ update test set txt = 'test2' where id = 2");
68
+
69
+ // select
70
+ result_set rs = stmt.execute("select * from test");
71
+ while (rs.next())
72
+ {
73
+ cout << rs.column_name(0) << ": " << rs.get_int(0) << endl;
74
+ cout << rs.column_name(1) << ": " << rs.get_string(1) << endl;
75
+ cout << "column id: " << rs.get_int("id") << endl;
76
+ cout << "column txt1: " << rs.get_string("txt") << endl;
77
+ }
78
+
79
+ // delete
80
+ stmt.prepare("delete from test where id = 2");
81
+ rs = stmt.execute();
82
+ cout << "rows affected = " << rs.rows_affected() << endl;
83
+
84
+ // prepared statement
85
+ stmt.prepare("insert into test values (?, ?)");
86
+ stmt.set_int(0, 2);
87
+ stmt.set_string(1, "test2");
88
+ stmt.execute();
89
+
90
+ // cursor
91
+ rs = stmt.execute("select id, txt from test", true);
92
+ while (rs.next())
93
+ {
94
+ cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
95
+ cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
96
+ }
97
+
98
+ // scrollable cursor
99
+ rs = stmt.execute("select id, txt from test", true, true);
100
+ while (rs.next())
101
+ {
102
+ cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
103
+ cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
104
+ }
105
+ rs.first();
106
+ do
107
+ {
108
+ cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
109
+ cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
110
+ }
111
+ while (rs.next());
112
+ while (rs.prev())
113
+ {
114
+ cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
115
+ cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
116
+ }
117
+
118
+ // stored procedure
119
+ stmt.execute("create procedure test_proc @id int, @error varchar(128) output AS \
120
+ BEGIN \
121
+ DECLARE @ret int \
122
+ SET @error = NULL \
123
+ SET @ret = 0 \
124
+ IF @id = 0 \
125
+ BEGIN \
126
+ SET @error = 'id must be > 0' \
127
+ SET @ret = 1 \
128
+ END \
129
+ SELECT txt FROM test WHERE id = @id \
130
+ RETURN @ret \
131
+ END");
132
+ stmt.call("test_proc");
133
+ stmt.set_int(0, 3);
134
+ rs = stmt.execute();
135
+ while (rs.next())
136
+ cout << rs.column_name(0) << ": " << (rs.is_null(0) ? "NULL" : rs.get_string(0)) << endl;
137
+ cout << "rows affected = " << rs.rows_affected() << endl;
138
+ cout << "stored proc return = " << stmt.proc_retval() << endl;
139
+ cout << "@error : >" << (rs.is_null(0) ? "NULL" : rs.get_string("@error ")) << endl;
140
+
141
+ // truncate
142
+ stmt.execute("truncate table test");
143
+
144
+ // transaction
145
+ conn.autocommit(false);
146
+ stmt.execute("insert into test values (1, 'test1')");
147
+ conn.commit();
148
+ stmt.execute("insert into test values (2, 'test2')");
149
+ stmt.execute("insert into test values (3, 'test3')");
150
+ conn.rollback();
151
+ conn.autocommit(true);
152
+ rs = stmt.execute("select count(* ) from test");
153
+ rs.next();
154
+ cout << "Table has " << rs.get_int(0) << " rows\n";
155
+
156
+ // drop
157
+ stmt.execute("drop table test");
58
158
}
59
-
60
- // delete
61
- stmt.prepare("delete from test where id = 2");
62
- rs = stmt.execute();
63
- cout << "rows affected = " << rs.rows_affected() << endl;
64
-
65
- // prepared statement
66
- stmt.prepare("insert into test values (?, ?)");
67
- stmt.set_int(0, 2);
68
- stmt.set_string(1, "test2");
69
- stmt.execute();
70
-
71
- // cursor
72
- rs = stmt.execute("select id, txt from test", true);
73
- while (rs.next())
74
- {
75
- cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
76
- cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
77
- }
78
-
79
- // scrollable cursor
80
- rs = stmt.execute("select id, txt from test", true, true);
81
- while (rs.next())
82
- {
83
- cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
84
- cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
85
- }
86
- rs.first();
87
- do
88
- {
89
- cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
90
- cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
91
- }
92
- while (rs.next());
93
- while (rs.prev())
94
- {
95
- cout << rs.column_name(0) << ": " << (rs.is_null(0) ? -1 : rs.get_int(0)) << endl;
96
- cout << rs.column_name(1) << ": " << (rs.is_null(1) ? "NULL" : rs.get_string(1)) << endl;
97
- }
98
-
99
- // stored procedure
100
- stmt.execute("create procedure test_proc @id int, @error varchar(128) output AS \
101
- BEGIN \
102
- DECLARE @ret int \
103
- SET @error = NULL \
104
- SET @ret = 0 \
105
- IF @id = 0 \
106
- BEGIN \
107
- SET @error = 'id must be > 0' \
108
- SET @ret = 1 \
109
- END \
110
- SELECT txt FROM test WHERE id = @id \
111
- RETURN @ret \
112
- END");
113
- stmt.call("test_proc");
114
- stmt.set_int(0, 3);
115
- rs = stmt.execute();
116
- while (rs.next())
117
- cout << rs.column_name(0) << ": " << (rs.is_null(0) ? "NULL" : rs.get_string(0)) << endl;
118
- cout << "rows affected = " << rs.rows_affected() << endl;
119
- cout << "stored proc return = " << stmt.proc_retval() << endl;
120
- cout << "@error : >" << (rs.is_null(0) ? "NULL" : rs.get_string("@error ")) << endl;
121
-
122
- // truncate
123
- stmt.execute("truncate table test");
124
-
125
- // transaction
126
- conn.autocommit(false);
127
- stmt.execute("insert into test values (1, 'test1')");
128
- conn.commit();
129
- stmt.execute("insert into test values (2, 'test2')");
130
- stmt.execute("insert into test values (3, 'test3')");
131
- conn.rollback();
132
- conn.autocommit(true);
133
- rs = stmt.execute("select count(* ) from test");
134
- rs.next();
135
- cout << "Table has " << rs.get_int(0) << " rows\n";
136
-
137
- // drop
138
- stmt.execute("drop table test");
159
+ else
160
+ cout << "failed to connect!\n";
139
161
}
140
- else
141
- cout << "failed to connect!\n";
142
- }
143
- catch (const exception& e)
144
- {
145
- cout << "exception: " << e.what() << endl;
146
- }
147
- return 0;
148
- }
162
+ catch (const exception& e)
163
+ {
164
+ cout << "exception: " << e.what() << endl;
165
+ }
166
+ return 0;
167
+ }
168
+
169
+
149
170
@endcode
150
171
151
172
Limited amount of testing was done.
0 commit comments