Exemple #1
0
/*
 * success, event = stmt:prepare_start(query)
 */
static int
statement_prepare_start (lua_State * L) /* {{{ */
{
  statement_t *statement =
    (statement_t *) luaL_checkudata (L, 1, DBD_MYSQL_STATEMENT);
  const char *sql_query = luaL_checkstring (L, 2);
  unsigned long sql_len = strlen (sql_query);

  if (!statement->stmt)
    {
      luaL_error (L, DBI_ERR_INVALID_STATEMENT);
    }

  statement->event =
    mysql_stmt_prepare_start (&(statement->ret), statement->stmt,
			      sql_query, sql_len);

  if (statement->event & MYSQL_WAIT_EXCEPT)
    {
      lua_pushnil (L);
      lua_pushfstring (L, DBI_ERR_PREP_STATEMENT,
		       mysql_stmt_error (statement->stmt));
      return 2;
    }

  if (statement->event & MYSQL_WAIT_TIMEOUT)
    {
      statement->timeout =
	1000 * mysql_get_timeout_value_ms (statement->mysql);
    }

  lua_pushboolean (L, 1);
  lua_pushnumber (L, convert_mysql_to_ev (statement->event));
  return 2;
} /* }}} */
Exemple #2
0
/*
 * success,err = statement:execute_cont(...)
 */
static int
statement_execute_cont (lua_State * L) /* {{{ */
{
  statement_t *statement =
    (statement_t *) luaL_checkudata (L, 1, DBD_MYSQL_STATEMENT);
  int event = convert_ev_to_mysql (lua_tonumber (L, 2));
  MYSQL_RES *metadata = NULL;

  if (!statement->stmt)
    {
      luaL_error (L, DBI_ERR_INVALID_STATEMENT);
    }
  statement->event =
    mysql_stmt_execute_cont (&(statement->ret), statement->stmt, event);

  if (statement->event & MYSQL_WAIT_EXCEPT)
    {
      lua_pushnil (L);
      lua_pushfstring (L, DBI_ERR_BINDING_EXEC,
		       mysql_stmt_error (statement->stmt));
    }

  if (statement->event & MYSQL_WAIT_TIMEOUT)
    {
      statement->timeout =
	1000 * mysql_get_timeout_value_ms (statement->mysql);
    }
  if (statement->ret)
    {
      lua_pushnil (L);
      lua_pushfstring (L, DBI_ERR_BINDING_EXEC,
		       mysql_stmt_error (statement->stmt));
      return 2;
    }
  if (statement->event > 0)
    {
      lua_pushboolean (L, 0);
      lua_pushnumber (L, convert_mysql_to_ev (statement->event));
      return 2;
    }

  metadata = mysql_stmt_result_metadata (statement->stmt);

  statement->metadata = metadata;

  lua_pushboolean (L, 1);
  return 1;
} /* }}} */
static int
wait_for_mysql(MYSQL *mysql, int status)
{
#ifdef _WIN32
  fd_set rs, ws, es;
  int res;
  struct timeval tv, *timeout;
  my_socket s= mysql_get_socket(mysql);
  FD_ZERO(&rs);
  FD_ZERO(&ws);
  FD_ZERO(&es);
  if (status & MYSQL_WAIT_READ)
    FD_SET(s, &rs);
  if (status & MYSQL_WAIT_WRITE)
    FD_SET(s, &ws);
  if (status & MYSQL_WAIT_EXCEPT)
    FD_SET(s, &es);
  if (status & MYSQL_WAIT_TIMEOUT)
  {
    tv.tv_sec= mysql_get_timeout_value(mysql);
    tv.tv_usec= 0;
    timeout= &tv;
  }
  else
    timeout= NULL;
  res= select(1, &rs, &ws, &es, timeout);
  if (res == 0)
    return MYSQL_WAIT_TIMEOUT;
  else if (res == SOCKET_ERROR)
  {
    /*
      In a real event framework, we should handle errors and re-try the select.
    */
    return MYSQL_WAIT_TIMEOUT;
  }
  else
  {
    int status= 0;
    if (FD_ISSET(s, &rs))
      status|= MYSQL_WAIT_READ;
    if (FD_ISSET(s, &ws))
      status|= MYSQL_WAIT_WRITE;
    if (FD_ISSET(s, &es))
      status|= MYSQL_WAIT_EXCEPT;
    return status;
  }
#else
  struct pollfd pfd;
  int timeout;
  int res= -1;

  pfd.fd= mysql_get_socket(mysql);
  pfd.events=
    (status & MYSQL_WAIT_READ ? POLLIN : 0) |
    (status & MYSQL_WAIT_WRITE ? POLLOUT : 0) |
    (status & MYSQL_WAIT_EXCEPT ? POLLPRI : 0);
  if (status & MYSQL_WAIT_TIMEOUT)
    timeout= mysql_get_timeout_value_ms(mysql);
  else
    timeout= -1;
  do {
    res= poll(&pfd, 1, timeout);
  } while (res == -1 && errno == EINTR);
  if (res == 0)
    return MYSQL_WAIT_TIMEOUT;
  else if (res < 0)
  {
    /*
      In a real event framework, we should handle EINTR and re-try the poll.
    */
    return MYSQL_WAIT_TIMEOUT;
  }
  else
  {
    int status= 0;
    if (pfd.revents & POLLIN)
      status|= MYSQL_WAIT_READ;
    if (pfd.revents & POLLOUT)
      status|= MYSQL_WAIT_WRITE;
    if (pfd.revents & POLLPRI)
      status|= MYSQL_WAIT_EXCEPT;
    return status;
  }
#endif
}
Exemple #4
0
static int
statement_fetch_impl_cont (lua_State * L, statement_t * statement, /* {{{ */
			   int event, int named_columns)
{
  int column_count;
  unsigned long *real_length = NULL;
  int values = 0;

  column_count = mysql_num_fields (statement->metadata);

  if (column_count > 0)
    {
      int i;

      real_length = calloc (column_count, sizeof (unsigned long));

      statement->event =
	mysql_stmt_fetch_cont (&(statement->ret), statement->stmt, event);

      if (statement->event & MYSQL_WAIT_EXCEPT)
	{
	  lua_pushnil (L);
	  lua_pushfstring (L, mysql_stmt_error (statement->stmt));
	  values = 2;
	}

      if (statement->event & MYSQL_WAIT_TIMEOUT)
	{
	  statement->timeout =
	    1000 * mysql_get_timeout_value_ms (statement->mysql);
	}
      /* Pretty sure statement->ret should be the return value, but it seems to return 1 */
      /* using mysql_stmt_errno instead */
      if (mysql_stmt_errno (statement->stmt) != 0)
	{
	  lua_pushnil (L);
	  lua_pushstring (L, mysql_stmt_error (statement->stmt));
	  values = 2;
	}
      if (statement->event > 0)
	{
	  lua_pushboolean (L, 0);
	  lua_pushnumber (L, convert_mysql_to_ev (statement->event));
	  values = 2;
	}

      if (mysql_stmt_errno (statement->stmt) == 0
	  || statement->ret == MYSQL_DATA_TRUNCATED)
	{
	  int d = 1;

	  lua_pushboolean (L, 1);
	  lua_newtable (L);
	  values = 2;
	  for (i = 0; i < column_count; i++)
	    {
	      lua_push_type_t lua_push =
		mysql_to_lua_push (statement->fields[i].type);
	      const char *name = statement->fields[i].name;

	      if (statement->bind[i].buffer == NULL)
		{
		  char *buffer =
		    (char *) calloc (real_length[i] + 1, sizeof (char));
		  statement->bind[i].buffer = buffer;
		  statement->bind[i].buffer_length = real_length[i];
		  mysql_stmt_fetch_column (statement->stmt,
					   &(statement->bind[i]), i, 0);
		}

	      if (lua_push == LUA_PUSH_NIL)
		{
		  if (named_columns)
		    {
		      LUA_PUSH_ATTRIB_NIL (name);
		    }
		  else
		    {
		      LUA_PUSH_ARRAY_NIL (d);
		    }
		}
	      else if (lua_push == LUA_PUSH_INTEGER)
		{
		  if (statement->fields[i].type == MYSQL_TYPE_YEAR
		      || statement->fields[i].type == MYSQL_TYPE_SHORT)
		    {
		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_INT (name,
					       *(short
						 *) (statement->
						     bind[i].buffer));
			}
		      else
			{
			  LUA_PUSH_ARRAY_INT (d,
					      *(short
						*) (statement->
						    bind[i].buffer));
			}
		    }
		  else if (statement->fields[i].type == MYSQL_TYPE_TINY)
		    {
		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_INT (name,
					       (int) *(char
						       *) (statement->bind
							   [i].buffer));
			}
		      else
			{
			  LUA_PUSH_ARRAY_INT (d,
					      (int) *(char
						      *) (statement->bind
							  [i].buffer));
			}
		    }
		  else
		    {
		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_INT (name,
					       *(int
						 *) (statement->
						     bind[i].buffer));
			}
		      else
			{
			  LUA_PUSH_ARRAY_INT (d,
					      *(int
						*) (statement->
						    bind[i].buffer));
			}
		    }
		}
	      else if (lua_push == LUA_PUSH_NUMBER)
		{
		  if (named_columns)
		    {
		      LUA_PUSH_ATTRIB_FLOAT (name,
					     *(double
					       *) (statement->
						   bind[i].buffer));
		    }
		  else
		    {
		      LUA_PUSH_ARRAY_FLOAT (d,
					    *(double
					      *) (statement->bind[i].buffer));
		    }
		}
	      else if (lua_push == LUA_PUSH_STRING)
		{

		  if (statement->fields[i].type == MYSQL_TYPE_TIMESTAMP
		      || statement->fields[i].type == MYSQL_TYPE_DATETIME)
		    {
		      char str[20];
		      struct st_mysql_time *t = statement->bind[i].buffer;

		      snprintf (str, 20, "%d-%02d-%02d %02d:%02d:%02d",
				t->year, t->month, t->day, t->hour,
				t->minute, t->second);

		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_STRING (name, str);
			}
		      else
			{
			  LUA_PUSH_ARRAY_STRING (d, str);
			}
		    }
		  else if (statement->fields[i].type == MYSQL_TYPE_TIME)
		    {
		      char str[9];
		      struct st_mysql_time *t = statement->bind[i].buffer;

		      snprintf (str, 9, "%02d:%02d:%02d", t->hour,
				t->minute, t->second);

		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_STRING (name, str);
			}
		      else
			{
			  LUA_PUSH_ARRAY_STRING (d, str);
			}
		    }
		  else if (statement->fields[i].type == MYSQL_TYPE_DATE)
		    {
		      char str[20];
		      struct st_mysql_time *t = statement->bind[i].buffer;

		      snprintf (str, 11, "%d-%02d-%02d", t->year,
				t->month, t->day);

		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_STRING (name, str);
			}
		      else
			{
			  LUA_PUSH_ARRAY_STRING (d, str);
			}

		    }
		  else
		    {
		      if (named_columns)
			{
			  LUA_PUSH_ATTRIB_STRING (name,
						  statement->bind[i].buffer);
			}
		      else
			{
			  LUA_PUSH_ARRAY_STRING (d,
						 statement->bind[i].buffer);
			}
		    }
		}
	      else if (lua_push == LUA_PUSH_BOOLEAN)
		{
		  if (named_columns)
		    {
		      LUA_PUSH_ATTRIB_BOOL (name,
					    *(int *) (statement->
						      bind[i].buffer));
		    }
		  else
		    {
		      LUA_PUSH_ARRAY_BOOL (d,
					   *(int *) (statement->
						     bind[i].buffer));
		    }
		}
	      else
		{
		  luaL_error (L, DBI_ERR_UNKNOWN_PUSH);
		  values = 1;
		}
	    }
	}
      else
	{
	  lua_pushnil (L);
	  values = 1;
	}
    }

  if (statement->bind)
    {
      int i;

      for (i = 0; i < column_count; i++)
	{
	  free (statement->bind[i].buffer);
	}

      free (statement->bind);
    }
  return values;

} /* }}} */
Exemple #5
0
static int
statement_fetch_impl_start (lua_State * L, statement_t * statement) /* {{{ */
{
  int column_count;
  unsigned long *real_length = NULL;
  const char *error_message = NULL;

  if (!statement->stmt)
    {
      luaL_error (L, DBI_ERR_FETCH_INVALID);
      return 0;
    }

  if (!statement->metadata)
    {
      luaL_error (L, DBI_ERR_FETCH_NO_EXECUTE);
      return 0;
    }

  column_count = mysql_num_fields (statement->metadata);

  if (column_count > 0)
    {
      int i;

      real_length = calloc (column_count, sizeof (unsigned long));

      statement->bind = malloc (sizeof (MYSQL_BIND) * column_count);
      memset (statement->bind, 0, sizeof (MYSQL_BIND) * column_count);

      statement->fields = mysql_fetch_fields (statement->metadata);

      for (i = 0; i < column_count; i++)
	{
	  unsigned int length = mysql_buffer_size (&statement->fields[i]);
	  if (length > sizeof (MYSQL_TIME))
	    {
	      statement->bind[i].buffer = NULL;
	      statement->bind[i].buffer_length = 0;
	    }
	  else
	    {
	      char *buffer = (char *) malloc (length);
	      memset (buffer, 0, length);

	      statement->bind[i].buffer = buffer;
	      statement->bind[i].buffer_length = length;
	    }

	  statement->bind[i].buffer_type = statement->fields[i].type;
	  statement->bind[i].length = &real_length[i];
	}

      if (mysql_stmt_bind_result (statement->stmt, statement->bind))
	{
	  error_message = DBI_ERR_BINDING_RESULTS;
	  goto cleanup;
	}

      statement->event =
	mysql_stmt_fetch_start (&(statement->ret), statement->stmt);

      if (statement->event & MYSQL_WAIT_EXCEPT)
	{
	  lua_pushnil (L);
	  return 1;
	}
      if (statement->event & MYSQL_WAIT_TIMEOUT)
	{
	  statement->timeout =
	    1000 * mysql_get_timeout_value_ms (statement->mysql);
	}

      lua_pushboolean (L, 1);
      lua_pushnumber (L, statement->event);
      return 2;
    }
  else
    {
      lua_pushnil (L);
      return 1;
    }


cleanup:
  free (real_length);

  if (statement->bind)
    {
      int i;

      for (i = 0; i < column_count; i++)
	{
	  free (statement->bind[i].buffer);
	}

      free (statement->bind);
    }


  if (error_message)
    {
      luaL_error (L, error_message, mysql_stmt_error (statement->stmt));
      return 0;
    }

  return 1;
} /* }}} */
Exemple #6
0
/*
 * success,event = statement:execute(...)
 */
static int
statement_execute_start (lua_State * L) /* {{{ */
{
  int n = lua_gettop (L);
  statement_t *statement =
    (statement_t *) luaL_checkudata (L, 1, DBD_MYSQL_STATEMENT);
  int num_bind_params = n - 1;
  int expected_params;

  unsigned char *buffer = NULL;
  int offset = 0;

  char *error_message = NULL;
  char *errstr = NULL;

  int p;

  if (statement->metadata)
    {
      /*
       * free existing metadata from any previous executions
       * TODO mysql_free_result is blocking
       */
      mysql_free_result (statement->metadata);
      statement->metadata = NULL;
    }

  if (!statement->stmt)
    {
      lua_pushboolean (L, 0);
      lua_pushstring (L, DBI_ERR_EXECUTE_INVALID);
      return 2;
    }

  expected_params = mysql_stmt_param_count (statement->stmt);

  if (expected_params != num_bind_params)
    {
      /*
       * mysql_stmt_bind_param does not handle this condition,
       * and the client library will segfault if these do no match
       */
      lua_pushboolean (L, 0);
      lua_pushfstring (L, DBI_ERR_PARAM_MISCOUNT, expected_params,
		       num_bind_params);
      return 2;
    }

  if (num_bind_params > 0)
    {
      statement->bind = malloc (sizeof (MYSQL_BIND) * num_bind_params);
      if (statement->bind == NULL)
	{
	  luaL_error (L, "Could not alloc bind params\n");
	}

      buffer = (unsigned char *) malloc (num_bind_params * sizeof (double));
      memset (statement->bind, 0, sizeof (MYSQL_BIND) * num_bind_params);
    }

  for (p = 2; p <= n; p++)
    {				/* {{{ */
      int type = lua_type (L, p);
      int i = p - 2;

      const char *str = NULL;
      size_t *str_len = NULL;
      double *num = NULL;
      int *boolean = NULL;
      char err[64];

      switch (type)
	{
	case LUA_TNIL:
	  statement->bind[i].buffer_type = MYSQL_TYPE_NULL;
	  statement->bind[i].is_null = (my_bool *) 1;
	  break;

	case LUA_TBOOLEAN:
	  boolean = (int *) (buffer + offset);
	  offset += sizeof (int);
	  *boolean = lua_toboolean (L, p);

	  statement->bind[i].buffer_type = MYSQL_TYPE_LONG;
	  statement->bind[i].is_null = (my_bool *) 0;
	  statement->bind[i].buffer = (char *) boolean;
	  statement->bind[i].length = 0;
	  break;

	case LUA_TNUMBER:
	  /*
	   * num needs to be it's own 
	   * memory here
	   */
	  num = (double *) (buffer + offset);
	  offset += sizeof (double);
	  *num = lua_tonumber (L, p);

	  statement->bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
	  statement->bind[i].is_null = (my_bool *) 0;
	  statement->bind[i].buffer = (char *) num;
	  statement->bind[i].length = 0;
	  break;

	case LUA_TSTRING:
	  str_len = (size_t *) (buffer + offset);
	  offset += sizeof (size_t);
	  str = lua_tolstring (L, p, str_len);

	  statement->bind[i].buffer_type = MYSQL_TYPE_STRING;
	  statement->bind[i].is_null = (my_bool *) 0;
	  statement->bind[i].buffer = (char *) str;
	  statement->bind[i].length = str_len;
	  break;

	default:
	  snprintf (err, sizeof (err) - 1, DBI_ERR_BINDING_TYPE_ERR,
		    lua_typename (L, type));
	  errstr = err;
	  error_message = DBI_ERR_BINDING_PARAMS;
	  goto cleanup;
	}
    }				/* }}} */

  if (mysql_stmt_bind_param (statement->stmt, statement->bind))
    {
      error_message = DBI_ERR_BINDING_PARAMS;
      goto cleanup;
    }

  statement->event =
    mysql_stmt_execute_start (&(statement->ret), statement->stmt);

  if (statement->event & MYSQL_WAIT_EXCEPT)
    {
      lua_pushnil (L);
      lua_pushfstring (L, DBI_ERR_BINDING_EXEC,
		       mysql_stmt_error (statement->stmt));
    }

  if (statement->event & MYSQL_WAIT_TIMEOUT)
    {
      statement->timeout =
	1000 * mysql_get_timeout_value_ms (statement->mysql);
    }

cleanup:
  if (statement->bind)
    {
      free (statement->bind);
    }

  if (buffer)
    {
      free (buffer);
    }

  if (error_message)
    {
      lua_pushboolean (L, 0);
      lua_pushfstring (L, error_message,
		       errstr ? errstr : mysql_stmt_error (statement->stmt));
      return 2;
    }

  lua_pushboolean (L, 1);
  lua_pushnumber (L, convert_mysql_to_ev (statement->event));
  return 2;
} /* }}} */