summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc31
-rw-r--r--sql/field.h7
-rw-r--r--sql/ha_blackhole.cc2
-rw-r--r--sql/ha_federated.cc44
-rw-r--r--sql/ha_myisammrg.cc2
-rw-r--r--sql/ha_ndbcluster.cc199
-rw-r--r--sql/handler.cc85
-rw-r--r--sql/handler.h6
-rw-r--r--sql/item.cc68
-rw-r--r--sql/item.h36
-rw-r--r--sql/item_cmpfunc.cc22
-rw-r--r--sql/item_create.cc6
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc18
-rw-r--r--sql/item_func.h10
-rw-r--r--sql/item_strfunc.cc115
-rw-r--r--sql/item_strfunc.h35
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/item_timefunc.cc67
-rw-r--r--sql/mysql_priv.h25
-rw-r--r--sql/opt_range.cc187
-rw-r--r--sql/set_var.cc40
-rw-r--r--sql/set_var.h22
-rw-r--r--sql/sql_acl.cc73
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_cache.cc2
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_delete.cc8
-rw-r--r--sql/sql_insert.cc176
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_lex.h5
-rw-r--r--sql/sql_load.cc10
-rw-r--r--sql/sql_locale.cc1607
-rw-r--r--sql/sql_parse.cc87
-rw-r--r--sql/sql_prepare.cc35
-rw-r--r--sql/sql_select.cc177
-rw-r--r--sql/sql_show.cc22
-rw-r--r--sql/sql_table.cc30
-rw-r--r--sql/sql_trigger.cc47
-rw-r--r--sql/sql_trigger.h8
-rw-r--r--sql/sql_udf.cc10
-rw-r--r--sql/sql_udf.h31
-rw-r--r--sql/sql_update.cc30
-rw-r--r--sql/sql_yacc.yy49
-rw-r--r--sql/table.cc58
-rw-r--r--sql/table.h7
-rw-r--r--sql/unireg.cc49
49 files changed, 3067 insertions, 508 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 453e50a3b0b..416f0faf1a6 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -79,7 +79,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
set_var.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
- sql_prepare.cc sql_error.cc \
+ sql_prepare.cc sql_error.cc sql_locale.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \
diff --git a/sql/field.cc b/sql/field.cc
index 7c25e4ad9f7..946351efe36 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1515,7 +1515,8 @@ bool Field::optimize_range(uint idx, uint part)
}
-Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
+Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type __attribute__((unused)))
{
Field *tmp;
if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
@@ -1540,7 +1541,7 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
uint new_null_bit)
{
Field *tmp;
- if ((tmp= new_field(root, new_table)))
+ if ((tmp= new_field(root, new_table, table == new_table)))
{
tmp->ptr= new_ptr;
tmp->null_ptr= new_null_ptr;
@@ -6227,29 +6228,21 @@ uint Field_string::max_packed_col_length(uint max_length)
}
-Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
+Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type)
{
Field *new_field;
- if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
- return Field::new_field(root, new_table);
+ if (type() != MYSQL_TYPE_VAR_STRING || keep_type)
+ return Field::new_field(root, new_table, keep_type);
/*
Old VARCHAR field which should be modified to a VARCHAR on copy
This is done to ensure that ALTER TABLE will convert old VARCHAR fields
to now VARCHAR fields.
*/
- if ((new_field= new Field_varstring(field_length, maybe_null(),
- field_name, new_table, charset())))
- {
- /*
- delayed_insert::get_local_table() needs a ptr copied from old table.
- This is what other new_field() methods do too. The above method of
- Field_varstring sets ptr to NULL.
- */
- new_field->ptr= ptr;
- }
- return new_field;
+ return new Field_varstring(field_length, maybe_null(),
+ field_name, new_table, charset());
}
/****************************************************************************
@@ -6741,9 +6734,11 @@ int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
}
-Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table)
+Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type)
{
- Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table);
+ Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
+ keep_type);
if (res)
res->length_bytes= length_bytes;
return res;
diff --git a/sql/field.h b/sql/field.h
index ed13372df71..3b33d3651e3 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -211,7 +211,8 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type);
virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
@@ -1033,7 +1034,7 @@ public:
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
};
@@ -1105,7 +1106,7 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc
index 7632ed59949..2505919af39 100644
--- a/sql/ha_blackhole.cc
+++ b/sql/ha_blackhole.cc
@@ -47,7 +47,7 @@ handlerton blackhole_hton= {
NULL, /* create_cursor_read_view */
NULL, /* set_cursor_read_view */
NULL, /* close_cursor_read_view */
- HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE
+ HTON_CAN_RECREATE
};
/*****************************************************************************
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index 11f676d9cf6..e2988df1619 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -1810,19 +1810,13 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
/*
buffers for following strings
*/
- char old_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
- char new_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char field_value_buffer[STRING_BUFFER_USUAL_SIZE];
char update_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char where_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- /* stores the value to be replaced of the field were are updating */
- String old_field_value(old_field_value_buffer,
- sizeof(old_field_value_buffer),
- &my_charset_bin);
- /* stores the new value of the field */
- String new_field_value(new_field_value_buffer,
- sizeof(new_field_value_buffer),
- &my_charset_bin);
+ /* Work area for field values */
+ String field_value(field_value_buffer, sizeof(field_value_buffer),
+ &my_charset_bin);
/* stores the update query */
String update_string(update_buffer,
sizeof(update_buffer),
@@ -1835,8 +1829,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
/*
set string lengths to 0 to avoid misc chars in string
*/
- old_field_value.length(0);
- new_field_value.length(0);
+ field_value.length(0);
update_string.length(0);
where_string.length(0);
@@ -1850,8 +1843,8 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
In this loop, we want to match column names to values being inserted
(while building INSERT statement).
- Iterate through table->field (new data) and share->old_filed (old_data)
- using the same index to created an SQL UPDATE statement, new data is
+ Iterate through table->field (new data) and share->old_field (old_data)
+ using the same index to create an SQL UPDATE statement. New data is
used to create SET field=value and old data is used to create WHERE
field=oldvalue
*/
@@ -1863,30 +1856,28 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
update_string.append(FEDERATED_EQ);
if ((*field)->is_null())
- new_field_value.append(FEDERATED_NULL);
+ update_string.append(FEDERATED_NULL);
else
{
/* otherwise = */
- (*field)->val_str(&new_field_value);
- (*field)->quote_data(&new_field_value);
-
- if (!field_in_record_is_null(table, *field, (char*) old_data))
- where_string.append(FEDERATED_EQ);
+ (*field)->val_str(&field_value);
+ (*field)->quote_data(&field_value);
+ update_string.append(field_value);
+ field_value.length(0);
}
if (field_in_record_is_null(table, *field, (char*) old_data))
where_string.append(FEDERATED_ISNULL);
else
{
- (*field)->val_str(&old_field_value,
+ where_string.append(FEDERATED_EQ);
+ (*field)->val_str(&field_value,
(char*) (old_data + (*field)->offset()));
- (*field)->quote_data(&old_field_value);
- where_string.append(old_field_value);
+ (*field)->quote_data(&field_value);
+ where_string.append(field_value);
+ field_value.length(0);
}
- update_string.append(new_field_value);
- new_field_value.length(0);
-
/*
Only append conjunctions if we have another field in which
to iterate
@@ -1896,7 +1887,6 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
update_string.append(FEDERATED_COMMA);
where_string.append(FEDERATED_AND);
}
- old_field_value.length(0);
}
update_string.append(FEDERATED_WHERE);
update_string.append(where_string);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index d2fd1a9e28a..9780f163634 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -55,7 +55,7 @@ handlerton myisammrg_hton= {
NULL, /* create_cursor_read_view */
NULL, /* set_cursor_read_view */
NULL, /* close_cursor_read_view */
- HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE
+ HTON_CAN_RECREATE
};
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index a9c23485042..1af677fa754 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -363,6 +363,7 @@ void ha_ndbcluster::records_update()
{
Ndb *ndb= get_ndb();
struct Ndb_statistics stat;
+ ndb->setDatabaseName(m_dbname);
if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
@@ -2253,9 +2254,10 @@ int ha_ndbcluster::write_row(byte *record)
{
Ndb *ndb= get_ndb();
Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1;
+ char buff[22];
DBUG_PRINT("info",
- ("Trying to set next auto increment value to %llu",
- (ulonglong) next_val));
+ ("Trying to set next auto increment value to %s",
+ llstr(next_val, buff)));
if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE)
== -1)
ERR_RETURN(ndb->getNdbError());
@@ -2581,13 +2583,15 @@ void ha_ndbcluster::unpack_record(byte* buf)
{
// Table with hidden primary key
int hidden_no= table->s->fields;
+ char buff[22];
const NDBTAB *tab= (const NDBTAB *) m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
const NdbRecAttr* rec= m_value[hidden_no].rec;
DBUG_ASSERT(rec);
- DBUG_PRINT("hidden", ("%d: %s \"%llu\"", hidden_no,
- hidden_col->getName(), rec->u_64_value()));
- }
+ DBUG_PRINT("hidden", ("%d: %s \"%s\"", hidden_no,
+ hidden_col->getName(),
+ llstr(rec->u_64_value(), buff)));
+ }
print_results();
#endif
DBUG_VOID_RETURN;
@@ -3081,6 +3085,7 @@ void ha_ndbcluster::info(uint flag)
DBUG_VOID_RETURN;
Ndb *ndb= get_ndb();
struct Ndb_statistics stat;
+ ndb->setDatabaseName(m_dbname);
if (current_thd->variables.ndb_use_exact_count &&
ndb_get_table_statistics(ndb, m_tabname, &stat) == 0)
{
@@ -3212,20 +3217,11 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
break;
case HA_EXTRA_IGNORE_DUP_KEY: /* Dup keys don't rollback everything*/
DBUG_PRINT("info", ("HA_EXTRA_IGNORE_DUP_KEY"));
- if (current_thd->lex->sql_command == SQLCOM_REPLACE && !m_has_unique_index)
- {
- DBUG_PRINT("info", ("Turning ON use of write instead of insert"));
- m_use_write= TRUE;
- } else
- {
- DBUG_PRINT("info", ("Ignoring duplicate key"));
- m_ignore_dup_key= TRUE;
- }
+ DBUG_PRINT("info", ("Ignoring duplicate key"));
+ m_ignore_dup_key= TRUE;
break;
case HA_EXTRA_NO_IGNORE_DUP_KEY:
DBUG_PRINT("info", ("HA_EXTRA_NO_IGNORE_DUP_KEY"));
- DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
- m_use_write= FALSE;
m_ignore_dup_key= FALSE;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS: /* Retrieve all columns, not just those
@@ -3255,7 +3251,19 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
DBUG_PRINT("info", ("HA_EXTRA_KEYREAD_PRESERVE_FIELDS"));
break;
-
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ DBUG_PRINT("info", ("HA_EXTRA_WRITE_CAN_REPLACE"));
+ if (!m_has_unique_index)
+ {
+ DBUG_PRINT("info", ("Turning ON use of write instead of insert"));
+ m_use_write= TRUE;
+ }
+ break;
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ DBUG_PRINT("info", ("HA_EXTRA_WRITE_CANNOT_REPLACE"));
+ DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
+ m_use_write= FALSE;
+ break;
}
DBUG_RETURN(0);
@@ -4099,10 +4107,11 @@ static int create_ndb_column(NDBCOL &col,
// Set autoincrement
if (field->flags & AUTO_INCREMENT_FLAG)
{
+ char buff[22];
col.setAutoIncrement(TRUE);
ulonglong value= info->auto_increment_value ?
info->auto_increment_value : (ulonglong) 1;
- DBUG_PRINT("info", ("Autoincrement key, initial: %llu", value));
+ DBUG_PRINT("info", ("Autoincrement key, initial: %s", llstr(value, buff)));
col.setAutoIncrementInitialValue(value);
}
else
@@ -4578,7 +4587,8 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
HA_NO_PREFIX_CHAR_KEYS |
HA_NEED_READ_RANGE_BUFFER |
HA_CAN_GEOMETRY |
- HA_CAN_BIT_FIELD),
+ HA_CAN_BIT_FIELD |
+ HA_PARTIAL_COLUMN_READ),
m_share(0),
m_use_write(FALSE),
m_ignore_dup_key(FALSE),
@@ -5491,8 +5501,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
if (share->commit_count != 0)
{
*commit_count= share->commit_count;
- DBUG_PRINT("info", ("Getting commit_count: %llu from share",
- share->commit_count));
+ char buff[22];
+ DBUG_PRINT("info", ("Getting commit_count: %s from share",
+ llstr(share->commit_count, buff)));
pthread_mutex_unlock(&share->mutex);
free_share(share);
DBUG_RETURN(0);
@@ -5516,7 +5527,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
pthread_mutex_lock(&share->mutex);
if (share->commit_count_lock == lock)
{
- DBUG_PRINT("info", ("Setting commit_count to %llu", stat.commit_count));
+ char buff[22];
+ DBUG_PRINT("info", ("Setting commit_count to %s",
+ llstr(stat.commit_count, buff)));
share->commit_count= stat.commit_count;
*commit_count= stat.commit_count;
}
@@ -5566,13 +5579,12 @@ ndbcluster_cache_retrieval_allowed(THD *thd,
char *full_name, uint full_name_len,
ulonglong *engine_data)
{
- DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
-
Uint64 commit_count;
bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
char *dbname= full_name;
char *tabname= dbname+strlen(dbname)+1;
-
+ char buff[22], buff2[22];
+ DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
DBUG_PRINT("enter", ("dbname: %s, tabname: %s, is_autocommit: %d",
dbname, tabname, is_autocommit));
@@ -5588,8 +5600,8 @@ ndbcluster_cache_retrieval_allowed(THD *thd,
DBUG_PRINT("exit", ("No, could not retrieve commit_count"));
DBUG_RETURN(FALSE);
}
- DBUG_PRINT("info", ("*engine_data: %llu, commit_count: %llu",
- *engine_data, commit_count));
+ DBUG_PRINT("info", ("*engine_data: %s, commit_count: %s",
+ llstr(*engine_data, buff), llstr(commit_count, buff2)));
if (commit_count == 0)
{
*engine_data= 0; /* invalidate */
@@ -5603,7 +5615,8 @@ ndbcluster_cache_retrieval_allowed(THD *thd,
DBUG_RETURN(FALSE);
}
- DBUG_PRINT("exit", ("OK to use cache, engine_data: %llu", *engine_data));
+ DBUG_PRINT("exit", ("OK to use cache, engine_data: %s",
+ llstr(*engine_data, buff)));
DBUG_RETURN(TRUE);
}
@@ -5636,10 +5649,10 @@ ha_ndbcluster::register_query_cache_table(THD *thd,
qc_engine_callback *engine_callback,
ulonglong *engine_data)
{
- DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
-
+ Uint64 commit_count;
+ char buff[22];
bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
-
+ DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
DBUG_PRINT("enter",("dbname: %s, tabname: %s, is_autocommit: %d",
m_dbname, m_tabname, is_autocommit));
@@ -5649,7 +5662,6 @@ ha_ndbcluster::register_query_cache_table(THD *thd,
DBUG_RETURN(FALSE);
}
- Uint64 commit_count;
if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count))
{
*engine_data= 0;
@@ -5658,7 +5670,7 @@ ha_ndbcluster::register_query_cache_table(THD *thd,
}
*engine_data= commit_count;
*engine_callback= ndbcluster_cache_retrieval_allowed;
- DBUG_PRINT("exit", ("commit_count: %llu", commit_count));
+ DBUG_PRINT("exit", ("commit_count: %s", llstr(commit_count, buff)));
DBUG_RETURN(commit_count > 0);
}
@@ -5839,65 +5851,64 @@ int
ndb_get_table_statistics(Ndb* ndb, const char * table,
struct Ndb_statistics * ndbstat)
{
- DBUG_ENTER("ndb_get_table_statistics");
- DBUG_PRINT("enter", ("table: %s", table));
NdbTransaction* pTrans;
+ NdbError error;
int retries= 10;
int retry_sleep= 30 * 1000; /* 30 milliseconds */
+ char buff[22], buff2[22], buff3[22], buff4[22];
+ DBUG_ENTER("ndb_get_table_statistics");
+ DBUG_PRINT("enter", ("table: %s", table));
do
{
- pTrans= ndb->startTransaction();
- if (pTrans == NULL)
+ Uint64 rows, commits, mem;
+ Uint32 size;
+ Uint32 count= 0;
+ Uint64 sum_rows= 0;
+ Uint64 sum_commits= 0;
+ Uint64 sum_row_size= 0;
+ Uint64 sum_mem= 0;
+ NdbScanOperation*pOp;
+ NdbResultSet *rs;
+ int check;
+
+ if ((pTrans= ndb->startTransaction()) == NULL)
{
- if (ndb->getNdbError().status == NdbError::TemporaryError &&
- retries--)
- {
- my_sleep(retry_sleep);
- continue;
- }
- break;
+ error= ndb->getNdbError();
+ goto retry;
+ }
+
+ if ((pOp= pTrans->getNdbScanOperation(table)) == NULL)
+ {
+ error= pTrans->getNdbError();
+ goto retry;
}
-
- NdbScanOperation* pOp= pTrans->getNdbScanOperation(table);
- if (pOp == NULL)
- break;
if (pOp->readTuples(NdbOperation::LM_CommittedRead))
- break;
+ {
+ error= pOp->getNdbError();
+ goto retry;
+ }
- int check= pOp->interpret_exit_last_row();
- if (check == -1)
- break;
+ if (pOp->interpret_exit_last_row() == -1)
+ {
+ error= pOp->getNdbError();
+ goto retry;
+ }
- Uint64 rows, commits, mem;
- Uint32 size;
pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows);
pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits);
pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&size);
pOp->getValue(NdbDictionary::Column::FRAGMENT_MEMORY, (char*)&mem);
- check= pTrans->execute(NdbTransaction::NoCommit,
- NdbTransaction::AbortOnError,
- TRUE);
- if (check == -1)
+ if (pTrans->execute(NdbTransaction::NoCommit,
+ NdbTransaction::AbortOnError,
+ TRUE) == -1)
{
- if (pTrans->getNdbError().status == NdbError::TemporaryError &&
- retries--)
- {
- ndb->closeTransaction(pTrans);
- pTrans= 0;
- my_sleep(retry_sleep);
- continue;
- }
- break;
+ error= pTrans->getNdbError();
+ goto retry;
}
-
- Uint32 count= 0;
- Uint64 sum_rows= 0;
- Uint64 sum_commits= 0;
- Uint64 sum_row_size= 0;
- Uint64 sum_mem= 0;
+
while ((check= pOp->nextResult(TRUE, TRUE)) == 0)
{
sum_rows+= rows;
@@ -5909,7 +5920,10 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
}
if (check == -1)
- break;
+ {
+ error= pOp->getNdbError();
+ goto retry;
+ }
pOp->close(TRUE);
@@ -5920,18 +5934,30 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
ndbstat->row_size= sum_row_size;
ndbstat->fragment_memory= sum_mem;
- DBUG_PRINT("exit", ("records: %llu commits: %llu "
- "row_size: %llu mem: %llu count: %u",
- sum_rows, sum_commits, sum_row_size,
- sum_mem, count));
+ DBUG_PRINT("exit", ("records: %s commits: %s "
+ "row_size: %s mem: %s count: %u",
+ llstr(sum_rows, buff),
+ llstr(sum_commits, buff2),
+ llstr(sum_row_size, buff3),
+ llstr(sum_mem, buff4),
+ count));
DBUG_RETURN(0);
+retry:
+ if (pTrans)
+ {
+ ndb->closeTransaction(pTrans);
+ pTrans= NULL;
+ }
+ if (error.status == NdbError::TemporaryError && retries--)
+ {
+ my_sleep(retry_sleep);
+ continue;
+ }
+ break;
} while(1);
-
- if (pTrans)
- ndb->closeTransaction(pTrans);
- DBUG_PRINT("exit", ("failed"));
- DBUG_RETURN(-1);
+ DBUG_PRINT("exit", ("failed, error %u(%s)", error.code, error.message));
+ ERR_RETURN(error);
}
/*
@@ -6449,9 +6475,12 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
if (ndb_get_table_statistics(ndb, tabname, &stat) == 0)
{
+ char buff[22], buff2[22];
DBUG_PRINT("ndb_util_thread",
- ("Table: %s, commit_count: %llu, rows: %llu",
- share->table_name, stat.commit_count, stat.row_count));
+ ("Table: %s commit_count: %s rows: %s",
+ share->table_name,
+ llstr(stat.commit_count, buff),
+ llstr(stat.row_count, buff2)));
}
else
{
diff --git a/sql/handler.cc b/sql/handler.cc
index b40934ea194..9c03a9ef88f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1471,6 +1471,66 @@ next_insert_id(ulonglong nr,struct system_variables *variables)
}
+void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr)
+{
+ /*
+ If we have set THD::next_insert_id previously and plan to insert an
+ explicitely-specified value larger than this, we need to increase
+ THD::next_insert_id to be greater than the explicit value.
+ */
+ THD *thd= table->in_use;
+ if (thd->clear_next_insert_id && (nr >= thd->next_insert_id))
+ {
+ if (thd->variables.auto_increment_increment != 1)
+ nr= next_insert_id(nr, &thd->variables);
+ else
+ nr++;
+ thd->next_insert_id= nr;
+ DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr));
+ }
+}
+
+
+/*
+ Computes the largest number X:
+ - smaller than or equal to "nr"
+ - of the form: auto_increment_offset + N * auto_increment_increment
+ where N>=0.
+
+ SYNOPSIS
+ prev_insert_id
+ nr Number to "round down"
+ variables variables struct containing auto_increment_increment and
+ auto_increment_offset
+
+ RETURN
+ The number X if it exists, "nr" otherwise.
+*/
+
+inline ulonglong
+prev_insert_id(ulonglong nr, struct system_variables *variables)
+{
+ if (unlikely(nr < variables->auto_increment_offset))
+ {
+ /*
+ There's nothing good we can do here. That is a pathological case, where
+ the offset is larger than the column's max possible value, i.e. not even
+ the first sequence value may be inserted. User will receive warning.
+ */
+ DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
+ "auto_increment_offset: %lu",
+ nr, variables->auto_increment_offset));
+ return nr;
+ }
+ if (variables->auto_increment_increment == 1)
+ return nr; // optimization of the formula below
+ nr= (((nr - variables->auto_increment_offset)) /
+ (ulonglong) variables->auto_increment_increment);
+ return (nr * (ulonglong) variables->auto_increment_increment +
+ variables->auto_increment_offset);
+}
+
+
/*
Update the auto_increment field if necessary
@@ -1547,17 +1607,7 @@ bool handler::update_auto_increment()
/* Clear flag for next row */
/* Mark that we didn't generate a new value **/
auto_increment_column_changed=0;
-
- /* Update next_insert_id if we have already generated a value */
- if (thd->clear_next_insert_id && nr >= thd->next_insert_id)
- {
- if (variables->auto_increment_increment != 1)
- nr= next_insert_id(nr, variables);
- else
- nr++;
- thd->next_insert_id= nr;
- DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr));
- }
+ adjust_next_insert_id_after_explicit_value(nr);
DBUG_RETURN(0);
}
if (!(nr= thd->next_insert_id))
@@ -1580,10 +1630,19 @@ bool handler::update_auto_increment()
/* Mark that we should clear next_insert_id before next stmt */
thd->clear_next_insert_id= 1;
- if (!table->next_number_field->store((longlong) nr, TRUE))
+ if (likely(!table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id((ulonglong) nr);
else
- thd->insert_id(table->next_number_field->val_int());
+ {
+ /*
+ overflow of the field; we'll use the max value, however we try to
+ decrease it to honour auto_increment_* variables:
+ */
+ nr= prev_insert_id(table->next_number_field->val_int(), variables);
+ thd->insert_id(nr);
+ if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
+ thd->insert_id(nr= table->next_number_field->val_int());
+ }
/*
We can't set next_insert_id if the auto-increment key is not the
diff --git a/sql/handler.h b/sql/handler.h
index 31aac075a5e..44de0cc715a 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -57,6 +57,7 @@
see mi_rsame/heap_rsame/myrg_rsame
*/
#define HA_READ_RND_SAME (1 << 0)
+#define HA_PARTIAL_COLUMN_READ (1 << 1) /* read may not return all columns */
#define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */
#define HA_REC_NOT_IN_SEQ (1 << 3) /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */
@@ -409,7 +410,6 @@ struct show_table_alias_st {
#define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter
#define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate
#define HTON_HIDDEN (1 << 3) //Engine does not appear in lists
-#define HTON_ALTER_CANNOT_CREATE (1 << 4) //Cannot use alter to create
typedef struct st_thd_trans
{
@@ -428,7 +428,8 @@ typedef struct st_ha_create_information
{
CHARSET_INFO *table_charset, *default_table_charset;
LEX_STRING connect_string;
- const char *comment,*password;
+ LEX_STRING comment;
+ const char *password;
const char *data_file_name, *index_file_name;
const char *alias;
ulonglong max_rows,min_rows;
@@ -563,6 +564,7 @@ public:
{}
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
int ha_open(const char *name, int mode, int test_if_locked);
+ void adjust_next_insert_id_after_explicit_value(ulonglong nr);
bool update_auto_increment();
virtual void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf);
diff --git a/sql/item.cc b/sql/item.cc
index 24efc1f106f..511ea1ffb44 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1315,35 +1315,37 @@ void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3,
static
-void my_coll_agg_error(Item** args, uint count, const char *fname)
+void my_coll_agg_error(Item** args, uint count, const char *fname,
+ int item_sep)
{
if (count == 2)
- my_coll_agg_error(args[0]->collation, args[1]->collation, fname);
+ my_coll_agg_error(args[0]->collation, args[item_sep]->collation, fname);
else if (count == 3)
- my_coll_agg_error(args[0]->collation, args[1]->collation,
- args[2]->collation, fname);
+ my_coll_agg_error(args[0]->collation, args[item_sep]->collation,
+ args[2*item_sep]->collation, fname);
else
my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
}
bool agg_item_collations(DTCollation &c, const char *fname,
- Item **av, uint count, uint flags)
+ Item **av, uint count, uint flags, int item_sep)
{
uint i;
+ Item **arg;
c.set(av[0]->collation);
- for (i= 1; i < count; i++)
+ for (i= 1, arg= &av[item_sep]; i < count; i++, arg++)
{
- if (c.aggregate(av[i]->collation, flags))
+ if (c.aggregate((*arg)->collation, flags))
{
- my_coll_agg_error(av, count, fname);
+ my_coll_agg_error(av, count, fname, item_sep);
return TRUE;
}
}
if ((flags & MY_COLL_DISALLOW_NONE) &&
c.derivation == DERIVATION_NONE)
{
- my_coll_agg_error(av, count, fname);
+ my_coll_agg_error(av, count, fname, item_sep);
return TRUE;
}
return FALSE;
@@ -1354,7 +1356,7 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
Item **av, uint count, uint flags)
{
return (agg_item_collations(c, fname, av, count,
- flags | MY_COLL_DISALLOW_NONE));
+ flags | MY_COLL_DISALLOW_NONE, 1));
}
@@ -1377,13 +1379,22 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
+
+ Since this function calls THD::change_item_tree() on the passed Item **
+ pointers, it is necessary to pass the original Item **'s, not copies.
+ Otherwise their values will not be properly restored (see BUG#20769).
+ If the items are not consecutive (eg. args[2] and args[5]), use the
+ item_sep argument, ie.
+
+ agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
+
*/
bool agg_item_charsets(DTCollation &coll, const char *fname,
- Item **args, uint nargs, uint flags)
+ Item **args, uint nargs, uint flags, int item_sep)
{
- Item **arg, **last, *safe_args[2];
- if (agg_item_collations(coll, fname, args, nargs, flags))
+ Item **arg, *safe_args[2];
+ if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
return TRUE;
/*
@@ -1396,19 +1407,20 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
if (nargs >=2 && nargs <= 3)
{
safe_args[0]= args[0];
- safe_args[1]= args[1];
+ safe_args[1]= args[item_sep];
}
THD *thd= current_thd;
Query_arena *arena, backup;
bool res= FALSE;
+ uint i;
/*
In case we're in statement prepare, create conversion item
in its memory: it will be reused on each execute.
*/
arena= thd->activate_stmt_arena_if_needed(&backup);
- for (arg= args, last= args + nargs; arg < last; arg++)
+ for (i= 0, arg= args; i < nargs; i++, arg+= item_sep)
{
Item* conv;
uint32 dummy_offset;
@@ -1423,9 +1435,9 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
{
/* restore the original arguments for better error message */
args[0]= safe_args[0];
- args[1]= safe_args[1];
+ args[item_sep]= safe_args[1];
}
- my_coll_agg_error(args, nargs, fname);
+ my_coll_agg_error(args, nargs, fname, item_sep);
res= TRUE;
break; // we cannot return here, we need to restore "arena".
}
@@ -1457,7 +1469,18 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
}
-
+void Item_ident_for_show::make_field(Send_field *tmp_field)
+{
+ tmp_field->table_name= tmp_field->org_table_name= table_name;
+ tmp_field->db_name= db_name;
+ tmp_field->col_name= tmp_field->org_col_name= field->field_name;
+ tmp_field->charsetnr= field->charset()->number;
+ tmp_field->length=field->field_length;
+ tmp_field->type=field->type();
+ tmp_field->flags= field->table->maybe_null ?
+ (field->flags & ~NOT_NULL_FLAG) : field->flags;
+ tmp_field->decimals= 0;
+}
/**********************************************/
@@ -5350,9 +5373,14 @@ void Item_insert_value::print(String *str)
void Item_trigger_field::setup_field(THD *thd, TABLE *table,
GRANT_INFO *table_grant_info)
{
+ /*
+ There is no sense in marking fields used by trigger with current value
+ of THD::query_id since it is completely unrelated to the THD::query_id
+ value for statements which will invoke trigger. So instead we use
+ Table_triggers_list::mark_fields_used() method which is called during
+ execution of these statements.
+ */
bool save_set_query_id= thd->set_query_id;
-
- /* TODO: Think more about consequences of this step. */
thd->set_query_id= 0;
/*
Try to find field by its name and if it will be found
diff --git a/sql/item.h b/sql/item.h
index 2cadfda6895..b7b9f972f67 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -827,13 +827,6 @@ protected:
public:
LEX_STRING m_name;
- /*
- Buffer, pointing to the string value of the item. We need it to
- protect internal buffer from changes. See comment to analogous
- member in Item_param for more details.
- */
- String str_value_ptr;
-
public:
#ifndef DBUG_OFF
/*
@@ -1075,12 +1068,11 @@ public:
};
bool agg_item_collations(DTCollation &c, const char *name,
- Item **items, uint nitems, uint flags= 0);
+ Item **items, uint nitems, uint flags, int item_sep);
bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
- Item **items, uint nitems,
- uint flags= 0);
+ Item **items, uint nitems, uint flags);
bool agg_item_charsets(DTCollation &c, const char *name,
- Item **items, uint nitems, uint flags= 0);
+ Item **items, uint nitems, uint flags, int item_sep);
class Item_num: public Item
@@ -1142,6 +1134,28 @@ public:
bool any_privileges);
};
+
+class Item_ident_for_show :public Item
+{
+public:
+ Field *field;
+ const char *db_name;
+ const char *table_name;
+
+ Item_ident_for_show(Field *par_field, const char *db_arg,
+ const char *table_name_arg)
+ :field(par_field), db_name(db_arg), table_name(table_name_arg)
+ {}
+
+ enum Type type() const { return FIELD_ITEM; }
+ double val_real() { return field->val_real(); }
+ longlong val_int() { return field->val_int(); }
+ String *val_str(String *str) { return field->val_str(str); }
+ my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); }
+ void make_field(Send_field *tmp_field);
+};
+
+
class Item_equal;
class COND_EQUAL;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 80cf756d852..98453899375 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -394,7 +394,7 @@ void Item_bool_func2::fix_length_and_dec()
DTCollation coll;
if (args[0]->result_type() == STRING_RESULT &&
args[1]->result_type() == STRING_RESULT &&
- agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV))
+ agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV, 1))
return;
@@ -1211,7 +1211,7 @@ void Item_func_between::fix_length_and_dec()
agg_cmp_type(thd, &cmp_type, args, 3);
if (cmp_type == STRING_RESULT)
- agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV);
+ agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1);
}
@@ -1331,7 +1331,7 @@ Item_func_ifnull::fix_length_and_dec()
switch (hybrid_type) {
case STRING_RESULT:
- agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
break;
case DECIMAL_RESULT:
case REAL_RESULT:
@@ -1503,7 +1503,7 @@ Item_func_if::fix_length_and_dec()
agg_result_type(&cached_result_type, args+1, 2);
if (cached_result_type == STRING_RESULT)
{
- if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV))
+ if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV, 1))
return;
}
else
@@ -1584,7 +1584,7 @@ Item_func_nullif::fix_length_and_dec()
unsigned_flag= args[0]->unsigned_flag;
cached_result_type= args[0]->result_type();
if (cached_result_type == STRING_RESULT &&
- agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV))
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1))
return;
}
}
@@ -1876,7 +1876,7 @@ void Item_func_case::fix_length_and_dec()
agg_result_type(&cached_result_type, agg, nagg);
if ((cached_result_type == STRING_RESULT) &&
- agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV))
+ agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV, 1))
return;
@@ -1892,7 +1892,7 @@ void Item_func_case::fix_length_and_dec()
nagg++;
agg_cmp_type(thd, &cmp_type, agg, nagg);
if ((cmp_type == STRING_RESULT) &&
- agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV))
+ agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1))
return;
}
@@ -2022,7 +2022,7 @@ void Item_func_coalesce::fix_length_and_dec()
case STRING_RESULT:
count_only_length();
decimals= NOT_FIXED_DEC;
- agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV);
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1);
break;
case DECIMAL_RESULT:
count_decimal_length();
@@ -2486,7 +2486,7 @@ void Item_func_in::fix_length_and_dec()
agg_cmp_type(thd, &cmp_type, args, arg_count);
if (cmp_type == STRING_RESULT &&
- agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV))
+ agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1))
return;
for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
@@ -3219,7 +3219,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref)
max_length= 1;
decimals= 0;
- if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV))
+ if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1))
return TRUE;
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
@@ -3303,7 +3303,7 @@ longlong Item_func_regex::val_int()
}
}
null_value=0;
- return my_regexec(&preg,res->c_ptr(),0,(my_regmatch_t*) 0,0) ? 0 : 1;
+ return my_regexec(&preg,res->c_ptr_safe(),0,(my_regmatch_t*) 0,0) ? 0 : 1;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index bfcb2101d60..7d57757432e 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -296,12 +296,6 @@ Item *create_func_pow(Item* a, Item *b)
return new Item_func_pow(a,b);
}
-Item *create_func_current_user()
-{
- current_thd->lex->safe_to_cache_query= 0;
- return new Item_func_user(TRUE);
-}
-
Item *create_func_radians(Item *a)
{
return new Item_func_units((char*) "radians",a,M_PI/180,0.0);
diff --git a/sql/item_create.h b/sql/item_create.h
index 35db9be3c89..cf61f90f91d 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -73,7 +73,6 @@ Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
-Item *create_func_current_user(void);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 57d3b0ac5f3..a4c786c2351 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2038,7 +2038,7 @@ void Item_func_min_max::fix_length_and_dec()
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
}
if (cmp_type == STRING_RESULT)
- agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
unsigned_flag);
@@ -2227,7 +2227,7 @@ longlong Item_func_coercibility::val_int()
void Item_func_locate::fix_length_and_dec()
{
maybe_null=0; max_length=11;
- agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV);
+ agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
}
@@ -2344,7 +2344,7 @@ void Item_func_field::fix_length_and_dec()
for (uint i=1; i < arg_count ; i++)
cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
if (cmp_type == STRING_RESULT)
- agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV);
+ agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1);
}
@@ -2411,7 +2411,7 @@ void Item_func_find_in_set::fix_length_and_dec()
}
}
}
- agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV);
+ agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
}
static const char separator=',';
@@ -2510,8 +2510,7 @@ void udf_handler::cleanup()
{
if (u_d->func_deinit != NULL)
{
- void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
- u_d->func_deinit;
+ Udf_func_deinit deinit= u_d->func_deinit;
(*deinit)(&initid);
}
free_udf(u_d);
@@ -2656,9 +2655,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
}
}
thd->net.last_error[0]=0;
- my_bool (*init)(UDF_INIT *, UDF_ARGS *, char *)=
- (my_bool (*)(UDF_INIT *, UDF_ARGS *, char *))
- u_d->func_init;
+ Udf_func_init init= u_d->func_init;
if ((error=(uchar) init(&initid, &f_args, thd->net.last_error)))
{
my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
@@ -4401,7 +4398,8 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
return 1;
}
table->fulltext_searched=1;
- return agg_arg_collations_for_comparison(cmp_collation, args+1, arg_count-1);
+ return agg_arg_collations_for_comparison(cmp_collation,
+ args+1, arg_count-1, 0);
}
bool Item_func_match::fix_index()
diff --git a/sql/item_func.h b/sql/item_func.h
index f70becb79fc..304aeb8aef1 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -166,21 +166,21 @@ public:
my_decimal *val_decimal(my_decimal *);
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems,
- uint flags= 0)
+ uint flags)
{
- return agg_item_collations(c, func_name(), items, nitems, flags);
+ return agg_item_collations(c, func_name(), items, nitems, flags, 1);
}
bool agg_arg_collations_for_comparison(DTCollation &c,
Item **items, uint nitems,
- uint flags= 0)
+ uint flags)
{
return agg_item_collations_for_comparison(c, func_name(),
items, nitems, flags);
}
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
- uint flags= 0)
+ uint flags, int item_sep)
{
- return agg_item_charsets(c, func_name(), items, nitems, flags);
+ return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
}
bool walk(Item_processor processor, byte *arg);
Item *transform(Item_transformer transformer, byte *arg);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7a35dedc08a..8bc1bfaf7dd 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -405,7 +405,7 @@ void Item_func_concat::fix_length_and_dec()
{
ulonglong max_result_length= 0;
- if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV))
+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
return;
for (uint i=0 ; i < arg_count ; i++)
@@ -727,7 +727,7 @@ void Item_func_concat_ws::fix_length_and_dec()
{
ulonglong max_result_length;
- if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV))
+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
return;
/*
@@ -937,7 +937,7 @@ void Item_func_replace::fix_length_and_dec()
}
max_length= (ulong) max_result_length;
- if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV))
+ if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1))
return;
}
@@ -982,15 +982,11 @@ null:
void Item_func_insert::fix_length_and_dec()
{
- Item *cargs[2];
ulonglong max_result_length;
- cargs[0]= args[0];
- cargs[1]= args[3];
- if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV))
+ // Handle character set for args[0] and args[3].
+ if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 3))
return;
- args[0]= cargs[0];
- args[3]= cargs[1];
max_result_length= ((ulonglong) args[0]->max_length+
(ulonglong) args[3]->max_length);
if (max_result_length >= MAX_BLOB_WIDTH)
@@ -1161,7 +1157,7 @@ void Item_func_substr_index::fix_length_and_dec()
{
max_length= args[0]->max_length;
- if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV))
+ if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV, 1))
return;
}
@@ -1497,13 +1493,10 @@ void Item_func_trim::fix_length_and_dec()
}
else
{
- Item *cargs[2];
- cargs[0]= args[1];
- cargs[1]= args[0];
- if (agg_arg_charsets(collation, cargs, 2, MY_COLL_CMP_CONV))
+ // Handle character set for args[1] and args[0].
+ // Note that we pass args[1] as the first item, and args[0] as the second.
+ if (agg_arg_charsets(collation, &args[1], 2, MY_COLL_CMP_CONV, -1))
return;
- args[0]= cargs[1];
- args[1]= cargs[0];
}
}
@@ -1677,42 +1670,51 @@ String *Item_func_database::val_str(String *str)
return str;
}
-// TODO: make USER() replicate properly (currently it is replicated to "")
-String *Item_func_user::val_str(String *str)
+/*
+ TODO: make USER() replicate properly (currently it is replicated to "")
+*/
+bool Item_func_user::init(const char *user, const char *host)
{
DBUG_ASSERT(fixed == 1);
- THD *thd=current_thd;
- CHARSET_INFO *cs= system_charset_info;
- const char *host, *user;
- uint res_length;
- if (is_current)
- {
- user= thd->security_ctx->priv_user;
- host= thd->security_ctx->priv_host;
- }
- else
+ // For system threads (e.g. replication SQL thread) user may be empty
+ if (user)
{
- user= thd->main_security_ctx.user;
- host= thd->main_security_ctx.host_or_ip;
- }
+ CHARSET_INFO *cs= str_value.charset();
+ uint res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
- // For system threads (e.g. replication SQL thread) user may be empty
- if (!user)
- return &my_empty_string;
- res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
+ if (str_value.alloc(res_length))
+ {
+ null_value=1;
+ return TRUE;
+ }
- if (str->alloc(res_length))
- {
- null_value=1;
- return 0;
+ res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length,
+ "%s@%s", user, host);
+ str_value.length(res_length);
+ str_value.mark_as_const();
}
- res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",
- user, host);
- str->length(res_length);
- str->set_charset(cs);
- return str;
+ return FALSE;
+}
+
+
+bool Item_func_user::fix_fields(THD *thd, Item **ref)
+{
+ return (Item_func_sysconst::fix_fields(thd, ref) ||
+ init(thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip));
+}
+
+
+bool Item_func_current_user::fix_fields(THD *thd, Item **ref)
+{
+ if (Item_func_sysconst::fix_fields(thd, ref))
+ return TRUE;
+
+ Security_context *ctx= (context->security_ctx
+ ? context->security_ctx : thd->security_ctx);
+ return init(ctx->priv_user, ctx->priv_host);
}
@@ -1887,7 +1889,7 @@ void Item_func_elt::fix_length_and_dec()
max_length=0;
decimals=0;
- if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV))
+ if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV, 1))
return;
for (uint i= 1 ; i < arg_count ; i++)
@@ -1954,7 +1956,7 @@ void Item_func_make_set::fix_length_and_dec()
{
max_length=arg_count-1;
- if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV))
+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
return;
for (uint i=0 ; i < arg_count ; i++)
@@ -2162,14 +2164,9 @@ err:
void Item_func_rpad::fix_length_and_dec()
{
- Item *cargs[2];
-
- cargs[0]= args[0];
- cargs[1]= args[2];
- if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV))
+ // Handle character set for args[0] and args[2].
+ if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
return;
- args[0]= cargs[0];
- args[2]= cargs[1];
if (args[1]->const_item())
{
ulonglong length= ((ulonglong) args[1]->val_int() *
@@ -2249,13 +2246,9 @@ String *Item_func_rpad::val_str(String *str)
void Item_func_lpad::fix_length_and_dec()
{
- Item *cargs[2];
- cargs[0]= args[0];
- cargs[1]= args[2];
- if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV))
+ // Handle character set for args[0] and args[2].
+ if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
return;
- args[0]= cargs[0];
- args[2]= cargs[1];
if (args[1]->const_item())
{
@@ -2712,8 +2705,8 @@ void Item_func_export_set::fix_length_and_dec()
uint sep_length=(arg_count > 3 ? args[3]->max_length : 1);
max_length=length*64+sep_length*63;
- if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1),
- MY_COLL_ALLOW_CONV)
+ if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1,
+ MY_COLL_ALLOW_CONV, 1))
return;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index af59b8d740b..a2204f22822 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -385,21 +385,40 @@ public:
class Item_func_user :public Item_func_sysconst
{
- bool is_current;
+protected:
+ bool init (const char *user, const char *host);
public:
- Item_func_user(bool is_current_arg)
- :Item_func_sysconst(), is_current(is_current_arg) {}
- String *val_str(String *);
+ Item_func_user()
+ {
+ str_value.set("", 0, system_charset_info);
+ }
+ String *val_str(String *)
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (null_value ? 0 : &str_value);
+ }
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec()
{
max_length= ((USERNAME_LENGTH + HOSTNAME_LENGTH + 1) *
system_charset_info->mbmaxlen);
}
- const char *func_name() const
- { return is_current ? "current_user" : "user"; }
- const char *fully_qualified_func_name() const
- { return is_current ? "current_user()" : "user()"; }
+ const char *func_name() const { return "user"; }
+ const char *fully_qualified_func_name() const { return "user()"; }
+};
+
+
+class Item_func_current_user :public Item_func_user
+{
+ Name_resolution_context *context;
+
+public:
+ Item_func_current_user(Name_resolution_context *context_arg)
+ : context(context_arg) {}
+ bool fix_fields(THD *thd, Item **ref);
+ const char *func_name() const { return "current_user"; }
+ const char *fully_qualified_func_name() const { return "current_user()"; }
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 962454e237e..4d70debb966 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -2102,7 +2102,6 @@ Item_sum_hybrid::min_max_update_str_field()
if (!args[0]->null_value)
{
- res_str->strip_sp();
result_field->val_str(&tmp_value);
if (result_field->is_null() ||
@@ -3229,7 +3228,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
args,
/* skip charset aggregation for order columns */
arg_count - arg_count_order,
- MY_COLL_ALLOW_CONV))
+ MY_COLL_ALLOW_CONV, 1))
return 1;
result.set_charset(collation.collation);
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index f741984e05f..9e1962835c8 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -30,25 +30,6 @@
/* Day number for Dec 31st, 9999 */
#define MAX_DAY_NUMBER 3652424L
-static const char *month_names[]=
-{
- "January", "February", "March", "April", "May", "June", "July", "August",
- "September", "October", "November", "December", NullS
-};
-
-TYPELIB month_names_typelib=
-{ array_elements(month_names)-1,"", month_names, NULL };
-
-static const char *day_names[]=
-{
- "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday" ,"Sunday", NullS
-};
-
-TYPELIB day_names_typelib=
-{ array_elements(day_names)-1,"", day_names, NULL};
-
-
/*
OPTIMIZATION TODO:
- Replace the switch with a function that should be called for each
@@ -223,8 +204,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
val= tmp;
break;
case 'M':
+ if ((l_time->month= check_word(my_locale_en_US.month_names,
+ val, val_end, &val)) <= 0)
+ goto err;
+ break;
case 'b':
- if ((l_time->month= check_word(&month_names_typelib,
+ if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
val, val_end, &val)) <= 0)
goto err;
break;
@@ -299,8 +284,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
/* Exotic things */
case 'W':
+ if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
+ goto err;
+ break;
case 'a':
- if ((weekday= check_word(&day_names_typelib, val, val_end, &val)) <= 0)
+ if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
goto err;
break;
case 'w':
@@ -502,9 +490,16 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
uint weekday;
ulong length;
const char *ptr, *end;
+ MY_LOCALE *locale;
+ THD *thd= current_thd;
+ char buf[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buf, sizeof(buf), thd->variables.character_set_results);
+ uint errors= 0;
+ tmp.length(0);
str->length(0);
str->set_charset(&my_charset_bin);
+ locale = thd->variables.lc_time_names;
if (l_time->neg)
str->append('-');
@@ -520,26 +515,38 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
case 'M':
if (!l_time->month)
return 1;
- str->append(month_names[l_time->month-1]);
+ tmp.copy(locale->month_names->type_names[l_time->month-1],
+ strlen(locale->month_names->type_names[l_time->month-1]),
+ system_charset_info, tmp.charset(), &errors);
+ str->append(tmp.ptr(), tmp.length());
break;
case 'b':
if (!l_time->month)
return 1;
- str->append(month_names[l_time->month-1],3);
+ tmp.copy(locale->ab_month_names->type_names[l_time->month-1],
+ strlen(locale->ab_month_names->type_names[l_time->month-1]),
+ system_charset_info, tmp.charset(), &errors);
+ str->append(tmp.ptr(), tmp.length());
break;
case 'W':
if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),0);
- str->append(day_names[weekday]);
+ tmp.copy(locale->day_names->type_names[weekday],
+ strlen(locale->day_names->type_names[weekday]),
+ system_charset_info, tmp.charset(), &errors);
+ str->append(tmp.ptr(), tmp.length());
break;
case 'a':
if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),0);
- str->append(day_names[weekday],3);
+ tmp.copy(locale->ab_day_names->type_names[weekday],
+ strlen(locale->ab_day_names->type_names[weekday]),
+ system_charset_info, tmp.charset(), &errors);
+ str->append(tmp.ptr(), tmp.length());
break;
case 'D':
if (type == MYSQL_TIMESTAMP_TIME)
@@ -919,6 +926,7 @@ String* Item_func_monthname::val_str(String* str)
DBUG_ASSERT(fixed == 1);
const char *month_name;
uint month= (uint) val_int();
+ THD *thd= current_thd;
if (null_value || !month)
{
@@ -926,7 +934,7 @@ String* Item_func_monthname::val_str(String* str)
return (String*) 0;
}
null_value=0;
- month_name= month_names[month-1];
+ month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
str->set(month_name, strlen(month_name), system_charset_info);
return str;
}
@@ -1051,11 +1059,12 @@ String* Item_func_dayname::val_str(String* str)
DBUG_ASSERT(fixed == 1);
uint weekday=(uint) val_int(); // Always Item_func_daynr()
const char *name;
+ THD *thd= current_thd;
if (null_value)
return (String*) 0;
- name= day_names[weekday];
+ name= thd->variables.lc_time_names->day_names->type_names[weekday];
str->set(name, strlen(name), system_charset_info);
return str;
}
@@ -1676,7 +1685,7 @@ uint Item_func_date_format::format_length(const String *format)
switch(*++ptr) {
case 'M': /* month, textual */
case 'W': /* day (of the week), textual */
- size += 9;
+ size += 64; /* large for UTF8 locale data */
break;
case 'D': /* day (of the month), numeric plus english suffix */
case 'Y': /* year, numeric, 4 digits */
@@ -1686,6 +1695,8 @@ uint Item_func_date_format::format_length(const String *format)
break;
case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
case 'b': /* locale's abbreviated month name (Jan.Dec) */
+ size += 32; /* large for UTF8 locale data */
+ break;
case 'j': /* day of year (001..366) */
size += 3;
break;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 3c58f2cbc6b..c9ae743addd 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -95,6 +95,23 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
+
+typedef struct my_locale_st
+{
+ const char *name;
+ const char *description;
+ const bool is_ascii;
+ TYPELIB *month_names;
+ TYPELIB *ab_month_names;
+ TYPELIB *day_names;
+ TYPELIB *ab_day_names;
+} MY_LOCALE;
+
+extern MY_LOCALE my_locale_en_US;
+extern MY_LOCALE *my_locales[];
+
+MY_LOCALE *my_locale_by_name(const char *name);
+
/***************************************************************************
Configuration parameters
****************************************************************************/
@@ -537,6 +554,7 @@ int append_query_string(CHARSET_INFO *csinfo,
void get_default_definer(THD *thd, LEX_USER *definer);
LEX_USER *create_default_definer(THD *thd);
LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
+LEX_USER *get_current_user(THD *thd, LEX_USER *user);
enum enum_mysql_completiontype {
ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
@@ -566,6 +584,7 @@ struct Query_cache_query_flags
ulong sql_mode;
ulong max_sort_length;
ulong group_concat_max_len;
+ MY_LOCALE *lc_time_names;
};
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
#include "sql_cache.h"
@@ -726,9 +745,7 @@ bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
TABLE_LIST *table_list,
List<create_field> &fields,
List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates,
- bool ignore,
+ uint order_num, ORDER *order, bool ignore,
ALTER_INFO *alter_info, bool do_send_ok);
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
@@ -764,6 +781,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
bool ignore);
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
TABLE_LIST *table_list);
+void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table,
+ enum_duplicates duplic);
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SQL_LIST *order, ha_rows rows, ulonglong options,
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index cb0f35a425e..3b77d1b419e 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -59,18 +59,119 @@ static int sel_cmp(Field *f,char *a,char *b,uint8 a_flag,uint8 b_flag);
static char is_null_string[2]= {1,0};
+
+/*
+ A construction block of the SEL_ARG-graph.
+
+ The following description only covers graphs of SEL_ARG objects with
+ sel_arg->type==KEY_RANGE:
+
+ One SEL_ARG object represents an "elementary interval" in form
+
+ min_value <=? table.keypartX <=? max_value
+
+ The interval is a non-empty interval of any kind: with[out] minimum/maximum
+ bound, [half]open/closed, single-point interval, etc.
+
+ 1. SEL_ARG GRAPH STRUCTURE
+
+ SEL_ARG objects are linked together in a graph. The meaning of the graph
+ is better demostrated by an example:
+
+ tree->keys[i]
+ |
+ | $ $
+ | part=1 $ part=2 $ part=3
+ | $ $
+ | +-------+ $ +-------+ $ +--------+
+ | | kp1<1 |--$-->| kp2=5 |--$-->| kp3=10 |
+ | +-------+ $ +-------+ $ +--------+
+ | | $ $ |
+ | | $ $ +--------+
+ | | $ $ | kp3=12 |
+ | | $ $ +--------+
+ | +-------+ $ $
+ \->| kp1=2 |--$--------------$-+
+ +-------+ $ $ | +--------+
+ | $ $ ==>| kp3=11 |
+ +-------+ $ $ | +--------+
+ | kp1=3 |--$--------------$-+ |
+ +-------+ $ $ +--------+
+ | $ $ | kp3=14 |
+ ... $ $ +--------+
+
+ The entire graph is partitioned into "interval lists".
+
+ An interval list is a sequence of ordered disjoint intervals over the same
+ key part. SEL_ARG are linked via "next" and "prev" pointers. Additionally,
+ all intervals in the list form an RB-tree, linked via left/right/parent
+ pointers. The RB-tree root SEL_ARG object will be further called "root of the
+ interval list".
+
+ In the example pic, there are 4 interval lists:
+ "kp<1 OR kp1=2 OR kp1=3", "kp2=5", "kp3=10 OR kp3=12", "kp3=11 OR kp3=13".
+ The vertical lines represent SEL_ARG::next/prev pointers.
+
+ In an interval list, each member X may have SEL_ARG::next_key_part pointer
+ pointing to the root of another interval list Y. The pointed interval list
+ must cover a key part with greater number (i.e. Y->part > X->part).
+
+ In the example pic, the next_key_part pointers are represented by
+ horisontal lines.
+
+ 2. SEL_ARG GRAPH SEMANTICS
+
+ It represents a condition in a special form (we don't have a name for it ATM)
+ The SEL_ARG::next/prev is "OR", and next_key_part is "AND".
+
+ For example, the picture represents the condition in form:
+ (kp1 < 1 AND kp2=5 AND (kp3=10 OR kp3=12)) OR
+ (kp1=2 AND (kp3=11 OR kp3=14)) OR
+ (kp1=3 AND (kp3=11 OR kp3=14))
+
+
+ 3. SEL_ARG GRAPH USE
+
+ Use get_mm_tree() to construct SEL_ARG graph from WHERE condition.
+ Then walk the SEL_ARG graph and get a list of dijsoint ordered key
+ intervals (i.e. intervals in form
+
+ (constA1, .., const1_K) < (keypart1,.., keypartK) < (constB1, .., constB_K)
+
+ Those intervals can be used to access the index. The uses are in:
+ - check_quick_select() - Walk the SEL_ARG graph and find an estimate of
+ how many table records are contained within all
+ intervals.
+ - get_quick_select() - Walk the SEL_ARG, materialize the key intervals,
+ and create QUICK_RANGE_SELECT object that will
+ read records within these intervals.
+*/
+
class SEL_ARG :public Sql_alloc
{
public:
uint8 min_flag,max_flag,maybe_flag;
uint8 part; // Which key part
uint8 maybe_null;
- uint16 elements; // Elements in tree
- ulong use_count; // use of this sub_tree
+ /*
+ Number of children of this element in the RB-tree, plus 1 for this
+ element itself.
+ */
+ uint16 elements;
+ /*
+ Valid only for elements which are RB-tree roots: Number of times this
+ RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by
+ SEL_TREE::keys[i] or by a temporary SEL_ARG* variable)
+ */
+ ulong use_count;
+
Field *field;
char *min_value,*max_value; // Pointer to range
- SEL_ARG *left,*right,*next,*prev,*parent,*next_key_part;
+ SEL_ARG *left,*right; /* R-B tree children */
+ SEL_ARG *next,*prev; /* Links for bi-directional interval list */
+ SEL_ARG *parent; /* R-B tree parent */
+ SEL_ARG *next_key_part;
enum leaf_color { BLACK,RED } color;
enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type;
@@ -80,8 +181,8 @@ public:
SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value,
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
SEL_ARG(enum Type type_arg)
- :elements(1),use_count(1),left(0),next_key_part(0),color(BLACK),
- type(type_arg),min_flag(0)
+ :min_flag(0),elements(1),use_count(1),left(0),next_key_part(0),
+ color(BLACK), type(type_arg)
{}
inline bool is_same(SEL_ARG *arg)
{
@@ -1278,6 +1379,7 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
}
increment_use_count(1);
tmp->color= color;
+ tmp->elements= this->elements;
return tmp;
}
@@ -4457,8 +4559,21 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
}
+/*
+ Produce a SEL_ARG graph that represents "key1 AND key2"
+
+ SYNOPSIS
+ key_and()
+ key1 First argument, root of its RB-tree
+ key2 Second argument, root of its RB-tree
+
+ RETURN
+ RB-tree root of the resulting SEL_ARG graph.
+ NULL if the result of AND operation is an empty interval {0}.
+*/
+
static SEL_ARG *
-key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
+key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
{
if (!key1)
return key2;
@@ -4521,6 +4636,7 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
if ((key1->min_flag | key2->min_flag) & GEOM_FLAG)
{
+ /* TODO: why not leave one of the trees? */
key1->free_tree();
key2->free_tree();
return 0; // Can't optimize this
@@ -5242,6 +5358,51 @@ int test_rb_tree(SEL_ARG *element,SEL_ARG *parent)
return -1; // Error, no more warnings
}
+
+/*
+ Count how many times SEL_ARG graph "root" refers to its part "key"
+
+ SYNOPSIS
+ count_key_part_usage()
+ root An RB-Root node in a SEL_ARG graph.
+ key Another RB-Root node in that SEL_ARG graph.
+
+ DESCRIPTION
+ The passed "root" node may refer to "key" node via root->next_key_part,
+ root->next->n
+
+ This function counts how many times the node "key" is referred (via
+ SEL_ARG::next_key_part) by
+ - intervals of RB-tree pointed by "root",
+ - intervals of RB-trees that are pointed by SEL_ARG::next_key_part from
+ intervals of RB-tree pointed by "root",
+ - and so on.
+
+ Here is an example (horizontal links represent next_key_part pointers,
+ vertical links - next/prev prev pointers):
+
+ +----+ $
+ |root|-----------------+
+ +----+ $ |
+ | $ |
+ | $ |
+ +----+ +---+ $ | +---+ Here the return value
+ | |- ... -| |---$-+--+->|key| will be 4.
+ +----+ +---+ $ | | +---+
+ | $ | |
+ ... $ | |
+ | $ | |
+ +----+ +---+ $ | |
+ | |---| |---------+ |
+ +----+ +---+ $ |
+ | | $ |
+ ... +---+ $ |
+ | |------------+
+ +---+ $
+ RETURN
+ Number of links to "key" from nodes reachable from "root".
+*/
+
static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key)
{
ulong count= 0;
@@ -5259,6 +5420,20 @@ static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key)
}
+/*
+ Check if SEL_ARG::use_count value is correct
+
+ SYNOPSIS
+ SEL_ARG::test_use_count()
+ root The root node of the SEL_ARG graph (an RB-tree root node that
+ has the least value of sel_arg->part in the entire graph, and
+ thus is the "origin" of the graph)
+
+ DESCRIPTION
+ Check if SEL_ARG::use_count value is correct. See the definition of
+ use_count for what is "correct".
+*/
+
void SEL_ARG::test_use_count(SEL_ARG *root)
{
uint e_count=0;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 1cb3878ac70..8e3fda0a164 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -58,6 +58,7 @@
#include <my_getopt.h>
#include <thr_alarm.h>
#include <myisam.h>
+
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
#endif
@@ -553,6 +554,9 @@ static sys_var_thd_ha_rows sys_select_limit("sql_select_limit",
static sys_var_timestamp sys_timestamp("timestamp");
static sys_var_last_insert_id sys_last_insert_id("last_insert_id");
static sys_var_last_insert_id sys_identity("identity");
+
+static sys_var_thd_lc_time_names sys_lc_time_names("lc_time_names");
+
static sys_var_insert_id sys_insert_id("insert_id");
static sys_var_readonly sys_error_count("error_count",
OPT_SESSION,
@@ -651,6 +655,7 @@ sys_var *sys_variables[]=
&sys_key_cache_division_limit,
&sys_key_cache_age_threshold,
&sys_last_insert_id,
+ &sys_lc_time_names,
&sys_license,
&sys_local_infile,
&sys_log_binlog,
@@ -921,6 +926,7 @@ struct show_var_st init_vars[]= {
{"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
{"large_page_size", (char*) &opt_large_page_size, SHOW_INT},
{"large_pages", (char*) &opt_large_pages, SHOW_MY_BOOL},
+ {sys_lc_time_names.name, (char*) &sys_lc_time_names, SHOW_SYS},
{sys_license.name, (char*) &sys_license, SHOW_SYS},
{sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS},
#ifdef HAVE_MLOCKALL
@@ -2764,6 +2770,40 @@ byte *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type,
return (byte*) &(max_user_connections);
}
+bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
+{
+ char *locale_str =var->value->str_value.c_ptr();
+ MY_LOCALE *locale_match= my_locale_by_name(locale_str);
+
+ if (locale_match == NULL)
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Unknown locale: '%s'", MYF(0), locale_str);
+ return 1;
+ }
+ var->save_result.locale_value= locale_match;
+ return 0;
+}
+
+
+bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var)
+{
+ thd->variables.lc_time_names= var->save_result.locale_value;
+ return 0;
+}
+
+
+byte *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ return (byte *)(thd->variables.lc_time_names->name);
+}
+
+
+void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
+{
+ thd->variables.lc_time_names = &my_locale_en_US;
+}
/*
Functions to update thd->options bits
diff --git a/sql/set_var.h b/sql/set_var.h
index b048428219d..11de6ceafe5 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -28,6 +28,8 @@
class sys_var;
class set_var;
typedef struct system_variables SV;
+typedef struct my_locale_st MY_LOCALE;
+
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib;
typedef int (*sys_check_func)(THD *, set_var *);
@@ -812,6 +814,25 @@ public:
bool update(THD *thd, set_var *var);
};
+
+class sys_var_thd_lc_time_names :public sys_var_thd
+{
+public:
+ sys_var_thd_lc_time_names(const char *name_arg):
+ sys_var_thd(name_arg)
+ {}
+ bool check(THD *thd, set_var *var);
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ bool check_update_type(Item_result type)
+ {
+ return type != STRING_RESULT; /* Only accept strings */
+ }
+ bool check_default(enum_var_type type) { return 0; }
+ bool update(THD *thd, set_var *var);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+ virtual void set_default(THD *thd, enum_var_type type);
+};
+
/****************************************************************************
Classes for parsing of the SET command
****************************************************************************/
@@ -844,6 +865,7 @@ public:
ulonglong ulonglong_value;
DATE_TIME_FORMAT *date_time_format;
Time_zone *time_zone;
+ MY_LOCALE *locale_value;
} save_result;
LEX_STRING base; /* for structs */
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 124d3566b19..f7dac349d8a 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2766,7 +2766,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
ulong column_priv= 0;
List_iterator <LEX_USER> str_list (user_list);
- LEX_USER *Str;
+ LEX_USER *Str, *tmp_Str;
TABLE_LIST tables[3];
bool create_new_users=0;
char *db_name, *table_name;
@@ -2891,10 +2891,15 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
thd->mem_root= &memex;
grant_version++;
- while ((Str = str_list++))
+ while ((tmp_Str = str_list++))
{
int error;
GRANT_TABLE *grant_table;
+ if (!(Str= get_current_user(thd, tmp_Str)))
+ {
+ result= TRUE;
+ continue;
+ }
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
@@ -3030,7 +3035,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
bool revoke_grant, bool no_error)
{
List_iterator <LEX_USER> str_list (user_list);
- LEX_USER *Str;
+ LEX_USER *Str, *tmp_Str;
TABLE_LIST tables[2];
bool create_new_users=0, result=0;
char *db_name, *table_name;
@@ -3098,10 +3103,15 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
DBUG_PRINT("info",("now time to iterate and add users"));
- while ((Str= str_list++))
+ while ((tmp_Str= str_list++))
{
int error;
GRANT_NAME *grant_name;
+ if (!(Str= get_current_user(thd, tmp_Str)))
+ {
+ result= TRUE;
+ continue;
+ }
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
@@ -3170,7 +3180,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
ulong rights, bool revoke_grant)
{
List_iterator <LEX_USER> str_list (list);
- LEX_USER *Str;
+ LEX_USER *Str, *tmp_Str;
char tmp_db[NAME_LEN+1];
bool create_new_users=0;
TABLE_LIST tables[2];
@@ -3229,8 +3239,13 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
grant_version++;
int result=0;
- while ((Str = str_list++))
+ while ((tmp_Str = str_list++))
{
+ if (!(Str= get_current_user(thd, tmp_Str)))
+ {
+ result= TRUE;
+ continue;
+ }
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
@@ -5187,7 +5202,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
int result;
String wrong_users;
ulong sql_mode;
- LEX_USER *user_name;
+ LEX_USER *user_name, *tmp_user_name;
List_iterator <LEX_USER> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_create_user");
@@ -5199,8 +5214,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
- while ((user_name= user_list++))
+ while ((tmp_user_name= user_list++))
{
+ if (!(user_name= get_current_user(thd, tmp_user_name)))
+ {
+ result= TRUE;
+ continue;
+ }
/*
Search all in-memory structures and grant tables
for a mention of the new user name.
@@ -5246,7 +5266,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
{
int result;
String wrong_users;
- LEX_USER *user_name;
+ LEX_USER *user_name, *tmp_user_name;
List_iterator <LEX_USER> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_drop_user");
@@ -5258,8 +5278,14 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
- while ((user_name= user_list++))
+ while ((tmp_user_name= user_list++))
{
+ user_name= get_current_user(thd, tmp_user_name);
+ if (!(user_name= get_current_user(thd, tmp_user_name)))
+ {
+ result= TRUE;
+ continue;
+ }
if (handle_grant_data(tables, 1, user_name, NULL) <= 0)
{
append_user(&wrong_users, user_name);
@@ -5296,8 +5322,8 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
{
int result;
String wrong_users;
- LEX_USER *user_from;
- LEX_USER *user_to;
+ LEX_USER *user_from, *tmp_user_from;
+ LEX_USER *user_to, *tmp_user_to;
List_iterator <LEX_USER> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_rename_user");
@@ -5309,9 +5335,19 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
- while ((user_from= user_list++))
+ while ((tmp_user_from= user_list++))
{
- user_to= user_list++;
+ if (!(user_from= get_current_user(thd, tmp_user_from)))
+ {
+ result= TRUE;
+ continue;
+ }
+ tmp_user_to= user_list++;
+ if (!(user_to= get_current_user(thd, tmp_user_to)))
+ {
+ result= TRUE;
+ continue;
+ }
DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */
/*
@@ -5366,10 +5402,15 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
- LEX_USER *lex_user;
+ LEX_USER *lex_user, *tmp_lex_user;
List_iterator <LEX_USER> user_list(list);
- while ((lex_user=user_list++))
+ while ((tmp_lex_user= user_list++))
{
+ if (!(lex_user= get_current_user(thd, tmp_lex_user)))
+ {
+ result= -1;
+ continue;
+ }
if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE))
{
sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 5904e13d710..5383bb52aaa 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -624,8 +624,10 @@ void close_temporary_tables(THD *thd)
if (!mysql_bin_log.is_open())
{
- for (table= thd->temporary_tables; table; table= table->next)
+ TABLE *next;
+ for (table= thd->temporary_tables; table; table= next)
{
+ next= table->next;
close_temporary(table, 1);
}
thd->temporary_tables= 0;
@@ -648,7 +650,6 @@ void close_temporary_tables(THD *thd)
insertion sort of temp tables by pseudo_thread_id to build ordered list
of sublists of equal pseudo_thread_id
*/
-
for (prev_table= thd->temporary_tables, table= prev_table->next;
table;
prev_table= table, table= table->next)
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 31201474c05..f8f7bde3a62 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -814,6 +814,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.time_zone= thd->variables.time_zone;
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
+ flags.lc_time_names= thd->variables.lc_time_names;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
@@ -1048,6 +1049,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
+ flags.lc_time_names= thd->variables.lc_time_names;
DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 06082a57964..5c8bd797e7c 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -306,6 +306,7 @@ void THD::init(void)
total_warn_count= 0;
update_charset();
bzero((char *) &status_var, sizeof(status_var));
+ variables.lc_time_names = &my_locale_en_US;
}
@@ -930,7 +931,7 @@ bool select_send::send_data(List<Item> &items)
Protocol *protocol= thd->protocol;
char buff[MAX_FIELD_WIDTH];
String buffer(buff, sizeof(buff), &my_charset_bin);
- DBUG_ENTER("send_data");
+ DBUG_ENTER("select_send::send_data");
protocol->prepare_for_resend();
Item *item;
@@ -1140,7 +1141,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
bool select_export::send_data(List<Item> &items)
{
- DBUG_ENTER("send_data");
+ DBUG_ENTER("select_export::send_data");
char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
bool space_inited=0;
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
@@ -1297,7 +1298,7 @@ bool select_dump::send_data(List<Item> &items)
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
tmp.length(0);
Item *item;
- DBUG_ENTER("send_data");
+ DBUG_ENTER("select_dump::send_data");
if (unit->offset_limit_cnt)
{ // using limit offset,count
@@ -1946,6 +1947,7 @@ void Security_context::init()
{
host= user= priv_user= ip= 0;
host_or_ip= "connecting host";
+ priv_host[0]= '\0';
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access= NO_ACCESS;
#endif
diff --git a/sql/sql_class.h b/sql/sql_class.h
index eb075dd54bb..45dc90f25b3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -575,6 +575,9 @@ struct system_variables
CHARSET_INFO *collation_database;
CHARSET_INFO *collation_connection;
+ /* Locale Support */
+ MY_LOCALE *lc_time_names;
+
Time_zone *time_zone;
/* DATE, DATETIME and TIME formats */
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index af20b770c56..381d1a71e31 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -194,6 +194,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
deleted=0L;
init_ftfuncs(thd, select_lex, 1);
thd->proc_info="updating";
+
+ if (table->triggers)
+ table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+
while (!(error=info.read_record(&info)) && !thd->killed &&
!thd->net.report_error)
{
@@ -387,7 +391,7 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
bool mysql_multi_delete_prepare(THD *thd)
{
LEX *lex= thd->lex;
- TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxilliary_table_list.first;
+ TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first;
TABLE_LIST *target_tbl;
DBUG_ENTER("mysql_multi_delete_prepare");
@@ -507,6 +511,8 @@ multi_delete::initialize_tables(JOIN *join)
transactional_tables= 1;
else
normal_tables= 1;
+ if (tbl->triggers)
+ tbl->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
}
else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
walk == delete_tables)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ba0d2d00f2c..eaa7d3a72db 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -17,6 +17,44 @@
/* Insert of records */
+/*
+ INSERT DELAYED
+
+ Insert delayed is distinguished from a normal insert by lock_type ==
+ TL_WRITE_DELAYED instead of TL_WRITE. It first tries to open a
+ "delayed" table (delayed_get_table()), but falls back to
+ open_and_lock_tables() on error and proceeds as normal insert then.
+
+ Opening a "delayed" table means to find a delayed insert thread that
+ has the table open already. If this fails, a new thread is created and
+ waited for to open and lock the table.
+
+ If accessing the thread succeeded, in
+ delayed_insert::get_local_table() the table of the thread is copied
+ for local use. A copy is required because the normal insert logic
+ works on a target table, but the other threads table object must not
+ be used. The insert logic uses the record buffer to create a record.
+ And the delayed insert thread uses the record buffer to pass the
+ record to the table handler. So there must be different objects. Also
+ the copied table is not included in the lock, so that the statement
+ can proceed even if the real table cannot be accessed at this moment.
+
+ Copying a table object is not a trivial operation. Besides the TABLE
+ object there are the field pointer array, the field objects and the
+ record buffer. After copying the field objects, their pointers into
+ the record must be "moved" to point to the new record buffer.
+
+ After this setup the normal insert logic is used. Only that for
+ delayed inserts write_delayed() is called instead of write_record().
+ It inserts the rows into a queue and signals the delayed insert thread
+ instead of writing directly to the table.
+
+ The delayed insert thread awakes from the signal. It locks the table,
+ inserts the rows from the queue, unlocks the table, and waits for the
+ next signal. It does normally live until a FLUSH TABLES or SHUTDOWN.
+
+*/
+
#include "mysql_priv.h"
#include "sp_head.h"
#include "sql_trigger.h"
@@ -241,6 +279,33 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
}
+/*
+ Mark fields used by triggers for INSERT-like statement.
+
+ SYNOPSIS
+ mark_fields_used_by_triggers_for_insert_stmt()
+ thd The current thread
+ table Table to which insert will happen
+ duplic Type of duplicate handling for insert which will happen
+
+ NOTE
+ For REPLACE there is no sense in marking particular fields
+ used by ON DELETE trigger as to execute it properly we have
+ to retrieve and store values for all table columns anyway.
+*/
+
+void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table,
+ enum_duplicates duplic)
+{
+ if (table->triggers)
+ {
+ table->triggers->mark_fields_used(thd, TRG_EVENT_INSERT);
+ if (duplic == DUP_UPDATE)
+ table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+ }
+}
+
+
bool mysql_insert(THD *thd,TABLE_LIST *table_list,
List<Item> &fields,
List<List_item> &values_list,
@@ -400,6 +465,17 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->proc_info="update";
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (duplic == DUP_REPLACE)
+ {
+ if (!table->triggers || !table->triggers->has_delete_triggers())
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+ /*
+ REPLACE should change values of all columns so we should mark
+ all columns as columns to be set. As nice side effect we will
+ retrieve columns which values are needed for ON DELETE triggers.
+ */
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ }
/*
let's *try* to start bulk inserts. It won't necessary
start them as values_list.elements should be greater than
@@ -428,6 +504,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
error= 1;
}
+ mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+
if (table_list->prepare_where(thd, 0, TRUE) ||
table_list->prepare_check_option(thd))
error= 1;
@@ -598,6 +676,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->next_insert_id=0; // Reset this if wrongly used
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ if (duplic == DUP_REPLACE &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
/* Reset value of LAST_INSERT_ID if no rows where inserted */
if (!info.copied && thd->insert_id_used)
@@ -954,7 +1035,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
uint key_nr;
if (error != HA_WRITE_SKIP)
goto err;
- table->file->restore_auto_increment();
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
{
error=HA_WRITE_SKIP; /* Database can't find key */
@@ -1027,20 +1107,20 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (res == VIEW_CHECK_ERROR)
goto before_trg_err;
- if (thd->clear_next_insert_id)
- {
- /* Reset auto-increment cacheing if we do an update */
- thd->clear_next_insert_id= 0;
- thd->next_insert_id= 0;
- }
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore)
+ {
+ table->file->restore_auto_increment();
goto ok_or_after_trg_err;
+ }
goto err;
}
info->updated++;
+ if (table->next_number_field)
+ table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int());
+
trg_error= (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
TRG_ACTION_AFTER, TRUE));
@@ -1069,12 +1149,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
(!table->triggers || !table->triggers->has_delete_triggers()))
{
- if (thd->clear_next_insert_id)
- {
- /* Reset auto-increment cacheing if we do an update */
- thd->clear_next_insert_id= 0;
- thd->next_insert_id= 0;
- }
if ((error=table->file->update_row(table->record[1],
table->record[0])))
goto err;
@@ -1138,6 +1212,7 @@ err:
table->file->print_error(error,MYF(0));
before_trg_err:
+ table->file->restore_auto_increment();
if (key)
my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH);
DBUG_RETURN(1);
@@ -1441,6 +1516,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field;
TABLE *copy;
+ DBUG_ENTER("delayed_insert::get_local_table");
/* First request insert thread to get a lock */
status=1;
@@ -1464,31 +1540,47 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
}
}
+ /*
+ Allocate memory for the TABLE object, the field pointers array, and
+ one record buffer of reclength size. Normally a table has three
+ record buffers of rec_buff_length size, which includes alignment
+ bytes. Since the table copy is used for creating one record only,
+ the other record buffers and alignment are unnecessary.
+ */
client_thd->proc_info="allocating local table";
copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
(table->s->fields+1)*sizeof(Field**)+
table->s->reclength);
if (!copy)
goto error;
+
+ /* Copy the TABLE object. */
*copy= *table;
copy->s= &copy->share_not_to_be_used;
// No name hashing
bzero((char*) &copy->s->name_hash,sizeof(copy->s->name_hash));
/* We don't need to change the file handler here */
- field=copy->field=(Field**) (copy+1);
- copy->record[0]=(byte*) (field+table->s->fields+1);
- memcpy((char*) copy->record[0],(char*) table->record[0],table->s->reclength);
-
- /* Make a copy of all fields */
+ /* Assign the pointers for the field pointers array and the record. */
+ field= copy->field= (Field**) (copy + 1);
+ copy->record[0]= (byte*) (field + table->s->fields + 1);
+ memcpy((char*) copy->record[0], (char*) table->record[0],
+ table->s->reclength);
- adjust_ptrs=PTR_BYTE_DIFF(copy->record[0],table->record[0]);
+ /*
+ Make a copy of all fields.
+ The copied fields need to point into the copied record. This is done
+ by copying the field objects with their old pointer values and then
+ "move" the pointers by the distance between the original and copied
+ records. That way we preserve the relative positions in the records.
+ */
+ adjust_ptrs= PTR_BYTE_DIFF(copy->record[0], table->record[0]);
- found_next_number_field=table->found_next_number_field;
- for (org_field=table->field ; *org_field ; org_field++,field++)
+ found_next_number_field= table->found_next_number_field;
+ for (org_field= table->field; *org_field; org_field++, field++)
{
- if (!(*field= (*org_field)->new_field(client_thd->mem_root,copy)))
- return 0;
+ if (!(*field= (*org_field)->new_field(client_thd->mem_root, copy, 1)))
+ DBUG_RETURN(0);
(*field)->orig_table= copy; // Remove connection
(*field)->move_field(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
@@ -1515,14 +1607,14 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
/* Adjust lock_count. This table object is not part of a lock. */
copy->lock_count= 0;
- return copy;
+ DBUG_RETURN(copy);
/* Got fatal error */
error:
tables_in_use--;
status=1;
pthread_cond_signal(&cond); // Inform thread about abort
- return 0;
+ DBUG_RETURN(0);
}
@@ -1879,7 +1971,8 @@ bool delayed_insert::handle_inserts(void)
{
int error;
ulong max_rows;
- bool using_ignore=0, using_bin_log=mysql_bin_log.is_open();
+ bool using_ignore= 0, using_opt_replace= 0;
+ bool using_bin_log= mysql_bin_log.is_open();
delayed_row *row;
DBUG_ENTER("handle_inserts");
@@ -1941,6 +2034,13 @@ bool delayed_insert::handle_inserts(void)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
using_ignore=1;
}
+ if (info.handle_duplicates == DUP_REPLACE &&
+ (!table->triggers ||
+ !table->triggers->has_delete_triggers()))
+ {
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+ using_opt_replace= 1;
+ }
thd.clear_error(); // reset error for binlog
if (write_record(&thd, table, &info))
{
@@ -1953,6 +2053,11 @@ bool delayed_insert::handle_inserts(void)
using_ignore=0;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
}
+ if (using_opt_replace)
+ {
+ using_opt_replace= 0;
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
+ }
if (row->query && row->log_query && using_bin_log)
{
Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE);
@@ -2198,6 +2303,12 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (info.handle_duplicates == DUP_REPLACE)
+ {
+ if (!table->triggers || !table->triggers->has_delete_triggers())
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ }
thd->no_trans_update= 0;
thd->abort_on_warning= (!info.ignore &&
(thd->variables.sql_mode &
@@ -2207,6 +2318,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
check_that_all_fields_are_given_values(thd, table, table_list)) ||
table_list->prepare_where(thd, 0, TRUE) ||
table_list->prepare_check_option(thd));
+
+ if (!res)
+ mark_fields_used_by_triggers_for_insert_stmt(thd, table,
+ info.handle_duplicates);
DBUG_RETURN(res);
}
@@ -2372,6 +2487,7 @@ bool select_insert::send_eof()
error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
/*
We must invalidate the table in the query cache before binlog writing
@@ -2601,6 +2717,12 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (info.handle_duplicates == DUP_REPLACE)
+ {
+ if (!table->triggers || !table->triggers->has_delete_triggers())
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ }
if (!thd->prelocked_mode)
table->file->start_bulk_insert((ha_rows) 0);
thd->no_trans_update= 0;
@@ -2640,6 +2762,7 @@ bool select_create::send_eof()
else
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
VOID(pthread_mutex_lock(&LOCK_open));
mysql_unlock_tables(thd, lock);
/*
@@ -2673,6 +2796,7 @@ void select_create::abort()
if (table)
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
enum db_type table_type=table->s->db_type;
if (!table->s->tmp_table)
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 47af816f41d..efbf29cf207 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -41,8 +41,6 @@ sys_var_long_ptr trg_new_row_fake_var(0, 0);
#define yySkip() lex->ptr++
#define yyLength() ((uint) (lex->ptr - lex->tok_start)-1)
-pthread_key(LEX*,THR_LEX);
-
/* Longest standard keyword name */
#define TOCK_NAME_LENGTH 24
@@ -91,8 +89,6 @@ void lex_init(void)
for (i=0 ; i < array_elements(sql_functions) ; i++)
sql_functions[i].length=(uchar) strlen(sql_functions[i].name);
- VOID(pthread_key_create(&THR_LEX,NULL));
-
DBUG_VOID_RETURN;
}
@@ -130,6 +126,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->param_list.empty();
lex->view_list.empty();
lex->prepared_stmt_params.empty();
+ lex->auxiliary_table_list.empty();
lex->unit.next= lex->unit.master=
lex->unit.link_next= lex->unit.return_to= 0;
lex->unit.prev= lex->unit.link_prev= 0;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 285e1d6d5a6..e5b087fc72a 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -873,7 +873,7 @@ typedef struct st_lex : public Query_tables_list
*/
List<Name_resolution_context> context_stack;
- SQL_LIST proc_list, auxilliary_table_list, save_list;
+ SQL_LIST proc_list, auxiliary_table_list, save_list;
create_field *last_field;
Item_sum *in_sum_func;
udf_func udf;
@@ -1116,6 +1116,3 @@ extern void lex_start(THD *thd, uchar *buf,uint length);
extern void lex_end(LEX *lex);
extern int MYSQLlex(void *arg, void *yythd);
-extern pthread_key(LEX*,THR_LEX);
-
-#define current_lex (current_thd->lex)
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index eaee5edf9f1..40e1e6b07aa 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -225,6 +225,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
}
+ mark_fields_used_by_triggers_for_insert_stmt(thd, table, handle_duplicates);
+
uint tot_length=0;
bool use_blobs= 0, use_vars= 0;
List_iterator_fast<Item> it(fields_vars);
@@ -357,6 +359,13 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (ignore ||
handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (handle_duplicates == DUP_REPLACE)
+ {
+ if (!table->triggers ||
+ !table->triggers->has_delete_triggers())
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ }
if (!thd->prelocked_mode)
table->file->start_bulk_insert((ha_rows) 0);
table->copy_blobs=1;
@@ -381,6 +390,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
error= 1;
}
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
table->next_number_field=0;
}
ha_enable_transaction(thd, TRUE);
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
new file mode 100644
index 00000000000..9dae55e4508
--- /dev/null
+++ b/sql/sql_locale.cc
@@ -0,0 +1,1607 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ The beginnings of locale(7) support.
+ Sponsored for subset of LC_TIME support, WorkLog entry 2928, -- Josh Chamas
+
+ !! This file is built from my_locale.pl !!
+*/
+
+#include "mysql_priv.h"
+
+
+MY_LOCALE *my_locale_by_name(const char *name)
+{
+ MY_LOCALE **locale;
+ for( locale= my_locales; *locale != NULL; locale++)
+ {
+ if(!strcmp((*locale)->name, name))
+ return *locale;
+ }
+ return NULL;
+}
+
+/***** LOCALE BEGIN ar_AE: Arabic - United Arab Emirates *****/
+static const char *my_locale_month_names_ar_AE[13] =
+ {"يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر", NullS };
+static const char *my_locale_ab_month_names_ar_AE[13] =
+ {"ينا","فبر","مار","أبر","ماي","يون","يول","أغس","سبت","أكت","نوف","ديس", NullS };
+static const char *my_locale_day_names_ar_AE[8] =
+ {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت ","الأحد", NullS };
+static const char *my_locale_ab_day_names_ar_AE[8] =
+ {"ن","ث","ر","خ","ج","س","ح", NullS };
+static TYPELIB my_locale_typelib_month_names_ar_AE =
+ { array_elements(my_locale_month_names_ar_AE)-1, "", my_locale_month_names_ar_AE, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ar_AE =
+ { array_elements(my_locale_ab_month_names_ar_AE)-1, "", my_locale_ab_month_names_ar_AE, NULL };
+static TYPELIB my_locale_typelib_day_names_ar_AE =
+ { array_elements(my_locale_day_names_ar_AE)-1, "", my_locale_day_names_ar_AE, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ar_AE =
+ { array_elements(my_locale_ab_day_names_ar_AE)-1, "", my_locale_ab_day_names_ar_AE, NULL };
+MY_LOCALE my_locale_ar_AE=
+ { "ar_AE", "Arabic - United Arab Emirates", FALSE, &my_locale_typelib_month_names_ar_AE, &my_locale_typelib_ab_month_names_ar_AE, &my_locale_typelib_day_names_ar_AE, &my_locale_typelib_ab_day_names_ar_AE };
+/***** LOCALE END ar_AE *****/
+
+/***** LOCALE BEGIN ar_BH: Arabic - Bahrain *****/
+static const char *my_locale_month_names_ar_BH[13] =
+ {"يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر", NullS };
+static const char *my_locale_ab_month_names_ar_BH[13] =
+ {"ينا","فبر","مار","أبر","ماي","يون","يول","أغس","سبت","أكت","نوف","ديس", NullS };
+static const char *my_locale_day_names_ar_BH[8] =
+ {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد", NullS };
+static const char *my_locale_ab_day_names_ar_BH[8] =
+ {"ن","ث","ر","خ","ج","س","ح", NullS };
+static TYPELIB my_locale_typelib_month_names_ar_BH =
+ { array_elements(my_locale_month_names_ar_BH)-1, "", my_locale_month_names_ar_BH, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ar_BH =
+ { array_elements(my_locale_ab_month_names_ar_BH)-1, "", my_locale_ab_month_names_ar_BH, NULL };
+static TYPELIB my_locale_typelib_day_names_ar_BH =
+ { array_elements(my_locale_day_names_ar_BH)-1, "", my_locale_day_names_ar_BH, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ar_BH =
+ { array_elements(my_locale_ab_day_names_ar_BH)-1, "", my_locale_ab_day_names_ar_BH, NULL };
+MY_LOCALE my_locale_ar_BH=
+ { "ar_BH", "Arabic - Bahrain", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_BH *****/
+
+/***** LOCALE BEGIN ar_JO: Arabic - Jordan *****/
+static const char *my_locale_month_names_ar_JO[13] =
+ {"كانون الثاني","شباط","آذار","نيسان","نوار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS };
+static const char *my_locale_ab_month_names_ar_JO[13] =
+ {"كانون الثاني","شباط","آذار","نيسان","نوار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS };
+static const char *my_locale_day_names_ar_JO[8] =
+ {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد", NullS };
+static const char *my_locale_ab_day_names_ar_JO[8] =
+ {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد", NullS };
+static TYPELIB my_locale_typelib_month_names_ar_JO =
+ { array_elements(my_locale_month_names_ar_JO)-1, "", my_locale_month_names_ar_JO, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ar_JO =
+ { array_elements(my_locale_ab_month_names_ar_JO)-1, "", my_locale_ab_month_names_ar_JO, NULL };
+static TYPELIB my_locale_typelib_day_names_ar_JO =
+ { array_elements(my_locale_day_names_ar_JO)-1, "", my_locale_day_names_ar_JO, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ar_JO =
+ { array_elements(my_locale_ab_day_names_ar_JO)-1, "", my_locale_ab_day_names_ar_JO, NULL };
+MY_LOCALE my_locale_ar_JO=
+ { "ar_JO", "Arabic - Jordan", FALSE, &my_locale_typelib_month_names_ar_JO, &my_locale_typelib_ab_month_names_ar_JO, &my_locale_typelib_day_names_ar_JO, &my_locale_typelib_ab_day_names_ar_JO };
+/***** LOCALE END ar_JO *****/
+
+/***** LOCALE BEGIN ar_SA: Arabic - Saudi Arabia *****/
+static const char *my_locale_month_names_ar_SA[13] =
+ {"كانون الثاني","شباط","آذار","نيسـان","أيار","حزيران","تـمـوز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS };
+static const char *my_locale_ab_month_names_ar_SA[13] =
+ {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec", NullS };
+static const char *my_locale_day_names_ar_SA[8] =
+ {"الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعـة","السبت","الأحد", NullS };
+static const char *my_locale_ab_day_names_ar_SA[8] =
+ {"Mon","Tue","Wed","Thu","Fri","Sat","Sun", NullS };
+static TYPELIB my_locale_typelib_month_names_ar_SA =
+ { array_elements(my_locale_month_names_ar_SA)-1, "", my_locale_month_names_ar_SA, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ar_SA =
+ { array_elements(my_locale_ab_month_names_ar_SA)-1, "", my_locale_ab_month_names_ar_SA, NULL };
+static TYPELIB my_locale_typelib_day_names_ar_SA =
+ { array_elements(my_locale_day_names_ar_SA)-1, "", my_locale_day_names_ar_SA, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ar_SA =
+ { array_elements(my_locale_ab_day_names_ar_SA)-1, "", my_locale_ab_day_names_ar_SA, NULL };
+MY_LOCALE my_locale_ar_SA=
+ { "ar_SA", "Arabic - Saudi Arabia", FALSE, &my_locale_typelib_month_names_ar_SA, &my_locale_typelib_ab_month_names_ar_SA, &my_locale_typelib_day_names_ar_SA, &my_locale_typelib_ab_day_names_ar_SA };
+/***** LOCALE END ar_SA *****/
+
+/***** LOCALE BEGIN ar_SY: Arabic - Syria *****/
+static const char *my_locale_month_names_ar_SY[13] =
+ {"كانون الثاني","شباط","آذار","نيسان","نواران","حزير","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS };
+static const char *my_locale_ab_month_names_ar_SY[13] =
+ {"كانون الثاني","شباط","آذار","نيسان","نوار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS };
+static const char *my_locale_day_names_ar_SY[8] =
+ {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد", NullS };
+static const char *my_locale_ab_day_names_ar_SY[8] =
+ {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد", NullS };
+static TYPELIB my_locale_typelib_month_names_ar_SY =
+ { array_elements(my_locale_month_names_ar_SY)-1, "", my_locale_month_names_ar_SY, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ar_SY =
+ { array_elements(my_locale_ab_month_names_ar_SY)-1, "", my_locale_ab_month_names_ar_SY, NULL };
+static TYPELIB my_locale_typelib_day_names_ar_SY =
+ { array_elements(my_locale_day_names_ar_SY)-1, "", my_locale_day_names_ar_SY, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ar_SY =
+ { array_elements(my_locale_ab_day_names_ar_SY)-1, "", my_locale_ab_day_names_ar_SY, NULL };
+MY_LOCALE my_locale_ar_SY=
+ { "ar_SY", "Arabic - Syria", FALSE, &my_locale_typelib_month_names_ar_SY, &my_locale_typelib_ab_month_names_ar_SY, &my_locale_typelib_day_names_ar_SY, &my_locale_typelib_ab_day_names_ar_SY };
+/***** LOCALE END ar_SY *****/
+
+/***** LOCALE BEGIN be_BY: Belarusian - Belarus *****/
+static const char *my_locale_month_names_be_BY[13] =
+ {"Студзень","Люты","Сакавік","Красавік","Травень","Чэрвень","Ліпень","Жнівень","Верасень","Кастрычнік","Лістапад","Снежань", NullS };
+static const char *my_locale_ab_month_names_be_BY[13] =
+ {"Стд","Лют","Сак","Крс","Тра","Чэр","Ліп","Жнв","Врс","Кст","Ліс","Снж", NullS };
+static const char *my_locale_day_names_be_BY[8] =
+ {"Панядзелак","Аўторак","Серада","Чацвер","Пятніца","Субота","Нядзеля", NullS };
+static const char *my_locale_ab_day_names_be_BY[8] =
+ {"Пан","Аўт","Срд","Чцв","Пят","Суб","Няд", NullS };
+static TYPELIB my_locale_typelib_month_names_be_BY =
+ { array_elements(my_locale_month_names_be_BY)-1, "", my_locale_month_names_be_BY, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_be_BY =
+ { array_elements(my_locale_ab_month_names_be_BY)-1, "", my_locale_ab_month_names_be_BY, NULL };
+static TYPELIB my_locale_typelib_day_names_be_BY =
+ { array_elements(my_locale_day_names_be_BY)-1, "", my_locale_day_names_be_BY, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_be_BY =
+ { array_elements(my_locale_ab_day_names_be_BY)-1, "", my_locale_ab_day_names_be_BY, NULL };
+MY_LOCALE my_locale_be_BY=
+ { "be_BY", "Belarusian - Belarus", FALSE, &my_locale_typelib_month_names_be_BY, &my_locale_typelib_ab_month_names_be_BY, &my_locale_typelib_day_names_be_BY, &my_locale_typelib_ab_day_names_be_BY };
+/***** LOCALE END be_BY *****/
+
+/***** LOCALE BEGIN bg_BG: Bulgarian - Bulgaria *****/
+static const char *my_locale_month_names_bg_BG[13] =
+ {"януари","февруари","март","април","май","юни","юли","август","септември","октомври","ноември","декември", NullS };
+static const char *my_locale_ab_month_names_bg_BG[13] =
+ {"яну","фев","мар","апр","май","юни","юли","авг","сеп","окт","ное","дек", NullS };
+static const char *my_locale_day_names_bg_BG[8] =
+ {"понеделник","вторник","сряда","четвъртък","петък","събота","неделя", NullS };
+static const char *my_locale_ab_day_names_bg_BG[8] =
+ {"пн","вт","ср","чт","пт","сб","нд", NullS };
+static TYPELIB my_locale_typelib_month_names_bg_BG =
+ { array_elements(my_locale_month_names_bg_BG)-1, "", my_locale_month_names_bg_BG, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_bg_BG =
+ { array_elements(my_locale_ab_month_names_bg_BG)-1, "", my_locale_ab_month_names_bg_BG, NULL };
+static TYPELIB my_locale_typelib_day_names_bg_BG =
+ { array_elements(my_locale_day_names_bg_BG)-1, "", my_locale_day_names_bg_BG, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_bg_BG =
+ { array_elements(my_locale_ab_day_names_bg_BG)-1, "", my_locale_ab_day_names_bg_BG, NULL };
+MY_LOCALE my_locale_bg_BG=
+ { "bg_BG", "Bulgarian - Bulgaria", FALSE, &my_locale_typelib_month_names_bg_BG, &my_locale_typelib_ab_month_names_bg_BG, &my_locale_typelib_day_names_bg_BG, &my_locale_typelib_ab_day_names_bg_BG };
+/***** LOCALE END bg_BG *****/
+
+/***** LOCALE BEGIN ca_ES: Catalan - Catalan *****/
+static const char *my_locale_month_names_ca_ES[13] =
+ {"gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre", NullS };
+static const char *my_locale_ab_month_names_ca_ES[13] =
+ {"gen","feb","mar","abr","mai","jun","jul","ago","set","oct","nov","des", NullS };
+static const char *my_locale_day_names_ca_ES[8] =
+ {"dilluns","dimarts","dimecres","dijous","divendres","dissabte","diumenge", NullS };
+static const char *my_locale_ab_day_names_ca_ES[8] =
+ {"dl","dt","dc","dj","dv","ds","dg", NullS };
+static TYPELIB my_locale_typelib_month_names_ca_ES =
+ { array_elements(my_locale_month_names_ca_ES)-1, "", my_locale_month_names_ca_ES, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ca_ES =
+ { array_elements(my_locale_ab_month_names_ca_ES)-1, "", my_locale_ab_month_names_ca_ES, NULL };
+static TYPELIB my_locale_typelib_day_names_ca_ES =
+ { array_elements(my_locale_day_names_ca_ES)-1, "", my_locale_day_names_ca_ES, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ca_ES =
+ { array_elements(my_locale_ab_day_names_ca_ES)-1, "", my_locale_ab_day_names_ca_ES, NULL };
+MY_LOCALE my_locale_ca_ES=
+ { "ca_ES", "Catalan - Catalan", FALSE, &my_locale_typelib_month_names_ca_ES, &my_locale_typelib_ab_month_names_ca_ES, &my_locale_typelib_day_names_ca_ES, &my_locale_typelib_ab_day_names_ca_ES };
+/***** LOCALE END ca_ES *****/
+
+/***** LOCALE BEGIN cs_CZ: Czech - Czech Republic *****/
+static const char *my_locale_month_names_cs_CZ[13] =
+ {"leden","únor","březen","duben","květen","červen","červenec","srpen","září","říjen","listopad","prosinec", NullS };
+static const char *my_locale_ab_month_names_cs_CZ[13] =
+ {"led","úno","bře","dub","kvě","čen","čec","srp","zář","říj","lis","pro", NullS };
+static const char *my_locale_day_names_cs_CZ[8] =
+ {"Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota","Neděle", NullS };
+static const char *my_locale_ab_day_names_cs_CZ[8] =
+ {"Po","Út","St","Čt","Pá","So","Ne", NullS };
+static TYPELIB my_locale_typelib_month_names_cs_CZ =
+ { array_elements(my_locale_month_names_cs_CZ)-1, "", my_locale_month_names_cs_CZ, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_cs_CZ =
+ { array_elements(my_locale_ab_month_names_cs_CZ)-1, "", my_locale_ab_month_names_cs_CZ, NULL };
+static TYPELIB my_locale_typelib_day_names_cs_CZ =
+ { array_elements(my_locale_day_names_cs_CZ)-1, "", my_locale_day_names_cs_CZ, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_cs_CZ =
+ { array_elements(my_locale_ab_day_names_cs_CZ)-1, "", my_locale_ab_day_names_cs_CZ, NULL };
+MY_LOCALE my_locale_cs_CZ=
+ { "cs_CZ", "Czech - Czech Republic", FALSE, &my_locale_typelib_month_names_cs_CZ, &my_locale_typelib_ab_month_names_cs_CZ, &my_locale_typelib_day_names_cs_CZ, &my_locale_typelib_ab_day_names_cs_CZ };
+/***** LOCALE END cs_CZ *****/
+
+/***** LOCALE BEGIN da_DK: Danish - Denmark *****/
+static const char *my_locale_month_names_da_DK[13] =
+ {"januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december", NullS };
+static const char *my_locale_ab_month_names_da_DK[13] =
+ {"jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_da_DK[8] =
+ {"mandag","tirsdag","onsdag","torsdag","fredag","lørdag","søndag", NullS };
+static const char *my_locale_ab_day_names_da_DK[8] =
+ {"man","tir","ons","tor","fre","lør","søn", NullS };
+static TYPELIB my_locale_typelib_month_names_da_DK =
+ { array_elements(my_locale_month_names_da_DK)-1, "", my_locale_month_names_da_DK, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_da_DK =
+ { array_elements(my_locale_ab_month_names_da_DK)-1, "", my_locale_ab_month_names_da_DK, NULL };
+static TYPELIB my_locale_typelib_day_names_da_DK =
+ { array_elements(my_locale_day_names_da_DK)-1, "", my_locale_day_names_da_DK, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_da_DK =
+ { array_elements(my_locale_ab_day_names_da_DK)-1, "", my_locale_ab_day_names_da_DK, NULL };
+MY_LOCALE my_locale_da_DK=
+ { "da_DK", "Danish - Denmark", FALSE, &my_locale_typelib_month_names_da_DK, &my_locale_typelib_ab_month_names_da_DK, &my_locale_typelib_day_names_da_DK, &my_locale_typelib_ab_day_names_da_DK };
+/***** LOCALE END da_DK *****/
+
+/***** LOCALE BEGIN de_AT: German - Austria *****/
+static const char *my_locale_month_names_de_AT[13] =
+ {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
+static const char *my_locale_ab_month_names_de_AT[13] =
+ {"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS };
+static const char *my_locale_day_names_de_AT[8] =
+ {"Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag", NullS };
+static const char *my_locale_ab_day_names_de_AT[8] =
+ {"Mon","Die","Mit","Don","Fre","Sam","Son", NullS };
+static TYPELIB my_locale_typelib_month_names_de_AT =
+ { array_elements(my_locale_month_names_de_AT)-1, "", my_locale_month_names_de_AT, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_de_AT =
+ { array_elements(my_locale_ab_month_names_de_AT)-1, "", my_locale_ab_month_names_de_AT, NULL };
+static TYPELIB my_locale_typelib_day_names_de_AT =
+ { array_elements(my_locale_day_names_de_AT)-1, "", my_locale_day_names_de_AT, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_de_AT =
+ { array_elements(my_locale_ab_day_names_de_AT)-1, "", my_locale_ab_day_names_de_AT, NULL };
+MY_LOCALE my_locale_de_AT=
+ { "de_AT", "German - Austria", FALSE, &my_locale_typelib_month_names_de_AT, &my_locale_typelib_ab_month_names_de_AT, &my_locale_typelib_day_names_de_AT, &my_locale_typelib_ab_day_names_de_AT };
+/***** LOCALE END de_AT *****/
+
+/***** LOCALE BEGIN de_DE: German - Germany *****/
+static const char *my_locale_month_names_de_DE[13] =
+ {"Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
+static const char *my_locale_ab_month_names_de_DE[13] =
+ {"Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS };
+static const char *my_locale_day_names_de_DE[8] =
+ {"Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag", NullS };
+static const char *my_locale_ab_day_names_de_DE[8] =
+ {"Mo","Di","Mi","Do","Fr","Sa","So", NullS };
+static TYPELIB my_locale_typelib_month_names_de_DE =
+ { array_elements(my_locale_month_names_de_DE)-1, "", my_locale_month_names_de_DE, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_de_DE =
+ { array_elements(my_locale_ab_month_names_de_DE)-1, "", my_locale_ab_month_names_de_DE, NULL };
+static TYPELIB my_locale_typelib_day_names_de_DE =
+ { array_elements(my_locale_day_names_de_DE)-1, "", my_locale_day_names_de_DE, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_de_DE =
+ { array_elements(my_locale_ab_day_names_de_DE)-1, "", my_locale_ab_day_names_de_DE, NULL };
+MY_LOCALE my_locale_de_DE=
+ { "de_DE", "German - Germany", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE };
+/***** LOCALE END de_DE *****/
+
+/***** LOCALE BEGIN en_US: English - United States *****/
+static const char *my_locale_month_names_en_US[13] =
+ {"January","February","March","April","May","June","July","August","September","October","November","December", NullS };
+static const char *my_locale_ab_month_names_en_US[13] =
+ {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec", NullS };
+static const char *my_locale_day_names_en_US[8] =
+ {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday", NullS };
+static const char *my_locale_ab_day_names_en_US[8] =
+ {"Mon","Tue","Wed","Thu","Fri","Sat","Sun", NullS };
+static TYPELIB my_locale_typelib_month_names_en_US =
+ { array_elements(my_locale_month_names_en_US)-1, "", my_locale_month_names_en_US, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_en_US =
+ { array_elements(my_locale_ab_month_names_en_US)-1, "", my_locale_ab_month_names_en_US, NULL };
+static TYPELIB my_locale_typelib_day_names_en_US =
+ { array_elements(my_locale_day_names_en_US)-1, "", my_locale_day_names_en_US, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_en_US =
+ { array_elements(my_locale_ab_day_names_en_US)-1, "", my_locale_ab_day_names_en_US, NULL };
+MY_LOCALE my_locale_en_US=
+ { "en_US", "English - United States", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_US *****/
+
+/***** LOCALE BEGIN es_ES: Spanish - Spain *****/
+static const char *my_locale_month_names_es_ES[13] =
+ {"enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre", NullS };
+static const char *my_locale_ab_month_names_es_ES[13] =
+ {"ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic", NullS };
+static const char *my_locale_day_names_es_ES[8] =
+ {"lunes","martes","miércoles","jueves","viernes","sábado","domingo", NullS };
+static const char *my_locale_ab_day_names_es_ES[8] =
+ {"lun","mar","mié","jue","vie","sáb","dom", NullS };
+static TYPELIB my_locale_typelib_month_names_es_ES =
+ { array_elements(my_locale_month_names_es_ES)-1, "", my_locale_month_names_es_ES, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_es_ES =
+ { array_elements(my_locale_ab_month_names_es_ES)-1, "", my_locale_ab_month_names_es_ES, NULL };
+static TYPELIB my_locale_typelib_day_names_es_ES =
+ { array_elements(my_locale_day_names_es_ES)-1, "", my_locale_day_names_es_ES, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_es_ES =
+ { array_elements(my_locale_ab_day_names_es_ES)-1, "", my_locale_ab_day_names_es_ES, NULL };
+MY_LOCALE my_locale_es_ES=
+ { "es_ES", "Spanish - Spain", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_ES *****/
+
+/***** LOCALE BEGIN et_EE: Estonian - Estonia *****/
+static const char *my_locale_month_names_et_EE[13] =
+ {"jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember", NullS };
+static const char *my_locale_ab_month_names_et_EE[13] =
+ {"jaan ","veebr","märts","apr ","mai ","juuni","juuli","aug ","sept ","okt ","nov ","dets ", NullS };
+static const char *my_locale_day_names_et_EE[8] =
+ {"esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev","pühapäev", NullS };
+static const char *my_locale_ab_day_names_et_EE[8] =
+ {"E","T","K","N","R","L","P", NullS };
+static TYPELIB my_locale_typelib_month_names_et_EE =
+ { array_elements(my_locale_month_names_et_EE)-1, "", my_locale_month_names_et_EE, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_et_EE =
+ { array_elements(my_locale_ab_month_names_et_EE)-1, "", my_locale_ab_month_names_et_EE, NULL };
+static TYPELIB my_locale_typelib_day_names_et_EE =
+ { array_elements(my_locale_day_names_et_EE)-1, "", my_locale_day_names_et_EE, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_et_EE =
+ { array_elements(my_locale_ab_day_names_et_EE)-1, "", my_locale_ab_day_names_et_EE, NULL };
+MY_LOCALE my_locale_et_EE=
+ { "et_EE", "Estonian - Estonia", FALSE, &my_locale_typelib_month_names_et_EE, &my_locale_typelib_ab_month_names_et_EE, &my_locale_typelib_day_names_et_EE, &my_locale_typelib_ab_day_names_et_EE };
+/***** LOCALE END et_EE *****/
+
+/***** LOCALE BEGIN eu_ES: Basque - Basque *****/
+static const char *my_locale_month_names_eu_ES[13] =
+ {"urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua", NullS };
+static const char *my_locale_ab_month_names_eu_ES[13] =
+ {"urt","ots","mar","api","mai","eka","uzt","abu","ira","urr","aza","abe", NullS };
+static const char *my_locale_day_names_eu_ES[8] =
+ {"astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata","igandea", NullS };
+static const char *my_locale_ab_day_names_eu_ES[8] =
+ {"al.","ar.","az.","og.","or.","lr.","ig.", NullS };
+static TYPELIB my_locale_typelib_month_names_eu_ES =
+ { array_elements(my_locale_month_names_eu_ES)-1, "", my_locale_month_names_eu_ES, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_eu_ES =
+ { array_elements(my_locale_ab_month_names_eu_ES)-1, "", my_locale_ab_month_names_eu_ES, NULL };
+static TYPELIB my_locale_typelib_day_names_eu_ES =
+ { array_elements(my_locale_day_names_eu_ES)-1, "", my_locale_day_names_eu_ES, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_eu_ES =
+ { array_elements(my_locale_ab_day_names_eu_ES)-1, "", my_locale_ab_day_names_eu_ES, NULL };
+MY_LOCALE my_locale_eu_ES=
+ { "eu_ES", "Basque - Basque", TRUE, &my_locale_typelib_month_names_eu_ES, &my_locale_typelib_ab_month_names_eu_ES, &my_locale_typelib_day_names_eu_ES, &my_locale_typelib_ab_day_names_eu_ES };
+/***** LOCALE END eu_ES *****/
+
+/***** LOCALE BEGIN fi_FI: Finnish - Finland *****/
+static const char *my_locale_month_names_fi_FI[13] =
+ {"tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu", NullS };
+static const char *my_locale_ab_month_names_fi_FI[13] =
+ {"tammi ","helmi ","maalis","huhti ","touko ","kesä  ","heinä ","elo   ","syys  ","loka  ","marras","joulu ", NullS };
+static const char *my_locale_day_names_fi_FI[8] =
+ {"maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai","sunnuntai", NullS };
+static const char *my_locale_ab_day_names_fi_FI[8] =
+ {"ma","ti","ke","to","pe","la","su", NullS };
+static TYPELIB my_locale_typelib_month_names_fi_FI =
+ { array_elements(my_locale_month_names_fi_FI)-1, "", my_locale_month_names_fi_FI, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_fi_FI =
+ { array_elements(my_locale_ab_month_names_fi_FI)-1, "", my_locale_ab_month_names_fi_FI, NULL };
+static TYPELIB my_locale_typelib_day_names_fi_FI =
+ { array_elements(my_locale_day_names_fi_FI)-1, "", my_locale_day_names_fi_FI, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_fi_FI =
+ { array_elements(my_locale_ab_day_names_fi_FI)-1, "", my_locale_ab_day_names_fi_FI, NULL };
+MY_LOCALE my_locale_fi_FI=
+ { "fi_FI", "Finnish - Finland", FALSE, &my_locale_typelib_month_names_fi_FI, &my_locale_typelib_ab_month_names_fi_FI, &my_locale_typelib_day_names_fi_FI, &my_locale_typelib_ab_day_names_fi_FI };
+/***** LOCALE END fi_FI *****/
+
+/***** LOCALE BEGIN fo_FO: Faroese - Faroe Islands *****/
+static const char *my_locale_month_names_fo_FO[13] =
+ {"januar","februar","mars","apríl","mai","juni","juli","august","september","oktober","november","desember", NullS };
+static const char *my_locale_ab_month_names_fo_FO[13] =
+ {"jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des", NullS };
+static const char *my_locale_day_names_fo_FO[8] =
+ {"mánadagur","týsdagur","mikudagur","hósdagur","fríggjadagur","leygardagur","sunnudagur", NullS };
+static const char *my_locale_ab_day_names_fo_FO[8] =
+ {"mán","týs","mik","hós","frí","ley","sun", NullS };
+static TYPELIB my_locale_typelib_month_names_fo_FO =
+ { array_elements(my_locale_month_names_fo_FO)-1, "", my_locale_month_names_fo_FO, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_fo_FO =
+ { array_elements(my_locale_ab_month_names_fo_FO)-1, "", my_locale_ab_month_names_fo_FO, NULL };
+static TYPELIB my_locale_typelib_day_names_fo_FO =
+ { array_elements(my_locale_day_names_fo_FO)-1, "", my_locale_day_names_fo_FO, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_fo_FO =
+ { array_elements(my_locale_ab_day_names_fo_FO)-1, "", my_locale_ab_day_names_fo_FO, NULL };
+MY_LOCALE my_locale_fo_FO=
+ { "fo_FO", "Faroese - Faroe Islands", FALSE, &my_locale_typelib_month_names_fo_FO, &my_locale_typelib_ab_month_names_fo_FO, &my_locale_typelib_day_names_fo_FO, &my_locale_typelib_ab_day_names_fo_FO };
+/***** LOCALE END fo_FO *****/
+
+/***** LOCALE BEGIN fr_FR: French - France *****/
+static const char *my_locale_month_names_fr_FR[13] =
+ {"janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre", NullS };
+static const char *my_locale_ab_month_names_fr_FR[13] =
+ {"jan","fév","mar","avr","mai","jun","jui","aoû","sep","oct","nov","déc", NullS };
+static const char *my_locale_day_names_fr_FR[8] =
+ {"lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche", NullS };
+static const char *my_locale_ab_day_names_fr_FR[8] =
+ {"lun","mar","mer","jeu","ven","sam","dim", NullS };
+static TYPELIB my_locale_typelib_month_names_fr_FR =
+ { array_elements(my_locale_month_names_fr_FR)-1, "", my_locale_month_names_fr_FR, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_fr_FR =
+ { array_elements(my_locale_ab_month_names_fr_FR)-1, "", my_locale_ab_month_names_fr_FR, NULL };
+static TYPELIB my_locale_typelib_day_names_fr_FR =
+ { array_elements(my_locale_day_names_fr_FR)-1, "", my_locale_day_names_fr_FR, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_fr_FR =
+ { array_elements(my_locale_ab_day_names_fr_FR)-1, "", my_locale_ab_day_names_fr_FR, NULL };
+MY_LOCALE my_locale_fr_FR=
+ { "fr_FR", "French - France", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR };
+/***** LOCALE END fr_FR *****/
+
+/***** LOCALE BEGIN gl_ES: Galician - Galician *****/
+static const char *my_locale_month_names_gl_ES[13] =
+ {"Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro", NullS };
+static const char *my_locale_ab_month_names_gl_ES[13] =
+ {"Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec", NullS };
+static const char *my_locale_day_names_gl_ES[8] =
+ {"Luns","Martes","Mércores","Xoves","Venres","Sábado","Domingo", NullS };
+static const char *my_locale_ab_day_names_gl_ES[8] =
+ {"Lun","Mar","Mér","Xov","Ven","Sáb","Dom", NullS };
+static TYPELIB my_locale_typelib_month_names_gl_ES =
+ { array_elements(my_locale_month_names_gl_ES)-1, "", my_locale_month_names_gl_ES, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_gl_ES =
+ { array_elements(my_locale_ab_month_names_gl_ES)-1, "", my_locale_ab_month_names_gl_ES, NULL };
+static TYPELIB my_locale_typelib_day_names_gl_ES =
+ { array_elements(my_locale_day_names_gl_ES)-1, "", my_locale_day_names_gl_ES, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_gl_ES =
+ { array_elements(my_locale_ab_day_names_gl_ES)-1, "", my_locale_ab_day_names_gl_ES, NULL };
+MY_LOCALE my_locale_gl_ES=
+ { "gl_ES", "Galician - Galician", FALSE, &my_locale_typelib_month_names_gl_ES, &my_locale_typelib_ab_month_names_gl_ES, &my_locale_typelib_day_names_gl_ES, &my_locale_typelib_ab_day_names_gl_ES };
+/***** LOCALE END gl_ES *****/
+
+/***** LOCALE BEGIN gu_IN: Gujarati - India *****/
+static const char *my_locale_month_names_gu_IN[13] =
+ {"જાન્યુઆરી","ફેબ્રુઆરી","માર્ચ","એપ્રિલ","મે","જુન","જુલાઇ","ઓગસ્ટ","સેપ્ટેમ્બર","ઓક્ટોબર","નવેમ્બર","ડિસેમ્બર", NullS };
+static const char *my_locale_ab_month_names_gu_IN[13] =
+ {"જાન","ફેબ","માર","એપ્ર","મે","જુન","જુલ","ઓગ","સેપ્ટ","ઓક્ટ","નોવ","ડિસ", NullS };
+static const char *my_locale_day_names_gu_IN[8] =
+ {"સોમવાર","મન્ગળવાર","બુધવાર","ગુરુવાર","શુક્રવાર","શનિવાર","રવિવાર", NullS };
+static const char *my_locale_ab_day_names_gu_IN[8] =
+ {"સોમ","મન્ગળ","બુધ","ગુરુ","શુક્ર","શનિ","રવિ", NullS };
+static TYPELIB my_locale_typelib_month_names_gu_IN =
+ { array_elements(my_locale_month_names_gu_IN)-1, "", my_locale_month_names_gu_IN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_gu_IN =
+ { array_elements(my_locale_ab_month_names_gu_IN)-1, "", my_locale_ab_month_names_gu_IN, NULL };
+static TYPELIB my_locale_typelib_day_names_gu_IN =
+ { array_elements(my_locale_day_names_gu_IN)-1, "", my_locale_day_names_gu_IN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_gu_IN =
+ { array_elements(my_locale_ab_day_names_gu_IN)-1, "", my_locale_ab_day_names_gu_IN, NULL };
+MY_LOCALE my_locale_gu_IN=
+ { "gu_IN", "Gujarati - India", FALSE, &my_locale_typelib_month_names_gu_IN, &my_locale_typelib_ab_month_names_gu_IN, &my_locale_typelib_day_names_gu_IN, &my_locale_typelib_ab_day_names_gu_IN };
+/***** LOCALE END gu_IN *****/
+
+/***** LOCALE BEGIN he_IL: Hebrew - Israel *****/
+static const char *my_locale_month_names_he_IL[13] =
+ {"ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר", NullS };
+static const char *my_locale_ab_month_names_he_IL[13] =
+ {"ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ", NullS };
+static const char *my_locale_day_names_he_IL[8] =
+ {"שני","שלישי","רביעי","חמישי","שישי","שבת","ראשון", NullS };
+static const char *my_locale_ab_day_names_he_IL[8] =
+ {"ב'","ג'","ד'","ה'","ו'","ש'","א'", NullS };
+static TYPELIB my_locale_typelib_month_names_he_IL =
+ { array_elements(my_locale_month_names_he_IL)-1, "", my_locale_month_names_he_IL, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_he_IL =
+ { array_elements(my_locale_ab_month_names_he_IL)-1, "", my_locale_ab_month_names_he_IL, NULL };
+static TYPELIB my_locale_typelib_day_names_he_IL =
+ { array_elements(my_locale_day_names_he_IL)-1, "", my_locale_day_names_he_IL, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_he_IL =
+ { array_elements(my_locale_ab_day_names_he_IL)-1, "", my_locale_ab_day_names_he_IL, NULL };
+MY_LOCALE my_locale_he_IL=
+ { "he_IL", "Hebrew - Israel", FALSE, &my_locale_typelib_month_names_he_IL, &my_locale_typelib_ab_month_names_he_IL, &my_locale_typelib_day_names_he_IL, &my_locale_typelib_ab_day_names_he_IL };
+/***** LOCALE END he_IL *****/
+
+/***** LOCALE BEGIN hi_IN: Hindi - India *****/
+static const char *my_locale_month_names_hi_IN[13] =
+ {"जनवरी","फ़रवरी","मार्च","अप्रेल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्टूबर","नवम्बर","दिसम्बर", NullS };
+static const char *my_locale_ab_month_names_hi_IN[13] =
+ {"जनवरी","फ़रवरी","मार्च","अप्रेल","मई","जून","जुलाई","अगस्त","सितम्बर","अक्टूबर","नवम्बर","दिसम्बर", NullS };
+static const char *my_locale_day_names_hi_IN[8] =
+ {"सोमवार ","मंगलवार ","बुधवार ","गुरुवार ","शुक्रवार ","शनिवार ","रविवार ", NullS };
+static const char *my_locale_ab_day_names_hi_IN[8] =
+ {"सोम ","मंगल ","बुध ","गुरु ","शुक्र ","शनि ","रवि ", NullS };
+static TYPELIB my_locale_typelib_month_names_hi_IN =
+ { array_elements(my_locale_month_names_hi_IN)-1, "", my_locale_month_names_hi_IN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_hi_IN =
+ { array_elements(my_locale_ab_month_names_hi_IN)-1, "", my_locale_ab_month_names_hi_IN, NULL };
+static TYPELIB my_locale_typelib_day_names_hi_IN =
+ { array_elements(my_locale_day_names_hi_IN)-1, "", my_locale_day_names_hi_IN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_hi_IN =
+ { array_elements(my_locale_ab_day_names_hi_IN)-1, "", my_locale_ab_day_names_hi_IN, NULL };
+MY_LOCALE my_locale_hi_IN=
+ { "hi_IN", "Hindi - India", FALSE, &my_locale_typelib_month_names_hi_IN, &my_locale_typelib_ab_month_names_hi_IN, &my_locale_typelib_day_names_hi_IN, &my_locale_typelib_ab_day_names_hi_IN };
+/***** LOCALE END hi_IN *****/
+
+/***** LOCALE BEGIN hr_HR: Croatian - Croatia *****/
+static const char *my_locale_month_names_hr_HR[13] =
+ {"Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac", NullS };
+static const char *my_locale_ab_month_names_hr_HR[13] =
+ {"Sij","Vel","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro", NullS };
+static const char *my_locale_day_names_hr_HR[8] =
+ {"Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja", NullS };
+static const char *my_locale_ab_day_names_hr_HR[8] =
+ {"Pon","Uto","Sri","Čet","Pet","Sub","Ned", NullS };
+static TYPELIB my_locale_typelib_month_names_hr_HR =
+ { array_elements(my_locale_month_names_hr_HR)-1, "", my_locale_month_names_hr_HR, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_hr_HR =
+ { array_elements(my_locale_ab_month_names_hr_HR)-1, "", my_locale_ab_month_names_hr_HR, NULL };
+static TYPELIB my_locale_typelib_day_names_hr_HR =
+ { array_elements(my_locale_day_names_hr_HR)-1, "", my_locale_day_names_hr_HR, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_hr_HR =
+ { array_elements(my_locale_ab_day_names_hr_HR)-1, "", my_locale_ab_day_names_hr_HR, NULL };
+MY_LOCALE my_locale_hr_HR=
+ { "hr_HR", "Croatian - Croatia", FALSE, &my_locale_typelib_month_names_hr_HR, &my_locale_typelib_ab_month_names_hr_HR, &my_locale_typelib_day_names_hr_HR, &my_locale_typelib_ab_day_names_hr_HR };
+/***** LOCALE END hr_HR *****/
+
+/***** LOCALE BEGIN hu_HU: Hungarian - Hungary *****/
+static const char *my_locale_month_names_hu_HU[13] =
+ {"január","február","március","április","május","június","július","augusztus","szeptember","október","november","december", NullS };
+static const char *my_locale_ab_month_names_hu_HU[13] =
+ {"jan","feb","már","ápr","máj","jún","júl","aug","sze","okt","nov","dec", NullS };
+static const char *my_locale_day_names_hu_HU[8] =
+ {"hétfő","kedd","szerda","csütörtök","péntek","szombat","vasárnap", NullS };
+static const char *my_locale_ab_day_names_hu_HU[8] =
+ {"h","k","sze","cs","p","szo","v", NullS };
+static TYPELIB my_locale_typelib_month_names_hu_HU =
+ { array_elements(my_locale_month_names_hu_HU)-1, "", my_locale_month_names_hu_HU, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_hu_HU =
+ { array_elements(my_locale_ab_month_names_hu_HU)-1, "", my_locale_ab_month_names_hu_HU, NULL };
+static TYPELIB my_locale_typelib_day_names_hu_HU =
+ { array_elements(my_locale_day_names_hu_HU)-1, "", my_locale_day_names_hu_HU, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_hu_HU =
+ { array_elements(my_locale_ab_day_names_hu_HU)-1, "", my_locale_ab_day_names_hu_HU, NULL };
+MY_LOCALE my_locale_hu_HU=
+ { "hu_HU", "Hungarian - Hungary", FALSE, &my_locale_typelib_month_names_hu_HU, &my_locale_typelib_ab_month_names_hu_HU, &my_locale_typelib_day_names_hu_HU, &my_locale_typelib_ab_day_names_hu_HU };
+/***** LOCALE END hu_HU *****/
+
+/***** LOCALE BEGIN id_ID: Indonesian - Indonesia *****/
+static const char *my_locale_month_names_id_ID[13] =
+ {"Januari","Pebruari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember", NullS };
+static const char *my_locale_ab_month_names_id_ID[13] =
+ {"Jan","Peb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des", NullS };
+static const char *my_locale_day_names_id_ID[8] =
+ {"Senin","Selasa","Rabu","Kamis","Jumat","Sabtu","Minggu", NullS };
+static const char *my_locale_ab_day_names_id_ID[8] =
+ {"Sen","Sel","Rab","Kam","Jum","Sab","Min", NullS };
+static TYPELIB my_locale_typelib_month_names_id_ID =
+ { array_elements(my_locale_month_names_id_ID)-1, "", my_locale_month_names_id_ID, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_id_ID =
+ { array_elements(my_locale_ab_month_names_id_ID)-1, "", my_locale_ab_month_names_id_ID, NULL };
+static TYPELIB my_locale_typelib_day_names_id_ID =
+ { array_elements(my_locale_day_names_id_ID)-1, "", my_locale_day_names_id_ID, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_id_ID =
+ { array_elements(my_locale_ab_day_names_id_ID)-1, "", my_locale_ab_day_names_id_ID, NULL };
+MY_LOCALE my_locale_id_ID=
+ { "id_ID", "Indonesian - Indonesia", TRUE, &my_locale_typelib_month_names_id_ID, &my_locale_typelib_ab_month_names_id_ID, &my_locale_typelib_day_names_id_ID, &my_locale_typelib_ab_day_names_id_ID };
+/***** LOCALE END id_ID *****/
+
+/***** LOCALE BEGIN is_IS: Icelandic - Iceland *****/
+static const char *my_locale_month_names_is_IS[13] =
+ {"janúar","febrúar","mars","apríl","maí","júní","júlí","ágúst","september","október","nóvember","desember", NullS };
+static const char *my_locale_ab_month_names_is_IS[13] =
+ {"jan","feb","mar","apr","maí","jún","júl","ágú","sep","okt","nóv","des", NullS };
+static const char *my_locale_day_names_is_IS[8] =
+ {"mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur","sunnudagur", NullS };
+static const char *my_locale_ab_day_names_is_IS[8] =
+ {"mán","þri","mið","fim","fös","lau","sun", NullS };
+static TYPELIB my_locale_typelib_month_names_is_IS =
+ { array_elements(my_locale_month_names_is_IS)-1, "", my_locale_month_names_is_IS, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_is_IS =
+ { array_elements(my_locale_ab_month_names_is_IS)-1, "", my_locale_ab_month_names_is_IS, NULL };
+static TYPELIB my_locale_typelib_day_names_is_IS =
+ { array_elements(my_locale_day_names_is_IS)-1, "", my_locale_day_names_is_IS, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_is_IS =
+ { array_elements(my_locale_ab_day_names_is_IS)-1, "", my_locale_ab_day_names_is_IS, NULL };
+MY_LOCALE my_locale_is_IS=
+ { "is_IS", "Icelandic - Iceland", FALSE, &my_locale_typelib_month_names_is_IS, &my_locale_typelib_ab_month_names_is_IS, &my_locale_typelib_day_names_is_IS, &my_locale_typelib_ab_day_names_is_IS };
+/***** LOCALE END is_IS *****/
+
+/***** LOCALE BEGIN it_CH: Italian - Switzerland *****/
+static const char *my_locale_month_names_it_CH[13] =
+ {"gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre", NullS };
+static const char *my_locale_ab_month_names_it_CH[13] =
+ {"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic", NullS };
+static const char *my_locale_day_names_it_CH[8] =
+ {"lunedì","martedì","mercoledì","giovedì","venerdì","sabato","domenica", NullS };
+static const char *my_locale_ab_day_names_it_CH[8] =
+ {"lun","mar","mer","gio","ven","sab","dom", NullS };
+static TYPELIB my_locale_typelib_month_names_it_CH =
+ { array_elements(my_locale_month_names_it_CH)-1, "", my_locale_month_names_it_CH, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_it_CH =
+ { array_elements(my_locale_ab_month_names_it_CH)-1, "", my_locale_ab_month_names_it_CH, NULL };
+static TYPELIB my_locale_typelib_day_names_it_CH =
+ { array_elements(my_locale_day_names_it_CH)-1, "", my_locale_day_names_it_CH, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_it_CH =
+ { array_elements(my_locale_ab_day_names_it_CH)-1, "", my_locale_ab_day_names_it_CH, NULL };
+MY_LOCALE my_locale_it_CH=
+ { "it_CH", "Italian - Switzerland", FALSE, &my_locale_typelib_month_names_it_CH, &my_locale_typelib_ab_month_names_it_CH, &my_locale_typelib_day_names_it_CH, &my_locale_typelib_ab_day_names_it_CH };
+/***** LOCALE END it_CH *****/
+
+/***** LOCALE BEGIN ja_JP: Japanese - Japan *****/
+static const char *my_locale_month_names_ja_JP[13] =
+ {"1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月", NullS };
+static const char *my_locale_ab_month_names_ja_JP[13] =
+ {" 1月"," 2月"," 3月"," 4月"," 5月"," 6月"," 7月"," 8月"," 9月","10月","11月","12月", NullS };
+static const char *my_locale_day_names_ja_JP[8] =
+ {"月曜日","火曜日","水曜日","木曜日","金曜日","土曜日","日曜日", NullS };
+static const char *my_locale_ab_day_names_ja_JP[8] =
+ {"月","火","水","木","金","土","日", NullS };
+static TYPELIB my_locale_typelib_month_names_ja_JP =
+ { array_elements(my_locale_month_names_ja_JP)-1, "", my_locale_month_names_ja_JP, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ja_JP =
+ { array_elements(my_locale_ab_month_names_ja_JP)-1, "", my_locale_ab_month_names_ja_JP, NULL };
+static TYPELIB my_locale_typelib_day_names_ja_JP =
+ { array_elements(my_locale_day_names_ja_JP)-1, "", my_locale_day_names_ja_JP, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ja_JP =
+ { array_elements(my_locale_ab_day_names_ja_JP)-1, "", my_locale_ab_day_names_ja_JP, NULL };
+MY_LOCALE my_locale_ja_JP=
+ { "ja_JP", "Japanese - Japan", FALSE, &my_locale_typelib_month_names_ja_JP, &my_locale_typelib_ab_month_names_ja_JP, &my_locale_typelib_day_names_ja_JP, &my_locale_typelib_ab_day_names_ja_JP };
+/***** LOCALE END ja_JP *****/
+
+/***** LOCALE BEGIN ko_KR: Korean - Korea *****/
+static const char *my_locale_month_names_ko_KR[13] =
+ {"일월","이월","삼월","사월","오월","유월","칠월","팔월","구월","시월","십일월","십이월", NullS };
+static const char *my_locale_ab_month_names_ko_KR[13] =
+ {" 1월"," 2월"," 3월"," 4월"," 5월"," 6월"," 7월"," 8월"," 9월","10월","11월","12월", NullS };
+static const char *my_locale_day_names_ko_KR[8] =
+ {"월요일","화요일","수요일","목요일","금요일","토요일","일요일", NullS };
+static const char *my_locale_ab_day_names_ko_KR[8] =
+ {"월","화","수","목","금","토","일", NullS };
+static TYPELIB my_locale_typelib_month_names_ko_KR =
+ { array_elements(my_locale_month_names_ko_KR)-1, "", my_locale_month_names_ko_KR, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ko_KR =
+ { array_elements(my_locale_ab_month_names_ko_KR)-1, "", my_locale_ab_month_names_ko_KR, NULL };
+static TYPELIB my_locale_typelib_day_names_ko_KR =
+ { array_elements(my_locale_day_names_ko_KR)-1, "", my_locale_day_names_ko_KR, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ko_KR =
+ { array_elements(my_locale_ab_day_names_ko_KR)-1, "", my_locale_ab_day_names_ko_KR, NULL };
+MY_LOCALE my_locale_ko_KR=
+ { "ko_KR", "Korean - Korea", FALSE, &my_locale_typelib_month_names_ko_KR, &my_locale_typelib_ab_month_names_ko_KR, &my_locale_typelib_day_names_ko_KR, &my_locale_typelib_ab_day_names_ko_KR };
+/***** LOCALE END ko_KR *****/
+
+/***** LOCALE BEGIN lt_LT: Lithuanian - Lithuania *****/
+static const char *my_locale_month_names_lt_LT[13] =
+ {"sausio","vasario","kovo","balandžio","gegužės","birželio","liepos","rugpjūčio","rugsėjo","spalio","lapkričio","gruodžio", NullS };
+static const char *my_locale_ab_month_names_lt_LT[13] =
+ {"Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rgp","Rgs","Spa","Lap","Grd", NullS };
+static const char *my_locale_day_names_lt_LT[8] =
+ {"Pirmadienis","Antradienis","Trečiadienis","Ketvirtadienis","Penktadienis","Šeštadienis","Sekmadienis", NullS };
+static const char *my_locale_ab_day_names_lt_LT[8] =
+ {"Pr","An","Tr","Kt","Pn","Št","Sk", NullS };
+static TYPELIB my_locale_typelib_month_names_lt_LT =
+ { array_elements(my_locale_month_names_lt_LT)-1, "", my_locale_month_names_lt_LT, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_lt_LT =
+ { array_elements(my_locale_ab_month_names_lt_LT)-1, "", my_locale_ab_month_names_lt_LT, NULL };
+static TYPELIB my_locale_typelib_day_names_lt_LT =
+ { array_elements(my_locale_day_names_lt_LT)-1, "", my_locale_day_names_lt_LT, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_lt_LT =
+ { array_elements(my_locale_ab_day_names_lt_LT)-1, "", my_locale_ab_day_names_lt_LT, NULL };
+MY_LOCALE my_locale_lt_LT=
+ { "lt_LT", "Lithuanian - Lithuania", FALSE, &my_locale_typelib_month_names_lt_LT, &my_locale_typelib_ab_month_names_lt_LT, &my_locale_typelib_day_names_lt_LT, &my_locale_typelib_ab_day_names_lt_LT };
+/***** LOCALE END lt_LT *****/
+
+/***** LOCALE BEGIN lv_LV: Latvian - Latvia *****/
+static const char *my_locale_month_names_lv_LV[13] =
+ {"janvāris","februāris","marts","aprīlis","maijs","jūnijs","jūlijs","augusts","septembris","oktobris","novembris","decembris", NullS };
+static const char *my_locale_ab_month_names_lv_LV[13] =
+ {"jan","feb","mar","apr","mai","jūn","jūl","aug","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_lv_LV[8] =
+ {"pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena","svētdiena", NullS };
+static const char *my_locale_ab_day_names_lv_LV[8] =
+ {"P ","O ","T ","C ","Pk","S ","Sv", NullS };
+static TYPELIB my_locale_typelib_month_names_lv_LV =
+ { array_elements(my_locale_month_names_lv_LV)-1, "", my_locale_month_names_lv_LV, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_lv_LV =
+ { array_elements(my_locale_ab_month_names_lv_LV)-1, "", my_locale_ab_month_names_lv_LV, NULL };
+static TYPELIB my_locale_typelib_day_names_lv_LV =
+ { array_elements(my_locale_day_names_lv_LV)-1, "", my_locale_day_names_lv_LV, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_lv_LV =
+ { array_elements(my_locale_ab_day_names_lv_LV)-1, "", my_locale_ab_day_names_lv_LV, NULL };
+MY_LOCALE my_locale_lv_LV=
+ { "lv_LV", "Latvian - Latvia", FALSE, &my_locale_typelib_month_names_lv_LV, &my_locale_typelib_ab_month_names_lv_LV, &my_locale_typelib_day_names_lv_LV, &my_locale_typelib_ab_day_names_lv_LV };
+/***** LOCALE END lv_LV *****/
+
+/***** LOCALE BEGIN mk_MK: Macedonian - FYROM *****/
+static const char *my_locale_month_names_mk_MK[13] =
+ {"јануари","февруари","март","април","мај","јуни","јули","август","септември","октомври","ноември","декември", NullS };
+static const char *my_locale_ab_month_names_mk_MK[13] =
+ {"јан","фев","мар","апр","мај","јун","јул","авг","сеп","окт","ное","дек", NullS };
+static const char *my_locale_day_names_mk_MK[8] =
+ {"понеделник","вторник","среда","четврток","петок","сабота","недела", NullS };
+static const char *my_locale_ab_day_names_mk_MK[8] =
+ {"пон","вто","сре","чет","пет","саб","нед", NullS };
+static TYPELIB my_locale_typelib_month_names_mk_MK =
+ { array_elements(my_locale_month_names_mk_MK)-1, "", my_locale_month_names_mk_MK, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_mk_MK =
+ { array_elements(my_locale_ab_month_names_mk_MK)-1, "", my_locale_ab_month_names_mk_MK, NULL };
+static TYPELIB my_locale_typelib_day_names_mk_MK =
+ { array_elements(my_locale_day_names_mk_MK)-1, "", my_locale_day_names_mk_MK, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_mk_MK =
+ { array_elements(my_locale_ab_day_names_mk_MK)-1, "", my_locale_ab_day_names_mk_MK, NULL };
+MY_LOCALE my_locale_mk_MK=
+ { "mk_MK", "Macedonian - FYROM", FALSE, &my_locale_typelib_month_names_mk_MK, &my_locale_typelib_ab_month_names_mk_MK, &my_locale_typelib_day_names_mk_MK, &my_locale_typelib_ab_day_names_mk_MK };
+/***** LOCALE END mk_MK *****/
+
+/***** LOCALE BEGIN mn_MN: Mongolia - Mongolian *****/
+static const char *my_locale_month_names_mn_MN[13] =
+ {"Нэгдүгээр сар","Хоёрдугаар сар","Гуравдугаар сар","Дөрөвдүгээр сар","Тавдугаар сар","Зургаадугар сар","Долоодугаар сар","Наймдугаар сар","Есдүгээр сар","Аравдугаар сар","Арваннэгдүгээр сар","Арванхоёрдгаар сар", NullS };
+static const char *my_locale_ab_month_names_mn_MN[13] =
+ {"1-р","2-р","3-р","4-р","5-р","6-р","7-р","8-р","9-р","10-р","11-р","12-р", NullS };
+static const char *my_locale_day_names_mn_MN[8] =
+ {"Даваа","Мягмар","Лхагва","Пүрэв","Баасан","Бямба","Ням", NullS };
+static const char *my_locale_ab_day_names_mn_MN[8] =
+ {"Да","Мя","Лх","Пү","Ба","Бя","Ня", NullS };
+static TYPELIB my_locale_typelib_month_names_mn_MN =
+ { array_elements(my_locale_month_names_mn_MN)-1, "", my_locale_month_names_mn_MN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_mn_MN =
+ { array_elements(my_locale_ab_month_names_mn_MN)-1, "", my_locale_ab_month_names_mn_MN, NULL };
+static TYPELIB my_locale_typelib_day_names_mn_MN =
+ { array_elements(my_locale_day_names_mn_MN)-1, "", my_locale_day_names_mn_MN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_mn_MN =
+ { array_elements(my_locale_ab_day_names_mn_MN)-1, "", my_locale_ab_day_names_mn_MN, NULL };
+MY_LOCALE my_locale_mn_MN=
+ { "mn_MN", "Mongolia - Mongolian", FALSE, &my_locale_typelib_month_names_mn_MN, &my_locale_typelib_ab_month_names_mn_MN, &my_locale_typelib_day_names_mn_MN, &my_locale_typelib_ab_day_names_mn_MN };
+/***** LOCALE END mn_MN *****/
+
+/***** LOCALE BEGIN ms_MY: Malay - Malaysia *****/
+static const char *my_locale_month_names_ms_MY[13] =
+ {"Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember", NullS };
+static const char *my_locale_ab_month_names_ms_MY[13] =
+ {"Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis", NullS };
+static const char *my_locale_day_names_ms_MY[8] =
+ {"Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu","Ahad", NullS };
+static const char *my_locale_ab_day_names_ms_MY[8] =
+ {"Isn","Sel","Rab","Kha","Jum","Sab","Ahd", NullS };
+static TYPELIB my_locale_typelib_month_names_ms_MY =
+ { array_elements(my_locale_month_names_ms_MY)-1, "", my_locale_month_names_ms_MY, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ms_MY =
+ { array_elements(my_locale_ab_month_names_ms_MY)-1, "", my_locale_ab_month_names_ms_MY, NULL };
+static TYPELIB my_locale_typelib_day_names_ms_MY =
+ { array_elements(my_locale_day_names_ms_MY)-1, "", my_locale_day_names_ms_MY, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ms_MY =
+ { array_elements(my_locale_ab_day_names_ms_MY)-1, "", my_locale_ab_day_names_ms_MY, NULL };
+MY_LOCALE my_locale_ms_MY=
+ { "ms_MY", "Malay - Malaysia", TRUE, &my_locale_typelib_month_names_ms_MY, &my_locale_typelib_ab_month_names_ms_MY, &my_locale_typelib_day_names_ms_MY, &my_locale_typelib_ab_day_names_ms_MY };
+/***** LOCALE END ms_MY *****/
+
+/***** LOCALE BEGIN nb_NO: Norwegian(Bokml) - Norway *****/
+static const char *my_locale_month_names_nb_NO[13] =
+ {"januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember", NullS };
+static const char *my_locale_ab_month_names_nb_NO[13] =
+ {"jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des", NullS };
+static const char *my_locale_day_names_nb_NO[8] =
+ {"mandag","tirsdag","onsdag","torsdag","fredag","lørdag","søndag", NullS };
+static const char *my_locale_ab_day_names_nb_NO[8] =
+ {"man","tir","ons","tor","fre","lør","søn", NullS };
+static TYPELIB my_locale_typelib_month_names_nb_NO =
+ { array_elements(my_locale_month_names_nb_NO)-1, "", my_locale_month_names_nb_NO, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_nb_NO =
+ { array_elements(my_locale_ab_month_names_nb_NO)-1, "", my_locale_ab_month_names_nb_NO, NULL };
+static TYPELIB my_locale_typelib_day_names_nb_NO =
+ { array_elements(my_locale_day_names_nb_NO)-1, "", my_locale_day_names_nb_NO, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_nb_NO =
+ { array_elements(my_locale_ab_day_names_nb_NO)-1, "", my_locale_ab_day_names_nb_NO, NULL };
+MY_LOCALE my_locale_nb_NO=
+ { "nb_NO", "Norwegian(Bokml) - Norway", FALSE, &my_locale_typelib_month_names_nb_NO, &my_locale_typelib_ab_month_names_nb_NO, &my_locale_typelib_day_names_nb_NO, &my_locale_typelib_ab_day_names_nb_NO };
+/***** LOCALE END nb_NO *****/
+
+/***** LOCALE BEGIN nl_NL: Dutch - The Netherlands *****/
+static const char *my_locale_month_names_nl_NL[13] =
+ {"januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december", NullS };
+static const char *my_locale_ab_month_names_nl_NL[13] =
+ {"jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_nl_NL[8] =
+ {"maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag", NullS };
+static const char *my_locale_ab_day_names_nl_NL[8] =
+ {"ma","di","wo","do","vr","za","zo", NullS };
+static TYPELIB my_locale_typelib_month_names_nl_NL =
+ { array_elements(my_locale_month_names_nl_NL)-1, "", my_locale_month_names_nl_NL, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_nl_NL =
+ { array_elements(my_locale_ab_month_names_nl_NL)-1, "", my_locale_ab_month_names_nl_NL, NULL };
+static TYPELIB my_locale_typelib_day_names_nl_NL =
+ { array_elements(my_locale_day_names_nl_NL)-1, "", my_locale_day_names_nl_NL, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_nl_NL =
+ { array_elements(my_locale_ab_day_names_nl_NL)-1, "", my_locale_ab_day_names_nl_NL, NULL };
+MY_LOCALE my_locale_nl_NL=
+ { "nl_NL", "Dutch - The Netherlands", TRUE, &my_locale_typelib_month_names_nl_NL, &my_locale_typelib_ab_month_names_nl_NL, &my_locale_typelib_day_names_nl_NL, &my_locale_typelib_ab_day_names_nl_NL };
+/***** LOCALE END nl_NL *****/
+
+/***** LOCALE BEGIN pl_PL: Polish - Poland *****/
+static const char *my_locale_month_names_pl_PL[13] =
+ {"styczeń","luty","marzec","kwiecień","maj","czerwiec","lipiec","sierpień","wrzesień","październik","listopad","grudzień", NullS };
+static const char *my_locale_ab_month_names_pl_PL[13] =
+ {"sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru", NullS };
+static const char *my_locale_day_names_pl_PL[8] =
+ {"poniedziałek","wtorek","środa","czwartek","piątek","sobota","niedziela", NullS };
+static const char *my_locale_ab_day_names_pl_PL[8] =
+ {"pon","wto","śro","czw","pią","sob","nie", NullS };
+static TYPELIB my_locale_typelib_month_names_pl_PL =
+ { array_elements(my_locale_month_names_pl_PL)-1, "", my_locale_month_names_pl_PL, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_pl_PL =
+ { array_elements(my_locale_ab_month_names_pl_PL)-1, "", my_locale_ab_month_names_pl_PL, NULL };
+static TYPELIB my_locale_typelib_day_names_pl_PL =
+ { array_elements(my_locale_day_names_pl_PL)-1, "", my_locale_day_names_pl_PL, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_pl_PL =
+ { array_elements(my_locale_ab_day_names_pl_PL)-1, "", my_locale_ab_day_names_pl_PL, NULL };
+MY_LOCALE my_locale_pl_PL=
+ { "pl_PL", "Polish - Poland", FALSE, &my_locale_typelib_month_names_pl_PL, &my_locale_typelib_ab_month_names_pl_PL, &my_locale_typelib_day_names_pl_PL, &my_locale_typelib_ab_day_names_pl_PL };
+/***** LOCALE END pl_PL *****/
+
+/***** LOCALE BEGIN pt_BR: Portugese - Brazil *****/
+static const char *my_locale_month_names_pt_BR[13] =
+ {"janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro", NullS };
+static const char *my_locale_ab_month_names_pt_BR[13] =
+ {"Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez", NullS };
+static const char *my_locale_day_names_pt_BR[8] =
+ {"segunda","terça","quarta","quinta","sexta","sábado","domingo", NullS };
+static const char *my_locale_ab_day_names_pt_BR[8] =
+ {"Seg","Ter","Qua","Qui","Sex","Sáb","Dom", NullS };
+static TYPELIB my_locale_typelib_month_names_pt_BR =
+ { array_elements(my_locale_month_names_pt_BR)-1, "", my_locale_month_names_pt_BR, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_pt_BR =
+ { array_elements(my_locale_ab_month_names_pt_BR)-1, "", my_locale_ab_month_names_pt_BR, NULL };
+static TYPELIB my_locale_typelib_day_names_pt_BR =
+ { array_elements(my_locale_day_names_pt_BR)-1, "", my_locale_day_names_pt_BR, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_pt_BR =
+ { array_elements(my_locale_ab_day_names_pt_BR)-1, "", my_locale_ab_day_names_pt_BR, NULL };
+MY_LOCALE my_locale_pt_BR=
+ { "pt_BR", "Portugese - Brazil", FALSE, &my_locale_typelib_month_names_pt_BR, &my_locale_typelib_ab_month_names_pt_BR, &my_locale_typelib_day_names_pt_BR, &my_locale_typelib_ab_day_names_pt_BR };
+/***** LOCALE END pt_BR *****/
+
+/***** LOCALE BEGIN pt_PT: Portugese - Portugal *****/
+static const char *my_locale_month_names_pt_PT[13] =
+ {"Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro", NullS };
+static const char *my_locale_ab_month_names_pt_PT[13] =
+ {"Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez", NullS };
+static const char *my_locale_day_names_pt_PT[8] =
+ {"Segunda","Terça","Quarta","Quinta","Sexta","Sábado","Domingo", NullS };
+static const char *my_locale_ab_day_names_pt_PT[8] =
+ {"Seg","Ter","Qua","Qui","Sex","Sáb","Dom", NullS };
+static TYPELIB my_locale_typelib_month_names_pt_PT =
+ { array_elements(my_locale_month_names_pt_PT)-1, "", my_locale_month_names_pt_PT, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_pt_PT =
+ { array_elements(my_locale_ab_month_names_pt_PT)-1, "", my_locale_ab_month_names_pt_PT, NULL };
+static TYPELIB my_locale_typelib_day_names_pt_PT =
+ { array_elements(my_locale_day_names_pt_PT)-1, "", my_locale_day_names_pt_PT, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_pt_PT =
+ { array_elements(my_locale_ab_day_names_pt_PT)-1, "", my_locale_ab_day_names_pt_PT, NULL };
+MY_LOCALE my_locale_pt_PT=
+ { "pt_PT", "Portugese - Portugal", FALSE, &my_locale_typelib_month_names_pt_PT, &my_locale_typelib_ab_month_names_pt_PT, &my_locale_typelib_day_names_pt_PT, &my_locale_typelib_ab_day_names_pt_PT };
+/***** LOCALE END pt_PT *****/
+
+/***** LOCALE BEGIN ro_RO: Romanian - Romania *****/
+static const char *my_locale_month_names_ro_RO[13] =
+ {"Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie", NullS };
+static const char *my_locale_ab_month_names_ro_RO[13] =
+ {"ian","feb","mar","apr","mai","iun","iul","aug","sep","oct","nov","dec", NullS };
+static const char *my_locale_day_names_ro_RO[8] =
+ {"Luni","Marţi","Miercuri","Joi","Vineri","SîmbĂtĂ","DuminicĂ", NullS };
+static const char *my_locale_ab_day_names_ro_RO[8] =
+ {"Lu","Ma","Mi","Jo","Vi","Sî","Du", NullS };
+static TYPELIB my_locale_typelib_month_names_ro_RO =
+ { array_elements(my_locale_month_names_ro_RO)-1, "", my_locale_month_names_ro_RO, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ro_RO =
+ { array_elements(my_locale_ab_month_names_ro_RO)-1, "", my_locale_ab_month_names_ro_RO, NULL };
+static TYPELIB my_locale_typelib_day_names_ro_RO =
+ { array_elements(my_locale_day_names_ro_RO)-1, "", my_locale_day_names_ro_RO, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ro_RO =
+ { array_elements(my_locale_ab_day_names_ro_RO)-1, "", my_locale_ab_day_names_ro_RO, NULL };
+MY_LOCALE my_locale_ro_RO=
+ { "ro_RO", "Romanian - Romania", FALSE, &my_locale_typelib_month_names_ro_RO, &my_locale_typelib_ab_month_names_ro_RO, &my_locale_typelib_day_names_ro_RO, &my_locale_typelib_ab_day_names_ro_RO };
+/***** LOCALE END ro_RO *****/
+
+/***** LOCALE BEGIN ru_RU: Russian - Russia *****/
+static const char *my_locale_month_names_ru_RU[13] =
+ {"Января","Февраля","Марта","Апреля","Мая","Июня","Июля","Августа","Сентября","Октября","Ноября","Декабря", NullS };
+static const char *my_locale_ab_month_names_ru_RU[13] =
+ {"Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек", NullS };
+static const char *my_locale_day_names_ru_RU[8] =
+ {"Понедельник","Вторник","Среда","Четверг","Пятница","Суббота","Воскресенье", NullS };
+static const char *my_locale_ab_day_names_ru_RU[8] =
+ {"Пнд","Втр","Срд","Чтв","Птн","Сбт","Вск", NullS };
+static TYPELIB my_locale_typelib_month_names_ru_RU =
+ { array_elements(my_locale_month_names_ru_RU)-1, "", my_locale_month_names_ru_RU, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ru_RU =
+ { array_elements(my_locale_ab_month_names_ru_RU)-1, "", my_locale_ab_month_names_ru_RU, NULL };
+static TYPELIB my_locale_typelib_day_names_ru_RU =
+ { array_elements(my_locale_day_names_ru_RU)-1, "", my_locale_day_names_ru_RU, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ru_RU =
+ { array_elements(my_locale_ab_day_names_ru_RU)-1, "", my_locale_ab_day_names_ru_RU, NULL };
+MY_LOCALE my_locale_ru_RU=
+ { "ru_RU", "Russian - Russia", FALSE, &my_locale_typelib_month_names_ru_RU, &my_locale_typelib_ab_month_names_ru_RU, &my_locale_typelib_day_names_ru_RU, &my_locale_typelib_ab_day_names_ru_RU };
+/***** LOCALE END ru_RU *****/
+
+/***** LOCALE BEGIN ru_UA: Russian - Ukraine *****/
+static const char *my_locale_month_names_ru_UA[13] =
+ {"Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь", NullS };
+static const char *my_locale_ab_month_names_ru_UA[13] =
+ {"Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек", NullS };
+static const char *my_locale_day_names_ru_UA[8] =
+ {"Понедельник","Вторник","Среда","Четверг","Пятница","Суббота","Воскресенье", NullS };
+static const char *my_locale_ab_day_names_ru_UA[8] =
+ {"Пнд","Вто","Срд","Чтв","Птн","Суб","Вск", NullS };
+static TYPELIB my_locale_typelib_month_names_ru_UA =
+ { array_elements(my_locale_month_names_ru_UA)-1, "", my_locale_month_names_ru_UA, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ru_UA =
+ { array_elements(my_locale_ab_month_names_ru_UA)-1, "", my_locale_ab_month_names_ru_UA, NULL };
+static TYPELIB my_locale_typelib_day_names_ru_UA =
+ { array_elements(my_locale_day_names_ru_UA)-1, "", my_locale_day_names_ru_UA, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ru_UA =
+ { array_elements(my_locale_ab_day_names_ru_UA)-1, "", my_locale_ab_day_names_ru_UA, NULL };
+MY_LOCALE my_locale_ru_UA=
+ { "ru_UA", "Russian - Ukraine", FALSE, &my_locale_typelib_month_names_ru_UA, &my_locale_typelib_ab_month_names_ru_UA, &my_locale_typelib_day_names_ru_UA, &my_locale_typelib_ab_day_names_ru_UA };
+/***** LOCALE END ru_UA *****/
+
+/***** LOCALE BEGIN sk_SK: Slovak - Slovakia *****/
+static const char *my_locale_month_names_sk_SK[13] =
+ {"január","február","marec","apríl","máj","jún","júl","august","september","október","november","december", NullS };
+static const char *my_locale_ab_month_names_sk_SK[13] =
+ {"jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_sk_SK[8] =
+ {"Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota","Nedeľa", NullS };
+static const char *my_locale_ab_day_names_sk_SK[8] =
+ {"Po","Ut","St","Št","Pi","So","Ne", NullS };
+static TYPELIB my_locale_typelib_month_names_sk_SK =
+ { array_elements(my_locale_month_names_sk_SK)-1, "", my_locale_month_names_sk_SK, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_sk_SK =
+ { array_elements(my_locale_ab_month_names_sk_SK)-1, "", my_locale_ab_month_names_sk_SK, NULL };
+static TYPELIB my_locale_typelib_day_names_sk_SK =
+ { array_elements(my_locale_day_names_sk_SK)-1, "", my_locale_day_names_sk_SK, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_sk_SK =
+ { array_elements(my_locale_ab_day_names_sk_SK)-1, "", my_locale_ab_day_names_sk_SK, NULL };
+MY_LOCALE my_locale_sk_SK=
+ { "sk_SK", "Slovak - Slovakia", FALSE, &my_locale_typelib_month_names_sk_SK, &my_locale_typelib_ab_month_names_sk_SK, &my_locale_typelib_day_names_sk_SK, &my_locale_typelib_ab_day_names_sk_SK };
+/***** LOCALE END sk_SK *****/
+
+/***** LOCALE BEGIN sl_SI: Slovenian - Slovenia *****/
+static const char *my_locale_month_names_sl_SI[13] =
+ {"januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december", NullS };
+static const char *my_locale_ab_month_names_sl_SI[13] =
+ {"jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_sl_SI[8] =
+ {"ponedeljek","torek","sreda","četrtek","petek","sobota","nedelja", NullS };
+static const char *my_locale_ab_day_names_sl_SI[8] =
+ {"pon","tor","sre","čet","pet","sob","ned", NullS };
+static TYPELIB my_locale_typelib_month_names_sl_SI =
+ { array_elements(my_locale_month_names_sl_SI)-1, "", my_locale_month_names_sl_SI, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_sl_SI =
+ { array_elements(my_locale_ab_month_names_sl_SI)-1, "", my_locale_ab_month_names_sl_SI, NULL };
+static TYPELIB my_locale_typelib_day_names_sl_SI =
+ { array_elements(my_locale_day_names_sl_SI)-1, "", my_locale_day_names_sl_SI, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_sl_SI =
+ { array_elements(my_locale_ab_day_names_sl_SI)-1, "", my_locale_ab_day_names_sl_SI, NULL };
+MY_LOCALE my_locale_sl_SI=
+ { "sl_SI", "Slovenian - Slovenia", FALSE, &my_locale_typelib_month_names_sl_SI, &my_locale_typelib_ab_month_names_sl_SI, &my_locale_typelib_day_names_sl_SI, &my_locale_typelib_ab_day_names_sl_SI };
+/***** LOCALE END sl_SI *****/
+
+/***** LOCALE BEGIN sq_AL: Albanian - Albania *****/
+static const char *my_locale_month_names_sq_AL[13] =
+ {"janar","shkurt","mars","prill","maj","qershor","korrik","gusht","shtator","tetor","nëntor","dhjetor", NullS };
+static const char *my_locale_ab_month_names_sq_AL[13] =
+ {"Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gsh","Sht","Tet","Nën","Dhj", NullS };
+static const char *my_locale_day_names_sq_AL[8] =
+ {"e hënë ","e martë ","e mërkurë ","e enjte ","e premte ","e shtunë ","e diel ", NullS };
+static const char *my_locale_ab_day_names_sq_AL[8] =
+ {"Hën ","Mar ","Mër ","Enj ","Pre ","Sht ","Die ", NullS };
+static TYPELIB my_locale_typelib_month_names_sq_AL =
+ { array_elements(my_locale_month_names_sq_AL)-1, "", my_locale_month_names_sq_AL, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_sq_AL =
+ { array_elements(my_locale_ab_month_names_sq_AL)-1, "", my_locale_ab_month_names_sq_AL, NULL };
+static TYPELIB my_locale_typelib_day_names_sq_AL =
+ { array_elements(my_locale_day_names_sq_AL)-1, "", my_locale_day_names_sq_AL, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_sq_AL =
+ { array_elements(my_locale_ab_day_names_sq_AL)-1, "", my_locale_ab_day_names_sq_AL, NULL };
+MY_LOCALE my_locale_sq_AL=
+ { "sq_AL", "Albanian - Albania", FALSE, &my_locale_typelib_month_names_sq_AL, &my_locale_typelib_ab_month_names_sq_AL, &my_locale_typelib_day_names_sq_AL, &my_locale_typelib_ab_day_names_sq_AL };
+/***** LOCALE END sq_AL *****/
+
+/***** LOCALE BEGIN sr_YU: Servian - Yugoslavia *****/
+static const char *my_locale_month_names_sr_YU[13] =
+ {"januar","februar","mart","april","maj","juni","juli","avgust","septembar","oktobar","novembar","decembar", NullS };
+static const char *my_locale_ab_month_names_sr_YU[13] =
+ {"jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_sr_YU[8] =
+ {"ponedeljak","utorak","sreda","četvrtak","petak","subota","nedelja", NullS };
+static const char *my_locale_ab_day_names_sr_YU[8] =
+ {"pon","uto","sre","čet","pet","sub","ned", NullS };
+static TYPELIB my_locale_typelib_month_names_sr_YU =
+ { array_elements(my_locale_month_names_sr_YU)-1, "", my_locale_month_names_sr_YU, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_sr_YU =
+ { array_elements(my_locale_ab_month_names_sr_YU)-1, "", my_locale_ab_month_names_sr_YU, NULL };
+static TYPELIB my_locale_typelib_day_names_sr_YU =
+ { array_elements(my_locale_day_names_sr_YU)-1, "", my_locale_day_names_sr_YU, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_sr_YU =
+ { array_elements(my_locale_ab_day_names_sr_YU)-1, "", my_locale_ab_day_names_sr_YU, NULL };
+MY_LOCALE my_locale_sr_YU=
+ { "sr_YU", "Servian - Yugoslavia", FALSE, &my_locale_typelib_month_names_sr_YU, &my_locale_typelib_ab_month_names_sr_YU, &my_locale_typelib_day_names_sr_YU, &my_locale_typelib_ab_day_names_sr_YU };
+/***** LOCALE END sr_YU *****/
+
+/***** LOCALE BEGIN sv_SE: Swedish - Sweden *****/
+static const char *my_locale_month_names_sv_SE[13] =
+ {"januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december", NullS };
+static const char *my_locale_ab_month_names_sv_SE[13] =
+ {"jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec", NullS };
+static const char *my_locale_day_names_sv_SE[8] =
+ {"måndag","tisdag","onsdag","torsdag","fredag","lördag","söndag", NullS };
+static const char *my_locale_ab_day_names_sv_SE[8] =
+ {"mån","tis","ons","tor","fre","lör","sön", NullS };
+static TYPELIB my_locale_typelib_month_names_sv_SE =
+ { array_elements(my_locale_month_names_sv_SE)-1, "", my_locale_month_names_sv_SE, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_sv_SE =
+ { array_elements(my_locale_ab_month_names_sv_SE)-1, "", my_locale_ab_month_names_sv_SE, NULL };
+static TYPELIB my_locale_typelib_day_names_sv_SE =
+ { array_elements(my_locale_day_names_sv_SE)-1, "", my_locale_day_names_sv_SE, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_sv_SE =
+ { array_elements(my_locale_ab_day_names_sv_SE)-1, "", my_locale_ab_day_names_sv_SE, NULL };
+MY_LOCALE my_locale_sv_SE=
+ { "sv_SE", "Swedish - Sweden", FALSE, &my_locale_typelib_month_names_sv_SE, &my_locale_typelib_ab_month_names_sv_SE, &my_locale_typelib_day_names_sv_SE, &my_locale_typelib_ab_day_names_sv_SE };
+/***** LOCALE END sv_SE *****/
+
+/***** LOCALE BEGIN ta_IN: Tamil - India *****/
+static const char *my_locale_month_names_ta_IN[13] =
+ {"ஜனவரி","பெப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்ட்","செப்டம்பர்","அக்டோபர்","நவம்பர்","டிசம்பர்r", NullS };
+static const char *my_locale_ab_month_names_ta_IN[13] =
+ {"ஜனவரி","பெப்ரவரி","மார்ச்","ஏப்ரல்","மே","ஜூன்","ஜூலை","ஆகஸ்ட்","செப்டம்பர்","அக்டோபர்","நவம்பர்","டிசம்பர்r", NullS };
+static const char *my_locale_day_names_ta_IN[8] =
+ {"திங்கள்","செவ்வாய்","புதன்","வியாழன்","வெள்ளி","சனி","ஞாயிறு", NullS };
+static const char *my_locale_ab_day_names_ta_IN[8] =
+ {"த","ச","ப","வ","வ","ச","ஞ", NullS };
+static TYPELIB my_locale_typelib_month_names_ta_IN =
+ { array_elements(my_locale_month_names_ta_IN)-1, "", my_locale_month_names_ta_IN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ta_IN =
+ { array_elements(my_locale_ab_month_names_ta_IN)-1, "", my_locale_ab_month_names_ta_IN, NULL };
+static TYPELIB my_locale_typelib_day_names_ta_IN =
+ { array_elements(my_locale_day_names_ta_IN)-1, "", my_locale_day_names_ta_IN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ta_IN =
+ { array_elements(my_locale_ab_day_names_ta_IN)-1, "", my_locale_ab_day_names_ta_IN, NULL };
+MY_LOCALE my_locale_ta_IN=
+ { "ta_IN", "Tamil - India", FALSE, &my_locale_typelib_month_names_ta_IN, &my_locale_typelib_ab_month_names_ta_IN, &my_locale_typelib_day_names_ta_IN, &my_locale_typelib_ab_day_names_ta_IN };
+/***** LOCALE END ta_IN *****/
+
+/***** LOCALE BEGIN te_IN: Telugu - India *****/
+static const char *my_locale_month_names_te_IN[13] =
+ {"జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్", NullS };
+static const char *my_locale_ab_month_names_te_IN[13] =
+ {"జనవరి","ఫిబ్రవరి","మార్చి","ఏప్రిల్","మే","జూన్","జూలై","ఆగస్టు","సెప్టెంబర్","అక్టోబర్","నవంబర్","డిసెంబర్", NullS };
+static const char *my_locale_day_names_te_IN[8] =
+ {"సోమవారం","మంగళవారం","బుధవారం","గురువారం","శుక్రవారం","శనివారం","ఆదివారం", NullS };
+static const char *my_locale_ab_day_names_te_IN[8] =
+ {"సోమ","మంగళ","బుధ","గురు","శుక్ర","శని","ఆది", NullS };
+static TYPELIB my_locale_typelib_month_names_te_IN =
+ { array_elements(my_locale_month_names_te_IN)-1, "", my_locale_month_names_te_IN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_te_IN =
+ { array_elements(my_locale_ab_month_names_te_IN)-1, "", my_locale_ab_month_names_te_IN, NULL };
+static TYPELIB my_locale_typelib_day_names_te_IN =
+ { array_elements(my_locale_day_names_te_IN)-1, "", my_locale_day_names_te_IN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_te_IN =
+ { array_elements(my_locale_ab_day_names_te_IN)-1, "", my_locale_ab_day_names_te_IN, NULL };
+MY_LOCALE my_locale_te_IN=
+ { "te_IN", "Telugu - India", FALSE, &my_locale_typelib_month_names_te_IN, &my_locale_typelib_ab_month_names_te_IN, &my_locale_typelib_day_names_te_IN, &my_locale_typelib_ab_day_names_te_IN };
+/***** LOCALE END te_IN *****/
+
+/***** LOCALE BEGIN th_TH: Thai - Thailand *****/
+static const char *my_locale_month_names_th_TH[13] =
+ {"มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม", NullS };
+static const char *my_locale_ab_month_names_th_TH[13] =
+ {"ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค.", NullS };
+static const char *my_locale_day_names_th_TH[8] =
+ {"จันทร์","อังคาร","พุธ","พฤหัสบดี","ศุกร์","เสาร์","อาทิตย์", NullS };
+static const char *my_locale_ab_day_names_th_TH[8] =
+ {"จ.","อ.","พ.","พฤ.","ศ.","ส.","อา.", NullS };
+static TYPELIB my_locale_typelib_month_names_th_TH =
+ { array_elements(my_locale_month_names_th_TH)-1, "", my_locale_month_names_th_TH, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_th_TH =
+ { array_elements(my_locale_ab_month_names_th_TH)-1, "", my_locale_ab_month_names_th_TH, NULL };
+static TYPELIB my_locale_typelib_day_names_th_TH =
+ { array_elements(my_locale_day_names_th_TH)-1, "", my_locale_day_names_th_TH, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_th_TH =
+ { array_elements(my_locale_ab_day_names_th_TH)-1, "", my_locale_ab_day_names_th_TH, NULL };
+MY_LOCALE my_locale_th_TH=
+ { "th_TH", "Thai - Thailand", FALSE, &my_locale_typelib_month_names_th_TH, &my_locale_typelib_ab_month_names_th_TH, &my_locale_typelib_day_names_th_TH, &my_locale_typelib_ab_day_names_th_TH };
+/***** LOCALE END th_TH *****/
+
+/***** LOCALE BEGIN tr_TR: Turkish - Turkey *****/
+static const char *my_locale_month_names_tr_TR[13] =
+ {"Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık", NullS };
+static const char *my_locale_ab_month_names_tr_TR[13] =
+ {"Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara", NullS };
+static const char *my_locale_day_names_tr_TR[8] =
+ {"Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi","Pazar", NullS };
+static const char *my_locale_ab_day_names_tr_TR[8] =
+ {"Pzt","Sal","Çrş","Prş","Cum","Cts","Paz", NullS };
+static TYPELIB my_locale_typelib_month_names_tr_TR =
+ { array_elements(my_locale_month_names_tr_TR)-1, "", my_locale_month_names_tr_TR, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_tr_TR =
+ { array_elements(my_locale_ab_month_names_tr_TR)-1, "", my_locale_ab_month_names_tr_TR, NULL };
+static TYPELIB my_locale_typelib_day_names_tr_TR =
+ { array_elements(my_locale_day_names_tr_TR)-1, "", my_locale_day_names_tr_TR, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_tr_TR =
+ { array_elements(my_locale_ab_day_names_tr_TR)-1, "", my_locale_ab_day_names_tr_TR, NULL };
+MY_LOCALE my_locale_tr_TR=
+ { "tr_TR", "Turkish - Turkey", FALSE, &my_locale_typelib_month_names_tr_TR, &my_locale_typelib_ab_month_names_tr_TR, &my_locale_typelib_day_names_tr_TR, &my_locale_typelib_ab_day_names_tr_TR };
+/***** LOCALE END tr_TR *****/
+
+/***** LOCALE BEGIN uk_UA: Ukrainian - Ukraine *****/
+static const char *my_locale_month_names_uk_UA[13] =
+ {"Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень", NullS };
+static const char *my_locale_ab_month_names_uk_UA[13] =
+ {"Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру", NullS };
+static const char *my_locale_day_names_uk_UA[8] =
+ {"Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота","Неділя", NullS };
+static const char *my_locale_ab_day_names_uk_UA[8] =
+ {"Пнд","Втр","Срд","Чтв","Птн","Сбт","Ндл", NullS };
+static TYPELIB my_locale_typelib_month_names_uk_UA =
+ { array_elements(my_locale_month_names_uk_UA)-1, "", my_locale_month_names_uk_UA, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_uk_UA =
+ { array_elements(my_locale_ab_month_names_uk_UA)-1, "", my_locale_ab_month_names_uk_UA, NULL };
+static TYPELIB my_locale_typelib_day_names_uk_UA =
+ { array_elements(my_locale_day_names_uk_UA)-1, "", my_locale_day_names_uk_UA, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_uk_UA =
+ { array_elements(my_locale_ab_day_names_uk_UA)-1, "", my_locale_ab_day_names_uk_UA, NULL };
+MY_LOCALE my_locale_uk_UA=
+ { "uk_UA", "Ukrainian - Ukraine", FALSE, &my_locale_typelib_month_names_uk_UA, &my_locale_typelib_ab_month_names_uk_UA, &my_locale_typelib_day_names_uk_UA, &my_locale_typelib_ab_day_names_uk_UA };
+/***** LOCALE END uk_UA *****/
+
+/***** LOCALE BEGIN ur_PK: Urdu - Pakistan *****/
+static const char *my_locale_month_names_ur_PK[13] =
+ {"جنوري","فروري","مارچ","اپريل","مٓی","جون","جولاي","اگست","ستمبر","اكتوبر","نومبر","دسمبر", NullS };
+static const char *my_locale_ab_month_names_ur_PK[13] =
+ {"جنوري","فروري","مارچ","اپريل","مٓی","جون","جولاي","اگست","ستمبر","اكتوبر","نومبر","دسمبر", NullS };
+static const char *my_locale_day_names_ur_PK[8] =
+ {"پير","منگل","بدھ","جمعرات","جمعه","هفته","اتوار", NullS };
+static const char *my_locale_ab_day_names_ur_PK[8] =
+ {"پير","منگل","بدھ","جمعرات","جمعه","هفته","اتوار", NullS };
+static TYPELIB my_locale_typelib_month_names_ur_PK =
+ { array_elements(my_locale_month_names_ur_PK)-1, "", my_locale_month_names_ur_PK, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_ur_PK =
+ { array_elements(my_locale_ab_month_names_ur_PK)-1, "", my_locale_ab_month_names_ur_PK, NULL };
+static TYPELIB my_locale_typelib_day_names_ur_PK =
+ { array_elements(my_locale_day_names_ur_PK)-1, "", my_locale_day_names_ur_PK, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_ur_PK =
+ { array_elements(my_locale_ab_day_names_ur_PK)-1, "", my_locale_ab_day_names_ur_PK, NULL };
+MY_LOCALE my_locale_ur_PK=
+ { "ur_PK", "Urdu - Pakistan", FALSE, &my_locale_typelib_month_names_ur_PK, &my_locale_typelib_ab_month_names_ur_PK, &my_locale_typelib_day_names_ur_PK, &my_locale_typelib_ab_day_names_ur_PK };
+/***** LOCALE END ur_PK *****/
+
+/***** LOCALE BEGIN vi_VN: Vietnamese - Vietnam *****/
+static const char *my_locale_month_names_vi_VN[13] =
+ {"Tháng một","Tháng hai","Tháng ba","Tháng tư","Tháng năm","Tháng sáu","Tháng bảy","Tháng tám","Tháng chín","Tháng mười","Tháng mười một","Tháng mười hai", NullS };
+static const char *my_locale_ab_month_names_vi_VN[13] =
+ {"Thg 1","Thg 2","Thg 3","Thg 4","Thg 5","Thg 6","Thg 7","Thg 8","Thg 9","Thg 10","Thg 11","Thg 12", NullS };
+static const char *my_locale_day_names_vi_VN[8] =
+ {"Thứ hai ","Thứ ba ","Thứ tư ","Thứ năm ","Thứ sáu ","Thứ bảy ","Chủ nhật ", NullS };
+static const char *my_locale_ab_day_names_vi_VN[8] =
+ {"Th 2 ","Th 3 ","Th 4 ","Th 5 ","Th 6 ","Th 7 ","CN ", NullS };
+static TYPELIB my_locale_typelib_month_names_vi_VN =
+ { array_elements(my_locale_month_names_vi_VN)-1, "", my_locale_month_names_vi_VN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_vi_VN =
+ { array_elements(my_locale_ab_month_names_vi_VN)-1, "", my_locale_ab_month_names_vi_VN, NULL };
+static TYPELIB my_locale_typelib_day_names_vi_VN =
+ { array_elements(my_locale_day_names_vi_VN)-1, "", my_locale_day_names_vi_VN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_vi_VN =
+ { array_elements(my_locale_ab_day_names_vi_VN)-1, "", my_locale_ab_day_names_vi_VN, NULL };
+MY_LOCALE my_locale_vi_VN=
+ { "vi_VN", "Vietnamese - Vietnam", FALSE, &my_locale_typelib_month_names_vi_VN, &my_locale_typelib_ab_month_names_vi_VN, &my_locale_typelib_day_names_vi_VN, &my_locale_typelib_ab_day_names_vi_VN };
+/***** LOCALE END vi_VN *****/
+
+/***** LOCALE BEGIN zh_CN: Chinese - Peoples Republic of China *****/
+static const char *my_locale_month_names_zh_CN[13] =
+ {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月", NullS };
+static const char *my_locale_ab_month_names_zh_CN[13] =
+ {" 1月"," 2月"," 3月"," 4月"," 5月"," 6月"," 7月"," 8月"," 9月","10月","11月","12月", NullS };
+static const char *my_locale_day_names_zh_CN[8] =
+ {"星期一","星期二","星期三","星期四","星期五","星期六","星期日", NullS };
+static const char *my_locale_ab_day_names_zh_CN[8] =
+ {"一","二","三","四","五","六","日", NullS };
+static TYPELIB my_locale_typelib_month_names_zh_CN =
+ { array_elements(my_locale_month_names_zh_CN)-1, "", my_locale_month_names_zh_CN, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_zh_CN =
+ { array_elements(my_locale_ab_month_names_zh_CN)-1, "", my_locale_ab_month_names_zh_CN, NULL };
+static TYPELIB my_locale_typelib_day_names_zh_CN =
+ { array_elements(my_locale_day_names_zh_CN)-1, "", my_locale_day_names_zh_CN, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_zh_CN =
+ { array_elements(my_locale_ab_day_names_zh_CN)-1, "", my_locale_ab_day_names_zh_CN, NULL };
+MY_LOCALE my_locale_zh_CN=
+ { "zh_CN", "Chinese - Peoples Republic of China", FALSE, &my_locale_typelib_month_names_zh_CN, &my_locale_typelib_ab_month_names_zh_CN, &my_locale_typelib_day_names_zh_CN, &my_locale_typelib_ab_day_names_zh_CN };
+/***** LOCALE END zh_CN *****/
+
+/***** LOCALE BEGIN zh_TW: Chinese - Taiwan *****/
+static const char *my_locale_month_names_zh_TW[13] =
+ {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月", NullS };
+static const char *my_locale_ab_month_names_zh_TW[13] =
+ {" 1月"," 2月"," 3月"," 4月"," 5月"," 6月"," 7月"," 8月"," 9月","10月","11月","12月", NullS };
+static const char *my_locale_day_names_zh_TW[8] =
+ {"週一","週二","週三","週四","週五","週六","週日", NullS };
+static const char *my_locale_ab_day_names_zh_TW[8] =
+ {"一","二","三","四","五","六","日", NullS };
+static TYPELIB my_locale_typelib_month_names_zh_TW =
+ { array_elements(my_locale_month_names_zh_TW)-1, "", my_locale_month_names_zh_TW, NULL };
+static TYPELIB my_locale_typelib_ab_month_names_zh_TW =
+ { array_elements(my_locale_ab_month_names_zh_TW)-1, "", my_locale_ab_month_names_zh_TW, NULL };
+static TYPELIB my_locale_typelib_day_names_zh_TW =
+ { array_elements(my_locale_day_names_zh_TW)-1, "", my_locale_day_names_zh_TW, NULL };
+static TYPELIB my_locale_typelib_ab_day_names_zh_TW =
+ { array_elements(my_locale_ab_day_names_zh_TW)-1, "", my_locale_ab_day_names_zh_TW, NULL };
+MY_LOCALE my_locale_zh_TW=
+ { "zh_TW", "Chinese - Taiwan", FALSE, &my_locale_typelib_month_names_zh_TW, &my_locale_typelib_ab_month_names_zh_TW, &my_locale_typelib_day_names_zh_TW, &my_locale_typelib_ab_day_names_zh_TW };
+/***** LOCALE END zh_TW *****/
+
+/***** LOCALE BEGIN ar_DZ: Arabic - Algeria *****/
+MY_LOCALE my_locale_ar_DZ=
+ { "ar_DZ", "Arabic - Algeria", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_DZ *****/
+
+/***** LOCALE BEGIN ar_EG: Arabic - Egypt *****/
+MY_LOCALE my_locale_ar_EG=
+ { "ar_EG", "Arabic - Egypt", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_EG *****/
+
+/***** LOCALE BEGIN ar_IN: Arabic - Iran *****/
+MY_LOCALE my_locale_ar_IN=
+ { "ar_IN", "Arabic - Iran", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_IN *****/
+
+/***** LOCALE BEGIN ar_IQ: Arabic - Iraq *****/
+MY_LOCALE my_locale_ar_IQ=
+ { "ar_IQ", "Arabic - Iraq", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_IQ *****/
+
+/***** LOCALE BEGIN ar_KW: Arabic - Kuwait *****/
+MY_LOCALE my_locale_ar_KW=
+ { "ar_KW", "Arabic - Kuwait", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_KW *****/
+
+/***** LOCALE BEGIN ar_LB: Arabic - Lebanon *****/
+MY_LOCALE my_locale_ar_LB=
+ { "ar_LB", "Arabic - Lebanon", FALSE, &my_locale_typelib_month_names_ar_JO, &my_locale_typelib_ab_month_names_ar_JO, &my_locale_typelib_day_names_ar_JO, &my_locale_typelib_ab_day_names_ar_JO };
+/***** LOCALE END ar_LB *****/
+
+/***** LOCALE BEGIN ar_LY: Arabic - Libya *****/
+MY_LOCALE my_locale_ar_LY=
+ { "ar_LY", "Arabic - Libya", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_LY *****/
+
+/***** LOCALE BEGIN ar_MA: Arabic - Morocco *****/
+MY_LOCALE my_locale_ar_MA=
+ { "ar_MA", "Arabic - Morocco", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_MA *****/
+
+/***** LOCALE BEGIN ar_OM: Arabic - Oman *****/
+MY_LOCALE my_locale_ar_OM=
+ { "ar_OM", "Arabic - Oman", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_OM *****/
+
+/***** LOCALE BEGIN ar_QA: Arabic - Qatar *****/
+MY_LOCALE my_locale_ar_QA=
+ { "ar_QA", "Arabic - Qatar", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_QA *****/
+
+/***** LOCALE BEGIN ar_SD: Arabic - Sudan *****/
+MY_LOCALE my_locale_ar_SD=
+ { "ar_SD", "Arabic - Sudan", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_SD *****/
+
+/***** LOCALE BEGIN ar_TN: Arabic - Tunisia *****/
+MY_LOCALE my_locale_ar_TN=
+ { "ar_TN", "Arabic - Tunisia", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_TN *****/
+
+/***** LOCALE BEGIN ar_YE: Arabic - Yemen *****/
+MY_LOCALE my_locale_ar_YE=
+ { "ar_YE", "Arabic - Yemen", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH };
+/***** LOCALE END ar_YE *****/
+
+/***** LOCALE BEGIN de_BE: German - Belgium *****/
+MY_LOCALE my_locale_de_BE=
+ { "de_BE", "German - Belgium", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE };
+/***** LOCALE END de_BE *****/
+
+/***** LOCALE BEGIN de_CH: German - Switzerland *****/
+MY_LOCALE my_locale_de_CH=
+ { "de_CH", "German - Switzerland", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE };
+/***** LOCALE END de_CH *****/
+
+/***** LOCALE BEGIN de_LU: German - Luxembourg *****/
+MY_LOCALE my_locale_de_LU=
+ { "de_LU", "German - Luxembourg", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE };
+/***** LOCALE END de_LU *****/
+
+/***** LOCALE BEGIN en_AU: English - Australia *****/
+MY_LOCALE my_locale_en_AU=
+ { "en_AU", "English - Australia", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_AU *****/
+
+/***** LOCALE BEGIN en_CA: English - Canada *****/
+MY_LOCALE my_locale_en_CA=
+ { "en_CA", "English - Canada", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_CA *****/
+
+/***** LOCALE BEGIN en_GB: English - United Kingdom *****/
+MY_LOCALE my_locale_en_GB=
+ { "en_GB", "English - United Kingdom", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_GB *****/
+
+/***** LOCALE BEGIN en_IN: English - India *****/
+MY_LOCALE my_locale_en_IN=
+ { "en_IN", "English - India", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_IN *****/
+
+/***** LOCALE BEGIN en_NZ: English - New Zealand *****/
+MY_LOCALE my_locale_en_NZ=
+ { "en_NZ", "English - New Zealand", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_NZ *****/
+
+/***** LOCALE BEGIN en_PH: English - Philippines *****/
+MY_LOCALE my_locale_en_PH=
+ { "en_PH", "English - Philippines", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_PH *****/
+
+/***** LOCALE BEGIN en_ZA: English - South Africa *****/
+MY_LOCALE my_locale_en_ZA=
+ { "en_ZA", "English - South Africa", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_ZA *****/
+
+/***** LOCALE BEGIN en_ZW: English - Zimbabwe *****/
+MY_LOCALE my_locale_en_ZW=
+ { "en_ZW", "English - Zimbabwe", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US };
+/***** LOCALE END en_ZW *****/
+
+/***** LOCALE BEGIN es_AR: Spanish - Argentina *****/
+MY_LOCALE my_locale_es_AR=
+ { "es_AR", "Spanish - Argentina", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_AR *****/
+
+/***** LOCALE BEGIN es_BO: Spanish - Bolivia *****/
+MY_LOCALE my_locale_es_BO=
+ { "es_BO", "Spanish - Bolivia", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_BO *****/
+
+/***** LOCALE BEGIN es_CL: Spanish - Chile *****/
+MY_LOCALE my_locale_es_CL=
+ { "es_CL", "Spanish - Chile", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_CL *****/
+
+/***** LOCALE BEGIN es_CO: Spanish - Columbia *****/
+MY_LOCALE my_locale_es_CO=
+ { "es_CO", "Spanish - Columbia", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_CO *****/
+
+/***** LOCALE BEGIN es_CR: Spanish - Costa Rica *****/
+MY_LOCALE my_locale_es_CR=
+ { "es_CR", "Spanish - Costa Rica", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_CR *****/
+
+/***** LOCALE BEGIN es_DO: Spanish - Dominican Republic *****/
+MY_LOCALE my_locale_es_DO=
+ { "es_DO", "Spanish - Dominican Republic", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_DO *****/
+
+/***** LOCALE BEGIN es_EC: Spanish - Ecuador *****/
+MY_LOCALE my_locale_es_EC=
+ { "es_EC", "Spanish - Ecuador", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_EC *****/
+
+/***** LOCALE BEGIN es_GT: Spanish - Guatemala *****/
+MY_LOCALE my_locale_es_GT=
+ { "es_GT", "Spanish - Guatemala", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_GT *****/
+
+/***** LOCALE BEGIN es_HN: Spanish - Honduras *****/
+MY_LOCALE my_locale_es_HN=
+ { "es_HN", "Spanish - Honduras", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_HN *****/
+
+/***** LOCALE BEGIN es_MX: Spanish - Mexico *****/
+MY_LOCALE my_locale_es_MX=
+ { "es_MX", "Spanish - Mexico", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_MX *****/
+
+/***** LOCALE BEGIN es_NI: Spanish - Nicaragua *****/
+MY_LOCALE my_locale_es_NI=
+ { "es_NI", "Spanish - Nicaragua", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_NI *****/
+
+/***** LOCALE BEGIN es_PA: Spanish - Panama *****/
+MY_LOCALE my_locale_es_PA=
+ { "es_PA", "Spanish - Panama", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_PA *****/
+
+/***** LOCALE BEGIN es_PE: Spanish - Peru *****/
+MY_LOCALE my_locale_es_PE=
+ { "es_PE", "Spanish - Peru", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_PE *****/
+
+/***** LOCALE BEGIN es_PR: Spanish - Puerto Rico *****/
+MY_LOCALE my_locale_es_PR=
+ { "es_PR", "Spanish - Puerto Rico", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_PR *****/
+
+/***** LOCALE BEGIN es_PY: Spanish - Paraguay *****/
+MY_LOCALE my_locale_es_PY=
+ { "es_PY", "Spanish - Paraguay", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_PY *****/
+
+/***** LOCALE BEGIN es_SV: Spanish - El Salvador *****/
+MY_LOCALE my_locale_es_SV=
+ { "es_SV", "Spanish - El Salvador", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_SV *****/
+
+/***** LOCALE BEGIN es_US: Spanish - United States *****/
+MY_LOCALE my_locale_es_US=
+ { "es_US", "Spanish - United States", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_US *****/
+
+/***** LOCALE BEGIN es_UY: Spanish - Uruguay *****/
+MY_LOCALE my_locale_es_UY=
+ { "es_UY", "Spanish - Uruguay", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_UY *****/
+
+/***** LOCALE BEGIN es_VE: Spanish - Venezuela *****/
+MY_LOCALE my_locale_es_VE=
+ { "es_VE", "Spanish - Venezuela", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES };
+/***** LOCALE END es_VE *****/
+
+/***** LOCALE BEGIN fr_BE: French - Belgium *****/
+MY_LOCALE my_locale_fr_BE=
+ { "fr_BE", "French - Belgium", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR };
+/***** LOCALE END fr_BE *****/
+
+/***** LOCALE BEGIN fr_CA: French - Canada *****/
+MY_LOCALE my_locale_fr_CA=
+ { "fr_CA", "French - Canada", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR };
+/***** LOCALE END fr_CA *****/
+
+/***** LOCALE BEGIN fr_CH: French - Switzerland *****/
+MY_LOCALE my_locale_fr_CH=
+ { "fr_CH", "French - Switzerland", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR };
+/***** LOCALE END fr_CH *****/
+
+/***** LOCALE BEGIN fr_LU: French - Luxembourg *****/
+MY_LOCALE my_locale_fr_LU=
+ { "fr_LU", "French - Luxembourg", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR };
+/***** LOCALE END fr_LU *****/
+
+/***** LOCALE BEGIN it_IT: Italian - Italy *****/
+MY_LOCALE my_locale_it_IT=
+ { "it_IT", "Italian - Italy", FALSE, &my_locale_typelib_month_names_it_CH, &my_locale_typelib_ab_month_names_it_CH, &my_locale_typelib_day_names_it_CH, &my_locale_typelib_ab_day_names_it_CH };
+/***** LOCALE END it_IT *****/
+
+/***** LOCALE BEGIN nl_BE: Dutch - Belgium *****/
+MY_LOCALE my_locale_nl_BE=
+ { "nl_BE", "Dutch - Belgium", TRUE, &my_locale_typelib_month_names_nl_NL, &my_locale_typelib_ab_month_names_nl_NL, &my_locale_typelib_day_names_nl_NL, &my_locale_typelib_ab_day_names_nl_NL };
+/***** LOCALE END nl_BE *****/
+
+/***** LOCALE BEGIN no_NO: Norwegian - Norway *****/
+MY_LOCALE my_locale_no_NO=
+ { "no_NO", "Norwegian - Norway", FALSE, &my_locale_typelib_month_names_nb_NO, &my_locale_typelib_ab_month_names_nb_NO, &my_locale_typelib_day_names_nb_NO, &my_locale_typelib_ab_day_names_nb_NO };
+/***** LOCALE END no_NO *****/
+
+/***** LOCALE BEGIN sv_FI: Swedish - Finland *****/
+MY_LOCALE my_locale_sv_FI=
+ { "sv_FI", "Swedish - Finland", FALSE, &my_locale_typelib_month_names_sv_SE, &my_locale_typelib_ab_month_names_sv_SE, &my_locale_typelib_day_names_sv_SE, &my_locale_typelib_ab_day_names_sv_SE };
+/***** LOCALE END sv_FI *****/
+
+/***** LOCALE BEGIN zh_HK: Chinese - Hong Kong SAR *****/
+MY_LOCALE my_locale_zh_HK=
+ { "zh_HK", "Chinese - Hong Kong SAR", FALSE, &my_locale_typelib_month_names_zh_CN, &my_locale_typelib_ab_month_names_zh_CN, &my_locale_typelib_day_names_zh_CN, &my_locale_typelib_ab_day_names_zh_CN };
+/***** LOCALE END zh_HK *****/
+
+MY_LOCALE *my_locales[]=
+ {
+ &my_locale_en_US,
+ &my_locale_en_GB,
+ &my_locale_ja_JP,
+ &my_locale_sv_SE,
+ &my_locale_de_DE,
+ &my_locale_fr_FR,
+ &my_locale_ar_AE,
+ &my_locale_ar_BH,
+ &my_locale_ar_JO,
+ &my_locale_ar_SA,
+ &my_locale_ar_SY,
+ &my_locale_be_BY,
+ &my_locale_bg_BG,
+ &my_locale_ca_ES,
+ &my_locale_cs_CZ,
+ &my_locale_da_DK,
+ &my_locale_de_AT,
+ &my_locale_es_ES,
+ &my_locale_et_EE,
+ &my_locale_eu_ES,
+ &my_locale_fi_FI,
+ &my_locale_fo_FO,
+ &my_locale_gl_ES,
+ &my_locale_gu_IN,
+ &my_locale_he_IL,
+ &my_locale_hi_IN,
+ &my_locale_hr_HR,
+ &my_locale_hu_HU,
+ &my_locale_id_ID,
+ &my_locale_is_IS,
+ &my_locale_it_CH,
+ &my_locale_ko_KR,
+ &my_locale_lt_LT,
+ &my_locale_lv_LV,
+ &my_locale_mk_MK,
+ &my_locale_mn_MN,
+ &my_locale_ms_MY,
+ &my_locale_nb_NO,
+ &my_locale_nl_NL,
+ &my_locale_pl_PL,
+ &my_locale_pt_BR,
+ &my_locale_pt_PT,
+ &my_locale_ro_RO,
+ &my_locale_ru_RU,
+ &my_locale_ru_UA,
+ &my_locale_sk_SK,
+ &my_locale_sl_SI,
+ &my_locale_sq_AL,
+ &my_locale_sr_YU,
+ &my_locale_ta_IN,
+ &my_locale_te_IN,
+ &my_locale_th_TH,
+ &my_locale_tr_TR,
+ &my_locale_uk_UA,
+ &my_locale_ur_PK,
+ &my_locale_vi_VN,
+ &my_locale_zh_CN,
+ &my_locale_zh_TW,
+ &my_locale_ar_DZ,
+ &my_locale_ar_EG,
+ &my_locale_ar_IN,
+ &my_locale_ar_IQ,
+ &my_locale_ar_KW,
+ &my_locale_ar_LB,
+ &my_locale_ar_LY,
+ &my_locale_ar_MA,
+ &my_locale_ar_OM,
+ &my_locale_ar_QA,
+ &my_locale_ar_SD,
+ &my_locale_ar_TN,
+ &my_locale_ar_YE,
+ &my_locale_de_BE,
+ &my_locale_de_CH,
+ &my_locale_de_LU,
+ &my_locale_en_AU,
+ &my_locale_en_CA,
+ &my_locale_en_IN,
+ &my_locale_en_NZ,
+ &my_locale_en_PH,
+ &my_locale_en_ZA,
+ &my_locale_en_ZW,
+ &my_locale_es_AR,
+ &my_locale_es_BO,
+ &my_locale_es_CL,
+ &my_locale_es_CO,
+ &my_locale_es_CR,
+ &my_locale_es_DO,
+ &my_locale_es_EC,
+ &my_locale_es_GT,
+ &my_locale_es_HN,
+ &my_locale_es_MX,
+ &my_locale_es_NI,
+ &my_locale_es_PA,
+ &my_locale_es_PE,
+ &my_locale_es_PR,
+ &my_locale_es_PY,
+ &my_locale_es_SV,
+ &my_locale_es_US,
+ &my_locale_es_UY,
+ &my_locale_es_VE,
+ &my_locale_fr_BE,
+ &my_locale_fr_CA,
+ &my_locale_fr_CH,
+ &my_locale_fr_LU,
+ &my_locale_it_IT,
+ &my_locale_nl_BE,
+ &my_locale_no_NO,
+ &my_locale_sv_FI,
+ &my_locale_zh_HK,
+ NULL
+ };
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 9a3b1e1234e..b868cd31eac 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1250,6 +1250,12 @@ pthread_handler_t handle_bootstrap(void *arg)
thd->version=refresh_version;
thd->security_ctx->priv_user=
thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
+ /*
+ Make the "client" handle multiple results. This is necessary
+ to enable stored procedures with SELECTs and Dynamic SQL
+ in init-file.
+ */
+ thd->client_capabilities|= CLIENT_MULTI_RESULTS;
buff= (char*) thd->net.buff;
thd->init_for_queries();
@@ -2365,7 +2371,7 @@ static void reset_one_shot_variables(THD *thd)
/*
- Execute command saved in thd and current_lex->sql_command
+ Execute command saved in thd and lex->sql_command
SYNOPSIS
mysql_execute_command()
@@ -3057,6 +3063,12 @@ end_with_restore_list:
}
}
/* Don't yet allow changing of symlinks with ALTER TABLE */
+ if (lex->create_info.data_file_name)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "DATA DIRECTORY option ignored");
+ if (lex->create_info.index_file_name)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "INDEX DIRECTORY option ignored");
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
@@ -3077,8 +3089,7 @@ end_with_restore_list:
lex->key_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
- lex->duplicates, lex->ignore, &lex->alter_info,
- 1);
+ lex->ignore, &lex->alter_info, 1);
}
break;
}
@@ -3451,7 +3462,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables=
- (TABLE_LIST *)thd->lex->auxilliary_table_list.first;
+ (TABLE_LIST *)thd->lex->auxiliary_table_list.first;
multi_delete *result;
if (!thd->locked_tables &&
@@ -3887,11 +3898,13 @@ end_with_restore_list:
if (thd->security_ctx->user) // If not replication
{
- LEX_USER *user;
+ LEX_USER *user, *tmp_user;
List_iterator <LEX_USER> user_list(lex->users_list);
- while ((user= user_list++))
+ while ((tmp_user= user_list++))
{
+ if (!(user= get_current_user(thd, tmp_user)))
+ goto error;
if (specialflag & SPECIAL_NO_RESOLVE &&
hostname_requires_resolving(user->host.str))
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -3973,9 +3986,13 @@ end_with_restore_list:
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
- LEX_USER *user;
- while ((user=str_list++))
+ LEX_USER *user, *tmp_user;
+ while ((tmp_user=str_list++))
+ {
+ if (!(user= get_current_user(thd, tmp_user)))
+ goto error;
reset_mqh(user);
+ }
}
}
}
@@ -4030,13 +4047,18 @@ end_with_restore_list:
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_GRANTS:
+ {
+ LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
+ if (!grant_user)
+ goto error;
if ((thd->security_ctx->priv_user &&
- !strcmp(thd->security_ctx->priv_user, lex->grant_user->user.str)) ||
+ !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
!check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
{
- res = mysql_show_grants(thd,lex->grant_user);
+ res = mysql_show_grants(thd, grant_user);
}
break;
+ }
#endif
case SQLCOM_HA_OPEN:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -5525,7 +5547,7 @@ bool check_stack_overrun(THD *thd, long margin,
bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
{
- LEX *lex=current_lex;
+ LEX *lex= current_thd->lex;
ulong old_info=0;
if ((uint) *yystacksize >= MY_YACC_MAX)
return 1;
@@ -5740,7 +5762,7 @@ void mysql_init_multi_delete(LEX *lex)
mysql_init_select(lex);
lex->select_lex.select_limit= 0;
lex->unit.select_limit_cnt= HA_POS_ERROR;
- lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list);
+ lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
@@ -5962,7 +5984,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
void store_position_for_column(const char *name)
{
- current_lex->last_field->after=my_const_cast(char*) (name);
+ current_thd->lex->last_field->after=my_const_cast(char*) (name);
}
bool
@@ -7000,7 +7022,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
- DUP_ERROR, 0, &alter_info, 1));
+ 0, &alter_info, 1));
}
@@ -7018,7 +7040,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
- DUP_ERROR, 0, alter_info, 1));
+ 0, alter_info, 1));
}
@@ -7119,7 +7141,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
{
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
- (TABLE_LIST *)thd->lex->auxilliary_table_list.first;
+ (TABLE_LIST *)thd->lex->auxiliary_table_list.first;
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
DBUG_ENTER("multi_delete_precheck");
@@ -7173,7 +7195,7 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
lex->table_count= 0;
- for (target_tbl= (TABLE_LIST *)lex->auxilliary_table_list.first;
+ for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first;
target_tbl; target_tbl= target_tbl->next_local)
{
lex->table_count++;
@@ -7479,3 +7501,34 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
return definer;
}
+
+
+/*
+ Retuns information about user or current user.
+
+ SYNOPSIS
+ get_current_user()
+ thd [in] thread handler
+ user [in] user
+
+ RETURN
+ On success, return a valid pointer to initialized
+ LEX_USER, which contains user information.
+ On error, return 0.
+*/
+
+LEX_USER *get_current_user(THD *thd, LEX_USER *user)
+{
+ LEX_USER *curr_user;
+ if (!user->user.str) // current_user
+ {
+ if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER));
+ return 0;
+ }
+ get_default_definer(thd, curr_user);
+ return curr_user;
+ }
+ return user;
+}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 103a0b9e54e..a2f73ac9989 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2128,28 +2128,21 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
they have their own table list).
*/
for (TABLE_LIST *tables= lex->query_tables;
- tables;
- tables= tables->next_global)
+ tables;
+ tables= tables->next_global)
{
- /*
- Reset old pointers to TABLEs: they are not valid since the tables
- were closed in the end of previous prepare or execute call.
- */
- tables->table= 0;
- /* Reset is_schema_table_processed value(needed for I_S tables */
- tables->is_schema_table_processed= FALSE;
-
- TABLE_LIST *embedded; /* The table at the current level of nesting. */
- TABLE_LIST *embedding= tables; /* The parent nested table reference. */
- do
- {
- embedded= embedding;
- if (embedded->prep_on_expr)
- embedded->on_expr= embedded->prep_on_expr->copy_andor_structure(thd);
- embedding= embedded->embedding;
- }
- while (embedding &&
- embedding->nested_join->join_list.head() == embedded);
+ tables->reinit_before_use(thd);
+ }
+ /*
+ Cleanup of the special case of DELETE t1, t2 FROM t1, t2, t3 ...
+ (multi-delete). We do a full clean up, although at the moment all we
+ need to clean in the tables of MULTI-DELETE list is 'table' member.
+ */
+ for (TABLE_LIST *tables= (TABLE_LIST*) lex->auxiliary_table_list.first;
+ tables;
+ tables= tables->next_global)
+ {
+ tables->reinit_before_use(thd);
}
lex->current_select= &lex->select_lex;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4899c1e16a3..400342854a6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -163,6 +163,10 @@ static Item* part_of_refkey(TABLE *form,Field *field);
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes);
+static bool list_contains_unique_index(TABLE *table,
+ bool (*find_func) (Field *, void *), void *data);
+static bool find_field_in_item_list (Field *field, void *data);
+static bool find_field_in_order_list (Field *field, void *data);
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
ha_rows filesort_limit, ha_rows select_limit);
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
@@ -858,6 +862,40 @@ JOIN::optimize()
if (old_group_list && !group_list)
select_distinct= 0;
}
+ /*
+ Check if we can optimize away GROUP BY/DISTINCT.
+ We can do that if there are no aggregate functions and the
+ fields in DISTINCT clause (if present) and/or columns in GROUP BY
+ (if present) contain direct references to all key parts of
+ an unique index (in whatever order).
+ Note that the unique keys for DISTINCT and GROUP BY should not
+ be the same (as long as they are unique).
+
+ The FROM clause must contain a single non-constant table.
+ */
+ if (tables - const_tables == 1 && (group_list || select_distinct) &&
+ !tmp_table_param.sum_func_count &&
+ (!join_tab[const_tables].select ||
+ !join_tab[const_tables].select->quick ||
+ join_tab[const_tables].select->quick->get_type() !=
+ QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
+ {
+ if (group_list &&
+ list_contains_unique_index(join_tab[const_tables].table,
+ find_field_in_order_list,
+ (void *) group_list))
+ {
+ group_list= 0;
+ group= 0;
+ }
+ if (select_distinct &&
+ list_contains_unique_index(join_tab[const_tables].table,
+ find_field_in_item_list,
+ (void *) &fields_list))
+ {
+ select_distinct= 0;
+ }
+ }
if (!group_list && group)
{
order=0; // The output has only one row
@@ -7979,7 +8017,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field,
org_field->field_name, table,
org_field->charset());
else
- new_field= org_field->new_field(thd->mem_root, table);
+ new_field= org_field->new_field(thd->mem_root, table,
+ table == org_field->table);
if (new_field)
{
if (item)
@@ -11209,6 +11248,140 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
return best;
}
+
+/*
+ Check if GROUP BY/DISTINCT can be optimized away because the set is
+ already known to be distinct.
+
+ SYNOPSIS
+ list_contains_unique_index ()
+ table The table to operate on.
+ find_func function to iterate over the list and search
+ for a field
+
+ DESCRIPTION
+ Used in removing the GROUP BY/DISTINCT of the following types of
+ statements:
+ SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref>
+ [GROUP BY <unique_key_cols>,...]
+
+ If (a,b,c is distinct)
+ then <any combination of a,b,c>,{whatever} is also distinct
+
+ This function checks if all the key parts of any of the unique keys
+ of the table are referenced by a list : either the select list
+ through find_field_in_item_list or GROUP BY list through
+ find_field_in_order_list.
+ If the above holds then we can safely remove the GROUP BY/DISTINCT,
+ as no result set can be more distinct than an unique key.
+
+ RETURN VALUE
+ 1 found
+ 0 not found.
+*/
+
+static bool
+list_contains_unique_index(TABLE *table,
+ bool (*find_func) (Field *, void *), void *data)
+{
+ for (uint keynr= 0; keynr < table->s->keys; keynr++)
+ {
+ if (keynr == table->s->primary_key ||
+ (table->key_info[keynr].flags & HA_NOSAME))
+ {
+ KEY *keyinfo= table->key_info + keynr;
+ KEY_PART_INFO *key_part, *key_part_end;
+
+ for (key_part=keyinfo->key_part,
+ key_part_end=key_part+ keyinfo->key_parts;
+ key_part < key_part_end;
+ key_part++)
+ {
+ if (!find_func(key_part->field, data))
+ break;
+ }
+ if (key_part == key_part_end)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Helper function for list_contains_unique_index.
+ Find a field reference in a list of ORDER structures.
+
+ SYNOPSIS
+ find_field_in_order_list ()
+ field The field to search for.
+ data ORDER *.The list to search in
+
+ DESCRIPTION
+ Finds a direct reference of the Field in the list.
+
+ RETURN VALUE
+ 1 found
+ 0 not found.
+*/
+
+static bool
+find_field_in_order_list (Field *field, void *data)
+{
+ ORDER *group= (ORDER *) data;
+ bool part_found= 0;
+ for (ORDER *tmp_group= group; tmp_group; tmp_group=tmp_group->next)
+ {
+ Item *item= (*tmp_group->item)->real_item();
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field->eq(field))
+ {
+ part_found= 1;
+ break;
+ }
+ }
+ return part_found;
+}
+
+
+/*
+ Helper function for list_contains_unique_index.
+ Find a field reference in a dynamic list of Items.
+
+ SYNOPSIS
+ find_field_in_item_list ()
+ field in The field to search for.
+ data in List<Item> *.The list to search in
+
+ DESCRIPTION
+ Finds a direct reference of the Field in the list.
+
+ RETURN VALUE
+ 1 found
+ 0 not found.
+*/
+
+static bool
+find_field_in_item_list (Field *field, void *data)
+{
+ List<Item> *fields= (List<Item> *) data;
+ bool part_found= 0;
+ List_iterator<Item> li(*fields);
+ Item *item;
+
+ while ((item= li++))
+ {
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field->eq(field))
+ {
+ part_found= 1;
+ break;
+ }
+ }
+ return part_found;
+}
+
+
/*
Test if we can skip the ORDER BY by using an index.
@@ -12890,7 +13063,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
saved value
*/
Field *field= item->field;
- item->result_field=field->new_field(thd->mem_root,field->table);
+ item->result_field=field->new_field(thd->mem_root,field->table, 1);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2c7a9b05cd9..cabb04c5f16 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -582,7 +582,14 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
{
if (!wild || !wild[0] ||
!wild_case_compare(system_charset_info, field->field_name,wild))
- field_list.push_back(new Item_field(field));
+ {
+ if (table_list->view)
+ field_list.push_back(new Item_ident_for_show(field,
+ table_list->view_db.str,
+ table_list->view_name.str));
+ else
+ field_list.push_back(new Item_field(field));
+ }
}
restore_record(table, s->default_values); // Get empty record
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
@@ -1073,10 +1080,10 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
packet->append(ha_row_type[(uint) share->row_type]);
}
table->file->append_create_info(packet);
- if (share->comment && share->comment[0])
+ if (share->comment.length)
{
packet->append(STRING_WITH_LEN(" COMMENT="));
- append_unescaped(packet, share->comment, strlen(share->comment));
+ append_unescaped(packet, share->comment.str, share->comment.length);
}
if (share->connect_string.length)
{
@@ -2540,11 +2547,14 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
(uint) (ptr-option_buff)-1), cs);
{
char *comment;
- comment= show_table->file->update_table_comment(share->comment);
+ comment= show_table->file->update_table_comment(share->comment.str);
if (comment)
{
- table->field[20]->store(comment, strlen(comment), cs);
- if (comment != share->comment)
+ table->field[20]->store(comment,
+ (comment == share->comment.str ?
+ share->comment.length :
+ strlen(comment)), cs);
+ if (comment != share->comment.str)
my_free(comment, MYF(0));
}
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 91c71193df2..4772d64ad0a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -35,9 +35,7 @@ const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to,
- List<create_field> &create,
- enum enum_duplicates handle_duplicates,
- bool ignore,
+ List<create_field> &create, bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
static bool prepare_blob_field(THD *thd, create_field *sql_field);
@@ -3141,8 +3139,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
List<create_field> &fields, List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates, bool ignore,
+ uint order_num, ORDER *order, bool ignore,
ALTER_INFO *alter_info, bool do_send_ok)
{
TABLE *table,*new_table=0;
@@ -3240,9 +3237,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_PRINT("info", ("old type: %d new type: %d", old_db_type, new_db_type));
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
- ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED) ||
- (old_db_type != new_db_type &&
- ha_check_storage_engine_flag(new_db_type, HTON_ALTER_CANNOT_CREATE)))
+ ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
{
DBUG_PRINT("info", ("doesn't support alter"));
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
@@ -3598,8 +3593,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
create_info->db_type=new_db_type;
- if (!create_info->comment)
- create_info->comment= table->s->comment;
+ if (!create_info->comment.str)
+ {
+ create_info->comment.str= table->s->comment.str;
+ create_info->comment.length= table->s->comment.length;
+ }
table->file->update_create_info(create_info);
if ((create_info->table_options &
@@ -3737,8 +3735,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
new_table->next_number_field=new_table->found_next_number_field;
- error=copy_data_between_tables(table,new_table,create_list,
- handle_duplicates, ignore,
+ error=copy_data_between_tables(table, new_table, create_list, ignore,
order_num, order, &copied, &deleted);
}
thd->last_insert_id=next_insert_id; // Needed for correct log
@@ -3961,7 +3958,6 @@ end_temporary:
static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
- enum enum_duplicates handle_duplicates,
bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,
@@ -4064,8 +4060,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
*/
from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
- if (ignore ||
- handle_duplicates == DUP_REPLACE)
+ if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->row_count= 0;
restore_record(to, s->default_values); // Create empty record
@@ -4092,8 +4087,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
if ((error=to->file->write_row((byte*) to->record[0])))
{
- if ((!ignore &&
- handle_duplicates != DUP_REPLACE) ||
+ if (!ignore ||
(error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE))
{
@@ -4171,7 +4165,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, lex->create_list,
lex->key_list, 0, (ORDER *) 0,
- DUP_ERROR, 0, &lex->alter_info, do_send_ok));
+ 0, &lex->alter_info, do_send_ok));
}
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 6effa6e0644..f46c7414fa4 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -747,7 +747,8 @@ bool Table_triggers_list::prepare_record1_accessors(TABLE *table)
QQ: it is supposed that it is ok to use this function for field
cloning...
*/
- if (!(*old_fld= (*fld)->new_field(&table->mem_root, table)))
+ if (!(*old_fld= (*fld)->new_field(&table->mem_root, table,
+ table == (*fld)->table)))
return 1;
(*old_fld)->move_field((my_ptrdiff_t)(table->record[1] -
table->record[0]));
@@ -1024,8 +1025,15 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
}
/*
- Let us bind Item_trigger_field objects representing access to fields
- in old/new versions of row in trigger to Field objects in table being
+ Gather all Item_trigger_field objects representing access to fields
+ in old/new versions of row in trigger into lists containing all such
+ objects for the triggers with same action and timing.
+ */
+ triggers->trigger_fields[lex.trg_chistics.event]
+ [lex.trg_chistics.action_time]=
+ (Item_trigger_field *)(lex.trg_table_fields.first);
+ /*
+ Also let us bind these objects to Field objects in table being
opened.
We ignore errors here, because if even something is wrong we still
@@ -1507,6 +1515,39 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
/*
+ Mark fields of subject table which we read/set in its triggers as such.
+
+ SYNOPSIS
+ mark_fields_used()
+ thd Current thread context
+ event Type of event triggers for which we are going to inspect
+
+ DESCRIPTION
+ This method marks fields of subject table which are read/set in its
+ triggers as such (by setting Field::query_id equal to THD::query_id)
+ and thus informs handler that values for these fields should be
+ retrieved/stored during execution of statement.
+*/
+
+void Table_triggers_list::mark_fields_used(THD *thd, trg_event_type event)
+{
+ int action_time;
+ Item_trigger_field *trg_field;
+
+ for (action_time= 0; action_time < (int)TRG_ACTION_MAX; action_time++)
+ {
+ for (trg_field= trigger_fields[event][action_time]; trg_field;
+ trg_field= trg_field->next_trg_field)
+ {
+ /* We cannot mark fields which does not present in table. */
+ if (trg_field->field_idx != (uint)-1)
+ table->field[trg_field->field_idx]->query_id = thd->query_id;
+ }
+ }
+}
+
+
+/*
Trigger BUG#14090 compatibility hook
SYNOPSIS
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index b67c22e0588..e736c3e0e1a 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -26,6 +26,11 @@ class Table_triggers_list: public Sql_alloc
/* Triggers as SPs grouped by event, action_time */
sp_head *bodies[TRG_EVENT_MAX][TRG_ACTION_MAX];
/*
+ Heads of the lists linking items for all fields used in triggers
+ grouped by event and action_time.
+ */
+ Item_trigger_field *trigger_fields[TRG_EVENT_MAX][TRG_ACTION_MAX];
+ /*
Copy of TABLE::Field array with field pointers set to TABLE::record[1]
buffer instead of TABLE::record[0] (used for OLD values in on UPDATE
trigger and DELETE trigger when it is called for REPLACE).
@@ -82,6 +87,7 @@ public:
record1_field(0), table(table_arg)
{
bzero((char *)bodies, sizeof(bodies));
+ bzero((char *)trigger_fields, sizeof(trigger_fields));
bzero((char *)&subject_table_grants, sizeof(subject_table_grants));
}
~Table_triggers_list();
@@ -119,6 +125,8 @@ public:
void set_table(TABLE *new_table);
+ void mark_fields_used(THD *thd, trg_event_type event);
+
friend class Item_trigger_field;
friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
TABLE_LIST *table);
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 95589a58b37..8f98bab5c04 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -83,7 +83,7 @@ static char *init_syms(udf_func *tmp, char *nm)
{
char *end;
- if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name.str))))
+ if (!((tmp->func= (Udf_func_any) dlsym(tmp->dlhandle, tmp->name.str))))
return tmp->name.str;
end=strmov(nm,tmp->name.str);
@@ -91,18 +91,18 @@ static char *init_syms(udf_func *tmp, char *nm)
if (tmp->type == UDFTYPE_AGGREGATE)
{
(void)strmov(end, "_clear");
- if (!((tmp->func_clear= dlsym(tmp->dlhandle, nm))))
+ if (!((tmp->func_clear= (Udf_func_clear) dlsym(tmp->dlhandle, nm))))
return nm;
(void)strmov(end, "_add");
- if (!((tmp->func_add= dlsym(tmp->dlhandle, nm))))
+ if (!((tmp->func_add= (Udf_func_add) dlsym(tmp->dlhandle, nm))))
return nm;
}
(void) strmov(end,"_deinit");
- tmp->func_deinit= dlsym(tmp->dlhandle, nm);
+ tmp->func_deinit= (Udf_func_deinit) dlsym(tmp->dlhandle, nm);
(void) strmov(end,"_init");
- tmp->func_init= dlsym(tmp->dlhandle, nm);
+ tmp->func_init= (Udf_func_init) dlsym(tmp->dlhandle, nm);
/*
to prefent loading "udf" from, e.g. libc.so
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index d0729deecaa..21cf735f5ab 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -23,6 +23,15 @@
enum Item_udftype {UDFTYPE_FUNCTION=1,UDFTYPE_AGGREGATE};
+typedef void (*Udf_func_clear)(UDF_INIT *, uchar *, uchar *);
+typedef void (*Udf_func_add)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *);
+typedef void (*Udf_func_deinit)(UDF_INIT*);
+typedef my_bool (*Udf_func_init)(UDF_INIT *, UDF_ARGS *, char *);
+typedef void (*Udf_func_any)();
+typedef double (*Udf_func_double)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *);
+typedef longlong (*Udf_func_longlong)(UDF_INIT *, UDF_ARGS *, uchar *,
+ uchar *);
+
typedef struct st_udf_func
{
LEX_STRING name;
@@ -30,11 +39,11 @@ typedef struct st_udf_func
Item_udftype type;
char *dl;
void *dlhandle;
- void *func;
- void *func_init;
- void *func_deinit;
- void *func_clear;
- void *func_add;
+ Udf_func_any func;
+ Udf_func_init func_init;
+ Udf_func_deinit func_deinit;
+ Udf_func_clear func_clear;
+ Udf_func_add func_add;
ulong usage_count;
} udf_func;
@@ -76,8 +85,7 @@ class udf_handler :public Sql_alloc
*null_value=1;
return 0.0;
}
- double (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
- (double (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func;
+ Udf_func_double func= (Udf_func_double) u_d->func;
double tmp=func(&initid, &f_args, &is_null, &error);
if (is_null || error)
{
@@ -95,8 +103,7 @@ class udf_handler :public Sql_alloc
*null_value=1;
return LL(0);
}
- longlong (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
- (longlong (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func;
+ Udf_func_longlong func= (Udf_func_longlong) u_d->func;
longlong tmp=func(&initid, &f_args, &is_null, &error);
if (is_null || error)
{
@@ -110,8 +117,7 @@ class udf_handler :public Sql_alloc
void clear()
{
is_null= 0;
- void (*func)(UDF_INIT *, uchar *, uchar *)=
- (void (*)(UDF_INIT *, uchar *, uchar *)) u_d->func_clear;
+ Udf_func_clear func= u_d->func_clear;
func(&initid, &is_null, &error);
}
void add(my_bool *null_value)
@@ -121,8 +127,7 @@ class udf_handler :public Sql_alloc
*null_value=1;
return;
}
- void (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
- (void (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func_add;
+ Udf_func_add func= u_d->func_add;
func(&initid, &f_args, &is_null, &error);
*null_value= (my_bool) (is_null || error);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c2b7624c9e7..9a207845893 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -120,6 +120,7 @@ int mysql_update(THD *thd,
bool using_limit= limit != HA_POS_ERROR;
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
bool used_key_is_modified, transactional_table;
+ bool can_compare_record;
int res;
int error;
uint used_index= MAX_KEY;
@@ -433,6 +434,15 @@ int mysql_update(THD *thd,
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
+ if (table->triggers)
+ table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+
+ /*
+ We can use compare_record() to optimize away updates if
+ the table handler is returning all columns
+ */
+ can_compare_record= !(table->file->table_flags() &
+ HA_PARTIAL_COLUMN_READ);
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (!(select && select->skip_record()))
@@ -445,7 +455,7 @@ int mysql_update(THD *thd,
found++;
- if (compare_record(table, query_id))
+ if (!can_compare_record || compare_record(table, query_id))
{
if ((res= table_list->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
@@ -755,6 +765,9 @@ reopen_tables:
DBUG_RETURN(TRUE);
}
+ if (table->triggers)
+ table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+
DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
/*
If table will be updated we should not downgrade lock for it and
@@ -1248,8 +1261,15 @@ bool multi_update::send_data(List<Item> &not_used_values)
uint offset= cur_table->shared;
table->file->position(table->record[0]);
+ /*
+ We can use compare_record() to optimize away updates if
+ the table handler is returning all columns
+ */
if (table == table_to_update)
{
+ bool can_compare_record;
+ can_compare_record= !(table->file->table_flags() &
+ HA_PARTIAL_COLUMN_READ);
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset],
@@ -1259,7 +1279,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
DBUG_RETURN(1);
found++;
- if (compare_record(table, thd->query_id))
+ if (!can_compare_record || compare_record(table, thd->query_id))
{
int error;
if ((error= cur_table->view_check_option(thd, ignore)) !=
@@ -1376,6 +1396,7 @@ int multi_update::do_updates(bool from_send_error)
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
byte *ref_pos;
+ bool can_compare_record;
table = cur_table->table;
if (table == table_to_update)
@@ -1402,6 +1423,9 @@ int multi_update::do_updates(bool from_send_error)
if ((local_error = tmp_table->file->ha_rnd_init(1)))
goto err;
+ can_compare_record= !(table->file->table_flags() &
+ HA_PARTIAL_COLUMN_READ);
+
ref_pos= (byte*) tmp_table->field[0]->ptr;
for (;;)
{
@@ -1431,7 +1455,7 @@ int multi_update::do_updates(bool from_send_error)
TRG_ACTION_BEFORE, TRUE))
goto err2;
- if (compare_record(table, thd->query_id))
+ if (!can_compare_record || compare_record(table, thd->query_id))
{
if ((local_error=table->file->update_row(table->record[1],
table->record[0])))
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 952a8eb44ea..deac9cb5c40 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2529,7 +2529,7 @@ create_table_option:
| MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
| AVG_ROW_LENGTH opt_equal ulong_num { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
| PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; }
- | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; }
+ | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; }
| AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
| PACK_KEYS_SYM opt_equal ulong_num
{
@@ -4453,7 +4453,10 @@ simple_expr:
Lex->safe_to_cache_query=0;
}
| CURRENT_USER optional_braces
- { $$= create_func_current_user(); }
+ {
+ $$= new Item_func_current_user(Lex->current_context());
+ Lex->safe_to_cache_query= 0;
+ }
| DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
{ $$= new Item_date_add_interval($3,$5,$6,0); }
| DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
@@ -4810,7 +4813,7 @@ simple_expr:
| UNIX_TIMESTAMP '(' expr ')'
{ $$= new Item_func_unix_timestamp($3); }
| USER '(' ')'
- { $$= new Item_func_user(FALSE); Lex->safe_to_cache_query=0; }
+ { $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
| UTC_DATE_SYM optional_braces
{ $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;}
| UTC_TIME_SYM optional_braces
@@ -6522,24 +6525,10 @@ show_param:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
- THD *thd= lex->thd;
- Security_context *sctx= thd->security_ctx;
LEX_USER *curr_user;
- if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user))))
YYABORT;
- curr_user->user.str= sctx->priv_user;
- curr_user->user.length= strlen(sctx->priv_user);
- if (*sctx->priv_host != 0)
- {
- curr_user->host.str= sctx->priv_host;
- curr_user->host.length= strlen(sctx->priv_host);
- }
- else
- {
- curr_user->host.str= (char *) "%";
- curr_user->host.length= 1;
- }
- curr_user->password=null_lex_str;
+ bzero(curr_user, sizeof(st_lex_user));
lex->grant_user= curr_user;
}
| GRANTS FOR_SYM user
@@ -7489,22 +7478,14 @@ user:
}
| CURRENT_USER optional_braces
{
- THD *thd= YYTHD;
- Security_context *sctx= thd->security_ctx;
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
YYABORT;
- $$->user.str= sctx->priv_user;
- $$->user.length= strlen(sctx->priv_user);
- if (*sctx->priv_host != 0)
- {
- $$->host.str= sctx->priv_host;
- $$->host.length= strlen(sctx->priv_host);
- }
- else
- {
- $$->host.str= (char *) "%";
- $$->host.length= 1;
- }
+ /*
+ empty LEX_USER means current_user and
+ will be handled in the get_current_user() function
+ later
+ */
+ bzero($$, sizeof(LEX_USER));
};
/* Keyword that we allow for identifiers (except SP labels) */
diff --git a/sql/table.cc b/sql/table.cc
index 9ec9463c33c..b4c08729a79 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -410,7 +410,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
int_length= uint2korr(head+274);
share->null_fields= uint2korr(head+282);
com_length= uint2korr(head+284);
- share->comment= strdup_root(&outparam->mem_root, (char*) head+47);
+ share->comment.length= (int) (head[46]);
+ share->comment.str= strmake_root(&outparam->mem_root, (char*) head+47,
+ share->comment.length);
DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length));
@@ -678,6 +680,27 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (outparam->key_info[key].flags & HA_FULLTEXT)
outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
+ if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
+ {
+ /*
+ If the UNIQUE key doesn't have NULL columns and is not a part key
+ declare this as a primary key.
+ */
+ primary_key=key;
+ for (i=0 ; i < keyinfo->key_parts ;i++)
+ {
+ uint fieldnr= key_part[i].fieldnr;
+ if (!fieldnr ||
+ outparam->field[fieldnr-1]->null_ptr ||
+ outparam->field[fieldnr-1]->key_length() !=
+ key_part[i].length)
+ {
+ primary_key=MAX_KEY; // Can't be used
+ break;
+ }
+ }
+ }
+
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
{
if (new_field_pack_flag <= 1)
@@ -781,7 +804,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (!(field->flags & BLOB_FLAG))
{ // Create a new field
field=key_part->field=field->new_field(&outparam->mem_root,
- outparam);
+ outparam,
+ outparam == field->table);
field->field_length=key_part->length;
}
}
@@ -2961,6 +2985,36 @@ Field_iterator_table_ref::get_natural_column_ref()
return nj_col;
}
+/*
+ Cleanup this table for re-execution.
+
+ SYNOPSIS
+ st_table_list::reinit_before_use()
+*/
+
+void st_table_list::reinit_before_use(THD *thd)
+{
+ /*
+ Reset old pointers to TABLEs: they are not valid since the tables
+ were closed in the end of previous prepare or execute call.
+ */
+ table= 0;
+ /* Reset is_schema_table_processed value(needed for I_S tables */
+ is_schema_table_processed= FALSE;
+
+ TABLE_LIST *embedded; /* The table at the current level of nesting. */
+ TABLE_LIST *embedding= this; /* The parent nested table reference. */
+ do
+ {
+ embedded= embedding;
+ if (embedded->prep_on_expr)
+ embedded->on_expr= embedded->prep_on_expr->copy_andor_structure(thd);
+ embedding= embedded->embedding;
+ }
+ while (embedding &&
+ embedding->nested_join->join_list.head() == embedded);
+}
+
/*****************************************************************************
** Instansiate templates
diff --git a/sql/table.h b/sql/table.h
index ebb4481ef3a..44ec3dc5c06 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -124,7 +124,7 @@ typedef struct st_table_share
#endif
uint *blob_field; /* Index to blobs in Field arrray*/
byte *default_values; /* row with default values */
- char *comment; /* Comment about table */
+ LEX_STRING comment; /* Comment about table */
CHARSET_INFO *table_charset; /* Default charset of string fields */
/* A pair "database_name\0table_name\0", widely used as simply a db name */
@@ -668,10 +668,15 @@ typedef struct st_table_list
Security_context *find_view_security_context(THD *thd);
bool prepare_view_securety_context(THD *thd);
#endif
+ void reinit_before_use(THD *thd);
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
+ /*
+ Cleanup for re-execution in a prepared statement or a stored
+ procedure.
+ */
} TABLE_LIST;
class Item;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 0ab77462f61..3a139aea4c7 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -76,7 +76,7 @@ bool mysql_create_frm(THD *thd, my_string file_name,
handler *db_file)
{
LEX_STRING str_db_type;
- uint reclength,info_length,screens,key_info_length,maxlength;
+ uint reclength, info_length, screens, key_info_length, maxlength, tmp_len;
ulong key_buff_length;
File file;
ulong filepos, data_offset;
@@ -143,10 +143,30 @@ bool mysql_create_frm(THD *thd, my_string file_name,
fileinfo[26]= (uchar) test((create_info->max_rows == 1) &&
(create_info->min_rows == 1) && (keys == 0));
int2store(fileinfo+28,key_info_length);
- strmake((char*) forminfo+47,create_info->comment ? create_info->comment : "",
- 60);
- forminfo[46]=(uchar) strlen((char*)forminfo+47); // Length of comment
+ tmp_len= system_charset_info->cset->charpos(system_charset_info,
+ create_info->comment.str,
+ create_info->comment.str +
+ create_info->comment.length, 60);
+ if (tmp_len < create_info->comment.length)
+ {
+ char buff[128];
+ (void) my_snprintf(buff, sizeof(buff), "Too long comment for table '%s'",
+ table);
+ if ((thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
+ {
+ my_message(ER_UNKNOWN_ERROR, buff, MYF(0));
+ goto err;
+ }
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff);
+ create_info->comment.length= tmp_len;
+ }
+
+ strmake((char*) forminfo+47, create_info->comment.str ?
+ create_info->comment.str : "", create_info->comment.length);
+ forminfo[46]=(uchar) create_info->comment.length;
if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) ||
my_pwrite(file,(byte*) keybuff,key_info_length,
(ulong) uint2korr(fileinfo+6),MYF_RW))
@@ -449,6 +469,27 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
create_field *field;
while ((field=it++))
{
+
+ uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
+ field->comment.str,
+ field->comment.str +
+ field->comment.length, 255);
+ if (tmp_len < field->comment.length)
+ {
+ char buff[128];
+ (void) my_snprintf(buff,sizeof(buff), "Too long comment for field '%s'",
+ field->field_name);
+ if ((current_thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
+ {
+ my_message(ER_UNKNOWN_ERROR, buff, MYF(0));
+ DBUG_RETURN(1);
+ }
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff);
+ field->comment.length= tmp_len;
+ }
+
totlength+= field->length;
com_length+= field->comment.length;
if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||