private function saveTable(
        $model,
        $forceInsert = false,
        $forceUpdate = false,
        $updateFields = null
    ) {
        $meta = $this->getMeta();

        /** @var $nonPkFields Field[] */
        $nonPkFields = [];

        /** @var $field Field */
        foreach ($meta->getConcreteFields() as $name => $field) {
            if ($field->primaryKey) {
                continue;
            }
            $nonPkFields[$name] = $field;
        }

        // if any fields we passed in use those
        /** @var $nonePkUpdateFields Field[] */
        $nonePkUpdateFields = [];

        if ($updateFields) {
            foreach ($nonPkFields as $nonPkField) {
                if (in_array($nonPkField->getName(), $updateFields)) {
                    $nonePkUpdateFields[$nonPkField->getName()] = $nonPkField;
                } elseif (in_array($nonPkField->getAttrName(), $updateFields)) {
                    $nonePkUpdateFields[$nonPkField->getAttrName()] = $nonPkField;
                }
            }
        } else {
            $nonePkUpdateFields = $nonPkFields;
        }

        // get pk value
        $pkValue = $this->getPkValue($meta);
        $pkSet = (false === empty($pkValue));

        if (!$pkSet && ($forceUpdate || $forceInsert)) {
            throw new ValueError(
                'Cannot force an update in '.
                'save() with no primary key.'
            );
        }

        $updated = false;

        if ($pkSet && !$forceInsert) {
            $values = [];
            foreach ($nonePkUpdateFields as $nonePkUpdateField) {
                $values[] = [
                    $nonePkUpdateField,
                    null, //model should go here
                    $nonePkUpdateField->preSave($this, false),
                ];
            }

            $updated = $this->doUpdate($values, $pkValue, $forceUpdate);
        }

        if (false === $updated) {
            /* @var $field $concreteField */
            $concreteFields = $meta->getConcreteFields();
            $fields = [];
            foreach ($concreteFields as $name => $concreteField) {
                // skip AutoFields their value is auto created by the database.
                if ($concreteField instanceof AutoField) {
                    continue;
                }
                $fields[$name] = $concreteField;
            }

            $updatePk = ($meta->hasAutoField && !$pkSet);

            $result = $this->doInsert($this, $fields, $updatePk);
            if ($updatePk) {
                $this->{$meta->primaryKey->getAttrName()} = $result;
            }
        }
    }