Example #1
0
/*
** Closes a connection.
** Lua Returns:
**   1 if close was sucsessful, 0 if already closed
**   nil and error message otherwise.
*/
static int conn_close (lua_State *L) {
    conn_data *conn = (conn_data *)luaL_checkudata(L,1,LUASQL_CONNECTION_FIREBIRD);
    luaL_argcheck (L, conn != NULL, 1, "connection expected");

    /* already closed */
    if(conn->closed != 0) {
        lua_pushboolean(L, 0);
        return 1;
    }

    /* are all related cursors closed? */
    if(conn->lock > 0)
        return luasql_faildirect(L, "there are still open cursors");

    if(conn->autocommit != 0)
        isc_commit_transaction(conn->env->status_vector, &conn->transaction);
    else
        isc_rollback_transaction(conn->env->status_vector, &conn->transaction);
    if ( CHECK_DB_ERROR(conn->env->status_vector) )
        return return_db_error(L, conn->env->status_vector);

    isc_detach_database(conn->env->status_vector, &conn->db);
    if ( CHECK_DB_ERROR(conn->env->status_vector) )
        return return_db_error(L, conn->env->status_vector);

    conn->closed = 1;
    --conn->env->lock;

    /* check environment can be GC'd */
    if(conn->env->lock == 0)
        lua_unregisterobj(L, conn->env);

    lua_pushboolean(L, 1);
    return 1;
}
Example #2
0
/*
** Connects to a data source.
*/
static int env_connect(lua_State *L)
{
  const char *sourcename;
  sqlite3 *conn;
  const char *errmsg;
  int res;
  getenvironment(L);  /* validate environment */

  sourcename = luaL_checkstring(L, 2);

  res = sqlite3_open(sourcename, &conn);
  if (res != SQLITE_OK)
    {
      errmsg = sqlite3_errmsg(conn);
      luasql_faildirect(L, errmsg);
      sqlite3_close(conn);
      return 2;
    }

  if (lua_isnumber(L, 3)) {
  	sqlite3_busy_timeout(conn, lua_tonumber(L,3)); // TODO: remove this
  }

  return create_connection(L, 1, conn);
}
Example #3
0
/*
** 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) {
	env_data *env = (env_data *) 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);
	SQLHDBC hdbc;
	SQLRETURN ret;

	/* tries to allocate connection handle */
	ret = SQLAllocHandle (hDBC, env->henv, &hdbc);
	if (error(ret))
		return luasql_faildirect (L, "connection allocation error.");

	/* tries to connect handle */
	ret = SQLConnect (hdbc, (char *) sourcename, SQL_NTS, 
		(char *) username, SQL_NTS, (char *) password, SQL_NTS);
	if (error(ret)) {
		ret = fail(L, hDBC, hdbc);
		SQLFreeHandle(hDBC, hdbc);
		return ret;
	}

	/* success, return connection object */
	return create_connection (L, 1, env, hdbc);
}
Example #4
0
/*
** Execute an SQL statement.
** Return a Cursor object if the statement is a query, otherwise
** return the number of tuples affected by the statement.
*/
static int conn_execute(lua_State *L)
{
  conn_data *conn = getconnection(L);
  const char *statement = luaL_checkstring(L, 2);
  int res;
  sqlite3_stmt *vm;
  const char *errmsg;
  int numcols;
  const char *tail;

  res = sqlite3_prepare(conn->sql_conn, statement, -1, &vm, &tail);
  if (res != SQLITE_OK)
    {
      errmsg = sqlite3_errmsg(conn->sql_conn);
      return luasql_faildirect(L, errmsg);
    }

  /* process first result to retrive query information and type */
  res = sqlite3_step(vm);
  numcols = sqlite3_column_count(vm);

  /* real query? if empty, must have numcols!=0 */
  if ((res == SQLITE_ROW) || ((res == SQLITE_DONE) && numcols))
    {
      sqlite3_reset(vm);
      return create_cursor(L, 1, conn, vm, numcols);
    }

  if (res == SQLITE_DONE) /* and numcols==0, INSERT,UPDATE,DELETE statement */
    {
      sqlite3_finalize(vm);
      /* return number of columns changed */
      lua_pushnumber(L, sqlite3_changes(conn->sql_conn));
      return 1;
    }

  /* error */
  errmsg = sqlite3_errmsg(conn->sql_conn);
  sqlite3_finalize(vm);
  return luasql_faildirect(L, errmsg);
}
Example #5
0
/*
** Finalizes the vm
** Return nil + errmsg or nil in case of sucess
*/
static int finalize(lua_State *L, cur_data *cur) {
  const char *errmsg;
  if (sqlite3_finalize(cur->sql_vm) != SQLITE_OK)
    {
      errmsg = sqlite3_errmsg(cur->conn_data->sql_conn);
      cur->sql_vm = NULL;
      return luasql_faildirect(L, errmsg);
    }
  cur->sql_vm = NULL;
  lua_pushnil(L);
  return 1;
}
Example #6
0
/*
** 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;
}
Example #7
0
/*
** 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;
}
Example #8
0
/*
** Closes an environment object
** Lua Returns:
**   1 if close was sucsessful, 0 if already closed
**   nil and error message otherwise.
*/
static int env_close (lua_State *L) {
    env_data *env = (env_data *)luaL_checkudata (L, 1, LUASQL_ENVIRONMENT_FIREBIRD);
    luaL_argcheck (L, env != NULL, 1, "environment expected");

    /* already closed? */
    if(env->closed == 1) {
        lua_pushboolean(L, 0);
        return 1;
    }

    /* check the lock */
    if(env->lock > 0)
        return luasql_faildirect(L, "there are still open connections");

    /* unregister */
    lua_unregisterobj(L, env);

    /* mark as closed */
    env->closed = 1;

    lua_pushboolean(L, 1);
    return 1;
}
Example #9
0
/*
** Connects to a data source.
**     param: one string for each connection parameter, said
**     datasource, username, password, host and port.
*/
static int env_connect (lua_State *L) {
	const char *sourcename = luaL_checkstring(L, 2);
	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 int port = luaL_optint(L, 6, 0);
	MYSQL *conn;
	getenvironment(L); /* validade environment */

	/* Try to init the connection object. */
	conn = mysql_init(NULL);
	if (conn == NULL)
		return luasql_faildirect(L, LUASQL_PREFIX"Error connecting: Out of memory.");

	if (!mysql_real_connect(conn, host, username, password, 
		sourcename, port, NULL, 0))
	{
		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);
	}
	return create_connection(L, 1, conn);
}
Example #10
0
/*
** 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;
}
Example #11
0
/*
** Retrieves data from the i_th column in the current row
** Input
**   types: index in stack of column types table
**   hstmt: statement handle
**   i: column number
** Returns:
**   0 if successfull, non-zero otherwise;
*/
static int push_column(lua_State *L, int coltypes, const SQLHSTMT hstmt, 
        SQLUSMALLINT i) {
    const char *tname;
    char type;
    /* get column type from types table */
	lua_rawgeti (L, LUA_REGISTRYINDEX, coltypes);
	lua_rawgeti (L, -1, i);	/* typename of the column */
    tname = lua_tostring(L, -1);
    if (!tname)
		return luasql_faildirect(L, "invalid type in table.");
    type = tname[1];
    lua_pop(L, 2);	/* pops type name and coltypes table */

    /* deal with data according to type */
    switch (type) {
        /* nUmber */
        case 'u': { 
			double num;
			SQLINTEGER got;
			SQLRETURN rc = SQLGetData(hstmt, i, SQL_C_DOUBLE, &num, 0, &got);
			if (error(rc))
				return fail(L, hSTMT, hstmt);
			if (got == SQL_NULL_DATA)
				lua_pushnil(L);
			else
				lua_pushnumber(L, num);
			return 0;
		}
                  /* bOol */
        case 'o': { 
			char b;
			SQLINTEGER got;
			SQLRETURN rc = SQLGetData(hstmt, i, SQL_C_BIT, &b, 0, &got);
			if (error(rc))
				return fail(L, hSTMT, hstmt);
			if (got == SQL_NULL_DATA)
				lua_pushnil(L);
			else
				lua_pushboolean(L, b);
			return 0;
		}
        /* sTring */
        case 't': 
        /* bInary */
        case 'i': { 
			SQLSMALLINT stype = (type == 't') ? SQL_C_CHAR : SQL_C_BINARY;
			SQLINTEGER got;
			char *buffer;
			luaL_Buffer b;
			SQLRETURN rc;
			luaL_buffinit(L, &b);
			buffer = luaL_prepbuffer(&b);
			rc = SQLGetData(hstmt, i, stype, buffer, LUAL_BUFFERSIZE, &got);
			if (got == SQL_NULL_DATA) {
				lua_pushnil(L);
				return 0;
			}
			/* concat intermediary chunks */
			while (rc == SQL_SUCCESS_WITH_INFO) {
				if (got >= LUAL_BUFFERSIZE || got == SQL_NO_TOTAL) {
					got = LUAL_BUFFERSIZE;
					/* get rid of null termination in string block */
					if (stype == SQL_C_CHAR) got--;
				}
				luaL_addsize(&b, got);
				buffer = luaL_prepbuffer(&b);
				rc = SQLGetData(hstmt, i, stype, buffer, 
					LUAL_BUFFERSIZE, &got);
			}
			/* concat last chunk */
			if (rc == SQL_SUCCESS) {
				if (got >= LUAL_BUFFERSIZE || got == SQL_NO_TOTAL) {
					got = LUAL_BUFFERSIZE;
					/* get rid of null termination in string block */
					if (stype == SQL_C_CHAR) got--;
				}
				luaL_addsize(&b, got);
			}
			if (rc == SQL_ERROR) return fail(L, hSTMT, hstmt);
			/* return everything we got */
			luaL_pushresult(&b);
			return 0;
		}
    }
    return 0;
}