54
41
get_collation_number_internal(const char *name)
56
for (CHARSET_INFO **cs= all_charsets;
57
cs < all_charsets+array_elements(all_charsets)-1;
44
for (cs= all_charsets;
45
cs < all_charsets+array_elements(all_charsets)-1 ;
60
if ( cs[0] && cs[0]->name && !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
48
if ( cs[0] && cs[0]->name &&
49
!my_strcasecmp(&my_charset_latin1, cs[0]->name, name))
62
50
return cs[0]->number;
68
static unsigned char *cs_alloc(size_t size)
70
memory_vector.push_back(new unsigned char[size]);
71
return memory_vector.back();
74
56
static bool init_state_maps(CHARSET_INFO *cs)
76
if (!(cs->state_map= cs_alloc(256)))
62
if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
79
if (!(cs->ident_map= cs_alloc(256)))
65
if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
82
unsigned char *state_map= cs->state_map;
83
unsigned char *ident_map= cs->ident_map;
68
state_map= cs->state_map;
69
ident_map= cs->ident_map;
85
71
/* Fill state_map with states to get a faster parser */
86
for (int i= 0; i < 256; i++)
72
for (i=0; i < 256 ; i++)
88
74
if (my_isalpha(cs,i))
89
state_map[i]= MY_LEX_IDENT;
75
state_map[i]=(uchar) MY_LEX_IDENT;
90
76
else if (my_isdigit(cs,i))
91
state_map[i]= MY_LEX_NUMBER_IDENT;
77
state_map[i]=(uchar) MY_LEX_NUMBER_IDENT;
78
#if defined(USE_MB) && defined(USE_MB_IDENT)
92
79
else if (my_mbcharlen(cs, i)>1)
93
state_map[i]= MY_LEX_IDENT;
80
state_map[i]=(uchar) MY_LEX_IDENT;
94
82
else if (my_isspace(cs,i))
95
state_map[i]= MY_LEX_SKIP;
83
state_map[i]=(uchar) MY_LEX_SKIP;
97
state_map[i]= MY_LEX_CHAR;
85
state_map[i]=(uchar) MY_LEX_CHAR;
99
state_map['_']=state_map['$']= MY_LEX_IDENT;
100
state_map['\'']= MY_LEX_STRING;
101
state_map['.']= MY_LEX_REAL_OR_POINT;
102
state_map['>']=state_map['=']=state_map['!']= MY_LEX_CMP_OP;
103
state_map['<']= MY_LEX_LONG_CMP_OP;
104
state_map['&']=state_map['|']= MY_LEX_BOOL;
105
state_map['#']= MY_LEX_COMMENT;
106
state_map[';']= MY_LEX_SEMICOLON;
107
state_map[':']= MY_LEX_SET_VAR;
108
state_map[0]= MY_LEX_EOL;
109
state_map['\\']= MY_LEX_ESCAPE;
110
state_map['/']= MY_LEX_LONG_COMMENT;
111
state_map['*']= MY_LEX_END_LONG_COMMENT;
112
state_map['@']= MY_LEX_USER_END;
113
state_map['`']= MY_LEX_USER_VARIABLE_DELIMITER;
114
state_map['"']= MY_LEX_STRING_OR_DELIMITER;
87
state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) MY_LEX_IDENT;
88
state_map[(uchar)'\'']=(uchar) MY_LEX_STRING;
89
state_map[(uchar)'.']=(uchar) MY_LEX_REAL_OR_POINT;
90
state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) MY_LEX_CMP_OP;
91
state_map[(uchar)'<']= (uchar) MY_LEX_LONG_CMP_OP;
92
state_map[(uchar)'&']=state_map[(uchar)'|']=(uchar) MY_LEX_BOOL;
93
state_map[(uchar)'#']=(uchar) MY_LEX_COMMENT;
94
state_map[(uchar)';']=(uchar) MY_LEX_SEMICOLON;
95
state_map[(uchar)':']=(uchar) MY_LEX_SET_VAR;
96
state_map[0]=(uchar) MY_LEX_EOL;
97
state_map[(uchar)'\\']= (uchar) MY_LEX_ESCAPE;
98
state_map[(uchar)'/']= (uchar) MY_LEX_LONG_COMMENT;
99
state_map[(uchar)'*']= (uchar) MY_LEX_END_LONG_COMMENT;
100
state_map[(uchar)'@']= (uchar) MY_LEX_USER_END;
101
state_map[(uchar) '`']= (uchar) MY_LEX_USER_VARIABLE_DELIMITER;
102
state_map[(uchar)'"']= (uchar) MY_LEX_STRING_OR_DELIMITER;
117
105
Create a second map to make it faster to find identifiers
119
for (int i= 0; i < 256; i++)
107
for (i=0; i < 256 ; i++)
121
ident_map[i]= state_map[i] == MY_LEX_IDENT || state_map[i] == MY_LEX_NUMBER_IDENT;
109
ident_map[i]= (uchar) (state_map[i] == MY_LEX_IDENT ||
110
state_map[i] == MY_LEX_NUMBER_IDENT);
124
113
/* Special handling of hex and binary strings */
125
state_map['x']= state_map['X']= MY_LEX_IDENT_OR_HEX;
126
state_map['b']= state_map['B']= MY_LEX_IDENT_OR_BIN;
130
static bool charset_initialized= false;
132
DRIZZLED_API CHARSET_INFO *all_charsets[256];
133
const DRIZZLED_API CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
114
state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX;
115
state_map[(uchar)'b']= state_map[(uchar)'B']= (uchar) MY_LEX_IDENT_OR_BIN;
120
static void simple_cs_init_functions(CHARSET_INFO *cs)
122
if (cs->state & MY_CS_BINSORT)
123
cs->coll= &my_collation_8bit_bin_handler;
125
cs->coll= &my_collation_8bit_simple_ci_handler;
127
cs->cset= &my_charset_8bit_handler;
132
static int cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
134
to->number= from->number ? from->number : to->number;
137
if (!(to->csname= my_once_strdup(from->csname,MYF(MY_WME))))
141
if (!(to->name= my_once_strdup(from->name,MYF(MY_WME))))
145
if (!(to->comment= my_once_strdup(from->comment,MYF(MY_WME))))
150
if (!(to->ctype= (uchar*) my_once_memdup((char*) from->ctype,
151
MY_CS_CTYPE_TABLE_SIZE,
154
if (init_state_maps(to))
158
if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower,
159
MY_CS_TO_LOWER_TABLE_SIZE,
164
if (!(to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper,
165
MY_CS_TO_UPPER_TABLE_SIZE,
168
if (from->sort_order)
170
if (!(to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order,
171
MY_CS_SORT_ORDER_TABLE_SIZE,
176
if (from->tab_to_uni)
178
uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16_t);
179
if (!(to->tab_to_uni= (uint16_t*) my_once_memdup((char*)from->tab_to_uni,
184
if (!(to->tailoring= my_once_strdup(from->tailoring,MYF(MY_WME))))
195
static bool simple_cs_is_full(CHARSET_INFO *cs)
197
return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper &&
199
(cs->number && cs->name &&
200
(cs->sort_order || (cs->state & MY_CS_BINSORT) )));
205
copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from)
207
to->cset= from->cset;
208
to->coll= from->coll;
209
to->strxfrm_multiply= from->strxfrm_multiply;
210
to->min_sort_char= from->min_sort_char;
211
to->max_sort_char= from->max_sort_char;
212
to->mbminlen= from->mbminlen;
213
to->mbmaxlen= from->mbmaxlen;
217
static int add_collation(CHARSET_INFO *cs)
219
if (cs->name && (cs->number ||
220
(cs->number=get_collation_number_internal(cs->name))))
222
if (!all_charsets[cs->number])
224
if (!(all_charsets[cs->number]=
225
(CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
227
memset(all_charsets[cs->number], 0, sizeof(CHARSET_INFO));
230
if (cs->primary_number == cs->number)
231
cs->state |= MY_CS_PRIMARY;
233
if (cs->binary_number == cs->number)
234
cs->state |= MY_CS_BINSORT;
236
all_charsets[cs->number]->state|= cs->state;
238
if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
240
CHARSET_INFO *newcs= all_charsets[cs->number];
241
if (cs_copy_data(all_charsets[cs->number],cs))
244
newcs->levels_for_compare= 1;
245
newcs->levels_for_order= 1;
247
if (!strcmp(cs->csname,"ucs2") )
249
#if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS)
250
copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci);
251
newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
254
else if (!strcmp(cs->csname, "utf8"))
256
#if defined (HAVE_CHARSET_utf8mb3) && defined(HAVE_UCA_COLLATIONS)
257
copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci);
258
newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED;
261
else if (!strcmp(cs->csname, "utf8mb3"))
263
#if defined (HAVE_CHARSET_utf8mb3) && defined(HAVE_UCA_COLLATIONS)
264
copy_uca_collation(newcs, &my_charset_utf8mb3_unicode_ci);
265
newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED;
268
else if (!strcmp(cs->csname, "utf16"))
270
#if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS)
271
copy_uca_collation(newcs, &my_charset_utf16_unicode_ci);
272
newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
275
else if (!strcmp(cs->csname, "utf32"))
277
#if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS)
278
copy_uca_collation(newcs, &my_charset_utf32_unicode_ci);
279
newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
284
uchar *sort_order= all_charsets[cs->number]->sort_order;
285
simple_cs_init_functions(all_charsets[cs->number]);
288
if (simple_cs_is_full(all_charsets[cs->number]))
290
all_charsets[cs->number]->state |= MY_CS_LOADED;
292
all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
295
Check if case sensitive sort order: A < a < B.
296
We need MY_CS_FLAG for regex library, and for
297
case sensitivity flag for 5.0 client protocol,
298
to support isCaseSensitive() method in JDBC driver
300
if (sort_order && sort_order['A'] < sort_order['a'] &&
301
sort_order['a'] < sort_order['B'])
302
all_charsets[cs->number]->state|= MY_CS_CSSORT;
304
if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number]))
305
all_charsets[cs->number]->state|= MY_CS_PUREASCII;
306
if (!my_charset_is_ascii_compatible(cs))
307
all_charsets[cs->number]->state|= MY_CS_NONASCII;
313
We need the below to make get_charset_name()
314
and get_charset_number() working even if a
315
character set has not been really incompiled.
316
The above functions are used for example
317
in error message compiler extra/comp_err.c.
318
If a character set was compiled, this information
319
will get lost and overwritten in add_compiled_collation().
321
CHARSET_INFO *dst= all_charsets[cs->number];
322
dst->number= cs->number;
324
if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME))))
326
if (cs->csname && !dst->csname)
327
if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME))))
329
if (cs->name && !dst->name)
330
if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME))))
334
cs->primary_number= 0;
335
cs->binary_number= 0;
338
cs->sort_order= NULL;
345
#define MY_MAX_ALLOWED_BUF 1024*1024
346
#define MY_CHARSET_INDEX "Index.xml"
348
const char *charsets_dir= NULL;
349
static int charset_initialized=0;
352
static bool my_read_charset_file(const char *filename, myf myflags)
357
struct stat stat_info;
359
if (stat(filename, &stat_info) ||
360
((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) ||
361
!(buf= (uchar*) my_malloc(len,myflags)))
364
if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
366
tmp_len=my_read(fd, buf, len, myflags);
367
my_close(fd,myflags);
371
if (my_parse_charset_xml((char*) buf,len,add_collation))
374
printf("ERROR at line %d pos %d '%s'\n",
375
my_xml_error_lineno(&p)+1,
376
my_xml_error_pos(&p),
377
my_xml_error_string(&p));
381
my_free(buf, myflags);
385
my_free(buf, myflags);
390
char *get_charsets_dir(char *buf)
392
const char *sharedir= SHAREDIR;
395
if (charsets_dir != NULL)
396
strmake(buf, charsets_dir, FN_REFLEN-1);
399
if (test_if_hard_path(sharedir) ||
400
is_prefix(sharedir, DEFAULT_CHARSET_HOME))
401
strxmov(buf, sharedir, "/", CHARSET_DIR, NullS);
403
strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR,
406
res= convert_dirname(buf,buf,NullS);
410
CHARSET_INFO *all_charsets[256];
411
const CHARSET_INFO *default_charset_info = &my_charset_latin1;
135
413
void add_compiled_collation(CHARSET_INFO * cs)
138
416
cs->state|= MY_CS_AVAILABLE;
419
static void *cs_alloc(size_t size)
421
return my_once_alloc(size, MYF(MY_WME));
141
425
static bool init_available_charsets(myf myflags)
427
char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
145
430
We have to use charset_initialized to not lock on THR_LOCK_charset
146
431
inside get_internal_charset...
148
if (charset_initialized == false)
433
if (!charset_initialized)
150
435
CHARSET_INFO **cs;
151
memset(&all_charsets, 0, sizeof(all_charsets));
152
init_compiled_charsets(myflags);
154
/* Copy compiled charsets */
155
for (cs=all_charsets;
156
cs < all_charsets+array_elements(all_charsets)-1 ;
437
To make things thread safe we are not allowing other threads to interfere
438
while we may changing the cs_info_table
440
pthread_mutex_lock(&THR_LOCK_charset);
441
if (!charset_initialized)
443
memset(&all_charsets, 0, sizeof(all_charsets));
444
init_compiled_charsets(myflags);
446
/* Copy compiled charsets */
447
for (cs=all_charsets;
448
cs < all_charsets+array_elements(all_charsets)-1 ;
162
if (init_state_maps(*cs))
454
if (init_state_maps(*cs))
459
stpcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
460
error= my_read_charset_file(fname,myflags);
461
charset_initialized=1;
167
charset_initialized= true;
463
pthread_mutex_unlock(&THR_LOCK_charset);
169
assert(charset_initialized);
469
void free_charsets(void)
177
charset_initialized= false;
179
while (not memory_vector.empty())
181
delete[] memory_vector.back();
182
memory_vector.pop_back();
471
charset_initialized=0;
187
uint32_t get_collation_number(const char *name)
475
uint get_collation_number(const char *name)
189
477
init_available_charsets(MYF(0));
190
478
return get_collation_number_internal(name);
194
uint32_t get_charset_number(const char *charset_name, uint32_t cs_flags)
482
uint get_charset_number(const char *charset_name, uint cs_flags)
196
484
CHARSET_INFO **cs;
197
485
init_available_charsets(MYF(0));
199
487
for (cs= all_charsets;
200
488
cs < all_charsets+array_elements(all_charsets)-1 ;
203
if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
491
if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
492
!my_strcasecmp(&my_charset_latin1, cs[0]->csname, charset_name))
204
493
return cs[0]->number;
210
const char *get_charset_name(uint32_t charset_number)
499
const char *get_charset_name(uint charset_number)
501
const CHARSET_INFO *cs;
212
502
init_available_charsets(MYF(0));
214
const CHARSET_INFO *cs= all_charsets[charset_number];
504
cs=all_charsets[charset_number];
215
505
if (cs && (cs->number == charset_number) && cs->name )
218
return "?"; /* this mimics find_type() */
506
return (char*) cs->name;
508
return (char*) "?"; /* this mimics find_type() */
222
static const CHARSET_INFO *get_internal_charset(uint32_t cs_number)
512
static const CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
224
515
CHARSET_INFO *cs;
226
517
To make things thread safe we are not allowing other threads to interfere
227
518
while we may changing the cs_info_table
520
pthread_mutex_lock(&THR_LOCK_charset);
229
521
if ((cs= all_charsets[cs_number]))
231
523
if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
525
strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
526
my_read_charset_file(buf,flags);
235
528
cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
243
536
cs->state|= MY_CS_READY;
538
pthread_mutex_unlock(&THR_LOCK_charset);
250
const CHARSET_INFO *get_charset(uint32_t cs_number)
543
const const CHARSET_INFO *get_charset(uint cs_number, myf flags)
252
545
const CHARSET_INFO *cs;
253
546
if (cs_number == default_charset_info->number)
254
547
return default_charset_info;
256
549
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
258
551
if (!cs_number || cs_number >= array_elements(all_charsets)-1)
261
cs= get_internal_charset(cs_number);
554
cs=get_internal_charset(cs_number, flags);
556
if (!cs && (flags & MY_WME))
558
char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)], cs_string[23];
559
stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
561
int10_to_str(cs_number, cs_string+1, 10);
562
my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
266
const CHARSET_INFO *get_charset_by_name(const char *cs_name)
567
const CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
269
570
const CHARSET_INFO *cs;
270
571
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
272
cs_number= get_collation_number(cs_name);
273
cs= cs_number ? get_internal_charset(cs_number) : NULL;
573
cs_number=get_collation_number(cs_name);
574
cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
576
if (!cs && (flags & MY_WME))
578
char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
579
stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
580
my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file);
279
const CHARSET_INFO *get_charset_by_csname(const char *cs_name, uint32_t cs_flags)
587
const CHARSET_INFO *get_charset_by_csname(const char *cs_name,
282
592
const CHARSET_INFO *cs;
284
594
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
286
596
cs_number= get_charset_number(cs_name, cs_flags);
287
cs= cs_number ? get_internal_charset(cs_number) : NULL;
597
cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
599
if (!cs && (flags & MY_WME))
601
char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
602
stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
603
my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
611
Resolve character set by the character set name (utf8, latin1, ...).
613
The function tries to resolve character set by the specified name. If
614
there is character set with the given name, it is assigned to the "cs"
615
parameter and false is returned. If there is no such character set,
616
"default_cs" is assigned to the "cs" and true is returned.
618
@param[in] cs_name Character set name.
619
@param[in] default_cs Default character set.
620
@param[out] cs Variable to store character set.
622
@return false if character set was resolved successfully; true if there
623
is no character set with given name.
626
bool resolve_charset(const char *cs_name,
627
const CHARSET_INFO *default_cs,
628
const CHARSET_INFO **cs)
630
*cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0));
643
Resolve collation by the collation name (utf8_general_ci, ...).
645
The function tries to resolve collation by the specified name. If there
646
is collation with the given name, it is assigned to the "cl" parameter
647
and false is returned. If there is no such collation, "default_cl" is
648
assigned to the "cl" and true is returned.
650
@param[out] cl Variable to store collation.
651
@param[in] cl_name Collation name.
652
@param[in] default_cl Default collation.
654
@return false if collation was resolved successfully; true if there is no
655
collation with given name.
658
bool resolve_collation(const char *cl_name,
659
const CHARSET_INFO *default_cl,
660
const CHARSET_INFO **cl)
662
*cl= get_charset_by_name(cl_name, MYF(0));
675
Escape string with backslashes (\)
678
escape_string_for_drizzle()
679
charset_info Charset of the strings
680
to Buffer for escaped string
681
to_length Length of destination buffer, or 0
682
from The string to escape
683
length The length of the string to escape
686
This escapes the contents of a string by adding backslashes before special
687
characters, and turning others into specific escape sequences, such as
688
turning newlines into \n and null bytes into \0.
691
To maintain compatibility with the old C API, to_length may be 0 to mean
695
(size_t) -1 The escaped string did not fit in the to buffer
696
# The length of the escaped string
699
size_t escape_string_for_drizzle(const CHARSET_INFO *charset_info,
700
char *to, size_t to_length,
701
const char *from, size_t length)
703
const char *to_start= to;
704
const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
705
bool overflow= false;
707
bool use_mb_flag= use_mb(charset_info);
709
for (end= from + length; from < end; from++)
714
if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
716
if (to + tmp_length > to_end)
727
If the next character appears to begin a multi-byte character, we
728
escape that first byte of that apparent multi-byte character. (The
729
character just looks like a multi-byte character -- if it were actually
730
a multi-byte character, it would have been passed through in the test
733
Without this check, we can create a problem by converting an invalid
734
multi-byte character into a valid one. For example, 0xbf27 is not
735
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
737
if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1)
742
case 0: /* Must be escaped for 'mysql' */
745
case '\n': /* Must be escaped for logs */
757
case '"': /* Better safe than sorry */
760
case '\032': /* This gives problems on Win32 */
785
return overflow ? (size_t) -1 : (size_t) (to - to_start);
789
#ifdef BACKSLASH_MBTAIL
790
static CHARSET_INFO *fs_cset_cache= NULL;
792
CHARSET_INFO *fs_character_set()
797
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE,
798
buf+2, sizeof(buf)-3);
800
We cannot call get_charset_by_name here
801
because fs_character_set() is executed before
802
LOCK_THD_charset mutex initialization, which
803
is used inside get_charset_by_name.
804
As we're now interested in cp932 only,
805
let's just detect it using strcmp().
807
fs_cset_cache= !strcmp(buf, "cp932") ?
808
&my_charset_cp932_japanese_ci : &my_charset_bin;
810
return fs_cset_cache;
294
815
Escape apostrophes by doubling them up