• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 25918451630

15 May 2026 12:43PM UTC coverage: 60.929% (+2.1%) from 58.859%
25918451630

push

github

turleypol
added dynamic property which returns a pointer of the object instead of
a copy like the current imp.
needed to be able to eg store a vector

43 of 61 new or added lines in 2 files covered. (70.49%)

14455 existing lines in 345 files now uncovered.

44695 of 73356 relevant lines covered (60.93%)

449621.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.91
/pol-core/pol/module/sqlmod.cpp
1
/** @file
2
 *
3
 * @par History
4
 */
5

6
#include "pol_global_config.h"
7

8
#include "sqlmod.h"
9
#include <stddef.h>
10

11
#include "../../bscript/berror.h"
12
#include "../../bscript/impstr.h"
13
#include "../../clib/logfacility.h"
14
#include "../../clib/refptr.h"
15
#include "../../clib/weakptr.h"
16
#include "../globals/network.h"
17
#include "../polsem.h"
18
#include "../sqlscrobj.h"
19
#include "../uoexec.h"
20

21
#include <module_defs/sql.h>
22

23
#include <memory>
24

25

26
namespace Pol::Module
27
{
28
using namespace Bscript;
29

30
SQLExecutorModule::SQLExecutorModule( Bscript::Executor& exec )
379✔
31
    : Bscript::TmplExecutorModule<SQLExecutorModule, Core::PolModule>( exec )
379✔
32
{
33
}
379✔
34

35
size_t SQLExecutorModule::sizeEstimate() const
14✔
36
{
37
  return sizeof( *this );
14✔
38
}
39

40
BObjectImp* SQLExecutorModule::background_connect( weak_ptr<Core::UOExecutor> uoexec,
1✔
41
                                                   const std::string host,
42
                                                   const std::string username,
43
                                                   const std::string password, int port )
44
{
45
  auto msg = [uoexec, host, username, password, port]()
2✔
46
  {
47
    std::unique_ptr<Core::BSQLConnection> sql;
1✔
48
    {
49
      Core::PolLock lck;
1✔
50
      sql = std::make_unique<Core::BSQLConnection>();
1✔
51
    }
1✔
52
    if ( sql->getLastErrNo() )
1✔
53
    {
UNCOV
54
      Core::PolLock lck;
×
55
      if ( !uoexec.exists() )
×
56
        INFO_PRINTLN( "Script has been destroyed" );
×
57
      else
58
      {
UNCOV
59
        uoexec.get_weakptr()->ValueStack.back().set(
×
60
            new BObject( new BError( "Insufficient memory" ) ) );
×
61
        uoexec.get_weakptr()->revive();
×
62
      }
UNCOV
63
    }
×
64
    else if ( !sql->connect( host.data(), username.data(), password.data(), port ) )
1✔
65
    {
UNCOV
66
      Core::PolLock lck;
×
67
      if ( !uoexec.exists() )
×
68
        INFO_PRINTLN( "Script has been destroyed" );
×
69
      else
70
      {
UNCOV
71
        uoexec.get_weakptr()->ValueStack.back().set(
×
72
            new BObject( new BError( sql->getLastError() ) ) );
×
73
        uoexec.get_weakptr()->revive();
×
74
      }
UNCOV
75
    }
×
76
    else
77
    {
78
      Core::PolLock lck;
1✔
79
      if ( !uoexec.exists() )
1✔
UNCOV
80
        INFO_PRINTLN( "Script has been destroyed" );
×
81
      else
82
      {
83
        uoexec.get_weakptr()->ValueStack.back().set( new BObject( sql.release() ) );
1✔
84
        uoexec.get_weakptr()->revive();
1✔
85
      }
86
    }
1✔
87
  };
2✔
88

89
  if ( !uoexec->suspend() )
1✔
90
  {
UNCOV
91
    DEBUGLOGLN(
×
92
        "Script Error in '{}' PC={}: \n"
93
        "\tThe execution of this script can't be blocked!",
UNCOV
94
        uoexec->scriptname(), uoexec->PC );
×
95
    return new Bscript::BError( "Script can't be blocked" );
×
96
  }
97

98
  Core::networkManager.sql_service->push( std::move( msg ) );
1✔
99
  return new BLong( 0 );
1✔
100
}
1✔
101

102
Bscript::BObjectImp* SQLExecutorModule::background_select( weak_ptr<Core::UOExecutor> uoexec,
1✔
103
                                                           Core::BSQLConnection* sql,
104
                                                           const std::string db )
105
{
106
  // The BSQLConnection shouldn't be destroyed before the lambda runs
107
  ref_ptr<Core::BSQLConnection> sqlRef( sql );
1✔
108
  auto msg = [uoexec, sqlRef, db]()
1✔
109
  {
110
    if ( sqlRef == nullptr )
1✔
111
    {
UNCOV
112
      Core::PolLock lck;
×
113
      if ( !uoexec.exists() )
×
114
        INFO_PRINTLN( "Script has been destroyed" );
×
115
      else
116
      {
UNCOV
117
        uoexec.get_weakptr()->ValueStack.back().set(
×
118
            new BObject( new BError( "Invalid parameters" ) ) );
×
119
        uoexec.get_weakptr()->revive();
×
120
      }
UNCOV
121
    }
×
122
    else if ( !sqlRef->select_db( db.c_str() ) )
1✔
123
    {
UNCOV
124
      Core::PolLock lck;
×
125
      if ( !uoexec.exists() )
×
126
        INFO_PRINTLN( "Script has been destroyed" );
×
127
      else
128
      {
UNCOV
129
        uoexec.get_weakptr()->ValueStack.back().set(
×
130
            new BObject( new BError( sqlRef->getLastError() ) ) );
×
131
        uoexec.get_weakptr()->revive();
×
132
      }
UNCOV
133
    }
×
134
    else
135
    {
136
      Core::PolLock lck;
1✔
137
      if ( !uoexec.exists() )
1✔
UNCOV
138
        INFO_PRINTLN( "Script has been destroyed" );
×
139
      else
140
      {
141
        uoexec.get_weakptr()->ValueStack.back().set( new BObject( new BLong( 1 ) ) );
1✔
142
        uoexec.get_weakptr()->revive();
1✔
143
      }
144
    }
1✔
145
  };
2✔
146

147
  if ( !uoexec->suspend() )
1✔
148
  {
UNCOV
149
    DEBUGLOGLN(
×
150
        "Script Error in '{}' PC={}: \n"
151
        "\tThe execution of this script can't be blocked!",
UNCOV
152
        uoexec->scriptname(), uoexec->PC );
×
153
    return new Bscript::BError( "Script can't be blocked" );
×
154
  }
155
  Core::networkManager.sql_service->push( std::move( msg ) );
1✔
156
  return new BLong( 0 );
1✔
157
}
1✔
158

159
Bscript::BObjectImp* SQLExecutorModule::background_query( weak_ptr<Core::UOExecutor> uoexec,
8✔
160
                                                          Core::BSQLConnection* sql,
161
                                                          const std::string query,
162
                                                          const Bscript::ObjArray* params )
163
{
164
  // Copy and parse params before they will be deleted by this thread (go out of scope)
165
  Core::QueryParams sharedParams( nullptr );
8✔
166
  if ( params != nullptr )
8✔
167
  {
168
    sharedParams = std::make_shared<Core::QueryParam>();
8✔
169

170
    for ( const auto& ref : params->ref_arr )
10✔
171
    {
172
      const BObject* obj = ref.get();
2✔
173
      if ( obj != nullptr )
2✔
174
        sharedParams->insert( sharedParams->end(), obj->impptr()->getStringRep() );
2✔
175
    }
176
  }
177

178
  // The BSQLConnection shouldn't be destroyed before the lambda runs
179
  ref_ptr<Core::BSQLConnection> sqlRef( sql );
8✔
180
  auto msg = [uoexec, sqlRef, query, sharedParams]()
8✔
181
  {
182
    if ( sqlRef == nullptr )  // TODO: this doesn't make any sense and should be checked before the
8✔
183
                              // lambda. Same happens in background_select().
184
    {
UNCOV
185
      Core::PolLock lck;
×
UNCOV
186
      if ( !uoexec.exists() )
×
187
        INFO_PRINTLN( "Script has been destroyed" );
×
188
      else
189
      {
UNCOV
190
        uoexec.get_weakptr()->ValueStack.back().set(
×
UNCOV
191
            new BObject( new BError( "Invalid parameters" ) ) );
×
192
        uoexec.get_weakptr()->revive();
×
193
      }
194
    }
×
195
    else if ( !sqlRef->query( query, sharedParams ) )
8✔
196
    {
UNCOV
197
      Core::PolLock lck;
×
UNCOV
198
      if ( !uoexec.exists() )
×
199
        INFO_PRINTLN( "Script has been destroyed" );
×
200
      else
201
      {
UNCOV
202
        uoexec.get_weakptr()->ValueStack.back().set(
×
UNCOV
203
            new BObject( new BError( sqlRef->getLastError() ) ) );
×
204
        uoexec.get_weakptr()->revive();
×
205
      }
206
    }
×
207
    else
208
    {
209
      Core::PolLock lck;
8✔
210
      if ( !uoexec.exists() )
8✔
UNCOV
211
        INFO_PRINTLN( "Script has been destroyed" );
×
212
      else
213
      {
214
        uoexec.get_weakptr()->ValueStack.back().set( new BObject( sqlRef->getResultSet() ) );
8✔
215
        uoexec.get_weakptr()->revive();
8✔
216
      }
217
    }
8✔
218
  };
16✔
219

220
  if ( !uoexec->suspend() )
8✔
221
  {
UNCOV
222
    DEBUGLOGLN(
×
223
        "Script Error in '{}' PC={}: \n"
224
        "\tThe execution of this script can't be blocked!",
UNCOV
225
        uoexec->scriptname(), uoexec->PC );
×
UNCOV
226
    return new Bscript::BError( "Script can't be blocked" );
×
227
  }
228

229
  Core::networkManager.sql_service->push( std::move( msg ) );
8✔
230
  return new BLong( 0 );
8✔
231
}
8✔
232

233
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_connect()
1✔
234
{
235
  const String* host = getStringParam( 0 );
1✔
236
  const String* username = getStringParam( 1 );
1✔
237
  const String* password = getStringParam( 2 );
1✔
238
  int port;
239
  if ( !host || !username || !password || !getParam( 3, port ) )
1✔
240
  {
UNCOV
241
    return new BError( "Invalid parameters" );
×
242
  }
243
  return background_connect( uoexec().weakptr, host->getStringRep(), username->getStringRep(),
2✔
244
                             password->getStringRep(), port );
3✔
245
}
246
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_select_db()
1✔
247
{
248
  Core::BSQLConnection* sql =
249
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
1✔
250
  const String* db = getStringParam( 1 );
1✔
251
  if ( !sql || !db )
1✔
252
  {
UNCOV
253
    return new BError( "Invalid parameters" );
×
254
  }
255
  return background_select( uoexec().weakptr, sql, db->getStringRep() );
1✔
256
}
257

258
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_query()
8✔
259
{
260
  Core::BSQLConnection* sql =
261
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
8✔
262
  const String* query = getStringParam( 1 );
8✔
263
  ObjArray* params;
264
  bool use_parameters = getObjArrayParam( 2, params );
8✔
265
  if ( !sql || !query )
8✔
266
  {
UNCOV
267
    return new BError( "Invalid parameters" );
×
268
  }
269

270
  return background_query( uoexec().weakptr, sql, query->getStringRep(),
16✔
271
                           use_parameters ? params : nullptr );
8✔
272
}
273

UNCOV
274
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_fields()
×
275
{
276
  Core::BSQLResultSet* result =
UNCOV
277
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
×
UNCOV
278
  if ( !result )
×
279
  {
280
    return new BError( "Invalid parameters" );
×
281
  }
282
  return new BLong( result->num_fields() );
×
283
}
284

UNCOV
285
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_field_name()
×
286
{
287
  Core::BSQLResultSet* result =
UNCOV
288
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
×
289
  int index;
290
  if ( !getParam( 1, index ) )
×
UNCOV
291
    return new BError( "Invalid parameters" );
×
292

293
  if ( !result || !index )
×
294
  {
295
    return new BError( "Invalid parameters" );
×
296
  }
297
  const char* name = result->field_name( index );
×
UNCOV
298
  if ( name == nullptr )
×
299
    return new BError( "Column does not exist" );
×
300
  return new String( name, String::Tainted::YES );
×
301
}
302

UNCOV
303
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_affected_rows()
×
304
{
305
  Core::BSQLResultSet* result =
UNCOV
306
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
×
UNCOV
307
  if ( !result )
×
308
  {
309
    return new BError( "Invalid parameters" );
×
310
  }
311
  return new BLong( result->affected_rows() );
×
312
}
313

314
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_rows()
6✔
315
{
316
  Core::BSQLResultSet* result =
317
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
6✔
318
  if ( !result )
6✔
319
  {
UNCOV
320
    return new BError( "Invalid parameters" );
×
321
  }
322
  return new BLong( result->num_rows() );
6✔
323
}
324

UNCOV
325
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_close()
×
326
{
327
  Core::BSQLConnection* sql =
UNCOV
328
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
×
UNCOV
329
  if ( !sql )
×
330
    return new BError( "Invalid parameters" );
×
331
  sql->close();
×
332
  return new BLong( 1 );
×
333
}
334

335
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_fetch_row()
6✔
336
{
337
  Core::BSQLResultSet* result =
338
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
6✔
339
  if ( !result )
6✔
340
  {
UNCOV
341
    return new BError( "Invalid parameters" );
×
342
  }
343
  if ( !result->has_result() )
6✔
344
  {
UNCOV
345
    return new BError( "Query returned no result" );
×
346
  }
347
  return new Core::BSQLRow( result );
6✔
348
}
349

350
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_escape_string()
1✔
351
{
352
  Core::BSQLConnection* sql =
353
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
1✔
354
  const String* text;
355
  if ( !sql || !getStringParam( 1, text ) )
1✔
UNCOV
356
    return new BError( "Invalid parameters" );
×
357

358
  std::string escaped;
1✔
359
  if ( !sql->escape_string( text->value(), &escaped ) )
1✔
UNCOV
360
    return new BError( "failed to escape string" );
×
361
  return new String( escaped );
1✔
362
}
1✔
363
}  // namespace Pol::Module
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc