upgrading moodle from 3.9 to 4.0.1 duplicate entry error - moodle

I'm trying to upgrade moodle from 3.9 to 4.0.1 but keep getting the following error in the database. Please could you advise on how to resolve this. Thank You in advance
Error writing to database
×Debug info: Duplicate entry '35-mod_quiz-slot-3' for key 'mdl_quesrefe_usicomqueite_uix'
INSERT INTO mdl_question_references
(usingcontextid, component, questionarea, itemid, questionbankentryid)
SELECT c.id, 'mod_quiz', 'slot', qs.id, qv.questionbankentryid
FROM mdl_question q
JOIN mdl_question_versions qv ON q.id = qv.questionid
JOIN mdl_quiz_slots qs ON q.id = qs.questionid
JOIN mdl_modules m ON m.name = 'quiz'
JOIN mdl_course_modules cm ON cm.module = m.id AND cm.instance = qs.quizid
JOIN mdl_context c ON c.instanceid = cm.id AND c.contextlevel = 70
WHERE q.qtype <> 'random'
[array (
)]
Error code: dmlwriteexception

Related

Incorrect number of query parameters in Moodle *How to get the external links from course page

My Dear
I tried to run the following ad-hoc database query in Moodle but i got it error
there any way to fix it , thanks
*My target to find all the external links (URL) from course page
SELECT
concat('<a target="_new" href=%%WWWROOT%%/course/view.php?id=',
c.id, '">', c.fullname, '</a>') AS Course
,c.shortname,r.name
,(
SELECT CONCAT(u.firstname,' ', u.lastname) AS Teacher
FROM prefix_role_assignments AS ra
JOIN prefix_context AS ctx ON ra.contextid = ctx.id
JOIN prefix_user AS u ON u.id = ra.userid
WHERE ra.roleid = 3
AND ctx.instanceid = c.id
LIMIT 1
) AS Teacher
,concat('<a target="_new" href="%%WWWROOT%%/mod/resource/view.php?id=',
r.id, '">', r.name, '</a>') AS Resource
FROM prefix_resource AS r
JOIN prefix_course AS c ON r.course = c.id
WHERE r.reference LIKE 'https://stackoverflow.com/%'
Error message :
" Error when executing the query: ERROR: Incorrect number of query
parameters. Expected 2, got 0"
When executing SQL statements in Moodle, any '?' characters are used to indicate placeholders for parameters that need to be provided along with the query.
From the style of your query, I'm assuming you're using report_customsql or block_configurablereports for your query, so you won't have the option of providing such parameters.
If you look at the documentation here: https://docs.moodle.org/en/Custom_SQL_queries_report you will see that the workaround for this is to replace any '?' characters in your query with '%%Q%%'.
So the fixed query should look like:
SELECT concat('<a target="_new" href="%%WWWROOT%%/course/view.php%%Q%%id=',c.id,'">',c.fullname,'</a>') AS Course,
c.shortname,r.name, (SELECT CONCAT(u.firstname,' ', u.lastname) AS Teacher
FROM prefix_role_assignments AS ra
JOIN prefix_context AS ctx ON ra.contextid = ctx.id
JOIN prefix_user AS u ON u.id = ra.userid
WHERE ra.roleid = 3 AND ctx.instanceid = c.id LIMIT 1) AS Teacher,
concat('<a target="_new" href="%%WWWROOT%%/mod/resource/view.php%%Q%%id=',r.id,'">',r.name,'</a>') AS Resource
FROM prefix_resource AS r
JOIN prefix_course AS c ON r.course = c.id
WHERE r.reference LIKE 'https://stackoverflow.com/%'

how to get courses created by particular user in moodle 3

Currently I'm working on moodle-3 plug-in development,and I have a user Id who is a course creator and i want to get all courses created by that user,is their any function, I can use or if you can help me with names of tables where I can fetch this data.I tried table called standard log where I can get all events is that only way to do it.
Not sure if this will work but you could try searching for courses that have the coursecreator role assigned.
SELECT r.shortname, u.username, c.fullname AS coursename
FROM mdl_role r
JOIN mdl_role_assignments ra ON ra.roleid = r.id
JOIN mdl_context ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
JOIN mdl_course c ON c.id = ctx.instanceid
JOIN mdl_user u ON u.id = ra.userid
WHERE r.shortname = 'coursecreator'

Postgres UPDATE statement

I have moved from mysql to psql, but find it hard to get my head around the UPDATE statement using multiple left joins.
How would you rewrite this in Postgres? (I am using postresql 9.4)
update task t
left join project p on t.project_id = p.id
left join client c on t.client_id = c.id
left join user u on t.user_id = u.id
set t.project_name = p.name,
t.client_name = c.name,
t.user_name = u.name;
Any pointer will be welcome.
Here you go:
WITH task_data AS (
SELECT t.id,
p.name AS project_name,
c.name AS client_name,
u.name AS user_name
FROM task t
LEFT JOIN project p ON t.project_id = p.id
LEFT JOIN client c ON t.client_id = c.id
LEFT JOIN "user" u ON t.user_id = u.id
)
UPDATE task t
FROM task_data d
SET
project_name = d.project_name,
client_name = d.client_name,
user_name = d.user_name
WHERE t.id = d.id
I would be curious to see if there is a more efficient way

JPA Criteria JOIN et ON

I have been searching for a while, I haven't found any responses to my problem.
I am making an application in JSF, EclipseLink, Glassfish in which the user can have one or more groups. The application contains modules and permissions as follows:
Module => permission => utilisateur
Module => permission => groupe => utilisateur
I am looking for a criteria query (not in jqpl) to get all of the modules of a user. I have constructed my SQL query, which functions very well like this:
SELECT *
FROM core_module m
WHERE m.id IN (
SELECT m.id
FROM core_module m
INNER JOIN modules_permissions mp
ON mp.modules_id = m.id
INNER JOIN core_permission p
ON p.id = mp.permissions_id
INNER JOIN users_permissions up
ON p.id = up.permissions_id
INNER JOIN core_user u
ON u.id = 1
)
OR m.id IN (
SELECT m.id
FROM core_module m
INNER JOIN modules_permissions mp
ON m.id = mp.modules_id
INNER JOIN core_permission p
ON p.id = mp.permissions_id
INNER JOIN groups_permissions gp
ON gp.permissions_id = p.id
INNER JOIN core_group g
ON g.id = gp.groups_id
INNER JOIN users_groups ug
ON g.id = ug.groups_id
INNER JOIN core_user u
ON u.id = ug.users_id
WHERE u.id = 1
)
I am trying somehow to transform this into a criteria query without great success. I have just started the first part of the query, which gives me the modules immediately accessible to a user. I have the impression that I am missing some conditions or joins, as I am getting 2 results when I shouldn't be getting any. In effect, I haven't been able to include my ON clauses, so I can't change my to joins in my query since the entities don't exist: the table modules_permissions is created by a #ManyToMany in my entities...
Here is my first draft subquery:
List<Module> modules;
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Root<User> root_user = query.from(User.class);
Root<Permission> root_permission = query.from(Permission.class);
Root<Group> root_group = query.from(Group.class);
Join<Module, Permission> join_module_permission = root_module.join(Module_.permissions);
Join<Permission, User> join_permission_user = root_permission.join(Permission_.users);
query.where(cb.equal(root_user.get(User_.email), current.getEmail()));
modules = getEntityManager().createQuery(query).getResultList();
Try turning EclipseLink logging to finest so you can see the SQL that is generated. You might also use JPQL as it is closer to the SQL, and then convert to criteria once you have something working. Something like
"select m from Module m where
m in (select m1 from Module m1 join m1.permissions p join p.users u where u.id = 1) or
m in (select m2 from Module m2 join m2.permissions p2 join p2.groups g join g.users u2 where u2.id =1)"
The key here is that you use the entity relationships in the criteria query so that it matches what you want in the generated SQL. Don't use multiple from clauses when you only want those tables and their joins included in an inner query. If the above JPQL works and the relationships exist, something like this is equivalent:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Path path = root_module.get(Module_.id);
Subquery<Integer> subquery = criteriaQuery.subquery(Integer.class);
Root subRoot = subquery.from(Module.class);
subquery.select(subRoot.get((Module_.id)));
Join user1 = subRoot.join(Module_.permissions).join(Permission_.users);
subquery.where(criteriaBuilder.equals(user1.get(User_.id), 1));
Subquery<Integer> subquery2 = criteriaQuery.subquery(Integer.class);
Root subRoot2 = subquery.from(Module.class);
subquery2.select(subRoot2.get((Module_.id)));
Join user2 = subRoot2.join(Module_.permissions).join(Permission_.groups).join(Group_.users);
subquery2.where(criteriaBuilder.equals(user2.get(User_.id), 1));
query.where(criteriaBuilder.or(criteriaBuilder.in(path ).value(subquery),
criteriaBuilder.in(path ).value(subquery2)));
The final answer is :
in JPQL :
#NamedQuery(name = "core_user.findModuleAssociated", query = "select m from Module m where m.id in (select m1.id from Module m1 join m1.permissions p join p.user u where u.id = :userid) or m.id in (select m2.id from Module m2 join m2.permissions p2 join p2.group g join g.users u2 where u2.id = :userid)")
in criteria query :
List<Module> modules;
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Path path = root_module.get(Module_.id);
Subquery<Integer> subquery = query.subquery(Integer.class);
Root subRoot = subquery.from(Module.class);
subquery.select(subRoot.get((Module_.id)));
Join user1 = subRoot.join(Module_.permissions).join(Permission_.user);
subquery.where(cb.equal(user1.get(User_.id), current.getId()));
Subquery<Integer> subquery2 = query.subquery(Integer.class);
Root subRoot2 = subquery.from(Module.class);
subquery2.select(subRoot2.get((Module_.id)));
Join user2 = subRoot2.join(Module_.permissions).join(Permission_.group).join(Group_.users);
subquery2.where(cb.equal(user2.get(User_.id), current.getId()));
query.where(cb.or(cb.in(path).value(subquery), cb.in(path).value(subquery2)));
modules = getEntityManager().createQuery(query).getResultList();
Special thanks to Chris

Moodle - Report to determine how long it takes before a student's assignment is graded

I am using Moodle LMS and I need to run a report to find out how long it takes between the time a student submits any sort of human-gradable assignment and the time it is graded so that we can monitor our staff's efficiency. Right now I am going for a query similar to the one below. I still need to add in the actual assignments but I am not sure which items in moodle could possibly fit into the "submitted but waiting to be graded" category.
Which tables am I missing for this query and is there anything I am obviously doing wrong here?
SELECT c.shortname AS course_name
, cm.id AS cmid
, cm.course AS courseid
, md.name AS modname
, gi.itemname AS itemname
, u.firstname AS student_first
, u.lastname AS student_last
, f.firstname AS grader_first
, f.lastname AS grader_last
, NULLIF(GREATEST(IFNULL(g.overridden, 0)
,IFNULL(g.timecreated, 0)
,IFNULL(g.timemodified, 0))
,0) AS graded_unixtimestamp
FROM mdl_user u
JOIN mdl_user_enrolments ue
ON (u.id = ue.userid)
JOIN mdl_enrol e
ON (e.id = ue.enrolid)
JOIN mdl_course c
ON (c.id = e.courseid)
JOIN mdl_course_modules cm
ON (c.id = cm.course)
JOIN mdl_modules md
ON (md.id = cm.module)
JOIN mdl_grade_items gi
ON (
gi.itemmodule = md.name
AND gi.iteminstance = cm.instance
AND gi.courseid = cm.course)
LEFT
JOIN mdl_grade_grades g
ON (gi.id = g.itemid AND g.userid = u.id)
LEFT
JOIN mdl_user f
ON (g.usermodified = u.id);