#include "../shared/ReplyToClient.h" #include "UserInfo.h" #include "AlertSqlProducer.h" void AlertSqlProducer::clear() { load("", NULL, ExternalRequest::MessageId::none(), false, false, false); } void AlertSqlProducer::load(std::string const &longForm, SocketInfo *socket, ExternalRequest::MessageId responseId, bool allowCustomColumns, bool useEtradeColumns, bool allowNonFilterColumns) { _longForm = longForm; _socket = socket; _responseId = responseId; _allowCustomColumns = allowCustomColumns; _useEtradeColumns = useEtradeColumns; _allowNonFilterColumns = allowNonFilterColumns; } void AlertSqlProducer::load(ExternalRequest *request) { load(request->getProperty("long_form"), request->getSocketInfo(), request->getResponseMessageId(), request->getProperty("custom_columns") == "1", request->getProperty("etrade_columns") == "1", request->getProperty("non_filter_columns") == "1"); } void AlertSqlProducer::init(DatabaseWithRetry &writableDatabase, DatabaseWithRetry &readOnlyDatabase, AlertConfig::CustomSql &generator) { init(&writableDatabase, readOnlyDatabase, generator); } void AlertSqlProducer::init(DatabaseWithRetry *writableDatabase, DatabaseWithRetry &readOnlyDatabase, AlertConfig::CustomSql &generator) { assert(ready()); const UserId userId = userInfoGetInfo(_socket).userId; AlertConfig config; config.load(_longForm, userId, readOnlyDatabase, _allowCustomColumns, _allowNonFilterColumns); std::string shortForm = config.save(); // Get the short form before we remove the illegal data. The lists might // only temporarily be illegal. A client might easily send us the config // info before the login info. Also, removeIllegalData() can add "hidden" // data that the user should never see. // saveToMru is the only part of this process which modifies the database. // Notice that we call saveToMru before calling removeIllegalData() for the // same reasons that we set shortForm before calling removeIllegalData(). if (writableDatabase) config.saveToMru(userId, *writableDatabase); config.removeIllegalData(userId, readOnlyDatabase); static std::string selectFieldsUnixTime = "id,alert_type,UNIX_TIMESTAMP(timestamp) AS alert_time,alerts.symbol," "description, quality"; static std::string selectFieldsEasternTime = "id,alert_type,timestamp + INTERVAL 3 HOUR AS alert_time,alerts.symbol," "description, quality"; static std::string defaultSelectFields = ", relvol, num, (price-t_low)/(t_high-t_low) as day_range" ", bright_volatility*price AS stddev,volatility"; static std::string newSelectFields = ", alt_description, list_exch"; static std::string etradeSelectFields = ", price, t_low, t_high, last_price"; const bool useEasternTime = userInfoUseEasternTime(_socket); std::string selectFields = useEasternTime?selectFieldsEasternTime:selectFieldsUnixTime; if (!_allowCustomColumns) // older client selectFields += defaultSelectFields; else // newer client selectFields += newSelectFields; if (_useEtradeColumns) selectFields += etradeSelectFields; config.customSql(userId, readOnlyDatabase, selectFields, false, generator); if (_responseId.present()) { XmlNode response; response["STATUS"].properties["SHORT_FORM"] = shortForm; std::string windowName = config.getWindowName(); if (!windowName.empty()) { response["STATUS"].properties["WINDOW_NAME"] = windowName; } if (_allowCustomColumns) { PairedFilterList pairedFilterList(userId, readOnlyDatabase, false, !_allowNonFilterColumns); config.getInitialDescription(response["STATUS"], pairedFilterList); } addToOutputQueue(_socket, response.asString("API"), _responseId); } clear(); } AlertConfig::CustomSql AlertSqlProducer::init(DatabaseWithRetry &readOnlyDatabase) { AlertConfig::CustomSql result; init(NULL, readOnlyDatabase, result); return result; } void AlertSqlProducer::abandon() { XmlNode response; addToOutputQueue(_socket, response.asString("API"), _responseId); clear(); }