2016-02-11 22:54:43 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
*/
|
|
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "pol_global_config.h"
|
|
|
|
|
|
2016-02-11 22:54:43 +01:00
|
|
|
#include "sqlmod.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <stddef.h>
|
|
|
|
|
|
2016-02-11 22:54:43 +01:00
|
|
|
#include "../../bscript/berror.h"
|
|
|
|
|
#include "../../bscript/impstr.h"
|
|
|
|
|
#include "../../clib/logfacility.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../../clib/refptr.h"
|
|
|
|
|
#include "../../clib/weakptr.h"
|
2016-12-20 23:53:32 +01:00
|
|
|
#include "../globals/network.h"
|
|
|
|
|
#include "../polsem.h"
|
|
|
|
|
#include "../sqlscrobj.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../uoexec.h"
|
|
|
|
|
|
2019-11-10 22:04:08 +01:00
|
|
|
#include <module_defs/sql.h>
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Module
|
|
|
|
|
{
|
|
|
|
|
using namespace Bscript;
|
2016-12-14 21:50:23 +01:00
|
|
|
|
|
|
|
|
SQLExecutorModule::SQLExecutorModule( Bscript::Executor& exec )
|
2020-02-08 09:21:35 +01:00
|
|
|
: Bscript::TmplExecutorModule<SQLExecutorModule, Core::PolModule>( exec )
|
2016-12-14 21:50:23 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-01 23:18:43 +01:00
|
|
|
size_t SQLExecutorModule::sizeEstimate() const
|
|
|
|
|
{
|
|
|
|
|
return sizeof( *this );
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 22:54:43 +01:00
|
|
|
#ifdef HAVE_MYSQL
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
BObjectImp* SQLExecutorModule::background_connect( weak_ptr<Core::UOExecutor> uoexec,
|
|
|
|
|
const std::string host,
|
|
|
|
|
const std::string username,
|
|
|
|
|
const std::string password )
|
|
|
|
|
{
|
2018-01-29 21:55:48 +01:00
|
|
|
auto msg = [uoexec, host, username, password]() {
|
2016-02-19 19:26:35 +01:00
|
|
|
std::unique_ptr<Core::BSQLConnection> sql;
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
Core::PolLock lck;
|
|
|
|
|
sql = std::unique_ptr<Core::BSQLConnection>( new Core::BSQLConnection() );
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( sql->getLastErrNo() )
|
|
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uoexec.get_weakptr()->ValueStack.back().set(
|
|
|
|
|
new BObject( new BError( "Insufficient memory" ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( !sql->connect( host.data(), username.data(), password.data() ) )
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uoexec.get_weakptr()->ValueStack.back().set(
|
|
|
|
|
new BObject( new BError( sql->getLastError() ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
else
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
uoexec.get_weakptr()->ValueStack.back().set( new BObject( sql.release() ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-07-30 22:31:58 +02:00
|
|
|
if ( !uoexec->suspend() )
|
|
|
|
|
{
|
|
|
|
|
DEBUGLOG << "Script Error in '" << uoexec->scriptname() << "' PC=" << uoexec->PC << ": \n"
|
2018-01-29 21:55:48 +01:00
|
|
|
<< "\tThe execution of this script can't be blocked!\n";
|
2017-07-30 22:31:58 +02:00
|
|
|
return new Bscript::BError( "Script can't be blocked" );
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
Core::networkManager.sql_service->push( std::move( msg ) );
|
|
|
|
|
return new BLong( 0 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-03-23 18:40:10 +01:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::background_select( weak_ptr<Core::UOExecutor> uoexec,
|
2018-01-29 21:55:48 +01:00
|
|
|
Core::BSQLConnection* sql,
|
|
|
|
|
const std::string db )
|
|
|
|
|
{
|
2016-03-23 18:40:10 +01:00
|
|
|
// The BSQLConnection shouldn't be destroyed before the lambda runs
|
|
|
|
|
ref_ptr<Core::BSQLConnection> sqlRef( sql );
|
2018-01-29 21:55:48 +01:00
|
|
|
auto msg = [uoexec, sqlRef, db]() {
|
2016-03-23 18:40:10 +01:00
|
|
|
if ( sqlRef == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uoexec.get_weakptr()->ValueStack.back().set(
|
|
|
|
|
new BObject( new BError( "Invalid parameters" ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-23 18:40:10 +01:00
|
|
|
else if ( !sqlRef->select_db( db.c_str() ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uoexec.get_weakptr()->ValueStack.back().set(
|
2018-01-29 21:55:48 +01:00
|
|
|
new BObject( new BError( sqlRef->getLastError() ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uoexec.get_weakptr()->ValueStack.back().set( new BObject( new BLong( 1 ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
};
|
2017-07-30 22:31:58 +02:00
|
|
|
|
|
|
|
|
if ( !uoexec->suspend() )
|
|
|
|
|
{
|
|
|
|
|
DEBUGLOG << "Script Error in '" << uoexec->scriptname() << "' PC=" << uoexec->PC << ": \n"
|
2018-01-29 21:55:48 +01:00
|
|
|
<< "\tThe execution of this script can't be blocked!\n";
|
2017-07-30 22:31:58 +02:00
|
|
|
return new Bscript::BError( "Script can't be blocked" );
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
Core::networkManager.sql_service->push( std::move( msg ) );
|
|
|
|
|
return new BLong( 0 );
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-23 18:40:10 +01:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::background_query( weak_ptr<Core::UOExecutor> uoexec,
|
2018-01-29 21:55:48 +01:00
|
|
|
Core::BSQLConnection* sql,
|
|
|
|
|
const std::string query,
|
|
|
|
|
const Bscript::ObjArray* params )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
// 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
|
|
|
|
2016-02-19 19:26:35 +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 )
|
2016-02-19 19:26:35 +01:00
|
|
|
sharedParams->insert( sharedParams->end(), obj->impptr()->getStringRep() );
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-03-23 18:40:10 +01:00
|
|
|
// The BSQLConnection shouldn't be destroyed before the lambda runs
|
2018-01-29 21:55:48 +01:00
|
|
|
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().
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uoexec.get_weakptr()->ValueStack.back().set(
|
|
|
|
|
new BObject( new BError( "Invalid parameters" ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-23 18:40:10 +01:00
|
|
|
else if ( !sqlRef->query( query, sharedParams ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
uoexec.get_weakptr()->ValueStack.back().set(
|
2018-01-29 21:55:48 +01:00
|
|
|
new BObject( new BError( sqlRef->getLastError() ) ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Core::PolLock lck;
|
|
|
|
|
if ( !uoexec.exists() )
|
|
|
|
|
INFO_PRINT << "Script has been destroyed\n";
|
|
|
|
|
else
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-03-23 18:40:10 +01:00
|
|
|
uoexec.get_weakptr()->ValueStack.back().set( new BObject( sqlRef->getResultSet() ) );
|
2019-03-11 21:37:51 +01:00
|
|
|
uoexec.get_weakptr()->revive();
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
};
|
2018-01-29 21:55:48 +01:00
|
|
|
|
2017-07-30 22:31:58 +02:00
|
|
|
if ( !uoexec->suspend() )
|
|
|
|
|
{
|
|
|
|
|
DEBUGLOG << "Script Error in '" << uoexec->scriptname() << "' PC=" << uoexec->PC << ": \n"
|
2018-01-29 21:55:48 +01:00
|
|
|
<< "\tThe execution of this script can't be blocked!\n";
|
2017-07-30 22:31:58 +02:00
|
|
|
return new Bscript::BError( "Script can't be blocked" );
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
Core::networkManager.sql_service->push( std::move( msg ) );
|
|
|
|
|
return new BLong( 0 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_connect()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
const String* host = getStringParam( 0 );
|
|
|
|
|
const String* username = getStringParam( 1 );
|
|
|
|
|
const String* password = getStringParam( 2 );
|
|
|
|
|
if ( !host || !username || !password )
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameters" );
|
|
|
|
|
}
|
2020-02-08 09:21:35 +01:00
|
|
|
return background_connect( uoexec().weakptr, host->getStringRep(), username->getStringRep(),
|
2016-02-19 19:26:35 +01:00
|
|
|
password->getStringRep() );
|
|
|
|
|
}
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_select_db()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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" );
|
|
|
|
|
}
|
2020-02-08 09:21:35 +01:00
|
|
|
return background_select( uoexec().weakptr, sql, db->getStringRep() );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_query()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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
|
|
|
|
2020-02-08 09:21:35 +01:00
|
|
|
return background_query( uoexec().weakptr, sql, query->getStringRep(),
|
2016-02-19 19:26:35 +01:00
|
|
|
use_parameters ? params : nullptr );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_fields()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_field_name()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( !result || !index )
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameters" );
|
|
|
|
|
}
|
|
|
|
|
const char* name = result->field_name( index );
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( name == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
return new BError( "Column does not exist" );
|
2019-01-12 17:14:05 +01:00
|
|
|
return new String( name, String::Tainted::YES );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_affected_rows()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_rows()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_close()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
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
|
|
|
|
2019-10-17 22:37:26 +02:00
|
|
|
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_fetch_row()
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
Core::BSQLResultSet* result =
|
|
|
|
|
static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
|
|
|
|
|
if ( !result )
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameters" );
|
|
|
|
|
}
|
|
|
|
|
return new Core::BSQLRow( result );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
#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
|
|
|
}
|
2019-12-12 22:32:17 +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 )
|
2020-01-06 22:19:51 +01:00
|
|
|
MF_NO_MYSQL( mf_mysql_field_name )
|
2019-12-12 22:32:17 +01:00
|
|
|
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 )
|
2016-02-19 19:26:35 +01:00
|
|
|
#endif
|
2019-01-12 17:14:05 +01:00
|
|
|
} // namespace Module
|
|
|
|
|
} // namespace Pol
|