diff options
Diffstat (limited to 'sql')
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= ©->share_not_to_be_used; // No name hashing bzero((char*) ©->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> ¬_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> ¬_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 || |