Drizzled Public API Documentation

dtcollation.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 #include <drizzled/dtcollation.h>
00022 
00023 #include <drizzled/definitions.h>
00024 #include <drizzled/internal/my_sys.h>
00025 #include <drizzled/error.h>
00026 #include <drizzled/function/str/conv_charset.h>
00027 #include <drizzled/session.h>
00028 #include <drizzled/charset.h>
00029 
00030 namespace drizzled {
00031 
00032 DTCollation::DTCollation()
00033 {
00034   collation= &my_charset_bin;
00035   derivation= DERIVATION_NONE;
00036 }
00037 
00038 
00039 DTCollation::DTCollation(const charset_info_st * const collation_arg,
00040                          Derivation derivation_arg)
00041 {
00042   collation= collation_arg;
00043   derivation= derivation_arg;
00044 }
00045 
00046 
00047 void DTCollation::set(DTCollation &dt)
00048 {
00049   collation= dt.collation;
00050   derivation= dt.derivation;
00051 }
00052 
00053 
00054 void DTCollation::set(const charset_info_st * const collation_arg,
00055                       Derivation derivation_arg)
00056 {
00057   collation= collation_arg;
00058   derivation= derivation_arg;
00059 }
00060 
00061 
00062 void DTCollation::set(const charset_info_st * const collation_arg)
00063 {
00064   collation= collation_arg;
00065 }
00066 
00067 
00068 void DTCollation::set(Derivation derivation_arg)
00069 {
00070   derivation= derivation_arg;
00071 }
00072 
00073 
00074 bool DTCollation::aggregate(DTCollation &dt, uint32_t flags)
00075 {
00076   if (!my_charset_same(collation, dt.collation))
00077   {
00078     /*
00079       We do allow to use binary strings (like BLOBS)
00080       together with character strings.
00081       Binaries have more precedence than a character
00082       string of the same derivation.
00083     */
00084     if (collation == &my_charset_bin)
00085     {
00086       if (derivation <= dt.derivation)
00087         ; // Do nothing
00088       else
00089       {
00090         set(dt);
00091       }
00092     }
00093     else if (dt.collation == &my_charset_bin)
00094     {
00095       if (dt.derivation <= derivation)
00096       {
00097         set(dt);
00098       }
00099       else
00100       {
00101         // Do nothing
00102       }
00103     }
00104     else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
00105              collation->state & MY_CS_UNICODE &&
00106              (derivation < dt.derivation ||
00107               (derivation == dt.derivation &&
00108                !(dt.collation->state & MY_CS_UNICODE))))
00109     {
00110       // Do nothing
00111     }
00112     else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
00113              dt.collation->state & MY_CS_UNICODE &&
00114              (dt.derivation < derivation ||
00115               (dt.derivation == derivation &&
00116                !(collation->state & MY_CS_UNICODE))))
00117     {
00118       set(dt);
00119     }
00120     else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
00121              derivation < dt.derivation &&
00122              dt.derivation >= DERIVATION_SYSCONST)
00123     {
00124       // Do nothing;
00125     }
00126     else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
00127              dt.derivation < derivation &&
00128              derivation >= DERIVATION_SYSCONST)
00129     {
00130       set(dt);
00131     }
00132     else
00133     {
00134       // Cannot apply conversion
00135       set(0, DERIVATION_NONE);
00136       return true;
00137     }
00138   }
00139   else if (derivation < dt.derivation)
00140   {
00141     // Do nothing
00142   }
00143   else if (dt.derivation < derivation)
00144   {
00145     set(dt);
00146   }
00147   else
00148   {
00149     if (collation == dt.collation)
00150     {
00151       // Do nothing
00152     }
00153     else
00154     {
00155       if (derivation == DERIVATION_EXPLICIT)
00156       {
00157         set(0, DERIVATION_NONE);
00158         return true;
00159       }
00160       if (collation->state & MY_CS_BINSORT)
00161         return false;
00162       if (dt.collation->state & MY_CS_BINSORT)
00163       {
00164         set(dt);
00165         return false;
00166       }
00167       const charset_info_st * const bin= get_charset_by_csname(collation->csname, MY_CS_BINSORT);
00168       set(bin, DERIVATION_NONE);
00169     }
00170   }
00171 
00172   return false;
00173 }
00174 
00175 
00176 bool DTCollation::set(DTCollation &dt1, DTCollation &dt2, uint32_t flags)
00177 { set(dt1); return aggregate(dt2, flags); }
00178 
00179 
00180 const char *DTCollation::derivation_name() const
00181 {
00182   switch(derivation)
00183   {
00184   case DERIVATION_IGNORABLE: return "IGNORABLE";
00185   case DERIVATION_COERCIBLE: return "COERCIBLE";
00186   case DERIVATION_IMPLICIT:  return "IMPLICIT";
00187   case DERIVATION_SYSCONST:  return "SYSCONST";
00188   case DERIVATION_EXPLICIT:  return "EXPLICIT";
00189   case DERIVATION_NONE:      return "NONE";
00190   default: return "UNKNOWN";
00191   }
00192 }
00193 
00194 
00195 bool agg_item_collations(DTCollation &c, const char *fname,
00196                          Item **av, uint32_t count,
00197                          uint32_t flags, int item_sep)
00198 {
00199   uint32_t i;
00200   Item **arg;
00201   c.set(av[0]->collation);
00202   for (i= 1, arg= &av[item_sep]; i < count; i++, arg++)
00203   {
00204     if (c.aggregate((*arg)->collation, flags))
00205     {
00206       my_coll_agg_error(av, count, fname, item_sep);
00207       return true;
00208     }
00209   }
00210   if ((flags & MY_COLL_DISALLOW_NONE) &&
00211       c.derivation == DERIVATION_NONE)
00212   {
00213     my_coll_agg_error(av, count, fname, item_sep);
00214     return true;
00215   }
00216   return false;
00217 }
00218 
00219 
00220 bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
00221                                         Item **av, uint32_t count,
00222                                         uint32_t flags)
00223 {
00224   return (agg_item_collations(c, fname, av, count,
00225                               flags | MY_COLL_DISALLOW_NONE, 1));
00226 }
00227 
00228 
00229 bool agg_item_charsets(DTCollation &coll, const char *fname,
00230                        Item **args, uint32_t nargs, uint32_t flags,
00231                        int item_sep)
00232 {
00233   if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
00234     return true;
00235 
00236   return false;
00237 }
00238 
00239 
00240 void my_coll_agg_error(DTCollation &c1,
00241                        DTCollation &c2, const char *fname)
00242 {
00243   my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
00244            c1.collation->name,c1.derivation_name(),
00245            c2.collation->name,c2.derivation_name(),
00246            fname);
00247 }
00248 
00249 
00250 void my_coll_agg_error(DTCollation &c1,
00251                        DTCollation &c2,
00252                        DTCollation &c3,
00253                        const char *fname)
00254 {
00255   my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
00256            c1.collation->name,c1.derivation_name(),
00257            c2.collation->name,c2.derivation_name(),
00258            c3.collation->name,c3.derivation_name(),
00259            fname);
00260 }
00261 
00262 
00263 void my_coll_agg_error(Item** args, uint32_t count, const char *fname,
00264                        int item_sep)
00265 {
00266   if (count == 2)
00267     my_coll_agg_error(args[0]->collation, args[item_sep]->collation, fname);
00268   else if (count == 3)
00269     my_coll_agg_error(args[0]->collation, args[item_sep]->collation,
00270                       args[2*item_sep]->collation, fname);
00271   else
00272     my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
00273 }
00274 
00275 } /* namespace drizzled */