<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/test/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skodak</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/test/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skodak"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/Special:Contributions/Skodak"/>
	<updated>2026-04-13T12:33:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Security&amp;diff=48082</id>
		<title>Security</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Security&amp;diff=48082"/>
		<updated>2008-12-11T20:01:14Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Firewalls */ rpd fix proposed by Vicente&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;All web application software is highly complex, and every application has security issues that are found from time to time, usually involving some combination of input that the programmers did not anticipate. The Moodle project takes security seriously, and is continuously improving Moodle to close such holes as we find them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
*This page contains important security measures for your Moodle installation.&lt;br /&gt;
*You should report security problems to the [http://tracker.moodle.org/secure/CreateIssue!default.jspa  Moodle tracker] (and mark it as a security issue!) so that developers can see it and inform  registered Moodle sites about fixes as soon as possible.&lt;br /&gt;
*You should not post actual exploits in the forums or elsewhere on the web (to protect Moodle admins who have not upgraded yet).&lt;br /&gt;
&lt;br /&gt;
==Simple security measures==&lt;br /&gt;
*The best security strategy is a good backup! But you don&#039;t have a good backup unless you are able to restore it. Test your restoration procedures!&lt;br /&gt;
*Load only software or services you will use&lt;br /&gt;
*Perform regular updates&lt;br /&gt;
*Model your security after the layers of clothing you wear on a cold winter day&lt;br /&gt;
&lt;br /&gt;
==Basic recommendations==&lt;br /&gt;
*Update Moodle regularly on each release&lt;br /&gt;
:Published security holes draw crackers attention after release. The older the version, the more vulnerabilities it is likely to contain.&lt;br /&gt;
*Disable register globals&lt;br /&gt;
:This will help prevent against possible XSS problems in third-party scripts.&lt;br /&gt;
*Use strong passwords for admin and teachers&lt;br /&gt;
:Choosing &amp;quot;difficult&amp;quot; passwords is a basic security practice to protect against &amp;quot;brute force&amp;quot; cracking of accounts.&lt;br /&gt;
*Only give teacher accounts to trusted users. Avoid creating public sandboxes with free teacher accounts on production servers.&lt;br /&gt;
:Teacher accounts have much freer permissions and it is easier to create situations where data can be abused or stolen.&lt;br /&gt;
*Separate your systems as much as possible&lt;br /&gt;
:Another basic security technique is to use different passwords on different systems, use different machines for different services and so on.  This will prevent damage being widespread even if one account or one server is compromised.&lt;br /&gt;
&lt;br /&gt;
==Run regular updates==&lt;br /&gt;
*Use auto update systems&lt;br /&gt;
*Windows Update &lt;br /&gt;
*Linux: up2date, yum, apt-get&lt;br /&gt;
:Consider automating updates with a script scheduled via cron &lt;br /&gt;
*Mac OSX update system&lt;br /&gt;
*Stay current with php, apache, and moodle&lt;br /&gt;
&lt;br /&gt;
==Use mailing lists to stay updated==&lt;br /&gt;
*CERT - http://www.us-cert.gov/cas/signup.html&lt;br /&gt;
*PHP - http://www.php.net/mailing-lists.php - sign up for Announcements list&lt;br /&gt;
*MySQL - http://lists.mysql.com - sign up for MySQL Announcements&lt;br /&gt;
&lt;br /&gt;
==Firewalls==&lt;br /&gt;
*Security experts recommend a dual firewall&lt;br /&gt;
:Differing hardware/software combinations &lt;br /&gt;
*Disabling unused services is often as effective as a firewall&lt;br /&gt;
:Use netstat -a to review open network ports&lt;br /&gt;
*Not a guarantee of protection&lt;br /&gt;
*Allow ports &lt;br /&gt;
:80, 443(ssl), and 9111 (for chat), &lt;br /&gt;
:Remote admin: ssh 22, or rdp 3389&lt;br /&gt;
&lt;br /&gt;
==Password policy==&lt;br /&gt;
&lt;br /&gt;
{{Moodle 1.9}}In Moodle 1.9 onwards, a password policy may be set up via &#039;&#039;Administration &amp;gt; Security &amp;gt; [[Site policies]]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
There is a check box to determine if password complexity should be enforced or not, the option to set the minimum length of the password, the minimum number of digits, the minimum number of lowercase characters, the minimum number of uppercase characters and the minimum number of non alphanumeric characters.&lt;br /&gt;
&lt;br /&gt;
If a user enters a password that does not meet those requirements, they are given an error message indicating the nature of the problem with the entered password.&lt;br /&gt;
&lt;br /&gt;
Enforcing password complexity along with requiring users to change their initial password go a long way in helping ensure that users choose and are in fact using &amp;quot;good passwords&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Be prepared for the worst==&lt;br /&gt;
*Have backups ready &lt;br /&gt;
*Practice recovery procedures ahead of time &lt;br /&gt;
*Use a rootkit detector on a regular basis &lt;br /&gt;
**Linux/MacOSX - http://www.chkrootkit.org/ &lt;br /&gt;
**Windows - http://www.sysinternals.com/Utilities/RootkitRevealer.html&lt;br /&gt;
&lt;br /&gt;
==Moodle security alerts==&lt;br /&gt;
*Register your site with Moodle.org&lt;br /&gt;
:Registered users receive email alerts&lt;br /&gt;
*Security alerts also posted online&lt;br /&gt;
*Web - http://moodle.org/security&lt;br /&gt;
*RSS feed - http://moodle.org/rss/file.php/1/1/forum/996/rss.xml&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous considerations==&lt;br /&gt;
These are all things you might consider that impact your overall security:&lt;br /&gt;
*Use the secure forms setting&lt;br /&gt;
*Set the mysql root user password&lt;br /&gt;
*Turn off mysql network access&lt;br /&gt;
*Use SSL, httpslogins=yes&lt;br /&gt;
*Use good passwords - set up a password policy in &#039;&#039;Administration &amp;gt; Security &amp;gt; [[Site policies]]&#039;&#039; (in Moodle 1.9 onwards)&lt;br /&gt;
*Do not enable the &#039;&#039;opentogoogle&#039;&#039; setting (in &#039;&#039;Administration &amp;gt; Security &amp;gt; [[Site policies]]&#039;&#039;)&lt;br /&gt;
*Disable guest access by hiding the guest login button (in &#039;&#039;Administration &amp;gt; Users &amp;gt; [[Authentication]]&#039;&#039;)&lt;br /&gt;
*Place enrollment keys on all courses&lt;br /&gt;
*Disable the enrolment key hint in the [[Internal enrolment]] settings (via &#039;&#039;Administration &amp;gt; Courses &amp;gt; [[Enrolment plugins|Enrolments]]&#039;&#039;) (in Moodle 1.9.3 onwards) or remove it by editing the enrolmentkeyhint string in &#039;&#039;moodle.php&#039;&#039; (via &#039;&#039;Administration &amp;gt; Language &amp;gt; [[Language editing]]&#039;&#039;) and changing&lt;br /&gt;
 That enrolment key was incorrect, please try again. (Here&#039;s a hint - it starts with &#039;$a&#039;)&lt;br /&gt;
:to&lt;br /&gt;
 That enrolment key was incorrect, please try again. Contact your instructor if you need assistance.&lt;br /&gt;
&lt;br /&gt;
==Most secure/paranoid file permissions==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: &amp;lt;u&amp;gt;The following information applies to Linux/Unix based installations only, as MS Windows permission system is quite different&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Depending on your server setup there are two different scenarios:&lt;br /&gt;
# You are running Moodle on your own dedicated server.&lt;br /&gt;
# You are running Moodle on a shared hosting environment.&lt;br /&gt;
&lt;br /&gt;
In the sections below, you are required to use the web service user account and group to set the permissions, so you need to know them. This can vary quite a bit from server to server but if this feature has not been disabled in your server, you can go to http://your.moodle.site/admin/phpinfo.php (logging in as admin), and then search for the line that reads &#039;User/Group&#039;, inside the &#039;apache&#039; table. For example, I get &#039;www-data&#039; for the user account and &#039;www-data&#039; for the group too.&lt;br /&gt;
&lt;br /&gt;
=== Running Moodle on a dedicated server ===&lt;br /&gt;
Assuming you are running Moodle on a sealed server (i.e. no user logins allowed on the machine) and that root takes care of the modifications to both moodle code and moodle config (config.php), then this are the most tight permissions I can think of:&lt;br /&gt;
&lt;br /&gt;
1. moodledata directory and all of its contents (and subdirectories, includes sessions):&lt;br /&gt;
 owner: apache user (apache, httpd, www-data, whatever; see above)&lt;br /&gt;
 group: apache group (apache, httpd, www-data, whatever; see above)&lt;br /&gt;
 permissions: 700 on directories, 600 on files&lt;br /&gt;
&lt;br /&gt;
2. moodle directory and all of its contents and subdirectories (including config.php):&lt;br /&gt;
 owner: root&lt;br /&gt;
 group: root&lt;br /&gt;
 permissions: 755 on directories, 644 on files.&lt;br /&gt;
&lt;br /&gt;
If you allow local logins for regular users, then 2. should be:&lt;br /&gt;
 owner: root&lt;br /&gt;
 group: apache group (apache, httpd, www-data, whatever; see above)&lt;br /&gt;
 permissions: 750 on directories, 640 on files.&lt;br /&gt;
&lt;br /&gt;
Think of these permissions as the most paranoid ones. You can be secure enough with less tighter permissions, both in moodledata and moodle directories (and subdirectories).&lt;br /&gt;
&lt;br /&gt;
=== Running Moodle on a shared hosting environment ===&lt;br /&gt;
If you are running Moodle on a shared hosting environment, then above permissions are probably wrong. If you set 700 as the permission for directories (and 600 for files), you are probably denying the web service user account access to your directories and files.&lt;br /&gt;
&lt;br /&gt;
If you want to tighten your permissions as much as possible, you will need to know:&lt;br /&gt;
&lt;br /&gt;
# the user account and the group the web service is running under (see above).&lt;br /&gt;
# the owner of the directories/files of both moodledata and the moodle directory (this should normally be your client user account), and the group of the directories/files. You can usually get this information from the file manager of your hosting control panel. Go to the moodle folder and pick any directory or file and try to view/change the permissions, owner and group of that file. That would normally show the current permissions, owner and group. Do the same for the moodledata directory.&lt;br /&gt;
&lt;br /&gt;
Then, depending on the following scenarios you should use a different set of permissions (listed from more secure to less secure) for your moodledata directory:&lt;br /&gt;
&lt;br /&gt;
# if the web service account and the owner of the directories/files is the same, you should use 700 for directories and 600 for files.&lt;br /&gt;
# if the web service group and the group of the directories/files is the same, you should use 770 for directories and 660 for the files.&lt;br /&gt;
# if none of the above, you will need to use 777 for directories and 666 for files, which is less secure but it is your only option. 707 and 606 would be more secure, but it might or might not work, depending on your particular setup.&lt;br /&gt;
&lt;br /&gt;
In fact, you just need to set moodledata the permissions specified above, as all the directories and files inside are created by the web service itself, and will have the right permissions.&lt;br /&gt;
&lt;br /&gt;
Regarding the moodle directory, as long as the web service user account can read the files plus read and execute the directories, that should be enough. There is no need to grant write permission to the web service account/group on any of the files or subdirectories. The only drawback is that you will need to create the config.php by hand during the installation process, as Moodle will not be able to create it. But that should not be a big problem.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
*[[Security FAQ]]&lt;br /&gt;
Using Moodle forum discussions:&lt;br /&gt;
*[http://moodle.org/mod/forum/discuss.php?d=39404 Guide to Securing your Moodle Server]&lt;br /&gt;
*[http://moodle.org/mod/forum/discuss.php?d=93561 How to secure Moodle website from hacking] including recommendations on emergency recovery&lt;br /&gt;
&lt;br /&gt;
[[Category:Security]]&lt;br /&gt;
&lt;br /&gt;
[[es:Seguridad]]&lt;br /&gt;
[[fr:Sécurité]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Gradebook_improvements&amp;diff=47865</id>
		<title>Development:Gradebook improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Gradebook_improvements&amp;diff=47865"/>
		<updated>2008-12-08T11:04:18Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Effectiveness of grading interface */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Same aspects of gradebook were not fully solved in 1.9.x, this page tries to summarize potential improvements&lt;br /&gt;
&lt;br /&gt;
==Aggregation of hidden grades==&lt;br /&gt;
Overlook problem partially solve after the database freeze - workaround was to recalculate the grades on the fly so that users that can the hidden grades are ignored. This approach is expensive and can not be used in conditional activities, grade exports, etc.&lt;br /&gt;
&lt;br /&gt;
Solution is to add new flag into grade categories - &#039;&#039;aggregate hidden grades&#039;&#039;. Having two values for each grade would be too complex, selective agrragation should solve most of the problems and should be reasonably backwards compatible.&lt;br /&gt;
&lt;br /&gt;
==Final grading in activities==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Effectiveness of grading interface==&lt;br /&gt;
&lt;br /&gt;
==Tracking of submission dates==&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Gradebook_improvements&amp;diff=47859</id>
		<title>Development:Gradebook improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Gradebook_improvements&amp;diff=47859"/>
		<updated>2008-12-08T09:56:27Z</updated>

		<summary type="html">&lt;p&gt;Skodak: New page: Same aspects of gradebook were not fully solved in 1.9.x, this page tries to summarize potential improvements  ==Aggregation of hidden grades== Overlook problem partially solve after the d...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Same aspects of gradebook were not fully solved in 1.9.x, this page tries to summarize potential improvements&lt;br /&gt;
&lt;br /&gt;
==Aggregation of hidden grades==&lt;br /&gt;
Overlook problem partially solve after the database freeze - workaround was to recalculate the grades on the fly so that users that can the hidden grades are ignored. This approach is expensive and can not be used in conditional activities, grade exports, etc.&lt;br /&gt;
&lt;br /&gt;
Solution is to add new flag into grade categories - &#039;&#039;aggregate hidden grades&#039;&#039;. Having two values for each grade would be too complex, selective agrragation should solve most of the problems and should be reasonably backwards compatible.&lt;br /&gt;
&lt;br /&gt;
==Final grading in activities==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Effectiveness of grading interface==&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Capabilities/moodle/user:viewuseractivitiesreport&amp;diff=47471</id>
		<title>Capabilities/moodle/user:viewuseractivitiesreport</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Capabilities/moodle/user:viewuseractivitiesreport&amp;diff=47471"/>
		<updated>2008-12-01T19:22:50Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*This allows a user to view this user&#039;s activity reports and grades (user context only)&lt;br /&gt;
&lt;br /&gt;
====Legacy Role Default Settings====&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! Legacy Role !! Inherit !! Allow !! Prevent !! Prohibit&lt;br /&gt;
|-&lt;br /&gt;
| Administrator || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Course Creator || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Teacher || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Non-editing Teacher || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Student || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Guest || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Authenticated User || X || - || - || -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: originally there were some defaults for legacy roles, but they were removed because this capability can be used only in user or system context.&lt;br /&gt;
&lt;br /&gt;
==Example usage==&lt;br /&gt;
&lt;br /&gt;
*[[Parent role]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Capabilities|User]]&lt;br /&gt;
&lt;br /&gt;
[[eu:Gaitasunak/moodle/user:viewuseractivitiesreport]]&lt;br /&gt;
[[fr:Capabilities/moodle/user:viewuseractivitiesreport]]&lt;br /&gt;
[[ja:ケイパビリティ/moodle/user:viewuseractivitiesreport]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Capabilities/moodle/user:viewuseractivitiesreport&amp;diff=47470</id>
		<title>Capabilities/moodle/user:viewuseractivitiesreport</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Capabilities/moodle/user:viewuseractivitiesreport&amp;diff=47470"/>
		<updated>2008-12-01T19:22:16Z</updated>

		<summary type="html">&lt;p&gt;Skodak: fixed definition and added explanation why defaults do not make sense see MDL-17485&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*This allows a user to view this user&#039;s activity reports and grades (user context only)&lt;br /&gt;
&lt;br /&gt;
====Legacy Role Default Settings====&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! Legacy Role !! Inherit !! Allow !! Prevent !! Prohibit&lt;br /&gt;
|-&lt;br /&gt;
| Administrator || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Course Creator || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Teacher || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Non-editing Teacher || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Student || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Guest || X || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Authenticated User || X || - || - || -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: originally there were some defaults for legacy roles, but they were removed because this capability can be used only in user context.&lt;br /&gt;
&lt;br /&gt;
==Example usage==&lt;br /&gt;
&lt;br /&gt;
*[[Parent role]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Capabilities|User]]&lt;br /&gt;
&lt;br /&gt;
[[eu:Gaitasunak/moodle/user:viewuseractivitiesreport]]&lt;br /&gt;
[[fr:Capabilities/moodle/user:viewuseractivitiesreport]]&lt;br /&gt;
[[ja:ケイパビリティ/moodle/user:viewuseractivitiesreport]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Coding&amp;diff=47323</id>
		<title>Development:Coding</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Coding&amp;diff=47323"/>
		<updated>2008-11-27T22:38:34Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* General rules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Any collaborative project needs consistency and stability to stay strong.&lt;br /&gt;
&lt;br /&gt;
These &#039;&#039;&#039;coding guidelines&#039;&#039;&#039; are to provide a goal for all Moodle code to strive to. It&#039;s true that some of the older existing code falls short in a few areas, but it will all be fixed eventually. All new code definitely must adhere to these standards as closely as possible.&lt;br /&gt;
&lt;br /&gt;
==General rules==&lt;br /&gt;
&lt;br /&gt;
# All &#039;&#039;&#039;code&#039;&#039;&#039; files should use the &#039;&#039;&#039;.php&#039;&#039;&#039; extension.&lt;br /&gt;
# All &#039;&#039;&#039;template&#039;&#039;&#039; files should use the &#039;&#039;&#039;.html&#039;&#039;&#039; extension.&lt;br /&gt;
# All text files should use &#039;&#039;&#039;Unix-style text format&#039;&#039;&#039; (most text editors have this as an option).&lt;br /&gt;
# All php tags must be &#039;full&#039; tags like &#039;&#039;&#039;&amp;lt;?php ?&amp;gt;&#039;&#039;&#039; ... not &#039;short&#039; tags like &amp;lt;? ?&amp;gt;.&lt;br /&gt;
# All existing &#039;&#039;&#039;copyright notices must be retained&#039;&#039;&#039;. You can add your own if necessary.&lt;br /&gt;
# Each file should &#039;&#039;&#039;include (require_once) the main config.php&#039;&#039;&#039; file.&lt;br /&gt;
# Any &#039;&#039;&#039;other include/require should use an absolute path&#039;&#039;&#039; beginning with $CFG-&amp;gt;dirroot or  $CFG-&amp;gt;libdir, not relative includes, which [http://uk.php.net/manual/en/function.include.php sometimes behave strangely under PHP].&lt;br /&gt;
# Includes should be done at the top of files or inside functions/methods, do not include/require in the middle of file in global scope&lt;br /&gt;
# Each file should &#039;&#039;&#039;check that the user is authenticated correctly&#039;&#039;&#039;, using require_login() and has_capability() or require_capability().&lt;br /&gt;
# All &#039;&#039;&#039;access to databases should use the functions in &#039;&#039;lib/dmllib.php&#039;&#039;&#039;&#039;&#039; whenever possible - this allows compatibility across a wide range of databases. You should find that almost anything is possible using these functions. If you must write SQL code then make sure it is: cross-platform; restricted to specific functions within your code (usually a lib.php file); and clearly marked.&lt;br /&gt;
# &#039;&#039;&#039;Don&#039;t create new global variables&#039;&#039;&#039;. Use only the Moodle-standard $CFG, $SESSION, $THEME, $SITE, $COURSE and $USER global variables.&lt;br /&gt;
# &#039;&#039;&#039;All variables should be initialised&#039;&#039;&#039; or at least tested for existence using isset() or empty() before they are used.&lt;br /&gt;
# &#039;&#039;&#039;All strings should be translatable&#039;&#039;&#039; - create new texts in the &amp;quot;lang/en_utf8&amp;quot; files with concise English lowercase names and retrieve them from your code using get_string() or print_string(). Never delete strings to ensure backwards compatibility of the language packs is maintained.&lt;br /&gt;
# &#039;&#039;&#039;Don&#039;t use p() and s() functions&#039;&#039;&#039; to print language strings. Those functions are not designed to print html with tags. Use echo() instead.&lt;br /&gt;
# All &#039;&#039;&#039;errors should be printed using print_error()&#039;&#039;&#039; to maximise translation and help for users (it automatically links to the docs wiki).&lt;br /&gt;
# All &#039;&#039;&#039;help files should be translatable&#039;&#039;&#039; - create new texts in the &amp;quot;lang/en_utf8/help&amp;quot; directory and call them using helpbutton(). If you need to update a help file:&lt;br /&gt;
#* with a minor change, where an old translation of the file would still make sense, then it&#039;s OK to make the change but you should notify translation AT moodle DOT org.&lt;br /&gt;
#* for a major change you should create a new file by adding an incrementing number (eg filename2.html) so that translators can easily see it&#039;s a new version of the file. Obviously the new code and the help index files should also be modified to point to the newest versions.&lt;br /&gt;
# Incoming data from the browser (sent via &#039;&#039;&#039;GET or POST) automatically has magic_quotes applied&#039;&#039;&#039; (regardless of the PHP settings) so that you can safely insert it straight into the database. &#039;&#039;&#039;All other raw data (from files, or from databases) must be escaped with addslashes()&#039;&#039;&#039; before inserting it into the database. Because this is so often done incorrectly, there is more explanation on this issue of adding and stripping slashes on a [[Developer:Slashes|separate page]].&lt;br /&gt;
# VERY IMPORTANT: Within Moodle, &#039;&#039;&#039;All texts should be printed using the format_text() function&#039;&#039;&#039;, especially those that have come from users. This ensures that text is filtered and cleaned correctly. More information can be found on the page about [[Development:Output_functions|output functions]].&lt;br /&gt;
# User actions should be logged using the [[Development:Logs|add_to_log()]] function. These logs are used for [[Settings#Show_activity_reports|activity reports]] and [[Logs]].&lt;br /&gt;
# &#039;&#039;&#039;Always create HTML links relative to the full site root&#039;&#039;&#039;, i.e. link to  &#039;&#039;$CFG-&amp;gt;wwwroot/mod/blonk/view.php?id=99&#039;&#039; rather than just &#039;&#039;view.php?id=99&#039;&#039;. This means that your code will work if called by a script in another folder, among other things.&lt;br /&gt;
# Modules should &#039;&#039;&#039;store config variables using &#039;&#039;set_config(&#039;varname&#039;, $value, &#039;mod/modulename&#039;)&#039;&#039;&#039;&#039;&#039; where the last parameter is the path to the module directory.&lt;br /&gt;
# &#039;&#039;&#039;Respect decimal separators specified&#039;&#039;&#039; in language pack - do not use number_format() directly, instead use format_float() and unformat_float() when displaying or processing floating point numbers (mandatory in 2.0)&lt;br /&gt;
&lt;br /&gt;
==Coding style==&lt;br /&gt;
&lt;br /&gt;
I know it can be a little annoying to change your style if you&#039;re used to something else, but balance that annoyance against the annoyance of all the people trying later on to make sense of Moodle code with mixed styles. There are obviously many good points for and against any style that people use, but the current style just is, so please stick to it.&lt;br /&gt;
&lt;br /&gt;
1. Indenting should be consistently 4 spaces. Don&#039;t use tabs AT ALL.&lt;br /&gt;
&lt;br /&gt;
2. Variable names should always be easy-to-read, meaningful lowercase English words. If you really need more than one word then run them together, but keep them short as possible. Use plural names for arrays of objects.&lt;br /&gt;
&lt;br /&gt;
      GOOD: $quiz&lt;br /&gt;
      GOOD: $errorstring&lt;br /&gt;
      GOOD: $assignments (for an array of objects)&lt;br /&gt;
      GOOD: $i (but only in little loops)&lt;br /&gt;
&lt;br /&gt;
      BAD: $Quiz&lt;br /&gt;
      BAD: $aReallyLongVariableNameWithoutAGoodReason&lt;br /&gt;
      BAD: $error_string&lt;br /&gt;
&lt;br /&gt;
3. Constants should always be in upper case, and always start with the name of the module. They should have words separated by underscores.&lt;br /&gt;
&lt;br /&gt;
      define(&amp;quot;FORUM_MODE_FLATOLDEST&amp;quot;, 1);&lt;br /&gt;
4. Function names should be simple English lowercase words, and start with the name of the module to avoid conflicts between modules. Words should be separated by underscores. Parameters should always have sensible defaults if possible. Note there is no space between the function name and the following (brackets).&lt;br /&gt;
&lt;br /&gt;
      function forum_set_display_mode($mode=0) {&lt;br /&gt;
          global $USER, $CFG;&lt;br /&gt;
          &lt;br /&gt;
          if ($mode) {&lt;br /&gt;
              $USER-&amp;gt;mode = $mode;&lt;br /&gt;
          } else if (empty($USER-&amp;gt;mode)) {&lt;br /&gt;
              $USER-&amp;gt;mode = $CFG-&amp;gt;forum_displaymode;&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
The same applies to naming classes and their methods. Use lowercase words separated by underscores.&lt;br /&gt;
&lt;br /&gt;
      class some_custom_class {&lt;br /&gt;
          function class_method() {&lt;br /&gt;
              ...&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
Note there are some exceptions in the code using camelcase: class SomeCustomClass {function classMethod(){...}}, but these are usually there because of compatibility with thirds party libraries (e.g. formslib).&lt;br /&gt;
&lt;br /&gt;
5. Blocks must always be enclosed in curly braces (even if there is only one line). Moodle uses this style:&lt;br /&gt;
&lt;br /&gt;
      if ($quiz-&amp;gt;attempts) {&lt;br /&gt;
          if ($numattempts &amp;gt; $quiz-&amp;gt;attempts) {&lt;br /&gt;
              error($strtoomanyattempts, &amp;quot;view.php?id=$cm-&amp;gt;id&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
6. Strings should be defined using single quotes where possible, so that [http://php.net/types.string less memory is used].&lt;br /&gt;
&lt;br /&gt;
      $var = &#039;some text without any variables&#039;;&lt;br /&gt;
      $var = &#039;with special characters like a new line &#039;.&amp;quot;\n&amp;quot;;&lt;br /&gt;
      $var = &#039;a very, very long string with a &#039;.$single.&#039; variable in it&#039;;&lt;br /&gt;
      $var = &amp;quot;some $text with $many variables $within it&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
7. Comments should be added as much as is practical, to explain the code flow and the purpose of functions and variables.&lt;br /&gt;
&lt;br /&gt;
* Every function (and class) should use the popular [http://www.phpdoc.org/ phpDoc format]. This allows code documentation to be generated automatically.&lt;br /&gt;
* Inline comments should use the // style, laid out neatly so that it fits among the code and lines up with it.&lt;br /&gt;
&lt;br /&gt;
      /**&lt;br /&gt;
      * The description should be first, with asterisks laid out exactly&lt;br /&gt;
      * like this example. If you want to refer to a another function,&lt;br /&gt;
      * do it like this: {@link clean_param()}. Then, add descriptions&lt;br /&gt;
      * for each parameter as follows.&lt;br /&gt;
      *&lt;br /&gt;
      * @param int $postid The PHP type is followed by the variable name&lt;br /&gt;
      * @param array $scale The PHP type is followed by the variable name&lt;br /&gt;
      * @param array $ratings The PHP type is followed by the variable name&lt;br /&gt;
      * @return mixed&lt;br /&gt;
      */&lt;br /&gt;
      function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {&lt;br /&gt;
          if (!$ratings) {&lt;br /&gt;
              $ratings = array();     // Initialize the empty array&lt;br /&gt;
              if ($rates = get_records(&amp;quot;forum_ratings&amp;quot;, &amp;quot;post&amp;quot;, $postid)) {&lt;br /&gt;
                  // Process each rating in turn&lt;br /&gt;
                  foreach ($rates as $rate) {&lt;br /&gt;
      ....etc&lt;br /&gt;
&lt;br /&gt;
8. Space should be used liberally - don&#039;t be afraid to spread things out a little to gain some clarity. Generally, there should be one space between brackets and normal statements, but no space between brackets and variables or functions:&lt;br /&gt;
&lt;br /&gt;
      foreach ($objects as $key =&amp;gt; $thing) {&lt;br /&gt;
          process($thing);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      if ($x == $y) {&lt;br /&gt;
          $a = $b;&lt;br /&gt;
      } else if ($x == $z) {&lt;br /&gt;
          $a = $c;&lt;br /&gt;
      } else {&lt;br /&gt;
          $a = $d;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
9. When making a COPY of an object, always use the php5 clone() function (otherwise you may end up with just a reference to the first object).  Moodle will make sure this works consistently on php4 too.&lt;br /&gt;
&lt;br /&gt;
      BAD:   $b = $a;&lt;br /&gt;
      GOOD:  $b = clone($a);&lt;br /&gt;
&lt;br /&gt;
If the thing you want to copy is not an object, but may contain objects (eg an array of objects) then use fullclone() instead.&lt;br /&gt;
&lt;br /&gt;
==Database structures==&lt;br /&gt;
&lt;br /&gt;
To help you create tables that meet these guidelines, we recommend you use the built in [[Development:XMLDB_defining_an_XML_structure#The_XMLDB_editor|database definition (XMLDB) editor]].&lt;br /&gt;
&lt;br /&gt;
# Every table must have an auto-incrementing id field (INT10) as primary index. (see [[IdColumnReasons]])&lt;br /&gt;
# The main table containing instances of each module must have the same name as the module (eg widget) and contain the following minimum fields:&lt;br /&gt;
#* id - as described above&lt;br /&gt;
#* course - the id of the course that each instance belongs to&lt;br /&gt;
#* name - the full name of each instance of the module&lt;br /&gt;
# Other tables associated with a module that contain information about &#039;things&#039; should be named widget_things (note the plural).&lt;br /&gt;
# Table and column names should avoid using [[Database reserved words|reserved words in any database]]. Please check them before creation. Table names may be up to 28 characters long, and Column names up to 30 characters.&lt;br /&gt;
# Column names should be always lowercase, simple and short, following the same rules as for variable names.&lt;br /&gt;
# Where possible, columns that contain a reference to the id field of another table (eg widget) should be called widgetid. (Note that this convention is newish and not followed in some older tables)&lt;br /&gt;
# Boolean fields should be implemented as small integer fields (eg INT4) containing 0 or 1, to allow for later expansion of values if necessary.&lt;br /&gt;
# Most tables should have a timemodified field (INT10) which is updated with a current timestamp obtained with the PHP time() function.&lt;br /&gt;
# Always define a default value for each field (and make it sensible)&lt;br /&gt;
# Each table name should start with the database prefix ($CFG-&amp;gt;prefix). In a lot of cases, this is taken care of for you automatically. Also, under Postgres, the name of every index must start with the prefix too.&lt;br /&gt;
# In order to guarantee [[Development:XMLDB problems#Table and column aliases - the AS keyword|cross-db compatibility]] follow these simple rules about the use of the &#039;&#039;&#039;AS&#039;&#039;&#039; keyword (only if you need table/colum aliases, of course):&lt;br /&gt;
#* &#039;&#039;&#039;Don&#039;t use&#039;&#039;&#039; the &#039;&#039;&#039;AS&#039;&#039;&#039; keyword for &#039;&#039;&#039;table aliases&#039;&#039;&#039;.&lt;br /&gt;
#* &#039;&#039;&#039;Do use&#039;&#039;&#039; the &#039;&#039;&#039;AS&#039;&#039;&#039; keyword for &#039;&#039;&#039;column aliases&#039;&#039;&#039;.&lt;br /&gt;
# &#039;&#039;&#039;Never&#039;&#039;&#039; create UNIQUE KEYs (constraints) at all. Instead use UNIQUE INDEXes. In the future, if we decide to add referential integrity to Moodle and we need UNIQUE KEYs they will be used, but not now. Please note that the XMLDB editor allows you to specify both XMLDB-only UNIQUE and FOREIGN constraints (and that&#039;s good, in order to have the XML well defined) but only underlying INDEXes will be generated. &lt;br /&gt;
# Those XMLDB-only UNIQUE KEYs (read previous point) only must be defined if such field/fields &#039;&#039;&#039;are going to be the target&#039;&#039;&#039; for some (XMLDB-only too) FOREIGN KEY. Else, create them as simple UNIQUE INDEXes.&lt;br /&gt;
# Tables associated &#039;&#039;&#039;with one block&#039;&#039;&#039; must follow this convention with their names: &#039;&#039;&#039;$CFG-&amp;gt;prefix + &amp;quot;block_&amp;quot; + name_of_the_block + anything_else&#039;&#039;&#039;. For example, assuming that $CFG-&amp;gt;prefix is &#039;mdl_&#039;, all the tables for the block &amp;quot;rss_client&amp;quot; must start by &#039;mdl_block_rss_client&#039; (being possible to add more words at the end, i.e. &#039;mdl_block_rss_client_anothertable&#039;...). This rule will be 100% enforced with Moodle 2.0, giving time to developers until then. See [http://tracker.moodle.org/browse/MDL-6786 Task 6786] for more info about this.&lt;br /&gt;
# &#039;&#039;&#039;Never&#039;&#039;&#039; make database changes in the STABLE branches.  If we did, then users upgrading from one stable version to the next would have duplicate changes occurring, which may cause serious errors.&lt;br /&gt;
# When refering to integer variable in SQL queries, do not surround the value in quotes. For example, get_records_select(&#039;question&#039;, &amp;quot;category=$catid&amp;quot;) is right. get_records_select(&#039;question&#039;, &amp;quot;category=&#039;$catid&#039;&amp;quot;) is wrong. It hides bugs where $catid is undefined. ([http://moodle.org/mod/forum/discuss.php?d=80629 This thread explains].)&lt;br /&gt;
&lt;br /&gt;
==Security issues (and handling form and URL data)==&lt;br /&gt;
&lt;br /&gt;
# Do not rely on &#039;register_globals&#039;. Every variable must be properly initialised in every code file. It must be obvious where the variable came from.&lt;br /&gt;
# Initialise all arrays and objects, even if empty. $a = array() or $obj = new stdClass();.&lt;br /&gt;
# Do not use the optional_variable() function (this function is now deprecated). Use the optional_param() function instead. Pick the correct PARAM_XXXX value for the data type you expect.&lt;br /&gt;
# Do not use the require_variable() function (this function is now deprecated). Use the required_param() function instead. Pick the correct PARAM_XXXX value for the data type you expect.&lt;br /&gt;
# Use data_submitted(), with care. Data must still be cleaned before use.&lt;br /&gt;
# Do not use $_GET, $_POST or $_REQUEST. Use the appropriate required_param() or optional_param() appropriate to your need.&lt;br /&gt;
# Do not check for an action using something like if (isset($_GET[&#039;something&#039;])). Use, e.g., $something = optional_param( &#039;something&#039;,-1,PARAM_INT ) and then perform proper test for it being in its expected range of values e.g., if ($something&amp;gt;=0) {....&lt;br /&gt;
# Wherever possible group all your required_param(), optional_param() and other variables initialisation at the beginning of each file to make them easy to find.&lt;br /&gt;
# Use &#039;sesskey&#039; mechanism to protect form handling routines from attack. Basic example of use: when form is generated, include &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;sesskey&amp;quot; value=&amp;quot;&amp;lt;?php echo sesskey(); ?&amp;gt;&amp;quot; /&amp;gt;. When you process the form check with if (!confirm_sesskey()) { print_error(&#039;confirmsesskeybad&#039;);}.&lt;br /&gt;
# All filenames must be &#039;cleaned&#039; using the clean_filename() function, if this has not been done already by appropriate use of required_param() or optional_param()&lt;br /&gt;
# Any data read from the database must have [[Developer:Slashes|addslashes()]] applied to it before it can be written back. A whole object of data can be hit at once with addslashes_object().&lt;br /&gt;
# addslashes_js() must be used for escaping of javascript strings&lt;br /&gt;
# Wherever possible, data to be stored in the database must come from POST data (from a form with method=&amp;quot;POST&amp;quot;) as opposed to GET data (ie, data from the URL line).&lt;br /&gt;
# Do not use data from $_SERVER if you can avoid it. This has portability issues.&lt;br /&gt;
# If it hasn&#039;t been done somewhere else, make sure all data written to the database has been through the clean_param() function using the appropriate PARAM_XXXX for the datatype.&lt;br /&gt;
# If you write custom SQL code, make very sure it is correct. In particular watch out for missing quotes around values. Possible SQL &#039;injection&#039; exploit.&lt;br /&gt;
# Check all data (particularly that written to the database) in every file it is used. Do not expect or rely on it being done somewhere else.&lt;br /&gt;
# Blocks of code to be included should contain a definite PHP structure (e.g, a class declaration, function definition(s) etc.) - straight blocks of code promote uninitialised variable usage.&lt;br /&gt;
# If you need to use shell_exec() (or any other shell invoking function), make sure you clean parameters first with escapeshellcmd()/escapeshellarg (otherwise, we open up for shell injection attacks).&lt;br /&gt;
&lt;br /&gt;
==Use of JavaScript within Moodle==&lt;br /&gt;
&lt;br /&gt;
On a separate page, see [[Development:JavaScript guidelines]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer|Coding]]&lt;br /&gt;
&lt;br /&gt;
[[es:Manual de Estilo de Código]]&lt;br /&gt;
[[ja:コーディング]]&lt;br /&gt;
[[zh:代码指南]]&lt;br /&gt;
[[pl:Kodowanie]]&lt;br /&gt;
[[pt:manual_de_codigo]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47319</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47319"/>
		<updated>2008-11-27T18:26:02Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* The tin changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally DML functions were returning &#039;&#039;false&#039;&#039; if error occurred - &#039;&#039;dml_exception&#039;&#039; is thrown now instead.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
if (!$id = insert_record(&#039;sometable&#039;, $record)) {&lt;br /&gt;
   error(&#039;can not insert new record&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
$id = $DB-&amp;gt;insert_record(&#039;sometable&#039;, $record);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47317</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47317"/>
		<updated>2008-11-27T18:11:33Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* The tin changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally DML functions were returning &#039;&#039;false&#039;&#039; if error occurred - exceptions are thrown now instead.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
if (!$id = insert_record(&#039;sometable&#039;, $record)) {&lt;br /&gt;
   error(&#039;can not insert new record&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
$id = $DB-&amp;gt;insert_record(&#039;sometable&#039;, $record);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47316</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47316"/>
		<updated>2008-11-27T18:11:05Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* The tin changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally DML functions were returning &#039;&#039;false&#039;&#039; if error occurred - exceptions are thrown now instead.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
if (!$id = insert_record(&#039;sometable&#039;, $record)) {&lt;br /&gt;
   error(&#039;can not insert new reocrd&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
$id = $DB-&amp;gt;insert_record(&#039;sometable&#039;, $record);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47315</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47315"/>
		<updated>2008-11-27T18:06:33Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* The tin changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally DML functions were returning &#039;&#039;false&#039;&#039; if error occurred - exceptions are thrown now instead.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
if (!$id = insert_record(&#039;sometable&#039;, $record)) {&lt;br /&gt;
   error(&#039;can not insert new reocrd&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
$id = insert_record(&#039;sometable&#039;, $record);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47314</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47314"/>
		<updated>2008-11-27T17:58:14Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47313</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47313"/>
		<updated>2008-11-27T17:55:04Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* The golden changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47312</id>
		<title>Development:DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DB_layer_2.0_migration_docs&amp;diff=47312"/>
		<updated>2008-11-27T17:45:42Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[Development:XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[Development:XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[Development:dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the XMLDB Editor (Admin-&amp;gt;Misc-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!).&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All XMLDBTable instances in your upgrade code must be replaced by xmldb_table (parameters are the same, no change with them required)&lt;br /&gt;
* All XMLDBField instances in your upgrade code must be replaced by xmldb_field (no change in parameters)&lt;br /&gt;
* All XMLDBIndex instances in your upgrade code must be replaced by xmldb_index (no change in parameters)&lt;br /&gt;
* All XMLDBKey instances in your upgrade code must be replaced by xmldb_key (no change in parameters)&lt;br /&gt;
* All the addFieldInfo() methods must be replaced by add_field() (no change in parameters)&lt;br /&gt;
* All the addIndexInfo() methods must be replaced by add_index() (no change in parameters)&lt;br /&gt;
* All the addKeyInfo() methods must be replaced by add_key() (no change in parameters)&lt;br /&gt;
* All the setAttributes() methods must be replaced by set_attributes() (no change in parameters)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
    table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
    field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
    index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
    find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
    find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name&lt;br /&gt;
    check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists&lt;br /&gt;
    find_sequence_name ==&amp;gt; $dbman-&amp;gt;find_sequence_name&lt;br /&gt;
    create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
    drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
    rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
    add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
    drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
    rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
    change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
    change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
    change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
    change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
    change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum&lt;br /&gt;
    change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
    add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
    drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
    add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
    drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded ONLY from Moodle 1.9, so any previous upgrade code can be safely deleted. Moodle 2.0 requires Moodle 1.9 to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the XMLDB Editor and to core modules to see how upgrade.php files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into two sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere).&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
        WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
        FROM {grade_items}&lt;br /&gt;
        WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[Development:DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[Development:DDL exceptions|DDL functions]] - DDL exceptions information.&lt;br /&gt;
* [[Development:DML exceptions|DML functions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=File:Ddl_exceptions.png&amp;diff=47311</id>
		<title>File:Ddl exceptions.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=File:Ddl_exceptions.png&amp;diff=47311"/>
		<updated>2008-11-27T17:33:15Z</updated>

		<summary type="html">&lt;p&gt;Skodak: Hierarchy of DDL exceptions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hierarchy of DDL exceptions&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DDL_exceptions&amp;diff=47310</id>
		<title>Development:DDL exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DDL_exceptions&amp;diff=47310"/>
		<updated>2008-11-27T17:32:57Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems during upgrade were ignored by default.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[Image:Ddl_exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
Defined in lib/ddllib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for DDL related exceptions&lt;br /&gt;
&lt;br /&gt;
===ddl_table_missing_exception===&lt;br /&gt;
Table specified in function parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
===ddl_field_missing_exception===&lt;br /&gt;
Field specified in function parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
===ddl_change_structure_exception===&lt;br /&gt;
General exception thrown during execution of sql that changes database structure.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DDL_exceptions&amp;diff=47309</id>
		<title>Development:DDL exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DDL_exceptions&amp;diff=47309"/>
		<updated>2008-11-27T17:32:30Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems during upgrade were ignored by default.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[Image:Ddl_exceptions]]&lt;br /&gt;
&lt;br /&gt;
Defined in lib/ddllib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for DDL related exceptions&lt;br /&gt;
&lt;br /&gt;
===ddl_table_missing_exception===&lt;br /&gt;
Table specified in function parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
===ddl_field_missing_exception===&lt;br /&gt;
Field specified in function parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
===ddl_change_structure_exception===&lt;br /&gt;
General exception thrown during execution of sql that changes database structure.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47308</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47308"/>
		<updated>2008-11-27T17:23:19Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[Image:Dml_exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
Defined in lib/dmllib.php for now.&lt;br /&gt;
&lt;br /&gt;
===dml_connection_exception===&lt;br /&gt;
Thrown when can not connect to database for any reason.&lt;br /&gt;
&lt;br /&gt;
===dml_read_exception===&lt;br /&gt;
Problem occurred during reading from database. Originally indicated be returning &#039;&#039;false&#039;&#039; - this value was often confused with &#039;&#039;false&#039;&#039; return value meaning &#039;&#039;not found&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===dml_read_exception===&lt;br /&gt;
Problem occurred during writing to database. Originally indicated be returning &#039;&#039;false&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47307</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47307"/>
		<updated>2008-11-27T17:21:59Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[Image:Dml_exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
===dml_connection_exception===&lt;br /&gt;
Thrown when can not connect to database for any reason.&lt;br /&gt;
&lt;br /&gt;
===dml_read_exception===&lt;br /&gt;
Problem occurred during reading from database. Originally indicated be returning &#039;&#039;false&#039;&#039; - this value was often confused with &#039;&#039;false&#039;&#039; return value meaning &#039;&#039;not found&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===dml_read_exception===&lt;br /&gt;
Problem occurred during writing to database. Originally indicated be returning &#039;&#039;false&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47306</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47306"/>
		<updated>2008-11-27T17:18:26Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[Image:Dml_exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
===connection_exception===&lt;br /&gt;
&lt;br /&gt;
===dml_read_exception===&lt;br /&gt;
&lt;br /&gt;
===dml_read_exception===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=File:Dml_exceptions.png&amp;diff=47305</id>
		<title>File:Dml exceptions.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=File:Dml_exceptions.png&amp;diff=47305"/>
		<updated>2008-11-27T17:17:34Z</updated>

		<summary type="html">&lt;p&gt;Skodak: Hierarchy of DML exceptions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hierarchy of DML exceptions&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47304</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47304"/>
		<updated>2008-11-27T17:17:12Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[Image:Dml_exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47303</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47303"/>
		<updated>2008-11-27T17:17:03Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
[[[Image:Dml_exceptions.png]]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47302</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47302"/>
		<updated>2008-11-27T17:03:34Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
===moodle_exception===&lt;br /&gt;
Unknown type of problem, also used by print_error() and error() functions. Please try to find some more suitable exception type if possible.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===coding_exception===&lt;br /&gt;
General exception indicating incorrect use of function, bogus parameters, etc. Most probably a typo or developer did not understand the inline docs. Use especially in library functions when you think that the developer should be notified. The hint in constructor is not expected to be localised.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during manipulation of database structure. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===dml_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during normal database access. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===file_exception===&lt;br /&gt;
Base class for file storage related problems.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;br /&gt;
* [[Development:File storage exceptions|File exceptions]]: Use of exceptions in file storage layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47301</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47301"/>
		<updated>2008-11-27T17:02:13Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* coding_exception */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
===moodle_exception===&lt;br /&gt;
Unknown type of problem, also used by print_error() and error() functions. Please try to find some more suitable exception type if possible.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===coding_exception===&lt;br /&gt;
General exception indicating incorrect use of function, bogus parameters, etc. Most probably a typo or developer did not understand the inline docs. Use especially in library functions when you think that the developer should be notified. The hint in constructor is not expected to be localised.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during manipulation of database structure. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===dml_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during normal database access. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===file_exception===&lt;br /&gt;
Base class for file storage related problems.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47300</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47300"/>
		<updated>2008-11-27T16:58:30Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* moodle_exception */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
===moodle_exception===&lt;br /&gt;
Unknown type of problem, also used by print_error() and error() functions. Please try to find some more suitable exception type if possible.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===coding_exception===&lt;br /&gt;
General exception indicating incorrect use of function, bogus parameters, etc. Most probably a typo or developer did not understand the inline docs.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during manipulation of database structure. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===dml_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during normal database access. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===file_exception===&lt;br /&gt;
Base class for file storage related problems.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47299</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47299"/>
		<updated>2008-11-27T16:58:10Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* moodle_exception */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
===moodle_exception===&lt;br /&gt;
Unknown type of problem, also used by print_error() and error() functions. Please try to find some more suitable exception type if possible.&lt;br /&gt;
&lt;br /&gt;
===coding_exception===&lt;br /&gt;
General exception indicating incorrect use of function, bogus parameters, etc. Most probably a typo or developer did not understand the inline docs.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during manipulation of database structure. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===dml_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during normal database access. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===file_exception===&lt;br /&gt;
Base class for file storage related problems.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47298</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47298"/>
		<updated>2008-11-27T16:57:58Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* =coding_exception */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
==moodle_exception==&lt;br /&gt;
Unknown type of problem, also used by print_error() and error() functions. Please try to find some more suitable exception type if possible.&lt;br /&gt;
&lt;br /&gt;
===coding_exception===&lt;br /&gt;
General exception indicating incorrect use of function, bogus parameters, etc. Most probably a typo or developer did not understand the inline docs.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during manipulation of database structure. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===dml_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during normal database access. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===file_exception===&lt;br /&gt;
Base class for file storage related problems.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47297</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47297"/>
		<updated>2008-11-27T16:57:44Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Exception hierarchy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
==moodle_exception==&lt;br /&gt;
Unknown type of problem, also used by print_error() and error() functions. Please try to find some more suitable exception type if possible.&lt;br /&gt;
&lt;br /&gt;
===coding_exception==&lt;br /&gt;
General exception indicating incorrect use of function, bogus parameters, etc. Most probably a typo or developer did not understand the inline docs.&lt;br /&gt;
&lt;br /&gt;
Defined in lib/setuplib.php for now.&lt;br /&gt;
&lt;br /&gt;
===ddl_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during manipulation of database structure. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===dml_exception===&lt;br /&gt;
Base class for all exceptions that may be thrown during normal database access. See linked page for details.&lt;br /&gt;
&lt;br /&gt;
===file_exception===&lt;br /&gt;
Base class for file storage related problems.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47296</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47296"/>
		<updated>2008-11-27T16:52:11Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
[[Image:Exceptions.png]]&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=File:Exceptions.png&amp;diff=47295</id>
		<title>File:Exceptions.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=File:Exceptions.png&amp;diff=47295"/>
		<updated>2008-11-27T16:51:19Z</updated>

		<summary type="html">&lt;p&gt;Skodak: Top exceptions hierarchy&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Top exceptions hierarchy&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47294</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47294"/>
		<updated>2008-11-27T15:42:22Z</updated>

		<summary type="html">&lt;p&gt;Skodak: exceptions info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Exceptions are a common feature in all modern programming languages. They help us to handle exceptional problems that may appear unexpectedly during code execution.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
Please keep in mind that exceptions are for something really &#039;&#039;exceptional&#039;&#039;, normal code execution flow should not depend on them.&lt;br /&gt;
&lt;br /&gt;
Examples of suitable use are:&lt;br /&gt;
* problem writing to directory moodledata directory - this is expected to be always writable&lt;br /&gt;
* wrong function/method parameters - coding error which must be fixed by a developer&lt;br /&gt;
* inserting data into non-existent database table&lt;br /&gt;
&lt;br /&gt;
Incorrect uses:&lt;br /&gt;
* using exceptions instead of break in order to terminate loops&lt;br /&gt;
* returning results from functions&lt;br /&gt;
&lt;br /&gt;
==Major benefits==&lt;br /&gt;
===Less code===&lt;br /&gt;
Many IFs can be eliminated.&lt;br /&gt;
&lt;br /&gt;
===Return values are not mixed with error flags===&lt;br /&gt;
In previous versions database functions were returning false if something went wrong during execution. Sometimes the &#039;&#039;false&#039;&#039; value also meant no value found.&lt;br /&gt;
&lt;br /&gt;
===Recovery after error===&lt;br /&gt;
Previously if something went wrong we either returned false and printed debug info or terminated execution with error(), print_error() or die(). Exceptions allow us to wrap potentially problematic code in try-catch block and recover from exceptions.&lt;br /&gt;
&lt;br /&gt;
Example of suitable use could be admin/cron.php. There were several problems with module scripts terminating and preventing execution of other parts of cron script. Now we can wrap all calls to cron functions in try-catch block and recover from problems in individual activities or 3rd party code.&lt;br /&gt;
&lt;br /&gt;
==Exception hierarchy==&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47293</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47293"/>
		<updated>2008-11-27T15:15:06Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://www.php.net/manual/en/language.exceptions.php PHP Manual - Exceptions]&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DDL_exceptions&amp;diff=47292</id>
		<title>Development:DDL exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DDL_exceptions&amp;diff=47292"/>
		<updated>2008-11-27T15:08:24Z</updated>

		<summary type="html">&lt;p&gt;Skodak: New page: {{Moodle_2.0}}In previous versions problems during upgrade were ignored by default.   TODO: add more info here, explanation and same examples.   ==See also==  * [[Development:Exceptions|Ex...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems during upgrade were ignored by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47291</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47291"/>
		<updated>2008-11-27T15:07:09Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL exceptions|DDL exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47290</id>
		<title>Development:Exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:Exceptions&amp;diff=47290"/>
		<updated>2008-11-27T15:06:30Z</updated>

		<summary type="html">&lt;p&gt;Skodak: New page: {{Moodle_2.0}}   TODO: add more info here, explanation and same examples.   ==See also==  * DML Exceptions: Use of exceptions in DML layer * [[Development:DD...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML Exceptions|DML Exceptions]]: Use of exceptions in DML layer&lt;br /&gt;
* [[Development:DDL Exceptions|DDL Exceptions]]: Use of exceptions in DDL layer&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47289</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47289"/>
		<updated>2008-11-27T15:05:39Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidelines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47288</id>
		<title>Development:DML exceptions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_exceptions&amp;diff=47288"/>
		<updated>2008-11-27T15:05:17Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In previous versions problems in database calls were ignored by default.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Exceptions|Exceptions]]: General guidlines for using of exceptions in Moodle 2.0&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data. ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DTL_functions&amp;diff=47137</id>
		<title>Development:DTL functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DTL_functions&amp;diff=47137"/>
		<updated>2008-11-24T23:37:14Z</updated>

		<summary type="html">&lt;p&gt;Skodak: New page: {{Moodle_2.0}}New feature that enables transferring, import and export of sql data from one server to another. Useful especially when moving data to another type of database.  This is the ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}New feature that enables transferring, import and export of sql data from one server to another. Useful especially when moving data to another type of database.&lt;br /&gt;
&lt;br /&gt;
This is the result of GSOC 2OO8 project by Andrei Bautu.&lt;br /&gt;
&lt;br /&gt;
==TODO==&lt;br /&gt;
* add more info here&lt;br /&gt;
* add links to pages and docs created by Andrei&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DDL_functions&amp;diff=47136</id>
		<title>Development:DDL functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DDL_functions&amp;diff=47136"/>
		<updated>2008-11-24T23:30:58Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In this page you&#039;ll access to the available functions under Moodle to be able to handle DB structures (tables, fields, indexes...).&lt;br /&gt;
&lt;br /&gt;
The objective is to have a well-defined group of functions able to handle all the DB structure (DDL statements) using one neutral description, being able to execute the correct SQL statements required by each RDBMS. All these functions are used &#039;&#039;&#039;[[Development:Installing and upgrading plugin database tables|exclusively by the installation and upgrade processes]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In this page you&#039;ll see a complete list of such functions, with some explanations, tricks and examples of their use. If you are interested, it&#039;s also highly recommendable to take a look to the [[Development:DML functions|DML functions page]] where everything about how to handle DB data (select, insert, update, delete i.e. DML statements) is defined.&lt;br /&gt;
&lt;br /&gt;
Of course, feel free to clarify, complete and add more info to all this documentation. It will be welcome, absolutely!&lt;br /&gt;
&lt;br /&gt;
==Main info==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; All the functions showed in this page are for use in &#039;&#039;&#039;Moodle 2.0 upwards&#039;&#039;&#039;, where we changed the [[Development:DB layer 2.0|DB layer]] to support some new features. If you need information for previous Moodle version, take a look to the [[Development:DDL functions - pre 2.0|DDL functions - pre 2.0]] page.&lt;br /&gt;
&lt;br /&gt;
* All the function calls in this page are public methods of the &#039;&#039;&#039;database manager&#039;&#039;&#039;, accessible from the $DB global object. So you&#039;ll need to &amp;quot;import&amp;quot; it within your &#039;&#039;&#039;upgrade.php&#039;&#039;&#039; main function with something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_xxxx_upgrade {&lt;br /&gt;
  &lt;br /&gt;
    global $DB;&lt;br /&gt;
  &lt;br /&gt;
    $dbman = $DB-&amp;gt;get_manager(); // loads ddl manager and xmldb classes&lt;br /&gt;
  &lt;br /&gt;
    /// Your upgrade code goes here&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Once more, the use of these functions is &#039;&#039;&#039;restricted&#039;&#039;&#039; to the upgrade processes and it shouldn&#039;t be used ever out from there.&lt;br /&gt;
* All the $table, $field, $index parameters are, always, XMLDB objects. Don&#039;t forget to read carefully the complete documentation about [[Development:XMLDB creating new DDL functions|creating new DDL functions]] before playing with these functions. Everything is explained there, with one general example and some really useful tricks to improve the use of all the functions detailed below.&lt;br /&gt;
* If you want real examples of the usage of these functions it&#039;s 100% interesting to examine the &#039;&#039;&#039;upgrade.php&#039;&#039;&#039; scripts that are responsible for Moodle upgrading since the 1.7 release. &lt;br /&gt;
* Also, it&#039;s a &#039;&#039;&#039;very good idea&#039;&#039;&#039; (highly recommended!) to use the [[XMLDB editor|XMLDB Editor]] itself to generate automatically the desired PHP code. Just play with it!&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
&lt;br /&gt;
===Handling tables===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// To detect if one table exists:&lt;br /&gt;
    $dbman-&amp;gt;table_exists($table)&lt;br /&gt;
/// To create one table:&lt;br /&gt;
    $dbman-&amp;gt;create_table($table, $continue=true, $feedback=true)&lt;br /&gt;
/// To drop one table:&lt;br /&gt;
    $dbman-&amp;gt;drop_table($table, $continue=true, $feedback=true)&lt;br /&gt;
/// To rename one table:&lt;br /&gt;
    $dbman-&amp;gt;rename_table($table, $newname, $continue=true, $feedback=true)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Handling fields===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// To detect if one field exists:&lt;br /&gt;
    $dbman-&amp;gt;field_exists($table, $field)&lt;br /&gt;
/// To create one field:&lt;br /&gt;
    $dbman-&amp;gt;add_field($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To drop one field:&lt;br /&gt;
    $dbman-&amp;gt;drop_field($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To change the type of one field:&lt;br /&gt;
    $dbman-&amp;gt;change_field_type($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To change the precision of one field:&lt;br /&gt;
    $dbman-&amp;gt;change_field_precision($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To change the signed/unsigned status of one field:&lt;br /&gt;
    $dbman-&amp;gt;change_field_unsigned($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To make one field nullable or not:&lt;br /&gt;
    $dbman-&amp;gt;change_field_notnull($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To change the enum (check constraint) of one field:&lt;br /&gt;
    $dbman-&amp;gt;change_field_enum($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To change the default value of one field:&lt;br /&gt;
    $dbman-&amp;gt;change_field_default($table, $field, $continue=true, $feedback=true)&lt;br /&gt;
/// To rename one field:&lt;br /&gt;
    $dbman-&amp;gt;rename_field($table, $field, $newname, $continue=true, $feedback=true)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Handling indexes===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// To detect if one index exists:&lt;br /&gt;
    $dbman-&amp;gt;index_exists($table, $index)&lt;br /&gt;
/// To return the name of one index in DB:&lt;br /&gt;
    $dbman-&amp;gt;find_index_name($table, $index)&lt;br /&gt;
/// To add one index:&lt;br /&gt;
    $dbman-&amp;gt;add_index($table, $index, $continue=true, $feedback=true)&lt;br /&gt;
/// To drop one index:&lt;br /&gt;
    $dbman-&amp;gt;drop_index($table, $index, $continue=true, $feedback=true)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Some considerations==&lt;br /&gt;
# All the $table, $field, $index parameters are, always, XMLDB objects.&lt;br /&gt;
# All the $newtablename, $newfieldname parameters are, always, simple strings.&lt;br /&gt;
# All the ***_exists() functions return boolean true/false.&lt;br /&gt;
# Any problem in the execution of the functions will throw one Exception and the upgrade process will die.&lt;br /&gt;
# It&#039;s recommendable to use the [[XMLDB editor|XMLDB Editor]] to generate the PHP code automatically (did I say this before? :-P )&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:XMLDB Documentation|XMLDB Documentation]]: Main page of the whole XMLDB documentation, where all the process is defined and all the related information resides.&lt;br /&gt;
* [[XMLDB Defining one XML structure]]: Where you will know a bit more about the underlying XML structure used to define the DB objects, that is used continuously by the functions described in this page.&lt;br /&gt;
* [[Development:Installing and upgrading plugin database tables|Installing and upgrading plugin DB tables]]&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DDL functions - pre 2.0|DDL functions - pre 2.0]]: &#039;&#039;&#039;(deprecated!)&#039;&#039;&#039; For information valid before Moodle 2.0.&lt;br /&gt;
* [[Development:DB layer 2.0 migration docs|DB layer 2.0 migration docs]]: Information about how to modify your code to work with the new Moodle 2.0 DB layer.&lt;br /&gt;
* [[Development:DTL functions|DTL functions]]: Exporting, importing and moving of data stored in sql databases&lt;br /&gt;
&lt;br /&gt;
[[Category:DB]]&lt;br /&gt;
[[Category:XMLDB]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_functions&amp;diff=47135</id>
		<title>Development:DML functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_functions&amp;diff=47135"/>
		<updated>2008-11-24T23:30:08Z</updated>

		<summary type="html">&lt;p&gt;Skodak: DTL info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In this page you&#039;ll access to the available functions under Moodle to be able to access to DB data. You should use &#039;&#039;&#039;exclusively&#039;&#039;&#039; these functions in order to retrieve or modify DB contents because these functions provide an high level of abstraction and guarantee that your DB manipulation will work against different RDBMS.&lt;br /&gt;
&lt;br /&gt;
Where possible, tricks and examples will be documented here in order to make developers&#039; lives a bit easier. Of course, feel free to clarify, complete and add more info to all this documentation. It will be welcome, absolutely!&lt;br /&gt;
&lt;br /&gt;
== Main info ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; All the functions showed in this page are for use in &#039;&#039;&#039;Moodle 2.0 upwards&#039;&#039;&#039;, where we changed the [[Development:DB layer 2.0|DB layer]] to support some new features. If you need information for previous Moodle version, take a look to the [[Development:DML functions - pre 2.0|DML functions - pre 2.0]] page.&lt;br /&gt;
&lt;br /&gt;
* All the function calls in this page are public methods of the $DB global object. So you&#039;ll need to &amp;quot;import&amp;quot; it within your functions (not needed in global scripts) with one simple:&lt;br /&gt;
&amp;lt;code php&amp;gt;global $DB;&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $table parameters in the functions are mean to be the table name &#039;&#039;&#039;without&#039;&#039; prefixes.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;&#039;1&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
* When using the xxx_sql() functions, table names must be enclosed between curly braces.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE id = ?&#039;, array(1));&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $conditions parameters in the functions are arrays of fieldname=&amp;gt;fieldvalue elements.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record(&#039;user&#039;, array(&#039;firstname&#039;=&amp;gt;&#039;Martin&#039;, &#039;lastname&#039;=&amp;gt;&#039;Dougiamas&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $params parameters in the functions are arrays of values used to fill placeholders in SQL statements. Both question mark and named placeholders can be used.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// Question mark placeholders:&lt;br /&gt;
   $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE firstname = ? AND lastname = ?&#039;, &lt;br /&gt;
                       array(&#039;Martin&#039;, &#039;Dougiamas&#039;));&lt;br /&gt;
&lt;br /&gt;
/// Named placeholders:&lt;br /&gt;
   $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE firstname = :firstname AND lastname = :lastname&#039;,&lt;br /&gt;
                       array(&#039;firstname&#039;=&amp;gt;&#039;Martin&#039;, &#039;lastname&#039;=&amp;gt;&#039;Dougiamas&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The functions ==&lt;br /&gt;
&lt;br /&gt;
===Seeing how many records match a given criteria===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;count_records($table, array $conditions=null) &lt;br /&gt;
  /// Count the records in a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;count_records_select($table, $select, array $params=null, $countitem=&amp;quot;COUNT(&#039;x&#039;)&amp;quot;) &lt;br /&gt;
  /// Count the records in a table which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;count_records_sql($sql, array $params=null) &lt;br /&gt;
  /// Get the result of a SQL SELECT COUNT(...) query.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Seeing if one record exists===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;record_exists($table, array $conditions=null) &lt;br /&gt;
  /// Test whether a record exists in a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;record_exists_select($table, $select, array $params=null) &lt;br /&gt;
  /// Test whether any records exists in a table which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;record_exists_sql($sql, array $params=null) &lt;br /&gt;
  /// Test whether a SQL SELECT statement returns any records.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Retrieving a single record===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_record($table, array $conditions, $fields=&#039;*&#039;, $ignoremultiple=false) &lt;br /&gt;
  /// Get a single database record as an object where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_record_select($table, $select, array $params=null, $fields=&#039;*&#039;, $ignoremultiple=false)&lt;br /&gt;
  /// Get a single database record as an object which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_record_select($table, $select, array $params=null, $fields=&#039;*&#039;, $ignoremultiple=false)&lt;br /&gt;
  /// Get a single database record as an object using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting an array of records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_records($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as an array of objects where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_records_select($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as an array of objects which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get a number of records as an array of objects using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_records_menu($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_records_select_menu($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_records_sql_menu($sql, array $params=null, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_records_list($table, $field=&#039;&#039;, $values=&#039;&#039;, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=&#039;&#039;, $limitnum=&#039;&#039;) &lt;br /&gt;
  /// Get a number of records as an array of objects where one field match one list of values.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting a particular field value from one record===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_field($table, $return, array $conditions)&lt;br /&gt;
  /// Get a single field value from a table record where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_field_select($table, $return, $select, array $params=null)&lt;br /&gt;
  /// Get a single field value from a table record which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_field_sql($sql, array $params=null)&lt;br /&gt;
  /// Get a single field value (first field) using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting a particular field value from various records===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_fieldset_select($table, $return, $select, array $params=null)&lt;br /&gt;
  /// Selects records and return values of chosen field as an array which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_fieldset_sql($sql, array $params=null)&lt;br /&gt;
  /// Selects records and return values (first field) as an array using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Setting a particular field in the database===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;set_field($table, $newfield, $newvalue, array $conditions=null)&lt;br /&gt;
  /// Set a single field in every table record where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;set_field_select($table, $newfield, $newvalue, $select, array $params=null)&lt;br /&gt;
  /// Set a single field in every table record which match a particular WHERE clause.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Deleting Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;delete_records($table, array $conditions=null) &lt;br /&gt;
  /// Delete the records from a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;delete_records_select($table, $select, array $params=null)&lt;br /&gt;
  /// Delete one or more records from a table which match a particular WHERE clause.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Inserting Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;insert_record($table, $dataobject, $returnid=true, $bulk=false) &lt;br /&gt;
  /// Insert a record into a table and return the &amp;quot;id&amp;quot; field if required.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Updating Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;update_record($table, $dataobject, $bulk=false)&lt;br /&gt;
  /// Update a record in a table.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using Recordsets===&lt;br /&gt;
&lt;br /&gt;
While the number of records to be retrieved from DB is high, the &#039;&#039;&#039;get_records_xxx()&#039;&#039;&#039; functions above are far from optimal, because they use to load all the records in memory at the same time. Under those circumstances, it&#039;s highly recommended to use this &#039;&#039;&#039;get_recordset_xxx()&#039;&#039;&#039; functions instead, using one nice mechanism to iterate over all the target records saving a lot of memory.&lt;br /&gt;
&lt;br /&gt;
Only one thing is &#039;&#039;&#039;absolutely important&#039;&#039;&#039;. Don&#039;t forget to close the record sets after using them! (that will freed a lot of resources in the RDBMS).&lt;br /&gt;
&lt;br /&gt;
Here it&#039;s the general way to iterate over records using the &#039;&#039;&#039;get_recordset_xxx()&#039;&#039;&#039; functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($rs = $DB-&amp;gt;get_recordset(....) {&lt;br /&gt;
    foreach ($rs as $record) {&lt;br /&gt;
     /// Do whatever you want with this record&lt;br /&gt;
    }&lt;br /&gt;
    $rs-&amp;gt;close(); /// Don&#039;t forget to close the recordset!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And this is the list of available functions (100% paired with the get_records_xxx() above):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_recordset($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_recordset_select($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0);&lt;br /&gt;
  /// Get a number of records as a moodle_recordset using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_recordset_list($table, $field=&#039;&#039;, $values=&#039;&#039;, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=&#039;&#039;, $limitnum=&#039;&#039;) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset where one field match one list of values.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Functions===&lt;br /&gt;
&lt;br /&gt;
In order have real cross-db compatibility, there are some helper functions used to build SQL fragments based on the DB Moodle is running. Using them we&#039;ll avoid conditional queries here and there, having those &amp;quot;incompatibilities&amp;quot; fixed once and for ever.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;sql_bitand($int1, $int2) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise AND &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
o $DB-&amp;gt;sql_bitnot($int1) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise NOT &lt;br /&gt;
  /// operation with 1 integer.&lt;br /&gt;
o $DB-&amp;gt;sql_bitor($int1, $int2)&lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise OR &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
o $DB-&amp;gt;sql_bitxor($int1, $int2) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise XOR &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_null_from_clause()&lt;br /&gt;
  /// Returns the FROM clause required by some DBs in all SELECT statements.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_ceil($fieldname)&lt;br /&gt;
  /// Returns the correct CEIL expression applied to fieldname.&lt;br /&gt;
o $DB-&amp;gt;sql_substr()&lt;br /&gt;
  /// Returns the proper substr() function for each DB.&lt;br /&gt;
o $DB-&amp;gt;sql_ilike()&lt;br /&gt;
  /// Returns the proper SQL to do LIKE in a case-insensitive way.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_cast_char2int($fieldname, $text=false)&lt;br /&gt;
  /// Returns the SQL to be used in order to CAST one CHAR column to INTEGER.&lt;br /&gt;
o $DB-&amp;gt;sql_cast_char2real($fieldname, $text=false)&lt;br /&gt;
  /// Returns the SQL to be used in order to CAST one CHAR column to REAL number.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_compare_text($fieldname, $numchars=32) &lt;br /&gt;
  /// Returns the SQL text to be used to compare one TEXT (clob) column.&lt;br /&gt;
  /// with one VARCHAR column.&lt;br /&gt;
o $DB-&amp;gt;sql_order_by_text($fieldname, $numchars=32)&lt;br /&gt;
  /// Returns the SQL text to be used to order by one TEXT (clob) column.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_concat()&lt;br /&gt;
  /// Returns the proper SQL to do CONCAT between the elements passed.&lt;br /&gt;
o $DB-&amp;gt;sql_concat_join($separator=&amp;quot;&#039; &#039;&amp;quot;, $elements=array())&lt;br /&gt;
  /// Returns the proper SQL to do CONCAT between the elements passed using one separator.&lt;br /&gt;
o $DB-&amp;gt;sql_fullname($first=&#039;firstname&#039;, $last=&#039;lastname&#039;)&lt;br /&gt;
  /// Returns the proper SQL to concatenate $firstname and $lastname.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_isempty($tablename, $fieldname, $nullablefield, $textfield)&lt;br /&gt;
  /// Returns the proper SQL to know if one field is empty.&lt;br /&gt;
o $DB-&amp;gt;sql_isnotempty($tablename, $fieldname, $nullablefield, $textfield)&lt;br /&gt;
  /// Returns the proper SQL to know if one field is not empty.&lt;br /&gt;
o $DB-&amp;gt;sql_empty()&lt;br /&gt;
  /// Returns the empty string char used by every supported DB.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;br /&gt;
* [[Development:DML drivers|DML drivers]]: Database drivers for new DML layer&lt;br /&gt;
* [[Development:DML functions - pre 2.0|DML functions - pre 2.0]]: &#039;&#039;&#039;(deprecated!)&#039;&#039;&#039; For information valid before Moodle 2.0.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;br /&gt;
* [[Development:DB layer 2.0 examples|DB layer 2.0 examples]]: To see some code examples using various DML functions.&lt;br /&gt;
* [[Development:DB layer 2.0 migration docs|DB layer 2.0 migration docs]]: Information about how to modify your code to work with the new Moodle 2.0 DB layer.&lt;br /&gt;
* [[Development:DTL functions|DTL functions]]: Exporting, importing and moving of data stored in sql databases&lt;br /&gt;
&lt;br /&gt;
[[Category:DB]]&lt;br /&gt;
[[Category:XMLDB]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Developer_meeting_November_2008&amp;diff=47133</id>
		<title>Developer meeting November 2008</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Developer_meeting_November_2008&amp;diff=47133"/>
		<updated>2008-11-24T23:25:34Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Moodle 2.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; November 2008 meeting&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Date: 23:00 UTC on Monday, 24 November 2008 - see the [http://moodle.org/calendar/view.php?view=day&amp;amp;course=5&amp;amp;cal_d=25&amp;amp;cal_m=11&amp;amp;cal_y=2008#event_4805 Moodle Developer Meeting calendar entry] for conversion into your time zone &lt;br /&gt;
*Location: [http://elluminate.remote-learner.net/join_meeting.html?meetingId=1176914355734 Elluminate Moodle Developers Meeting Room] - login using your actual name as login name and password &#039;&#039;moodle&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Moodle 2.0==&lt;br /&gt;
&lt;br /&gt;
* Overview and timeline - Martin D&lt;br /&gt;
* [[Development:Roles_administration_improvements_for_Moodle_2.0|New roles interfaces demo]], as an example of good JavaScript practices - Tim&lt;br /&gt;
* [[Development:Enrolment_plugins_2.0|Enrolment plugins proposal]]? - Tim&lt;br /&gt;
*  Database related changes: [[Development:DML functions|DML]], [[Development:DDL functions|DDL]], DTL and new [[Development:DML drivers|native database drivers]] - skodak&lt;br /&gt;
* Privacy project MDL-17205 - skodak&lt;br /&gt;
* [[Development:Web_services|New web services system]] - Jerome&lt;br /&gt;
* Repository Plugins &amp;amp; new chat module - Dongsheng&lt;br /&gt;
* [https://docs.moodle.org/en/Feedback_link_for_all_elements Feedback link for all elements] If there&#039;s time, and I get up again before midnight - Jeff Forssell&lt;br /&gt;
&lt;br /&gt;
==Other news==&lt;br /&gt;
&lt;br /&gt;
*Google Highly Open Participation Contest (GHOP) (Helen)&lt;br /&gt;
*GSOC Mentor Summit - a few words about the summit (DanP &amp;amp; maybe Anthony/David Horat if they have anything to add)&lt;br /&gt;
*[[Events Subscriptions / Notifications sub-system]] - concept stage (Mike C.)&lt;br /&gt;
&lt;br /&gt;
*Anything else?  Please add yours.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
*[[Roadmap]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Developer_meeting_November_2008&amp;diff=47130</id>
		<title>Developer meeting November 2008</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Developer_meeting_November_2008&amp;diff=47130"/>
		<updated>2008-11-24T23:24:29Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Moodle 2.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; November 2008 meeting&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Date: 23:00 UTC on Monday, 24 November 2008 - see the [http://moodle.org/calendar/view.php?view=day&amp;amp;course=5&amp;amp;cal_d=25&amp;amp;cal_m=11&amp;amp;cal_y=2008#event_4805 Moodle Developer Meeting calendar entry] for conversion into your time zone &lt;br /&gt;
*Location: [http://elluminate.remote-learner.net/join_meeting.html?meetingId=1176914355734 Elluminate Moodle Developers Meeting Room] - login using your actual name as login name and password &#039;&#039;moodle&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Moodle 2.0==&lt;br /&gt;
&lt;br /&gt;
* Overview and timeline - Martin D&lt;br /&gt;
* [[Development:Roles_administration_improvements_for_Moodle_2.0|New roles interfaces demo]], as an example of good JavaScript practices - Tim&lt;br /&gt;
* [[Development:Enrolment_plugins_2.0|Enrolment plugins proposal]]? - Tim&lt;br /&gt;
*  Database related changes: [[Development:DML functions|DML]], [[Development:DDL functions|DDL]], DTL and new [[Development:DML drivers|native database drivers]] - skodak&lt;br /&gt;
* Privacy project - skodak&lt;br /&gt;
* [[Development:Web_services|New web services system]] - Jerome&lt;br /&gt;
* Repository Plugins &amp;amp; new chat module - Dongsheng&lt;br /&gt;
* [https://docs.moodle.org/en/Feedback_link_for_all_elements Feedback link for all elements] If there&#039;s time, and I get up again before midnight - Jeff Forssell&lt;br /&gt;
&lt;br /&gt;
==Other news==&lt;br /&gt;
&lt;br /&gt;
*Google Highly Open Participation Contest (GHOP) (Helen)&lt;br /&gt;
*GSOC Mentor Summit - a few words about the summit (DanP &amp;amp; maybe Anthony/David Horat if they have anything to add)&lt;br /&gt;
*Events Subscriptions / Notifications sub-system - concept stage (Mike C.)&lt;br /&gt;
&lt;br /&gt;
*Anything else?  Please add yours.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
*[[Roadmap]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_functions&amp;diff=47129</id>
		<title>Development:DML functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_functions&amp;diff=47129"/>
		<updated>2008-11-24T23:20:05Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In this page you&#039;ll access to the available functions under Moodle to be able to access to DB data. You should use &#039;&#039;&#039;exclusively&#039;&#039;&#039; these functions in order to retrieve or modify DB contents because these functions provide an high level of abstraction and guarantee that your DB manipulation will work against different RDBMS.&lt;br /&gt;
&lt;br /&gt;
Where possible, tricks and examples will be documented here in order to make developers&#039; lives a bit easier. Of course, feel free to clarify, complete and add more info to all this documentation. It will be welcome, absolutely!&lt;br /&gt;
&lt;br /&gt;
== Main info ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; All the functions showed in this page are for use in &#039;&#039;&#039;Moodle 2.0 upwards&#039;&#039;&#039;, where we changed the [[Development:DB layer 2.0|DB layer]] to support some new features. If you need information for previous Moodle version, take a look to the [[Development:DML functions - pre 2.0|DML functions - pre 2.0]] page.&lt;br /&gt;
&lt;br /&gt;
* All the function calls in this page are public methods of the $DB global object. So you&#039;ll need to &amp;quot;import&amp;quot; it within your functions (not needed in global scripts) with one simple:&lt;br /&gt;
&amp;lt;code php&amp;gt;global $DB;&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $table parameters in the functions are mean to be the table name &#039;&#039;&#039;without&#039;&#039; prefixes.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;&#039;1&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
* When using the xxx_sql() functions, table names must be enclosed between curly braces.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE id = ?&#039;, array(1));&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $conditions parameters in the functions are arrays of fieldname=&amp;gt;fieldvalue elements.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record(&#039;user&#039;, array(&#039;firstname&#039;=&amp;gt;&#039;Martin&#039;, &#039;lastname&#039;=&amp;gt;&#039;Dougiamas&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $params parameters in the functions are arrays of values used to fill placeholders in SQL statements. Both question mark and named placeholders can be used.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// Question mark placeholders:&lt;br /&gt;
   $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE firstname = ? AND lastname = ?&#039;, &lt;br /&gt;
                       array(&#039;Martin&#039;, &#039;Dougiamas&#039;));&lt;br /&gt;
&lt;br /&gt;
/// Named placeholders:&lt;br /&gt;
   $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE firstname = :firstname AND lastname = :lastname&#039;,&lt;br /&gt;
                       array(&#039;firstname&#039;=&amp;gt;&#039;Martin&#039;, &#039;lastname&#039;=&amp;gt;&#039;Dougiamas&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The functions ==&lt;br /&gt;
&lt;br /&gt;
===Seeing how many records match a given criteria===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;count_records($table, array $conditions=null) &lt;br /&gt;
  /// Count the records in a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;count_records_select($table, $select, array $params=null, $countitem=&amp;quot;COUNT(&#039;x&#039;)&amp;quot;) &lt;br /&gt;
  /// Count the records in a table which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;count_records_sql($sql, array $params=null) &lt;br /&gt;
  /// Get the result of a SQL SELECT COUNT(...) query.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Seeing if one record exists===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;record_exists($table, array $conditions=null) &lt;br /&gt;
  /// Test whether a record exists in a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;record_exists_select($table, $select, array $params=null) &lt;br /&gt;
  /// Test whether any records exists in a table which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;record_exists_sql($sql, array $params=null) &lt;br /&gt;
  /// Test whether a SQL SELECT statement returns any records.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Retrieving a single record===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_record($table, array $conditions, $fields=&#039;*&#039;, $ignoremultiple=false) &lt;br /&gt;
  /// Get a single database record as an object where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_record_select($table, $select, array $params=null, $fields=&#039;*&#039;, $ignoremultiple=false)&lt;br /&gt;
  /// Get a single database record as an object which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_record_select($table, $select, array $params=null, $fields=&#039;*&#039;, $ignoremultiple=false)&lt;br /&gt;
  /// Get a single database record as an object using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting an array of records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_records($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as an array of objects where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_records_select($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as an array of objects which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get a number of records as an array of objects using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_records_menu($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_records_select_menu($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_records_sql_menu($sql, array $params=null, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_records_list($table, $field=&#039;&#039;, $values=&#039;&#039;, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=&#039;&#039;, $limitnum=&#039;&#039;) &lt;br /&gt;
  /// Get a number of records as an array of objects where one field match one list of values.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting a particular field value from one record===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_field($table, $return, array $conditions)&lt;br /&gt;
  /// Get a single field value from a table record where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_field_select($table, $return, $select, array $params=null)&lt;br /&gt;
  /// Get a single field value from a table record which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_field_sql($sql, array $params=null)&lt;br /&gt;
  /// Get a single field value (first field) using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting a particular field value from various records===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_fieldset_select($table, $return, $select, array $params=null)&lt;br /&gt;
  /// Selects records and return values of chosen field as an array which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_fieldset_sql($sql, array $params=null)&lt;br /&gt;
  /// Selects records and return values (first field) as an array using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Setting a particular field in the database===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;set_field($table, $newfield, $newvalue, array $conditions=null)&lt;br /&gt;
  /// Set a single field in every table record where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;set_field_select($table, $newfield, $newvalue, $select, array $params=null)&lt;br /&gt;
  /// Set a single field in every table record which match a particular WHERE clause.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Deleting Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;delete_records($table, array $conditions=null) &lt;br /&gt;
  /// Delete the records from a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;delete_records_select($table, $select, array $params=null)&lt;br /&gt;
  /// Delete one or more records from a table which match a particular WHERE clause.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Inserting Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;insert_record($table, $dataobject, $returnid=true, $bulk=false) &lt;br /&gt;
  /// Insert a record into a table and return the &amp;quot;id&amp;quot; field if required.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Updating Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;update_record($table, $dataobject, $bulk=false)&lt;br /&gt;
  /// Update a record in a table.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using Recordsets===&lt;br /&gt;
&lt;br /&gt;
While the number of records to be retrieved from DB is high, the &#039;&#039;&#039;get_records_xxx()&#039;&#039;&#039; functions above are far from optimal, because they use to load all the records in memory at the same time. Under those circumstances, it&#039;s highly recommended to use this &#039;&#039;&#039;get_recordset_xxx()&#039;&#039;&#039; functions instead, using one nice mechanism to iterate over all the target records saving a lot of memory.&lt;br /&gt;
&lt;br /&gt;
Only one thing is &#039;&#039;&#039;absolutely important&#039;&#039;&#039;. Don&#039;t forget to close the record sets after using them! (that will freed a lot of resources in the RDBMS).&lt;br /&gt;
&lt;br /&gt;
Here it&#039;s the general way to iterate over records using the &#039;&#039;&#039;get_recordset_xxx()&#039;&#039;&#039; functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($rs = $DB-&amp;gt;get_recordset(....) {&lt;br /&gt;
    foreach ($rs as $record) {&lt;br /&gt;
     /// Do whatever you want with this record&lt;br /&gt;
    }&lt;br /&gt;
    $rs-&amp;gt;close(); /// Don&#039;t forget to close the recordset!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And this is the list of available functions (100% paired with the get_records_xxx() above):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_recordset($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_recordset_select($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0);&lt;br /&gt;
  /// Get a number of records as a moodle_recordset using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_recordset_list($table, $field=&#039;&#039;, $values=&#039;&#039;, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=&#039;&#039;, $limitnum=&#039;&#039;) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset where one field match one list of values.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Functions===&lt;br /&gt;
&lt;br /&gt;
In order have real cross-db compatibility, there are some helper functions used to build SQL fragments based on the DB Moodle is running. Using them we&#039;ll avoid conditional queries here and there, having those &amp;quot;incompatibilities&amp;quot; fixed once and for ever.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;sql_bitand($int1, $int2) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise AND &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
o $DB-&amp;gt;sql_bitnot($int1) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise NOT &lt;br /&gt;
  /// operation with 1 integer.&lt;br /&gt;
o $DB-&amp;gt;sql_bitor($int1, $int2)&lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise OR &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
o $DB-&amp;gt;sql_bitxor($int1, $int2) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise XOR &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_null_from_clause()&lt;br /&gt;
  /// Returns the FROM clause required by some DBs in all SELECT statements.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_ceil($fieldname)&lt;br /&gt;
  /// Returns the correct CEIL expression applied to fieldname.&lt;br /&gt;
o $DB-&amp;gt;sql_substr()&lt;br /&gt;
  /// Returns the proper substr() function for each DB.&lt;br /&gt;
o $DB-&amp;gt;sql_ilike()&lt;br /&gt;
  /// Returns the proper SQL to do LIKE in a case-insensitive way.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_cast_char2int($fieldname, $text=false)&lt;br /&gt;
  /// Returns the SQL to be used in order to CAST one CHAR column to INTEGER.&lt;br /&gt;
o $DB-&amp;gt;sql_cast_char2real($fieldname, $text=false)&lt;br /&gt;
  /// Returns the SQL to be used in order to CAST one CHAR column to REAL number.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_compare_text($fieldname, $numchars=32) &lt;br /&gt;
  /// Returns the SQL text to be used to compare one TEXT (clob) column.&lt;br /&gt;
  /// with one VARCHAR column.&lt;br /&gt;
o $DB-&amp;gt;sql_order_by_text($fieldname, $numchars=32)&lt;br /&gt;
  /// Returns the SQL text to be used to order by one TEXT (clob) column.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_concat()&lt;br /&gt;
  /// Returns the proper SQL to do CONCAT between the elements passed.&lt;br /&gt;
o $DB-&amp;gt;sql_concat_join($separator=&amp;quot;&#039; &#039;&amp;quot;, $elements=array())&lt;br /&gt;
  /// Returns the proper SQL to do CONCAT between the elements passed using one separator.&lt;br /&gt;
o $DB-&amp;gt;sql_fullname($first=&#039;firstname&#039;, $last=&#039;lastname&#039;)&lt;br /&gt;
  /// Returns the proper SQL to concatenate $firstname and $lastname.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_isempty($tablename, $fieldname, $nullablefield, $textfield)&lt;br /&gt;
  /// Returns the proper SQL to know if one field is empty.&lt;br /&gt;
o $DB-&amp;gt;sql_isnotempty($tablename, $fieldname, $nullablefield, $textfield)&lt;br /&gt;
  /// Returns the proper SQL to know if one field is not empty.&lt;br /&gt;
o $DB-&amp;gt;sql_empty()&lt;br /&gt;
  /// Returns the empty string char used by every supported DB.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;br /&gt;
* [[Development:DML drivers|DML drivers]]: Database drivers for new DML layer&lt;br /&gt;
* [[Development:DML functions - pre 2.0|DML functions - pre 2.0]]: &#039;&#039;&#039;(deprecated!)&#039;&#039;&#039; For information valid before Moodle 2.0.&lt;br /&gt;
* [[Development:DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;br /&gt;
* [[Development:DB layer 2.0 examples|DB layer 2.0 examples]]: To see some code examples using various DML functions.&lt;br /&gt;
* [[Development:DB layer 2.0 migration docs|DB layer 2.0 migration docs]]: Information about how to modify your code to work with the new Moodle 2.0 DB layer.&lt;br /&gt;
&lt;br /&gt;
[[Category:DB]]&lt;br /&gt;
[[Category:XMLDB]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47128</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47128"/>
		<updated>2008-11-24T23:18:13Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encapsulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
At present there are two sample native drivers - mysqli and pgsql. The benefits are:&lt;br /&gt;
* more optimised and probably faster&lt;br /&gt;
* consume less memory&lt;br /&gt;
* better possibility to improve logging, debugging, profiling, etc.&lt;br /&gt;
* less code, easier to fix and maintain&lt;br /&gt;
* and more&lt;br /&gt;
&lt;br /&gt;
Please note that native drivers are now used by default in HEAD because we need to get as much testing as possible ;-)&lt;br /&gt;
&lt;br /&gt;
==TODO==&lt;br /&gt;
* add more info here&lt;br /&gt;
* add separate docs pages for each driver - describe all options there&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47127</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47127"/>
		<updated>2008-11-24T23:17:28Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encapsulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
At present there are two sample native drivers - mysqli and pgsql. The benefits are:&lt;br /&gt;
* more optimised and probably faster&lt;br /&gt;
* consume less memory&lt;br /&gt;
* better possibility to improve logging, debugging, profiling&lt;br /&gt;
* smaller code &amp;amp; easier to fix and maintain&lt;br /&gt;
* and more&lt;br /&gt;
&lt;br /&gt;
Please note that native drivers are now used by default in HEAD because we need to get as much testing as possible ;-)&lt;br /&gt;
&lt;br /&gt;
==TODO==&lt;br /&gt;
* add more info here&lt;br /&gt;
* add separate docs pages for each driver - describe all options there&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47126</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47126"/>
		<updated>2008-11-24T23:17:01Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encapsulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
At present there are two sample native drivers - mysqli and pgsql. The benefits are:&lt;br /&gt;
* more optimised and probably faster&lt;br /&gt;
* consume less memory&lt;br /&gt;
* better possibility to improve logging, debugging, profiling&lt;br /&gt;
* smaller code &amp;amp; easier to fix and maintain&lt;br /&gt;
* and more&lt;br /&gt;
&lt;br /&gt;
Please note that native drivers are now used by default in HEAD because we need to get as much testing as possible.&lt;br /&gt;
&lt;br /&gt;
==TODO==&lt;br /&gt;
* add more info here&lt;br /&gt;
* add separate docs pages for each driver - describe all options there&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47125</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47125"/>
		<updated>2008-11-24T23:16:42Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encapsulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
At present there are two sample native drivers - mysqli and pgsql. The benefits are:&lt;br /&gt;
* more optimised and probably faster&lt;br /&gt;
* consume less memory&lt;br /&gt;
* better possibility to improve logging, debugging, profiling&lt;br /&gt;
* smaller code &amp;amp; easier to fix and maintain&lt;br /&gt;
* and more&lt;br /&gt;
&lt;br /&gt;
Please note that native drivers are now used by default in HEAD because we need to get as much testing as possible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TODO==&lt;br /&gt;
* add more info here&lt;br /&gt;
* add separate docs pages for each driver - describe all options there&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47124</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47124"/>
		<updated>2008-11-24T23:13:41Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encapsulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
At present there are two sample native drivers - mysql and pgsql. The benefits are:&lt;br /&gt;
* more optimised and probably faster&lt;br /&gt;
* consume less memory&lt;br /&gt;
* better possibility to improve logging, debugging, profiling&lt;br /&gt;
* smaller code &amp;amp; easier to fix and maintain&lt;br /&gt;
* and more&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47122</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47122"/>
		<updated>2008-11-24T23:06:22Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encaplulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here and explanation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47121</id>
		<title>Development:DML drivers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/test/index.php?title=Development:DML_drivers&amp;diff=47121"/>
		<updated>2008-11-24T23:04:38Z</updated>

		<summary type="html">&lt;p&gt;Skodak: New page: {{Moodle_2.0}}Previous versions were using adodb abstraction partially encaplulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possib...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}Previous versions were using adodb abstraction partially encaplulated by old DML api. The database drivers are now fully separated from the rest of code and it is even possible to create new native drivers that do not rely on adodb abstraction anymore.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: add more info here, explanation and same examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development:DML functions|DML functions]]: Where all the functions used to handle DB data ([[wikipedia:Data_Manipulation_Language|DML]]) are defined.&lt;br /&gt;
* [[Development:DML exceptions|DML exceptions]]: New DML code is throwing exceptions instead of returning false if anything goes wrong&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
</feed>