polserver/pol-core/pol/module/sqlmod.cpp

330 lines
9.7 KiB
C++
Raw Permalink Normal View History

2016-02-11 22:54:43 +01:00
/** @file
*
* @par History
*/
#include "pol_global_config.h"
2016-02-11 22:54:43 +01:00
#include "sqlmod.h"
#include <stddef.h>
2016-02-11 22:54:43 +01:00
#include "../../bscript/berror.h"
#include "../../bscript/impstr.h"
#include "../../clib/logfacility.h"
#include "../../clib/refptr.h"
#include "../../clib/weakptr.h"
#include "../globals/network.h"
#include "../polsem.h"
#include "../sqlscrobj.h"
#include "../uoexec.h"
2024-07-20 03:20:28 +02:00
#include "sqlmod.inl.h"
#include <module_defs/sql.h>
namespace Pol
{
namespace Module
{
using namespace Bscript;
SQLExecutorModule::SQLExecutorModule( Bscript::Executor& exec )
: Bscript::TmplExecutorModule<SQLExecutorModule, Core::PolModule>( exec )
{
}
size_t SQLExecutorModule::sizeEstimate() const
{
return sizeof( *this );
}
Bscript::BObjectImp* SQLExecutorModule::background_select( weak_ptr<Core::UOExecutor> uoexec,
Core::BSQLConnection* sql,
const std::string db )
{
// The BSQLConnection shouldn't be destroyed before the lambda runs
ref_ptr<Core::BSQLConnection> sqlRef( sql );
auto msg = [uoexec, sqlRef, db]()
{
if ( sqlRef == nullptr )
{
Core::PolLock lck;
if ( !uoexec.exists() )
INFO_PRINTLN( "Script has been destroyed" );
else
{
uoexec.get_weakptr()->ValueStack.back().set(
new BObject( new BError( "Invalid parameters" ) ) );
uoexec.get_weakptr()->revive();
}
}
else if ( !sqlRef->select_db( db.c_str() ) )
{
Core::PolLock lck;
if ( !uoexec.exists() )
INFO_PRINTLN( "Script has been destroyed" );
else
{
uoexec.get_weakptr()->ValueStack.back().set(
new BObject( new BError( sqlRef->getLastError() ) ) );
uoexec.get_weakptr()->revive();
}
}
else
{
Core::PolLock lck;
if ( !uoexec.exists() )
INFO_PRINTLN( "Script has been destroyed" );
else
{
uoexec.get_weakptr()->ValueStack.back().set( new BObject( new BLong( 1 ) ) );
uoexec.get_weakptr()->revive();
2016-02-11 22:54:43 +01:00
}
}
};
if ( !uoexec->suspend() )
{
DEBUGLOGLN(
"Script Error in '{}' PC={}: \n"
"\tThe execution of this script can't be blocked!",
uoexec->scriptname(), uoexec->PC );
return new Bscript::BError( "Script can't be blocked" );
}
Core::networkManager.sql_service->push( std::move( msg ) );
return new BLong( 0 );
}
Bscript::BObjectImp* SQLExecutorModule::background_query( weak_ptr<Core::UOExecutor> uoexec,
Core::BSQLConnection* sql,
const std::string query,
const Bscript::ObjArray* params )
{
// Copy and parse params before they will be deleted by this thread (go out of scope)
Core::QueryParams sharedParams( nullptr );
if ( params != nullptr )
{
sharedParams = std::make_shared<Core::QueryParam>();
2016-02-11 22:54:43 +01:00
for ( unsigned i = 0; i < params->ref_arr.size(); ++i )
{
const BObjectRef& ref = params->ref_arr[i];
const BObject* obj = ref.get();
2018-07-31 14:30:29 +02:00
if ( obj != nullptr )
sharedParams->insert( sharedParams->end(), obj->impptr()->getStringRep() );
2016-02-11 22:54:43 +01:00
}
}
2016-02-11 22:54:43 +01:00
// The BSQLConnection shouldn't be destroyed before the lambda runs
ref_ptr<Core::BSQLConnection> sqlRef( sql );
auto msg = [uoexec, sqlRef, query, sharedParams]()
{
if ( sqlRef == nullptr ) // TODO: this doesn't make any sense and should be checked before the
// lambda. Same happens in background_select().
{
Core::PolLock lck;
if ( !uoexec.exists() )
INFO_PRINTLN( "Script has been destroyed" );
else
{
uoexec.get_weakptr()->ValueStack.back().set(
new BObject( new BError( "Invalid parameters" ) ) );
uoexec.get_weakptr()->revive();
}
}
else if ( !sqlRef->query( query, sharedParams ) )
{
Core::PolLock lck;
if ( !uoexec.exists() )
INFO_PRINTLN( "Script has been destroyed" );
else
2016-02-11 22:54:43 +01:00
{
uoexec.get_weakptr()->ValueStack.back().set(
new BObject( new BError( sqlRef->getLastError() ) ) );
uoexec.get_weakptr()->revive();
2016-02-11 22:54:43 +01:00
}
}
else
{
Core::PolLock lck;
if ( !uoexec.exists() )
INFO_PRINTLN( "Script has been destroyed" );
else
2016-02-11 22:54:43 +01:00
{
uoexec.get_weakptr()->ValueStack.back().set( new BObject( sqlRef->getResultSet() ) );
uoexec.get_weakptr()->revive();
2016-02-11 22:54:43 +01:00
}
}
};
if ( !uoexec->suspend() )
{
DEBUGLOGLN(
"Script Error in '{}' PC={}: \n"
"\tThe execution of this script can't be blocked!",
uoexec->scriptname(), uoexec->PC );
return new Bscript::BError( "Script can't be blocked" );
}
Core::networkManager.sql_service->push( std::move( msg ) );
return new BLong( 0 );
}
2016-02-11 22:54:43 +01:00
2024-07-20 03:20:28 +02:00
#ifdef HAVE_MYSQL
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_connect()
{
const String* host = getStringParam( 0 );
const String* username = getStringParam( 1 );
const String* password = getStringParam( 2 );
int port;
if ( !host || !username || !password || !getParam( 3, port ) )
{
return new BError( "Invalid parameters" );
}
2024-07-20 03:20:28 +02:00
auto connector = [host = host->getStringRep(), username = username->getStringRep(),
password = password->getStringRep(), port]( Core::BSQLConnection* conn )
{ return conn->connect( host.c_str(), username.c_str(), password.c_str(), port ); };
return background_connect<Core::BSQLConnection>( uoexec().weakptr, connector );
}
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_select_db()
{
Core::BSQLConnection* sql =
static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
const String* db = getStringParam( 1 );
if ( !sql || !db )
{
return new BError( "Invalid parameters" );
}
return background_select( uoexec().weakptr, sql, db->getStringRep() );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_query()
{
Core::BSQLConnection* sql =
static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
const String* query = getStringParam( 1 );
ObjArray* params;
bool use_parameters = getObjArrayParam( 2, params );
if ( !sql || !query )
{
return new BError( "Invalid parameters" );
}
2016-02-11 22:54:43 +01:00
return background_query( uoexec().weakptr, sql, query->getStringRep(),
use_parameters ? params : nullptr );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_fields()
{
Core::BSQLResultSet* result =
static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
if ( !result )
{
return new BError( "Invalid parameters" );
}
return new BLong( result->num_fields() );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_field_name()
{
Core::BSQLResultSet* result =
static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
int index;
if ( !getParam( 1, index ) )
return new BError( "Invalid parameters" );
2016-02-11 22:54:43 +01:00
if ( !result || !index )
{
return new BError( "Invalid parameters" );
}
const char* name = result->field_name( index );
if ( name == nullptr )
return new BError( "Column does not exist" );
return new String( name, String::Tainted::YES );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_affected_rows()
{
Core::BSQLResultSet* result =
static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
if ( !result )
{
return new BError( "Invalid parameters" );
}
return new BLong( result->affected_rows() );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_rows()
{
Core::BSQLResultSet* result =
static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
if ( !result )
{
return new BError( "Invalid parameters" );
}
return new BLong( result->num_rows() );
}
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_close()
{
Core::BSQLConnection* sql =
static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
if ( !sql )
return new BError( "Invalid parameters" );
sql->close();
return new BLong( 1 );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_fetch_row()
{
Core::BSQLResultSet* result =
static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
if ( !result )
{
return new BError( "Invalid parameters" );
}
2023-05-25 08:13:39 +02:00
else if ( !result->has_result() )
{
return new BError( "Query returned no result" );
}
return new Core::BSQLRow( result );
}
2016-02-11 22:54:43 +01:00
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_escape_string()
{
Core::BSQLConnection* sql =
static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
const String* text;
if ( !sql || !getStringParam( 1, text ) )
return new BError( "Invalid parameters" );
std::string escaped;
if ( !sql->escape_string( text->value(), &escaped ) )
return new BError( "failed to escape string" );
return new String( escaped );
}
2016-02-11 22:54:43 +01:00
#else
#define MF_NO_MYSQL( funcName ) \
BObjectImp* SQLExecutorModule::funcName() \
{ \
return new BError( "POL was not compiled with MySQL support." ); \
2016-02-11 22:54:43 +01:00
}
MF_NO_MYSQL( mf_mysql_connect )
MF_NO_MYSQL( mf_mysql_select_db )
MF_NO_MYSQL( mf_mysql_query )
MF_NO_MYSQL( mf_mysql_num_fields )
MF_NO_MYSQL( mf_mysql_field_name )
MF_NO_MYSQL( mf_mysql_affected_rows )
MF_NO_MYSQL( mf_mysql_num_rows )
MF_NO_MYSQL( mf_mysql_close )
MF_NO_MYSQL( mf_mysql_fetch_row )
MF_NO_MYSQL( mf_mysql_escape_string )
#endif
} // namespace Module
} // namespace Pol