*** empty log message ***
This commit is contained in:
parent
cf8f7c4e34
commit
b5fdc8788e
172
src/ls_mysql.c
172
src/ls_mysql.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
** LuaSQL, MySQL driver
|
||||
** Authors: Eduardo Quintao
|
||||
** $Id: ls_mysql.c,v 1.3 2003/07/23 18:32:38 eduquintao Exp $
|
||||
** $Id: ls_mysql.c,v 1.4 2003/07/28 20:10:12 eduquintao Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -32,24 +32,31 @@ typedef struct {
|
||||
MYSQL *my_conn;
|
||||
} conn_data;
|
||||
|
||||
|
||||
typedef struct {
|
||||
short closed;
|
||||
int conn; /* reference to connection */
|
||||
int numcols; /* number of columns */
|
||||
int numrows; /* number of rows returned or affected */
|
||||
int colnames, coltypes; /* reference to column information tables */
|
||||
int curr_tuple; /* current tuple to be read by fetch */
|
||||
MYSQL_RES *my_res;
|
||||
} cur_data;
|
||||
|
||||
|
||||
typedef void (*creator) (lua_State *L, cur_data *cur);
|
||||
|
||||
|
||||
LUASQL_API int luasql_libopen_mysql (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** Generates a driver error plus the error message from the database
|
||||
** The generated error message is preceded by LUASQL_PREFIX string
|
||||
*/
|
||||
static int luasql_failmessage(lua_State *L, const char *err, const char *m) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, LUASQL_PREFIX);
|
||||
lua_pushstring(L, err);
|
||||
lua_pushstring(L, m);
|
||||
lua_concat(L, 3);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check for valid environment.
|
||||
*/
|
||||
@ -86,12 +93,12 @@ static cur_data *getcursor (lua_State *L) {
|
||||
/*
|
||||
** Push the value of #i field of #tuple row.
|
||||
*/
|
||||
static void pushvalue (lua_State *L, void *row) {
|
||||
static void pushvalue (lua_State *L, void *row, long int len) {
|
||||
/* Levar em consideracao os tipos mais proximos a lua */
|
||||
if (row == NULL)
|
||||
lua_pushnil (L);
|
||||
else
|
||||
lua_pushstring (L, row);
|
||||
lua_pushlstring (L, row, len);
|
||||
}
|
||||
|
||||
|
||||
@ -102,40 +109,50 @@ static int cur_fetch (lua_State *L) {
|
||||
cur_data *cur = getcursor (L);
|
||||
MYSQL_RES *res = cur->my_res;
|
||||
MYSQL_ROW row;
|
||||
MYSQL_FIELD *fields;
|
||||
int tuple = cur->curr_tuple;
|
||||
fields = mysql_fetch_fields(res);
|
||||
unsigned long *lengths;
|
||||
|
||||
if (tuple >= cur->numrows) {
|
||||
row = mysql_fetch_row(res);
|
||||
if (row == NULL) {
|
||||
lua_pushnil(L); /* no more results */
|
||||
return 1;
|
||||
}
|
||||
lengths = mysql_fetch_lengths(res);
|
||||
|
||||
cur->curr_tuple++;
|
||||
row = mysql_fetch_row(res);
|
||||
if (lua_istable (L, 2)) {
|
||||
int i;
|
||||
const char *opts = luaL_optstring (L, 3, "n");
|
||||
if (strchr (opts, 'n') != NULL)
|
||||
/* Copy values to numerical indices */
|
||||
for (i = 0; i < cur->numcols; i++) {
|
||||
pushvalue (L, row[i]);
|
||||
pushvalue (L, row[i], lengths[i]);
|
||||
lua_rawseti (L, 2, i+1);
|
||||
}
|
||||
if (strchr (opts, 'a') != NULL)
|
||||
if (strchr (opts, 'a') != NULL) {
|
||||
/* Check if colnames exists */
|
||||
if (cur->colnames == LUA_NOREF)
|
||||
create_colinfo(L, cur);
|
||||
lua_rawgeti (L, LUA_REGISTRYINDEX, cur->colnames);/* Push colnames*/
|
||||
|
||||
/* Copy values to alphanumerical indices */
|
||||
for (i = 0; i < cur->numcols; i++) {
|
||||
lua_pushstring (L, fields[i].name);
|
||||
pushvalue (L, row[i]);
|
||||
lua_rawgeti(L, -1, i+1); /* push the field name */
|
||||
|
||||
/* Actually push the value */
|
||||
lua_pushstring (L, lua_tostring(L, -1) );
|
||||
pushvalue (L, row[i], lengths[i]);
|
||||
lua_rawset (L, 2);
|
||||
|
||||
lua_pop(L, 1); /* pop the field name */
|
||||
}
|
||||
lua_pop(L, 1); /* Pops colnames table */
|
||||
}
|
||||
lua_pushvalue(L, 2);
|
||||
return 1; /* return table */
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for (i = 0; i < cur->numcols; i++)
|
||||
pushvalue (L, row[i]);
|
||||
pushvalue (L, row[i], lengths[i]);
|
||||
return cur->numcols; /* return #numcols values */
|
||||
}
|
||||
}
|
||||
@ -153,7 +170,6 @@ static int cur_close (lua_State *L) {
|
||||
|
||||
/* Nullify structure fields. */
|
||||
cur->closed = 1;
|
||||
/* Checar o my_res antes */
|
||||
mysql_free_result(cur->my_res);
|
||||
luaL_unref (L, LUA_REGISTRYINDEX, cur->conn);
|
||||
luaL_unref (L, LUA_REGISTRYINDEX, cur->colnames);
|
||||
@ -185,10 +201,10 @@ static char *getcolumntype (enum enum_field_types type) {
|
||||
return "datetime";
|
||||
case MYSQL_TYPE_TIME:
|
||||
return "time";
|
||||
case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET:
|
||||
return "set";
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
return "timestamp";
|
||||
case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET:
|
||||
return "set";
|
||||
case MYSQL_TYPE_NULL:
|
||||
return "null";
|
||||
default:
|
||||
@ -198,42 +214,25 @@ static char *getcolumntype (enum enum_field_types type) {
|
||||
|
||||
|
||||
/*
|
||||
** Creates the list of fields names and pushes it on top of the stack.
|
||||
** Creates the lists of fields names and fields types.
|
||||
*/
|
||||
static void create_colnames (lua_State *L, cur_data *cur) {
|
||||
/* Posso usar o proprio cur->my_res ???? */
|
||||
MYSQL_RES *result = cur->my_res;
|
||||
static void create_colinfo (lua_State *L, cur_data *cur) {
|
||||
MYSQL_FIELD *fields;
|
||||
char typename[50];
|
||||
int i;
|
||||
fields = mysql_fetch_fields(result);
|
||||
lua_newtable (L);
|
||||
fields = mysql_fetch_fields(cur->my_res);
|
||||
lua_newtable (L); /* names */
|
||||
lua_newtable (L); /* types */
|
||||
for (i = 1; i <= cur->numcols; i++) {
|
||||
lua_pushstring (L, fields[i-1].name);
|
||||
lua_rawseti (L, -2, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Creates the list of fields types and pushes it on top of the stack.
|
||||
*/
|
||||
static void create_coltypes (lua_State *L, cur_data *cur) {
|
||||
/* conn_data *conn; */
|
||||
char typename[100];
|
||||
MYSQL_RES *result = cur->my_res;
|
||||
MYSQL_FIELD *fields;
|
||||
int i;
|
||||
fields = mysql_fetch_fields(result);
|
||||
/* lua_rawgeti (L, LUA_REGISTRYINDEX, cur->conn);
|
||||
if (!lua_isuserdata (L, -1))
|
||||
luaL_error (L, LUASQL_PREFIX"invalid connection");
|
||||
conn = (conn_data *)lua_touserdata (L, -1);*/
|
||||
lua_newtable (L);
|
||||
for (i = 1; i <= cur->numcols; i++) {
|
||||
sprintf (typename, "%.20s (%d)", getcolumntype (fields[i-1].type), fields[i-1].length);
|
||||
lua_rawseti (L, -3, i);
|
||||
sprintf (typename, "%.20s(%ld)", getcolumntype (fields[i-1].type), fields[i-1].length);
|
||||
lua_pushstring(L, typename);
|
||||
lua_rawseti (L, -2, i);
|
||||
}
|
||||
/* Stores the references in the cursor structure */
|
||||
cur->coltypes = luaL_ref (L, LUA_REGISTRYINDEX);
|
||||
cur->colnames = luaL_ref (L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
|
||||
@ -242,25 +241,24 @@ static void create_coltypes (lua_State *L, cur_data *cur) {
|
||||
** If the table isn't built yet, call the creator function and stores
|
||||
** a reference to it on the cursor structure.
|
||||
*/
|
||||
static void _pushtable (lua_State *L, cur_data *cur, size_t off, creator func) {
|
||||
static void _pushtable (lua_State *L, cur_data *cur, size_t off) {
|
||||
int *ref = (int *)((char *)cur + off);
|
||||
if (*ref != LUA_NOREF)
|
||||
lua_rawgeti (L, LUA_REGISTRYINDEX, *ref);
|
||||
else {
|
||||
func (L, cur);
|
||||
/* Stores a reference to it on the cursor structure */
|
||||
lua_pushvalue (L, -1);
|
||||
*ref = luaL_ref (L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
/* If colnames or coltypes do not exist, create both. */
|
||||
if (*ref == LUA_NOREF)
|
||||
create_colinfo(L, cur);
|
||||
|
||||
/* Pushes the right table (colnames or coltypes) */
|
||||
lua_rawgeti (L, LUA_REGISTRYINDEX, *ref);
|
||||
}
|
||||
#define pushtable(L,c,m,f) (_pushtable(L,c,offsetof(cur_data,m),f))
|
||||
#define pushtable(L,c,m) (_pushtable(L,c,offsetof(cur_data,m)))
|
||||
|
||||
|
||||
/*
|
||||
** Return the list of field names.
|
||||
*/
|
||||
static int cur_getcolnames (lua_State *L) {
|
||||
pushtable (L, getcursor(L), colnames, create_colnames);
|
||||
pushtable (L, getcursor(L), colnames);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -269,16 +267,7 @@ static int cur_getcolnames (lua_State *L) {
|
||||
** Return the list of field types.
|
||||
*/
|
||||
static int cur_getcoltypes (lua_State *L) {
|
||||
pushtable (L, getcursor(L), coltypes, create_coltypes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Push the number of rows.
|
||||
*/
|
||||
static int cur_numrows (lua_State *L) {
|
||||
lua_pushnumber (L, getcursor(L)->numrows );
|
||||
pushtable (L, getcursor(L), coltypes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -286,7 +275,7 @@ static int cur_numrows (lua_State *L) {
|
||||
/*
|
||||
** 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 rows, int cols) {
|
||||
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);
|
||||
|
||||
@ -294,10 +283,8 @@ static int create_cursor (lua_State *L, int conn, MYSQL_RES *result, int rows, i
|
||||
cur->closed = 0;
|
||||
cur->conn = LUA_NOREF;
|
||||
cur->numcols = cols;
|
||||
cur->numrows = rows;
|
||||
cur->colnames = LUA_NOREF;
|
||||
cur->coltypes = LUA_NOREF;
|
||||
cur->curr_tuple = 0;
|
||||
cur->my_res = result;
|
||||
lua_pushvalue (L, conn);
|
||||
cur->conn = luaL_ref (L, LUA_REGISTRYINDEX);
|
||||
@ -318,7 +305,6 @@ static int conn_close (lua_State *L) {
|
||||
/* Nullify structure fields. */
|
||||
conn->closed = 1;
|
||||
luaL_unref (L, LUA_REGISTRYINDEX, conn->env);
|
||||
/* Testar o my_conn ?????? */
|
||||
mysql_close(conn->my_conn);
|
||||
lua_pushnumber(L, 1);
|
||||
return 1;
|
||||
@ -335,26 +321,26 @@ static int conn_execute (lua_State *L) {
|
||||
const char *statement = luaL_checkstring (L, 2);
|
||||
unsigned long st_len = strlen(statement);
|
||||
if (!mysql_real_query(conn->my_conn, statement, st_len)) {
|
||||
unsigned int num_rows, num_cols;
|
||||
unsigned int num_cols;
|
||||
MYSQL_RES *res;
|
||||
res = mysql_store_result(conn->my_conn);
|
||||
num_rows = mysql_affected_rows(conn->my_conn);
|
||||
res = mysql_use_result(conn->my_conn);
|
||||
num_cols = mysql_field_count(conn->my_conn);
|
||||
|
||||
if (res) { /* tuples returned */
|
||||
return create_cursor (L, 1, res, num_rows, num_cols);
|
||||
return create_cursor (L, 1, res, num_cols);
|
||||
}
|
||||
else { /* mysql_store_result() returned nothing; should it have? */
|
||||
else { /* mysql_use_result() returned nothing; should it have? */
|
||||
if(num_cols == 0) { /* no tuples returned */
|
||||
/* query does not return data (it was not a SELECT) */
|
||||
lua_pushnumber(L, num_rows);
|
||||
lua_pushnumber(L, mysql_affected_rows(conn->my_conn));
|
||||
return 1;
|
||||
}
|
||||
else /* mysql_store_result() should have returned data */
|
||||
return luasql_faildirect(L, mysql_error(conn->my_conn));
|
||||
else /* mysql_use_result() should have returned data */
|
||||
return luasql_failmessage(L, "Error retrieving result. MySQL: ", mysql_error(conn->my_conn));
|
||||
}
|
||||
}
|
||||
else /* error executing query */
|
||||
return luasql_faildirect(L, mysql_error(conn->my_conn));
|
||||
return luasql_failmessage(L, "Error executing query. MySQL: ", mysql_error(conn->my_conn));
|
||||
}
|
||||
|
||||
|
||||
@ -426,9 +412,9 @@ static int env_connect (lua_State *L) {
|
||||
const char *username = luaL_optstring(L, 3, NULL);
|
||||
const char *password = luaL_optstring(L, 4, NULL);
|
||||
const char *host = luaL_optstring(L, 5, NULL);
|
||||
const char *port = luaL_optstring(L, 6, 0);
|
||||
const int port = luaL_optint(L, 6, 0);
|
||||
|
||||
/* Inicializa o ponteiro da conexao e testa se conseguiu */
|
||||
/* Try to init the connection object. */
|
||||
conn = mysql_init(NULL);
|
||||
if (conn == NULL)
|
||||
return luasql_faildirect(L, LUASQL_PREFIX"Error connecting: Out of memory.");
|
||||
@ -436,10 +422,11 @@ static int env_connect (lua_State *L) {
|
||||
if (!mysql_real_connect(conn, host, username, password,
|
||||
sourcename, port, NULL, 0))
|
||||
{
|
||||
mysql_close(conn);
|
||||
return luasql_faildirect(L, LUASQL_PREFIX"Error connecting to database.");
|
||||
char error_msg[100];
|
||||
strncpy(error_msg, mysql_error(conn), 99);
|
||||
mysql_close(conn); /* Close conn if connect failed */
|
||||
return luasql_failmessage(L, "Error connecting to database. MySQL: ", error_msg);
|
||||
}
|
||||
/*mysql_error(&conn)); */
|
||||
return create_connection(L, 1, conn);
|
||||
}
|
||||
|
||||
@ -459,7 +446,6 @@ static int env_close (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Create metatables for each class of object.
|
||||
*/
|
||||
@ -482,7 +468,6 @@ static void create_metatables (lua_State *L) {
|
||||
{"getcolnames", cur_getcolnames},
|
||||
{"getcoltypes", cur_getcoltypes},
|
||||
{"fetch", cur_fetch},
|
||||
{"numrows", cur_numrows},
|
||||
{NULL, NULL},
|
||||
};
|
||||
luasql_createmeta (L, LUASQL_ENVIRONMENT_MYSQL, environment_methods);
|
||||
@ -490,6 +475,7 @@ static void create_metatables (lua_State *L) {
|
||||
luasql_createmeta (L, LUASQL_CURSOR_MYSQL, cursor_methods);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Creates an Environment and returns it.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user