Skip to content

Commit ceeda3b

Browse files
committed
2 parents b41ae4d + e6f13f1 commit ceeda3b

File tree

1 file changed

+146
-125
lines changed

1 file changed

+146
-125
lines changed

README.md

Lines changed: 146 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -8,144 +8,165 @@ Header files based C++ database connection API based on KISS principle
88
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.
99

1010

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+
1122
### Currently supported databases:
1223

1324
* Sybase ASE (ASA was not tested) - see sybase_example.cpp
1425

1526

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.
1732

18-
@code
19-
#include "sybase_driver.hpp"
2033

21-
using namespace std;
22-
using namespace vgi::dbconn::dbi;
23-
using namespace vgi::dbconn::dbd;
34+
### Usage example
2435

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)
2845
{
29-
connection conn = driver<sybase::driver>::load().get_connection("DBSYB1", "sa", "");
30-
if (conn.connect())
46+
try
3147
{
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())
5350
{
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");
58158
}
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";
139161
}
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+
149170
@endcode
150171

151172
Limited amount of testing was done.

0 commit comments

Comments
 (0)