dbd/db2/connection.c

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 */
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
    SQLRETURN rc = SQL_SUCCESS;
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
 
143
	conn->db2 = 0;
144
    }
145
 
146
    if (conn->env) {
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
/*
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
/*
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
 
233
/*
234
 * __tostring
235
 */
236
static int connection_tostring(lua_State *L) {
237
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_DB2_CONNECTION);
238
    
239
    lua_pushfstring(L, "%s: %p", DBD_DB2_CONNECTION, conn);
240
 
241
    return 1;
242
}
243
 
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},
251
	{"quote", connection_quote},
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
 
269
    lua_pushcfunction(L, connection_tostring);
270
    lua_setfield(L, -2, "__tostring");
271
 
272
    luaL_register(L, DBD_DB2_CONNECTION, connection_class_methods);
273
 
274
    return 1;    
275
}