--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbd/oracle/connection.c Sat Dec 06 00:32:37 2008 +0000 @@ -0,0 +1,244 @@ +#include "dbd_oracle.h" + +int dbd_oracle_statement_create(lua_State *L, connection_t *conn, const char *sql_query); + +static int commit(connection_t *conn) { + int rc = OCITransCommit(conn->svc, conn->err, OCI_DEFAULT); + return rc; +} + +static int rollback(connection_t *conn) { + int rc = OCITransRollback(conn->svc, conn->err, OCI_DEFAULT); + return rc; +} + + +/* + * connection,err = DBD.Oracle.New(dbfile) + */ +static int connection_new(lua_State *L) { + int n = lua_gettop(L); + + int rc = 0; + + const char *user = NULL; + const char *password = NULL; + const char *db = NULL; + + OCIEnv *env = NULL; + OCIError *err = NULL; + OCISvcCtx *svc = NULL; + + connection_t *conn = NULL; + + /* db, user, password */ + switch(n) { + case 5: + case 4: + case 3: + if (lua_isnil(L, 3) == 0) + password = luaL_checkstring(L, 3); + case 2: + if (lua_isnil(L, 2) == 0) + user = luaL_checkstring(L, 2); + case 1: + /* + * db is the only mandatory parameter + */ + db = luaL_checkstring(L, 1); + } + + /* + * initialise OCI + */ + OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t))0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *))0); + + /* + * initialise environment + */ + OCIEnvInit((OCIEnv **)&env, OCI_DEFAULT, 0, (dvoid **)0); + + /* + * server contexts + */ + OCIHandleAlloc((dvoid *)env, (dvoid **)&err, OCI_HTYPE_ERROR, 0, (dvoid **)0); + OCIHandleAlloc((dvoid *)env, (dvoid **)&svc, OCI_HTYPE_SVCCTX, 0, (dvoid **)0); + + /* + * connect to database server + */ + rc = OCILogon(env, err, &svc, user, strlen(user), password, strlen(password), db, strlen(db)); + if (rc != 0) { + char errbuf[100]; + int errcode; + + OCIErrorGet((dvoid *)err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR); + + lua_pushnil(L); + lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, errbuf); + + return 2; + } + + conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t)); + conn->oracle = env; + conn->err = err; + conn->svc = svc; + conn->autocommit = 0; + + luaL_getmetatable(L, DBD_ORACLE_CONNECTION); + lua_setmetatable(L, -2); + + return 1; +} + +/* + * success = connection:autocommit(on) + */ +static int connection_autocommit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION); + int on = lua_toboolean(L, 2); + int err = 1; + + if (conn->oracle) { + if (on) + rollback(conn); + + conn->autocommit = on; + err = 0; + } + + lua_pushboolean(L, !err); + return 1; +} + + +/* + * success = connection:close() + */ +static int connection_close(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION); + int disconnect = 0; + + if (conn->oracle) { + rollback(conn); + + OCILogoff(conn->svc, conn->err); + + if (conn->svc) + OCIHandleFree((dvoid *)conn->svc, OCI_HTYPE_ENV); + if (conn->err) + OCIHandleFree((dvoid *)conn->err, OCI_HTYPE_ERROR); + + disconnect = 1; + conn->oracle = NULL; + } + + lua_pushboolean(L, disconnect); + return 1; +} + +/* + * success = connection:commit() + */ +static int connection_commit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION); + int err = 1; + + if (conn->oracle) { + err = commit(conn); + } + + lua_pushboolean(L, !err); + return 1; +} + +/* + * ok = connection:ping() + */ +static int connection_ping(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION); + int ok = 0; + + if (conn->oracle) { + ok = 1; + } + + lua_pushboolean(L, ok); + return 1; +} + +/* + * statement,err = connection:prepare(sql_str) + */ +static int connection_prepare(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION); + + if (conn->oracle) { + return dbd_oracle_statement_create(L, conn, luaL_checkstring(L, 2)); + } + + lua_pushnil(L); + lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE); + return 2; +} + +/* + * success = connection:rollback() + */ +static int connection_rollback(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_ORACLE_CONNECTION); + int err = 1; + + if (conn->oracle) { + err = rollback(conn); + } + + lua_pushboolean(L, !err); + return 1; +} + +/* + * __gc + */ +static int connection_gc(lua_State *L) { + /* always close the connection */ + connection_close(L); + + return 0; +} + +int dbd_oracle_connection(lua_State *L) { + /* + * instance methods + */ + static const luaL_Reg connection_methods[] = { + {"autocommit", connection_autocommit}, + {"close", connection_close}, + {"commit", connection_commit}, + {"ping", connection_ping}, + {"prepare", connection_prepare}, + {"rollback", connection_rollback}, + {NULL, NULL} + }; + + /* + * class methods + */ + static const luaL_Reg connection_class_methods[] = { + {"New", connection_new}, + {NULL, NULL} + }; + + luaL_newmetatable(L, DBD_ORACLE_CONNECTION); + luaL_register(L, 0, connection_methods); + lua_pushvalue(L,-1); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, connection_gc); + lua_setfield(L, -2, "__gc"); + + luaL_register(L, DBD_ORACLE_CONNECTION, connection_class_methods); + + return 1; +}