*** empty log message ***

This commit is contained in:
eduquintao 2003-07-28 20:10:12 +00:00
parent cf8f7c4e34
commit b5fdc8788e

View File

@ -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.
*/