UnitOfWork.php 20.6 KB
Newer Older
1
<?php
lsmith's avatar
lsmith committed
2
/*
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *  $Id$
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information, see
 * <http://www.phpdoctrine.com>.
 */
21
Doctrine::autoload('Doctrine_Connection_Module');
22
/**
zYne's avatar
zYne committed
23
 * Doctrine_Connection_UnitOfWork
24
 *
25
 * @package     Doctrine
26
 * @subpackage  Connection
27 28 29 30 31 32
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link        www.phpdoctrine.com
 * @since       1.0
 * @version     $Revision$
 * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
 */
zYne's avatar
zYne committed
33
class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
lsmith's avatar
lsmith committed
34
{
35 36 37
    /**
     * buildFlushTree
     * builds a flush tree that is used in transactions
lsmith's avatar
lsmith committed
38
     *
39
     * The returned array has all the initialized components in
lsmith's avatar
lsmith committed
40
     * 'correct' order. Basically this means that the records of those
41
     * components can be saved safely in the order specified by the returned array.
42
     *
zYne's avatar
zYne committed
43 44
     * @param array $tables     an array of Doctrine_Table objects or component names
     * @return array            an array of component names in flushing order
45
     */
lsmith's avatar
lsmith committed
46 47
    public function buildFlushTree(array $tables)
    {
48
        $tree = array();
lsmith's avatar
lsmith committed
49
        foreach ($tables as $k => $table) {
zYne's avatar
zYne committed
50

lsmith's avatar
lsmith committed
51
            if ( ! ($table instanceof Doctrine_Table)) {
52
                $table = $this->conn->getTable($table, false);
lsmith's avatar
lsmith committed
53
            }
54 55
            $nm     = $table->getComponentName();

zYne's avatar
zYne committed
56
            $index  = array_search($nm, $tree);
57

lsmith's avatar
lsmith committed
58
            if ($index === false) {
59 60 61 62 63
                $tree[] = $nm;
                $index  = max(array_keys($tree));
            }

            $rels = $table->getRelations();
lsmith's avatar
lsmith committed
64

65
            // group relations
lsmith's avatar
lsmith committed
66 67 68

            foreach ($rels as $key => $rel) {
                if ($rel instanceof Doctrine_Relation_ForeignKey) {
69 70 71 72 73
                    unset($rels[$key]);
                    array_unshift($rels, $rel);
                }
            }

lsmith's avatar
lsmith committed
74
            foreach ($rels as $rel) {
75 76 77 78 79
                $name   = $rel->getTable()->getComponentName();
                $index2 = array_search($name,$tree);
                $type   = $rel->getType();

                // skip self-referenced relations
zYne's avatar
zYne committed
80
                if ($name === $nm) {
81
                    continue;
82
                }
83

lsmith's avatar
lsmith committed
84 85 86
                if ($rel instanceof Doctrine_Relation_ForeignKey) {
                    if ($index2 !== false) {
                        if ($index2 >= $index)
87 88 89 90 91 92 93 94 95
                            continue;

                        unset($tree[$index]);
                        array_splice($tree,$index2,0,$nm);
                        $index = $index2;
                    } else {
                        $tree[] = $name;
                    }

lsmith's avatar
lsmith committed
96 97 98
                } elseif ($rel instanceof Doctrine_Relation_LocalKey) {
                    if ($index2 !== false) {
                        if ($index2 <= $index)
99 100 101 102 103 104 105 106
                            continue;

                        unset($tree[$index2]);
                        array_splice($tree,$index,0,$name);
                    } else {
                        array_unshift($tree,$name);
                        $index++;
                    }
lsmith's avatar
lsmith committed
107
                } elseif ($rel instanceof Doctrine_Relation_Association) {
108 109
                    $t = $rel->getAssociationFactory();
                    $n = $t->getComponentName();
lsmith's avatar
lsmith committed
110 111

                    if ($index2 !== false)
112
                        unset($tree[$index2]);
lsmith's avatar
lsmith committed
113

zYne's avatar
zYne committed
114
                    array_splice($tree, $index, 0, $name);
115 116
                    $index++;

zYne's avatar
zYne committed
117
                    $index3 = array_search($n, $tree);
118

lsmith's avatar
lsmith committed
119 120
                    if ($index3 !== false) {
                        if ($index3 >= $index)
121 122 123
                            continue;

                        unset($tree[$index]);
zYne's avatar
zYne committed
124
                        array_splice($tree, $index3, 0, $n);
125 126 127 128 129 130 131 132 133
                        $index = $index2;
                    } else {
                        $tree[] = $n;
                    }
                }
            }
        }
        return array_values($tree);
    }
zYne's avatar
zYne committed
134 135 136 137 138 139 140 141
    /**
     * saves the given record
     *
     * @param Doctrine_Record $record
     * @return void
     */
    public function saveGraph(Doctrine_Record $record)
    {
142
        $conn = $this->getConnection();
zYne's avatar
zYne committed
143

zYne's avatar
zYne committed
144 145
        $state = $record->state();
        if ($state === Doctrine_Record::STATE_LOCKED) {
146 147 148
            return false;
        }

zYne's avatar
zYne committed
149
        $record->state(Doctrine_Record::STATE_LOCKED);
zYne's avatar
zYne committed
150 151

        $conn->beginTransaction();
152

zYne's avatar
zYne committed
153 154
        $saveLater = $this->saveRelated($record);

zYne's avatar
zYne committed
155 156
        $record->state($state);

zYne's avatar
zYne committed
157
        if ($record->isValid()) {
zYne's avatar
zYne committed
158
            $event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
zYne's avatar
zYne committed
159

zYne's avatar
zYne committed
160 161 162
            $record->preSave($event);
    
            $record->getTable()->getRecordListener()->preSave($event);
zYne's avatar
zYne committed
163

zYne's avatar
zYne committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
            if ( ! $event->skipOperation) {
                switch ($state) {
                    case Doctrine_Record::STATE_TDIRTY:
                        $this->insert($record);
                        break;
                    case Doctrine_Record::STATE_DIRTY:
                    case Doctrine_Record::STATE_PROXY:
                        $this->update($record);
                        break;
                    case Doctrine_Record::STATE_CLEAN:
                    case Doctrine_Record::STATE_TCLEAN:

                        break;
                }
            }
zYne's avatar
zYne committed
179

zYne's avatar
zYne committed
180 181 182
            $record->getTable()->getRecordListener()->postSave($event);
            
            $record->postSave($event);
zYne's avatar
zYne committed
183 184 185
        } else {
            $conn->transaction->addInvalid($record);
        }
186

zYne's avatar
zYne committed
187 188 189
        $state = $record->state();

        $record->state(Doctrine_Record::STATE_LOCKED);
zYne's avatar
zYne committed
190 191 192 193 194 195

        foreach ($saveLater as $fk) {
            $alias = $fk->getAlias();

            if ($record->hasReference($alias)) {
                $obj = $record->$alias;
zYne's avatar
zYne committed
196
                
zYne's avatar
zYne committed
197 198
                // check that the related object is not an instance of Doctrine_Null
                if ( ! ($obj instanceof Doctrine_Null)) {
zYne's avatar
zYne committed
199 200
                    $obj->save($conn);
                }
zYne's avatar
zYne committed
201 202 203 204 205 206
            }
        }

        // save the MANY-TO-MANY associations
        $this->saveAssociations($record);

zYne's avatar
zYne committed
207 208
        $record->state($state);

zYne's avatar
zYne committed
209
        $conn->commit();
zYne's avatar
zYne committed
210

211
        return true;
zYne's avatar
zYne committed
212
    }
zYne's avatar
zYne committed
213 214 215 216 217 218 219 220
    /**
     * saves the given record
     *
     * @param Doctrine_Record $record
     * @return void
     */
    public function save(Doctrine_Record $record)
    {
221
        $event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
zYne's avatar
zYne committed
222

zYne's avatar
zYne committed
223
        $record->preSave($event);
zYne's avatar
zYne committed
224

225 226
        $record->getTable()->getRecordListener()->preSave($event);

227
        if ( ! $event->skipOperation) {
zYne's avatar
zYne committed
228 229 230 231 232 233 234 235 236 237 238 239 240
            switch ($record->state()) {
                case Doctrine_Record::STATE_TDIRTY:
                    $this->insert($record);
                    break;
                case Doctrine_Record::STATE_DIRTY:
                case Doctrine_Record::STATE_PROXY:
                    $this->update($record);
                    break;
                case Doctrine_Record::STATE_CLEAN:
                case Doctrine_Record::STATE_TCLEAN:
                    // do nothing
                    break;
            }
zYne's avatar
zYne committed
241
        }
zYne's avatar
zYne committed
242

243 244
        $record->getTable()->getRecordListener()->postSave($event);
        
zYne's avatar
zYne committed
245
        $record->postSave($event);
zYne's avatar
zYne committed
246 247
    }
    /**
zYne's avatar
zYne committed
248
     * deletes given record and all the related composites
zYne's avatar
zYne committed
249 250 251 252 253 254 255 256 257 258 259 260 261
     * this operation is isolated by a transaction
     *
     * this event can be listened by the onPreDelete and onDelete listeners
     *
     * @return boolean      true on success, false on failure
     */
    public function delete(Doctrine_Record $record)
    {
        if ( ! $record->exists()) {
            return false;
        }
        $this->conn->beginTransaction();

262
        $event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE);
zYne's avatar
zYne committed
263 264

        $record->preDelete($event);
265
        
266 267
        $record->getTable()->getRecordListener()->preDelete($event);

268 269
        $state = $record->state();

270
        $record->state(Doctrine_Record::STATE_LOCKED);
zYne's avatar
zYne committed
271 272 273

        $this->deleteComposites($record);

274
        if ( ! $event->skipOperation) {
275 276 277
            $record->state(Doctrine_Record::STATE_TDIRTY);

            $this->deleteRecord($record);
zYne's avatar
zYne committed
278

zYne's avatar
zYne committed
279
            $record->state(Doctrine_Record::STATE_TCLEAN);
280 281 282
        } else {
            // return to original state   
            $record->state($state);
zYne's avatar
zYne committed
283
        }
284 285


286 287
        $record->getTable()->getRecordListener()->postDelete($event);

zYne's avatar
zYne committed
288
        $record->postDelete($event);
zYne's avatar
zYne committed
289 290 291 292 293

        $this->conn->commit();

        return true;
    }
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
    
    public function deleteRecord(Doctrine_Record $record)
    {
        $ids = $record->identifier();
        $tmp = array();
        
        foreach (array_keys($ids) as $id) {
            $tmp[] = $id . ' = ? ';
        }
        
        $params = array_values($ids);

        $query = 'DELETE FROM '
               . $this->conn->quoteIdentifier($record->getTable()->getTableName())
               . ' WHERE ' . implode(' AND ', $tmp);


        return $this->conn->exec($query, $params);
    }
    /**
     * deleteMultiple
     * deletes all records from the pending delete list
     *
     * @return void
     */
    public function deleteMultiple(array $records)
    {
321

322 323 324 325
        foreach ($this->delete as $name => $deletes) {
            $record = false;
            $ids    = array();

326
            if (is_array($deletes[count($deletes)-1]->getTable()->getIdentifier())) {
327 328 329 330 331 332 333 334 335 336
                if (count($deletes) > 0) {
                    $query = 'DELETE FROM '
                           . $this->conn->quoteIdentifier($deletes[0]->getTable()->getTableName())
                           . ' WHERE ';
    
                    $params = array();
                    $cond = array();
                    foreach ($deletes as $k => $record) {
                        $ids = $record->identifier();
                        $tmp = array();
337
                        foreach (array_keys($ids) as $id) {
338 339 340 341 342 343 344 345 346
                            $tmp[] = $id . ' = ? ';
                        }
                        $params = array_merge($params, array_values($ids));
                        $cond[] = '(' . implode(' AND ', $tmp) . ')';
                    }
                    $query .= implode(' OR ', $cond);

                    $this->conn->execute($query, $params);
                }
347 348
            } else {
                foreach ($deletes as $k => $record) {
349
                    $ids[] = $record->getIncremented();
350 351 352
                }
                if ($record instanceof Doctrine_Record) {
                    $params = substr(str_repeat('?, ', count($ids)), 0, -2);
353
    
354 355 356 357 358
                    $query = 'DELETE FROM '
                           . $this->conn->quoteIdentifier($record->getTable()->getTableName())
                           . ' WHERE '
                           . $record->getTable()->getIdentifier()
                           . ' IN(' . $params . ')';
359
        
360 361 362
                    $this->conn->execute($query, $ids);
                }
            }
363 364
        }
    }
365 366 367 368
    /**
     * saveRelated
     * saves all related records to $record
     *
zYne's avatar
zYne committed
369
     * @throws PDOException         if something went wrong at database level
370 371
     * @param Doctrine_Record $record
     */
lsmith's avatar
lsmith committed
372 373
    public function saveRelated(Doctrine_Record $record)
    {
374
        $saveLater = array();
zYne's avatar
zYne committed
375
        foreach ($record->getReferences() as $k => $v) {
zYne's avatar
zYne committed
376
            $rel = $record->getTable()->getRelation($k);
377

zYne's avatar
zYne committed
378 379
            $local = $rel->getLocal();
            $foreign = $rel->getForeign();
zYne's avatar
zYne committed
380

zYne's avatar
zYne committed
381
            if ($rel instanceof Doctrine_Relation_ForeignKey) {
zYne's avatar
zYne committed
382
                $saveLater[$k] = $rel;
zYne's avatar
zYne committed
383 384 385 386 387 388 389 390
            } elseif ($rel instanceof Doctrine_Relation_LocalKey) {
                // ONE-TO-ONE relationship
                $obj = $record->get($rel->getAlias());

                // Protection against infinite function recursion before attempting to save
                if ($obj instanceof Doctrine_Record &&
                    $obj->isModified()) {
                    $obj->save($this->conn);
zYne's avatar
zYne committed
391 392 393 394 395 396 397
                    /**
                    $id = array_values($obj->identifier());

                    foreach ((array) $rel->getLocal() as $k => $field) {
                        $record->set($field, $id[$k]);
                    }
                    */
398
                }
399 400
            }
        }
401

402 403 404 405
        return $saveLater;
    }
    /**
     * saveAssociations
lsmith's avatar
lsmith committed
406 407
     *
     * this method takes a diff of one-to-many / many-to-many original and
408 409 410 411 412 413 414
     * current collections and applies the changes
     *
     * for example if original many-to-many related collection has records with
     * primary keys 1,2 and 3 and the new collection has records with primary keys
     * 3, 4 and 5, this method would first destroy the associations to 1 and 2 and then
     * save new associations to 4 and 5
     *
415
     * @throws Doctrine_Connection_Exception         if something went wrong at database level
416 417 418
     * @param Doctrine_Record $record
     * @return void
     */
lsmith's avatar
lsmith committed
419 420
    public function saveAssociations(Doctrine_Record $record)
    {
zYne's avatar
zYne committed
421 422
        foreach ($record->getReferences() as $k => $v) {
            $rel = $record->getTable()->getRelation($k);
zYne's avatar
zYne committed
423
            
zYne's avatar
zYne committed
424
            if ($rel instanceof Doctrine_Relation_Association) {   
zYne's avatar
zYne committed
425
                $v->save($this->conn);
zYne's avatar
zYne committed
426

zYne's avatar
zYne committed
427 428 429 430 431 432
                $assocTable = $rel->getAssociationTable();
                foreach ($v->getDeleteDiff() as $r) {
                    $query = 'DELETE FROM ' . $assocTable->getTableName()
                           . ' WHERE ' . $rel->getForeign() . ' = ?'
                           . ' AND ' . $rel->getLocal() . ' = ?';

zYne's avatar
zYne committed
433
                    $this->conn->execute($query, array($r->getIncremented(), $record->getIncremented()));
zYne's avatar
zYne committed
434
                }
zYne's avatar
zYne committed
435

zYne's avatar
zYne committed
436 437 438 439
                foreach ($v->getInsertDiff() as $r) {
                    $assocRecord = $assocTable->create();
                    $assocRecord->set($rel->getForeign(), $r);
                    $assocRecord->set($rel->getLocal(), $record);
zYne's avatar
zYne committed
440 441

                    $this->saveGraph($assocRecord);
zYne's avatar
zYne committed
442 443
                }
            }
444 445 446 447 448 449
        }
    }
    /**
     * deletes all related composites
     * this method is always called internally when a record is deleted
     *
zYne's avatar
zYne committed
450
     * @throws PDOException         if something went wrong at database level
451 452
     * @return void
     */
lsmith's avatar
lsmith committed
453 454
    public function deleteComposites(Doctrine_Record $record)
    {
lsmith's avatar
lsmith committed
455
        foreach ($record->getTable()->getRelations() as $fk) {
456 457 458 459 460 461 462 463
            if ($fk->isComposite()) {
                $obj = $record->get($fk->getAlias());
                if ( $obj instanceof Doctrine_Record && 
                     $obj->state() != Doctrine_Record::STATE_LOCKED)  {

                    $obj->delete($this->conn);

                }
zYne's avatar
zYne committed
464
            }
465 466
        }
    }
zYne's avatar
zYne committed
467
    /**
lsmith's avatar
lsmith committed
468
     * saveAll
zYne's avatar
zYne committed
469 470 471 472 473
     * persists all the pending records from all tables
     *
     * @throws PDOException         if something went wrong at database level
     * @return void
     */
lsmith's avatar
lsmith committed
474 475
    public function saveAll()
    {
zYne's avatar
zYne committed
476 477 478 479
        // get the flush tree
        $tree = $this->buildFlushTree($this->conn->getTables());

        // save all records
lsmith's avatar
lsmith committed
480
        foreach ($tree as $name) {
zYne's avatar
zYne committed
481 482
            $table = $this->conn->getTable($name);

lsmith's avatar
lsmith committed
483
            foreach ($table->getRepository() as $record) {
zYne's avatar
zYne committed
484
                $this->save($record);
zYne's avatar
zYne committed
485 486
            }
        }
lsmith's avatar
lsmith committed
487

zYne's avatar
zYne committed
488
        // save all associations
lsmith's avatar
lsmith committed
489
        foreach ($tree as $name) {
zYne's avatar
zYne committed
490 491
            $table = $this->conn->getTable($name);

lsmith's avatar
lsmith committed
492
            foreach ($table->getRepository() as $record) {
zYne's avatar
zYne committed
493 494 495 496
                $this->saveAssociations($record);
            }
        }
    }
497
    /**
498
     * update
499 500
     * updates the given record
     *
501 502
     * @param Doctrine_Record $record   record to be updated
     * @return boolean                  whether or not the update was successful
503
     */
lsmith's avatar
lsmith committed
504 505
    public function update(Doctrine_Record $record)
    {
506
        $event = new Doctrine_Event($record, Doctrine_Event::RECORD_UPDATE);
zYne's avatar
zYne committed
507

zYne's avatar
zYne committed
508
        $record->preUpdate($event);
509

510
        $record->getTable()->getRecordListener()->preUpdate($event);
zYne's avatar
zYne committed
511

512
        if ( ! $event->skipOperation) {
zYne's avatar
zYne committed
513
            $array = $record->getPrepared();
zYne's avatar
zYne committed
514

zYne's avatar
zYne committed
515 516 517
            if (empty($array)) {
                return false;
            }
518
            $set = array();
zYne's avatar
zYne committed
519
            foreach ($array as $name => $value) {
520 521 522 523 524 525
                if ($value instanceof Doctrine_Expression) {
                    $set[] = $value->getSql();
                    unset($array[$name]);
                } else {

                    $set[] = $name . ' = ?';
zYne's avatar
zYne committed
526
    
527 528 529 530 531 532
                    if ($value instanceof Doctrine_Record) {
                        if ( ! $value->exists()) {
                            $record->save($this->conn);
                        }
                        $array[$name] = $value->getIncremented();
                        $record->set($name, $value->getIncremented());
zYne's avatar
zYne committed
533
                    }
534
                }
535
            }
zYne's avatar
zYne committed
536

zYne's avatar
zYne committed
537
            $params = array_values($array);
538
            $id     = $record->identifier();
zYne's avatar
zYne committed
539 540 541 542 543 544 545 546 547
    
            if ( ! is_array($id)) {
                $id = array($id);
            }
            $id     = array_values($id);
            $params = array_merge($params, $id);
    
            $sql  = 'UPDATE ' . $this->conn->quoteIdentifier($record->getTable()->getTableName())
                  . ' SET ' . implode(', ', $set)
zYne's avatar
zYne committed
548
                  . ' WHERE ' . implode(' = ? AND ', (array) $record->getTable()->getIdentifier())
zYne's avatar
zYne committed
549 550
                  . ' = ?';
    
zYne's avatar
zYne committed
551
            $stmt = $this->conn->prepare($sql);
zYne's avatar
zYne committed
552 553 554
            $stmt->execute($params);
    
            $record->assignIdentifier(true);
555
        }
556 557 558
        
        $record->getTable()->getRecordListener()->postUpdate($event);

zYne's avatar
zYne committed
559
        $record->postUpdate($event);
zYne's avatar
zYne committed
560

561 562 563 564 565 566 567 568
        return true;
    }
    /**
     * inserts a record into database
     *
     * @param Doctrine_Record $record   record to be inserted
     * @return boolean
     */
lsmith's avatar
lsmith committed
569 570
    public function insert(Doctrine_Record $record)
    {
571
         // listen the onPreInsert event
572
        $event = new Doctrine_Event($record, Doctrine_Event::RECORD_INSERT);
zYne's avatar
zYne committed
573 574

        $record->preInsert($event);
zYne's avatar
zYne committed
575
        
576 577
        $record->getTable()->getRecordListener()->preInsert($event);

578
        if ( ! $event->skipOperation) {
zYne's avatar
zYne committed
579 580 581 582
            $array = $record->getPrepared();
    
            if (empty($array)) {
                return false;
583
            }
zYne's avatar
zYne committed
584
            $table     = $record->getTable();
zYne's avatar
zYne committed
585
            $keys      = (array) $table->getIdentifier();
zYne's avatar
zYne committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599
    
            $seq       = $record->getTable()->sequenceName;
    
            if ( ! empty($seq)) {
                $id             = $this->conn->sequence->nextId($seq);
                $name           = $record->getTable()->getIdentifier();
                $array[$name]   = $id;
    
                $record->assignIdentifier($id);
            }
    
            $this->conn->insert($table->getTableName(), $array);
    
            if (empty($seq) && count($keys) == 1 && $keys[0] == $table->getIdentifier() &&
zYne's avatar
zYne committed
600
                $table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) {
zYne's avatar
zYne committed
601 602 603 604 605 606 607 608
    
                if (strtolower($this->conn->getName()) == 'pgsql') {
                    $seq = $table->getTableName() . '_' . $keys[0];
                }
    
                $id = $this->conn->sequence->lastInsertId($seq);
    
                if ( ! $id) {
zYne's avatar
zYne committed
609
                    throw new Doctrine_Connection_Exception("Couldn't get last insert identifier.");
zYne's avatar
zYne committed
610 611 612 613 614
                }
    
                $record->assignIdentifier($id);
            } else {
                $record->assignIdentifier(true);
zYne's avatar
zYne committed
615
            }
lsmith's avatar
lsmith committed
616
        }
617 618
        $record->getTable()->addRecord($record);

619 620
        $record->getTable()->getRecordListener()->postInsert($event);

zYne's avatar
zYne committed
621
        $record->postInsert($event);
zYne's avatar
zYne committed
622

623 624
        return true;
    }
zYne's avatar
zYne committed
625
}