collate_map_t slave::readCollateMap(nanomysql::Connection& conn) { collate_map_t res; nanomysql::Connection::result_t nanores; typedef std::map<std::string, int> charset_maxlen_t; charset_maxlen_t cm; conn.query("SHOW CHARACTER SET"); conn.store(nanores); for (nanomysql::Connection::result_t::const_iterator i = nanores.begin(); i != nanores.end(); ++i) { std::map<std::string, nanomysql::field>::const_iterator z = i->find("Charset"); if (z == i->end()) throw std::runtime_error("Slave::readCollateMap(): SHOW CHARACTER SET query did not return 'Charset'"); const std::string name = z->second.data; z = i->find("Maxlen"); if (z == i->end()) throw std::runtime_error("Slave::readCollateMap(): SHOW CHARACTER SET query did not return 'Maxlen'"); const int maxlen = atoi(z->second.data.c_str()); cm[name] = maxlen; } nanores.clear(); conn.query("SHOW COLLATION"); conn.store(nanores); for (nanomysql::Connection::result_t::const_iterator i = nanores.begin(); i != nanores.end(); ++i) { collate_info ci; std::map<std::string, nanomysql::field>::const_iterator z = i->find("Collation"); if (z == i->end()) throw std::runtime_error("Slave::readCollateMap(): SHOW COLLATION query did not return 'Collation'"); ci.name = z->second.data; z = i->find("Charset"); if (z == i->end()) throw std::runtime_error("Slave::readCollateMap(): SHOW COLLATION query did not return 'Charset'"); ci.charset = z->second.data; charset_maxlen_t::const_iterator j = cm.find(ci.charset); if (j == cm.end()) throw std::runtime_error("Slave::readCollateMap(): SHOW COLLATION returns charset not shown in SHOW CHARACTER SET" " (collation '" + ci.name + "', charset '" + ci.charset + "')"); ci.maxlen = j->second; res[ci.name] = ci; } return res; }
void Slave::createTable(RelayLogInfo& rli, const std::string& db_name, const std::string& tbl_name, const collate_map_t& collate_map, nanomysql::Connection& conn) const { LOG_TRACE(log, "enter: createTable " << db_name << " " << tbl_name); nanomysql::Connection::result_t res; conn.query("SHOW FULL COLUMNS FROM " + tbl_name + " IN " + db_name); conn.store(res); boost::shared_ptr<Table> table(new Table(db_name, tbl_name)); LOG_DEBUG(log, "Created new Table object: database:" << db_name << " table: " << tbl_name ); for (nanomysql::Connection::result_t::const_iterator i = res.begin(); i != res.end(); ++i) { //row.at(0) - field name //row.at(1) - field type //row.at(2) - collation //row.at(3) - can be null std::map<std::string,nanomysql::field>::const_iterator z = i->find("Field"); if (z == i->end()) throw std::runtime_error("Slave::create_table(): DESCRIBE query did not return 'Field'"); std::string name = z->second.data; z = i->find("Type"); if (z == i->end()) throw std::runtime_error("Slave::create_table(): DESCRIBE query did not return 'Type'"); std::string type = z->second.data; z = i->find("Null"); if (z == i->end()) throw std::runtime_error("Slave::create_table(): DESCRIBE query did not return 'Null'"); std::string extract_field; // Extract field type for (size_t tmpi = 0; tmpi < type.size(); ++tmpi) { if (!((type[tmpi] >= 'a' && type[tmpi] <= 'z') || (type[tmpi] >= 'A' && type[tmpi] <= 'Z'))) { extract_field = type.substr(0, tmpi); break; } if (tmpi == type.size()-1) { extract_field = type; break; } } if (extract_field.empty()) throw std::runtime_error("Slave::create_table(): Regexp error, type not found"); collate_info ci; if ("varchar" == extract_field || "char" == extract_field) { z = i->find("Collation"); if (z == i->end()) throw std::runtime_error("Slave::create_table(): DESCRIBE query did not return 'Collation' for field '" + name + "'"); const std::string collate = z->second.data; collate_map_t::const_iterator it = collate_map.find(collate); if (collate_map.end() == it) throw std::runtime_error("Slave::create_table(): cannot find collate '" + collate + "' from field " + name + " type " + type + " in collate info map"); ci = it->second; LOG_DEBUG(log, "Created column: name-type: " << name << " - " << type << " Field type: " << extract_field << " Collation: " << ci.name); } else LOG_DEBUG(log, "Created column: name-type: " << name << " - " << type << " Field type: " << extract_field ); PtrField field; if (extract_field == "int") field = PtrField(new Field_long(name, type)); else if (extract_field == "double") field = PtrField(new Field_double(name, type)); else if (extract_field == "float") field = PtrField(new Field_float(name, type)); else if (extract_field == "date") field = PtrField(new Field_date(name, type)); else if (extract_field == "year") field = PtrField(new Field_year(name, type)); else if (extract_field == "enum") field = PtrField(new Field_enum(name, type)); else if (extract_field == "set") field = PtrField(new Field_set(name, type)); else if (extract_field == "varchar") field = PtrField(new Field_varstring(name, type, ci)); else if (extract_field == "char") field = PtrField(new Field_varstring(name, type, ci)); else if (extract_field == "tinyint") field = PtrField(new Field_tiny(name, type)); else if (extract_field == "smallint") field = PtrField(new Field_short(name, type)); else if (extract_field == "mediumint") field = PtrField(new Field_medium(name, type)); else if (extract_field == "bigint") field = PtrField(new Field_longlong(name, type)); else if (extract_field == "text") field = PtrField(new Field_blob(name, type)); else if (extract_field == "tinytext") field = PtrField(new Field_tinyblob(name, type)); else if (extract_field == "mediumtext") field = PtrField(new Field_mediumblob(name, type)); else if (extract_field == "longtext") field = PtrField(new Field_longblob(name, type)); else if (extract_field == "blob") field = PtrField(new Field_blob(name, type)); else if (extract_field == "tinyblob") field = PtrField(new Field_tinyblob(name, type)); else if (extract_field == "mediumblob") field = PtrField(new Field_mediumblob(name, type)); else if (extract_field == "longblob") field = PtrField(new Field_longblob(name, type)); else if (extract_field == "decimal") field = PtrField(new Field_decimal(name, type)); else if (extract_field == "bit") field = PtrField(new Field_bit(name, type)); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Temporal types that have been changed in the MySql 5.6.4 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= else if (extract_field == "time") { if (!is_master_5_6_x()) field = PtrField(new Field_time_5_5(name, type)); else field = PtrField(new Field_time_5_6(name, type)); } else if (extract_field == "timestamp") { if (!is_master_5_6_x()) field = PtrField(new Field_timestamp_5_5(name, type)); else field = PtrField(new Field_timestamp_5_6(name, type)); } else if (extract_field == "datetime") { if (!is_master_5_6_x()) field = PtrField(new Field_datetime_5_5(name, type)); else field = PtrField(new Field_datetime_5_6(name, type)); } else { LOG_ERROR(log, "createTable: class name don't exist: " << extract_field ); throw std::runtime_error("class name does not exist: " + extract_field); } table->fields.push_back(field); } rli.setTable(tbl_name, db_name, table); }