#include "../shared/SimpleLogFile.h" #include #include "SimpleDatabaseFields.h" ///////////////////////////////////////////////////////////////////// // PROTECTED_ORDER // // The symbol_info_t table often has two rows for a single stock. // - protected="N" means that the row was automatically added by our // software and will likely be overwritten by our software. // - protected="Y" means that the row was manually added by a human // and can only be changed by a human. // If both rows exist for a stock, you should give priority to the // protected="Y" row. // // Note: In most contexts MySQL would say that "N" comes before "Y". // But protected is an enum, and the opposite is true. To avoid // confusion I'm explicitly ORDERing by protected='Y'. So I know the // N's will come first, because false comes before true. // // In some places we ORDER it with the Y's first, then use "LIMIT 1" to // ignore the second row, if it exists. That code works becuse it is only // looking for a single symbol. The code in this file is loading values // for all symbols at once. If we get two (or more) rows for a symbol, // the C++ code knows to keep the last one. // // Note: In some places the code says "WHERE protected='N'" // instead of "ORDER BY". That is old code and it should change to // look more like this code. ///////////////////////////////////////////////////////////////////// static const std::string PROTECTED_ORDER = " ORDER BY protected='Y' "; ///////////////////////////////////////////////////////////////////// // CompanyNameManager ///////////////////////////////////////////////////////////////////// ThreadSafeWrapper< CompanyNameInfo > CompanyNameManager::_current(new CompanyNameInfo); __thread ThreadSafeCache< CompanyNameInfo > *CompanyNameManager::_cache = NULL; void CompanyNameManager::set(CompanyNameInfo *newValue) { assert(newValue); // So much easier to check for it here rather than each // time we read. _current.set(newValue); } void CompanyNameManager::load(DatabaseWithRetry &database) { CompanyNameInfo *companyNameInfo = new CompanyNameInfo; const std::string sql = "SELECT symbol, company_name FROM symbol_info_f " + PROTECTED_ORDER; for (MysqlResultRef result = database.tryQueryUntilSuccess(sql); result->rowIsValid(); result->nextRow()) if (!result->fieldIsEmpty(1)) { // Map the symbol to the name. companyNameInfo->values[result->getStringField(0)] = result->getStringField(1); //TclList msg; //msg<getStringField(0) // Symbol e.g. MSFT // <getStringField(1); // Name e.g. Microsoft Corporation //sendToLogFile(msg); } set(companyNameInfo); } ///////////////////////////////////////////////////////////////////// // NaicsInfo ///////////////////////////////////////////////////////////////////// ValueBox NaicsInfo::get(ValueBox const &symbol, int digits) const { if ((digits < 2) || (digits > 6)) return ValueBox(); bool valid; std::string value; symbol.getString(valid, value); if (!valid) return ValueBox(); if (Code const *code = getProperty(_bySymbol, value)) { const std::string prefix(code->code, digits); if (std::string const *result = getProperty(_byCode, prefix)) return *result; } return ValueBox(); } void NaicsInfo::load(DatabaseWithRetry &database) { std::string sql = "SELECT symbol,naics FROM symbol_info_f " "WHERE LENGTH(naics)=6 " + PROTECTED_ORDER; for (MysqlResultRef result = database.tryQueryUntilSuccess(sql); result->rowIsValid(); result->nextRow()) { const std::string databaseCode = result->getStringField(1); if (databaseCode.length() != 6) // This shouldn't happen. continue; Code internalCode; memcpy(internalCode.code, databaseCode.c_str(), 6); _bySymbol[result->getStringField(0)] = internalCode; //TclList msg; //msg<getStringField(0) // Symbol e.g. MSFT // <getStringField(1); // NAICS code e.g. 511210 //sendToLogFile(msg); } sql = "SELECT code,sector FROM naics_lookup"; for (MysqlResultRef result = database.tryQueryUntilSuccess(sql); result->rowIsValid(); result->nextRow()) _byCode[result->getStringField(0)] = result->getStringField(1); } ///////////////////////////////////////////////////////////////////// // NaicsManager ///////////////////////////////////////////////////////////////////// ThreadSafeWrapper< NaicsInfo > NaicsManager::_current(new NaicsInfo); __thread ThreadSafeCache< NaicsInfo > *NaicsManager::_cache = NULL; void NaicsManager::load(DatabaseWithRetry &database) { NaicsInfo *naicsInfo = new NaicsInfo; naicsInfo->load(database); _current.set(naicsInfo); }