Пример #1
0
void Session::processSQL(std::string& sqlQuery)
{
	std::ostringstream oss;
	if (this->m_current_db_cfg)
	{

		boost::posix_time::ptime begin(boost::posix_time::microsec_clock::local_time());

		try
		{

			tnode	*pNode  = NULL;
			int	nRet;

			//
			// Prepare
			TProjectSettings settings(*m_current_db_cfg->settings);
			std::string displayFile;

			//
			// generate ident and ini file
			std::string queryIdentStr = "";
			boost::uuids::uuid queryIdent = boost::uuids::random_generator()();
			std::ostringstream queryIdentOSS;
			queryIdentOSS << queryIdent;
			queryIdentStr = queryIdentOSS.str();
			settings.changeIdent(queryIdentOSS.str());

			//
			// create directories
			std::list<fs::path> lpaths;
			lpaths.push_back(fs::path(settings.szRootPath + "/calculus/" + queryIdentOSS.str()));
			lpaths.push_back(fs::path(settings.szTempPath1));
			lpaths.push_back(fs::path(settings.szTempPath2));
			for (std::list<fs::path>::const_iterator dir = lpaths.begin(); dir != lpaths.end(); ++dir)
			{
				std::ostringstream ossDirName;
				ossDirName << *dir;
				aq::Logger::getInstance().log(AQ_DEBUG, "create directory '%s'\n", ossDirName.str().c_str());

				if (fs::exists(*dir))
				{
					aq::Logger::getInstance().log(AQ_ERROR, "directory already exist '%s'\n", ossDirName.str().c_str());
					return;
				}

				if (!fs::create_directory(*dir))
				{
					aq::Logger::getInstance().log(AQ_ERROR, "cannot create directory '%s'\n", ossDirName.str().c_str());
					return;
				}

				aq::Logger::getInstance().log(AQ_DEBUG, "directory '%s' created\n", ossDirName.str().c_str());
			}

			//
			// write ini file (it is needed for now by AQEngine)
			std::ofstream iniFile(settings.iniFile.c_str());
			settings.writeAQEngineIni(iniFile);
			iniFile.close();

			// generate answer file
			displayFile = settings.szRootPath + "/calculus/" + queryIdentStr + "/display.txt"; // TODO
			aq::Logger::getInstance().log(AQ_INFO, "save answer to %s\n", displayFile.c_str());


			//
			// Parse SQL request
			aq::Logger::getInstance().log(AQ_INFO, "parse sql request %s\n", sqlQuery.c_str());
			if ((nRet = SQLParse(sqlQuery.c_str(), &pNode)) != 0 ) 
			{
				oss << "error parsing sql query '" << sqlQuery << "'" << std::endl;
				aq::Logger::getInstance().log(AQ_ERROR, oss.str().c_str());
				throw generic_error(generic_error::INVALID_QUERY, oss.str());
			}

			//
			// Transform SQL request in prefix form
			unsigned int id = 1;
      QueryResolver queryResolver(pNode, &settings, this->m_current_db_cfg->m_aq_engine, *this->m_current_db_cfg->baseDesc.get(), id);
			aq::Logger::getInstance().log(AQ_INFO, "execute query %s\n", sqlQuery.c_str());
			queryResolver.solve();

      //
      // Generate result file
      Table::Ptr result = queryResolver.getResult();
      if (result)
      {
        aq::Timer timer;
        result->saveToAnswer(settings.szAnswerFN, settings.fieldSeparator);
        aq::Logger::getInstance().log(AQ_INFO, "Save Answer: Time Elapsed = %s\n", aq::Timer::getString(timer.getTimeElapsed()).c_str());
        std::ofstream fresult(settings.szAnswerFN, std::ios::app);
        fresult << "EOS";
        fresult.close();
      }

			//
			// read result file and deliver on the socket
			aq::Logger::getInstance().log(AQ_DEBUG, "read answer file %s\n", settings.szAnswerFN);
			std::ifstream answerFile(settings.szAnswerFN);
			std::string bloc;
			std::string line;
			while (std::getline(answerFile, line))
			{
				line += "\n";
				bloc += line;
				if (bloc.size() > 2048)
				{
					this->deliver(bloc);
					bloc = "";
				}
			}
			if (bloc.size())
				this->deliver(bloc);

			oss << "sql request successfully executed" << std::endl;
		}
		catch (const generic_error& ex)
		{
			aq::Logger::getInstance().log(AQ_ERROR, "%s\n", ex.what());
			oss << "error during sql processing: " << ex.what() << std::endl;
		}

		boost::posix_time::ptime end(boost::posix_time::microsec_clock::local_time());
		oss << "Time elapsed: " << (end - begin) << std::endl;
	}
	else
	{
		oss << "not connected to any database" << std::endl;
		aq::Logger::getInstance().log(AQ_NOTICE, oss.str().c_str());
	}
	this->deliver(oss.str());
}