Exemple #1
0
//TODO Fix memory leak if transaction is never started
int Transaction::addQuery(lua_State* state) {
	GarrysMod::Lua::ILuaBase* LUA = state->luabase;
	LUA->SetState(state);
	Transaction* transaction = dynamic_cast<Transaction*>(unpackSelf(LUA, TYPE_QUERY));
	if (transaction == nullptr) {
		LUA->ThrowError("Tried to pass wrong self");
	}
	IQuery* iQuery = (IQuery*)unpackLuaObject(LUA, 2, TYPE_QUERY, false);
	Query* query = dynamic_cast<Query*>(iQuery);
	if (query == nullptr) {
		LUA->ThrowError("Tried to pass non query to addQuery()");
	}
	//This is all very ugly
	LUA->Push(1);
	LUA->GetField(-1, "__queries");
	if (LUA->IsType(-1, GarrysMod::Lua::Type::NIL)) {
		LUA->Pop();
		LUA->CreateTable();
		LUA->SetField(-2, "__queries");
		LUA->GetField(-1, "__queries");
	}
	int tblIndex = LUA->Top();
	LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB);
	LUA->GetField(-1, "table");
	LUA->GetField(-1, "insert");
	LUA->Push(tblIndex);
	LUA->Push(2);
	LUA->Call(2, 0);
	LUA->Push(4);
	return 0;
}
Exemple #2
0
/* Returns the status of the database, constants can be found in GMModule
 */
int Database::status(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	LUA->PushNumber(object->m_status);
	return 1;
}
Exemple #3
0
/* Creates and returns a PreparedQuery instance and enqueues it into the queue of accepted queries.
*/
int Database::createTransaction(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	Transaction* transactionObject = new Transaction(object, state);
	transactionObject->pushTableReference(state);
	return 1;
}
Exemple #4
0
/* Returns the amount of queued querys in the database instance
 * If a query is currently being processed, it does not count towards the queue size
 */
int Database::queueSize(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	std::unique_lock<std::mutex> qlck(object->m_queryQueueMutex);
	LUA->PushNumber(object->queryQueue.size());
	return 1;
	
}
Exemple #5
0
int Transaction::getQueries(lua_State* state) {
	GarrysMod::Lua::ILuaBase* LUA = state->luabase;
	LUA->SetState(state);
	Transaction* transaction = dynamic_cast<Transaction*>(unpackSelf(LUA, TYPE_QUERY));
	if (transaction == nullptr) {
		LUA->ThrowError("Tried to pass wrong self");
	}
	LUA->Push(1);
	LUA->GetField(-1, "__queries");
	return 1;
}
Exemple #6
0
/* Returns a string of the hostname connected to as well as the connection type
 * Only works as soon as the connection has been established
 */
int Database::hostInfo(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	if (!object->m_connectionDone)
	{
		LUA->ThrowError("Tried to get server info when client is not connected to server yet!");
	}
	LUA->PushString(object->m_hostInfo.c_str());
	return 1;
}
Exemple #7
0
/* Returns the server version as a formatted integer (XYYZZ, X= major-, Y=minor, Z=sub-version)
 * Only works as soon as the connection has been established
 */
int Database::serverVersion(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	if (!object->m_connectionDone)
	{
		LUA->ThrowError("Tried to get server version when client is not connected to server yet!");
	}
	LUA->PushNumber(object->m_serverVersion);
	return 1;
}
Exemple #8
0
/* Creates and returns a PreparedQuery instance and enqueues it into the queue of accepted queries.
*/
int Database::prepare(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	LUA->CheckType(2, GarrysMod::Lua::Type::STRING);
	unsigned int outLen = 0;
	const char* query = LUA->GetString(2, &outLen);
	PreparedQuery* queryObject = new PreparedQuery(object, state);
	queryObject->setQuery(std::string(query, outLen));
	queryObject->pushTableReference(state);
	return 1;
}
Exemple #9
0
int Database::setMultiStatements(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE, true);
	if (object->m_status != DATABASE_NOT_CONNECTED || object->startedConnecting)
	{
		LUA->ThrowError("Database already connected.");
	}
	LUA->CheckType(2, GarrysMod::Lua::Type::BOOL);
	object->useMultiStatements = LUA->GetBool(2);
	return 0;
}
Exemple #10
0
/* Starts the thread that connects to the database and then handles queries.
 */
int Database::connect(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE, true);
	if (object->m_status != DATABASE_NOT_CONNECTED || object->startedConnecting)
	{
		LUA->ThrowError("Database already connected.");
	}
	object->startedConnecting = true;
	object->m_status = DATABASE_CONNECTING;
	object->m_thread = std::thread(&Database::connectRun, object);
	return 0;
}
Exemple #11
0
/* Waits for the connection of the database to finish by blocking the current thread until the connect thread finished.
 * Callbacks are going to be called before this function returns
 */
int Database::wait(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	if (!object->startedConnecting)
	{
		LUA->ThrowError("Tried to wait for database connection to finish without starting the connection!");
	}
	std::unique_lock<std::mutex> lck(object->m_connectMutex);
	while (!object->m_connectionDone) object->m_connectWakeupVariable.wait(lck);
	object->think(state);
	return 0;
}
Exemple #12
0
/* Aborts all queries that are in the queue of started queries and returns the number of successfully aborted queries.
 * Does not abort queries that are already taken from the queue and being processed.
 */
int Database::abortAllQueries(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	std::lock_guard<std::mutex> lock(object->m_queryQueueMutex);
	for (auto& query : object->queryQueue)
	{
		query->m_status = QUERY_ABORTED;
		query->unreference(state);
	}
	LUA->PushNumber((double)object->queryQueue.size());
	object->queryQueue.clear();
	return 1;
}
Exemple #13
0
/* Escapes an unescaped string using the database taking into account the characterset of the database.
 * This might break if the characterset of the database is changed after the connection was done
 */
int Database::escape(lua_State* state)
{
	LOG_CURRENT_FUNCTIONCALL
	Database* object = (Database*)unpackSelf(state, TYPE_DATABASE);
	std::lock_guard<std::mutex>(object->m_connectMutex);
	//No query mutex needed since this doesn't use the connection at all
	if (!object->m_connectionDone || object->m_sql == nullptr) return 0;
	LUA->CheckType(2, GarrysMod::Lua::Type::STRING);
	const char* sQuery = LUA->GetString(2);
	size_t nQueryLength = strlen(sQuery);
	//escaped string can be twice as big as original string
	//source: http://dev.mysql.com/doc/refman/5.1/en/mysql-real-escape-string.html
	std::vector<char> escapedQuery(nQueryLength * 2 + 1);
	mysql_real_escape_string(object->m_sql, escapedQuery.data(), sQuery, nQueryLength);
	LUA->PushString(escapedQuery.data());
	return 1;
}