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

polserver / polserver / 29352231943

14 Jul 2026 05:04PM UTC coverage: 61.419% (+0.07%) from 61.349%
29352231943

push

github

web-flow
Misc modernizations and improvments (#896)

* fixed_allocator cleanup
template argument is now the type and not the size
general cleanup, rewrote refill loop to better understand whats
happening
possibility to use different alignments (not needed for the used types)

* adapted fixed_allocator usage

* simplified message_queue conditial wait, removed unused header

* use moveonlyfunction for logging queue

* cleanup and performance improvment for clienttransmit

* use moveonlyfunction for sql

* fixed use after move

* TaskThreadPool uses moveonlyfunction

* catch exception locally without stopping the complete workerthread

* message_queue pop with timeout

* DynTaskThreadPool changes

- using move_only_function
- general simplification
- minimum of 4 threads
- added idle timeout to get rid of workers

* simplified auxpoolthread usage

* fixed threadmap initialization

* to avoid static initialization problem dont prefill worker threada in
the constructor
update macos to latest which hopefully supports jthreads

* removed debug logs

* seems macos-latest is not always 26, explicitly use it

* added jitter for timeout
secured the logic when to spawn a new thread more
busyguard is now used to track a message compare value against
live_threads to decide if a new thread should be spawned
unique name per poolworker

199 of 248 new or added lines in 15 files covered. (80.24%)

1 existing line in 1 file now uncovered.

45056 of 73359 relevant lines covered (61.42%)

634055.61 hits per line

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

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

6
#include "sqlmod.h"
7
#include <stddef.h>
8

9
#include "bscript/barray.h"
10
#include "bscript/berror.h"
11
#include "bscript/blong.h"
12
#include "bscript/bstring.h"
13
#include "clib/logfacility.h"
14
#include "clib/refptr.h"
15
#include "clib/weakptr.h"
16

17
#include "../globals/network.h"
18
#include "../polsem.h"
19
#include "../sqlscrobj.h"
20
#include "../uoexec.h"
21

22
#include <module_defs/sql.h>
23

24
#include <memory>
25

26

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

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

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

41
BObjectImp* SQLExecutorModule::background_connect( weak_ptr<Core::UOExecutor> uoexec,
1✔
42
                                                   std::string host, std::string username,
43
                                                   std::string password, int port )
44
{
45
  if ( !uoexec->suspend() )
1✔
46
  {
47
    DEBUGLOGLN(
×
48
        "Script Error in '{}' PC={}: \n"
49
        "\tThe execution of this script can't be blocked!",
50
        uoexec->scriptname(), uoexec->PC );
×
51
    return new Bscript::BError( "Script can't be blocked" );
×
52
  }
53
  Core::networkManager.sql_service->push(
2✔
54
      [uoexec = std::move( uoexec ), host = std::move( host ), username = std::move( username ),
3✔
55
       password = std::move( password ), port]()
1✔
56
      {
57
        std::unique_ptr<Core::BSQLConnection> sql;
1✔
58
        {
59
          Core::PolLock lck;
1✔
60
          sql = std::make_unique<Core::BSQLConnection>();
1✔
61
        }
1✔
62
        if ( sql->getLastErrNo() )
1✔
63
        {
NEW
64
          Core::PolLock lck;
×
NEW
65
          if ( !uoexec.exists() )
×
NEW
66
            INFO_PRINTLN( "Script has been destroyed" );
×
67
          else
68
          {
NEW
69
            uoexec.get_weakptr()->ValueStack.back().set(
×
NEW
70
                new BObject( new BError( "Insufficient memory" ) ) );
×
NEW
71
            uoexec.get_weakptr()->revive();
×
72
          }
NEW
73
        }
×
74
        else if ( !sql->connect( host, username, password, port ) )
1✔
75
        {
NEW
76
          Core::PolLock lck;
×
NEW
77
          if ( !uoexec.exists() )
×
NEW
78
            INFO_PRINTLN( "Script has been destroyed" );
×
79
          else
80
          {
NEW
81
            uoexec.get_weakptr()->ValueStack.back().set(
×
NEW
82
                new BObject( new BError( sql->getLastError() ) ) );
×
NEW
83
            uoexec.get_weakptr()->revive();
×
84
          }
NEW
85
        }
×
86
        else
87
        {
88
          Core::PolLock lck;
1✔
89
          if ( !uoexec.exists() )
1✔
NEW
90
            INFO_PRINTLN( "Script has been destroyed" );
×
91
          else
92
          {
93
            uoexec.get_weakptr()->ValueStack.back().set( new BObject( sql.release() ) );
1✔
94
            uoexec.get_weakptr()->revive();
1✔
95
          }
96
        }
1✔
97
      } );
1✔
98

99
  return new BLong( 0 );
1✔
100
}
101

102
Bscript::BObjectImp* SQLExecutorModule::background_select( weak_ptr<Core::UOExecutor> uoexec,
1✔
103
                                                           Core::BSQLConnection* sql,
104
                                                           std::string db )
105
{
106
  // The BSQLConnection shouldn't be destroyed before the lambda runs
107
  ref_ptr<Core::BSQLConnection> sqlRef( sql );
1✔
108
  if ( !uoexec->suspend() )
1✔
109
  {
110
    DEBUGLOGLN(
×
111
        "Script Error in '{}' PC={}: \n"
112
        "\tThe execution of this script can't be blocked!",
113
        uoexec->scriptname(), uoexec->PC );
×
114
    return new Bscript::BError( "Script can't be blocked" );
×
115
  }
116
  Core::networkManager.sql_service->push(
2✔
117
      [uoexec = std::move( uoexec ), sqlRef = std::move( sqlRef ), db = std::move( db )]()
2✔
118
      {
119
        if ( !sqlRef->select_db( db ) )
1✔
120
        {
NEW
121
          Core::PolLock lck;
×
NEW
122
          if ( !uoexec.exists() )
×
NEW
123
            INFO_PRINTLN( "Script has been destroyed" );
×
124
          else
125
          {
NEW
126
            uoexec.get_weakptr()->ValueStack.back().set(
×
NEW
127
                new BObject( new BError( sqlRef->getLastError() ) ) );
×
NEW
128
            uoexec.get_weakptr()->revive();
×
129
          }
NEW
130
        }
×
131
        else
132
        {
133
          Core::PolLock lck;
1✔
134
          if ( !uoexec.exists() )
1✔
NEW
135
            INFO_PRINTLN( "Script has been destroyed" );
×
136
          else
137
          {
138
            uoexec.get_weakptr()->ValueStack.back().set( new BObject( new BLong( 1 ) ) );
1✔
139
            uoexec.get_weakptr()->revive();
1✔
140
          }
141
        }
1✔
142
      } );
1✔
143

144
  return new BLong( 0 );
1✔
145
}
1✔
146

147
Bscript::BObjectImp* SQLExecutorModule::background_query( weak_ptr<Core::UOExecutor> uoexec,
8✔
148
                                                          Core::BSQLConnection* sql,
149
                                                          std::string query,
150
                                                          const Bscript::ObjArray* params )
151
{
152
  // Copy and parse params before they will be deleted by this thread (go out of scope)
153
  Core::QueryParams sharedParams;
8✔
154
  if ( params != nullptr )
8✔
155
  {
156
    for ( const auto& ref : params->ref_arr )
10✔
157
    {
158
      const BObject* obj = ref.get();
2✔
159
      if ( obj != nullptr )
2✔
160
        sharedParams.push_back( obj->impptr()->getStringRep() );
2✔
161
    }
162
  }
163

164
  // The BSQLConnection shouldn't be destroyed before the lambda runs
165
  ref_ptr<Core::BSQLConnection> sqlRef( sql );
8✔
166
  if ( !uoexec->suspend() )
8✔
167
  {
168
    DEBUGLOGLN(
×
169
        "Script Error in '{}' PC={}: \n"
170
        "\tThe execution of this script can't be blocked!",
171
        uoexec->scriptname(), uoexec->PC );
×
172
    return new Bscript::BError( "Script can't be blocked" );
×
173
  }
174

175
  Core::networkManager.sql_service->push(
16✔
176
      [uoexec = std::move( uoexec ), sqlRef = std::move( sqlRef ), query = std::move( query ),
24✔
177
       sharedParams = std::move( sharedParams )]()
8✔
178
      {
179
        if ( !sqlRef->query( query, sharedParams ) )
8✔
180
        {
NEW
181
          Core::PolLock lck;
×
NEW
182
          if ( !uoexec.exists() )
×
NEW
183
            INFO_PRINTLN( "Script has been destroyed" );
×
184
          else
185
          {
NEW
186
            uoexec.get_weakptr()->ValueStack.back().set(
×
NEW
187
                new BObject( new BError( sqlRef->getLastError() ) ) );
×
NEW
188
            uoexec.get_weakptr()->revive();
×
189
          }
NEW
190
        }
×
191
        else
192
        {
193
          Core::PolLock lck;
8✔
194
          if ( !uoexec.exists() )
8✔
NEW
195
            INFO_PRINTLN( "Script has been destroyed" );
×
196
          else
197
          {
198
            uoexec.get_weakptr()->ValueStack.back().set( new BObject( sqlRef->getResultSet() ) );
8✔
199
            uoexec.get_weakptr()->revive();
8✔
200
          }
201
        }
8✔
202
      } );
8✔
203

204
  return new BLong( 0 );
8✔
205
}
8✔
206

207
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_connect()
1✔
208
{
209
  const String* host = getStringParam( 0 );
1✔
210
  const String* username = getStringParam( 1 );
1✔
211
  const String* password = getStringParam( 2 );
1✔
212
  int port;
213
  if ( !host || !username || !password || !getParam( 3, port ) )
1✔
214
  {
215
    return new BError( "Invalid parameters" );
×
216
  }
217
  return background_connect( uoexec().weakptr, host->getStringRep(), username->getStringRep(),
2✔
218
                             password->getStringRep(), port );
3✔
219
}
220
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_select_db()
1✔
221
{
222
  Core::BSQLConnection* sql =
223
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
1✔
224
  const String* db = getStringParam( 1 );
1✔
225
  if ( !sql || !db )
1✔
226
  {
227
    return new BError( "Invalid parameters" );
×
228
  }
229
  return background_select( uoexec().weakptr, sql, db->getStringRep() );
1✔
230
}
231

232
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_query()
8✔
233
{
234
  Core::BSQLConnection* sql =
235
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
8✔
236
  const String* query = getStringParam( 1 );
8✔
237
  ObjArray* params;
238
  bool use_parameters = getObjArrayParam( 2, params );
8✔
239
  if ( !sql || !query )
8✔
240
  {
241
    return new BError( "Invalid parameters" );
×
242
  }
243

244
  return background_query( uoexec().weakptr, sql, query->getStringRep(),
16✔
245
                           use_parameters ? params : nullptr );
8✔
246
}
247

248
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_fields()
×
249
{
250
  Core::BSQLResultSet* result =
251
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
×
252
  if ( !result )
×
253
  {
254
    return new BError( "Invalid parameters" );
×
255
  }
256
  return new BLong( result->num_fields() );
×
257
}
258

259
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_field_name()
×
260
{
261
  Core::BSQLResultSet* result =
262
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
×
263
  int index;
264
  if ( !getParam( 1, index ) )
×
265
    return new BError( "Invalid parameters" );
×
266

267
  if ( !result || !index )
×
268
  {
269
    return new BError( "Invalid parameters" );
×
270
  }
271
  const char* name = result->field_name( index );
×
272
  if ( name == nullptr )
×
273
    return new BError( "Column does not exist" );
×
274
  return new String( name, String::Tainted::YES );
×
275
}
276

277
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_affected_rows()
×
278
{
279
  Core::BSQLResultSet* result =
280
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
×
281
  if ( !result )
×
282
  {
283
    return new BError( "Invalid parameters" );
×
284
  }
285
  return new BLong( result->affected_rows() );
×
286
}
287

288
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_num_rows()
6✔
289
{
290
  Core::BSQLResultSet* result =
291
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
6✔
292
  if ( !result )
6✔
293
  {
294
    return new BError( "Invalid parameters" );
×
295
  }
296
  return new BLong( result->num_rows() );
6✔
297
}
298

299
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_close()
×
300
{
301
  Core::BSQLConnection* sql =
302
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
×
303
  if ( !sql )
×
304
    return new BError( "Invalid parameters" );
×
305
  sql->close();
×
306
  return new BLong( 1 );
×
307
}
308

309
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_fetch_row()
6✔
310
{
311
  Core::BSQLResultSet* result =
312
      static_cast<Core::BSQLResultSet*>( getParamImp( 0, Bscript::BObjectImp::OTSQLResultSet ) );
6✔
313
  if ( !result )
6✔
314
  {
315
    return new BError( "Invalid parameters" );
×
316
  }
317
  if ( !result->has_result() )
6✔
318
  {
319
    return new BError( "Query returned no result" );
×
320
  }
321
  return new Core::BSQLRow( result );
6✔
322
}
323

324
Bscript::BObjectImp* SQLExecutorModule::mf_mysql_escape_string()
1✔
325
{
326
  Core::BSQLConnection* sql =
327
      static_cast<Core::BSQLConnection*>( getParamImp( 0, Bscript::BObjectImp::OTSQLConnection ) );
1✔
328
  const String* text;
329
  if ( !sql || !getStringParam( 1, text ) )
1✔
330
    return new BError( "Invalid parameters" );
×
331

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

© 2026 Coveralls, Inc