thrift-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Debacker <deback...@gmail.com>
Subject [PROPOSAL] implement unions
Date Sun, 12 Apr 2009 18:40:41 GMT
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.

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message