Tue, 01 Sep 2009 13:15:02 +0000
Add __tostring method to connection and statement objects.
14 | 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 | ||
16 | 39 | /* db, user, password */ |
14 | 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; | |
26 | 132 | SQLRETURN rc = SQL_SUCCESS; |
14 | 133 | |
134 | if (conn->db2) { | |
135 | rollback(conn); | |
136 | ||
137 | /* disconnect from the database */ | |
138 | rc = SQLDisconnect(conn->db2); | |
139 | ||
140 | /* free connection handle */ | |
141 | rc = SQLFreeHandle(SQL_HANDLE_DBC, conn->db2); | |
142 | ||
26 | 143 | conn->db2 = 0; |
144 | } | |
145 | ||
146 | if (conn->env) { | |
14 | 147 | /* free environment handle */ |
148 | rc = SQLFreeHandle(SQL_HANDLE_ENV, conn->env); | |
149 | } | |
150 | ||
151 | lua_pushboolean(L, disconnect); | |
152 | return 1; | |
153 | } | |
154 | ||
155 | /* | |
156 | * success = connection:commit() | |
157 | */ | |
158 | static int connection_commit(lua_State *L) { | |
159 | connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION); | |
160 | int err = 1; | |
161 | ||
162 | if (conn->db2) { | |
163 | err = commit(conn); | |
164 | } | |
165 | ||
166 | lua_pushboolean(L, !err); | |
167 | return 1; | |
168 | } | |
169 | ||
170 | /* | |
171 | * ok = connection:ping() | |
172 | */ | |
173 | static int connection_ping(lua_State *L) { | |
174 | connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION); | |
175 | int ok = 0; | |
176 | ||
177 | if (conn->db2) { | |
178 | ok = 1; | |
179 | } | |
180 | ||
181 | lua_pushboolean(L, ok); | |
182 | return 1; | |
183 | } | |
184 | ||
185 | /* | |
186 | * statement = connection:prepare(sql_string) | |
187 | */ | |
188 | static int connection_prepare(lua_State *L) { | |
189 | connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION); | |
190 | ||
191 | if (conn->db2) { | |
192 | return dbd_db2_statement_create(L, conn, luaL_checkstring(L, 2)); | |
193 | } | |
194 | ||
195 | lua_pushnil(L); | |
196 | lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE); | |
197 | return 2; | |
198 | } | |
199 | ||
200 | /* | |
22 | 201 | * quoted = connection:quote(str) |
202 | */ | |
203 | static int connection_quote(lua_State *L) { | |
204 | luaL_error(L, DBI_ERR_NOT_IMPLEMENTED, DBD_DB2_CONNECTION, "quote"); | |
205 | return 0; | |
206 | } | |
207 | ||
208 | /* | |
14 | 209 | * success = connection:rollback() |
210 | */ | |
211 | static int connection_rollback(lua_State *L) { | |
212 | connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION); | |
213 | int err = 1; | |
214 | ||
215 | if (conn->db2) { | |
216 | err = rollback(conn); | |
217 | } | |
218 | ||
219 | lua_pushboolean(L, !err); | |
220 | return 1; | |
221 | } | |
222 | ||
223 | /* | |
224 | * __gc | |
225 | */ | |
226 | static int connection_gc(lua_State *L) { | |
227 | /* always close the connection */ | |
228 | connection_close(L); | |
229 | ||
230 | return 0; | |
231 | } | |
232 | ||
32
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
233 | /* |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
234 | * __tostring |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
235 | */ |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
236 | static int connection_tostring(lua_State *L) { |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
237 | connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
238 | |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
239 | lua_pushfstring(L, "%s: %p", DBD_DB2_CONNECTION, conn); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
240 | |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
241 | return 1; |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
242 | } |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
243 | |
14 | 244 | int dbd_db2_connection(lua_State *L) { |
245 | static const luaL_Reg connection_methods[] = { | |
246 | {"autocommit", connection_autocommit}, | |
247 | {"close", connection_close}, | |
248 | {"commit", connection_commit}, | |
249 | {"ping", connection_ping}, | |
250 | {"prepare", connection_prepare}, | |
22 | 251 | {"quote", connection_quote}, |
14 | 252 | {"rollback", connection_rollback}, |
253 | {NULL, NULL} | |
254 | }; | |
255 | ||
256 | static const luaL_Reg connection_class_methods[] = { | |
257 | {"New", connection_new}, | |
258 | {NULL, NULL} | |
259 | }; | |
260 | ||
261 | luaL_newmetatable(L, DBD_DB2_CONNECTION); | |
262 | luaL_register(L, 0, connection_methods); | |
263 | lua_pushvalue(L,-1); | |
264 | lua_setfield(L, -2, "__index"); | |
265 | ||
266 | lua_pushcfunction(L, connection_gc); | |
267 | lua_setfield(L, -2, "__gc"); | |
268 | ||
32
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
269 | lua_pushcfunction(L, connection_tostring); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
270 | lua_setfield(L, -2, "__tostring"); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
26
diff
changeset
|
271 | |
14 | 272 | luaL_register(L, DBD_DB2_CONNECTION, connection_class_methods); |
273 | ||
274 | return 1; | |
275 | } |