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/charset_info.h>
00026 #include <drizzled/error.h>
00027 #include <drizzled/function/str/conv_charset.h>
00028 #include <drizzled/session.h>
00029 #include <drizzled/charset.h>
00030 
00031 namespace drizzled
00032 {
00033 
00034 DTCollation::DTCollation()
00035 {
00036   collation= &my_charset_bin;
00037   derivation= DERIVATION_NONE;
00038 }
00039 
00040 
00041 DTCollation::DTCollation(const CHARSET_INFO * const collation_arg,
00042                          Derivation derivation_arg)
00043 {
00044   collation= collation_arg;
00045   derivation= derivation_arg;
00046 }
00047 
00048 
00049 void DTCollation::set(DTCollation &dt)
00050 {
00051   collation= dt.collation;
00052   derivation= dt.derivation;
00053 }
00054 
00055 
00056 void DTCollation::set(const CHARSET_INFO * const collation_arg,
00057                       Derivation derivation_arg)
00058 {
00059   collation= collation_arg;
00060   derivation= derivation_arg;
00061 }
00062 
00063 
00064 void DTCollation::set(const CHARSET_INFO * const collation_arg)
00065 {
00066   collation= collation_arg;
00067 }
00068 
00069 
00070 void DTCollation::set(Derivation derivation_arg)
00071 {
00072   derivation= derivation_arg;
00073 }
00074 
00075 
00076 bool DTCollation::aggregate(DTCollation &dt, uint32_t flags)
00077 {
00078   if (!my_charset_same(collation, dt.collation))
00079   {
00080     /*
00081       We do allow to use binary strings (like BLOBS)
00082       together with character strings.
00083       Binaries have more precedence than a character
00084       string of the same derivation.
00085     */
00086     if (collation == &my_charset_bin)
00087     {
00088       if (derivation <= dt.derivation)
00089         ; // Do nothing
00090       else
00091       {
00092         set(dt);
00093       }
00094     }
00095     else if (dt.collation == &my_charset_bin)
00096     {
00097       if (dt.derivation <= derivation)
00098       {
00099         set(dt);
00100       }
00101       else
00102       {
00103         // Do nothing
00104       }
00105     }
00106     else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
00107              collation->state & MY_CS_UNICODE &&
00108              (derivation < dt.derivation ||
00109               (derivation == dt.derivation &&
00110                !(dt.collation->state & MY_CS_UNICODE))))
00111     {
00112       // Do nothing
00113     }
00114     else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
00115              dt.collation->state & MY_CS_UNICODE &&
00116              (dt.derivation < derivation ||
00117               (dt.derivation == derivation &&
00118                !(collation->state & MY_CS_UNICODE))))
00119     {
00120       set(dt);
00121     }
00122     else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
00123              derivation < dt.derivation &&
00124              dt.derivation >= DERIVATION_SYSCONST)
00125     {
00126       // Do nothing;
00127     }
00128     else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
00129              dt.derivation < derivation &&
00130              derivation >= DERIVATION_SYSCONST)
00131     {
00132       set(dt);
00133     }
00134     else
00135     {
00136       // Cannot apply conversion
00137       set(0, DERIVATION_NONE);
00138       return true;
00139     }
00140   }
00141   else if (derivation < dt.derivation)
00142   {
00143     // Do nothing
00144   }
00145   else if (dt.derivation < derivation)
00146   {
00147     set(dt);
00148   }
00149   else
00150   {
00151     if (collation == dt.collation)
00152     {
00153       // Do nothing
00154     }
00155     else
00156     {
00157       if (derivation == DERIVATION_EXPLICIT)
00158       {
00159         set(0, DERIVATION_NONE);
00160         return true;
00161       }
00162       if (collation->state & MY_CS_BINSORT)
00163         return false;
00164       if (dt.collation->state & MY_CS_BINSORT)
00165       {
00166         set(dt);
00167         return false;
00168       }
00169       const CHARSET_INFO * const bin= get_charset_by_csname(collation->csname, MY_CS_BINSORT);
00170       set(bin, DERIVATION_NONE);
00171     }
00172   }
00173 
00174   return false;
00175 }
00176 
00177 
00178 bool DTCollation::set(DTCollation &dt1, DTCollation &dt2, uint32_t flags)
00179 { set(dt1); return aggregate(dt2, flags); }
00180 
00181 
00182 const char *DTCollation::derivation_name() const
00183 {
00184   switch(derivation)
00185   {
00186   case DERIVATION_IGNORABLE: return "IGNORABLE";
00187   case DERIVATION_COERCIBLE: return "COERCIBLE";
00188   case DERIVATION_IMPLICIT:  return "IMPLICIT";
00189   case DERIVATION_SYSCONST:  return "SYSCONST";
00190   case DERIVATION_EXPLICIT:  return "EXPLICIT";
00191   case DERIVATION_NONE:      return "NONE";
00192   default: return "UNKNOWN";
00193   }
00194 }
00195 
00196 
00197 bool agg_item_collations(DTCollation &c, const char *fname,
00198                          Item **av, uint32_t count,
00199                          uint32_t flags, int item_sep)
00200 {
00201   uint32_t i;
00202   Item **arg;
00203   c.set(av[0]->collation);
00204   for (i= 1, arg= &av[item_sep]; i < count; i++, arg++)
00205   {
00206     if (c.aggregate((*arg)->collation, flags))
00207     {
00208       my_coll_agg_error(av, count, fname, item_sep);
00209       return true;
00210     }
00211   }
00212   if ((flags & MY_COLL_DISALLOW_NONE) &&
00213       c.derivation == DERIVATION_NONE)
00214   {
00215     my_coll_agg_error(av, count, fname, item_sep);
00216     return true;
00217   }
00218   return false;
00219 }
00220 
00221 
00222 bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
00223                                         Item **av, uint32_t count,
00224                                         uint32_t flags)
00225 {
00226   return (agg_item_collations(c, fname, av, count,
00227                               flags | MY_COLL_DISALLOW_NONE, 1));
00228 }
00229 
00230 
00231 bool agg_item_charsets(DTCollation &coll, const char *fname,
00232                        Item **args, uint32_t nargs, uint32_t flags,
00233                        int item_sep)
00234 {
00235   if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
00236     return true;
00237 
00238   return false;
00239 }
00240 
00241 
00242 void my_coll_agg_error(DTCollation &c1,
00243                        DTCollation &c2, const char *fname)
00244 {
00245   my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
00246            c1.collation->name,c1.derivation_name(),
00247            c2.collation->name,c2.derivation_name(),
00248            fname);
00249 }
00250 
00251 
00252 void my_coll_agg_error(DTCollation &c1,
00253                        DTCollation &c2,
00254                        DTCollation &c3,
00255                        const char *fname)
00256 {
00257   my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
00258            c1.collation->name,c1.derivation_name(),
00259            c2.collation->name,c2.derivation_name(),
00260            c3.collation->name,c3.derivation_name(),
00261            fname);
00262 }
00263 
00264 
00265 void my_coll_agg_error(Item** args, uint32_t count, const char *fname,
00266                        int item_sep)
00267 {
00268   if (count == 2)
00269     my_coll_agg_error(args[0]->collation, args[item_sep]->collation, fname);
00270   else if (count == 3)
00271     my_coll_agg_error(args[0]->collation, args[item_sep]->collation,
00272                       args[2*item_sep]->collation, fname);
00273   else
00274     my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
00275 }
00276 
00277 } /* namespace drizzled */