00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <pion/platform/Database.hpp>
00021 #include <pion/platform/DatabaseManager.hpp>
00022 #include <pion/platform/ConfigManager.hpp>
00023 #include <boost/filesystem/operations.hpp>
00024
00025 namespace pion {
00026 namespace platform {
00027
00028
00029
00030
00031 const std::string Database::INSERT_QUERY_ID = "urn:sql:insert-event";
00032 const std::string Database::INSERT_IGNORE_QUERY_ID = "urn:sql:insert-ignore-event";
00033 const std::string Database::BEGIN_QUERY_ID = "urn:sql:begin-transaction";
00034 const std::string Database::COMMIT_QUERY_ID = "urn:sql:commit-transaction";
00035
00036 const std::string Database::MAP_ELEMENT_NAME = "TypeMap";
00037 const std::string Database::PAIR_ELEMENT_NAME = "Pair";
00038
00039 const std::string Database::CLIENT_ELEMENT_NAME = "Client";
00040 const std::string Database::BEGIN_ELEMENT_NAME = "BeginInsert";
00041 const std::string Database::COMMIT_ELEMENT_NAME = "CommitInsert";
00042 const std::string Database::CREATE_LOG_ELEMENT_NAME = "CreateLog";
00043 const std::string Database::INSERT_LOG_ELEMENT_NAME = "InsertLog";
00044 const std::string Database::ISOLATION_ELEMENT_NAME = "IsolationLevel";
00045 const std::string Database::PRESQL_ELEMENT_NAME = "PreSQL";
00046 const std::string Database::OPTION_ELEMENT_NAME = "Option";
00047
00048 const std::string Database::CREATE_STAT_ELEMENT_NAME = "CreateStat";
00049 const std::string Database::UPDATE_STAT_ELEMENT_NAME = "UpdateStat";
00050 const std::string Database::SELECT_STAT_ELEMENT_NAME = "SelectStat";
00051
00052 const std::string Database::DROP_INDEX_ELEMENT_NAME = "DropIndex";
00053 const std::string Database::CREATE_INDEX_NORMAL_ELEMENT_NAME = "CreateIndexNormal";
00054 const std::string Database::CREATE_INDEX_UNIQUE_ELEMENT_NAME = "CreateIndexUnique";
00055 const std::string Database::CREATE_INDEX_CUSTOM_ELEMENT_NAME = "CreateIndexCustom";
00056
00057 const std::string Database::IGNORE_ATTRIBUTE_NAME = "ignore";
00058 const std::string Database::OPTION_ATTRIBUTE_NAME = "option";
00059
00060 const std::string Database::INSERT_IGNORE_ELEMENT_NAME = "InsertIgnore";
00061 const std::string Database::DROP_TABLE_ELEMENT_NAME = "DropTable";
00062
00063
00064
00065 void Database::setConfig(const Vocabulary& v, const xmlNodePtr config_ptr)
00066 {
00067 PlatformPlugin::setConfig(v, config_ptr);
00068 }
00069
00071 const boost::regex inline getRegex(const std::string& str)
00072 {
00073 return (str.empty() ? boost::regex() : boost::regex(str));
00074 }
00075
00076 void Database::readConfigDetails(const xmlNodePtr config_ptr)
00077 {
00078 if (! ConfigManager::getConfigOption(CLIENT_ELEMENT_NAME, m_database_client, config_ptr))
00079 throw DatabaseClientException(getId());
00080
00081 m_begin_insert.clear();
00082 m_commit_insert.clear();
00083 ConfigManager::getConfigOption(BEGIN_ELEMENT_NAME, m_begin_insert, config_ptr);
00084
00085 ConfigManager::getConfigOption(COMMIT_ELEMENT_NAME, m_commit_insert, config_ptr);
00086
00087 if (! ConfigManager::getConfigOption(CREATE_LOG_ELEMENT_NAME, m_create_log, config_ptr))
00088 throw DatabaseConfigMissing(CREATE_LOG_ELEMENT_NAME);
00089
00090
00091 m_create_log_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(CREATE_LOG_ELEMENT_NAME, config_ptr)));
00092
00093 if (! ConfigManager::getConfigOption(INSERT_LOG_ELEMENT_NAME, m_insert_log, config_ptr))
00094 throw DatabaseConfigMissing(INSERT_LOG_ELEMENT_NAME);
00095
00096 m_insert_log_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(INSERT_LOG_ELEMENT_NAME, config_ptr)));
00097
00098 if (! ConfigManager::getConfigOption(CREATE_STAT_ELEMENT_NAME, m_create_stat, config_ptr))
00099 throw DatabaseConfigMissing(CREATE_STAT_ELEMENT_NAME);
00100
00101 m_create_stat_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(CREATE_STAT_ELEMENT_NAME, config_ptr)));
00102
00103 if (! ConfigManager::getConfigOption(UPDATE_STAT_ELEMENT_NAME, m_update_stat, config_ptr))
00104 throw DatabaseConfigMissing(UPDATE_STAT_ELEMENT_NAME);
00105
00106 m_update_stat_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(UPDATE_STAT_ELEMENT_NAME, config_ptr)));
00107
00108 if (! ConfigManager::getConfigOption(SELECT_STAT_ELEMENT_NAME, m_select_stat, config_ptr))
00109 throw DatabaseConfigMissing(SELECT_STAT_ELEMENT_NAME);
00110
00111 m_select_stat_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(SELECT_STAT_ELEMENT_NAME, config_ptr)));
00112
00113 if (! ConfigManager::getConfigOption(DROP_INDEX_ELEMENT_NAME, m_drop_index, config_ptr))
00114 throw DatabaseConfigMissing(DROP_INDEX_ELEMENT_NAME);
00115
00116 m_drop_index_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(DROP_INDEX_ELEMENT_NAME, config_ptr)));
00117
00118 if (! ConfigManager::getConfigOption(CREATE_INDEX_NORMAL_ELEMENT_NAME, m_create_index_normal, config_ptr))
00119 throw DatabaseConfigMissing(CREATE_INDEX_NORMAL_ELEMENT_NAME);
00120
00121 m_create_index_normal_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(CREATE_INDEX_NORMAL_ELEMENT_NAME, config_ptr)));
00122
00123 if (! ConfigManager::getConfigOption(CREATE_INDEX_UNIQUE_ELEMENT_NAME, m_create_index_unique, config_ptr))
00124 throw DatabaseConfigMissing(CREATE_INDEX_UNIQUE_ELEMENT_NAME);
00125
00126 m_create_index_unique_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(CREATE_INDEX_UNIQUE_ELEMENT_NAME, config_ptr)));
00127
00128 if (! ConfigManager::getConfigOption(CREATE_INDEX_CUSTOM_ELEMENT_NAME, m_create_index_custom, config_ptr))
00129 throw DatabaseConfigMissing(CREATE_INDEX_CUSTOM_ELEMENT_NAME);
00130
00131 m_create_index_custom_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(CREATE_INDEX_CUSTOM_ELEMENT_NAME, config_ptr)));
00132
00133 if (! ConfigManager::getConfigOption(INSERT_IGNORE_ELEMENT_NAME, m_insert_ignore, config_ptr))
00134 throw DatabaseConfigMissing(INSERT_IGNORE_ELEMENT_NAME);
00135
00136 m_insert_ignore_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(INSERT_IGNORE_ELEMENT_NAME, config_ptr)));
00137
00138 if (! ConfigManager::getConfigOption(DROP_TABLE_ELEMENT_NAME, m_drop_table, config_ptr))
00139 throw DatabaseConfigMissing(DROP_TABLE_ELEMENT_NAME);
00140
00141 m_drop_table_attr = getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, ConfigManager::findConfigNodeByName(DROP_TABLE_ELEMENT_NAME, config_ptr)));
00142
00143
00144
00145 std::string isolation_level_str;
00146 if (ConfigManager::getConfigOption(ISOLATION_ELEMENT_NAME, isolation_level_str, config_ptr)) {
00147 if (isolation_level_str == "ReadUncommitted")
00148 m_isolation_level = IL_ReadUncommitted;
00149 else if (isolation_level_str == "ReadCommitted")
00150 m_isolation_level = IL_ReadCommitted;
00151 else if (isolation_level_str == "RepeatableRead")
00152 m_isolation_level = IL_RepeatableRead;
00153 else if (isolation_level_str == "Serializable")
00154 m_isolation_level = IL_Serializable;
00155 else
00156 throw InvalidIsolationLevel(isolation_level_str);
00157 } else
00158 m_isolation_level = IL_ReadUncommitted;
00159
00160
00161
00162 m_sql_affinity.clear();
00163 m_sql_affinity.resize(Vocabulary::TYPE_OBJECT + 1);
00164 xmlNodePtr mapping_node;
00165 if ((mapping_node = ConfigManager::findConfigNodeByName(MAP_ELEMENT_NAME, config_ptr)) != NULL) {
00166 xmlNodePtr map_pair_node = mapping_node->children;
00167 std::string map_pair_str;
00168 while (ConfigManager::getConfigOption(PAIR_ELEMENT_NAME, map_pair_str, map_pair_node)) {
00169
00170 std::string::size_type loc = map_pair_str.find(',');
00171 if (loc != std::string::npos) {
00172 pion::platform::Vocabulary::DataType i = Vocabulary::parseDataType(map_pair_str.substr(0, loc));
00173 m_sql_affinity[i] = map_pair_str.substr(loc + 1);
00174 } else
00175 throw BadTypePair(map_pair_str);
00176 map_pair_node = map_pair_node->next;
00177 }
00178 } else
00179 throw MissingTypeMap(getId());
00180
00181
00182 m_pre_sql.clear();
00183 m_pre_sql_attr.clear();
00184 xmlNodePtr presql_node;
00185 if ((presql_node = ConfigManager::findConfigNodeByName(PRESQL_ELEMENT_NAME, config_ptr)) != NULL) {
00186 std::string presql_str;
00187 while (ConfigManager::getConfigOption(PRESQL_ELEMENT_NAME, presql_str, presql_node)) {
00188 m_pre_sql.push_back(presql_str);
00189 m_pre_sql_attr.push_back(getRegex(ConfigManager::getAttribute(IGNORE_ATTRIBUTE_NAME, presql_node)));
00190 presql_node = presql_node->next;
00191 }
00192 }
00193
00194
00195 m_options.clear();
00196 m_options_values.clear();
00197 xmlNodePtr option_node;
00198 if ((option_node = ConfigManager::findConfigNodeByName(OPTION_ELEMENT_NAME, config_ptr)) != NULL) {
00199 std::string option_value_str;
00200 while (ConfigManager::getConfigOption(OPTION_ELEMENT_NAME, option_value_str, option_node)) {
00201 m_options_values.push_back(option_value_str);
00202 m_options.push_back(ConfigManager::getAttribute(OPTION_ATTRIBUTE_NAME, option_node));
00203 option_node = option_node->next;
00204 }
00205 }
00206 }
00207
00209 void Database::readConfig(const xmlNodePtr config_ptr, std::string engine_str)
00210 {
00211
00212 xmlNodePtr config_detail_ptr = config_ptr;
00213
00214
00215
00216 if (m_database_engine.empty())
00217 m_database_engine = engine_str;
00218 if (m_database_client.empty())
00219 m_database_client = engine_str;
00220
00221 xmlDocPtr template_doc_ptr = NULL;
00222 if (! ConfigManager::getConfigOption(CLIENT_ELEMENT_NAME, m_database_client, config_ptr)) {
00223 if ((template_doc_ptr = getDatabaseManager().getDatabaseEngineConfig(m_database_engine, config_detail_ptr)) == NULL)
00224 throw ReadConfigException(getId());
00225 }
00226 readConfigDetails(config_detail_ptr);
00227
00228 if (template_doc_ptr != NULL)
00229 xmlFreeDoc(template_doc_ptr);
00230 }
00231
00233 void Database::stringReplace(std::string& src, const char* search, const std::string& substitute)
00234 {
00235 std::string::size_type i = 0;
00236 while ((i = src.find(search, i)) != std::string::npos)
00237 src.replace(i, strlen(search), substitute);
00238 }
00239
00241 std::string& Database::stringSubstitutes(std::string& query, const pion::platform::Query::FieldMap& field_map, const std::string& table_name, const std::string& columns_override)
00242 {
00243
00244 stringReplace(query, ":TABLE", table_name);
00245
00246 std::string col, fields, columns, questions, params;
00247 for (unsigned int p = 0; p < field_map.size(); p++) {
00248 fields += field_map[p].first + ' ' +
00249 m_sql_affinity[field_map[p].second.term_type];
00250
00251
00252 columns += field_map[p].first;
00253 if (p == 0)
00254 col = field_map[p].first;
00255 questions += '?';
00256 params += ':' + boost::lexical_cast<std::string>(p+1);
00257 if (p+1 < field_map.size()) {
00258 fields += ',';
00259 columns += ',';
00260 questions += ',';
00261 params += ',';
00262 }
00263 }
00264 stringReplace(query, ":FIELDS", fields);
00265 stringReplace(query, ":COLUMNS", columns_override.empty() ? columns : columns_override);
00266 stringReplace(query, ":COLUMN", col);
00267 stringReplace(query, ":QUESTIONS", questions);
00268 stringReplace(query, ":PARAMS", params);
00269 return query;
00270 }
00271
00272 }
00273 }