Esempio n. 1
0
void Statement::prepare(sqlite3 *connection, const String &sql)
{
	OS_ASSERT(m_statement == nullptr);

	OS_EXCEPT_IF(connection == nullptr, "Invalid connection");
	m_connection = connection;

	sqlite_int res = safe_sqlite_prepare(connection, sql, &m_statement);
	OS_EXCEPT_IF(res != SQLITE_OK, sqlite_last_error(connection, res));
}
Esempio n. 2
0
void Statement::close()
{
	if(m_statement != nullptr)
	{
		sqlite3_stmt *statement = m_statement;
		m_statement = nullptr;		// Resetta il puntatore allo statement

		sqlite_int res = safe_sqlite_finalize(statement);
		// La chiusura  richiamata nel distruttore pertanto non deve lanciare eccezioni
		if(res != SQLITE_OK)
		{
			OS_TRACE(sqlite_last_error(m_connection, res));
			OS_ASSERTFALSE();
		}
	}

	m_connection = nullptr;
}
Esempio n. 3
0
void Connection::connect(const String &filename)
{
	close();

	// _tsqlite3_open crea un nuovo database se il file non esiste: dovrebbe essere il driver a monte che non crea la connessione se il file non esiste
	OS_ASSERT(FileSystem::instance()->fileExists(filename));

	int32 res = _tsqlite3_open(filename.c_str(), &m_connection);
	OS_EXCEPT_IF(res != SQLITE_OK, sqlite_last_error(m_connection, res));
	m_filename = filename;

	uint32 cacheSize = OS_NAMESPACE_NAME::Options::instance()->getOption<uint32>(OS_SQLITE_OPTION_CACHE_SIZE);
	String synchronous = static_cast<String>(OS_NAMESPACE_NAME::Options::instance()->getOption<String>(OS_SQLITE_OPTION_SYNCHRONOUS)).to_upper();
	if((synchronous != _S("FULL")) && (synchronous != _S("NORMAL")) && (synchronous != _S("OFF")))
		synchronous = _S("FULL");
	uint32 tempStore = OS_NAMESPACE_NAME::Options::instance()->getOption<uint32>(OS_SQLITE_OPTION_TEMP_STORE);
	if(tempStore > 2)
		tempStore = 0;

	doExecute(m_connection, _S("PRAGMA legacy_file_format = OFF;"));
	doExecute(m_connection, String::format(_S("PRAGMA cache_size = %d;").c_str(), cacheSize)); // Default di sqlite:2000
	doExecute(m_connection, String::format(_S("PRAGMA synchronous = %S;").c_str(), synchronous.c_str())); // FULL/NORMAL/OFF, Default di sqlite: FULL
	doExecute(m_connection, String::format(_S("PRAGMA temp_store = %d").c_str(), tempStore)); // 0(Default)/1(File)/2(Memory), Default di sqlite: 0
}
Esempio n. 4
0
String Connection::preAnalyze(const String &sql)
{
	static boost::recursive_mutex cs;
	OS_LOCK(cs);

	// Per vedere le sql nel charts:
	// RealtimeStatsManager::signal(sql, 1, RealtimeStatsCounter::ctAbsolute, _S("status"));

	// Da notare che vengono archiviate nella os_monitor solo le query analizzate dalla "explain".
	// Una "insert", non usando indici, non viene catalogata, a meno che non abbia sotto-query.

	if(sql.find(_S("explain query plan ")) != String::npos)
		return _S("");

	if(sql.find(_S("os_monitor")) != String::npos)
		return _S("");

	static shared_ptr<Connection> connectionAnalyze = nullptr;
	if(connectionAnalyze == nullptr)
	{
		shared_ptr<Driver> driver = boost::dynamic_pointer_cast<Driver>(getDriver());
		String path = driver->getDatabasePath(_S("monitor.db"));
		if(FileSystem::instance()->exists(path) == false)
		{
			// Crea il database se non esiste
			File file;
			String msg = _S("Cannot create file '") + path + _S("'");
			OS_EXCEPT_IF(file.open(path, File::ofWrite) == false, msg.to_ascii());
		}

		connectionAnalyze.reset(OS_NEW Connection(path, getDriver()->createOptions(), getDriver()));

		int32 res = _tsqlite3_open(path.c_str(), &connectionAnalyze->m_connection);
		OS_EXCEPT_IF(res != SQLITE_OK, sqlite_last_error(connectionAnalyze->m_connection, res));

		// Creazione tabella
		String sqlCreate = _S("CREATE TABLE IF NOT EXISTS os_monitor (filename text,sql text,thread integer,conn integer,trans integer, qorder integer,qfrom integer,detail text,indexUsed text)");
		doExecute(connectionAnalyze->m_connection, sqlCreate);
	}

	// I valori dei campi li setto a ?, per poter fare delle distinct sui risultati
	String keySql = sql;
	keySql.trim();
	keySql = regex_replace(keySql, RegexManager::instance()->getRegex(_S("'(.*?)'")), _S("<s>")); // Valori dei campi
	keySql = regex_replace(keySql, RegexManager::instance()->getRegex(_S("[-+]?[0-9]*\\.?[0-9]+")), _S("<n>")); // Numeri
	keySql = keySql.replace_all(_S("\n"),_S(""));
	keySql = keySql.replace_all(_S("\r"),_S(""));
	keySql = keySql.replace_all(_S("\t"),_S(""));
	keySql = keySql.replace_all(_S("'"),_S("")); // Futile, per evitare errori nella insert nella os_monitor
	for(;;) // Comprimo gli spazi
	{
		String x = keySql;
		keySql = keySql.replace_all(_S("  "),_S(" "));
		if(x == keySql)
			break;
	}

	uint32 conn = uint32(reinterpret_cast<uint64>(this));
	boost::any threadID = PlatformManager::instance()->getCurrentThreadID();
	// Tenta un cast a uint32
	uint32 *thread = boost::any_cast<uint32>(&threadID);
	int32 trans = m_transactionId;

	DataTable result;
	doQuery(m_connection, _S("explain query plan ") + sql,result);

	for(uint32 r=0;r<result.rows();r++)
	{
		int32 order = *result.get(r,_S("order"));
		int32 from = *result.get(r,_S("from"));
		String detail = *result.get(r,_S("detail"));

		String indexUsed;
		String::size_type posWithIndex = detail.find(_S("WITH INDEX"));
		if(posWithIndex != String::npos)
		{
			indexUsed = detail.substr(posWithIndex+10);
			indexUsed = indexUsed.replace_all(_S("ORDER BY"),String::EMPTY);
			indexUsed.trim();
		}

		String sqlInsert = String::format(_S("insert into os_monitor values ('%S','%S',%u,%u,%u,%d,%d,'%S','%S')").c_str(), m_filename.c_str(), keySql.c_str(), conn, thread != nullptr ? *thread : 0, trans, order, from, detail.c_str(), indexUsed.c_str());
		doExecute(connectionAnalyze->m_connection, sqlInsert);
	}

	String trace = String::format(_S("Sqlite monitor: sql='%S',conn=%u,thread=%u,trans=%u\n").c_str(), sql.c_str(), conn, thread != nullptr ? *thread : 0, trans);
	//OS_TRACE(trace);

	//RealtimeStatsManager::signal(_S("Sqlite ") + keySql.mid(0,6), 1, RealtimeStatsCounter::ctRelative, _S("items"));
	return keySql;
}
Esempio n. 5
0
void Statement::run()
{
	sqlite_int res = safe_sqlite_step(m_statement);
	OS_EXCEPT_IF(res != SQLITE_OK && res != SQLITE_ROW && res != SQLITE_DONE, sqlite_last_error(m_connection, res));
}