New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select from a sql function #815

Closed
fluxxu opened this Issue Mar 20, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@fluxxu
Contributor

fluxxu commented Mar 20, 2017

Now diesel has a sql_function! macro which allows we map a SQL function to query DSL, but I can't figure out a way to map a function to return a table.

For example, it seems that there is no way to select from this function:

CREATE TABLE tbl_function_return_data (
  id serial,
  text_value text,
  int_value integer,
  PRIMARY KEY(id)
);

CREATE FUNCTION function_return_table(v1 integer, v2 text)
  RETURNS TABLE(
    id integer,
    text_value text,
    int_value integer
  )
AS
$$
  SELECT * FROM tbl_function_return_data WHERE int_value > v1 OR text_value = v2
$$
LANGUAGE 'sql' IMMUTABLE;

To make diesel compiles, we can

sql_function!(function_return_table, function_return_table_t, (v1: Integer, v2: VarChar) -> (i32, String, i32));

diesel::select(tbl_function_return_data(1, "string")).load::<(i32, String, i32)>(conn);

But this generates a query as

SELECT tbl_function_return_data(1, 'string');

which returns a tuple instead of a record set, which causes a DeserializationError.
The query we actually need is:

SELECT * FROM tbl_function_return_data(1, 'string');

To generate this query, I tried

diesel::expression::SelectStatement::simple(tbl_function_return_data(1, "string")).load::<(i32, String, i32)>(conn);

To make this compiles, I need to impl QuerySource for function_return_table_t:

impl<A: Clone, B: Clone> QuerySource for function_return_table_t<A, B> {
  type FromClause = Self;
  type DefaultSelection = SqlLiteral<(Integer, VarChar, Integer)>;

  fn from_clause(&self) -> Self::FromClause {
    self.clone()
  }

  fn default_selection(&self) -> Self::DefaultSelection {
    SqlLiteral::new("*".to_owned())
  }
}

My question is should we have a macro like

sql_function_query_souce!(
  function_return_table, function_return_table_t, (v1: Integer, v2: VarChar) -> (i32, String, i32)
);

which impl QuerySource?
sql_function + impl QuerySource works, but the return type of sql_function is useless for this use case.

Thanks!

@sgrif

This comment has been minimized.

Member

sgrif commented Dec 16, 2017

I think for now sql_query is the best bet for something like this. Support for this is roughly the same as supporting selecting from a subselect, which will come at some point in the future.

@sgrif sgrif closed this Dec 16, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment