- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-
- namespace Zend\Db\Metadata\Source;
-
- use Zend\Db\Adapter\Adapter;
-
- class SqlServerMetadata extends AbstractSource
- {
-
-
- protected function loadSchemaData()
- {
- if (isset($this->data['schemas'])) {
- return;
- }
- $this->prepareDataHierarchy('schemas');
-
- $p = $this->adapter->getPlatform();
-
- $sql = 'SELECT ' . $p->quoteIdentifier('SCHEMA_NAME')
- . ' FROM ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'SCHEMATA'))
- . ' WHERE ' . $p->quoteIdentifier('SCHEMA_NAME')
- . ' != \'INFORMATION_SCHEMA\'';
-
- $results = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE);
-
- $schemas = array();
- foreach ($results->toArray() as $row) {
- $schemas[] = $row['SCHEMA_NAME'];
- }
-
- $this->data['schemas'] = $schemas;
- }
-
- protected function loadTableNameData($schema)
- {
- if (isset($this->data['table_names'][$schema])) {
- return;
- }
- $this->prepareDataHierarchy('table_names', $schema);
-
- $p = $this->adapter->getPlatform();
-
- $isColumns = array(
- array('T', 'TABLE_NAME'),
- array('T', 'TABLE_TYPE'),
- array('V', 'VIEW_DEFINITION'),
- array('V', 'CHECK_OPTION'),
- array('V', 'IS_UPDATABLE'),
- );
-
- array_walk($isColumns, function (&$c) use ($p) { $c = $p->quoteIdentifierChain($c); });
-
- $sql = 'SELECT ' . implode(', ', $isColumns)
- . ' FROM ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'TABLES')) . ' t'
-
- . ' LEFT JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'VIEWS')) . ' v'
- . ' ON ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('V', 'TABLE_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('V', 'TABLE_NAME'))
-
- . ' WHERE ' . $p->quoteIdentifierChain(array('T', 'TABLE_TYPE'))
- . ' IN (\'BASE TABLE\', \'VIEW\')';
-
- if ($schema != self::DEFAULT_SCHEMA) {
- $sql .= ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteTrustedValue($schema);
- } else {
- $sql .= ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' != \'INFORMATION_SCHEMA\'';
- }
-
- $results = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE);
-
- $tables = array();
- foreach ($results->toArray() as $row) {
- $tables[$row['TABLE_NAME']] = array(
- 'table_type' => $row['TABLE_TYPE'],
- 'view_definition' => $row['VIEW_DEFINITION'],
- 'check_option' => $row['CHECK_OPTION'],
- 'is_updatable' => ('YES' == $row['IS_UPDATABLE']),
- );
- }
-
- $this->data['table_names'][$schema] = $tables;
- }
-
- protected function loadColumnData($table, $schema)
- {
- if (isset($this->data['columns'][$schema][$table])) {
- return;
- }
- $this->prepareDataHierarchy('columns', $schema, $table);
- $p = $this->adapter->getPlatform();
-
- $isColumns = array(
- array('C', 'ORDINAL_POSITION'),
- array('C', 'COLUMN_DEFAULT'),
- array('C', 'IS_NULLABLE'),
- array('C', 'DATA_TYPE'),
- array('C', 'CHARACTER_MAXIMUM_LENGTH'),
- array('C', 'CHARACTER_OCTET_LENGTH'),
- array('C', 'NUMERIC_PRECISION'),
- array('C', 'NUMERIC_SCALE'),
- array('C', 'COLUMN_NAME'),
- );
-
- array_walk($isColumns, function (&$c) use ($p) { $c = $p->quoteIdentifierChain($c); });
-
- $sql = 'SELECT ' . implode(', ', $isColumns)
- . ' FROM ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'TABLES')) . 'T'
- . ' INNER JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'COLUMNS')) . 'C'
- . ' ON ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('C', 'TABLE_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('C', 'TABLE_NAME'))
- . ' WHERE ' . $p->quoteIdentifierChain(array('T', 'TABLE_TYPE'))
- . ' IN (\'BASE TABLE\', \'VIEW\')'
- . ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_NAME'))
- . ' = ' . $p->quoteTrustedValue($table);
-
- if ($schema != self::DEFAULT_SCHEMA) {
- $sql .= ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteTrustedValue($schema);
- } else {
- $sql .= ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' != \'INFORMATION_SCHEMA\'';
- }
-
- $results = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE);
- $columns = array();
- foreach ($results->toArray() as $row) {
- $columns[$row['COLUMN_NAME']] = array(
- 'ordinal_position' => $row['ORDINAL_POSITION'],
- 'column_default' => $row['COLUMN_DEFAULT'],
- 'is_nullable' => ('YES' == $row['IS_NULLABLE']),
- 'data_type' => $row['DATA_TYPE'],
- 'character_maximum_length' => $row['CHARACTER_MAXIMUM_LENGTH'],
- 'character_octet_length' => $row['CHARACTER_OCTET_LENGTH'],
- 'numeric_precision' => $row['NUMERIC_PRECISION'],
- 'numeric_scale' => $row['NUMERIC_SCALE'],
- 'numeric_unsigned' => null,
- 'erratas' => array(),
- );
- }
-
- $this->data['columns'][$schema][$table] = $columns;
- }
-
- protected function loadConstraintData($table, $schema)
- {
- if (isset($this->data['constraints'][$schema][$table])) {
- return;
- }
-
- $this->prepareDataHierarchy('constraints', $schema, $table);
-
- $isColumns = array(
- array('T', 'TABLE_NAME'),
- array('TC', 'CONSTRAINT_NAME'),
- array('TC', 'CONSTRAINT_TYPE'),
- array('KCU', 'COLUMN_NAME'),
- array('CC', 'CHECK_CLAUSE'),
- array('RC', 'MATCH_OPTION'),
- array('RC', 'UPDATE_RULE'),
- array('RC', 'DELETE_RULE'),
- array('REFERENCED_TABLE_SCHEMA' => 'KCU2', 'TABLE_SCHEMA'),
- array('REFERENCED_TABLE_NAME' => 'KCU2', 'TABLE_NAME'),
- array('REFERENCED_COLUMN_NAME' => 'KCU2', 'COLUMN_NAME'),
- );
-
- $p = $this->adapter->getPlatform();
-
- array_walk($isColumns, function (&$c) use ($p) {
- $alias = key($c);
- $c = $p->quoteIdentifierChain($c);
- if (is_string($alias)) {
- $c .= ' ' . $p->quoteIdentifier($alias);
- }
- });
-
- $sql = 'SELECT ' . implode(', ', $isColumns)
- . ' FROM ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'TABLES')) . ' T'
-
- . ' INNER JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'TABLE_CONSTRAINTS')) . ' TC'
- . ' ON ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('TC', 'TABLE_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('TC', 'TABLE_NAME'))
-
- . ' LEFT JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'KEY_COLUMN_USAGE')) . ' KCU'
- . ' ON ' . $p->quoteIdentifierChain(array('TC', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('KCU', 'TABLE_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('TC', 'TABLE_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('KCU', 'TABLE_NAME'))
- . ' AND ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('KCU', 'CONSTRAINT_NAME'))
-
- . ' LEFT JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'CHECK_CONSTRAINTS')) . ' CC'
- . ' ON ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('CC', 'CONSTRAINT_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('CC', 'CONSTRAINT_NAME'))
-
- . ' LEFT JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'REFERENTIAL_CONSTRAINTS')) . ' RC'
- . ' ON ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('RC', 'CONSTRAINT_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('RC', 'CONSTRAINT_NAME'))
-
- . ' LEFT JOIN ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'KEY_COLUMN_USAGE')) . ' KCU2'
- . ' ON ' . $p->quoteIdentifierChain(array('RC', 'UNIQUE_CONSTRAINT_SCHEMA'))
- . ' = ' . $p->quoteIdentifierChain(array('KCU2', 'CONSTRAINT_SCHEMA'))
- . ' AND ' . $p->quoteIdentifierChain(array('RC', 'UNIQUE_CONSTRAINT_NAME'))
- . ' = ' . $p->quoteIdentifierChain(array('KCU2', 'CONSTRAINT_NAME'))
- . ' AND ' . $p->quoteIdentifierChain(array('KCU', 'ORDINAL_POSITION'))
- . ' = ' . $p->quoteIdentifierChain(array('KCU2', 'ORDINAL_POSITION'))
-
- . ' WHERE ' . $p->quoteIdentifierChain(array('T', 'TABLE_NAME'))
- . ' = ' . $p->quoteTrustedValue($table)
- . ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_TYPE'))
- . ' IN (\'BASE TABLE\', \'VIEW\')';
-
- if ($schema != self::DEFAULT_SCHEMA) {
- $sql .= ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' = ' . $p->quoteTrustedValue($schema);
- } else {
- $sql .= ' AND ' . $p->quoteIdentifierChain(array('T', 'TABLE_SCHEMA'))
- . ' != \'INFORMATION_SCHEMA\'';
- }
-
- $sql .= ' ORDER BY CASE ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_TYPE'))
- . " WHEN 'PRIMARY KEY' THEN 1"
- . " WHEN 'UNIQUE' THEN 2"
- . " WHEN 'FOREIGN KEY' THEN 3"
- . " WHEN 'CHECK' THEN 4"
- . " ELSE 5 END"
- . ', ' . $p->quoteIdentifierChain(array('TC', 'CONSTRAINT_NAME'))
- . ', ' . $p->quoteIdentifierChain(array('KCU', 'ORDINAL_POSITION'));
-
- $results = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE);
-
- $name = null;
- $constraints = array();
- $isFK = false;
- foreach ($results->toArray() as $row) {
- if ($row['CONSTRAINT_NAME'] !== $name) {
- $name = $row['CONSTRAINT_NAME'];
- $constraints[$name] = array(
- 'constraint_name' => $name,
- 'constraint_type' => $row['CONSTRAINT_TYPE'],
- 'table_name' => $row['TABLE_NAME'],
- );
- if ('CHECK' == $row['CONSTRAINT_TYPE']) {
- $constraints[$name]['check_clause'] = $row['CHECK_CLAUSE'];
- continue;
- }
- $constraints[$name]['columns'] = array();
- $isFK = ('FOREIGN KEY' == $row['CONSTRAINT_TYPE']);
- if ($isFK) {
- $constraints[$name]['referenced_table_schema'] = $row['REFERENCED_TABLE_SCHEMA'];
- $constraints[$name]['referenced_table_name'] = $row['REFERENCED_TABLE_NAME'];
- $constraints[$name]['referenced_columns'] = array();
- $constraints[$name]['match_option'] = $row['MATCH_OPTION'];
- $constraints[$name]['update_rule'] = $row['UPDATE_RULE'];
- $constraints[$name]['delete_rule'] = $row['DELETE_RULE'];
- }
- }
- $constraints[$name]['columns'][] = $row['COLUMN_NAME'];
- if ($isFK) {
- $constraints[$name]['referenced_columns'][] = $row['REFERENCED_COLUMN_NAME'];
- }
- }
-
- $this->data['constraints'][$schema][$table] = $constraints;
- }
-
- protected function loadTriggerData($schema)
- {
- if (isset($this->data['triggers'][$schema])) {
- return;
- }
-
- $this->prepareDataHierarchy('triggers', $schema);
-
- $p = $this->adapter->getPlatform();
-
- $isColumns = array(
- 'TRIGGER_NAME',
- 'EVENT_MANIPULATION',
- 'EVENT_OBJECT_CATALOG',
- 'EVENT_OBJECT_SCHEMA',
- 'EVENT_OBJECT_TABLE',
- 'ACTION_ORDER',
- 'ACTION_CONDITION',
- 'ACTION_STATEMENT',
- 'ACTION_ORIENTATION',
- 'ACTION_TIMING',
- 'ACTION_REFERENCE_OLD_TABLE',
- 'ACTION_REFERENCE_NEW_TABLE',
- 'ACTION_REFERENCE_OLD_ROW',
- 'ACTION_REFERENCE_NEW_ROW',
- 'CREATED',
- );
-
- array_walk($isColumns, function (&$c) use ($p) {
- $c = $p->quoteIdentifier($c);
- });
-
- $sql = 'SELECT ' . implode(', ', $isColumns)
- . ' FROM ' . $p->quoteIdentifierChain(array('INFORMATION_SCHEMA', 'TRIGGERS'))
- . ' WHERE ';
-
- if ($schema != self::DEFAULT_SCHEMA) {
- $sql .= $p->quoteIdentifier('TRIGGER_SCHEMA')
- . ' = ' . $p->quoteTrustedValue($schema);
- } else {
- $sql .= $p->quoteIdentifier('TRIGGER_SCHEMA')
- . ' != \'INFORMATION_SCHEMA\'';
- }
-
- $results = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE);
-
- $data = array();
- foreach ($results->toArray() as $row) {
- $row = array_change_key_case($row, CASE_LOWER);
- if (null !== $row['created']) {
- $row['created'] = new \DateTime($row['created']);
- }
- $data[$row['trigger_name']] = $row;
- }
-
- $this->data['triggers'][$schema] = $data;
- }
- }