You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@thrift.apache.org by Debacker <de...@gmail.com> on 2009/04/12 20:40:41 UTC

[PROPOSAL] implement unions

Hi,

I recently came across a problem which could be nicely implemented if union
were supported. Let's suppose that you want to create a method to query
objects based on several fields. The problem is that for string fields for
example, you may want to do a range query, or a fulltext search query. Thus
you would created the following two structs to represent that:

struct StringRangeFilter { string minValue, string maxValue }
struct StringSearchFilter { string expression }

The problem is that the caller need to use only one, not both. What I
propose would be this:

union StringFilter {
  1:StringRangeFilter rangeFilter,
  2:StringSearchFilter searchFilter,
}

When sending such an object over the wire, we could write the id number
first, followed by the binary form of the field that is used. With unions,
the method signature could be:

query(1:StringFilter nameFilter, 2:StringFilter descriptionFilter)

The binary format would be efficient (more efficient than sending two
structs, and using only one at least). But still we would need a nice API
for client and server.

What we could do for Java-like languages is:

class StringFilter {
   int id;
   Object data;

   void setRangeFilter(StringRangeFilter rangeFilter) { id = 1; data =
rangeFilter; }
   void setSearchFilter(StringSearchFilter searchFilter) { id = 2; data =
searchFilter; }

   int getID() { return id; }

   StringRangeFilter getRangeFilter() {
      if(id != 1) throw ....
      return (StringRangeFilter)data;
   }

   StringSearchFilter getSearchFilter() {
      if(id != 2) throw ....
      return (StringSearchFilter)data;
   }
}

The reader can use the getID method to know the data type. If we don't want
the developer to care about the ID, we could use the visitor pattern:

interface StringFilterVisitor {
    void visitStringRangeFilter(StringRangeFilter rangeFilter);
    void visitStringSearchFilter(StringSearchFilter searchFilter);
    void other();
}

and add the following method to StringFilter:

void accept(StringFilterVisitor visitor) {
    switch(id) {
       case 1: visitor.visitStringRangeFilter((StringRangeFilter)data);
break;
       case 2: visitor.visitStringSearchFilter((StringSearchFilter)data);
break;
       default: visitor.other(); break;
   }
}

I think that the ID use fits nicely with the style of Thrift. However, I
understand that not many poeple would be willing to change the binary
protocol. But I would like to start the debate :)

Laurent Debacker.

Re: [PROPOSAL] implement unions

Posted by Jake Luciani <ja...@gmail.com>.
there's been some discussion about this:
http://issues.apache.org/jira/browse/THRIFT-409

On Sun, Apr 12, 2009 at 2:40 PM, Debacker <de...@gmail.com> wrote:

> Hi,
>
> I recently came across a problem which could be nicely implemented if union
> were supported. Let's suppose that you want to create a method to query
> objects based on several fields. The problem is that for string fields for
> example, you may want to do a range query, or a fulltext search query. Thus
> you would created the following two structs to represent that:
>
> struct StringRangeFilter { string minValue, string maxValue }
> struct StringSearchFilter { string expression }
>
> The problem is that the caller need to use only one, not both. What I
> propose would be this:
>
> union StringFilter {
>  1:StringRangeFilter rangeFilter,
>  2:StringSearchFilter searchFilter,
> }
>
> When sending such an object over the wire, we could write the id number
> first, followed by the binary form of the field that is used. With unions,
> the method signature could be:
>
> query(1:StringFilter nameFilter, 2:StringFilter descriptionFilter)
>
> The binary format would be efficient (more efficient than sending two
> structs, and using only one at least). But still we would need a nice API
> for client and server.
>
> What we could do for Java-like languages is:
>
> class StringFilter {
>   int id;
>   Object data;
>
>   void setRangeFilter(StringRangeFilter rangeFilter) { id = 1; data =
> rangeFilter; }
>   void setSearchFilter(StringSearchFilter searchFilter) { id = 2; data =
> searchFilter; }
>
>   int getID() { return id; }
>
>   StringRangeFilter getRangeFilter() {
>      if(id != 1) throw ....
>      return (StringRangeFilter)data;
>   }
>
>   StringSearchFilter getSearchFilter() {
>      if(id != 2) throw ....
>      return (StringSearchFilter)data;
>   }
> }
>
> The reader can use the getID method to know the data type. If we don't want
> the developer to care about the ID, we could use the visitor pattern:
>
> interface StringFilterVisitor {
>    void visitStringRangeFilter(StringRangeFilter rangeFilter);
>    void visitStringSearchFilter(StringSearchFilter searchFilter);
>    void other();
> }
>
> and add the following method to StringFilter:
>
> void accept(StringFilterVisitor visitor) {
>    switch(id) {
>       case 1: visitor.visitStringRangeFilter((StringRangeFilter)data);
> break;
>       case 2: visitor.visitStringSearchFilter((StringSearchFilter)data);
> break;
>       default: visitor.other(); break;
>   }
> }
>
> I think that the ID use fits nicely with the style of Thrift. However, I
> understand that not many poeple would be willing to change the binary
> protocol. But I would like to start the debate :)
>
> Laurent Debacker.
>