Important! insert_record() changes

Important! insert_record() changes

by Martín Langhoff -
Number of replies: 29

Specialy important for module maintainers and contrib code maintainers!

The insert_record() we have in HEAD (devel 1.6) today has changed its function prototype -- it used to allow for an optional 4th parameter which was only used in 2 places.

We discovered that it was meant to support tables without an 'id' column. And tables without an id column are generally a really bad idea, and were causing trouble with backup/restore and potentially a few other places.

And in any case, id-less are sooooo last century, that we don't care about them any more. So the 4th parameter is now deprecated.

All the gory details are at http://moodle.org/bugs/bug.php?op=show&bugid=4583

Eloy has audited Moodle core code, and the official modules, and fixed all the invocations. But it is up to you to ensure that your code is compatible with 1.6! So be good, and review your insert_record() calls wink

cheers!

Average of ratings: -
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Eloy Lafuente (stronk7) -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers Picture of Testers
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...
I won't post anything before reading existing discussions...

http://moodle.org/mod/forum/discuss.php?d=38228

blush blush blush

Sorry all, ciao smile
In reply to Eloy Lafuente (stronk7)

Re: Important! insert_record() changes

by Martín Langhoff -
smile

No worries. We're doubling up -- and it's good. Only the very distracted will miss out on this announcement. It's an important thing, so there are now two writeups. We got it covered.

In reply to Eloy Lafuente (stronk7)

Re: Important! insert_record() changes

by sam marshall -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers
Whoops. I saw your link above and thought you were pointing to the correct thread (which should be used instead of this one), so I posted in there... oh well, my comment is now in that other thread. sorry.

--sam
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I've got to speak out against this.

I am generally against this 'everything must have an id column' thing, and therefore I feel this is generally a backward step, since it entrenches that policy.

Obviously, an ID makes sense for actual things like courses, users, etc.

However, I really don's see the point of having ids on some of the 'relationship' tables like user_teachers, which don't store acutal things, just realation ships between things - in this case saying that user X is a teachon on course Y. I have yet to see any place in the code where the id column in this table is used. All references to rows in this table (which mostly come through functions in moodlelib.php), identify rows by a combination of userid and courseid. That is entirely natural and as it should be. As far as I can see, the id column here is just so much dead wood that has to be carried around.
In reply to Tim Hunt

Re: Important! insert_record() changes

by Eloy Lafuente (stronk7) -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers Picture of Testers
Hey,

I only can say that, from a relational-DB perspective, I agree 100% with your posts. I remember, some time ago, when I arrived to Moodle, that I was really surprised about all those "id" artificial PKs (not necessary nor used at all). More yet, my first DB contributions (the backup tables) didn't contain such artificial "id" at all and "true" PKs were used instead.

But problems arrive when any of the get_record_XXX() functions are used, because all them returns associative arrays (GetAssoc()) where the first field in the returned recordset becomes the key of the array. So having those artificial "id" fields for each table is the only mechanism to fetch all the records from any table without losing some of them by the "key overwritten" effect. Following your example, something so simple like:

get_records('user_teachers')

won't work if the id field is missing. Only one occurrence of every teacher (the first field in the select, userid) will be returned, missing a lot of records.

I'm pretty sure that we could bypass this limit in the long term (current recordsets implementation is a good start) but it would force us to review all the get_records_XXX() calls before, because a lot of them, simply will break and others could be using the GetAssoc() key feature in its own benefit so, modifying the type of arrays returned by the functions isn't an immediate alternative.

I really think that it's the reason to have that mandatory id column inside each table. And the proposed change about killing the 4th parameter in the insert_record() function was only to enforce it more...

Perhaps 2.0 would be a cool target to "modernise" DB a bit, but for now...I think it's a good idea to require the id to be present to avoid unexpected results...

Ciao smile
In reply to Eloy Lafuente (stronk7)

Re: Important! insert_record() changes

by Martín Langhoff -
Hey, when in Rome, I make sure I enjoy the pizza & pasta. When in Moodle, I make sure I get as much mileage out of the fact that we have easy to use datalib functions based on certain assumptions.

It actually works pretty well with an RDBMS that shall not be named which has problems (historically at least) with using multiple indexes per column. So selecting on your true unique set of values may be the relationally correct way, but pretty ineffective on M-named database engines.

And we use quite a few JOINs... and to scale better we should be pushing more work we do in PHP into smarter SELECTs that inevitably use JOINs (I'll dance and rejoice the day we can count on subselects to work). Arbitrary numeric id fields are great for that! JOINing on multiple keys gets us rather hard to maintain SQL.

I have some multi-page SQL statements from other projects that I am very proud of. But it's a dog to read and maintain. We do most of our work on Moodle without thinking much about SQL, and that's actually great. I'm pushing for a little bit more of SQL for better scalability, knowing that it'll have an impact on code maintainability and readability for new coders...

... now moving away from ids would mean we do all our SQL the hard way. Now, what feature or concrete benefit does it buy us? A bit less disk space usage?

It will force people to learn more about the table design they are dealing with, and that's good. Perhaps marginally faster on Postgres. But it will make the code more brittle and fiddly.

If it's about shutting up the RDBMS purists, earplugs are easier & cheaper wink
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Eloy Lafuente (stronk7) -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers Picture of Testers
Hey Martín,

I always get really impressed about your vocabulary facilities and how sometimes you are able to say exactly what I'm not able to express properly.

Is there any course available in NZ about "how to say what you want to say in English"? Online preferred, of course! wink No preferences about the platform to use. tongueout

Also, as Michael suggested, we all could spend some weeks there if the course is not available online. I'm ready to go!

Ciao smile
In reply to Eloy Lafuente (stronk7)

Re: Important! insert_record() changes

by Martín Langhoff -
Thanks, but I think it's really undeserved. Your English is great ... now that you live in Spain. Come to NZ for a season and you'll write and talk way better than me. And I'm sure you'll like the place too wink

(BTW, today I'm a bit edgy due to severe sleep deprivation -- my earlier post should be taken with a pinch of salt. I'm at LCA and there's been some excitement here lately, as described here http://www.stuff.co.nz/stuff/0,2106,3551312a28,00.html . Between stressing about the git workshop and Google getting us all drunk, it's been a couple of nights of <4hs sleep. The workshop led to a brief programming session today in _good_ company -- and some small improvements to git.)
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Michael Penney -

Heh. Of course we didn't use this, but it was fun to think aboutwink.

Built in XUL on top of firefox...tongueout.

Attachment logoidea.jpg
In reply to Martín Langhoff

Re: insert_record() function changes...

by sam marshall -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers
Our modules and other OU changes already create tables which do not include an ID column. (Where they do contain one, it isn't always called 'id'.)

Though Moodle does indeed have a fixed style of its database, it's a somewhat interesting one, and most of us decided it preferable to follow good database design practice in our own tables. So we use the 'Moodle' style for tables Moodle owns (the module's main table for instance) but good practice elsewhere.

For example, we have tables which add data corresponding to items in two other tables. E.g. table 'gloob_items' has 3 columns, gloob (foreign key to 'gloobs'), course (foreign key to 'mdl_course'->id), and 'item' (foreign key to somewhere else). So the primary key is a combination of gloob and course. While I suppose we could add an unused ID field, that would frankly just waste database space and time.

So anyway, I don't particularly mind if insert_record is changed because obviously for that particular table we weren't using insert_record anyhow, it plain wouldn't work (we were using the methods in datalib that execute raw sql). But I think it would be a problem to require every table to follow the 'Moodle style'. In fact it would be worth considering a gradual change of that Moodle style, rather than solidifying it.

If it's a modular design, modules should have control of their own tables (with exception of the module main table, which Moodle uses directly). Modules should have control of their own database install (they do), uninstall (they don't), and backup and restore which I expect they do if you write backuplib.php etc but I haven't looked at that.

What are the consequences of having tables without an id field? For example, does this mean the 'default' backup facilities won't work (?) and you have to be careful when implementing backuplib.php for the module? That's cool, if it's documented.

--sam
In reply to sam marshall

Re: insert_record() function changes...

by Michael Penney -

What are the consequences of having tables without an id field?

Hmm, the consequences of using non-Moodle standard design may be descreased ability for others to test/help with your code and integrate it into the standard system and increased chance of forking.

IANADBA, just a PM, but I would suggest asking folks like Martin D and L why the db is designed the way it is before making changes, in some cases there may be a excellent reason that 'good practice' hasn't yet taken into account (IMO the Martins could write one of the best books on good practice if they had timesmile.

In reply to sam marshall

Re: insert_record() function changes...

by Michael Penney -
PS I suggest OU fly you to Australia and New Zealand asap to work out the best method for moving forward without forkingsmile.
In reply to Michael Penney

Re: insert_record() function changes...

by sam marshall -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers
The University flew the two Martins (on separate occasions) over here late last year to give us training, presentations, etc. - and argument opportunities, of course. smile

By the way, so far in these forums I think you've only seen the two of us, mys'elf and Tim Hunt. We are on the same team, which is tasked with implementing Moodle features so that it's capable of doing the things our existing course website system does, and with a very slightly similar editing workflow facility. Our first release in May isn't going to actually do much that's available in Moodle, it's just going to do what our existing sites do. After that the intention is to gradually use more Moodle features.

Also on that team are Alan Carter and Derek Woolhead, who haven't posted here yet (and might be described as less outspoken, perhaps); the four of us share an office. The other key team is Rod Norfor and Nick Freear; they are dealing with tools, automated testing, source control, and 'our side' of the database import process from University systems. These people are working full-time on OU/Moodle stuff; there are also a few other developers working on related issues which might become part of Moodle in future.

(For example the e-portfolio system, which is initially using an outside solution. However the person in charge of that is also looking at the options available for Moodle, for later consideration... his comment in a meeting, 'Everybody seems to want e-portfolio systems at the moment.' my comment 'Except students.' smile

As for forks, I somehow don't think our management will accept a fork any time soon! We've done a lot of planning for our initial changes (the set we're making now, for that May release) to minimise the points where we have to touch core code.

But there are still quite a lot of changes - some of which are simple bugfixes or very minor tweaks (like making the Javascript function that hides/shows form elements able to work even if you don't have hidden fields that record their status, so that you don't have to include the fields if you don't care), or relatively minor extensions that directly follow the spirit of existing interfaces (like the 'letting modules control file download' thing I posted about). Those kind of things we would definitely like to contribute to the core. The rest of our diff... well, I guess managing it is Rod's problem. smile

(It's not that bad... but it would be better if we could get rid of that 'ought to be in core and the Moodle community wouldn't even object to it' stuff. I think we're going to take some time, perhaps after we've finished the work for our May release when hopefully our source code management is in a better state, to look at the differences and check which ones are OK to put in core. My post about the modules/file download thing is a first step at that, for a moderately interesting change that shouldn't be controversial.)

--sam
In reply to sam marshall

Re: insert_record() function changes...

by Matt Oquist -
Hey Sam,

I'd love to be in touch with the person working on e-portfolios for you.  I'm working for my client to fulfill the New Hampshire, USA state requirements for students to have e-portfolios, but I'd like to know what your requirements are so, at the very least, I can keep them in mind as I work.
In reply to sam marshall

Re: insert_record() function changes...

by Martín Langhoff -
> What are the consequences of having tables without an id field?

Oh, just can't use datalib's core functions -- or rather, you can only use a subset. If you do that in custom modules/plugins, great! Within Moodle we have a few id-less tables, and they need special handling.

Backup support also gets tricky. You're unlikely to use Moodle's app-level backups as backups. But they are used for a lot of other things. Might be a good idea to do Moodle backups even for custom modules.

WRT the id vs no id debates... oh, well. Lets focus on effective code wink

> That's cool, if it's documented.

Documented Right Now. Hi GoogleBot! wink
(Link here and give us some googlejuice)
In reply to sam marshall

Re: insert_record() function changes...

by Martin Dougiamas -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers
Sam, have you read the coding guide?
In reply to Martin Dougiamas

Re: insert_record() function changes...

by sam marshall -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers
Yes, I've read it.

I think there are issues as to the way Moodle uses databases - the questionable use of IDs is certainly one, but the lack of referential integrity is more serious. [By the way, the '<table>id' convention suggested in the coding guidelines is at least a step up in this regard. We'll be following that one at least!]

There are of course big problems with adding referential integrity, for example if we add foreign key references to a courseid in some table, then we have to be sure the table entries get deleted by the course delete (either manually, which I think is probably better practice, or using the 'cascade' type things to make it automatically drop those rows if the course goes). So each time that happens it's a significant change and I can see why it hasn't happened (quite apart from issues like still supporting mysql 3).

Anyway so it isn't possible to address the database problems all at once but I think when making any changes we should ensure that we aren't shutting out the possibility for improvements in future. That was my initial concern with the changes to insert_record.

With respect to the initial subject of this thread though, having read the reasoning for it I think I can now agree with the decision to remove support for differently-named columns in insert_record. If get_record isn't going to work with tables that don't have an 'id' column, then it does make sense that insert_record won't allow it either; treat those utilities as a unit, so that you know that if you want to use one, you have to use the other.

If you're going to have to write SQL to access the table then you can deal with writing SQL to add items to it.

--sam
In reply to Martin Dougiamas

Re: insert_record() function changes...

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I clearly haven't re-read it recently enough. I had forgotten a few of the points. I am duly reminded.

And I think you have convinced me on the ID column thing.
In reply to Martín Langhoff

id column reasons - must be documented

by Ne Nashev -
id column reasons - must be documented once and for all times IMHO

http://docs.moodle.org/en/IdColumnReasons
Average of ratings: Useful (1)
In reply to Ne Nashev

Re: id column reasons - must be documented

by Martín Langhoff -
The real reference if the coding guide as MD said, and the (excellent) forum search will do the rest. (And googlebot too)

Having that wikipage is only good _if_ you're going to keep it up to date. If you don't keep it up to date it will just be old information claiming to be authoritative. Perhaps it's better to remove it.
In reply to Martín Langhoff

Re: if you keep it up to date

by Ne Nashev -
 I think wiki-engine was picked out to make document pages to be supported by all community.  I make a first step to document one vexed aspect of moodle style and i'll be adding to that page some reasons if it come to my eyes, but i think this page will be helpful for community even if it stay as is now.

And i will happy if some of the main moodle developers add to that page self comments and reasons!
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
And in any case, id-less are sooooo last century, that we don't care about them any more. So the 4th parameter is now deprecated.

Did this ever happen? I am just looking at insert_record from HEAD, and the 4th parameter is still sitting there with no indication that it is deprecated.

I think we should edit the function comment ASAP to mark this parameter deprecated, possibly with a link to this thread as explanation.

Then, shortly after 1.6 is realeased, we add code so that if you are in debug mode, and this function is called with a 4th parameter, you get a warning (probably generated with trigger_error('Call to insert_record() with a 4th parameter. This is strongly deprecated.');).
In reply to Tim Hunt

Re: Important! insert_record() changes

by Eloy Lafuente (stronk7) -
Picture of Core developers Picture of Documentation writers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers Picture of Testers
Agree,

anything against raising the trigger_error() from today (if the $primarykey parameter is different from "id") and changing the comments? (but leaving everything inside the function unmodified under 1.6 - changing it after branching 1.6).

Ciao smile
In reply to Eloy Lafuente (stronk7)

Re: Important! insert_record() changes

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Fine by me.

This postgres query should list all tables without an id column.

SELECT pc.relname
FROM pg_class AS pc
WHERE
    NOT EXISTS(SELECT pa.attname FROM pg_attribute AS pa
                WHERE pa.attname = 'id' AND pa.attrelid = pc.oid)
    AND pc.relkind = 'r'
    AND pc.relname LIKE 'mdl_%'
ORDER BY pc.relname

It only finds mdl_log_display and mdl_sessions.
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Mauricio Munera -

It's Funny, cos I was working creating a new functionality for the quiz module. I'm woring creating metadata for language teaching to the questions, the thing is that I used some tables without primary key 'id', so I made by my self the change in datalib.php, the thing is that then I saw the same function with the same changes posted, so for me that means that it is something like a plus in the code, for bad pleople like me, that don't follow the rule literaly some times.

My question is how I can share my single mutation in the module quiz, I want that the pleople that can find it usefull they can use that.

Greetings!!

In the attached image you can see, more or less, what I made.

Attachment flujoMetadatosQuiz.JPG
In reply to Martín Langhoff

Re: Important! insert_record() changes

by Mauricio Munera -

I wrote before about that I made that change by myself from before, but I see that in the new version, just the function insert_record() has the change with the new primarykey parameter but update_record() does not have the change...

What about it?

In reply to Martín Langhoff

Re: Important! insert_record() changes

by george alex -

hello! i'm a new beginner developer.  i've started using moodle for a project. i have an initial problem. i've added an element to the form of a resource, of type date_selector, and i need to insert to my db the values of that field in a record via insert_record function. how can i achieve this?

In reply to george alex

Re: Important! insert_record() changes

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

George, I don't think resurrecting a 6 year old thread is a good place to start. Take a look at http://docs.moodle.org/dev and then, if that does help you, come back to the forums and start a new thread outlining where exactly you are stuck.