/**
  * Return object (table/schema) configuration
  *
  * @throws Exception\ErrorException
  *
  * @param string $table
  * @param boolean $include_options
  * @return array
  */
 protected function getObjectConfig($table = null, $include_options = false)
 {
     $schema = $this->schema;
     $qSchema = $this->adapter->getPlatform()->quoteValue($schema);
     if ($table !== null) {
         $qTable = $this->adapter->getPlatform()->quoteValue($table);
         $table_clause = "and (t.TABLE_NAME = {$qTable} or (kcu.referenced_table_name = {$qTable} and kcu.constraint_name = 'FOREIGN KEY'))";
         $table_join_condition = "(t.table_name = kcu.table_name or  kcu.referenced_table_name = t.table_name)";
     } else {
         $table_join_condition = "t.table_name = kcu.table_name";
         $table_clause = '';
     }
     $query = "\n\n            SELECT\n                    t.table_name,\n                    c.column_name,\n                    c.data_type,\n                    c.column_type,\n\n                    c.extra,\n\n                    tc.constraint_type,\n                    kcu.constraint_name,\n                    kcu.referenced_table_name,\n                    kcu.referenced_column_name,\n\n                    c.column_default,\n                    c.is_nullable,\n                    c.numeric_precision,\n                    c.numeric_scale,\n                    c.character_octet_length,\n                    c.character_maximum_length,\n                    c.ordinal_position,\n\n                    c.column_key, -- UNI/MUL/PRI\n                    c.character_set_name,\n\n\n                    c.collation_name,\n\n                    c.column_comment,\n\n                    t.table_type,\n                    t.engine,\n                    t.table_comment,\n                    t.table_collation\n\n            FROM `INFORMATION_SCHEMA`.`COLUMNS` c\n            INNER JOIN `INFORMATION_SCHEMA`.`TABLES` t on c.TABLE_NAME = t.TABLE_NAME\n            LEFT JOIN `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` kcu\n               on (\n                    {$table_join_condition}\n                     and kcu.table_schema = t.table_schema\n                     and kcu.column_name = c.column_name\n                 )\n              LEFT JOIN\n                `INFORMATION_SCHEMA`.`TABLE_CONSTRAINTS` tc\n               on (\n                     t.table_name = tc.table_name\n                      and tc.table_schema = t.table_schema\n                      and tc.constraint_name = kcu.constraint_name\n                  )\n\n\n            where c.TABLE_SCHEMA = {$qSchema}\n            and t.TABLE_SCHEMA = {$qSchema}\n            {$table_clause}\n            and (kcu.table_schema = {$qSchema}  or kcu.table_schema is null)\n\n            and (kcu.column_name = c.column_name or kcu.column_name is null)\n            order by t.table_name, c.ordinal_position\n        ";
     $this->disableInnoDbStats();
     try {
         $results = $this->adapter->query($query, Adapter::QUERY_MODE_EXECUTE);
     } catch (\Exception $e) {
         //@codeCoverageIgnoreStart
         $this->restoreInnoDbStats();
         throw new Exception\ErrorException(__METHOD__ . ": " . $e->getMessage());
         //@codeCoverageIgnoreEnd
     }
     $this->restoreInnoDbStats();
     $references = array();
     $config = new Config(array('tables' => array()), true);
     $tables = $config->offsetGet('tables');
     foreach ($results as $r) {
         // Setting table information
         $table_name = $r['table_name'];
         if (!$tables->offsetExists($table_name)) {
             $table_def = array('name' => $table_name, 'columns' => array(), 'primary_keys' => array(), 'unique_keys' => array(), 'foreign_keys' => array(), 'references' => array(), 'indexes' => array());
             if ($include_options) {
                 $table_def['options'] = array('comment' => $r['table_comment'], 'collation' => $r['table_collation'], 'type' => $r['table_type'], 'engine' => $r['engine']);
             }
             $tables->offsetSet($table_name, $table_def);
         }
         $table = $tables->offsetGet($table_name);
         $columns = $table->columns;
         $column_name = $r['column_name'];
         $data_type = strtolower($r['data_type']);
         $col_def = array('type' => $data_type, 'primary' => $r['constraint_type'] == 'PRIMARY KEY', 'nullable' => $r['is_nullable'] == 'YES', 'default' => $r['column_default']);
         if ($r['constraint_type'] == 'PRIMARY KEY') {
             $col_def['primary'] = true;
             $col_def['autoincrement'] = $r['extra'] == 'auto_increment';
         }
         $has_charset = false;
         if (in_array($data_type, array('int', 'tinyint', 'mediumint', 'bigint', 'int', 'smallint', 'year'))) {
             $col_def['unsigned'] = (bool) preg_match('/unsigned/', strtolower($r['column_type']));
             $col_def['precision'] = $r['numeric_precision'];
         } elseif (in_array($data_type, array('real', 'double precision', 'decimal', 'numeric', 'float', 'dec', 'fixed'))) {
             $col_def['precision'] = $r['numeric_precision'];
             $col_def['scale'] = $r['numeric_scale'];
         } elseif (in_array($data_type, array('timestamp', 'date', 'time', 'datetime'))) {
             // nothing yet
         } elseif (in_array($data_type, array('char', 'varchar', 'binary', 'varbinary', 'text', 'tinytext', 'mediumtext', 'longtext'))) {
             $col_def['octet_length'] = $r['character_octet_length'];
             $col_def['length'] = $r['character_maximum_length'];
             $has_charset = true;
         } elseif (in_array($data_type, array('blob', 'tinyblob', 'mediumblob', 'longblob'))) {
             $col_def['octet_length'] = $r['character_octet_length'];
             $col_def['length'] = $r['character_maximum_length'];
         } elseif (in_array($data_type, array('enum', 'set'))) {
             $col_def['octet_length'] = $r['character_octet_length'];
             $col_def['length'] = $r['character_maximum_length'];
             $def = $r['column_type'];
             preg_match_all("/'([^']+)'/", $def, $matches);
             if (is_array($matches[1]) && count($matches) > 0) {
                 $col_def['values'] = $matches[1];
             }
         }
         if ($include_options) {
             $col_def['options'] = array('comment' => $r['column_comment'], 'definition' => $r['column_type'], 'column_key' => $r['column_key'], 'ordinal_position' => $r['ordinal_position'], 'constraint_type' => $r['constraint_type']);
             if ($has_charset) {
                 $col_def['options']['charset'] = $r['character_set_name'];
                 $col_def['options']['collation'] = $r['collation_name'];
             }
         }
         $columns[$column_name] = $col_def;
         $foreign_keys = $table->foreign_keys;
         $unique_keys = $table->unique_keys;
         $constraint_name = $r['constraint_name'];
         $referenced_table_name = $r['referenced_table_name'];
         $referenced_column_name = $r['referenced_column_name'];
         switch ($r['constraint_type']) {
             case 'PRIMARY KEY':
                 $table->primary_keys = array_merge($table->primary_keys->toArray(), (array) $column_name);
                 break;
             case 'UNIQUE':
                 if (!$unique_keys->offsetExists($constraint_name)) {
                     $unique_keys[$constraint_name] = array();
                 }
                 $unique_keys[$constraint_name] = array_merge($unique_keys[$constraint_name]->toArray(), (array) $column_name);
                 break;
             case 'FOREIGN KEY':
                 /*
                                     if (!$foreign_keys->offsetExists($constraint_name)) {
                    $foreign_keys[$constraint_name] = array();
                                     }
                 *
                 */
                 $fk = array('referenced_table' => $referenced_table_name, 'referenced_column' => $referenced_column_name, 'constraint_name' => $constraint_name);
                 $foreign_keys[$column_name] = $fk;
                 //$table->references[$referenced_table_name] = array($column_name => $r['referenced_column_name']);
                 if (!array_key_exists($referenced_table_name, $references)) {
                     $references[$referenced_table_name] = array();
                 }
                 $references[$referenced_table_name][] = array('column' => $column_name, 'referenced_column' => $referenced_column_name, 'constraint_name' => $constraint_name);
                 break;
         }
     }
     foreach ($references as $referenced_table_name => $refs) {
         if ($tables->offsetExists($referenced_table_name)) {
             $table = $tables[$referenced_table_name];
             $references = $table->references;
             $references[$referenced_table_name] = $refs;
         }
     }
     $array = $config->toArray();
     unset($config);
     return $array;
 }
 /**
  * {@inheritdoc}
  * @throws Exception\ErrorException
  */
 public function getSchemaConfig($table = null, $include_options = true)
 {
     $results = $this->executeQuery($table);
     $references = [];
     $config = new Config(['tables' => []], true);
     $tables = $config->offsetGet('tables');
     foreach ($results as $r) {
         // Setting table information
         $table_name = $r['table_name'];
         if (!$tables->offsetExists($table_name)) {
             $table_def = ['name' => $table_name, 'columns' => [], 'primary_keys' => [], 'unique_keys' => [], 'foreign_keys' => [], 'references' => [], 'indexes' => []];
             if ($include_options) {
                 $table_def['options'] = ['comment' => $r['table_comment'], 'collation' => $r['table_collation'], 'type' => $r['table_type'], 'engine' => $r['engine']];
             }
             $tables->offsetSet($table_name, $table_def);
         }
         $table = $tables->offsetGet($table_name);
         $columns = $table->columns;
         $column_name = $r['column_name'];
         $data_type = strtolower($r['data_type']);
         $col_def = ['type' => $data_type, 'primary' => $r['constraint_type'] == 'PRIMARY KEY', 'nullable' => $r['is_nullable'] == 'YES', 'default' => $r['column_default']];
         if ($r['constraint_type'] == 'PRIMARY KEY') {
             $col_def['primary'] = true;
             $col_def['autoincrement'] = $r['extra'] == 'auto_increment';
         }
         $has_charset = false;
         if (in_array($data_type, ['int', 'tinyint', 'mediumint', 'bigint', 'int', 'smallint', 'year'])) {
             $col_def['unsigned'] = (bool) preg_match('/unsigned/', strtolower($r['column_type']));
             $col_def['precision'] = is_numeric($r['numeric_precision']) ? (int) $r['numeric_precision'] : null;
         } elseif (in_array($data_type, ['real', 'double precision', 'decimal', 'numeric', 'float', 'dec', 'fixed'])) {
             $col_def['precision'] = is_numeric($r['numeric_precision']) ? (int) $r['numeric_precision'] : null;
             $col_def['scale'] = is_numeric($r['numeric_scale']) ? (int) $r['numeric_scale'] : null;
         } elseif (in_array($data_type, ['timestamp', 'date', 'time', 'datetime'])) {
             // nothing yet
         } elseif (in_array($data_type, ['char', 'varchar', 'binary', 'varbinary', 'text', 'tinytext', 'mediumtext', 'longtext'])) {
             $col_def['octet_length'] = is_numeric($r['character_octet_length']) ? (int) $r['character_octet_length'] : null;
             $col_def['length'] = is_numeric($r['character_maximum_length']) ? (int) $r['character_maximum_length'] : null;
             $has_charset = true;
         } elseif (in_array($data_type, ['blob', 'tinyblob', 'mediumblob', 'longblob'])) {
             $col_def['octet_length'] = (int) $r['character_octet_length'];
             $col_def['length'] = (int) $r['character_maximum_length'];
         } elseif (in_array($data_type, ['enum', 'set'])) {
             $col_def['octet_length'] = (int) $r['character_octet_length'];
             $col_def['length'] = (int) $r['character_maximum_length'];
             $def = $r['column_type'];
             preg_match_all("/'([^']+)'/", $def, $matches);
             if (is_array($matches[1]) && count($matches) > 0) {
                 $col_def['values'] = $matches[1];
             }
         }
         if ($include_options) {
             $col_def['options'] = ['comment' => $r['column_comment'], 'definition' => $r['column_type'], 'column_key' => $r['column_key'], 'ordinal_position' => $r['ordinal_position'], 'constraint_type' => $r['constraint_type']];
             if ($has_charset) {
                 $col_def['options']['charset'] = $r['character_set_name'];
                 $col_def['options']['collation'] = $r['collation_name'];
             }
         }
         $columns[$column_name] = $col_def;
         $foreign_keys = $table->foreign_keys;
         $unique_keys = $table->unique_keys;
         $constraint_name = $r['constraint_name'];
         $referenced_table_name = $r['referenced_table_name'];
         $referenced_column_name = $r['referenced_column_name'];
         switch ($r['constraint_type']) {
             case 'PRIMARY KEY':
                 $table->primary_keys = array_merge($table->primary_keys->toArray(), (array) $column_name);
                 break;
             case 'UNIQUE':
                 if (!$unique_keys->offsetExists($constraint_name)) {
                     $unique_keys[$constraint_name] = [];
                 }
                 $unique_keys[$constraint_name] = array_merge($unique_keys[$constraint_name]->toArray(), (array) $column_name);
                 break;
             case 'FOREIGN KEY':
                 /*
                                     if (!$foreign_keys->offsetExists($constraint_name)) {
                    $foreign_keys[$constraint_name] = array();
                                     }
                 *
                 */
                 $fk = ['referenced_table' => $referenced_table_name, 'referenced_column' => $referenced_column_name, 'constraint_name' => $constraint_name];
                 $foreign_keys[$column_name] = $fk;
                 //$table->references[$referenced_table_name] = array($column_name => $r['referenced_column_name']);
                 if (!array_key_exists($referenced_table_name, $references)) {
                     $references[$referenced_table_name] = [];
                 }
                 $k = "{$table_name}:{$referenced_column_name}->{$column_name}";
                 $references[$referenced_table_name][$k] = ['column' => $column_name, 'referencing_table' => $table_name, 'referencing_column' => $referenced_column_name, 'constraint_name' => $constraint_name];
                 break;
         }
     }
     foreach ($references as $referenced_table_name => $refs) {
         if ($tables->offsetExists($referenced_table_name)) {
             $table = $tables[$referenced_table_name];
             $table->references = $refs;
         }
     }
     $array = new ArrayObject($config->toArray());
     unset($config);
     return $array;
 }