You are here

public function Schema::queryColumnInformation in Drupal driver for SQL Server and SQL Azure 3.0.x

Same name and namespace in other branches
  1. 8 drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php \Drupal\Driver\Database\sqlsrv\Schema::queryColumnInformation()

Database introspection: fetch technical information about a table.

Return value

array An array with the following structure:

  • blobs[]: Array of column names that should be treated as blobs in this table.
  • identities[]: Array of column names that are identities in this table.
  • identity: The name of the identity column
  • columns[]: An array of specification details for the columns
    • name: Column name.
    • max_length: Maximum length.
    • precision: Precision.
    • collation_name: Collation.
    • is_nullable: Is nullable.
    • is_ansi_padded: Is ANSI padded.
    • is_identity: Is identity.
    • definition: If a computed column, the computation formulae.
    • default_value: Default value for the column (if any).
7 calls to Schema::queryColumnInformation()
Schema::calculateClusteredIndexRowSizeBytes in drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php
Estimates the row size of a clustered index.
Schema::createIndexSql in drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php
Returns the SQL needed to create an index.
Schema::dropFieldRelatedObjects in drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php
Drop the related objects of a column (indexes, constraints, etc.).
Schema::introspectIndexSchema in drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php
Finds the columns for the primary key, unique keys and indexes of a table.
Schema::introspectPrimaryKeyFields in drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php
Get the list of fields participating in the Primary Key.

... See full list

File

drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php, line 855

Class

Schema

Namespace

Drupal\Driver\Database\sqlsrv

Code

public function queryColumnInformation($table) {
  if (empty($table) || !$this
    ->tableExists($table)) {
    return [];
  }
  if ($this->cacheSchema && isset($this->columnInformation[$table])) {
    return $this->columnInformation[$table];
  }
  $table_info = $this
    ->getPrefixInfo($table);

  // We could adapt the current code to support temporary table introspection,
  // but for now this is not supported.
  if ($this->connection
    ->isTemporaryTable($table)) {
    throw new \Exception('Temporary table introspection is not supported.');
  }
  $info = [];

  // Don't use {} around information_schema.columns table.
  $sql = "SELECT sysc.name, sysc.max_length, sysc.precision, sysc.collation_name,\n      sysc.is_nullable, sysc.is_ansi_padded, sysc.is_identity, sysc.is_computed, TYPE_NAME(sysc.user_type_id) as type,\n      syscc.definition, sm.[text] as default_value\n      FROM sys.columns AS sysc\n      INNER JOIN sys.syscolumns AS sysc2 ON sysc.object_id = sysc2.id and sysc.name = sysc2.name\n      LEFT JOIN sys.computed_columns AS syscc ON sysc.object_id = syscc.object_id AND sysc.name = syscc.name\n      LEFT JOIN sys.syscomments sm ON sm.id = sysc2.cdefault\n      WHERE sysc.object_id = OBJECT_ID(:table)";
  $args = [
    ':table' => $table_info['schema'] . '.' . $table_info['table'],
  ];
  $result = $this->connection
    ->queryDirect($sql, $args);
  foreach ($result as $column) {
    if ($column->type == 'varbinary') {
      $info['blobs'][$column->name] = TRUE;
    }
    $info['columns'][$column->name] = (array) $column;

    // Provide a clean list of columns that excludes the ones internally
    // created by the database driver.
    if (!(isset($column->name[1]) && substr($column->name, 0, 2) == "__")) {
      $info['columns_clean'][$column->name] = (array) $column;
    }
  }

  // If we have computed columns, it is important to know what other columns
  // they depend on!
  $column_names = array_keys($info['columns']);
  $column_regex = implode('|', $column_names);
  foreach ($info['columns'] as &$column) {
    $dependencies = [];
    if (!empty($column['definition'])) {
      $matches = [];
      if (preg_match_all("/\\[[{$column_regex}\\]]*\\]/", $column['definition'], $matches) > 0) {
        $dependencies = array_map(function ($m) {
          return trim($m, "[]");
        }, array_shift($matches));
      }
    }
    $column['dependencies'] = array_flip($dependencies);
  }

  // Don't use {} around system tables.
  $result = $this->connection
    ->queryDirect('SELECT name FROM sys.identity_columns WHERE object_id = OBJECT_ID(:table)', [
    ':table' => $table_info['schema'] . '.' . $table_info['table'],
  ]);
  unset($column);
  $info['identities'] = [];
  $info['identity'] = NULL;
  foreach ($result as $column) {
    $info['identities'][$column->name] = $column->name;
    $info['identity'] = $column->name;
  }

  // Now introspect information about indexes.
  $result = $this->connection
    ->queryDirect("select tab.[name]  as [table_name],\n         idx.[name]  as [index_name],\n         allc.[name] as [column_name],\n         idx.[type_desc],\n         idx.[is_unique],\n         idx.[data_space_id],\n         idx.[ignore_dup_key],\n         idx.[is_primary_key],\n         idx.[is_unique_constraint],\n         idx.[fill_factor],\n         idx.[is_padded],\n         idx.[is_disabled],\n         idx.[is_hypothetical],\n         idx.[allow_row_locks],\n         idx.[allow_page_locks],\n         idxc.[is_descending_key],\n         idxc.[is_included_column],\n         idxc.[index_column_id],\n         idxc.[key_ordinal]\n    FROM sys.[tables] as tab\n    INNER join sys.[indexes]       idx  ON tab.[object_id] =  idx.[object_id]\n    INNER join sys.[index_columns] idxc ON idx.[object_id] = idxc.[object_id] and  idx.[index_id]  = idxc.[index_id]\n    INNER join sys.[all_columns]   allc ON tab.[object_id] = allc.[object_id] and idxc.[column_id] = allc.[column_id]\n    WHERE tab.object_id = OBJECT_ID(:table)\n    ORDER BY tab.[name], idx.[index_id], idxc.[index_column_id]\n                    ", [
    ':table' => $table_info['schema'] . '.' . $table_info['table'],
  ]);
  foreach ($result as $index_column) {
    if (!isset($info['indexes'][$index_column->index_name])) {
      $ic = clone $index_column;

      // Only retain index specific details.
      unset($ic->column_name);
      unset($ic->index_column_id);
      unset($ic->is_descending_key);
      unset($ic->table_name);
      unset($ic->key_ordinal);
      $info['indexes'][$index_column->index_name] = (array) $ic;
      if ($index_column->is_primary_key) {
        $info['primary_key_index'] = $ic->index_name;
      }
    }
    $index =& $info['indexes'][$index_column->index_name];
    $index['columns'][$index_column->key_ordinal] = [
      'name' => $index_column->column_name,
      'is_descending_key' => $index_column->is_descending_key,
      'key_ordinal' => $index_column->key_ordinal,
    ];

    // Every columns keeps track of what indexes it is part of.
    $info['columns'][$index_column->column_name]['indexes'][] = $index_column->index_name;
    if (isset($info['columns_clean'][$index_column->column_name])) {
      $info['columns_clean'][$index_column->column_name]['indexes'][] = $index_column->index_name;
    }
  }
  if ($this->cacheSchema) {
    $this->columnInformation[$table] = $info;
  }
  return $info;
}