Paul J. Lucas has proposed merging lp:~paul-lucas/zorba/bug-923015 into 
lp:zorba.

Requested reviews:
  Matthias Brantner (matthias-brantner)
  William Candillon (wcandillon)
Related bugs:
  Bug #923015 in Zorba: "clone() not implemented for full-text expressions"
  https://bugs.launchpad.net/zorba/+bug/923015

For more details, see:
https://code.launchpad.net/~paul-lucas/zorba/bug-923015/+merge/92398

Added clone().
-- 
https://code.launchpad.net/~paul-lucas/zorba/bug-923015/+merge/92398
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2012-02-07 14:26:42 +0000
+++ ChangeLog	2012-02-10 01:03:24 +0000
@@ -2,6 +2,7 @@
 
 version 2.2
 
+  * Fixed bug 923015 (clone() not implemented for full-text expressions)
   * No-copy optimization: avoids copying nodes during node-constructor expressions.
   * Added external function annotations %ann:propagates-input-nodes and 
     %ann:must-copy-input-nodes to be used by the no-copy optimization.

=== modified file 'src/compiler/expression/ft_expr.cpp'
--- src/compiler/expression/ft_expr.cpp	2011-06-14 17:26:33 +0000
+++ src/compiler/expression/ft_expr.cpp	2012-02-10 01:03:24 +0000
@@ -58,6 +58,15 @@
   v.end_visit( *this );
 }
 
+expr_t ftcontains_expr::clone( substitution_t &s ) const {
+  return new ftcontains_expr(
+    theSctx, get_loc(),
+    range_->clone( s ),
+    ftselection_->clone( s ).release(),
+    ftignore_.isNull() ? 0 : ftignore_->clone( s )
+  );
+}
+
 void ftcontains_expr::compute_scripting_kind() {
   checkSimpleExpr(range_);
 

=== modified file 'src/compiler/expression/ft_expr.h'
--- src/compiler/expression/ft_expr.h	2012-01-11 17:30:25 +0000
+++ src/compiler/expression/ft_expr.h	2012-02-10 01:03:24 +0000
@@ -37,13 +37,14 @@
   void serialize( serialization::Archiver& );
 
   ftcontains_expr(
-    static_context* sctx,
+    static_context*,
     QueryLoc const&,
     expr_t range,
     ftnode *ftselection,
     expr_t ftignore
   );
 
+  expr_t clone( substitution_t& ) const;
   void compute_scripting_kind();
 
   expr_t get_range() const { return range_; }
@@ -63,7 +64,6 @@
 } // namespace zorba
 
 #endif /* ZORBA_FT_EXPR_H */
-
 /*
  * Local variables:
  * mode: c++

=== modified file 'src/compiler/expression/ftnode.cpp'
--- src/compiler/expression/ftnode.cpp	2012-02-02 09:56:52 +0000
+++ src/compiler/expression/ftnode.cpp	2012-02-10 01:03:24 +0000
@@ -30,6 +30,7 @@
 #include "ftnode_visitor.h"
 
 using namespace std;
+using namespace zorba::locale;
 
 namespace zorba {
 
@@ -199,6 +200,37 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+template<typename PointerType>
+inline PointerType clone_ptr( PointerType p, expr::substitution_t &s ) {
+  return static_cast<PointerType>( p->clone( s ).release() );
+}
+
+template<class RCHandleValueType>
+inline RCHandleValueType* clone_ptr( rchandle<RCHandleValueType> const &p,
+                                     expr::substitution_t &s ) {
+  return static_cast<RCHandleValueType*>( p->clone( s ).release() );
+}
+
+template<typename PointerType>
+inline PointerType clone_ptr_if( PointerType p, expr::substitution_t &s ) {
+  return p ? clone_ptr( p, s ) : nullptr;
+}
+
+template<class RCHandleValueType>
+inline RCHandleValueType* clone_ptr_if( rchandle<RCHandleValueType> const &p,
+                                        expr::substitution_t &s ) {
+  return p.isNull() ? nullptr : clone_ptr( p, s );
+}
+
+template<class ContainerType>
+void clone_list( ContainerType const &from, ContainerType *to,
+                 expr::substitution_t &s ) {
+  FOR_EACH( typename ContainerType, i, from )
+    to->push_back( clone_ptr( *i, s ) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 void ftnode::serialize( serialization::Archiver &ar ) {
   ar & loc_;
 }
@@ -214,6 +246,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftand::clone( expr::substitution_t &s ) const {
+  ftnode_list_t copy;
+  clone_list( get_node_list(), &copy, s );
+  return new ftand( get_loc(), copy );
+}
+
 ostream& ftand::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftand );
   PUT_SEQ( o, ftnode_list_t, get_node_list() );
@@ -238,6 +276,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftcase_option::clone( expr::substitution_t& ) const {
+  return new ftcase_option( get_loc(), mode_ );
+}
+
 ostream& ftcase_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftcase_option );
   PUT_ATTR( o, mode ) << endl;
@@ -262,6 +304,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftcontent_filter::clone( expr::substitution_t &s ) const {
+  return new ftcontent_filter( get_loc(), mode_ );
+}
+
 void ftcontent_filter::serialize( serialization::Archiver &ar ) {
   serialize_baseclass( ar, (ftpos_filter*)this );
   SERIALIZE_ENUM(ft_content_mode::type, mode_);
@@ -287,6 +333,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftdiacritics_option::clone( expr::substitution_t& ) const {
+  return new ftdiacritics_option( get_loc(), mode_ );
+}
+
 ostream& ftdiacritics_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftdiacritics_option );
   PUT_ATTR( o, mode ) << endl;
@@ -320,6 +370,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftdistance_filter::clone( expr::substitution_t &s ) const {
+  return new ftdistance_filter( get_loc(), clone_ptr_if( range_, s ), unit_ );
+}
+
 ostream& ftdistance_filter::put( ostream &o ) const {
   BEGIN_PUT( o, ftcontent_filter );
   PUT_ATTR( o, unit );
@@ -355,6 +409,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftextension_selection::clone( expr::substitution_t &s ) const {
+  return new ftextension_selection(
+    get_loc(), pragmas_, clone_ptr_if( ftselection_, s )
+  );
+}
+
 ostream& ftextension_selection::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftextension_selection );
   PUT_NODE( o, ftselection_ );
@@ -383,6 +443,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftextension_option::clone( expr::substitution_t& ) const {
+  return new ftextension_option( get_loc(), qname_, val_ );
+}
+
 ostream& ftextension_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftextension_option )
   //<< " qname=" << qname_
@@ -416,6 +480,15 @@
     );
 }
 
+ftlanguage_option::ftlanguage_option(
+  QueryLoc const &loc,
+  iso639_1::type lang
+) :
+  ftmatch_option( loc ),
+  lang_( lang )
+{
+}
+
 void ftlanguage_option::serialize( serialization::Archiver &ar ) {
   serialize_baseclass( ar, (ftmatch_option*)this );
   SERIALIZE_ENUM(locale::iso639_1::type,lang_);
@@ -427,6 +500,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftlanguage_option::clone( expr::substitution_t& ) const {
+  return new ftlanguage_option( get_loc(), lang_ );
+}
+
 ostream& ftlanguage_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftlanguage_option );
   PUT_ATTR( o, lang ) << endl;
@@ -456,6 +533,33 @@
   END_VISIT( v );
 }
 
+ftnode_t ftmatch_options::clone( expr::substitution_t &s ) const {
+  unique_ptr<ftmatch_options> p( new ftmatch_options( get_loc() ) );
+  if ( case_option_ )
+    p->set_case_option( clone_ptr( case_option_, s ) );
+  if ( diacritics_option_ )
+    p->set_diacritics_option(
+      clone_ptr( diacritics_option_, s )
+    );
+
+  FOR_EACH( ftextension_option_list_t, i, extension_options_ )
+    p->add_extension_option( clone_ptr( *i, s ) );
+  if ( current_extension_options_ != &extension_options_ )
+    p->set_extension_options( current_extension_options_ );
+
+  if ( language_option_ )
+    p->set_language_option( clone_ptr( language_option_, s ) );
+  if ( stem_option_ )
+    p->set_stem_option( clone_ptr( stem_option_, s ) );
+  if ( stop_word_option_ )
+    p->set_stop_word_option( clone_ptr( stop_word_option_, s ) );
+  if ( thesaurus_option_ )
+    p->set_thesaurus_option( clone_ptr( thesaurus_option_, s ) );
+  if ( wild_card_option_ )
+    p->set_wild_card_option( clone_ptr( wild_card_option_, s ) );
+  return p.release();
+}
+
 ostream& ftmatch_options::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftmatch_options );
   PUT_NODE( o, case_option_ );
@@ -474,7 +578,7 @@
   ar & case_option_;
   ar & diacritics_option_;
   ar & extension_options_;
-  if(!ar.is_serializing_out())
+  if ( !ar.is_serializing_out() )
     current_extension_options_ = &extension_options_;
   ar & language_option_;
   ar & stem_option_;
@@ -510,6 +614,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftmild_not::clone( expr::substitution_t &s ) const {
+  ftnode_list_t copy;
+  clone_list( get_node_list(), &copy, s );
+  return new ftmild_not( get_loc(), copy );
+}
+
 ostream& ftmild_not::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftmild_not );
   PUT_SEQ( o, ftnode_list_t, get_node_list() );
@@ -546,6 +656,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftor::clone( expr::substitution_t &s ) const {
+  ftnode_list_t copy;
+  clone_list( get_node_list(), &copy, s );
+  return new ftor( get_loc(), copy );
+}
+
 ostream& ftor::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftor );
   PUT_SEQ( o, ftnode_list_t, get_node_list() );
@@ -566,10 +682,15 @@
   END_VISIT( v );
 }
 
+ftnode_t ftorder_filter::clone( expr::substitution_t &s ) const {
+  return new ftorder_filter( get_loc() );
+}
+
 ostream& ftorder_filter::put( ostream &o ) const {
   BEGIN_PUT( o, ftorder_filter ) << endl;
   END_PUT( o );
 }
+
 void ftorder_filter::serialize( serialization::Archiver &ar ) {
   serialize_baseclass( ar, (ftpos_filter*)this );
 }
@@ -583,9 +704,7 @@
   serialize_baseclass( ar, (ftnode*)this );
 }
 
-ftprimary_with_options::ftprimary_with_options(
-  QueryLoc const &loc
-) :
+ftprimary_with_options::ftprimary_with_options( QueryLoc const &loc ) :
   ftnode( loc ),
   primary_( nullptr ),
   match_options_( new ftmatch_options( loc ) ),
@@ -607,6 +726,17 @@
   END_VISIT( v );
 }
 
+ftnode_t ftprimary_with_options::clone( expr::substitution_t &s ) const {
+  unique_ptr<ftprimary_with_options> p(
+    new ftprimary_with_options( get_loc() )
+  );
+  p->set_match_options( clone_ptr( match_options_, s ) );
+  p->set_primary( clone_ptr( primary_, s ) );
+  if ( weight_ )
+    p->set_weight( clone_ptr( weight_, s ) );
+  return p.release();
+}
+
 ostream& ftprimary_with_options::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftprimary_with_options );
   PUT_NODE( o, primary_ );
@@ -643,6 +773,15 @@
   END_VISIT( v );
 }
 
+ftnode_t ftrange::clone( expr::substitution_t &s ) const {
+  return new ftrange(
+    get_loc(), mode_,
+    clone_ptr( expr1_, s ),
+    clone_ptr_if( expr2_, s )
+  );
+  // TODO: do PlanIter_t's have to be cloned?
+}
+
 ostream& ftrange::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftrange );
   PUT_EXPR( o, expr1_ );
@@ -673,6 +812,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftscope_filter::clone( expr::substitution_t &s ) const {
+  return new ftscope_filter( get_loc(), scope_, unit_ );
+}
+
 ostream& ftscope_filter::put( ostream &o ) const {
   BEGIN_PUT( o, ftscope_filter );
   PUT_ATTR( o, scope );
@@ -726,6 +869,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftselection::clone( expr::substitution_t &s ) const {
+  return new ftselection( get_loc(), ftor_->clone( s ).release(), list_ );
+}
+
 ostream& ftselection::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftselection );
   PUT_NODE( o, ftor_ );
@@ -753,6 +900,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftstem_option::clone( expr::substitution_t& ) const {
+  return new ftstem_option( get_loc(), mode_ );
+}
+
 ostream& ftstem_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftstem_option );
   PUT_ATTR( o, mode ) << endl;
@@ -783,6 +934,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftstop_words::clone( expr::substitution_t& ) const {
+  return new ftstop_words( get_loc(), uri_, list_, mode_ );
+}
+
 ostream& ftstop_words::put( ostream &o ) const {
   BEGIN_PUT( o, ftstop_words );
   PUT_ATTR( o, uri );
@@ -831,6 +986,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftstop_word_option::clone( expr::substitution_t &s ) const {
+  list_t copy;
+  clone_list( stop_words_, &copy, s );
+  return new ftstop_word_option( get_loc(), copy, mode_ );
+}
+
 ostream& ftstop_word_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftstop_word_option );
   PUT_ATTR( o, mode );
@@ -873,6 +1034,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftthesaurus_id::clone( expr::substitution_t &s ) const {
+  return new ftthesaurus_id(
+    get_loc(), uri_, relationship_, clone_ptr_if( levels_, s )
+  );
+}
+
 ostream& ftthesaurus_id::put( ostream &o ) const {
   BEGIN_PUT( o, ftthesaurus_id );
   PUT_ATTR( o, uri );
@@ -914,6 +1081,14 @@
   END_VISIT( v );
 }
 
+ftnode_t ftthesaurus_option::clone( expr::substitution_t &s ) const {
+  thesaurus_id_list_t copy;
+  clone_list( thesaurus_id_list_, &copy, s );
+  return new ftthesaurus_option(
+    get_loc(), clone_ptr_if( default_tid_, s ), copy, no_thesaurus_
+  );
+}
+
 ostream& ftthesaurus_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftthesaurus_option );
   PUT_BOOL( o, no_thesaurus );
@@ -945,6 +1120,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftunary_not::clone( expr::substitution_t &s ) const {
+  return new ftunary_not( get_loc(), subnode_->clone( s ).release() );
+}
+
 ostream& ftunary_not::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftunary_not );
   PUT_NODE( o, subnode_ );
@@ -967,6 +1146,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftweight::clone( expr::substitution_t &s ) const {
+  return new ftweight( get_loc(), weight_expr_->clone( s ).release() );
+}
+
 ostream& ftweight::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftweight );
   PUT_EXPR( o, weight_expr_ );
@@ -993,6 +1176,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftwild_card_option::clone( expr::substitution_t &s ) const {
+  return new ftwild_card_option( get_loc(), mode_ );
+}
+
 ostream& ftwild_card_option::put( ostream &o ) const {
   BEGIN_PUT( o, ftwild_card_option );
   PUT_ATTR( o, mode ) << endl;
@@ -1022,6 +1209,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftwindow_filter::clone( expr::substitution_t &s ) const {
+  return new ftwindow_filter(
+    get_loc(), window_expr_->clone( s ).release(), unit_
+  );
+}
+
 ostream& ftwindow_filter::put( ostream &o ) const {
   BEGIN_PUT( o, ftwindow_filter );
   PUT_ATTR( o, unit );
@@ -1054,6 +1247,10 @@
   END_VISIT( v );
 }
 
+ftnode_t ftwords::clone( expr::substitution_t &s ) const {
+  return new ftwords( get_loc(), value_expr_->clone( s ).release(), mode_ );
+}
+
 ostream& ftwords::put( ostream &o ) const {
   BEGIN_PUT( o, ftwords );
   PUT_ATTR( o, mode );
@@ -1093,6 +1290,12 @@
   END_VISIT( v );
 }
 
+ftnode_t ftwords_times::clone( expr::substitution_t &s ) const {
+  return new ftwords_times(
+    get_loc(), clone_ptr( ftwords_, s ), clone_ptr_if( fttimes_, s )
+  );
+}
+
 ostream& ftwords_times::put( ostream &o ) const {
   BEGIN_INDENT_PUT( o, ftwords_times );
   PUT_NODE( o, ftwords_ );

=== modified file 'src/compiler/expression/ftnode.h'
--- src/compiler/expression/ftnode.h	2011-07-17 20:05:49 +0000
+++ src/compiler/expression/ftnode.h	2012-02-10 01:03:24 +0000
@@ -43,6 +43,7 @@
   void serialize( serialization::Archiver& );
 
   virtual ft_visit_result::type accept( ftnode_visitor& ) = 0;
+  virtual ftnode_t clone( expr::substitution_t& ) const = 0;
   QueryLoc const& get_loc() const { return loc_; }
   virtual std::ostream& put( std::ostream& ) const = 0;
 
@@ -83,6 +84,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_case_mode::type get_mode() const { return mode_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -104,6 +106,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_diacritics_mode::type get_mode() const { return mode_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -126,6 +129,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   rchandle<QName> const& get_qname() const { return qname_; }
   zstring const& get_val() const { return val_; }
   std::ostream& put( std::ostream& ) const;
@@ -148,7 +152,13 @@
     zstring const &language
   );
 
+  ftlanguage_option(
+    QueryLoc const&,
+    locale::iso639_1::type
+  );
+
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   locale::iso639_1::type get_language() const { return lang_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -170,6 +180,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_stem_mode::type get_mode() const { return mode_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -195,6 +206,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   zstring const& get_uri() const { return uri_; }
   list_t const& get_list() const { return list_; }
   ft_stop_words_unex::type get_mode() const { return mode_; }
@@ -233,6 +245,7 @@
   ~ftstop_word_option();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_stop_words_mode::type get_mode() const { return mode_; }
   list_t const& get_stop_words() const { return stop_words_; }
   std::ostream& put( std::ostream& ) const;
@@ -259,6 +272,7 @@
   ~ftthesaurus_id();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   zstring const& get_uri() const { return uri_; }
   zstring const& get_relationship() const { return relationship_; }
   ftrange const* get_levels() const { return levels_; }
@@ -295,6 +309,7 @@
   }
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   bool no_thesaurus() const { return no_thesaurus_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -318,6 +333,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_wild_card_mode::type get_mode() const { return mode_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -338,31 +354,43 @@
   ftmatch_options( QueryLoc const& );
 
   ft_visit_result::type accept( ftnode_visitor& );
-
-  ftcase_option const* get_case_option() const { return case_option_.getp(); }
-
-  ftdiacritics_option const* get_diacritics_option() const
-    { return diacritics_option_.getp(); }
-
-  ftextension_option_list_t* get_extension_options()
-    { return extension_options_.empty() ? nullptr : &extension_options_; }
-
-  ftextension_option_list_t const* get_extension_options() const
-    { return extension_options_.empty() ? nullptr : &extension_options_; }
-
-  ftlanguage_option const* get_language_option() const
-    { return language_option_.getp(); }
-
-  ftstem_option const* get_stem_option() const { return stem_option_.getp(); }
-
-  ftstop_word_option const* get_stop_word_option() const
-    { return stop_word_option_.getp(); }
-
-  ftthesaurus_option const* get_thesaurus_option() const
-    { return thesaurus_option_.getp(); }
-
-  ftwild_card_option const* get_wild_card_option() const
-    { return wild_card_option_.getp(); }
+  ftnode_t clone( expr::substitution_t& ) const;
+
+  ftcase_option const* get_case_option() const {
+    return case_option_.getp();
+  }
+
+  ftdiacritics_option const* get_diacritics_option() const {
+    return diacritics_option_.getp();
+  }
+
+  ftextension_option_list_t* get_extension_options() {
+    return extension_options_.empty() ? nullptr : &extension_options_;
+  }
+
+  ftextension_option_list_t const* get_extension_options() const {
+    return extension_options_.empty() ? nullptr : &extension_options_;
+  }
+
+  ftlanguage_option const* get_language_option() const {
+    return language_option_.getp();
+  }
+
+  ftstem_option const* get_stem_option() const {
+    return stem_option_.getp();
+  }
+
+  ftstop_word_option const* get_stop_word_option() const {
+    return stop_word_option_.getp();
+  }
+
+  ftthesaurus_option const* get_thesaurus_option() const {
+    return thesaurus_option_.getp();
+  }
+
+  ftwild_card_option const* get_wild_card_option() const {
+    return wild_card_option_.getp();
+  }
 
   void add_extension_option( ftextension_option *o ) {
     extension_options_.push_back( o );
@@ -407,8 +435,14 @@
 private:
   ftcase_option_t case_option_;
   ftdiacritics_option_t diacritics_option_;
+
   ftextension_option_list_t extension_options_;
+  //
+  // This points either to our own extension_options_ or a different one set by
+  // set_extension_options().
+  //
   ftextension_option_list_t const *current_extension_options_;
+
   ftlanguage_option_t language_option_;
   ftstem_option_t stem_option_;
   ftstop_word_option_t stop_word_option_;
@@ -427,6 +461,7 @@
   ftweight( QueryLoc const&, expr_t const &weight_expr );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   expr_t& get_weight_expr() { return weight_expr_; }
   PlanIter_t get_weight_iter() const { return weight_iter_; }
   std::ostream& put( std::ostream& ) const;
@@ -465,6 +500,7 @@
   ~ftprimary_with_options();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ftprimary const* get_primary() const { return primary_; }
   ftweight* get_weight() { return weight_; }
   ftmatch_options const* get_match_options() const { return match_options_; }
@@ -506,6 +542,7 @@
   ~ftextension_selection();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   rchandle<PragmaList> const& get_pragmas() const { return pragmas_; }
   ftselection const* get_ftselection() const { return ftselection_; }
   std::ostream& put( std::ostream& ) const;
@@ -532,6 +569,7 @@
   ~ftselection();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ftpos_filter_list_t const& get_ftpos_filter_list() const { return list_; }
   ftnode const* get_ftor() const { return ftor_; };
   std::ostream& put( std::ostream& ) const;
@@ -556,6 +594,7 @@
   ~ftwords_times();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ftwords const* get_words() const { return ftwords_; }
   ftrange const* get_times() const { return fttimes_; }
   std::ostream& put( std::ostream& ) const;
@@ -587,6 +626,7 @@
   ftcontent_filter( QueryLoc const&, ft_content_mode::type );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_content_mode::type get_mode() const { return mode_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -605,6 +645,7 @@
   ~ftdistance_filter();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ftrange const* get_range() const { return range_; }
   ft_unit::type get_unit() const { return unit_; }
   std::ostream& put( std::ostream& ) const;
@@ -621,8 +662,10 @@
   SERIALIZABLE_CLASS_CONSTRUCTOR2(ftorder_filter,ftpos_filter)
   void serialize( serialization::Archiver& );
 
-  ft_visit_result::type accept( ftnode_visitor& );
   ftorder_filter( QueryLoc const& );
+
+  ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   std::ostream& put( std::ostream& ) const;
 };
 
@@ -636,6 +679,7 @@
   ftscope_filter( QueryLoc const&, ft_scope::type, ft_big_unit::type );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_scope::type get_scope() const { return scope_; }
   ft_big_unit::type get_unit() const { return unit_; }
   std::ostream& put( std::ostream& ) const;
@@ -655,6 +699,7 @@
   ftwindow_filter( QueryLoc const&, expr_t const&, ft_unit::type );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ft_unit::type get_unit() const { return unit_; }
   expr_t& get_window_expr() { return window_expr_; }
   PlanIter_t get_window_iter() const { return window_iter_; }
@@ -705,6 +750,7 @@
   ftand( QueryLoc const&, ftnode_list_t& );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   std::ostream& put( std::ostream& ) const;
 };
 
@@ -718,6 +764,7 @@
   ftmild_not( QueryLoc const&, ftnode_list_t& );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   std::ostream& put( std::ostream& ) const;
 };
 
@@ -731,6 +778,7 @@
   ftor( QueryLoc const&, ftnode_list_t& );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   std::ostream& put( std::ostream& ) const;
 };
 
@@ -745,6 +793,7 @@
   ~ftunary_not();
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   ftnode const* get_subnode() const { return subnode_; }
   std::ostream& put( std::ostream& ) const;
 
@@ -768,6 +817,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   expr_t& get_expr1() { return expr1_; }
   expr_t& get_expr2() { return expr2_; }
   PlanIter_t get_plan_iter1() const { return iter1_; }
@@ -802,6 +852,7 @@
   );
 
   ft_visit_result::type accept( ftnode_visitor& );
+  ftnode_t clone( expr::substitution_t& ) const;
   expr_t& get_value_expr() { return value_expr_; }
   PlanIter_t get_value_iter() const { return value_iter_; }
   ft_anyall_mode::type get_mode() const { return mode_; }

=== modified file 'src/zorbatypes/rchandle.h'
--- src/zorbatypes/rchandle.h	2012-02-02 09:56:52 +0000
+++ src/zorbatypes/rchandle.h	2012-02-10 01:03:24 +0000
@@ -142,6 +142,13 @@
 ********************************************************************************/
 template<class T> class rchandle
 {
+public:
+  typedef T value_type;
+  typedef value_type* pointer;
+  typedef value_type const* const_pointer;
+  typedef value_type& reference;
+  typedef value_type const& const_reference;
+
 protected:
   T  * p;
 

=== added file 'test/rbkt/ExpQueryResults/zorba/fulltext/ft-expr-clone-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/fulltext/ft-expr-clone-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/fulltext/ft-expr-clone-1.xml.res	2012-02-10 01:03:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/Queries/zorba/fulltext/ft-expr-clone-1.xq'
--- test/rbkt/Queries/zorba/fulltext/ft-expr-clone-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/fulltext/ft-expr-clone-1.xq	2012-02-10 01:03:24 +0000
@@ -0,0 +1,10 @@
+(: This tests that full-text expressions are cloned properly. :)
+
+declare function local:f() {
+  let $x := <msg>hello world</msg>
+  return $x contains text "hello"
+};
+
+local:f()
+
+(: vim:set et sw=2 ts=2: :)

-- 
Mailing list: https://launchpad.net/~zorba-coders
Post to     : zorba-coders@lists.launchpad.net
Unsubscribe : https://launchpad.net/~zorba-coders
More help   : https://help.launchpad.net/ListHelp

Reply via email to