public function save() { $this->_init(); $this->_process_filters(SRECORD_FILTER_BEFORE_SAVE); $was_new = $this->is_new(); if (!$this->is_dirty()) { $this->_process_filters(SRECORD_FILTER_AFTER_SAVE, array($was_new)); return; } if (!$was_new) { $fields = ''; $keyname = $this->_db_key; foreach ($this->_db_fields as $k => $dummy) { if ($k == $keyname) { continue; } $fields .= ($fields == '' ? '' : ',') . "@_f_{$k}=@_v_{$k}"; } $cmd = new SDBCommand("UPDATE @_db_table SET {$fields} WHERE @_fk_id=@_k_id LIMIT 1"); $cmd->set('_db_table', $this->_db_table, SDB::TableName); $cmd->set('_fk_id', $this->_db_key, SDB::FieldName); $cmd->set('_k_id', $this->{$keyname}, SDB::Int); foreach ($this->_db_fields as $k => $ts) { if ($k == $keyname) { continue; } $cmd->set("_f_{$k}", $ts['f'], SDB::FieldName); $cmd->set("_v_{$k}", $this->{$k}, $ts['t'], $ts['s']); } if (!$cmd->execute()) { // is_new can return invalid values, if PK is not autoincremented, and PK is not null // in such cases update will be executed instead of insert // so if update failed, try to insert instead // *but* update will also failed, if no fields is updated and _use_dirty is false // so double-check for new record $cmd = new SDBCommand("SELECT @_fk_id FROM @_db_table WHERE @_fk_id=@_k_id LIMIT 1"); $cmd->set('_db_table', $this->_db_table, SDB::TableName); $cmd->set('_fk_id', $this->_db_key, SDB::FieldName); $cmd->set('_k_id', $this->{$keyname}, SDB::Int); $was_new = $cmd->get_row() == null; } } if ($was_new) { $fields = ''; $values = ''; foreach ($this->_db_fields as $k => $dummy) { if ($k == $this->_db_key && $this->{$k} === null) { continue; } $fields .= ($fields == '' ? '' : ',') . "@_f_{$k}"; $values .= ($values == '' ? '' : ',') . "@{$k}"; } $cmd = new SDBCommand("INSERT INTO @_db_table ({$fields}) VALUES ({$values})"); $cmd->set('_db_table', $this->_db_table, SDB::TableName); foreach ($this->_db_fields as $k => $ts) { if ($k == $this->_db_key && $this->{$k} === null) { continue; } $cmd->set("_f_{$k}", $ts['f'], SDB::FieldName); $cmd->set($k, $this->{$k}, $ts['t'], $ts['s']); } $keyname = $this->_db_key; $this->{$keyname} = $cmd->insert(); } if ($this->_use_dirty) { foreach ($this->_db_fields as $prop => $ts) { $this->_db_prev_value[$prop] = $this->{$prop}; } } $this->_process_filters(SRECORD_FILTER_AFTER_SAVE, array($was_new)); }