Version 20.61: Apr 13, 2021 Optimizations in database selects.

This commit is contained in:
acanas 2021-04-13 23:34:07 +02:00
parent 1b7350757a
commit 91d8c066a5
30 changed files with 317 additions and 601 deletions

View File

@ -1286,34 +1286,14 @@ static void Agd_FreeListEvents (struct Agd_Agenda *Agenda)
static void Agd_GetEventTxtFromDB (struct Agd_Event *AgdEvent,
char Txt[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of event from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get event text",
"SELECT Txt" // row[0]
" FROM agd_agendas"
" WHERE AgdCod=%ld"
" AND UsrCod=%ld",
AgdEvent->AgdCod,
AgdEvent->UsrCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting event text.");
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get event text",
"SELECT Txt"
" FROM agd_agendas"
" WHERE AgdCod=%ld"
" AND UsrCod=%ld",
AgdEvent->AgdCod,
AgdEvent->UsrCod);
}
/*****************************************************************************/

View File

@ -932,34 +932,14 @@ static void Asg_FreeListAssignments (struct Asg_Assignments *Assignments)
static void Asg_GetAssignmentTxtFromDB (long AsgCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of assignment from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get assignment text",
"SELECT Txt" // row[0]
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting assignment text.");
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get assignment text",
"SELECT Txt" // row[0]
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/

View File

@ -865,35 +865,14 @@ static void Att_FreeListAttEvents (struct Att_Events *Events)
static void Att_GetAttEventDescriptionFromDB (long AttCod,char Description[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of attendance event from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get attendance event text",
"SELECT Txt" // row[0]
" FROM att_events"
" WHERE AttCod=%ld"
" AND CrsCod=%ld",
AttCod,Gbl.Hierarchy.Crs.CrsCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get info text */
Str_Copy (Description,row[0],Cns_MAX_BYTES_TEXT);
}
else
Description[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting attendance event text.");
DB_QuerySELECTString (Description,Cns_MAX_BYTES_TEXT,"can not get attendance event text",
"SELECT Txt"
" FROM att_events"
" WHERE AttCod=%ld"
" AND CrsCod=%ld",
AttCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
@ -2545,33 +2524,29 @@ static unsigned Att_GetNumUsrsFromAListWhoAreInAttEvent (long AttCod,
static bool Att_CheckIfUsrIsInTableAttUsr (long AttCod,long UsrCod,bool *Present)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool InDBTable;
char StrPresent[1 + 1];
/***** Check if a student is registered in an event in database *****/
InDBTable = (DB_QuerySELECT (&mysql_res,"can not check if a student"
" is already registered in an event",
"SELECT Present" // row[0]
" FROM att_users"
" WHERE AttCod=%ld"
" AND UsrCod=%ld",
AttCod,UsrCod) != 0);
if (InDBTable)
DB_QuerySELECTString (StrPresent,1,"can not check if a student"
" is already registered in an event",
"SELECT Present"
" FROM att_users"
" WHERE AttCod=%ld"
" AND UsrCod=%ld",
AttCod,
UsrCod);
switch (StrPresent[0])
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get if present (row[0]) */
*Present = (row[0][0] == 'Y');
case '\0':
*Present = false;
return false;
case 'Y':
*Present = true;
return true;
default:
*Present = false;
return true;
}
else // User is not present
*Present = false;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return InDBTable;
}
/*****************************************************************************/

View File

@ -813,27 +813,20 @@ long Ctr_GetInsCodOfCenterByCod (long CtrCod)
void Ctr_GetShortNameOfCenterByCod (struct Ctr_Center *Ctr)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
Ctr->ShrtName[0] = '\0';
if (Ctr->CtrCod > 0)
/***** Trivial check: center code should be > 0 *****/
if (Ctr->CtrCod <= 0)
{
/***** Get the short name of a center from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get the short name of a center",
"SELECT ShortName" // row[0]
" FROM ctr_centers"
" WHERE CtrCod=%ld",
Ctr->CtrCod) == 1)
{
/***** Get the short name of this center *****/
row = mysql_fetch_row (mysql_res);
Str_Copy (Ctr->ShrtName,row[0],sizeof (Ctr->ShrtName) - 1);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
Ctr->ShrtName[0] = '\0';
return;
}
/***** Get the short name of a center from database *****/
DB_QuerySELECTString (Ctr->ShrtName,sizeof (Ctr->ShrtName) - 1,
"can not get the short name of a center",
"SELECT ShortName"
" FROM ctr_centers"
" WHERE CtrCod=%ld",
Ctr->CtrCod);
}
/*****************************************************************************/

View File

@ -600,13 +600,14 @@ TODO: Salvador Romero Cort
TODO: FIX BUG, URGENT! En las fechas como parámetro Dat_WriteParamsIniEndDates(), por ejemplo al cambiar el color de la gráfica de accesos por día y hora, no se respeta la zona horaria.
*/
#define Log_PLATFORM_VERSION "SWAD 20.60 (2021-04-07)"
#define Log_PLATFORM_VERSION "SWAD 20.61 (2021-04-13)"
#define CSS_FILE "swad20.45.css"
#define JS_FILE "swad20.6.2.js"
/*
TODO: Rename CENTRE to CENTER in help wiki.
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
Version 20.61: Apr 13, 2021 Optimizations in database selects. (308567 lines)
Version 20.60: Apr 07, 2021 Optimizations in database selects. (308790 lines)
Version 20.59: Apr 06, 2021 Optimizations in database selects. (308903 lines)
Version 20.58: Apr 06, 2021 Optimizations in database selects. (308989 lines)

View File

@ -349,29 +349,13 @@ void Cht_WriteParamsRoomCodeAndNames (const char *RoomCode,const char *RoomShrtN
static unsigned Cht_GetNumUsrsInChatRoom (const char *RoomCode)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrs = 0;
/***** Get number of users connected to chat rooms from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get number of users"
return DB_QuerySELECTUnsigned ("can not get number of users"
" connected to a chat room",
"SELECT NumUsrs" // row[0]
" FROM cht_rooms"
" WHERE RoomCode='%s'",
RoomCode))
{
/* Get number of users connected to the chat room */
row = mysql_fetch_row (mysql_res);
if (row[0])
if (sscanf (row[0],"%u",&NumUsrs) != 1)
NumUsrs = 0;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumUsrs;
"SELECT NumUsrs" // row[0]
" FROM cht_rooms"
" WHERE RoomCode='%s'",
RoomCode);
}
/*****************************************************************************/

View File

@ -1130,8 +1130,6 @@ void Cty_GetCountryName (long CtyCod,Lan_Language_t Language,
char CtyName[Cty_MAX_BYTES_NAME + 1])
{
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** 1. Fast check: Trivial case *****/
if (CtyCod <= 0)
@ -1151,26 +1149,14 @@ void Cty_GetCountryName (long CtyCod,Lan_Language_t Language,
/***** 3. Slow: get country name from database *****/
Gbl.Cache.CountryName.CtyCod = CtyCod;
Gbl.Cache.CountryName.Language = Language;
if (DB_QuerySELECT (&mysql_res,"can not get the name of a country",
"SELECT Name_%s" // row[0]
" FROM cty_countrs"
" WHERE CtyCod='%03ld'",
Lan_STR_LANG_ID[Language],CtyCod)) // Country found...
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get the name of the country */
Str_Copy (Gbl.Cache.CountryName.CtyName,row[0],
sizeof (Gbl.Cache.CountryName.CtyName) - 1);
}
else
Gbl.Cache.CountryName.CtyName[0] = '\0';
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
DB_QuerySELECTString (Gbl.Cache.CountryName.CtyName,
sizeof (Gbl.Cache.CountryName.CtyName) - 1,
"can not get the name of a country",
"SELECT Name_%s"
" FROM cty_countrs"
" WHERE CtyCod='%03ld'",
Lan_STR_LANG_ID[Language],
CtyCod);
Str_Copy (CtyName,Gbl.Cache.CountryName.CtyName,Cty_MAX_BYTES_NAME);
}

View File

@ -3836,6 +3836,40 @@ long DB_QuerySELECTCode (const char *MsgError,
return Cod;
}
/*****************************************************************************/
/*** Make a SELECT query for a unique row with one unsigned from database ****/
/*****************************************************************************/
unsigned DB_QuerySELECTUnsigned (const char *MsgError,
const char *fmt,...)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
va_list ap;
int NumBytesPrinted;
char *Query;
unsigned UnsignedNum = 0;
/***** Create query string *****/
va_start (ap,fmt);
NumBytesPrinted = vasprintf (&Query,fmt,ap);
va_end (ap);
if (NumBytesPrinted < 0) // -1 if no memory or any other error
Lay_NotEnoughMemoryExit ();
/***** Do SELECT query *****/
if (DB_QuerySELECTusingQueryStr (Query,&mysql_res,MsgError)) // Row found
{
row = mysql_fetch_row (mysql_res);
if (row[0])
UnsignedNum = Str_ConvertStrToUnsigned (row[0]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return UnsignedNum;
}
/*****************************************************************************/
/**** Make a SELECT query for a unique row with one double from database *****/
@ -3872,19 +3906,20 @@ double DB_QuerySELECTDouble (const char *MsgError,
return DoubleNum;
}
/*****************************************************************************/
/*** Make a SELECT query for a unique row with one unsigned from database ****/
/*****************************************************************************/
unsigned DB_QuerySELECTUnsigned (const char *MsgError,
const char *fmt,...)
/*****************************************************************************/
/**** Make a SELECT query for a unique row with one double from database *****/
/*****************************************************************************/
// StrSize does not include the ending byte '\0'
void DB_QuerySELECTString (char *Str,size_t StrSize,const char *MsgError,
const char *fmt,...)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
va_list ap;
int NumBytesPrinted;
char *Query;
unsigned UnsignedNum = 0;
/***** Create query string *****/
va_start (ap,fmt);
@ -3894,17 +3929,16 @@ unsigned DB_QuerySELECTUnsigned (const char *MsgError,
Lay_NotEnoughMemoryExit ();
/***** Do SELECT query *****/
if (DB_QuerySELECTusingQueryStr (Query,&mysql_res,MsgError)) // Row found
if (DB_QuerySELECTusingQueryStr (Query,&mysql_res,MsgError) == 1) // Row found
{
row = mysql_fetch_row (mysql_res);
if (row[0])
UnsignedNum = Str_ConvertStrToUnsigned (row[0]);
Str_Copy (Str,row[0],StrSize);
}
else
Str[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return UnsignedNum;
}
/*****************************************************************************/

View File

@ -43,10 +43,13 @@ unsigned long DB_QuerySELECT (MYSQL_RES **mysql_res,const char *MsgError,
const char *fmt,...);
long DB_QuerySELECTCode (const char *MsgError,
const char *fmt,...);
double DB_QuerySELECTDouble (const char *MsgError,
const char *fmt,...);
unsigned DB_QuerySELECTUnsigned (const char *MsgError,
const char *fmt,...);
double DB_QuerySELECTDouble (const char *MsgError,
const char *fmt,...);
void DB_QuerySELECTString (char *Str,size_t StrSize,const char *MsgError,
const char *fmt,...);
long DB_GetNextCode (MYSQL_RES *mysql_res);
unsigned long DB_GetNumRowsTable (const char *Table);
unsigned long DB_QueryCOUNT (const char *MsgError,const char *fmt,...);

View File

@ -1430,27 +1430,20 @@ static void Deg_GetDataOfDegreeFromRow (struct Deg_Degree *Deg,MYSQL_ROW row)
void Deg_GetShortNameOfDegreeByCod (struct Deg_Degree *Deg)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
Deg->ShrtName[0] = '\0';
/***** Trivial check: degree code should be > 0 *****/
if (Deg->DegCod > 0)
{
/***** Get the short name of a degree from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get the short name of a degree",
"SELECT ShortName" // row[0]
" FROM deg_degrees"
" WHERE DegCod=%ld",
Deg->DegCod) == 1)
{
/***** Get the short name of this degree *****/
row = mysql_fetch_row (mysql_res);
Str_Copy (Deg->ShrtName,row[0],sizeof (Deg->ShrtName) - 1);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
Deg->ShrtName[0] = '\0';
return;
}
/***** Get the short name of a degree from database *****/
DB_QuerySELECTString (Deg->ShrtName,sizeof (Deg->ShrtName) - 1,
"can not get the short name of a degree",
"SELECT ShortName"
" FROM deg_degrees"
" WHERE DegCod=%ld",
Deg->DegCod);
}
/*****************************************************************************/

View File

@ -853,12 +853,12 @@ long DT_GetAndCheckParamOtherDegTypCod (long MinCodAllowed)
static unsigned DT_CountNumDegsOfType (long DegTypCod)
{
/***** Get number of degrees of a type from database *****/
return
(unsigned) DB_QueryCOUNT ("can not get number of degrees of a type",
"SELECT COUNT(*)"
" FROM deg_degrees"
" WHERE DegTypCod=%ld",
DegTypCod);
return (unsigned)
DB_QueryCOUNT ("can not get number of degrees of a type",
"SELECT COUNT(*)"
" FROM deg_degrees"
" WHERE DegTypCod=%ld",
DegTypCod);
}
/*****************************************************************************/
@ -867,53 +867,31 @@ static unsigned DT_CountNumDegsOfType (long DegTypCod)
bool DT_GetDataOfDegreeTypeByCod (struct DegreeType *DegTyp)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
bool DegTypFound = false;
/***** Trivial check: code of degree type should be >= 0 *****/
if (DegTyp->DegTypCod <= 0)
{
DegTyp->DegTypCod = -1L;
DegTyp->DegTypName[0] = '\0';
DegTyp->NumDegs = 0;
return false;
}
/***** Get the name of a type of degree from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get the name of a type of degree",
"SELECT DegTypName" // row[0]
" FROM deg_types"
" WHERE DegTypCod=%ld",
DegTyp->DegTypCod);
if (NumRows == 1)
DB_QuerySELECTString (DegTyp->DegTypName,sizeof (DegTyp->DegTypName) - 1,
"can not get the name of a type of degree",
"SELECT DegTypName"
" FROM deg_types"
" WHERE DegTypCod=%ld",
DegTyp->DegTypCod);
if (DegTyp->DegTypName[0])
{
/***** Get data of degree type *****/
row = mysql_fetch_row (mysql_res);
/* Get the name of the degree type (row[0]) */
Str_Copy (DegTyp->DegTypName,row[0],sizeof (DegTyp->DegTypName) - 1);
/* Count number of degrees of this type */
DegTyp->NumDegs = DT_CountNumDegsOfType (DegTyp->DegTypCod);
/* Set return value */
DegTypFound = true;
return true;
}
else if (NumRows == 0)
{
DegTyp->DegTypCod = -1L;
DegTyp->DegTypName[0] = '\0';
DegTyp->NumDegs = 0;
return false;
}
else // NumRows > 1
Lay_ShowErrorAndExit ("Type of degree repeated in database.");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return DegTypFound;
DegTyp->DegTypName[0] = '\0';
DegTyp->NumDegs = 0;
return false;
}
/*****************************************************************************/
@ -929,7 +907,7 @@ static void DT_RemoveDegreeTypeCompletely (long DegTypCod)
/***** Get degrees of a type from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get degrees of a type",
"SELECT DegCod" // row[0]
"SELECT DegCod"
" FROM deg_degrees"
" WHERE DegTypCod=%ld",
DegTypCod);

View File

@ -1067,32 +1067,12 @@ void Exa_FreeListExams (struct Exa_Exams *Exams)
void Exa_GetExamTxtFromDB (long ExaCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of exam from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get exam text",
"SELECT Txt" // row[0]
" FROM exa_exams"
" WHERE ExaCod=%ld",
ExaCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting exam text.");
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get exam text",
"SELECT Txt"
" FROM exa_exams"
" WHERE ExaCod=%ld",
ExaCod);
}
/*****************************************************************************/
@ -1264,7 +1244,7 @@ static void Exa_RemoveAllMedFilesFromStemOfAllQstsInCrs (long CrsCod)
/***** Get media codes associated to stems of exam questions from database *****/
NumMedia =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT exa_set_questions.MedCod" // row[0]
"SELECT exa_set_questions.MedCod"
" FROM exa_exams,"
"exa_sets,"
"exa_set_questions"
@ -1292,7 +1272,7 @@ static void Exa_RemoveAllMedFilesFromAnsOfAllQstsInCrs (long CrsCod)
/***** Get names of media files associated to answers of exam questions from database *****/
NumMedia = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get media",
"SELECT exa_set_answers.MedCod" // row[0]
"SELECT exa_set_answers.MedCod"
" FROM exa_exams,"
"exa_sets,"
"exa_set_questions,"

View File

@ -1132,32 +1132,12 @@ void Gam_FreeListGames (struct Gam_Games *Games)
static void Gam_GetGameTxtFromDB (long GamCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of game from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get game text",
"SELECT Txt" // row[0]
" FROM gam_games"
" WHERE GamCod=%ld",
GamCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting game text.");
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get game text",
"SELECT Txt" // row[0]
" FROM gam_games"
" WHERE GamCod=%ld",
GamCod);
}
/*****************************************************************************/

View File

@ -878,9 +878,6 @@ void Ins_FlushCacheShortNameOfInstitution (void)
void Ins_GetShortNameOfInstitution (struct Ins_Instit *Ins)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** 1. Fast check: Trivial case *****/
if (Ins->InsCod <= 0)
{
@ -898,25 +895,13 @@ void Ins_GetShortNameOfInstitution (struct Ins_Instit *Ins)
/***** 3. Slow: get short name of institution from database *****/
Gbl.Cache.InstitutionShrtName.InsCod = Ins->InsCod;
if (DB_QuerySELECT (&mysql_res,"can not get the short name of an institution",
"SELECT ShortName" // row[0]
" FROM ins_instits"
" WHERE InsCod=%ld",
Ins->InsCod) == 1)
{
/* Get the short name of this institution */
row = mysql_fetch_row (mysql_res);
Str_Copy (Gbl.Cache.InstitutionShrtName.ShrtName,row[0],
sizeof (Gbl.Cache.InstitutionShrtName.ShrtName) - 1);
}
else
Gbl.Cache.InstitutionShrtName.ShrtName[0] = '\0';
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
DB_QuerySELECTString (Gbl.Cache.InstitutionShrtName.ShrtName,
sizeof (Gbl.Cache.InstitutionShrtName.ShrtName) - 1,
"can not get the short name of an institution",
"SELECT ShortName"
" FROM ins_instits"
" WHERE InsCod=%ld",
Ins->InsCod);
Str_Copy (Ins->ShrtName,Gbl.Cache.InstitutionShrtName.ShrtName,
sizeof (Ins->ShrtName) - 1);
}
@ -1038,14 +1023,14 @@ void Ins_WriteSelectorOfInstitution (void)
if (Gbl.Hierarchy.Cty.CtyCod > 0)
{
/***** Get institutions of selected country from database *****/
NumInss =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get institutions",
"SELECT DISTINCT InsCod," // row[0]
"ShortName" // row[1]
" FROM ins_instits"
" WHERE CtyCod=%ld"
" ORDER BY ShortName",
Gbl.Hierarchy.Cty.CtyCod);
NumInss = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get institutions",
"SELECT DISTINCT InsCod," // row[0]
"ShortName" // row[1]
" FROM ins_instits"
" WHERE CtyCod=%ld"
" ORDER BY ShortName",
Gbl.Hierarchy.Cty.CtyCod);
/***** List institutions *****/
for (NumIns = 0;

View File

@ -1754,17 +1754,16 @@ static void Mai_InsertMailKey (const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]
void Mai_ConfirmEmail (void)
{
extern const char *Txt_Failed_email_confirmation_key;
extern const char *Txt_Email_X_has_already_been_confirmed_before;
extern const char *Txt_The_email_X_has_been_confirmed;
extern const char *Txt_The_email_address_has_not_been_confirmed;
extern const char *Txt_Failed_email_confirmation_key;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
char MailKey[Mai_LENGTH_EMAIL_CONFIRM_KEY + 1];
long UsrCod;
char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1];
bool KeyIsCorrect;
bool Confirmed;
char StrConfirmed[1 + 1];
/***** Get parameter Key *****/
Par_GetParToText ("key",MailKey,Mai_LENGTH_EMAIL_CONFIRM_KEY);
@ -1807,43 +1806,34 @@ void Mai_ConfirmEmail (void)
/***** Check user's code and email
and get if email is already confirmed *****/
if (DB_QuerySELECT (&mysql_res,"can not check if email is confirmed",
"SELECT Confirmed" // row[0]
" FROM usr_emails"
" WHERE UsrCod=%ld"
" AND E_mail='%s'",
UsrCod,
Email))
{
Confirmed = false;
if (row)
if (row[0])
Confirmed = (row[0][0] == 'Y');
/***** Confirm email *****/
if (Confirmed)
DB_QuerySELECTString (StrConfirmed,1,"can not check if email is confirmed",
"SELECT Confirmed"
" FROM usr_emails"
" WHERE UsrCod=%ld"
" AND E_mail='%s'",
UsrCod,
Email);
switch (StrConfirmed[0])
{
case '\0':
Ale_ShowAlert (Ale_WARNING,Txt_Failed_email_confirmation_key);
break;
case 'Y':
Ale_ShowAlert (Ale_SUCCESS,Txt_Email_X_has_already_been_confirmed_before,
Email);
else
{
break;
default:
/***** Confirm email *****/
DB_QueryUPDATE ("can not confirm email",
"UPDATE usr_emails SET Confirmed='Y'"
" WHERE usr_emails.UsrCod=%ld"
" AND usr_emails.E_mail='%s'",
UsrCod,Email);
Ale_ShowAlert (Ale_SUCCESS,Txt_The_email_X_has_been_confirmed,
Email);
}
}
else
Ale_ShowAlert (Ale_WARNING,Txt_The_email_address_has_not_been_confirmed);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
break;
}
}
else
Ale_ShowAlert (Ale_WARNING,Txt_Failed_email_confirmation_key);
/***** Form to log in *****/
Usr_WriteFormLogin (ActLogIn,NULL);

View File

@ -1911,26 +1911,19 @@ static void Mch_ReorderAnswer (long MchCod,unsigned QstInd,
void Mch_GetIndexes (long MchCod,unsigned QstInd,
unsigned Indexes[Tst_MAX_OPTIONS_PER_QUESTION])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
char StrIndexesOneQst[Tst_MAX_BYTES_INDEXES_ONE_QST + 1];
/***** Get indexes for a question from database *****/
if (!DB_QuerySELECT (&mysql_res,"can not get data of a question",
"SELECT Indexes" // row[0]
" FROM mch_indexes"
" WHERE MchCod=%ld"
" AND QstInd=%u",
MchCod,
QstInd))
DB_QuerySELECTString (StrIndexesOneQst,sizeof (StrIndexesOneQst) - 1,
"can not get data of a question",
"SELECT Indexes" // row[0]
" FROM mch_indexes"
" WHERE MchCod=%ld"
" AND QstInd=%u",
MchCod,
QstInd);
if (!StrIndexesOneQst[0])
Lay_ShowErrorAndExit ("No indexes found for a question.");
row = mysql_fetch_row (mysql_res);
/* Get indexes (row[0]) */
Str_Copy (StrIndexesOneQst,row[0],sizeof (StrIndexesOneQst) - 1);
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Get indexes from string *****/
TstPrn_GetIndexesFromStr (StrIndexesOneQst,Indexes);

View File

@ -566,8 +566,11 @@ static void Msg_WriteFormUsrsIDsOrNicksOtherRecipients (void)
else if (Gbl.Usrs.Other.UsrDat.UsrCod > 0) // If there is a recipient
// and there's no list of explicit recipients,
// write @nickname of original sender
if (Nck_GetNicknameFromUsrCod (Gbl.Usrs.Other.UsrDat.UsrCod,Nickname))
{
Nck_GetNicknameFromUsrCod (Gbl.Usrs.Other.UsrDat.UsrCod,Nickname);
if (Nickname[0])
HTM_TxtF ("@%s",Nickname);
}
HTM_TEXTAREA_End ();
HTM_TD_End ();
@ -4154,16 +4157,17 @@ void Msg_ListBannedUsrs (void)
struct UsrData UsrDat;
/***** Get my banned users *****/
NumUsrs = (unsigned) DB_QuerySELECT (&mysql_res,"can not get banned users",
"SELECT msg_banned.FromUsrCod"
" FROM msg_banned,"
"usr_data"
" WHERE msg_banned.ToUsrCod=%ld"
" AND msg_banned.FromUsrCod=usr_data.UsrCod"
" ORDER BY usr_data.Surname1,"
"usr_data.Surname2,"
"usr_data.FirstName",
Gbl.Usrs.Me.UsrDat.UsrCod);
NumUsrs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get banned users",
"SELECT msg_banned.FromUsrCod"
" FROM msg_banned,"
"usr_data"
" WHERE msg_banned.ToUsrCod=%ld"
" AND msg_banned.FromUsrCod=usr_data.UsrCod"
" ORDER BY usr_data.Surname1,"
"usr_data.Surname2,"
"usr_data.FirstName",
Gbl.Usrs.Me.UsrDat.UsrCod);
if (NumUsrs == 0) // If not result ==> sent message is deleted
Ale_ShowAlert (Ale_INFO,Txt_You_have_not_banned_any_sender);

View File

@ -206,8 +206,6 @@ static void Net_GetMyWebsAndSocialNetsFromForm (void);
void Net_ShowWebsAndSocialNets (const struct UsrData *UsrDat)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
Net_WebsAndSocialNetworks_t NumURL;
char URL[Cns_MAX_BYTES_WWW + 1];
@ -224,26 +222,19 @@ void Net_ShowWebsAndSocialNets (const struct UsrData *UsrDat)
NumURL++)
{
/***** Check if exists the web / social network for this user *****/
if (DB_QuerySELECT (&mysql_res,"can not get user's web / social network",
"SELECT URL" // row[0]
" FROM usr_webs"
" WHERE UsrCod=%ld"
" AND Web='%s'",
UsrDat->UsrCod,
Net_WebsAndSocialNetworksDB[NumURL]))
{
/* Get URL */
row = mysql_fetch_row (mysql_res);
Str_Copy (URL,row[0],sizeof (URL) - 1);
DB_QuerySELECTString (URL,sizeof (URL) - 1,
"can not get user's web / social network",
"SELECT URL" // row[0]
" FROM usr_webs"
" WHERE UsrCod=%ld"
" AND Web='%s'",
UsrDat->UsrCod,
Net_WebsAndSocialNetworksDB[NumURL]);
if (URL[0])
/* Show the web / social network */
Net_ShowAWebOrSocialNet (URL,
Net_WebsAndSocialNetworksIcons[NumURL],
Net_WebsAndSocialNetworksTitle[NumURL]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/***** End container *****/
@ -275,8 +266,6 @@ void Net_ShowFormMyWebsAndSocialNets (void)
extern const char *The_ClassFormInBox[The_NUM_THEMES];
extern const char *Txt_Webs_social_networks;
extern const char *Txt_Save_changes;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
Net_WebsAndSocialNetworks_t NumURL;
char URL[Cns_MAX_BYTES_WWW + 1];
char StrRecordWidth[Cns_MAX_DECIMAL_DIGITS_UINT + 2 + 1];
@ -303,25 +292,14 @@ void Net_ShowFormMyWebsAndSocialNets (void)
NumURL++)
{
/***** Get user's web / social network from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get user's web / social network",
"SELECT URL" // row[0]
" FROM usr_webs"
" WHERE UsrCod=%ld"
" AND Web='%s'",
Gbl.Usrs.Me.UsrDat.UsrCod,
Net_WebsAndSocialNetworksDB[NumURL]))
{
/***** Read the data comunes a all the users *****/
row = mysql_fetch_row (mysql_res);
/* Get URL */
Str_Copy (URL,row[0],sizeof (URL) - 1);
}
else
URL[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
DB_QuerySELECTString (URL,sizeof (URL) - 1,
"can not get user's web / social network",
"SELECT URL" // row[0]
" FROM usr_webs"
" WHERE UsrCod=%ld"
" AND Web='%s'",
Gbl.Usrs.Me.UsrDat.UsrCod,
Net_WebsAndSocialNetworksDB[NumURL]);
/***** Row for this web / social network *****/
snprintf (StrName,sizeof (StrName),"URL%u",(unsigned) NumURL);

View File

@ -112,37 +112,18 @@ bool Nck_CheckIfNickWithArrIsValid (const char *NickWithArr)
/************* Get nickname of a user from his/her user's code ***************/
/*****************************************************************************/
bool Nck_GetNicknameFromUsrCod (long UsrCod,
void Nck_GetNicknameFromUsrCod (long UsrCod,
char Nickname[Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool Found;
/***** Get current (last updated) user's nickname from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get nickname",
"SELECT Nickname" // row[0]
" FROM usr_nicknames"
" WHERE UsrCod=%ld"
" ORDER BY CreatTime DESC"
" LIMIT 1",
UsrCod))
{
/* Get nickname */
row = mysql_fetch_row (mysql_res);
Str_Copy (Nickname,row[0],Nck_MAX_BYTES_NICK_WITHOUT_ARROBA);
Found = true;
}
else
{
Nickname[0] = '\0';
Found = false;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return Found;
DB_QuerySELECTString (Nickname,Nck_MAX_BYTES_NICK_WITHOUT_ARROBA,
"can not get nickname",
"SELECT Nickname"
" FROM usr_nicknames"
" WHERE UsrCod=%ld"
" ORDER BY CreatTime DESC"
" LIMIT 1",
UsrCod);
}
/*****************************************************************************/

View File

@ -48,7 +48,7 @@
bool Nck_CheckIfNickWithArrIsValid (const char *NickWithArr);
bool Nck_GetNicknameFromUsrCod (long UsrCod,
void Nck_GetNicknameFromUsrCod (long UsrCod,
char Nickname[Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1]);
long Nck_GetUsrCodFromNickname (const char *Nickname);

View File

@ -115,26 +115,14 @@ bool Pwd_CheckCurrentPassword (void)
bool Pwd_CheckPendingPassword (void)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Get pending password from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get pending password",
"SELECT PendingPassword" // row[0]
" FROM usr_pending_passwd"
" WHERE UsrCod=%ld",
Gbl.Usrs.Me.UsrDat.UsrCod))
{
/* Get encrypted pending password */
row = mysql_fetch_row (mysql_res);
Str_Copy (Gbl.Usrs.Me.PendingPassword,row[0],
sizeof (Gbl.Usrs.Me.PendingPassword) - 1);
}
else
Gbl.Usrs.Me.PendingPassword[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
DB_QuerySELECTString (Gbl.Usrs.Me.PendingPassword,
sizeof (Gbl.Usrs.Me.PendingPassword) - 1,
"can not get pending password",
"SELECT PendingPassword" // row[0]
" FROM usr_pending_passwd"
" WHERE UsrCod=%ld",
Gbl.Usrs.Me.UsrDat.UsrCod);
return (Gbl.Usrs.Me.PendingPassword[0] ?
!strcmp (Gbl.Usrs.Me.LoginEncryptedPassword,Gbl.Usrs.Me.PendingPassword) :

View File

@ -1159,33 +1159,14 @@ static void Prg_FreeListItems (void)
static void Prg_GetItemTxtFromDB (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of program item from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get program item text",
"SELECT Txt" // row[0]
" FROM prg_items"
" WHERE ItmCod=%ld"
" AND CrsCod=%ld", // Extra check
ItmCod,Gbl.Hierarchy.Crs.CrsCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting program item text.");
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get program item text",
"SELECT Txt"
" FROM prg_items"
" WHERE ItmCod=%ld"
" AND CrsCod=%ld", // Extra check
ItmCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/

View File

@ -2317,13 +2317,14 @@ unsigned Prj_GetMyRolesInProject (long PrjCod)
The result of the query will have one row or none *****/
Gbl.Cache.MyRolesInProject.PrjCod = PrjCod;
Gbl.Cache.MyRolesInProject.RolesInProject = 0;
NumRows = (unsigned) DB_QuerySELECT (&mysql_res,"can not get my roles in project",
"SELECT RoleInProject" // row[0]
" FROM prj_users"
" WHERE PrjCod=%ld"
" AND UsrCod=%ld",
PrjCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
NumRows = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get my roles in project",
"SELECT RoleInProject" // row[0]
" FROM prj_users"
" WHERE PrjCod=%ld"
" AND UsrCod=%ld",
PrjCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
for (NumRow = 0;
NumRow < NumRows;
NumRow++)

View File

@ -476,8 +476,6 @@ void Ses_GetParamFromDB (const char *ParamName,char *ParamValue,size_t MaxBytes)
bool Ses_GetPublicDirFromCache (const char *FullPathMediaPriv,
char TmpPubDir[PATH_MAX + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool Cached;
bool TmpPubDirExists;
@ -487,22 +485,14 @@ bool Ses_GetPublicDirFromCache (const char *FullPathMediaPriv,
if (Gbl.Session.IsOpen)
{
/***** Get temporary directory from cache *****/
if (DB_QuerySELECT (&mysql_res,"can not get check if file is cached",
"SELECT TmpPubDir" // row[0]
" FROM brw_caches"
" WHERE SessionId='%s'"
" AND PrivPath='%s'",
Gbl.Session.Id,FullPathMediaPriv))
{
/* Get the temporary public directory (row[0]) */
row = mysql_fetch_row (mysql_res);
Str_Copy (TmpPubDir,row[0],PATH_MAX);
}
else
Cached = false;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
DB_QuerySELECTString (TmpPubDir,PATH_MAX,"can not get check if file is cached",
"SELECT TmpPubDir"
" FROM brw_caches"
" WHERE SessionId='%s'"
" AND PrivPath='%s'",
Gbl.Session.Id,
FullPathMediaPriv);
Cached = (TmpPubDir[0] != '\0');
/***** Check if temporary public directory exists *****/
if (Cached)

View File

@ -3003,7 +3003,7 @@ void Str_CreateRandomAlphanumStr (char *Str,size_t Length)
/*****************************************************************************/
/****************************** Safe string copy *****************************/
/*****************************************************************************/
// DstSize does not include ending byte '\0'
// DstSize does not include the ending byte '\0'
void Str_Copy (char *Dst,const char *Src,size_t DstSize)
{

View File

@ -1484,32 +1484,12 @@ void Svy_FreeListSurveys (struct Svy_Surveys *Surveys)
static void Svy_GetSurveyTxtFromDB (long SvyCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of survey from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get survey text",
"SELECT Txt" // row[0]
" FROM svy_surveys"
" WHERE SvyCod=%ld",
SvyCod);
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting survey text.");
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get survey text",
"SELECT Txt"
" FROM svy_surveys"
" WHERE SvyCod=%ld",
SvyCod);
}
/*****************************************************************************/

View File

@ -2622,18 +2622,18 @@ static void TstPrn_ShowTagsPresentInAPrint (long ResCod)
/***** Get all tags of questions in this test *****/
NumTags = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get tags"
" present in a test exam",
"SELECT tst_tags.TagTxt" // row[0]
" FROM (SELECT DISTINCT(tst_question_tags.TagCod)"
" FROM tst_question_tags,"
"tst_exam_questions"
" WHERE tst_exam_questions.ExaCod=%ld"
" AND tst_exam_questions.QstCod=tst_question_tags.QstCod) AS TagsCods,"
"tst_tags"
" WHERE TagsCods.TagCod=tst_tags.TagCod"
" ORDER BY tst_tags.TagTxt",
ResCod);
DB_QuerySELECT (&mysql_res,"can not get tags"
" present in a test exam",
"SELECT tst_tags.TagTxt" // row[0]
" FROM (SELECT DISTINCT(tst_question_tags.TagCod)"
" FROM tst_question_tags,"
"tst_exam_questions"
" WHERE tst_exam_questions.ExaCod=%ld"
" AND tst_exam_questions.QstCod=tst_question_tags.QstCod) AS TagsCods,"
"tst_tags"
" WHERE TagsCods.TagCod=tst_tags.TagCod"
" ORDER BY tst_tags.TagTxt",
ResCod);
Tst_ShowTagList (NumTags,mysql_res);
/***** Free structure that stores the query result *****/

View File

@ -47379,30 +47379,6 @@ const char *Txt_The_email_address_X_has_been_registered_successfully = // Warnin
" foi registrado com sucesso.";
#endif
const char *Txt_The_email_address_has_not_been_confirmed =
#if L==1 // ca
"La direcci&oacute;n de correo"
" no ha podido confirmarse."; // Necessita traduccio
#elif L==2 // de
"The email address has not been confirmed."; // Need Übersetzung
#elif L==3 // en
"The email address has not been confirmed.";
#elif L==4 // es
"La direcci&oacute;n de correo"
" no ha podido confirmarse.";
#elif L==5 // fr
"The email address has not been confirmed."; // Besoin de traduction
#elif L==6 // gn
"La direcci&oacute;n de correo"
" no ha podido confirmarse."; // Okoteve traducción
#elif L==7 // it
"The email address has not been confirmed."; // Bisogno di traduzione
#elif L==8 // pl
"The email address has not been confirmed."; // Potrzebujesz tlumaczenie
#elif L==9 // pt
"O endere&ccedil;o de email n&atilde;o foi confirmado.";
#endif
const char *Txt_The_email_address_X_matches_one_previously_registered = // Warning: it is very important to include %s in the following sentences
#if L==1 // ca
"La direcci&oacute;n de correo <strong>%s</strong>"

View File

@ -139,8 +139,10 @@ void Tml_Pub_GetListPubsToShowInTimeline (struct Tml_Timeline *Timeline)
As an alternative, we tried to get the maximum PubCod,
i.e more recent publication (original, shared or commment),
of every set of publications corresponding to the same note:
"SELECT MAX(PubCod) AS NewestPubCod FROM tml_pubs ...
" GROUP BY NotCod ORDER BY NewestPubCod DESC LIMIT ..."
SELECT MAX(PubCod) AS NewestPubCod
FROM tml_pubs ...
GROUP BY NotCod
ORDER BY NewestPubCod DESC LIMIT ...
but this query is slow (several seconds) with a big table.
*/
for (NumPub = 0;

View File

@ -2236,26 +2236,26 @@ unsigned Usr_GetCtysFromUsr (long UsrCod,MYSQL_RES **mysql_res)
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
/***** Get the institutions a user belongs to from database *****/
return
(unsigned) DB_QuerySELECT (mysql_res,"can not get the countries"
" a user belongs to",
"SELECT cty_countrs.CtyCod," // row[0]
"MAX(crs_users.Role)" // row[1]
" FROM crs_users,"
"crs_courses,"
"deg_degrees,"
"ctr_centers,"
"ins_instits,"
"cty_countrs"
" WHERE crs_users.UsrCod=%ld"
" AND crs_users.CrsCod=crs_courses.CrsCod"
" AND crs_courses.DegCod=deg_degrees.DegCod"
" AND deg_degrees.CtrCod=ctr_centers.CtrCod"
" AND ctr_centers.InsCod=ins_instits.InsCod"
" AND ins_instits.CtyCod=cty_countrs.CtyCod"
" GROUP BY cty_countrs.CtyCod"
" ORDER BY cty_countrs.Name_%s",
UsrCod,Lan_STR_LANG_ID[Gbl.Prefs.Language]);
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get the countries a user belongs to",
"SELECT cty_countrs.CtyCod," // row[0]
"MAX(crs_users.Role)" // row[1]
" FROM crs_users,"
"crs_courses,"
"deg_degrees,"
"ctr_centers,"
"ins_instits,"
"cty_countrs"
" WHERE crs_users.UsrCod=%ld"
" AND crs_users.CrsCod=crs_courses.CrsCod"
" AND crs_courses.DegCod=deg_degrees.DegCod"
" AND deg_degrees.CtrCod=ctr_centers.CtrCod"
" AND ctr_centers.InsCod=ins_instits.InsCod"
" AND ins_instits.CtyCod=cty_countrs.CtyCod"
" GROUP BY cty_countrs.CtyCod"
" ORDER BY cty_countrs.Name_%s",
UsrCod,
Lan_STR_LANG_ID[Gbl.Prefs.Language]);
}
/*****************************************************************************/