first sorry my english :(
I am making a Python program accessing information from moodle. But the access to the server's sql is very slow, I needed to optimize the sql like the one below:
try:
query1 = "SELECT id FROM mdl_user WHERE username= ('%s')" % (self.searchuser2)
cursor.execute(query1)
linhas = cursor.fetchall()
for row in linhas:
self.userid = row[0]
# Pegando enrol_id do curso
query2 = "SELECT id FROM mdl_enrol WHERE courseid = %s AND enrol = 'manual'" % (self.rowidcourse)
cursor.execute(query2)
linhas = cursor.fetchall()
for row in linhas:
self.enrol_courseid = row[0]
# Inserindo o aluno e curso em mdl_user_enrolments
query3 = "INSERT INTO mdl_user_enrolments (status, enrolid, userid, timestart, timeend, timecreated, timemodified) VALUES(0, %s, %s, 1, 0, 1, 1)" % (
self.enrol_courseid, self.userid)
cursor.execute(query3)
mariadb_connection.commit()
# Pegando contex_id do curso e aluno
query4 = "SELECT id FROM mdl_context WHERE instanceid=%s AND contextlevel=50" % (self.rowidcourse)
cursor.execute(query4)
linhas = cursor.fetchall()
for row in linhas:
self.contexid = row[0]
# Inserindo aluno no curso
query5 = "INSERT INTO mdl_role_assignments (roleid,contextid,userid,timemodified) VALUES (5,%s,%s,2000)" \
% (self.contexid, self.userid)
cursor.execute(query5)
mariadb_connection.commit()
closedb()
tkinter.messagebox.showinfo("Muito bem!", "Aluno cadastrado com sucesso.", parent=self.register1)
It looks like you are enrolling all users into all courses? That's potentially a lot of data.
You are also getting all records from mdl_enrol for each loop of mdl_user.
And enrolid isn't the same as courseid. Enrolid is in mdl_enrol.
The code also doesn't check if the data already exists.
Also Moodle has lots of triggers that won't be activated by this code.
It might be better to have a look at Site Admin > Users > Upload users
https://docs.moodle.org/39/en/Upload_users#Enrolment_fields
This will allow you to enrol users into multiple courses.
Related
I have multiple models in Sparx Enterprise Architect in file-based, i.e. using MS access.
I'm using a custom template to populate a table with data from object's properties, including some with <memo> fields.
This is the query i'm using in the template fragment:
SELECT obj.object_id,
obj.Stereotype,
objp.Property as Prop,
switch(objp.Value = '<memo>', objp.Notes, objp.Value LIKE '{*}',
NULL, 1=1, objp.Value) AS Val,
(SELECT tobj2.ea_guid & tobj2.Name FROM t_object tobj2 WHERE
tobj2.ea_guid = objp.Value) AS [Obj-Hyperlink]
FROM t_object obj
INNER JOIN t_objectproperties objp
ON (obj.object_id = objp.object_id)
WHERE obj.object_id = #OBJECTID# AND obj.Stereotype='Data-
Stream' AND objp.Property NOT IN ('isEncapsulated')
ORDER BY objp.Property ASC;
I found that the when these fields are longer than 249 chars I get an error message when generating the reports and the cell in the generated table is simply empty. This is also noticeable with a query:
The error I'm getting states:
"Error Processing xml document: an invalid character was found in text context"
Is there any workarround to enable including the <memo> fields' data with more than 249 chars in the reports?
Any help is much appreciated.
I've found a workaround for this by joining two queries with a "Union all". The first query will handle the non-memo fields with the switch function and the second one the memo fields without the switch function.
select
obj.object_id,
obj.Stereotype,
objp.Property as Prop,
objp.Notes AS Val,
(
SELECT
tobj2.ea_guid & tobj2.Name
FROM
t_object tobj2
WHERE
tobj2.ea_guid = objp.Value
) AS [Obj-Hyperlink]
from
t_objectproperties objp
left join t_object obj on (obj.object_id = objp.object_ID)
where
obj.object_id = #OBJECTID#
AND obj.Stereotype = 'Data-Stream'
AND objp.Property NOT IN ('isEncapsulated')
AND objp.Value = "<memo>"
UNION ALL
SELECT
obj2.object_id,
obj2.Stereotype,
objp2.Property as Prop,
switch(
objp2.Value LIKE '{*}', NULL, 1 = 1, objp2.Value
) AS Val,
(
SELECT
tobj2.ea_guid & tobj2.Name
FROM
t_object tobj2
WHERE
tobj2.ea_guid = objp2.Value
) AS [Obj-Hyperlink]
FROM
t_object obj2
INNER JOIN t_objectproperties objp2 ON (obj2.object_id = objp2.object_id)
WHERE
obj2.object_id = #OBJECTID#
AND obj2.Stereotype = 'Data-Stream'
AND objp2.Property NOT IN ('isEncapsulated')
and objp2.Value <> "<memo>"
order by
3 asc;
Thanks a lot #geertbellekens for your comment which was crucial to find this solution.
I tryied to in insert and select in the same time in mysql PyQt5 but the program didn't work.
the program is working till i tryied to insert and selectin the same time in MySql.
This is the code before I got the issue :
self.groupe.currentTextChanged.connect(self.grouchan)
def grouchan(self):
global id_filint
qidmat = "select Id_filiere from filiereacademiquecsv where Libelle_filiere_francais=%s"
ridmat = (self.txt_filiere.text(),)
mycursor.execute(qidmat, ridmat)
myresult = mycursor.fetchone()
for idf in myresult:
id_filint = idf
qmat = "select distinct Id_matiere from matiereunité m inner join filiereacademiquecsv f on f.Id_filiere=m.Id_filieranalytiq where Id_filieranalytiq=%s and Libelle_matiere_francais=%s"
rnp1 = (id_filint, self.matiere.currentText())
mycursor.execute(qmat,rnp1)
myresult1 = mycursor.fetchone()
for i in myresult1:
print(i)
qgrp = "select idgroupe from groupcyclniv where LibGroupe=%s"
rnp3 = (self.groupe.currentText(),)
mycursor.execute(qgrp, rnp3)
myresult2 = mycursor.fetchone()
for v in myresult2:
print(v)
This is where I got the issue.
This is where I tryied to insert and select :
qnp = "insert into mobile (Id_eleve, nomprenom, Id_matiere) SELECT a.IdEleve,e.nomprenom,m.Id_matiere FROM asselevgroupevf a inner join eleve e inner join matiereunité m on a.IdEleve = e.Ideleve where a.IdGroup =%s and Id_matiere =%s"
rnp1 = (v, i)
mycursor.execute(rnp1, qnp)
mydb.commit()
I have an entity called tracking. It relates to a User and a Course.
I also have an entity called credential which officially links User and Course
User <- Tracking -> Course || User <- Credential -> Course
Tracking is a joining entity of sorts, but it's not the primary join between the two. I have a query where I already have the user and the course joined, and I want to left-join the tracking if it exists. I've tried to simplify my example.
$q->select(
'user.id',
'user.firstname',
'user.lastname',
'count(t) as courses',
'count(t.completed) as completed'
);
$q->from(Credential::class, 'c');
$q->from(Course::class, 'course');
$q->from(User::class, 'user');
$q->leftJoin(Tracking::class, 't', 'WITH', 't.user = user and t.course = course');
$q->where('c.user = user and c.object = course');
$q->groupBy('user');
What I'm trying to achieve here, is a list of users who are enrolled in courses, the number of courses, and where possible the number of completed courses.
Unfortunately, doctrine can only seem to join to either the user table or the course table, but not to both. This might even be a mysql limitation. I've debugged this over and over - and I've run into the problem several times with different examples - and I just can't seem to find a solution other than using ->from(Tracking) which would eliminate students who haven't started any courses, and stats from courses they haven't started. I've googled over and over again, but It's so hard to search for this problem and not get 'How to join two tables with Doctrine'.
I get the error Column not found: 1054 Unknown column 'c1_.id' in 'on clause' which I assume means it can join on t.user = user but not t.course = course
Here is the actual code and error
$q = $this->em->createQueryBuilder();
$q->select(
'user.id',
'user.firstname',
'user.lastname',
'count(sc.id) as courses',
'count(ct.commenced) as commenced',
'count(ct.completed) as completed',
'avg(ct.scorePercent) as avgscore',
'avg(ct.totalTime) as avgtime'
);
$q->from(Security\Credential::class, 'c');
$q->from(Security\SecurableCourse::class, 'sc');
$q->from(Security\AccreditableInheritance::class, 'ai');
$q->from(Security\AccreditableUser::class, 'au');
$q->from(User::class, 'user');
$q->join(Tracking\CourseTracking::class, 'ct', 'WITH', 'ct.objectIdentity = sc and ct.user = user');
$q->where('sc = c.securable and ai.parent = c.accreditable and au = ai.child and user = au.user');
$q->andWhere('c.action = :action and sc.course in (:courses)');
$q->setParameter('action', 'study')->setParameter('courses', $courses);
$q->groupBy('user.id');
$users = $q->getQuery()->getScalarResult();
Doctrine\DBAL\Exception\InvalidFieldNameException(code: 0): An exception occurred while executing 'SELECT u0_.id AS id_0, u0_.firstname AS firstname_1, u0_.lastname AS lastname_2, count(s1_.id) AS sclr_3, count(t2_.commenced) AS sclr_4, count(t2_.completed) AS sclr_5, avg(t2_.scorePercent) AS sclr_6, avg(t2_.totalTime) AS sclr_7 FROM Credential c3_ INNER JOIN Tracking t2_ ON (t2_.objectIdentity_id = s1_.id AND t2_.user_id = u0_.id) AND t2_.dtype IN ('coursetracking') AND ((t2_.deleted IS NULL OR t2_.deleted > '2016-04-26 08:33:31')), SecurableIdentity s1_, AccreditableInheritance a4_, AccreditableIdentity a5_, User u0_ WHERE (((s1_.id = c3_.securable_id AND a4_.parent_id = c3_.accreditable_id AND a5_.id = a4_.child_id AND u0_.id = a5_.user_id) AND (c3_.action = ? AND s1_.course_id IN (?, ?, ?))) AND ((u0_.deleted IS NULL OR u0_.deleted > '2016-04-26 08:33:31'))) AND (s1_.dtype IN ('securablecourse') AND a5_.dtype IN ('accreditableuser')) GROUP BY u0_.id' with params [\"study\", \"46\", \"45\", \"160\"]:\n\nSQLSTATE[42S22]: Column not found: 1054 Unknown column 's1_.id' in 'on clause'
This is just a hint how to achieve it. I cannot give you the correct answer as you don't give enough details. But this will help you to achieve what you need.
$q->select(u, t, co, ce);
$q->from('User', 'u');
$q->leftJoin('u.tracking', 't');
$q->leftJoin('t.course', 'co');
$q->leftJoin('u.credential', 'ce');
I want to look for duplicate members in the database.
First I want to check if their username exists.
If not, I want to check their first name, last name and email address.
Lastly if that doesn't match anyone, I want to just check if a first name and last name exists.
I've been looking at IF/ELSE statements and even CASE in Google but I can't seem to figure out how it would work in my situation.
Here's some code that in my mind makes sense (being a PHP programmer) but it isn't how MySQL does things...
SELECT id FROM members WHERE (
IF (member_username = 'john.doe')
ELSEIF (member_firstname = 'John' AND member_lastname = 'Doe' AND member_email = 'john#doe.com')
ELSE (member_firstname = 'John' AND member_lastname = 'Doe')
) AND deleted = 0
How would I translate the above into working MySQL code if it's even possible.
I ended up taking #Corbin's advice and used
SELECT username, first_name, last_name, email_addr FROM members WHERE username = 'username' OR (first_name = 'first name' AND last_name = 'last name')
And then used PHP if/else statements to determine which record was the exact duplicate.
What would be wrong with this?
SELECT id
FROM members
WHERE (member_username = 'john.doe'
OR (member_firstname = 'John' AND member_lastname = 'Doe' AND member_email = 'john#doe.com')
OR (member_firstname = 'John' AND member_lastname = 'Do'))
AND deleted = 0
Have a look at this: http://docs.oracle.com/cd/E17952_01/refman-5.5-en/control-flow-functions.html#operator_case
Don't forget TOP 1!
SELECT TOP 1 id FROM members WHERE deleted = 0 AND
(
(member_username = 'john.doe') OR
(member_email = 'john#doe.com' AND member_firstname = 'John' AND member_lastname = 'Doe') OR
(member_firstname = 'John' AND member_lastname = 'Doe')
)
i have created the following ruby script that logs into a mysql database and returns order information based on what username and password the user has entered. my question is how would i go about preventing sql injections? i know that the way it is written at the moment leaves it wide open to attacks but i am new to ruby and am not sure how to go about preventing this.
#!/usr/bin/ruby
#Import mysql module
require "mysql"
begin
#Establish connection to mysql database as the operator user.
connection = Mysql.real_connect("localhost", "operator", "", "rainforest")
#Allow Multi line statements
connection.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON)
#Prompt user for username
puts "Please Enter Your Customer Username:"
#Get username entered and store to variable
username = gets.chomp
#Prompt user for password
puts "Please Enter Your Customer Password"
#Get password entered and store to variable
password = gets.chomp
#Specify SQL query that returns order if user entered data matches data held in customer table
customerQuery = connection.query("SELECT O.order_ID, O.date_ordered, C.customer_name, P.product_name
FROM orders As O
INNER JOIN customer As C ON O.customer_ID=C.customer_ID
INNER JOIN product As P ON O.product_ID=P.product_ID
WHERE C.customer_name = '" + name + "' AND C.customer_password = '" + password + "'")
#If query returns a row then user has entered correct login details
if customerQuery.num_rows > 0 then
#tell user they have successfully logged in
puts "User Successfully Authenticated: Hello " + username + ". Here are your orders: \n**********"
#Print all row data containing users order details to screen
while row = customerQuery.fetch_row do
puts row
puts "**********"
end
else
#if no rows return, user has entered incorrect details, inform them of this by printing to screen
puts "User Authentication Unsuccessful:Incorrect Username or Password, Please Try Again"
end
#close connection to database
connection.close
end
Use a prepared statement instead of string concatenation/interpolation:
p = connection.prepare(%q{
select o.order_id, o.date_ordered, c.customer_name, p.product_name
from orders as o
join customer as c on o.customer_id = c.customer_id
join product as p on o.product_id = p.product_id
where c.customer_name = ?
and c.customer_password = ?
})
customerQuery = p.execute(name, password)
if customerQuery.num_rows > 0
customerQuery.each do |row|
#...
end
else
#...
end
If you absolutely must use string interpolation for some bizarre reason, then use connection.quote:
customerQuery = connection.query(%Q{
select o.order_id, o.date_ordered, c.customer_name, p.product_name
from orders as o
join customer as c on o.customer_id = c.customer_id
join product as p on o.product_id = p.product_id
where c.customer_name = '#{connection.quote(name)}'
and c.customer_password = '#{connection.quote(password)}'
})
But really, don't do this unless you have no other choice. And in this case, you don't have to use string manipulation for this.