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/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
00080
00081
00082
00083
00084 if (collation == &my_charset_bin)
00085 {
00086 if (derivation <= dt.derivation)
00087 ;
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
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
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
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
00135 set(0, DERIVATION_NONE);
00136 return true;
00137 }
00138 }
00139 else if (derivation < dt.derivation)
00140 {
00141
00142 }
00143 else if (dt.derivation < derivation)
00144 {
00145 set(dt);
00146 }
00147 else
00148 {
00149 if (collation == dt.collation)
00150 {
00151
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 }