Problem/Motivation
Recently updated from 3.0.9 => 3.1.0;
When I try to create a new training I receive the following error:
Drupal\Core\Database\IntegrityConstraintViolationException: SQLSTATE[HY000]: General error: 1364 Field 'revision_id' doesn't have a default value: INSERT INTO "groups_field_data" ("id", "type", "langcode", "uid", "label", "created", "changed", "default_langcode") VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7); Array ( [:db_insert_placeholder_0] => 17 [:db_insert_placeholder_1] => learning_path [:db_insert_placeholder_2] => en [:db_insert_placeholder_3] => 2 [:db_insert_placeholder_4] => Software development training [:db_insert_placeholder_5] => 1692195455 [:db_insert_placeholder_6] => 1692195455 [:db_insert_placeholder_7] => 1 ) in Drupal\mysql\Driver\Database\mysql\ExceptionHandler->handleExecutionException() (line 50 of /code/web/core/modules/mysql/src/Driver/Database/mysql/ExceptionHandler.php).
Call stack
Drupal\Core\Database\StatementWrapper->execute(Array, Array) (Line: 44)
Drupal\mysql\Driver\Database\mysql\Insert->execute() (Line: 1020)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->saveToSharedTables(Object) (Line: 958)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->doSaveFieldItems(Object) (Line: 718)
Drupal\Core\Entity\ContentEntityStorageBase->doSave(NULL, Object) (Line: 520)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 804)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object) (Line: 339)
Drupal\Core\Entity\EntityBase->save() (Line: 285)
Drupal\Core\Entity\EntityForm->save(Array, Object) (Line: 88)
Drupal\group\Entity\Form\GroupForm->save(Array, Object)
call_user_func_array(Array, Array) (Line: 114)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 597)
Drupal\Core\Form\FormBuilder->processForm('group_learning_path_add_form', Array, Object) (Line: 325)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'add', Array) (Line: 139)
Drupal\group\Entity\Controller\GroupController->addForm(Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
In an attempt to track down where "revision_id" should be, I added some logs to the function addForm() seen in the call stack above
public function addForm(GroupTypeInterface $group_type) {
// Log the group type being processed.
\Drupal::logger('addForm1')->notice('Starting addForm for group type: @group_type_id', ['@group_type_id' => $group_type->id()]);
This log returns: Starting addForm for group type: learning_path
$wizard_id = 'group_creator';
$store = $this->privateTempStoreFactory->get($wizard_id);
$store_id = $group_type->id();
// See if the group type is configured to ask the creator to fill out their
// membership details. Also pass this info to the form state.
$extra['group_wizard'] = $group_type->creatorMustCompleteMembership();
$extra['group_wizard_id'] = $wizard_id;
// Pass the group type and store ID to the form state as well.
$extra['group_type'] = $group_type;
$extra['store_id'] = $store_id;
// See if we are on the second step of the form.
$step2 = $extra['group_wizard'] && $store->get("$store_id:step") === 2;
// Group form, potentially as wizard step 1.
if (!$step2) {
$storage = $this->entityTypeManager()->getStorage('group');
// Only create a new group if we have nothing stored.
if (!$entity = $store->get("$store_id:entity")) {
$values['type'] = $group_type->id();
// Log the values used to create the group or group membership entity.
\Drupal::logger('addForm2')->notice('Creating entity with values: @values', ['@values' => print_r($values, TRUE)]);
This log returns: Creating entity with values: Array ( [type] => learning_path )
$entity = $storage->create($values);
}
// Log the group entity details.
\Drupal::logger('addForm3')->notice('Group entity created: @entity', ['@entity' => print_r($entity->toArray(), TRUE)]);
This log returns: Group entity created:
Array (
[id] => Array ( )
[uuid] => Array ( [0] => Array ( [value] => 53d30af7-b2c7-44d6-a310-a77bd85d3b1d ) )
[langcode] => Array ( [0] => Array ( [value] => en ) )
[type] => Array ( [0] => Array ( [target_id] => learning_path ) )
[uid] => Array ( [0] => Array ( [target_id] => 2 ) )
[label] => Array ( ) [created] => Array ( [0] => Array ( [value] => 1692195455 ) )
[changed] => Array ( [0] => Array ( [value] => 1692195455 ) )
[path] => Array ( [0] => Array ( [langcode] => en ) )
[default_langcode] => Array ( [0] => Array ( [value] => 1 ) )
[field_anonymous_visibility] => Array ( [0] => Array ( [value] => 0 ) )
[field_certificate] => Array ( )
[field_certificate_expire] => Array ( [0] => Array ( [value] => 0 ) )
[field_certificate_expire_results] => Array ( [0] => Array ( [value] => 1 ) )
[field_guided_navigation] => Array ( [0] => Array ( [value] => 0 ) )
[field_learning_path_category] => Array ( )
[field_learning_path_description] => Array ( )
[field_learning_path_duration] => Array ( )
[field_learning_path_enable_forum] => Array ( [0] => Array ( [value] => 0 ) )
[field_learning_path_folder] => Array ( )
[field_learning_path_forum] => Array ( )
[field_learning_path_media_image] => Array ( )
[field_learning_path_published] => Array ( [0] => Array ( [value] => 0 ) )
[field_learning_path_visibility] => Array ( [0] => Array ( [value] => semiprivate ) )
[field_lesson_instructors] => Array ( )
[field_required_trainings] => Array ( )
[field_requires_validation] => Array ( [0] => Array ( [value] => 0 ) )
[field_workspace] => Array ( ) )
}
// Wizard step 2: Group membership form.
else {
// Create an empty group membership that does not yet have a group set.
$values = [
'type' => $group_type->getContentPlugin('group_membership')->getContentTypeConfigId(),
'entity_id' => $this->currentUser()->id(),
];
$entity = $this->entityTypeManager()->getStorage('group_content')->create($values);
// Log the group membership entity details.
\Drupal::logger('addForm4')->notice('Group membership entity created: @entity', ['@entity' => print_r($entity->toArray(), TRUE)]);
}
// Return the entity form with the configuration gathered above.
return $this->entityFormBuilder()->getForm($entity, 'add', $extra);
}
I checked the database schema for groups_field_data:
CREATE TABLE `groups_field_data` (
`id` int(10) unsigned NOT NULL,
`revision_id` int(10) unsigned NOT NULL,
`type` varchar(32) CHARACTER SET ascii NOT NULL COMMENT 'The ID of the target entity.',
`langcode` varchar(12) CHARACTER SET ascii NOT NULL,
`uid` int(10) unsigned NOT NULL COMMENT 'The ID of the target entity.',
`label` varchar(255) DEFAULT NULL,
`created` int(11) DEFAULT NULL,
`changed` int(11) DEFAULT NULL,
`default_langcode` tinyint(4) NOT NULL,
`status` tinyint(4) NOT NULL,
`revision_translation_affected` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`,`langcode`),
KEY `group__id__default_langcode__langcode` (`id`,`default_langcode`,`langcode`),
KEY `group__revision_id` (`revision_id`),
KEY `group_field__type__target_id` (`type`),
KEY `group_field__uid__target_id` (`uid`),
KEY `group__status_type` (`status`,`type`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='The data table for group entities.';
This clearly shows that revision_id is set to NOT NULL without a default value. This means that any INSERT operation into this table must include a value for the revision_id field.
Steps to reproduce
composer file has the following relevant packages:
"opigno/opigno_lms": "3.1.0",
"drupal/group": "1.2.0",
"drupal/core-recommended": "^9.4",
"drupal/core": "9.5.10"
Drupal Version
9.5.10
Web Server
nginx/1.21.6
PHP Version
8.1.14
Memory limit
512M
Database Version
10.4.25-MariaDB-log
Proposed resolution
Find out where "revision_id" should exist, and patch it in to where it should exist.
Remaining tasks
n/a
User interface changes
n/a
API changes
n/a
Data model changes
n/a