00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00082
00083
00084
00085
00086 if (collation == &my_charset_bin)
00087 {
00088 if (derivation <= dt.derivation)
00089 ;
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
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
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
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
00137 set(0, DERIVATION_NONE);
00138 return true;
00139 }
00140 }
00141 else if (derivation < dt.derivation)
00142 {
00143
00144 }
00145 else if (dt.derivation < derivation)
00146 {
00147 set(dt);
00148 }
00149 else
00150 {
00151 if (collation == dt.collation)
00152 {
00153
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 }