/* * 设置与此 Column 联合的 JOIN 表 * 一般来说只设置 ON column 用于连接表即可 * 如果有特殊要求,则会输入扩展条件 ext_condition * * 实验显示,一般情况下 ext_condition 条件续放到外面才起作用 */ void ExMysqlColumn::add_join(const char* type, MysqlTable* join_table, const char* on_column, const char* ext_condition) { if(type == NULL || join_table == NULL || on_column == NULL) { LOGD("[GWJ] %s: [join type] or [join table] or [ON column] NULL ERROR!! ", __FUNCTION__); return; } JoinCondition join_condition(type, join_table, on_column); if(ext_condition != NULL) { join_condition.set_extra(ext_condition); } /* * 当执行 join 操作时,要把参与 joint 的表需要 select 的列加入到 owner 表中 * 保证在执行 SQL 语句时能够选出 joint 表中想要的列 */ MysqlTable* this_table = this->owner_table; int joint_col_size = join_table->get_select_column_size(); for(int i = 0; i < joint_col_size; i++) { const char* joint_column = (*join_table)[i]; if(joint_column != NULL) { this_table->add_select_column(joint_column, join_table->nick_name); } else { LOGD("[GWJ] %s: NULL joint column[%d]", __FUNCTION__, i); } } this_table->add_join_table(join_table); this->join_conditon.push_back(join_condition); LOGD("[GWJ] %s:add join[%s %s]", __FUNCTION__, type, join_table->table_name); }
Query Parser::parse(std::string query_str) { regex regex("(SELECT .*)(FROM .*)(WHERE .*)", regex_constants::icase); smatch match; regex_match(query_str, match, regex); if(match.size() != 4) { throw std::invalid_argument("Query does match SELECT .* FROM .* WHERE .* syntax"); } string select_str = match[1]; string from_str = match[2]; string where_str = match[3]; Query query; // evaluate SELECT if(std::regex_match(select_str, std::regex("SELECT\\s*\\*\\s*", regex::ECMAScript))) { // leave query.selections empty to indicate that all should be // selected } else { // remove SELECT and any whitespaces from the input boost::algorithm::erase_all(select_str, "SELECT"); boost::algorithm::erase_all(select_str, " "); // split the remainder by "," and check with regex // if it confirms to our input format std::regex attribute_regex("(?:([\'\"a-zA-Z0-9-_]+)\\.){0,1}([\'\"a-zA-Z0-9-_]+)", regex::ECMAScript); vector<string> tokens; boost::algorithm::split(tokens, select_str, boost::is_any_of(",")); for(uint64_t i=0; i<tokens.size(); i++) { std::smatch match; std::regex_search(tokens[i], match, attribute_regex); if(match.size() != 3) { throw std::invalid_argument("Attribute in SELECT is not of the form binding.attribute"); } // if the group before the dot was matched, we have a binding // like "binding.attribute" if(match[1].length() > 0) { Selection selection(match[1], match[2]); query.selections.push_back(selection); } else { string attribute = match[2]; // check if we have a constant string like 'foo' or "bar" if(std::regex_match(attribute, std::regex("(\".*\")|(\'.*\')"))) { boost::algorithm::erase_all(attribute, "\""); boost::algorithm::erase_all(attribute, "\'"); Constant constant(attribute); Selection selection(constant); query.selections.push_back(selection); } else { Selection selection(string(""), attribute); query.selections.push_back(selection); } /* TODO Check for numeric constants here*/ } } } // parse FROM boost::algorithm::erase_all(from_str, "FROM"); vector<string> tokens; boost::algorithm::split(tokens, from_str, boost::is_any_of(",")); for(uint64_t i=0; i<tokens.size(); i++) { smatch match; if(regex_search((string)tokens[i], match, std::regex("\\s*([a-zA-Z-_]+)\\s+([a-zA-Z-_]+)\\s*"))) { Relation relation(match[1], match[2]); query.relations.push_back(relation); } else { throw std::invalid_argument("relation in FROM clause does not match format"); } } // parse WHERE boost::erase_all(where_str, "WHERE"); boost::replace_all(where_str, " and ", ","); boost::replace_all(where_str, " AND ", ","); boost::erase_all(where_str, " "); std::regex join_condition_attribute_regex("([a-zA-Z0-9-_]+)\\.([a-zA-Z0-9-_]+)=(?:([a-zA-Z0-9-_]+)\\.([a-zA-Z0-9-_]+))", regex::ECMAScript); std::regex join_condition_constant_regex("([a-zA-Z0-9-_]+)\\.([a-zA-Z0-9-_]+)=([\'\"a-zA-Z0-9-_]+)", regex::ECMAScript); boost::algorithm::split(tokens, where_str, boost::is_any_of(",")); for(uint64_t i=0; i<tokens.size(); i++) { std::smatch match; std::regex_search(tokens[i], match, join_condition_attribute_regex); if(match.size() > 0) { Attribute left(match[1], match[2]); Attribute right(match[3], match[4]); JoinCondition join_condition(left, right); query.join_conditions.push_back(join_condition); } else { // TODO we cannot parse numeric constants std::regex_search(tokens[i], match, join_condition_constant_regex); string constant_str = match[3]; boost::algorithm::erase_all(constant_str, "\""); boost::algorithm::erase_all(constant_str, "\'"); Attribute left(match[1], match[2]); Constant right(constant_str); JoinCondition join_condition(left, right); query.join_conditions.push_back(join_condition); } } return query; }