I created a feature with the export of a data table in it. When I enable the feature on a new site, the table is not automatically created, which causes some errors in the other components which are relying on it (e.g. views for example).

Comments

scor’s picture

Here are a couple of manual work arounds.

1. via the UI, you can enable data_ui and schema modules, and hit the "create table button" in the compare schema tab at admin/structure/data/compare/YOURTABLENAME

2. I managed to do it progammatically as well via two separate update functions (for deployment):

/**
 * enable feature.
 */
function msdfsite_update_7002() {
  module_enable(array('myfeature', 'data'));
  drupal_flush_all_caches();
  features_revert(array('myfeature' => array('data_tables', 'views_view')));
}

/**
 * create the data module table (this has to be run in a separate
 * update call for some reason).
 */
function msdfsite_update_7003() {
  $table = data_get_table('mytable');
  db_create_table($table->get('name'), $table->get('table_schema'));
}
joachim’s picture

Tricky to fix, as you'd need to know when a Feature is enabled and quickly whip in and make the data table it describes.

Features has a hook_features_enable() which might be the place to do that in.

mstef’s picture

Would it make sense to implement hook_modules_installed() (http://api.drupal.org/api/drupal/modules%21system%21system.api.php/funct...) in data.module? See if the module being installed contains a data table export, and create them?

joachim’s picture

Just spotted this in the api.php file:

/**
 * Expose default tables.
 *
 * Note:
 *
 * - Implementor is responsible for creating this table on installation and for
 *   proper updates in case of schema changes (hook_install(), hook_update_N())
 * - Implement hook_ctools_plugin_api() to make this hook discoverable by
 *   CTools - see below.
 */
function hook_data_default() {

I assume this is how features define their tables?
Is it possible to force a feature to add a code function to take care of installing the tables>

andybrace’s picture

I'm also seeing this when enabling a feature containing a data table definition, the table is correctly defined but is not imported when the feature is enabled. hook_ctools_plugin_api has been correctly defined and the hook_data_default definition is also found in the module.data_default.inc file as expected. When viewing the feature in the admin ui screen it is showing as state 'default' so there is no option to revert the feature.

Has anyone else managed to find a solution?

ice5nake’s picture

I am also seeing this in the 6.x version. I guess Features support isn't fully baked out yet?

As an aside, surprisingly Feeds does not complain about the data table not being there when I import into it. It acts like it succeeds but obviously nothing is actually imported into the table.

zeip’s picture

Version: 7.x-1.0-alpha2 » 7.x-1.x-dev
Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new4.69 KB

Attached is a patch for Features integration. It uses the Ctools export but provides the Features export & import as custom functionality. It seems that tapping into the Ctools Features revert doesn't work very well, so this seems to be the way to go.

brtamas’s picture

StatusFileSize
new4.87 KB

Hi, I have updated the preivous patch to work with 7-1.0-alpha7 release.

caschbre’s picture

Patch #8 seems to work for alpha8 as well. One thing to note is that it only works with tables exported using the patch. Previously exported tables using just the alpha8 release would not properly import.

caschbre’s picture

I take that back... I'm unable to export the tables. Nothing appears to be generated.

johnorourke’s picture

For anyone arriving here looking for a way to define your schema in just one place, and have tables automatically created, *and* available as entities and views via the data module, here's how I did it without using any patches, in 7.x. In this case you don't need to add the tables to your feature module since they're defined in our custom module:

mymodule.module:

/* regular Drupal schema definition - ensures the table gets created on install: */

function mymodule_schema(){

  $schema['test3'] = array(
    'description' => 'test3 table',
    'fields' => array(
      'id' => array(
        'type' => 'serial',
        'size' => 'normal',
        'unsigned' => TRUE,
        'description' => 'ID', // name to show in the data module
        'required' => 1, // used by the data module, see below
      ),
      'customer' => array(
        'type' => 'varchar',
        'size' => 'normal',
        'default' => null,
        'length' => 20,
        'description' => 'Customer ID',
        'required' => 1,
      ),
      'price' => array(
        'type' => 'numeric',
        'size' => 'normal',
        'unsigned' => false,
        'precision' => 12,
        'scale' => 6, // a specific use-case I was testing - the data_ui module doesn't support these numeric params so you can't use them from the data UI
        'description' => 'Unit Price',
        'required' => 1,
      ),
    ),
    'primary key' => array(
      'id',
    ),
    'name' => 'test3',
    '_entity_label' => 'customer', // our custom property, used below
  );
  return $schema;
}

/* as described in the data module API - this ensures our data_default hook gets seen */
function mymodule_ctools_plugin_api() {
  $args = func_get_args();
  $module = array_shift($args);
  $api = array_shift($args);
  if ($module == "data" && $api == "data_default") {
    return array("version" => 1);
  }
}

/* our data_default hook, uses the schema defined above to export data tables so the data module sees them */
function mymodule_data_default() {
  $export = array();

  $schemas = mymodule_schema();

  foreach($schemas as $t => $schema) {

    $data_table = new stdClass;
    $data_table->disabled = FALSE; /* Edit this to true to make a default data_table disabled initially */
    $data_table->api_version = 1;
    $data_table->title = $schema['description'];
    $data_table->name = $t;
    $data_table->table_schema = $schema;
    $data_table->meta = array(
      'fields' => array(),
      'label_field' => $schema['_entity_label'], // see schema above
      'is_entity_type' => 1,
      'entity_id' => 'id',
    );
    foreach($schema['fields'] as $f => $field_schema) {
      $data_table->meta['fields'][$f] = array(
        'label' => $field_schema['description'], // pull in our extra fields from the schema definition, so all our schema is in one place only
        'required' => $field_schema['required'],
        'locked' => 0,
      );
    }
    $export[$data_table->name] = $data_table;
  }

  return $export;
}