dbd/oracle/connection.c

1
#include "dbd_oracle.h"
2
 
3
int dbd_oracle_statement_create(lua_State *L, connection_t *conn, const char *sql_query);
4
 
5
static int commit(connection_t *conn) {
6
    int rc = OCITransCommit(conn->svc, conn->err, OCI_DEFAULT);
7
    return rc;
8
}
9
 
10
static int rollback(connection_t *conn) {
11
    int rc = OCITransRollback(conn->svc, conn->err, OCI_DEFAULT);
12
    return rc;
13
}
14
 
15
 
16
/* 
17
 * connection,err = DBD.Oracle.New(dbfile)
18
 */
19
static int connection_new(lua_State *L) {
20
    int n = lua_gettop(L);
21
 
22
    int rc = 0;
23
 
24
    const char *user = NULL;
25
    const char *password = NULL;
26
    const char *db = NULL;
27
 
28
    OCIEnv *env = NULL;
29
    OCIError *err = NULL;
30
    OCISvcCtx *svc = NULL;
31
 
32
    connection_t *conn = NULL;
33
 
34
    /* db, user, password */
35
    switch(n) {
36
    case 5:
37
    case 4:
38
    case 3:
39
	if (lua_isnil(L, 3) == 0) 
40
	    password = luaL_checkstring(L, 3);
41
    case 2:
42
	if (lua_isnil(L, 2) == 0) 
43
	    user = luaL_checkstring(L, 2);
44
    case 1:
45
        /*
46
         * db is the only mandatory parameter
47
         */
48
	db = luaL_checkstring(L, 1);
49
    }
50
 
51
    /*
52
     * initialise OCI
53
     */
54
    OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t))0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *))0);
55
 
56
    /*
57
     * initialise environment
58
     */
59
    OCIEnvInit((OCIEnv **)&env, OCI_DEFAULT, 0, (dvoid **)0);
60
 
61
    /* 
62
     * server contexts 
63
     */
64
    OCIHandleAlloc((dvoid *)env, (dvoid **)&err, OCI_HTYPE_ERROR, 0, (dvoid **)0);
65
    OCIHandleAlloc((dvoid *)env, (dvoid **)&svc, OCI_HTYPE_SVCCTX, 0, (dvoid **)0);
66
 
67
    /*
68
     * connect to database server
69
     */
70
    rc = OCILogon(env, err, &svc, user, strlen(user), password, strlen(password), db, strlen(db));
71
    if (rc != 0) {
72
	char errbuf[100];
73
	int errcode;
74
 
75
	OCIErrorGet((dvoid *)err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
76
	
77
	lua_pushnil(L);
78
	lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, errbuf);
79
 
80
	return 2;
81
    }
82
 
83
    conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t));
84
    conn->oracle = env;
85
    conn->err = err;
86
    conn->svc = svc;
87
    conn->autocommit = 0;
88
 
89
    luaL_getmetatable(L, DBD_ORACLE_CONNECTION);
90
    lua_setmetatable(L, -2);
91
 
92
    return 1;
93
}
94
 
95
/*
96
 * success = connection:autocommit(on)
97
 */
98
static int connection_autocommit(lua_State *L) {
99
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
100
    int on = lua_toboolean(L, 2); 
101
    int err = 1;
102
 
103
    if (conn->oracle) {
104
	if (on)
105
	    rollback(conn);
106
 
107
	conn->autocommit = on;
108
	err = 0;
109
    }
110
 
111
    lua_pushboolean(L, !err);
112
    return 1;
113
}
114
 
115
 
116
/*
117
 * success = connection:close()
118
 */
119
static int connection_close(lua_State *L) {
120
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
121
    int disconnect = 0;   
122
 
123
    if (conn->oracle) {
124
	rollback(conn);
125
 
126
	OCILogoff(conn->svc, conn->err);
127
	
128
	if (conn->svc)
129
	    OCIHandleFree((dvoid *)conn->svc, OCI_HTYPE_ENV);
130
        if (conn->err)
131
            OCIHandleFree((dvoid *)conn->err, OCI_HTYPE_ERROR);
132
 
133
	disconnect = 1;
134
	conn->oracle = NULL;
135
    }
136
 
137
    lua_pushboolean(L, disconnect);
138
    return 1;
139
}
140
 
141
/*
142
 * success = connection:commit()
143
 */
144
static int connection_commit(lua_State *L) {
145
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
146
    int err = 1;
147
 
148
    if (conn->oracle) {
149
	err = commit(conn);
150
    }
151
 
152
    lua_pushboolean(L, !err);
153
    return 1;
154
}
155
 
156
/*
157
 * ok = connection:ping()
158
 */
159
static int connection_ping(lua_State *L) {
160
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
161
    int ok = 0;   
162
 
163
    if (conn->oracle) {
164
	ok = 1;
165
    }
166
 
167
    lua_pushboolean(L, ok);
168
    return 1;
169
}
170
 
171
/*
172
 * statement,err = connection:prepare(sql_str)
173
 */
174
static int connection_prepare(lua_State *L) {
175
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
176
 
177
    if (conn->oracle) {
178
	return dbd_oracle_statement_create(L, conn, luaL_checkstring(L, 2));
179
    }
180
 
181
    lua_pushnil(L);    
182
    lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE);
183
    return 2;
184
}
185
 
186
/*
187
 * quoted = connection:quote(str)
188
 */
189
static int connection_quote(lua_State *L) {
190
    luaL_error(L, DBI_ERR_NOT_IMPLEMENTED, DBD_ORACLE_CONNECTION, "quote");
191
    return 0;
192
}
193
 
194
/*
195
 * success = connection:rollback()
196
 */
197
static int connection_rollback(lua_State *L) {
198
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
199
    int err = 1;
200
 
201
    if (conn->oracle) {
202
	err = rollback(conn);
203
    }
204
 
205
    lua_pushboolean(L, !err);
206
    return 1;
207
}
208
 
209
/*
210
 * __gc 
211
 */
212
static int connection_gc(lua_State *L) {
213
    /* always close the connection */
214
    connection_close(L);
215
 
216
    return 0;
217
}
218
 
219
/*
220
 * __tostring
221
 */
222
static int connection_tostring(lua_State *L) {
223
    connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION);
224
 
225
    lua_pushfstring(L, "%s: %p", DBD_ORACLE_CONNECTION, conn);
226
 
227
    return 1;
228
}
229
 
230
int dbd_oracle_connection(lua_State *L) {
231
    /*
232
     * instance methods
233
     */
234
    static const luaL_Reg connection_methods[] = {
235
	{"autocommit", connection_autocommit},
236
	{"close", connection_close},
237
	{"commit", connection_commit},
238
	{"ping", connection_ping},
239
	{"prepare", connection_prepare},
240
	{"quote", connection_quote},
241
	{"rollback", connection_rollback},
242
	{NULL, NULL}
243
    };
244
 
245
    /*
246
     * class methods
247
     */
248
    static const luaL_Reg connection_class_methods[] = {
249
	{"New", connection_new},
250
	{NULL, NULL}
251
    };
252
 
253
    luaL_newmetatable(L, DBD_ORACLE_CONNECTION);
254
    luaL_register(L, 0, connection_methods);
255
    lua_pushvalue(L,-1);
256
    lua_setfield(L, -2, "__index");
257
 
258
    lua_pushcfunction(L, connection_gc);
259
    lua_setfield(L, -2, "__gc");
260
 
261
    lua_pushcfunction(L, connection_tostring);
262
    lua_setfield(L, -2, "__tostring");
263
 
264
    luaL_register(L, DBD_ORACLE_CONNECTION, connection_class_methods);
265
 
266
    return 1;    
267
}