You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-08 14:22:09 +03:00
Fully resolve potentially ambiguous symbols by removing using namespace statements from headers which have a cascading effect. This causes potential behavior changes when switching to c++11 since symbols can be exported from std and boost while both have been imported into the global namespace.
This commit is contained in:
@@ -295,7 +295,7 @@ inline bool PredicateOperator::getBoolVal(rowgroup::Row& row, bool& isNull, Retu
|
||||
// we won't want to just multiply by scale, as it may move
|
||||
// significant digits out of scope. So we break them apart
|
||||
// and compare each separately
|
||||
int64_t scale = max(lop->resultType().scale, rop->resultType().scale);
|
||||
int64_t scale = std::max(lop->resultType().scale, rop->resultType().scale);
|
||||
if (scale)
|
||||
{
|
||||
long double intpart1;
|
||||
|
@@ -41,9 +41,6 @@
|
||||
#include "exceptclasses.h"
|
||||
#include "dataconvert.h"
|
||||
|
||||
// Workaround for my_global.h #define of isnan(X) causing a std::std namespace
|
||||
using namespace std;
|
||||
|
||||
namespace messageqcpp
|
||||
{
|
||||
class ByteStream;
|
||||
@@ -608,7 +605,7 @@ inline const std::string& TreeNode::getStrVal()
|
||||
int exponent = (int)floor(log10( fabs(fResult.floatVal))); // This will round down the exponent
|
||||
double base = fResult.floatVal * pow(10, -1.0 * exponent);
|
||||
|
||||
if (isnan(exponent) || std::isnan(base))
|
||||
if (std::isnan(exponent) || std::isnan(base))
|
||||
{
|
||||
snprintf(tmp, 312, "%f", fResult.floatVal);
|
||||
fResult.strVal = removeTrailing0(tmp, 312);
|
||||
@@ -643,7 +640,7 @@ inline const std::string& TreeNode::getStrVal()
|
||||
int exponent = (int)floor(log10( fabs(fResult.doubleVal))); // This will round down the exponent
|
||||
double base = fResult.doubleVal * pow(10, -1.0 * exponent);
|
||||
|
||||
if (isnan(exponent) || std::isnan(base))
|
||||
if (std::isnan(exponent) || std::isnan(base))
|
||||
{
|
||||
snprintf(tmp, 312, "%f", fResult.doubleVal);
|
||||
fResult.strVal = removeTrailing0(tmp, 312);
|
||||
@@ -677,7 +674,7 @@ inline const std::string& TreeNode::getStrVal()
|
||||
int exponent = (int)floorl(log10( fabsl(fResult.longDoubleVal))); // This will round down the exponent
|
||||
long double base = fResult.longDoubleVal * pow(10, -1.0 * exponent);
|
||||
|
||||
if (isnan(exponent) || isnan(base))
|
||||
if (std::isnan(exponent) || std::isnan(base))
|
||||
{
|
||||
snprintf(tmp, 312, "%Lf", fResult.longDoubleVal);
|
||||
fResult.strVal = removeTrailing0(tmp, 312);
|
||||
|
@@ -30,7 +30,6 @@ namespace messageqcpp
|
||||
class ByteStream;
|
||||
}
|
||||
|
||||
using namespace mcsv1sdk;
|
||||
/**
|
||||
* Namespace
|
||||
*/
|
||||
@@ -78,7 +77,7 @@ public:
|
||||
/**
|
||||
* Accessors and Mutators
|
||||
*/
|
||||
mcsv1Context& getContext()
|
||||
mcsv1sdk::mcsv1Context& getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
@@ -122,7 +121,7 @@ public:
|
||||
virtual bool operator!=(const UDAFColumn& t) const;
|
||||
|
||||
private:
|
||||
mcsv1Context context;
|
||||
mcsv1sdk::mcsv1Context context;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -63,9 +63,9 @@ namespace joblist
|
||||
{
|
||||
|
||||
CrossEngineStep::CrossEngineStep(
|
||||
const string& schema,
|
||||
const string& table,
|
||||
const string& alias,
|
||||
const std::string& schema,
|
||||
const std::string& table,
|
||||
const std::string& alias,
|
||||
const JobInfo& jobInfo) :
|
||||
BatchPrimitive(jobInfo),
|
||||
fRowsRetrieved(0),
|
||||
@@ -113,7 +113,7 @@ bool CrossEngineStep::deliverStringTableRowGroup() const
|
||||
}
|
||||
|
||||
|
||||
void CrossEngineStep::addFcnJoinExp(const vector<execplan::SRCP>& fe)
|
||||
void CrossEngineStep::addFcnJoinExp(const std::vector<execplan::SRCP>& fe)
|
||||
{
|
||||
fFeFcnJoin = fe;
|
||||
}
|
||||
@@ -131,7 +131,7 @@ void CrossEngineStep::setFE1Input(const rowgroup::RowGroup& rg)
|
||||
}
|
||||
|
||||
|
||||
void CrossEngineStep::setFcnExpGroup3(const vector<execplan::SRCP>& fe)
|
||||
void CrossEngineStep::setFcnExpGroup3(const std::vector<execplan::SRCP>& fe)
|
||||
{
|
||||
fFeSelects = fe;
|
||||
}
|
||||
@@ -336,7 +336,7 @@ int64_t CrossEngineStep::convertValueNum(
|
||||
case CalpontSystemCatalog::TEXT:
|
||||
case CalpontSystemCatalog::CLOB:
|
||||
{
|
||||
string i = boost::any_cast<string>(anyVal);
|
||||
std::string i = boost::any_cast<std::string>(anyVal);
|
||||
// bug 1932, pad nulls up to the size of v
|
||||
i.resize(sizeof(rv), 0);
|
||||
rv = *((uint64_t*) i.data());
|
||||
@@ -435,7 +435,7 @@ void CrossEngineStep::execute()
|
||||
if (ret != 0)
|
||||
mysql->handleMySqlError(mysql->getError().c_str(), ret);
|
||||
|
||||
string query(makeQuery());
|
||||
std::string query(makeQuery());
|
||||
fLogger->logMessage(logging::LOG_TYPE_INFO, "QUERY to foreign engine: " + query);
|
||||
|
||||
if (traceOn())
|
||||
@@ -651,7 +651,7 @@ void CrossEngineStep::setBPP(JobStep* jobStep)
|
||||
pDictionaryStep* pds = NULL;
|
||||
pDictionaryScan* pdss = NULL;
|
||||
FilterStep* fs = NULL;
|
||||
string bop = " AND ";
|
||||
std::string bop = " AND ";
|
||||
|
||||
if (pcs != 0)
|
||||
{
|
||||
@@ -690,12 +690,12 @@ void CrossEngineStep::setBPP(JobStep* jobStep)
|
||||
}
|
||||
}
|
||||
|
||||
void CrossEngineStep::addFilterStr(const vector<const Filter*>& f, const string& bop)
|
||||
void CrossEngineStep::addFilterStr(const std::vector<const Filter*>& f, const std::string& bop)
|
||||
{
|
||||
if (f.size() == 0)
|
||||
return;
|
||||
|
||||
string filterStr;
|
||||
std::string filterStr;
|
||||
|
||||
for (uint64_t i = 0; i < f.size(); i++)
|
||||
{
|
||||
@@ -731,7 +731,7 @@ void CrossEngineStep::setProjectBPP(JobStep* jobStep1, JobStep*)
|
||||
}
|
||||
|
||||
|
||||
string CrossEngineStep::makeQuery()
|
||||
std::string CrossEngineStep::makeQuery()
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << fSelectClause << " FROM " << fTable;
|
||||
@@ -742,7 +742,7 @@ string CrossEngineStep::makeQuery()
|
||||
if (!fWhereClause.empty())
|
||||
oss << fWhereClause;
|
||||
|
||||
// the string must consist of a single SQL statement without a terminating semicolon ; or \g.
|
||||
// the std::string must consist of a single SQL statement without a terminating semicolon ; or \g.
|
||||
// oss << ";";
|
||||
return oss.str();
|
||||
}
|
||||
@@ -832,7 +832,7 @@ uint32_t CrossEngineStep::nextBand(messageqcpp::ByteStream& bs)
|
||||
}
|
||||
|
||||
|
||||
const string CrossEngineStep::toString() const
|
||||
const std::string CrossEngineStep::toString() const
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "CrossEngineStep ses:" << fSessionId << " txn:" << fTxnId << " st:" << fStepId;
|
||||
|
@@ -30,8 +30,6 @@
|
||||
#include "primitivestep.h"
|
||||
#include "threadnaming.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// forward reference
|
||||
namespace utils
|
||||
{
|
||||
@@ -60,9 +58,9 @@ public:
|
||||
/** @brief CrossEngineStep constructor
|
||||
*/
|
||||
CrossEngineStep(
|
||||
const string& schema,
|
||||
const string& table,
|
||||
const string& alias,
|
||||
const std::string& schema,
|
||||
const std::string& table,
|
||||
const std::string& alias,
|
||||
const JobInfo& jobInfo);
|
||||
|
||||
/** @brief CrossEngineStep destructor
|
||||
@@ -124,15 +122,15 @@ public:
|
||||
{
|
||||
return fRowsReturned;
|
||||
}
|
||||
const string& schemaName() const
|
||||
const std::string& schemaName() const
|
||||
{
|
||||
return fSchema;
|
||||
}
|
||||
const string& tableName() const
|
||||
const std::string& tableName() const
|
||||
{
|
||||
return fTable;
|
||||
}
|
||||
const string& tableAlias() const
|
||||
const std::string& tableAlias() const
|
||||
{
|
||||
return fAlias;
|
||||
}
|
||||
@@ -149,10 +147,10 @@ public:
|
||||
bool deliverStringTableRowGroup() const;
|
||||
uint32_t nextBand(messageqcpp::ByteStream& bs);
|
||||
|
||||
void addFcnJoinExp(const vector<execplan::SRCP>&);
|
||||
void addFcnJoinExp(const std::vector<execplan::SRCP>&);
|
||||
void addFcnExpGroup1(const boost::shared_ptr<execplan::ParseTree>&);
|
||||
void setFE1Input(const rowgroup::RowGroup&);
|
||||
void setFcnExpGroup3(const vector<execplan::SRCP>&);
|
||||
void setFcnExpGroup3(const std::vector<execplan::SRCP>&);
|
||||
void setFE23Output(const rowgroup::RowGroup&);
|
||||
|
||||
void addFilter(JobStep* jobStep);
|
||||
|
@@ -3373,7 +3373,7 @@ namespace joblist
|
||||
// conversion performed by the functions in this file.
|
||||
// @bug6131, pre-order traversing
|
||||
/* static */ void
|
||||
JLF_ExecPlanToJobList::walkTree(ParseTree* n, JobInfo& jobInfo)
|
||||
JLF_ExecPlanToJobList::walkTree(execplan::ParseTree* n, JobInfo& jobInfo)
|
||||
{
|
||||
TreeNode* tn = n->data();
|
||||
JobStepVector jsv;
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "calpontexecutionplan.h"
|
||||
#include "calpontselectexecutionplan.h"
|
||||
#include "calpontsystemcatalog.h"
|
||||
using namespace execplan;
|
||||
|
||||
|
||||
#include "jlf_common.h"
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
* @param ParseTree (in) is CEP to be translated to a joblist
|
||||
* @param JobInfo& (in/out) is the JobInfo reference that is loaded
|
||||
*/
|
||||
static void walkTree(ParseTree* n, JobInfo& jobInfo);
|
||||
static void walkTree(execplan::ParseTree* n, JobInfo& jobInfo);
|
||||
|
||||
/** @brief This function add new job steps to the job step vector in JobInfo
|
||||
*
|
||||
|
@@ -88,6 +88,7 @@ using namespace logging;
|
||||
#include "rowgroup.h"
|
||||
using namespace rowgroup;
|
||||
|
||||
#include "mcsv1_udaf.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -709,7 +710,7 @@ void updateAggregateColType(AggregateColumn* ac, const SRCP& srcp, int op, JobIn
|
||||
|
||||
if (udafc)
|
||||
{
|
||||
mcsv1Context& udafContext = udafc->getContext();
|
||||
mcsv1sdk::mcsv1Context& udafContext = udafc->getContext();
|
||||
ct.colDataType = udafContext.getResultType();
|
||||
ct.colWidth = udafContext.getColWidth();
|
||||
ct.scale = udafContext.getScale();
|
||||
|
@@ -57,7 +57,7 @@ namespace joblist
|
||||
{
|
||||
boost::mutex JobStep::fLogMutex; //=PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
ThreadPool JobStep::jobstepThreadPool(defaultJLThreadPoolSize, 0);
|
||||
threadpool::ThreadPool JobStep::jobstepThreadPool(defaultJLThreadPoolSize, 0);
|
||||
|
||||
ostream& operator<<(ostream& os, const JobStep* rhs)
|
||||
{
|
||||
|
@@ -53,8 +53,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
using namespace threadpool;
|
||||
|
||||
namespace joblist
|
||||
{
|
||||
|
||||
@@ -423,7 +421,7 @@ public:
|
||||
fOnClauseFilter = b;
|
||||
}
|
||||
|
||||
static ThreadPool jobstepThreadPool;
|
||||
static threadpool::ThreadPool jobstepThreadPool;
|
||||
protected:
|
||||
|
||||
//@bug6088, for telemetry posting
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include <limits>
|
||||
|
||||
#include <string.h>
|
||||
#include "mcsv1_udaf.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -4610,7 +4611,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
|
||||
if (udafc)
|
||||
{
|
||||
mcsv1Context& context = udafc->getContext();
|
||||
mcsv1sdk::mcsv1Context& context = udafc->getContext();
|
||||
context.setName(isp->func_name());
|
||||
|
||||
// Set up the return type defaults for the call to init()
|
||||
@@ -4620,8 +4621,8 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
context.setPrecision(udafc->resultType().precision);
|
||||
|
||||
context.setParamCount(udafc->aggParms().size());
|
||||
ColumnDatum colType;
|
||||
ColumnDatum colTypes[udafc->aggParms().size()];
|
||||
mcsv1sdk::ColumnDatum colType;
|
||||
mcsv1sdk::ColumnDatum colTypes[udafc->aggParms().size()];
|
||||
|
||||
// Build the column type vector.
|
||||
// Modified for MCOL-1201 multi-argument aggregate
|
||||
@@ -4649,7 +4650,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (udaf->init(&context, colTypes) == mcsv1_UDAF::ERROR)
|
||||
if (udaf->init(&context, colTypes) == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText = udafc->getContext().getErrorMessage();
|
||||
@@ -4662,7 +4663,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
|
||||
|
||||
// UDAF_OVER_REQUIRED means that this function is for Window
|
||||
// Function only. Reject it here in aggregate land.
|
||||
if (udafc->getContext().getRunFlag(UDAF_OVER_REQUIRED))
|
||||
if (udafc->getContext().getRunFlag(mcsv1sdk::UDAF_OVER_REQUIRED))
|
||||
{
|
||||
gwi.fatalParseError = true;
|
||||
gwi.parseErrorText =
|
||||
|
@@ -3295,7 +3295,7 @@ void ha_calpont_impl_start_bulk_insert(ha_rows rows, TABLE* table)
|
||||
|
||||
if (get_local_query(thd))
|
||||
{
|
||||
OamCache* oamcache = OamCache::makeOamCache();
|
||||
const auto oamcache = oam::OamCache::makeOamCache();
|
||||
int localModuleId = oamcache->getLocalPMId();
|
||||
|
||||
if (localModuleId == 0)
|
||||
|
@@ -58,7 +58,7 @@ extern "C"
|
||||
const char* invalidParmSizeMessage(uint64_t size, size_t& len)
|
||||
{
|
||||
static char str[sizeof(InvalidParmSize) + 12] = {0};
|
||||
ostringstream os;
|
||||
std::ostringstream os;
|
||||
os << InvalidParmSize << size;
|
||||
len = os.str().length();
|
||||
strcpy(str, os.str().c_str());
|
||||
@@ -86,13 +86,13 @@ extern "C"
|
||||
uint64_t value = Config::uFromText(valuestr);
|
||||
|
||||
THD* thd = current_thd;
|
||||
uint32_t sessionID = CalpontSystemCatalog::idb_tid2sid(thd->thread_id);
|
||||
uint32_t sessionID = execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id);
|
||||
|
||||
const char* msg = SetParmsError;
|
||||
size_t mlen = Elen;
|
||||
bool includeInput = true;
|
||||
|
||||
string pstr(parameter);
|
||||
std::string pstr(parameter);
|
||||
boost::algorithm::to_lower(pstr);
|
||||
|
||||
if (get_fe_conn_info_ptr() == NULL)
|
||||
@@ -107,7 +107,7 @@ extern "C"
|
||||
|
||||
if (rm->getHjTotalUmMaxMemorySmallSide() >= value)
|
||||
{
|
||||
ci->rmParms.push_back(RMParam(sessionID, execplan::PMSMALLSIDEMEMORY, value));
|
||||
ci->rmParms.push_back(execplan::RMParam(sessionID, execplan::PMSMALLSIDEMEMORY, value));
|
||||
|
||||
msg = SetParmsPrelude;
|
||||
mlen = Plen;
|
||||
@@ -254,8 +254,8 @@ extern "C"
|
||||
long long oldTrace = ci->traceFlags;
|
||||
ci->traceFlags = (uint32_t)(*((long long*)args->args[0]));
|
||||
// keep the vtablemode bit
|
||||
ci->traceFlags |= (oldTrace & CalpontSelectExecutionPlan::TRACE_TUPLE_OFF);
|
||||
ci->traceFlags |= (oldTrace & CalpontSelectExecutionPlan::TRACE_TUPLE_AUTOSWITCH);
|
||||
ci->traceFlags |= (oldTrace & execplan::CalpontSelectExecutionPlan::TRACE_TUPLE_OFF);
|
||||
ci->traceFlags |= (oldTrace & execplan::CalpontSelectExecutionPlan::TRACE_TUPLE_AUTOSWITCH);
|
||||
return oldTrace;
|
||||
}
|
||||
|
||||
@@ -381,8 +381,8 @@ extern "C"
|
||||
{
|
||||
long long rtn = 0;
|
||||
Oam oam;
|
||||
string PrimaryUMModuleName;
|
||||
string localModule;
|
||||
std::string PrimaryUMModuleName;
|
||||
std::string localModule;
|
||||
oamModuleInfo_t st;
|
||||
|
||||
try
|
||||
@@ -396,7 +396,7 @@ extern "C"
|
||||
if (PrimaryUMModuleName == "unassigned")
|
||||
rtn = 1;
|
||||
}
|
||||
catch (runtime_error& e)
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
// It's difficult to return an error message from a numerical UDF
|
||||
//string msg = string("ERROR: Problem getting Primary UM Module Name. ") + e.what();
|
||||
@@ -469,7 +469,7 @@ extern "C"
|
||||
set_fe_conn_info_ptr((void*)new cal_connection_info());
|
||||
|
||||
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
|
||||
CalpontSystemCatalog::TableName tableName;
|
||||
execplan::CalpontSystemCatalog::TableName tableName;
|
||||
|
||||
if ( args->arg_count == 2 )
|
||||
{
|
||||
@@ -484,7 +484,7 @@ extern "C"
|
||||
tableName.schema = thd->db.str;
|
||||
else
|
||||
{
|
||||
string msg("No schema information provided");
|
||||
std::string msg("No schema information provided");
|
||||
memcpy(result, msg.c_str(), msg.length());
|
||||
*length = msg.length();
|
||||
return result;
|
||||
@@ -497,7 +497,7 @@ extern "C"
|
||||
//cout << "viewtablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id << endl;
|
||||
}
|
||||
|
||||
string lockinfo = ha_calpont_impl_viewtablelock(*ci, tableName);
|
||||
std::string lockinfo = ha_calpont_impl_viewtablelock(*ci, tableName);
|
||||
|
||||
memcpy(result, lockinfo.c_str(), lockinfo.length());
|
||||
*length = lockinfo.length();
|
||||
@@ -550,7 +550,7 @@ extern "C"
|
||||
}
|
||||
|
||||
unsigned long long uLockID = lockID;
|
||||
string lockinfo = ha_calpont_impl_cleartablelock(*ci, uLockID);
|
||||
std::string lockinfo = ha_calpont_impl_cleartablelock(*ci, uLockID);
|
||||
|
||||
memcpy(result, lockinfo.c_str(), lockinfo.length());
|
||||
*length = lockinfo.length();
|
||||
@@ -604,7 +604,7 @@ extern "C"
|
||||
{
|
||||
THD* thd = current_thd;
|
||||
|
||||
CalpontSystemCatalog::TableName tableName;
|
||||
execplan::CalpontSystemCatalog::TableName tableName;
|
||||
uint64_t nextVal = 0;
|
||||
|
||||
if ( args->arg_count == 2 )
|
||||
@@ -624,9 +624,9 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<CalpontSystemCatalog> csc =
|
||||
CalpontSystemCatalog::makeCalpontSystemCatalog(
|
||||
CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
|
||||
boost::shared_ptr<execplan::CalpontSystemCatalog> csc =
|
||||
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(
|
||||
execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
|
||||
csc->identity(execplan::CalpontSystemCatalog::FE);
|
||||
|
||||
try
|
||||
@@ -635,7 +635,7 @@ extern "C"
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
string msg("No such table found during autincrement");
|
||||
std::string msg("No such table found during autincrement");
|
||||
setError(thd, ER_INTERNAL_ERROR, msg);
|
||||
return nextVal;
|
||||
}
|
||||
@@ -649,7 +649,7 @@ extern "C"
|
||||
//@Bug 3559. Return a message for table without autoincrement column.
|
||||
if (nextVal == 0)
|
||||
{
|
||||
string msg("Autoincrement does not exist for this table.");
|
||||
std::string msg("Autoincrement does not exist for this table.");
|
||||
setError(thd, ER_INTERNAL_ERROR, msg);
|
||||
return nextVal;
|
||||
}
|
||||
@@ -705,7 +705,7 @@ extern "C"
|
||||
char* result, unsigned long* length,
|
||||
char* is_null, char* error)
|
||||
{
|
||||
const string* msgp;
|
||||
const std::string* msgp;
|
||||
int flags = 0;
|
||||
|
||||
if (args->arg_count > 0)
|
||||
@@ -776,7 +776,7 @@ extern "C"
|
||||
char* result, unsigned long* length,
|
||||
char* is_null, char* error)
|
||||
{
|
||||
string version(columnstore_version);
|
||||
std::string version(columnstore_version);
|
||||
*length = version.size();
|
||||
memcpy(result, version.c_str(), *length);
|
||||
return result;
|
||||
|
Reference in New Issue
Block a user