Пример #1
0
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;
}
Пример #2
0
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);

}