// swad_course_database.c: edition of courses operations with database
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2021 Antonio Caņas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#define _GNU_SOURCE // For asprintf
#include // For asprintf
#include // For free
#include "swad_course.h"
#include "swad_course_config.h"
#include "swad_database.h"
#include "swad_error.h"
#include "swad_global.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/*************************** Public constants ********************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private types *********************************/
/*****************************************************************************/
/*****************************************************************************/
/**************************** Private variables ******************************/
/*****************************************************************************/
/*****************************************************************************/
/**************************** Private prototypes *****************************/
/*****************************************************************************/
/*****************************************************************************/
/************* Add a new requested course to pending requests ****************/
/*****************************************************************************/
void Crs_DB_CreateCourse (struct Crs_Course *Crs,unsigned Status)
{
/***** Insert new course into pending requests *****/
Crs->CrsCod =
DB_QueryINSERTandReturnCode ("can not create a new course",
"INSERT INTO crs_courses"
" (DegCod,Year,InsCrsCod,Status,RequesterUsrCod,"
"ShortName,FullName)"
" VALUES"
" (%ld,%u,'%s',%u,%ld,"
"'%s','%s')",
Crs->DegCod,
Crs->Year,
Crs->InstitutionalCrsCod,
Status,
Gbl.Usrs.Me.UsrDat.UsrCod,
Crs->ShrtName,
Crs->FullName);
}
/*****************************************************************************/
/******************* Get courses of a degree from database *******************/
/*****************************************************************************/
unsigned Crs_DB_GetCrssInDeg (MYSQL_RES **mysql_res,long DegCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get courses of a degree",
"SELECT CrsCod"
" FROM crs_courses"
" WHERE DegCod=%ld",
DegCod);
}
/*****************************************************************************/
/******************** Get courses in current degree *********************/
/*****************************************************************************/
unsigned Crs_DB_GetCrssInCurrentDegBasic (MYSQL_RES **mysql_res)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get courses of a degree",
"SELECT CrsCod," // row[0]
"ShortName" // row[1]
" FROM crs_courses"
" WHERE DegCod=%ld"
" ORDER BY ShortName",
Gbl.Hierarchy.Deg.DegCod);
}
/*****************************************************************************/
/******************** Get courses in current degree *********************/
/*****************************************************************************/
unsigned Crs_DB_GetCrssInCurrentDegFull (MYSQL_RES **mysql_res)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get courses of a degree",
"SELECT CrsCod," // row[0]
"DegCod," // row[1]
"Year," // row[2]
"InsCrsCod," // row[3]
"Status," // row[4]
"RequesterUsrCod," // row[5]
"ShortName," // row[6]
"FullName" // row[7]
" FROM crs_courses"
" WHERE DegCod=%ld"
" AND (Status & %u)=0"
" ORDER BY Year,"
"ShortName",
Gbl.Hierarchy.Deg.DegCod,
(unsigned) Crs_STATUS_BIT_REMOVED); // All courses except those removed
}
/*****************************************************************************/
/********************* Get data of a course from its code ********************/
/*****************************************************************************/
unsigned Crs_DB_GetDataOfCourseByCod (MYSQL_RES **mysql_res,long CrsCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get data of a course",
"SELECT CrsCod," // row[0]
"DegCod," // row[1]
"Year," // row[2]
"InsCrsCod," // row[3]
"Status," // row[4]
"RequesterUsrCod," // row[5]
"ShortName," // row[6]
"FullName" // row[7]
" FROM crs_courses"
" WHERE CrsCod=%ld",
CrsCod);
}
/*****************************************************************************/
/******* Get the short names of degree and course from a course code *********/
/*****************************************************************************/
void Crs_DB_GetShortNamesByCod (long CrsCod,
char CrsShortName[Cns_HIERARCHY_MAX_BYTES_SHRT_NAME + 1],
char DegShortName[Cns_HIERARCHY_MAX_BYTES_SHRT_NAME + 1])
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
DegShortName[0] = CrsShortName[0] = '\0';
/***** Trivial check: course code should be > 0 *****/
if (CrsCod <= 0)
return;
/***** Get the short name of a degree from database *****/
if (DB_QuerySELECT (&mysql_res,"can not get the short name of a course",
"SELECT crs_courses.ShortName," // row[0]
"deg_degrees.ShortName" // row[1]
" FROM crs_courses,"
"deg_degrees"
" WHERE crs_courses.CrsCod=%ld"
" AND crs_courses.DegCod=deg_degrees.DegCod",
CrsCod) == 1)
{
/***** Get the course short name and degree short name *****/
row = mysql_fetch_row (mysql_res);
Str_Copy (CrsShortName,row[0],Cns_HIERARCHY_MAX_BYTES_SHRT_NAME);
Str_Copy (DegShortName,row[1],Cns_HIERARCHY_MAX_BYTES_SHRT_NAME);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********** Check if the name of course exists in existing courses ***********/
/*****************************************************************************/
bool Crs_DB_CheckIfCrsNameExistsInYearOfDeg (const char *FieldName,const char *Name,long CrsCod,
long DegCod,unsigned Year)
{
/***** Get number of courses in a year of a degree and with a name from database *****/
return (DB_QueryCOUNT ("can not check if the name"
" of a course already existed",
"SELECT COUNT(*)"
" FROM crs_courses"
" WHERE DegCod=%ld"
" AND Year=%u"
" AND %s='%s'"
" AND CrsCod<>%ld",
DegCod,
Year,
FieldName,
Name,
CrsCod) != 0);
}
/*****************************************************************************/
/************************** Write courses of a user **************************/
/*****************************************************************************/
unsigned Crs_DB_GetCrssOfAUsr (MYSQL_RES **mysql_res,long UsrCod,Rol_Role_t Role)
{
char *SubQuery;
unsigned NumCrss;
/***** Get courses of a user from database *****/
if (Role == Rol_UNK) // Role == Rol_UNK ==> any role
{
if (asprintf (&SubQuery,"%s","") < 0)
Err_NotEnoughMemoryExit ();
}
else
{
if (asprintf (&SubQuery," AND crs_users.Role=%u",(unsigned) Role) < 0)
Err_NotEnoughMemoryExit ();
}
NumCrss = (unsigned)
DB_QuerySELECT (mysql_res,"can not get courses of a user",
"SELECT deg_degrees.DegCod," // row[0]
"crs_courses.CrsCod," // row[1]
"deg_degrees.ShortName," // row[2]
"deg_degrees.FullName," // row[3]
"crs_courses.Year," // row[4]
"crs_courses.FullName," // row[5]
"ctr_centers.ShortName," // row[6]
"crs_users.Accepted" // row[7]
" FROM crs_users,"
"crs_courses,"
"deg_degrees,"
"ctr_centers"
" WHERE crs_users.UsrCod=%ld%s"
" AND crs_users.CrsCod=crs_courses.CrsCod"
" AND crs_courses.DegCod=deg_degrees.DegCod"
" AND deg_degrees.CtrCod=ctr_centers.CtrCod"
" ORDER BY deg_degrees.FullName,"
"crs_courses.Year,"
"crs_courses.FullName",
UsrCod,SubQuery);
/***** Free allocated memory for subquery *****/
free (SubQuery);
return NumCrss;
}
/*****************************************************************************/
/************************** Get old courses from database ********************/
/*****************************************************************************/
unsigned Crs_DB_GetOldCrss (MYSQL_RES **mysql_res,unsigned long SecondsWithoutAccess)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get old courses",
"SELECT CrsCod"
" FROM crs_last"
" WHERE LastTime