Getting the inserted record id

Getting the inserted record id

by Ahmed Nabil -
Number of replies: 6

Hi Martin

I create new module and I used this function insert_record() to insert record to some table with auto increment field called id.

insert_record() return record id but when i try to refresh the page that receive the form variables I get the old id not new one.

Now, how could I get the inserted record id using moodle APIs even if the user refresh page?

 

ana

 

Average of ratings: -
In reply to Ahmed Nabil

Re: Getting the inserted record id

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
I'm not sure, but it does sound like browser caching ... insert_record() should always insert a new record whenever it is called with a data object and a table.

I'd have to see your code to learn more.
In reply to Martin Dougiamas

Re: Getting the inserted record id

by Ahmed Nabil -

Yes, insert_record() insert a new record each time I refresh the page that receive the form data and I found repeated records at the table but the returned id is always the first one not the current.

I attached the code and you will find the  insert_record() at line 33

ana

In reply to Ahmed Nabil

Re: Getting the inserted record id

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
Ah, I see.

If you look at insert_record() you'll see that the id is obtained via a SELECT right at the end (because this is most reliable way I could find that works on any database).

However, if you have a table that contains:

id   name    comment
1    aaa     bbb
2    aaa     bbb
3    aaa     bbb
where multiple records are exactly the same, then the SELECT may grab another one and thus return the wrong ID.

The simple fix in this case is to add a field with a unique code of some sort, like a timestamp. I always use time(). Timestamps are very useful anyway when reconstructing logs etc.

Cheers!
Martin

In reply to Martin Dougiamas

Re: Getting the inserted record id

by Greg Barnett -
I believe I have a fix for non-unique records.

In contrib/crown_college/phproof I have added a test which can (if run enough times when the stars align just right) catch this intermittent bug.

Here is the slightly modified insert_record function that ought to do the trick (I have not committed this to CVS):

function insert_record($table, $dataobject, $returnid=true) {
/// Insert a record into a table and return the "id" field if required
/// If the return ID isn't required, then this just reports success as true/false.
/// $dataobject is an object containing needed data

global $db, $CFG;

// Determine all the fields needed
if (! $columns = $db->MetaColumns("$CFG->prefix$table")) {
return false;
}

$data = (array)$dataobject;

// Pull out data matching these fields
foreach ($columns as $column) {
if ($column->name "id" && isset($data[$column->name]) ) {
$ddd[$column->name] = $data[$column->name];
}
}

// Construct SQL queries
if (! $numddd = count($ddd)) {
return false;
}

$count = 0;
$inscolumns = "";
$insvalues = "";
$select = "";

foreach ($ddd as $key => $value) {
$count++;
$inscolumns .= "$key";
$insvalues .= "'$value'";
$select .= "$key = '$value'";
if ($count Execute("INSERT INTO $CFG->prefix$table ($inscolumns) VALUES ($insvalues)")) {
return false;
}

if ($returnid) {
if ($db->hasInsertID) {
return $db->Insert_ID();
// Pull it out again to find the id. This is the most cross-platform method.
} elseif ($rs = $db->Execute("SELECT id FROM $CFG->prefix$table WHERE $select")) {
if ($rs->RecordCount() == 1) {
return $rs->fields[0];
} else {
return false;
}
} else {
return false;
}
} else {
return true;
}
}
In reply to Greg Barnett

Re: Getting the inserted record id

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
Ah, well done. smile The ADOdb variable hasInsertID wasn't there last time I looked. This fix will definitely be in 1.0.8.