=== modified file 'modules/field/field.crud.inc'
--- modules/field/field.crud.inc	2010-09-24 02:10:06 +0000
+++ modules/field/field.crud.inc	2010-09-26 21:18:39 +0000
@@ -79,6 +79,11 @@
  *     'columns' setting are allowed. Note that field types can specify
  *     default indexes, which can be modified or added to when
  *     creating a field.
+ * - foreign keys: (optional) An associative array of relations, using the same
+ *   structure as the 'foreign keys' definition of hook_schema(). Note, however,
+ *   that the field data is not necessarily stored in SQL. Also, the possible
+ *   usage is limited, as you cannot specify another field as related, only
+ *   existing SQL tables, such as filter formats.
  * - settings (array)
  *     A sub-array of key/value pairs of field-type-specific settings. Each
  *     field type module defines and documents its own field settings.
@@ -319,9 +324,11 @@ function field_create_field($field) {
   // Collect storage information.
   module_load_install($field['module']);
   $schema = (array) module_invoke($field['module'], 'field_schema', $field);
-  $schema += array('columns' => array(), 'indexes' => array());
+  $schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
   // 'columns' are hardcoded in the field type.
   $field['columns'] = $schema['columns'];
+  // 'foreign keys' are hardcoded in the field type.
+  $field['foreign keys'] = $schema['foreign keys'];
   // 'indexes' can be both hardcoded in the field type, and specified in the
   // incoming $field definition.
   $field += array(

=== modified file 'modules/field/modules/field_sql_storage/field_sql_storage.module'
--- modules/field/modules/field_sql_storage/field_sql_storage.module	2010-09-05 20:00:45 +0000
+++ modules/field/modules/field_sql_storage/field_sql_storage.module	2010-09-26 21:18:39 +0000
@@ -188,20 +188,31 @@ function _field_sql_storage_schema($fiel
     ),
   );
 
+  $field += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
   // Add field columns.
-  foreach ((array) $field['columns'] as $column_name => $attributes) {
+  foreach ($field['columns'] as $column_name => $attributes) {
     $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
     $current['fields'][$real_name] = $attributes;
   }
 
   // Add indexes.
-  foreach ((array) $field['indexes'] as $index_name => $columns) {
+  foreach ($field['indexes'] as $index_name => $columns) {
     $real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
     foreach ($columns as $column_name) {
       $current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
     }
   }
 
+  // Add foreign keys.
+  foreach ($field['foreign keys'] as $specifier => $specification) {
+    $real_name = _field_sql_storage_indexname($field['field_name'], $specifier);
+    $current['foreign keys'][$real_name]['table'] = $specification['table'];
+    foreach ($specification['columns'] as $column => $referenced) {
+      $sql_storage_column = _field_sql_storage_columnname($field['field_name'], $column_name);
+      $current['foreign keys'][$real_name]['columns'][$sql_storage_column] = $referenced;
+    }
+  }
+
   // Construct the revision table. The primary key includes
   // revision_id but not entity_id so that multiple revision loads can
   // use the IN operator.

=== modified file 'modules/field/modules/field_sql_storage/field_sql_storage.test'
--- modules/field/modules/field_sql_storage/field_sql_storage.test	2010-08-05 23:53:37 +0000
+++ modules/field/modules/field_sql_storage/field_sql_storage.test	2010-09-26 21:19:06 +0000
@@ -392,4 +392,26 @@ class FieldSqlStorageTestCase extends Dr
       $this->assertEqual($details[FIELD_LOAD_REVISION][$revision][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $revision)));
     }
   }
+
+  /**
+   * Test foreign key support.
+   */
+  function testFieldSqlStorageForeignKeys() {
+    // Create a decimal field.
+    $field_name = 'testfield';
+    $field = array('field_name' => $field_name, 'type' => 'text');
+    $field = field_create_field($field);
+    // Retrieve the field and instance with field_info and verify the foreign
+    // keys are in place.
+    $field = field_info_field($field_name);
+    $this->assertEqual($field['foreign keys']['format']['table'], 'filter_format', t('Foreign key table name preserved through CRUD'));
+    $this->assertEqual($field['foreign keys']['format']['columns']['format'], 'format', t('Foreign key column name preserved through CRUD'));
+    // Now grab the SQL schema and verify that too.
+    $schema = drupal_get_schema(_field_sql_storage_tablename($field));
+    $this->assertEqual(count($schema['foreign keys']), 1, t("There is 1 foreign key in the schema"));
+    $foreign_key = reset($schema['foreign keys']);
+    $filter_column = _field_sql_storage_columnname($field['field_name'], 'format');
+    $this->assertEqual($foreign_key['table'], 'filter_format', t('Foreign key table name preserved in the schema'));
+    $this->assertEqual($foreign_key['columns'][$filter_column], 'format', t('Foreign key column name preserved in the schema'));
+  }
 }

=== modified file 'modules/field/modules/text/text.install'
--- modules/field/modules/text/text.install	2010-09-04 15:40:51 +0000
+++ modules/field/modules/text/text.install	2010-09-26 21:18:39 +0000
@@ -20,6 +20,7 @@ function text_field_schema($field) {
         ),
       );
       break;
+
     case 'text_long':
       $columns = array(
         'value' => array(
@@ -29,6 +30,7 @@ function text_field_schema($field) {
         ),
       );
       break;
+
     case 'text_with_summary':
       $columns = array(
         'value' => array(
@@ -56,5 +58,11 @@ function text_field_schema($field) {
     'indexes' => array(
       'format' => array('format'),
     ),
+    'foreign keys' => array(
+      'format' => array(
+        'table' => 'filter_format',
+        'columns' => array('format' => 'format'),
+      ),
+    ),
   );
 }

=== modified file 'modules/file/file.install'
--- modules/file/file.install	2010-09-04 15:40:51 +0000
+++ modules/file/file.install	2010-09-26 21:18:39 +0000
@@ -35,6 +35,12 @@ function file_field_schema($field) {
     'indexes' => array(
       'fid' => array('fid'),
     ),
+    'foreign keys' => array(
+      'fid' => array(
+        'table' => 'file',
+        'columns' => array('fid' => 'fid'),
+      ),
+    ),
   );
 }
 

=== modified file 'modules/system/system.api.php'
--- modules/system/system.api.php	2010-09-24 00:37:41 +0000
+++ modules/system/system.api.php	2010-09-26 21:18:39 +0000
@@ -2633,9 +2633,11 @@ function hook_requirements($phase) {
  * details on schema definition structures.
  *
  * @return
- * A schema definition structure array. For each element of the
- * array, the key is a table name and the value is a table structure
- * definition.
+ *   A schema definition structure array. For each element of the
+ *   array, the key is a table name and the value is a table structure
+ *   definition.
+ *
+ * @ingroup schemaapi
  */
 function hook_schema() {
   $schema['node'] = array(

