dbd/db2/connection.c

changeset 14
98192b7d4e89
child 16
318e5dfd03b8
equal deleted inserted replaced
13:10c8c6f0da14 14:98192b7d4e89
1 #include "dbd_db2.h"
2
3 int dbd_db2_statement_create(lua_State *L, connection_t *conn, const char *sql_query);
4
5 static int commit(connection_t *conn) {
6 SQLRETURN rc = SQL_SUCCESS;
7
8 rc = SQLEndTran(SQL_HANDLE_DBC, conn->db2, SQL_COMMIT);
9
10 return rc != SQL_SUCCESS;
11 }
12
13 static int rollback(connection_t *conn) {
14 SQLRETURN rc = SQL_SUCCESS;
15
16 rc = SQLEndTran(SQL_HANDLE_DBC, conn->db2, SQL_ROLLBACK);
17
18 return rc != SQL_SUCCESS;
19 }
20
21
22 /*
23 * connection = DBD.DB2.New(dbname, user, password, host, port)
24 */
25 static int connection_new(lua_State *L) {
26 int n = lua_gettop(L);
27 connection_t *conn = NULL;
28 SQLRETURN rc = SQL_SUCCESS;
29
30 const char *user = NULL;
31 const char *password = NULL;
32 const char *db = NULL;
33
34 SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
35 SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
36 SQLINTEGER sqlcode;
37 SQLSMALLINT length;
38
39 /* db, user, password, host, port */
40 switch(n) {
41 case 5:
42 case 4:
43 case 3:
44 if (lua_isnil(L, 3) == 0)
45 password = luaL_checkstring(L, 3);
46 case 2:
47 if (lua_isnil(L, 2) == 0)
48 user = luaL_checkstring(L, 2);
49 case 1:
50 /*
51 * db is the only mandatory parameter
52 */
53 db = luaL_checkstring(L, 1);
54 }
55
56 conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t));
57
58 /* allocate an environment handle */
59 rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &conn->env);
60 if (rc != SQL_SUCCESS) {
61 lua_pushnil(L);
62 lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, "Cannot allocate environment handle");
63 return 2;
64 }
65
66 /* set attribute to enable application to run as ODBC 3.0 application */
67 rc = SQLSetEnvAttr(conn->env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
68 if (rc != SQL_SUCCESS) {
69 lua_pushnil(L);
70 lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, "Cannot set ODBC version attribute");
71 return 2;
72 }
73
74 /* allocate a database connection handle */
75 rc = SQLAllocHandle(SQL_HANDLE_DBC, conn->env, &conn->db2);
76 if (rc != SQL_SUCCESS) {
77 lua_pushnil(L);
78 lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, "Cannot allocate database handle");
79 return 2;
80 }
81
82 /* set AUTOCOMMIT off */
83 rc = SQLSetConnectAttr(conn->db2, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
84 if (rc != SQL_SUCCESS) {
85 lua_pushnil(L);
86 lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, "Cannot turn off autocommit");
87 return 2;
88 }
89
90 /* connect to the database */
91 rc = SQLConnect(conn->db2, (SQLCHAR *)db, SQL_NTS, (SQLCHAR *)user, SQL_NTS, (SQLCHAR *)password, SQL_NTS);
92 if (rc != SQL_SUCCESS) {
93 SQLGetDiagRec(SQL_HANDLE_DBC, conn->db2, 1, sqlstate, &sqlcode, message, SQL_MAX_MESSAGE_LENGTH + 1, &length);
94
95 lua_pushnil(L);
96 lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, message);
97 return 2;
98 }
99
100 luaL_getmetatable(L, DBD_DB2_CONNECTION);
101 lua_setmetatable(L, -2);
102
103 return 1;
104 }
105
106 /*
107 * success = connection:autocommit(on)
108 */
109 static int connection_autocommit(lua_State *L) {
110 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
111 int on = lua_toboolean(L, 2);
112 int err = 0;
113
114 if (conn->db2) {
115 int onval = on ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
116
117 SQLRETURN rc = SQLSetConnectAttr(conn->db2, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)onval, SQL_NTS);
118
119 err = rc != SQL_SUCCESS;
120 }
121
122 lua_pushboolean(L, !err);
123 return 1;
124 }
125
126 /*
127 * success = connection:close()
128 */
129 static int connection_close(lua_State *L) {
130 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
131 int disconnect = 0;
132
133 if (conn->db2) {
134 SQLRETURN rc = SQL_SUCCESS;
135
136 rollback(conn);
137
138 /* disconnect from the database */
139 rc = SQLDisconnect(conn->db2);
140
141 /* free connection handle */
142 rc = SQLFreeHandle(SQL_HANDLE_DBC, conn->db2);
143
144 /* free environment handle */
145 rc = SQLFreeHandle(SQL_HANDLE_ENV, conn->env);
146
147 conn->db2 = 0;
148 }
149
150 lua_pushboolean(L, disconnect);
151 return 1;
152 }
153
154 /*
155 * success = connection:commit()
156 */
157 static int connection_commit(lua_State *L) {
158 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
159 int err = 1;
160
161 if (conn->db2) {
162 err = commit(conn);
163 }
164
165 lua_pushboolean(L, !err);
166 return 1;
167 }
168
169 /*
170 * ok = connection:ping()
171 */
172 static int connection_ping(lua_State *L) {
173 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
174 int ok = 0;
175
176 if (conn->db2) {
177 ok = 1;
178 }
179
180 lua_pushboolean(L, ok);
181 return 1;
182 }
183
184 /*
185 * statement = connection:prepare(sql_string)
186 */
187 static int connection_prepare(lua_State *L) {
188 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
189
190 if (conn->db2) {
191 return dbd_db2_statement_create(L, conn, luaL_checkstring(L, 2));
192 }
193
194 lua_pushnil(L);
195 lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE);
196 return 2;
197 }
198
199 /*
200 * success = connection:rollback()
201 */
202 static int connection_rollback(lua_State *L) {
203 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
204 int err = 1;
205
206 if (conn->db2) {
207 err = rollback(conn);
208 }
209
210 lua_pushboolean(L, !err);
211 return 1;
212 }
213
214 /*
215 * __gc
216 */
217 static int connection_gc(lua_State *L) {
218 /* always close the connection */
219 connection_close(L);
220
221 return 0;
222 }
223
224 int dbd_db2_connection(lua_State *L) {
225 static const luaL_Reg connection_methods[] = {
226 {"autocommit", connection_autocommit},
227 {"close", connection_close},
228 {"commit", connection_commit},
229 {"ping", connection_ping},
230 {"prepare", connection_prepare},
231 {"rollback", connection_rollback},
232 {NULL, NULL}
233 };
234
235 static const luaL_Reg connection_class_methods[] = {
236 {"New", connection_new},
237 {NULL, NULL}
238 };
239
240 luaL_newmetatable(L, DBD_DB2_CONNECTION);
241 luaL_register(L, 0, connection_methods);
242 lua_pushvalue(L,-1);
243 lua_setfield(L, -2, "__index");
244
245 lua_pushcfunction(L, connection_gc);
246 lua_setfield(L, -2, "__gc");
247
248 luaL_register(L, DBD_DB2_CONNECTION, connection_class_methods);
249
250 return 1;
251 }

mercurial