diff --git a/frappe/database.py b/frappe/database.py index 00b85a2218..845829299d 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -104,6 +104,9 @@ class Database: # in transaction validations self.check_transaction_status(query) + # prevent multiple queries in one + self.prevent_multiple_queries(query) + # autocommit if auto_commit: self.commit() @@ -199,7 +202,7 @@ class Database: executed in one transaction. This is to ensure that writes are always flushed otherwise this could cause the system to hang.""" if self.transaction_writes and \ - query and query.strip().split()[0].lower() in ['start', 'alter', 'drop', 'create', "begin"]: + query and query.strip().split()[0].lower() in ['start', 'alter', 'drop', 'create', "begin", "truncate"]: raise Exception, 'This statement can cause implicit commit' if query and query.strip().lower() in ('commit', 'rollback'): @@ -213,6 +216,26 @@ class Database: else: frappe.throw(_("Too many writes in one request. Please send smaller requests"), frappe.ValidationError) + def prevent_multiple_queries(self, query): + if frappe.flags.in_install_db or frappe.flags.in_install: + return + + query_lower = query.lower().split(";") + + if len(query_lower) > 1: + for q in query_lower[1:]: + if q.strip().split()[0] in ( + "update", + "truncate", + "alter", + "drop", + "create", + "begin", + "start transaction", + "commit" + ): + frappe.throw(_("Cannot have more than one SQL statement in a query."), frappe.SQLError) + def fetch_as_dict(self, formatted=0, as_utf8=0): """Internal. Converts results to dict.""" result = self._cursor.fetchall() diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 3c03e08c02..744f93067a 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -23,3 +23,7 @@ class TestDB(unittest.TestCase): def test_escape(self): frappe.db.escape("香港濟生堂製藥有限公司 - IT".encode("utf-8")) + + def test_multiple_queries(self): + # implicit commit + self.assertRaises(frappe.SQLError, frappe.db.sql, """select name from `tabUser`; truncate `tabBulk Email`""")