diff --git a/swad_API.c b/swad_API.c index af243f29..468c335e 100644 --- a/swad_API.c +++ b/swad_API.c @@ -635,77 +635,25 @@ static bool API_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod) Nck_GetNicknameFromUsrCod (UsrDat->UsrCod,UsrDat->Nickname); /***** Get user's role *****/ - /* Query database */ if (CrsCod > 0) - { /* Get the role in the given course */ - if (DB_QuerySELECT (&mysql_res,"can not get user's role", - "SELECT Role" // row[0] + UsrDat->Roles.InCurrentCrs.Role = + DB_QuerySELECTRole ("can not get user's role", + "SELECT Role" " FROM crs_users" " WHERE CrsCod=%ld" " AND UsrCod=%ld", CrsCod, - UsrDat->UsrCod)) // User belongs to course - { - row = mysql_fetch_row (mysql_res); - if (row[0]) - { - if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) == 1) - UsrDat->Roles.InCurrentCrs.Valid = true; - else - { - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = false; - } - } - else // Impossible - { - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = false; - } - } - else // User does not belong to course - { - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = true; - } - } + UsrDat->UsrCod); else - { /* Get the maximum role in any course */ - if (DB_QuerySELECT (&mysql_res,"can not get user's role", - "SELECT MAX(Role)" // row[0] + UsrDat->Roles.InCurrentCrs.Role = + DB_QuerySELECTRole ("can not get user's role", + "SELECT MAX(Role)" " FROM crs_users" " WHERE UsrCod=%ld", - UsrDat->UsrCod) == 1) - { - row = mysql_fetch_row (mysql_res); - if (row[0]) - { - if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) == 1) - UsrDat->Roles.InCurrentCrs.Valid = true; - else - { - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = false; - } - } - else - // MAX(Role) == NULL if user does not belong to any course - { - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = true; - } - } - else // Impossible - { - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = false; - } - } - - /* Free structure that stores the query result */ - DB_FreeMySQLResult (&mysql_res); + UsrDat->UsrCod); + UsrDat->Roles.InCurrentCrs.Filled = true; return true; } diff --git a/swad_announcement.c b/swad_announcement.c index 3b7a8cf8..86836975 100644 --- a/swad_announcement.c +++ b/swad_announcement.c @@ -96,48 +96,47 @@ void Ann_ShowAllAnnouncements (void) /***** Get announcements from database *****/ if (ICanEdit) - { /* Select all announcements */ - NumAnnouncements = (unsigned) DB_QuerySELECT (&mysql_res,"can not get announcements", - "SELECT AnnCod," // row[0] - "Status," // row[1] - "Roles," // row[2] - "Subject," // row[3] - "Content" // row[4] - " FROM ann_announcements" - " ORDER BY AnnCod DESC"); - } + NumAnnouncements = (unsigned) + DB_QuerySELECT (&mysql_res,"can not get announcements", + "SELECT AnnCod," // row[0] + "Status," // row[1] + "Roles," // row[2] + "Subject," // row[3] + "Content" // row[4] + " FROM ann_announcements" + " ORDER BY AnnCod DESC"); else if (Gbl.Usrs.Me.Logged) { /* Select only announcements I can see */ Rol_GetRolesInAllCrssIfNotYetGot (&Gbl.Usrs.Me.UsrDat); - NumAnnouncements = (unsigned) DB_QuerySELECT (&mysql_res,"can not get announcements", - "SELECT AnnCod," // row[0] - "Status," // row[1] - "Roles," // row[2] - "Subject," // row[3] - "Content" // row[4] - " FROM ann_announcements" - " WHERE (Roles&%u)<>0 " // All my roles in different courses - " ORDER BY AnnCod DESC", - (unsigned) Gbl.Usrs.Me.UsrDat.Roles.InCrss); + NumAnnouncements = (unsigned) + DB_QuerySELECT (&mysql_res,"can not get announcements", + "SELECT AnnCod," // row[0] + "Status," // row[1] + "Roles," // row[2] + "Subject," // row[3] + "Content" // row[4] + " FROM ann_announcements" + " WHERE (Roles&%u)<>0 " // All my roles in different courses + " ORDER BY AnnCod DESC", + (unsigned) Gbl.Usrs.Me.UsrDat.Roles.InCrss); } else // No user logged - { /* Select only active announcements for unknown users */ - NumAnnouncements = (unsigned) DB_QuerySELECT (&mysql_res,"can not get announcements", - "SELECT AnnCod," // row[0] - "Status," // row[1] - "Roles," // row[2] - "Subject," // row[3] - "Content" // row[4] - " FROM ann_announcements" - " WHERE Status=%u" - " AND (Roles&%u)<>0 " - " ORDER BY AnnCod DESC", - (unsigned) Ann_ACTIVE_ANNOUNCEMENT, - (unsigned) (1 << Rol_UNK)); - } + NumAnnouncements = (unsigned) + DB_QuerySELECT (&mysql_res,"can not get announcements", + "SELECT AnnCod," // row[0] + "Status," // row[1] + "Roles," // row[2] + "Subject," // row[3] + "Content" // row[4] + " FROM ann_announcements" + " WHERE Status=%u" + " AND (Roles&%u)<>0 " + " ORDER BY AnnCod DESC", + (unsigned) Ann_ACTIVE_ANNOUNCEMENT, + (unsigned) (1 << Rol_UNK)); /***** Begin box *****/ Box_BoxBegin ("550px",Txt_Announcements, @@ -231,21 +230,22 @@ void Ann_ShowMyAnnouncementsNotMarkedAsSeen (void) /***** Select announcements not seen *****/ Rol_GetRolesInAllCrssIfNotYetGot (&Gbl.Usrs.Me.UsrDat); - NumAnnouncements = (unsigned) DB_QuerySELECT (&mysql_res,"can not get announcements", - "SELECT AnnCod," // row[0] - "Subject," // row[1] - "Content" // row[2] - " FROM ann_announcements" - " WHERE Status=%u" - " AND (Roles&%u)<>0 " // All my roles in different courses - " AND AnnCod NOT IN" - " (SELECT AnnCod" - " FROM ann_seen" - " WHERE UsrCod=%ld)" - " ORDER BY AnnCod DESC", // Newest first - (unsigned) Ann_ACTIVE_ANNOUNCEMENT, - (unsigned) Gbl.Usrs.Me.UsrDat.Roles.InCrss, - Gbl.Usrs.Me.UsrDat.UsrCod); + NumAnnouncements = (unsigned) + DB_QuerySELECT (&mysql_res,"can not get announcements", + "SELECT AnnCod," // row[0] + "Subject," // row[1] + "Content" // row[2] + " FROM ann_announcements" + " WHERE Status=%u" + " AND (Roles&%u)<>0 " // All my roles in different courses + " AND AnnCod NOT IN" + " (SELECT AnnCod" + " FROM ann_seen" + " WHERE UsrCod=%ld)" + " ORDER BY AnnCod DESC", // Newest first + (unsigned) Ann_ACTIVE_ANNOUNCEMENT, + (unsigned) Gbl.Usrs.Me.UsrDat.Roles.InCrss, + Gbl.Usrs.Me.UsrDat.UsrCod); /***** Show the announcements *****/ if (NumAnnouncements) diff --git a/swad_changelog.h b/swad_changelog.h index 272edfe3..0d1b3d28 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -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.61 (2021-04-13)" +#define Log_PLATFORM_VERSION "SWAD 20.62 (2021-04-15)" #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.62: Apr 15, 2021 Optimizations in database selects related to roles. (308574 lines) 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) diff --git a/swad_chat.c b/swad_chat.c index e37be996..b2a3b768 100644 --- a/swad_chat.c +++ b/swad_chat.c @@ -352,7 +352,7 @@ static unsigned Cht_GetNumUsrsInChatRoom (const char *RoomCode) /***** Get number of users connected to chat rooms from database *****/ return DB_QuerySELECTUnsigned ("can not get number of users" " connected to a chat room", - "SELECT NumUsrs" // row[0] + "SELECT NumUsrs" " FROM cht_rooms" " WHERE RoomCode='%s'", RoomCode); diff --git a/swad_database.c b/swad_database.c index 86a52096..b8bc07d0 100644 --- a/swad_database.c +++ b/swad_database.c @@ -3906,6 +3906,40 @@ double DB_QuerySELECTDouble (const char *MsgError, return DoubleNum; } +/*****************************************************************************/ +/***** Make a SELECT query for a unique row with one role from database ******/ +/*****************************************************************************/ + +Rol_Role_t DB_QuerySELECTRole (const char *MsgError, + const char *fmt,...) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + va_list ap; + int NumBytesPrinted; + char *Query; + Rol_Role_t Role = Rol_UNK; + + /***** 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]) + Role = Rol_ConvertUnsignedStrToRole (row[0]); + } + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return Role; + } /*****************************************************************************/ /**** Make a SELECT query for a unique row with one double from database *****/ diff --git a/swad_database.h b/swad_database.h index 617a9927..3438fd19 100644 --- a/swad_database.h +++ b/swad_database.h @@ -29,6 +29,8 @@ #include // To access MySQL databases +#include "swad_role.h" + /*****************************************************************************/ /***************************** Public prototypes *****************************/ /*****************************************************************************/ @@ -47,6 +49,8 @@ unsigned DB_QuerySELECTUnsigned (const char *MsgError, const char *fmt,...); double DB_QuerySELECTDouble (const char *MsgError, const char *fmt,...); +Rol_Role_t DB_QuerySELECTRole (const char *MsgError, + const char *fmt,...); void DB_QuerySELECTString (char *Str,size_t StrSize,const char *MsgError, const char *fmt,...); diff --git a/swad_enrolment.c b/swad_enrolment.c index aa2db79b..caa22d04 100644 --- a/swad_enrolment.c +++ b/swad_enrolment.c @@ -260,8 +260,8 @@ void Enr_ModifyRoleInCurrentCrs (struct UsrData *UsrDat,Rol_Role_t NewRole) Usr_FlushCachesUsr (); /***** Set user's roles *****/ - UsrDat->Roles.InCurrentCrs.Role = NewRole; - UsrDat->Roles.InCurrentCrs.Valid = true; + UsrDat->Roles.InCurrentCrs.Role = NewRole; + UsrDat->Roles.InCurrentCrs.Filled = true; UsrDat->Roles.InCrss = -1; // Force roles to be got from database Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles @@ -326,8 +326,8 @@ void Enr_RegisterUsrInCurrentCrs (struct UsrData *UsrDat,Rol_Role_t NewRole, Usr_FlushCachesUsr (); /***** Set roles *****/ - UsrDat->Roles.InCurrentCrs.Role = NewRole; - UsrDat->Roles.InCurrentCrs.Valid = true; + UsrDat->Roles.InCurrentCrs.Role = NewRole; + UsrDat->Roles.InCurrentCrs.Filled = true; UsrDat->Roles.InCrss = -1; // Force roles to be got from database Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); // Get roles @@ -3960,8 +3960,8 @@ void Enr_ModifyUsr1 (void) /***** If it's me, change my roles *****/ if (ItsMe) { - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs.Role; - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Valid = true; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs.Role; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Filled = true; Gbl.Usrs.Me.UsrDat.Roles.InCrss = Gbl.Usrs.Other.UsrDat.Roles.InCrss; Rol_SetMyRoles (); } @@ -4243,8 +4243,8 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat, Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Valid = - UsrDat->Roles.InCurrentCrs.Valid = true; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Filled = + UsrDat->Roles.InCurrentCrs.Filled = true; Gbl.Usrs.Me.UsrDat.Roles.InCrss = UsrDat->Roles.InCrss = -1; // not yet filled/calculated @@ -4254,9 +4254,9 @@ static void Enr_EffectivelyRemUsrFromCrs (struct UsrData *UsrDat, else // Not me { /* Now he/she does not belong to current course */ - UsrDat->Accepted = false; - UsrDat->Roles.InCurrentCrs.Role = Rol_USR; - UsrDat->Roles.InCurrentCrs.Valid = false; + UsrDat->Accepted = false; + UsrDat->Roles.InCurrentCrs.Role = Rol_USR; + UsrDat->Roles.InCurrentCrs.Filled = false; // TODO: Set to true? } if (QuietOrVerbose == Cns_VERBOSE) diff --git a/swad_exam.c b/swad_exam.c index fbe416f0..9e948ac7 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -1777,7 +1777,7 @@ unsigned Exa_GetPrevQuestionIndexInExam (long ExaCod,unsigned QstInd) // Although indexes are always continuous... // ...this implementation works even with non continuous indexes return DB_QuerySELECTUnsigned ("can not get previous question index", - "SELECT MAX(QstInd)" // row[0] + "SELECT MAX(QstInd)" " FROM exa_set_questions" " WHERE ExaCod=%ld" " AND QstInd<%u", diff --git a/swad_figure.c b/swad_figure.c index affb3859..d922f94f 100644 --- a/swad_figure.c +++ b/swad_figure.c @@ -4048,7 +4048,7 @@ static void Fig_GetAndShowFollowStats (void) case Hie_Lvl_SYS: Average = DB_QuerySELECTDouble ("can not get number of questions" " per survey", - "SELECT AVG(N)" // row[0] + "SELECT AVG(N)" " FROM (SELECT COUNT(%s) AS N" " FROM usr_follow" " GROUP BY %s) AS F", @@ -4058,7 +4058,7 @@ static void Fig_GetAndShowFollowStats (void) case Hie_Lvl_CTY: Average = DB_QuerySELECTDouble ("can not get number of questions" " per survey", - "SELECT AVG(N)" // row[0] + "SELECT AVG(N)" " FROM (SELECT COUNT(DISTINCT usr_follow.%s) AS N" " FROM ins_instits," "ctr_centers," @@ -4081,7 +4081,7 @@ static void Fig_GetAndShowFollowStats (void) case Hie_Lvl_INS: Average = DB_QuerySELECTDouble ("can not get number of questions" " per survey", - "SELECT AVG(N)" // row[0] + "SELECT AVG(N)" " FROM (SELECT COUNT(DISTINCT usr_follow.%s) AS N" " FROM ctr_centers," "deg_degrees," @@ -4102,7 +4102,7 @@ static void Fig_GetAndShowFollowStats (void) case Hie_Lvl_CTR: Average = DB_QuerySELECTDouble ("can not get number of questions" " per survey", - "SELECT AVG(N)" // row[0] + "SELECT AVG(N)" " FROM (SELECT COUNT(DISTINCT usr_follow.%s) AS N" " FROM deg_degrees," "crs_courses," @@ -4121,7 +4121,7 @@ static void Fig_GetAndShowFollowStats (void) case Hie_Lvl_DEG: Average = DB_QuerySELECTDouble ("can not get number of questions" " per survey", - "SELECT AVG(N)" // row[0] + "SELECT AVG(N)" " FROM (SELECT COUNT(DISTINCT usr_follow.%s) AS N" " FROM crs_courses," "crs_users," @@ -4138,7 +4138,7 @@ static void Fig_GetAndShowFollowStats (void) case Hie_Lvl_CRS: Average = DB_QuerySELECTDouble ("can not get number of questions" " per survey", - "SELECT AVG(N)" // row[0] + "SELECT AVG(N)" " FROM (SELECT COUNT(DISTINCT usr_follow.%s) AS N" " FROM crs_users," "usr_follow" diff --git a/swad_global.c b/swad_global.c index 89d3e99d..09d7444e 100644 --- a/swad_global.c +++ b/swad_global.c @@ -338,6 +338,7 @@ void Gbl_InitializeGlobals (void) Usr_FlushCacheUsrBelongsToCurrentCrs (); Usr_FlushCacheUsrHasAcceptedInCurrentCrs (); Usr_FlushCacheUsrSharesAnyOfMyCrs (); + Rol_FlushCacheMyRoleInCurrentCrs (); Rol_FlushCacheRoleUsrInCrs (); Prj_FlushCacheMyRolesInProject (); Grp_FlushCacheIBelongToGrp (); diff --git a/swad_global.h b/swad_global.h index f3ca53b3..4fc1f229 100644 --- a/swad_global.h +++ b/swad_global.h @@ -602,6 +602,11 @@ struct Globals long CrsCod; Rol_Role_t Role; } RoleUsrInCrs; + struct + { + bool Cached; + Rol_Role_t Role; + } MyRoleInCurrentCrs; struct { long PrjCod; diff --git a/swad_profile.c b/swad_profile.c index 636fff98..0f1a8ed3 100644 --- a/swad_profile.c +++ b/swad_profile.c @@ -314,9 +314,9 @@ bool Prf_ShowUserProfile (struct UsrData *UsrDat) Gbl.Hierarchy.Level == Hie_Lvl_CRS) // ...and a course is selected { /* Get user's role in current course */ - UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, - Gbl.Hierarchy.Crs.CrsCod); - UsrDat->Roles.InCurrentCrs.Valid = true; + UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, + Gbl.Hierarchy.Crs.CrsCod); + UsrDat->Roles.InCurrentCrs.Filled = true; /* Get if user has accepted enrolment in current course */ UsrDat->Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (UsrDat); diff --git a/swad_record.c b/swad_record.c index 636dd59d..048aad0b 100644 --- a/swad_record.c +++ b/swad_record.c @@ -2050,9 +2050,9 @@ void Rec_ShowFormOtherNewSharedRecord (struct UsrData *UsrDat,Rol_Role_t Default /* In this case UsrDat->Roles.InCurrentCrsDB is not the current role in current course. Instead it is initialized with the preferred role. */ - UsrDat->Roles.InCurrentCrs.Role = (Gbl.Hierarchy.Level == Hie_Lvl_CRS) ? DefaultRole : // Course selected - Rol_UNK; // No course selected - UsrDat->Roles.InCurrentCrs.Valid = true; + UsrDat->Roles.InCurrentCrs.Role = (Gbl.Hierarchy.Level == Hie_Lvl_CRS) ? DefaultRole : // Course selected + Rol_UNK; // No course selected + UsrDat->Roles.InCurrentCrs.Filled = true; Rec_ShowSharedUsrRecord (Rec_SHA_OTHER_NEW_USR_FORM,UsrDat,NULL); } diff --git a/swad_role.c b/swad_role.c index f5af858f..d32209bb 100644 --- a/swad_role.c +++ b/swad_role.c @@ -85,10 +85,10 @@ void Rol_SetMyRoles (void) bool ICanBeDegAdm = false; /***** Get my role in current course if not yet filled *****/ - if (!Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Valid) + if (!Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Filled) { - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetMyRoleInCrs (Gbl.Hierarchy.Crs.CrsCod); - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Valid = true; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetMyRoleInCrs (Gbl.Hierarchy.Crs.CrsCod); + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Filled = true; } /***** Set the user's role I am logged *****/ @@ -315,44 +315,68 @@ Rol_Role_t Rol_GetMyMaxRoleInDeg (long DegCod) { unsigned NumMyDeg; - if (DegCod > 0) - { - /***** Fill the list with the degrees I belong to (if not already filled) *****/ - Usr_GetMyDegrees (); + /***** 1. Fast check: trivial cases *****/ + if (DegCod <= 0) + return Rol_UNK; - /***** Check if the degree passed as parameter is any of my degrees *****/ - for (NumMyDeg = 0; - NumMyDeg < Gbl.Usrs.Me.MyDegs.Num; - NumMyDeg++) - if (Gbl.Usrs.Me.MyDegs.Degs[NumMyDeg].DegCod == DegCod) - return Gbl.Usrs.Me.MyDegs.Degs[NumMyDeg].MaxRole; - return Rol_GST; - } - return Rol_UNK; // No degree + /***** Fill the list with the degrees I belong to (if not already filled) *****/ + Usr_GetMyDegrees (); + + /***** Check if the degree passed as parameter is any of my degrees *****/ + for (NumMyDeg = 0; + NumMyDeg < Gbl.Usrs.Me.MyDegs.Num; + NumMyDeg++) + if (Gbl.Usrs.Me.MyDegs.Degs[NumMyDeg].DegCod == DegCod) + return Gbl.Usrs.Me.MyDegs.Degs[NumMyDeg].MaxRole; + return Rol_GST; } /*****************************************************************************/ /*************************** Get my role in a course *************************/ /*****************************************************************************/ +void Rol_FlushCacheMyRoleInCurrentCrs (void) + { + Gbl.Cache.MyRoleInCurrentCrs.Cached = false; + Gbl.Cache.MyRoleInCurrentCrs.Role = Rol_UNK; + } + Rol_Role_t Rol_GetMyRoleInCrs (long CrsCod) { unsigned NumMyCrs; + Rol_Role_t Role; - if (CrsCod > 0) + /***** 1. Fast check: trivial cases *****/ + if (CrsCod <= 0) + return Rol_UNK; + + /***** 2. Fast check: is my role in current course already calculated? *****/ + if (CrsCod == Gbl.Hierarchy.Crs.CrsCod && + Gbl.Cache.MyRoleInCurrentCrs.Cached) + return Gbl.Cache.MyRoleInCurrentCrs.Role; + + /***** 3. Slow check: get my role from list of my courses *****/ + /* Fill the list with the courses I belong to (if not already filled) */ + Usr_GetMyCourses (); + + /* Check if the current course is any of my courses */ + for (NumMyCrs = 0, Role = Rol_UNK; + NumMyCrs < Gbl.Usrs.Me.MyCrss.Num; + NumMyCrs++) + if (Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].CrsCod == CrsCod) + { + Role = Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].Role; + break; + } + + /* Update my role in current course */ + if (CrsCod == Gbl.Hierarchy.Crs.CrsCod) { - /***** Fill the list with the courses I belong to (if not already filled) *****/ - Usr_GetMyCourses (); - - /***** Check if the course is any of my courses *****/ - for (NumMyCrs = 0; - NumMyCrs < Gbl.Usrs.Me.MyCrss.Num; - NumMyCrs++) - if (Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].CrsCod == CrsCod) - return Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].Role; + Gbl.Cache.MyRoleInCurrentCrs.Role = Role; + Gbl.Cache.MyRoleInCurrentCrs.Cached = true; } - return Rol_UNK; + return Role; } /*****************************************************************************/ @@ -363,14 +387,11 @@ void Rol_FlushCacheRoleUsrInCrs (void) { Gbl.Cache.RoleUsrInCrs.UsrCod = -1L; Gbl.Cache.RoleUsrInCrs.CrsCod = -1L; - Gbl.Cache.RoleUsrInCrs.Role = Rol_UNK; + Gbl.Cache.RoleUsrInCrs.Role = Rol_UNK; } Rol_Role_t Rol_GetRoleUsrInCrs (long UsrCod,long CrsCod) { - MYSQL_RES *mysql_res; - MYSQL_ROW row; - /***** 1. Fast check: trivial cases *****/ if (UsrCod <= 0 || CrsCod <= 0) @@ -378,26 +399,26 @@ Rol_Role_t Rol_GetRoleUsrInCrs (long UsrCod,long CrsCod) /***** 2. Fast check: Is role in course already calculated? *****/ if (UsrCod == Gbl.Cache.RoleUsrInCrs.UsrCod && - CrsCod == Gbl.Cache.RoleUsrInCrs.CrsCod ) + CrsCod == Gbl.Cache.RoleUsrInCrs.CrsCod) return Gbl.Cache.RoleUsrInCrs.Role; - /***** 3. Slow check: Get rol of a user in a course from database. + /***** 3. Slow check: Get role of a user in a course from database. The result of the query will have one row or none *****/ Gbl.Cache.RoleUsrInCrs.UsrCod = UsrCod; Gbl.Cache.RoleUsrInCrs.CrsCod = CrsCod; - Gbl.Cache.RoleUsrInCrs.Role = Rol_UNK; - if (DB_QuerySELECT (&mysql_res,"can not get the role of a user in a course", - "SELECT Role" // row[0] - " FROM crs_users" - " WHERE CrsCod=%ld" - " AND UsrCod=%ld", - CrsCod,UsrCod) == 1) // User belongs to the course - { - row = mysql_fetch_row (mysql_res); - Gbl.Cache.RoleUsrInCrs.Role = Rol_ConvertUnsignedStrToRole (row[0]); - } - DB_FreeMySQLResult (&mysql_res); - + if (UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod) // It's me + /* Get my role in course */ + Gbl.Cache.RoleUsrInCrs.Role = Rol_GetMyRoleInCrs (CrsCod); + else + /* Get role of the user in course from database */ + Gbl.Cache.RoleUsrInCrs.Role = + DB_QuerySELECTRole ("can not get the role of a user in a course", + "SELECT Role" + " FROM crs_users" + " WHERE CrsCod=%ld" + " AND UsrCod=%ld", + CrsCod, + UsrCod); return Gbl.Cache.RoleUsrInCrs.Role; } diff --git a/swad_role.h b/swad_role.h index 6242f02c..02cb4221 100644 --- a/swad_role.h +++ b/swad_role.h @@ -45,6 +45,7 @@ Rol_Role_t Rol_GetMaxRoleInCrss (unsigned Roles); Rol_Role_t Rol_GetMyMaxRoleInIns (long InsCod); Rol_Role_t Rol_GetMyMaxRoleInCtr (long CtrCod); Rol_Role_t Rol_GetMyMaxRoleInDeg (long DegCod); +void Rol_FlushCacheMyRoleInCurrentCrs (void); Rol_Role_t Rol_GetMyRoleInCrs (long CrsCod); void Rol_FlushCacheRoleUsrInCrs (void); Rol_Role_t Rol_GetRoleUsrInCrs (long UsrCod,long CrsCod); diff --git a/swad_user.c b/swad_user.c index 6d8804bc..10fdbad3 100644 --- a/swad_user.c +++ b/swad_user.c @@ -323,8 +323,8 @@ void Usr_ResetUsrDataExceptUsrCodAndIDs (struct UsrData *UsrDat) UsrDat->EnUsrCod[0] = '\0'; UsrDat->Nickname[0] = '\0'; UsrDat->Password[0] = '\0'; - UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; - UsrDat->Roles.InCurrentCrs.Valid = false; + UsrDat->Roles.InCurrentCrs.Role = Rol_UNK; + UsrDat->Roles.InCurrentCrs.Filled = false; UsrDat->Roles.InCrss = -1; // < 0 ==> not yet got from database UsrDat->Accepted = false; @@ -589,9 +589,9 @@ void Usr_GetUsrDataFromUsrCod (struct UsrData *UsrDat,Usr_GetPrefs_t GetPrefs) Str_Copy (UsrDat->Password,row[1],sizeof (UsrDat->Password) - 1); /* Get roles */ - UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, - Gbl.Hierarchy.Crs.CrsCod); - UsrDat->Roles.InCurrentCrs.Valid = true; + UsrDat->Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, + Gbl.Hierarchy.Crs.CrsCod); + UsrDat->Roles.InCurrentCrs.Filled = true; UsrDat->Roles.InCrss = -1; // Force roles to be got from database Rol_GetRolesInAllCrssIfNotYetGot (UsrDat); @@ -894,6 +894,7 @@ void Usr_FlushCachesUsr (void) Usr_FlushCacheUsrBelongsToCurrentCrs (); Usr_FlushCacheUsrHasAcceptedInCurrentCrs (); Usr_FlushCacheUsrSharesAnyOfMyCrs (); + Rol_FlushCacheMyRoleInCurrentCrs (); Rol_FlushCacheRoleUsrInCrs (); Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (); Grp_FlushCacheIBelongToGrp (); @@ -2077,9 +2078,9 @@ bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat) return Gbl.Cache.UsrBelongsToCurrentCrs.Belongs; /***** 3. Fast check: If we know role of user in the current course *****/ - if (UsrDat->Roles.InCurrentCrs.Valid) + if (UsrDat->Roles.InCurrentCrs.Filled) { - Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = UsrDat->UsrCod; + Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = UsrDat->UsrCod; Gbl.Cache.UsrBelongsToCurrentCrs.Belongs = UsrDat->Roles.InCurrentCrs.Role == Rol_STD || UsrDat->Roles.InCurrentCrs.Role == Rol_NET || UsrDat->Roles.InCurrentCrs.Role == Rol_TCH; @@ -2087,7 +2088,7 @@ bool Usr_CheckIfUsrBelongsToCurrentCrs (const struct UsrData *UsrDat) } /***** 4. Fast / slow check: Get if user belongs to current course *****/ - Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = UsrDat->UsrCod; + Gbl.Cache.UsrBelongsToCurrentCrs.UsrCod = UsrDat->UsrCod; Gbl.Cache.UsrBelongsToCurrentCrs.Belongs = Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod, Gbl.Hierarchy.Crs.CrsCod, false); @@ -3415,9 +3416,8 @@ static void Usr_SetMyPrefsAndRoles (void) /* Course may have changed ==> get my role in current course again */ if (Gbl.Hierarchy.Level == Hie_Lvl_CRS) // Course selected { - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetRoleUsrInCrs (Gbl.Usrs.Me.UsrDat.UsrCod, - Gbl.Hierarchy.Crs.CrsCod); - Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Valid = true; + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role = Rol_GetMyRoleInCrs (Gbl.Hierarchy.Crs.CrsCod); + Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Filled = true; } // role and action will be got from last data @@ -9745,7 +9745,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM ins_instits," "ctr_centers," @@ -9764,7 +9764,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_INS: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM ctr_centers," "deg_degrees," @@ -9778,7 +9778,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM ctr_centers," "deg_degrees," @@ -9795,7 +9795,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_CTR: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM deg_degrees," "crs_courses," @@ -9807,7 +9807,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM deg_degrees," "crs_courses," @@ -9822,7 +9822,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_DEG: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM crs_courses," "crs_users" @@ -9832,7 +9832,7 @@ static double Usr_GetNumCrssPerUsr (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of courses per user", - "SELECT AVG(NumCrss)" // row[0] + "SELECT AVG(NumCrss)" " FROM (SELECT COUNT(crs_users.CrsCod) AS NumCrss" " FROM crs_courses," "crs_users" @@ -9886,13 +9886,13 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_SYS: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(UsrCod) AS NumUsrs" " FROM crs_users" " GROUP BY CrsCod) AS NumUsrsTable"); else return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(UsrCod) AS NumUsrs" " FROM crs_users" " WHERE Role=%u GROUP BY CrsCod) AS NumUsrsTable", @@ -9900,7 +9900,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_CTY: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM ins_instits," "ctr_centers," @@ -9916,7 +9916,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM ins_instits," "ctr_centers," @@ -9935,7 +9935,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_INS: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM ctr_centers," "deg_degrees," @@ -9949,7 +9949,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM ctr_centers," "deg_degrees," @@ -9966,7 +9966,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_CTR: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM deg_degrees," "crs_courses," @@ -9978,7 +9978,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM deg_degrees," "crs_courses," @@ -9993,7 +9993,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro case Hie_Lvl_DEG: if (Role == Rol_UNK) // Any user return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM crs_courses," "crs_users" @@ -10003,7 +10003,7 @@ static double Usr_GetNumUsrsPerCrs (Hie_Lvl_Level_t Scope,long Cod,Rol_Role_t Ro Cod); else return DB_QuerySELECTDouble ("can not get number of users per course", - "SELECT AVG(NumUsrs)" // row[0] + "SELECT AVG(NumUsrs)" " FROM (SELECT COUNT(crs_users.UsrCod) AS NumUsrs" " FROM crs_courses," "crs_users" diff --git a/swad_user.h b/swad_user.h index 3852a385..cd40eeaa 100644 --- a/swad_user.h +++ b/swad_user.h @@ -171,7 +171,7 @@ struct UsrData { struct { - bool Valid; // Role is valid (is already filled)? + bool Filled; // Role is valid (is already filled)? Rol_Role_t Role; } InCurrentCrs; // Role in current course (Rol_UNK is no course selected) int InCrss; // Roles in all his/her courses