0010820: fix non-autoincrement integer id column for pgsql
authorLars Kneschke <l.kneschke@metaways.de>
Wed, 25 Feb 2015 07:21:09 +0000 (08:21 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Wed, 25 Feb 2015 11:36:21 +0000 (12:36 +0100)
https://forge.tine20.org/view.php?id=10820

Change-Id: I8d18906196fb407fb6628913eecf58d562c7419d
Reviewed-on: http://gerrit.tine20.com/customers/1690
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tine20/Tinebase/Backend/Sql/Abstract.php
tine20/Tinebase/Record/Interface.php

index 99305a2..a260bdf 100644 (file)
@@ -920,15 +920,14 @@ abstract class Tinebase_Backend_Sql_Abstract extends Tinebase_Backend_Abstract i
             }
             
             // set uid if record has hash id and id is empty
-            if ($this->_hasHashId() && empty($_record->$identifier)) {
-                $newId = $_record->generateUID();
-                $_record->setId($newId);
+            if (empty($_record->$identifier) && $this->_hasHashId()) {
+                $_record->setId($_record->generateUID());
             }
             
             $recordArray = $this->_recordToRawData($_record);
             
             // unset id if autoincrement & still empty
-            if (empty($_record->$identifier) || $_record->$identifier == 'NULL' ) {
+            if ($this->_hasAutoIncrementId() || $_record->$identifier == 'NULL' ) {
                 unset($recordArray['id']);
             }
             
@@ -936,26 +935,22 @@ abstract class Tinebase_Backend_Sql_Abstract extends Tinebase_Backend_Abstract i
             
             $this->_prepareData($recordArray);
             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__
-                    . " Prepared data for INSERT: " . print_r($recordArray, true)
+                . " Prepared data for INSERT: " . print_r($recordArray, true)
             );
             
             $this->_db->insert($this->_tablePrefix . $this->_tableName, $recordArray);
             
-            if (!$this->_hasHashId()) {
+            if ($this->_hasAutoIncrementId()) {
                 $newId = $this->_db->lastInsertId($this->getTablePrefix() . $this->getTableName(), $identifier);
-                if(!$newId && isset($_record[$identifier])){
-                    $newId = $_record[$identifier];
+                if (!$newId) {
+                    throw new Tinebase_Exception_UnexpectedValue("New record auto increment id is empty");
                 }
+                $_record->setId($newId);
             }
             
             // if we insert a record without an id, we need to get back one
-            if (empty($_record->$identifier) && $newId == 0) {
-                throw new Tinebase_Exception_UnexpectedValue("Returned record id is 0.");
-            }
-            
-            // if the record had no id set, set the id now
-            if ($_record->$identifier == NULL || $_record->$identifier == 'NULL') {
-                $_record->$identifier = $newId;
+            if (empty($_record->$identifier)) {
+                throw new Tinebase_Exception_UnexpectedValue("Returned record id is empty.");
             }
             
             // add custom fields
@@ -987,10 +982,84 @@ abstract class Tinebase_Backend_Sql_Abstract extends Tinebase_Backend_Abstract i
     protected function _hasHashId()
     {
         $identifier = $this->_getRecordIdentifier();
-        $schema = $this->getSchema();
-        $result = (in_array($schema[$identifier]['DATA_TYPE'], array('varchar', 'VARCHAR2')) && $schema[$identifier]['LENGTH'] == 40);
+        $schema     = $this->getSchema();
         
-        return $result;
+        if (!isset($schema[$identifier])) {
+            // should never happen
+            return false;
+        }
+        
+        $column = $schema[$identifier];
+        
+        if (!in_array($column['DATA_TYPE'], array('varchar', 'VARCHAR2'))) {
+            return false;
+        }
+        
+        return ($column['LENGTH'] == 40);
+    }
+    
+    /**
+     * returns true if id is an autoincrementing column
+     * 
+     * IDENTITY is 1 for auto increment columns
+     * 
+     * MySQL
+     * 
+     * Array (
+        [SCHEMA_NAME] => 
+        [TABLE_NAME] => tine20_container
+        [COLUMN_NAME] => id
+        [COLUMN_POSITION] => 1
+        [DATA_TYPE] => int
+        [DEFAULT] => 
+        [NULLABLE] => 
+        [LENGTH] => 
+        [SCALE] => 
+        [PRECISION] => 
+        [UNSIGNED] => 1
+        [PRIMARY] => 1
+        [PRIMARY_POSITION] => 1
+        [IDENTITY] => 1
+     * )
+     * 
+     * PostgreSQL
+     * 
+     * Array (
+        [SCHEMA_NAME] => public
+        [TABLE_NAME] => tine20_container
+        [COLUMN_NAME] => id
+        [COLUMN_POSITION] => 1
+        [DATA_TYPE] => int4
+        [DEFAULT] => nextval('tine20_container_id_seq'::regclass)
+        [NULLABLE] => 
+        [LENGTH] => 4
+        [SCALE] => 
+        [PRECISION] => 
+        [UNSIGNED] => 
+        [PRIMARY] => 1
+        [PRIMARY_POSITION] => 1
+        [IDENTITY] => 1
+     * )
+     * 
+     * @return boolean
+     */
+    protected function _hasAutoIncrementId()
+    {
+        $identifier = $this->_getRecordIdentifier();
+        $schema     = $this->getSchema();
+        
+        if (!isset($schema[$identifier])) {
+            // should never happen
+            return false;
+        }
+        
+        $column = $schema[$identifier];
+        
+        if (!in_array($column['DATA_TYPE'], array('int', 'int4'))) {
+            return false;
+        }
+        
+        return !!$column['IDENTITY'];
     }
     
     /**
index 2b8e668..ca7362d 100644 (file)
@@ -53,6 +53,13 @@ interface Tinebase_Record_Interface extends ArrayAccess, IteratorAggregate
     public function getId();
     
     /**
+     * returns id property of this model
+     *
+     * @return string
+     */
+    public function getIdProperty();
+    
+    /**
      * gets application the records belongs to
      * 
      * @return string application