/* ** Creates a cursor table and leave it on the top of the stack. */ static int create_cursor (lua_State *L, int o, conn_data *conn, const SQLHSTMT hstmt, const SQLSMALLINT numcols) { cur_data *cur = (cur_data *) lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_ODBC); conn->cur_counter++; /* fill in structure */ cur->closed = 0; cur->conn = LUA_NOREF; cur->numcols = numcols; cur->colnames = LUA_NOREF; cur->coltypes = LUA_NOREF; cur->hstmt = hstmt; lua_pushvalue (L, o); cur->conn = luaL_ref (L, LUA_REGISTRYINDEX); /* make and store column information table */ if(create_colinfo (L, cur) < 0) { lua_pop(L, 1); return fail(L, hSTMT, cur->hstmt); } return 1; }
/* ** Creates an Environment and returns it. */ static int create_environment (lua_State *L) { env_data *env = (env_data *)lua_newuserdata(L, sizeof(env_data)); luasql_setmeta (L, LUASQL_ENVIRONMENT_PG); /* fill in structure */ env->closed = 0; return 1; }
/* ** Create a new Connection object and push it on top of the stack. */ static int create_connection (lua_State *L, int env, MYSQL *const my_conn) { conn_data *conn = (conn_data *)lua_newuserdata(L, sizeof(conn_data)); luasql_setmeta (L, LUASQL_CONNECTION_MYSQL); /* fill in structure */ conn->closed = 0; conn->env = LUA_NOREF; conn->my_conn = my_conn; lua_pushvalue (L, env); conn->env = luaL_ref (L, LUA_REGISTRYINDEX); return 1; }
/* ** Creates an Environment and returns it. */ static int create_environment (lua_State *L) { int i; env_data *env; env = (env_data *)lua_newuserdata (L, sizeof (env_data)); luasql_setmeta (L, LUASQL_ENVIRONMENT_FIREBIRD); /* fill in structure */ for(i=0; i<20; i++) env->status_vector[i] = 0; env->closed = 0; env->lock = 0; return 1; }
/* ** Create a new Connection object and push it on top of the stack. */ static int create_connection(lua_State *L, int env, sqlite3 *sql_conn) { conn_data *conn = (conn_data*)lua_newuserdata(L, sizeof(conn_data)); luasql_setmeta(L, LUASQL_CONNECTION_SQLITE); /* fill in structure */ conn->closed = 0; conn->env = LUA_NOREF; conn->auto_commit = 1; conn->sql_conn = sql_conn; conn->cur_counter = 0; lua_pushvalue (L, env); conn->env = luaL_ref (L, LUA_REGISTRYINDEX); return 1; }
/* ** Create a new Cursor object and push it on top of the stack. */ static int create_cursor (lua_State *L, int conn, MYSQL_RES *result, int cols) { cur_data *cur = (cur_data *)lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_MYSQL); /* fill in structure */ cur->closed = 0; cur->conn = LUA_NOREF; cur->numcols = cols; cur->colnames = LUA_NOREF; cur->coltypes = LUA_NOREF; cur->my_res = result; lua_pushvalue (L, conn); cur->conn = luaL_ref (L, LUA_REGISTRYINDEX); return 1; }
/* ** Create a new Cursor object and push it on top of the stack. */ static int create_cursor (lua_State *L, int conn, PGresult *result) { cur_data *cur = (cur_data *)lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_PG); /* fill in structure */ cur->closed = 0; cur->conn = LUA_NOREF; cur->numcols = PQnfields(result); cur->colnames = LUA_NOREF; cur->coltypes = LUA_NOREF; cur->curr_tuple = 0; cur->pg_res = result; lua_pushvalue (L, conn); cur->conn = luaL_ref (L, LUA_REGISTRYINDEX); return 1; }
/* ** Connects to a data source. */ static int env_connect (lua_State *L) { env_data *env = getenvironment (L); const char *sourcename = luaL_checkstring(L, 2); const char *username = luaL_optstring(L, 3, NULL); const char *password = luaL_optstring(L, 4, NULL); /* Sizes of strings */ size_t snlen = strlen(sourcename); size_t userlen = (username) ? strlen(username) : 0; size_t passlen = (password) ? strlen(password) : 0; /* Alloc connection object */ conn_data *conn = (conn_data *)lua_newuserdata(L, sizeof(conn_data)); /* fill in structure */ luasql_setmeta (L, LUASQL_CONNECTION_OCI8); conn->env = LUA_NOREF; conn->closed = 1; conn->auto_commit = 1; conn->cur_counter = 0; conn->loggedon = 0; conn->svchp = NULL; conn->errhp = NULL; lua_pushvalue (L, 1); conn->env = luaL_ref (L, LUA_REGISTRYINDEX); /* error handler */ ASSERT (L, OCIHandleAlloc((dvoid *) env->envhp, (dvoid **) &(conn->errhp), /* !!! */ (ub4) OCI_HTYPE_ERROR, (size_t) 0, (dvoid **) 0), env->errhp); /* service handler */ /*ASSERT (L, OCIHandleAlloc((dvoid *) env->envhp, (dvoid **) &(conn->svchp), (ub4) OCI_HTYPE_SVCCTX, (size_t) 0, (dvoid **) 0), conn->errhp); */ /* login */ ASSERT (L, OCILogon(env->envhp, conn->errhp, &(conn->svchp), (CONST text*)username, userlen, (CONST text*)password, passlen, (CONST text*)sourcename, snlen), conn->errhp); conn->closed = 0; env->conn_counter++; conn->loggedon = 1; return 1; }
/* ** Create a new Cursor object and push it on top of the stack. */ static int create_cursor (lua_State *L, int o, conn_data *conn, OCIStmt *stmt, const char *text) { int i; env_data *env; cur_data *cur = (cur_data *)lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_OCI8); conn->cur_counter++; /* fill in structure */ cur->closed = 0; cur->numcols = 0; cur->colnames = LUA_NOREF; cur->coltypes = LUA_NOREF; cur->curr_tuple = 0; cur->stmthp = stmt; cur->errhp = NULL; cur->cols = NULL; cur->text = strdup (text); lua_pushvalue (L, o); cur->conn = luaL_ref (L, LUA_REGISTRYINDEX); /* error handler */ lua_rawgeti (L, LUA_REGISTRYINDEX, conn->env); env = lua_touserdata (L, -1); lua_pop (L, 1); ASSERT (L, OCIHandleAlloc((dvoid *) env->envhp, (dvoid **) &(cur->errhp), (ub4) OCI_HTYPE_ERROR, (size_t) 0, (dvoid **) 0), conn->errhp); /* get number of columns */ ASSERT (L, OCIAttrGet ((dvoid *)stmt, (ub4)OCI_HTYPE_STMT, (dvoid *)&cur->numcols, (ub4 *)0, (ub4)OCI_ATTR_PARAM_COUNT, cur->errhp), cur->errhp); cur->cols = (column_data *)malloc (sizeof(column_data) * cur->numcols); /* define output variables */ /* Oracle and Lua column indices ranges from 1 to numcols */ /* C array indices ranges from 0 to numcols-1 */ for (i = 1; i <= cur->numcols; i++) { int ret = alloc_column_buffer (L, cur, i); if (ret) return ret; } return 1; }
/* static int create_cursor(lua_State *L, int conn, sqlite3_stmt *sql_vm, int numcols, const char **row, const char **col_info)*/ static int create_cursor(lua_State *L, int o, conn_data *conn, sqlite3_stmt *sql_vm, int numcols) { int i; cur_data *cur = (cur_data*)lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_SQLITE); /* increment cursor count for the connection creating this cursor */ conn->cur_counter++; /* fill in structure */ cur->closed = 0; cur->conn = LUA_NOREF; cur->numcols = numcols; cur->colnames = LUA_NOREF; cur->coltypes = LUA_NOREF; cur->sql_vm = sql_vm; cur->conn_data = conn; lua_pushvalue(L, o); cur->conn = luaL_ref(L, LUA_REGISTRYINDEX); /* create table with column names */ lua_newtable(L); for (i = 0; i < numcols;) { lua_pushstring(L, sqlite3_column_name(sql_vm, i)); lua_rawseti(L, -2, ++i); } cur->colnames = luaL_ref(L, LUA_REGISTRYINDEX); /* create table with column types */ lua_newtable(L); for (i = 0; i < numcols;) { lua_pushstring(L, sqlite3_column_decltype(sql_vm, i)); lua_rawseti(L, -2, ++i); } cur->coltypes = luaL_ref(L, LUA_REGISTRYINDEX); return 1; }
/* ** Create a new Connection object and push it on top of the stack. */ static int create_connection (lua_State *L, int o, env_data *env, SQLHDBC hdbc) { conn_data *conn = (conn_data *) lua_newuserdata(L, sizeof(conn_data)); /* set auto commit mode */ SQLRETURN ret = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_ON, 0); if (error(ret)) return fail(L, hDBC, hdbc); luasql_setmeta (L, LUASQL_CONNECTION_ODBC); /* fill in structure */ conn->closed = 0; conn->cur_counter = 0; conn->env = LUA_NOREF; conn->hdbc = hdbc; lua_pushvalue (L, o); conn->env = luaL_ref (L, LUA_REGISTRYINDEX); env->conn_counter++; return 1; }
/* ** Creates an Environment and returns it. */ static int create_environment (lua_State *L) { env_data *env = (env_data *)lua_newuserdata(L, sizeof(env_data)); luasql_setmeta (L, LUASQL_ENVIRONMENT_OCI8); /* fill in structure */ env->closed = 0; env->conn_counter = 0; env->envhp = NULL; env->errhp = NULL; /* maybe OCI_SHARED and OCI_THREADED ??? */ if (OCIEnvCreate ( &(env->envhp), (ub4)OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t)) 0, (void (*)(dvoid *, dvoid *)) 0, (size_t) 0, (dvoid **) 0)) luasql_faildirect (L, "couldn't create environment"); /* error handler */ ASSERT (L, OCIHandleAlloc((dvoid *) env->envhp, (dvoid **) &(env->errhp), /* !!! */ (ub4) OCI_HTYPE_ERROR, (size_t) 0, (dvoid **) 0), env->errhp); return 1; }
/* ** Creates an Environment and returns it. */ static int create_environment (lua_State *L) { env_data *env; SQLHENV henv; SQLRETURN ret = SQLAllocHandle(hENV, SQL_NULL_HANDLE, &henv); if (error(ret)) return luasql_faildirect(L, "error creating environment."); ret = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if (error(ret)) { ret = luasql_faildirect (L, "error setting SQL version."); SQLFreeHandle (hENV, henv); return ret; } env = (env_data *)lua_newuserdata (L, sizeof (env_data)); luasql_setmeta (L, LUASQL_ENVIRONMENT_ODBC); /* fill in structure */ env->closed = 0; env->conn_counter = 0; env->henv = henv; return 1; }
/* ** Creates and returns a connection object ** Lua Input: source, user, pass ** source: data source ** user, pass: data source authentication information ** Lua Returns: ** connection object if successfull ** nil and error message otherwise. */ static int env_connect (lua_State *L) { char *dpb; int i; static char isc_tpb[] = { isc_tpb_version3, isc_tpb_write }; conn_data conn; conn_data* res_conn; env_data *env = (env_data *) getenvironment (L, 1); const char *sourcename = luaL_checkstring (L, 2); const char *username = luaL_optstring (L, 3, ""); const char *password = luaL_optstring (L, 4, ""); conn.env = env; conn.db = 0L; conn.transaction = 0L; conn.lock = 0; conn.autocommit = 0; /* Construct a database parameter buffer. */ dpb = conn.dpb_buffer; *dpb++ = isc_dpb_version1; *dpb++ = isc_dpb_num_buffers; *dpb++ = 1; *dpb++ = 90; /* add the user name and password */ *dpb++ = isc_dpb_user_name; *dpb++ = (char)strlen(username); for(i=0; i<(int)strlen(username); i++) *dpb++ = username[i]; *dpb++ = isc_dpb_password; *dpb++ = (char)strlen(password); for(i=0; i<(int)strlen(password); i++) *dpb++ = password[i]; /* the length of the dpb */ conn.dpb_length = (short)(dpb - conn.dpb_buffer); /* do the job */ isc_attach_database(env->status_vector, (short)strlen(sourcename), (char*)sourcename, &conn.db, conn.dpb_length, conn.dpb_buffer); /* an error? */ if ( CHECK_DB_ERROR(conn.env->status_vector) ) return return_db_error(L, conn.env->status_vector); /* open up the transaction handle */ isc_start_transaction( env->status_vector, &conn.transaction, 1, &conn.db, (unsigned short)sizeof(isc_tpb), isc_tpb ); /* return NULL on error */ if ( CHECK_DB_ERROR(conn.env->status_vector) ) return return_db_error(L, conn.env->status_vector); /* create the lua object and add the connection to the lock */ res_conn = (conn_data*)lua_newuserdata(L, sizeof(conn_data)); luasql_setmeta (L, LUASQL_CONNECTION_FIREBIRD); memcpy(res_conn, &conn, sizeof(conn_data)); res_conn->closed = 0; /* connect now officially open */ /* register the connection */ lua_registerobj(L, 1, env); ++env->lock; return 1; }
/* ** Executes a SQL statement. ** Returns ** cursor object: if there are results or ** row count: number of rows affected by statement if no results */ static int conn_execute (lua_State *L) { conn_data *conn = getconnection(L,1); const char *statement = luaL_checkstring(L, 2); int dialect = (int)luaL_optnumber(L, 3, 3); XSQLVAR *var; long dtype; int i, n, count, stmt_type; cur_data cur; cur.closed = 0; cur.env = conn->env; cur.conn = conn; cur.stmt = NULL; cur.out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(CURSOR_PREALLOC)); cur.out_sqlda->version = SQLDA_VERSION1; cur.out_sqlda->sqln = CURSOR_PREALLOC; /* create a statement to handle the query */ isc_dsql_allocate_statement(conn->env->status_vector, &conn->db, &cur.stmt); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } /* process the SQL ready to run the query */ isc_dsql_prepare(conn->env->status_vector, &conn->transaction, &cur.stmt, 0, (char*)statement, dialect, cur.out_sqlda); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } /* what type of SQL statement is it? */ stmt_type = get_statement_type(&cur); if(stmt_type < 0) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } /* an unsupported SQL statement (something like COMMIT) */ if(stmt_type > 5) { free(cur.out_sqlda); return luasql_faildirect(L, "unsupported SQL statement"); } /* resize the result set if needed */ if (cur.out_sqlda->sqld > cur.out_sqlda->sqln) { n = cur.out_sqlda->sqld; free(cur.out_sqlda); cur.out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(n)); cur.out_sqlda->sqln = n; cur.out_sqlda->version = SQLDA_VERSION1; isc_dsql_describe(conn->env->status_vector, &cur.stmt, 1, cur.out_sqlda); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } } /* prep the result set ready to handle the data */ for (i=0, var = cur.out_sqlda->sqlvar; i < cur.out_sqlda->sqld; i++, var++) { dtype = (var->sqltype & ~1); /* drop flag bit for now */ switch(dtype) { case SQL_VARYING: var->sqldata = (char *)malloc(sizeof(char)*var->sqllen + 2); break; case SQL_TEXT: var->sqldata = (char *)malloc(sizeof(char)*var->sqllen); break; case SQL_SHORT: var->sqldata = (char *)malloc(sizeof(short)); break; case SQL_LONG: var->sqldata = (char *)malloc(sizeof(long)); break; case SQL_INT64: var->sqldata = (char *)malloc(sizeof(ISC_INT64)); break; case SQL_FLOAT: var->sqldata = (char *)malloc(sizeof(float)); break; case SQL_DOUBLE: var->sqldata = (char *)malloc(sizeof(double)); break; case SQL_TYPE_TIME: var->sqldata = (char *)malloc(sizeof(ISC_TIME)); break; case SQL_TYPE_DATE: var->sqldata = (char *)malloc(sizeof(ISC_DATE)); break; case SQL_TIMESTAMP: var->sqldata = (char *)malloc(sizeof(ISC_TIMESTAMP)); break; case SQL_BLOB: var->sqldata = (char *)malloc(sizeof(ISC_QUAD)); break; /* TODO : add extra data type handles here */ } if (var->sqltype & 1) { /* allocate variable to hold NULL status */ var->sqlind = (short *)malloc(sizeof(short)); } else { var->sqlind = NULL; } } /* run the query */ isc_dsql_execute(conn->env->status_vector, &conn->transaction, &cur.stmt, 1, NULL); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free_cur(&cur); return return_db_error(L, conn->env->status_vector); } /* if autocommit is set and it's a non SELECT query, commit change */ if(conn->autocommit != 0 && stmt_type > 1) { isc_commit_retaining(conn->env->status_vector, &conn->transaction); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free_cur(&cur); return return_db_error(L, conn->env->status_vector); } } /* what do we return? a cursor or a count */ if(cur.out_sqlda->sqld > 0) { /* a cursor */ cur_data* user_cur; /* open the cursor ready for fetch cycles */ isc_dsql_set_cursor_name(cur.env->status_vector, &cur.stmt, "dyn_cursor", (unsigned short)NULL); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free_cur(&cur); return return_db_error(L, conn->env->status_vector); } /* copy the cursor into a new lua userdata object */ user_cur = (cur_data*)lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_FIREBIRD); memcpy((void*)user_cur, (void*)&cur, sizeof(cur_data)); /* add cursor to the lock count */ lua_registerobj(L, 1, conn); ++conn->lock; } else { /* a count */ if( (count = count_rows_affected(&cur)) < 0 ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } lua_pushnumber(L, count); /* totaly finnished with the cursor */ isc_dsql_free_statement(conn->env->status_vector, &cur.stmt, DSQL_drop); free(cur.out_sqlda); } return 1; }