Pol  Revision:cb584c9
sqlmod.cpp
Go to the documentation of this file.
1 
6 #include "pol_global_config.h"
7 
8 #include "sqlmod.h"
9 
10 #include <stddef.h>
11 
12 #include "../../bscript/berror.h"
13 #include "../../bscript/impstr.h"
14 #include "../../clib/logfacility.h"
15 #include "../../clib/refptr.h"
16 #include "../../clib/weakptr.h"
17 #include "../globals/network.h"
18 #include "../polsem.h"
19 #include "../sqlscrobj.h"
20 #include "../uoexec.h"
21 #include "osmod.h"
22 
23 
24 namespace Pol
25 {
26 namespace Bscript
27 {
28 using namespace Module;
29 template <>
32  {"MySQL_Connect", &SQLExecutorModule::mf_ConnectToDB},
33  {"MySQL_Query", &SQLExecutorModule::mf_Query},
34  {"MySQL_Close", &SQLExecutorModule::mf_Close},
35  {"MySQL_Num_Fields", &SQLExecutorModule::mf_NumFields},
36  {"MySQL_Fetch_Row", &SQLExecutorModule::mf_FetchRow},
37  {"MySQL_Affected_Rows", &SQLExecutorModule::mf_AffectedRows},
38  {"MySQL_Num_Rows", &SQLExecutorModule::mf_NumRows},
39  {"MySQL_Select_Db", &SQLExecutorModule::mf_SelectDb},
40  {"MySQL_Field_Name", &SQLExecutorModule::mf_FieldName}};
41 }
42 namespace Module
43 {
44 using namespace Bscript;
45 
47  : Bscript::TmplExecutorModule<SQLExecutorModule>( "sql", exec ),
48  uoexec( static_cast<Core::UOExecutor&>( exec ) )
49 {
50 }
51 
52 #ifdef HAVE_MYSQL
53 
55  const std::string host,
56  const std::string username,
57  const std::string password )
58 {
59  auto msg = [uoexec, host, username, password]() {
60  std::unique_ptr<Core::BSQLConnection> sql;
61  {
62  Core::PolLock lck;
63  sql = std::unique_ptr<Core::BSQLConnection>( new Core::BSQLConnection() );
64  }
65  if ( sql->getLastErrNo() )
66  {
67  Core::PolLock lck;
68  if ( !uoexec.exists() )
69  INFO_PRINT << "Script has been destroyed\n";
70  else
71  {
72  uoexec.get_weakptr()->ValueStack.back().set(
73  new BObject( new BError( "Insufficient memory" ) ) );
74  uoexec.get_weakptr()->os_module->revive();
75  }
76  }
77  else if ( !sql->connect( host.data(), username.data(), password.data() ) )
78  {
79  Core::PolLock lck;
80  if ( !uoexec.exists() )
81  INFO_PRINT << "Script has been destroyed\n";
82  else
83  {
84  uoexec.get_weakptr()->ValueStack.back().set(
85  new BObject( new BError( sql->getLastError() ) ) );
86  uoexec.get_weakptr()->os_module->revive();
87  }
88  }
89  else
90  {
91  Core::PolLock lck;
92  if ( !uoexec.exists() )
93  INFO_PRINT << "Script has been destroyed\n";
94  else
95  {
96  uoexec.get_weakptr()->ValueStack.back().set( new BObject( sql.release() ) );
97  uoexec.get_weakptr()->os_module->revive();
98  }
99  }
100  };
101 
102  if ( !uoexec->suspend() )
103  {
104  DEBUGLOG << "Script Error in '" << uoexec->scriptname() << "' PC=" << uoexec->PC << ": \n"
105  << "\tThe execution of this script can't be blocked!\n";
106  return new Bscript::BError( "Script can't be blocked" );
107  }
108 
109  Core::networkManager.sql_service->push( std::move( msg ) );
110  return new BLong( 0 );
111 }
112 
115  const std::string db )
116 {
117  // The BSQLConnection shouldn't be destroyed before the lambda runs
118  ref_ptr<Core::BSQLConnection> sqlRef( sql );
119  auto msg = [uoexec, sqlRef, db]() {
120  if ( sqlRef == nullptr )
121  {
122  Core::PolLock lck;
123  if ( !uoexec.exists() )
124  INFO_PRINT << "Script has been destroyed\n";
125  else
126  {
127  uoexec.get_weakptr()->ValueStack.back().set(
128  new BObject( new BError( "Invalid parameters" ) ) );
129  uoexec.get_weakptr()->os_module->revive();
130  }
131  }
132  else if ( !sqlRef->select_db( db.c_str() ) )
133  {
134  Core::PolLock lck;
135  if ( !uoexec.exists() )
136  INFO_PRINT << "Script has been destroyed\n";
137  else
138  {
139  uoexec.get_weakptr()->ValueStack.back().set(
140  new BObject( new BError( sqlRef->getLastError() ) ) );
141  uoexec.get_weakptr()->os_module->revive();
142  }
143  }
144  else
145  {
146  Core::PolLock lck;
147  if ( !uoexec.exists() )
148  INFO_PRINT << "Script has been destroyed\n";
149  else
150  {
151  uoexec.get_weakptr()->ValueStack.back().set( new BObject( new BLong( 1 ) ) );
152  uoexec.get_weakptr()->os_module->revive();
153  }
154  }
155  };
156 
157  if ( !uoexec->suspend() )
158  {
159  DEBUGLOG << "Script Error in '" << uoexec->scriptname() << "' PC=" << uoexec->PC << ": \n"
160  << "\tThe execution of this script can't be blocked!\n";
161  return new Bscript::BError( "Script can't be blocked" );
162  }
163  Core::networkManager.sql_service->push( std::move( msg ) );
164  return new BLong( 0 );
165 }
166 
169  const std::string query,
170  const Bscript::ObjArray* params )
171 {
172  // Copy and parse params before they will be deleted by this thread (go out of scope)
173  Core::QueryParams sharedParams( nullptr );
174  if ( params != nullptr )
175  {
176  sharedParams = std::make_shared<Core::QueryParam>();
177 
178  for ( unsigned i = 0; i < params->ref_arr.size(); ++i )
179  {
180  const BObjectRef& ref = params->ref_arr[i];
181  const BObject* obj = ref.get();
182  if ( obj != nullptr )
183  sharedParams->insert( sharedParams->end(), obj->impptr()->getStringRep() );
184  }
185  }
186 
187  // The BSQLConnection shouldn't be destroyed before the lambda runs
188  ref_ptr<Core::BSQLConnection> sqlRef( sql );
189  auto msg = [uoexec, sqlRef, query, sharedParams]() {
190  if ( sqlRef == nullptr ) // TODO: this doesn't make any sense and should be checked before the
191  // lambda. Same happens in background_select().
192  {
193  Core::PolLock lck;
194  if ( !uoexec.exists() )
195  INFO_PRINT << "Script has been destroyed\n";
196  else
197  {
198  uoexec.get_weakptr()->ValueStack.back().set(
199  new BObject( new BError( "Invalid parameters" ) ) );
200  uoexec.get_weakptr()->os_module->revive();
201  }
202  }
203  else if ( !sqlRef->query( query, sharedParams ) )
204  {
205  Core::PolLock lck;
206  if ( !uoexec.exists() )
207  INFO_PRINT << "Script has been destroyed\n";
208  else
209  {
210  uoexec.get_weakptr()->ValueStack.back().set(
211  new BObject( new BError( sqlRef->getLastError() ) ) );
212  uoexec.get_weakptr()->os_module->revive();
213  }
214  }
215  else
216  {
217  Core::PolLock lck;
218  if ( !uoexec.exists() )
219  INFO_PRINT << "Script has been destroyed\n";
220  else
221  {
222  uoexec.get_weakptr()->ValueStack.back().set( new BObject( sqlRef->getResultSet() ) );
223  uoexec.get_weakptr()->os_module->revive();
224  }
225  }
226  };
227 
228  if ( !uoexec->suspend() )
229  {
230  DEBUGLOG << "Script Error in '" << uoexec->scriptname() << "' PC=" << uoexec->PC << ": \n"
231  << "\tThe execution of this script can't be blocked!\n";
232  return new Bscript::BError( "Script can't be blocked" );
233  }
234 
235  Core::networkManager.sql_service->push( std::move( msg ) );
236  return new BLong( 0 );
237 }
238 
240 {
241  const String* host = getStringParam( 0 );
242  const String* username = getStringParam( 1 );
243  const String* password = getStringParam( 2 );
244  if ( !host || !username || !password )
245  {
246  return new BError( "Invalid parameters" );
247  }
248  return background_connect( uoexec.weakptr, host->getStringRep(), username->getStringRep(),
249  password->getStringRep() );
250 }
252 {
253  Core::BSQLConnection* sql =
255  const String* db = getStringParam( 1 );
256  if ( !sql || !db )
257  {
258  return new BError( "Invalid parameters" );
259  }
260  return background_select( uoexec.weakptr, sql, db->getStringRep() );
261 }
262 
264 {
265  Core::BSQLConnection* sql =
267  const String* query = getStringParam( 1 );
268  ObjArray* params;
269  bool use_parameters = getObjArrayParam( 2, params );
270  if ( !sql || !query )
271  {
272  return new BError( "Invalid parameters" );
273  }
274 
275  return background_query( uoexec.weakptr, sql, query->getStringRep(),
276  use_parameters ? params : nullptr );
277 }
278 
280 {
281  Core::BSQLResultSet* result =
283  if ( !result )
284  {
285  return new BError( "Invalid parameters" );
286  }
287  return new BLong( result->num_fields() );
288 }
289 
291 {
292  Core::BSQLResultSet* result =
294  int index;
295  if ( !getParam( 1, index ) )
296  return new BError( "Invalid parameters" );
297 
298  if ( !result || !index )
299  {
300  return new BError( "Invalid parameters" );
301  }
302  const char* name = result->field_name( index );
303  if ( name == 0 )
304  return new BError( "Column does not exist" );
305  return new String( name );
306 }
307 
309 {
310  Core::BSQLResultSet* result =
312  ;
313  if ( !result )
314  {
315  return new BError( "Invalid parameters" );
316  }
317  return new BLong( result->affected_rows() );
318 }
319 
321 {
322  Core::BSQLResultSet* result =
324  ;
325  if ( !result )
326  {
327  return new BError( "Invalid parameters" );
328  }
329  return new BLong( result->num_rows() );
330 }
331 
333 {
334  Core::BSQLConnection* sql =
336  if ( !sql )
337  return new BError( "Invalid parameters" );
338  sql->close();
339  return new BLong( 1 );
340 }
341 
343 {
344  Core::BSQLResultSet* result =
346  if ( !result )
347  {
348  return new BError( "Invalid parameters" );
349  }
350  return new Core::BSQLRow( result );
351 }
352 
353 #else
354 
355 #define MF_NO_MYSQL( funcName ) \
356  BObjectImp* SQLExecutorModule::funcName() \
357  { \
358  return new BError( "POL was not compiled with MySQL support." ); \
359  }
360 MF_NO_MYSQL( mf_ConnectToDB )
361 MF_NO_MYSQL( mf_SelectDb )
362 MF_NO_MYSQL( mf_Query )
363 MF_NO_MYSQL( mf_NumFields )
364 MF_NO_MYSQL( mf_FieldName )
365 MF_NO_MYSQL( mf_AffectedRows )
366 MF_NO_MYSQL( mf_NumRows )
367 MF_NO_MYSQL( mf_Close )
368 MF_NO_MYSQL( mf_FetchRow )
369 #endif
370 }
371 }
virtual std::string getStringRep() const =0
const char * field_name(unsigned int index) const
Definition: sqlscrobj.cpp:147
Bscript::BObjectImp * mf_NumRows()
Definition: sqlmod.cpp:320
Bscript::BObjectImp * mf_Close()
Definition: sqlmod.cpp:332
Bscript::BObjectImp * mf_ConnectToDB()
Definition: sqlmod.cpp:239
T * get() const
Definition: refptr.h:176
bool getParam(unsigned param, int &value)
Definition: execmodl.cpp:62
virtual std::string getStringRep() const POL_OVERRIDE
Definition: impstr.h:129
int affected_rows() const
Definition: sqlscrobj.cpp:177
T * get_weakptr() const
Definition: weakptr.h:110
BObjectImp * getParamImp(unsigned param)
Definition: execmodl.cpp:22
std::unique_ptr< SQLService > sql_service
Definition: network.h:61
Bscript::BObjectImp * mf_Query()
Definition: sqlmod.cpp:263
SQLExecutorModule(Bscript::Executor &exec)
Definition: sqlmod.cpp:46
#define DEBUGLOG
Definition: logfacility.h:237
Definition: refptr.h:65
NetworkManager networkManager
Definition: network.cpp:28
std::shared_ptr< QueryParam > QueryParams
Definition: sqlscrobj.h:120
bool exists() const
Definition: weakptr.h:115
weak_ptr_owner< UOExecutor > weakptr
Definition: uoexec.h:62
const String * getStringParam(unsigned param)
Definition: execmodl.cpp:36
Bscript::BObjectImp * mf_NumFields()
Definition: sqlmod.cpp:279
Bscript::BObjectImp * mf_FetchRow()
Definition: sqlmod.cpp:342
Core::UOExecutor & uoexec
Definition: sqlmod.h:65
Bscript::BObjectImp * mf_AffectedRows()
Definition: sqlmod.cpp:308
Bscript::BObjectImp * mf_FieldName()
Definition: sqlmod.cpp:290
std::string name
Definition: osmod.cpp:943
static Bscript::BObjectImp * background_query(weak_ptr< Core::UOExecutor > uoexec, Core::BSQLConnection *sql, const std::string query, const Bscript::ObjArray *params)
Definition: sqlmod.cpp:167
static Bscript::BObjectImp * background_connect(weak_ptr< Core::UOExecutor > uoexec, const std::string host, const std::string username, const std::string password)
Definition: sqlmod.cpp:54
bool getObjArrayParam(unsigned param, ObjArray *&pobjarr)
Definition: execmodl.cpp:57
Bscript::BObjectImp * mf_SelectDb()
Definition: sqlmod.cpp:251
#define INFO_PRINT
Definition: logfacility.h:223
Definition: berror.cpp:12
static Bscript::BObjectImp * background_select(weak_ptr< Core::UOExecutor > uoexec, Core::BSQLConnection *sql, const std::string db)
Definition: sqlmod.cpp:113